amphetamine-0.8.10/0040775000076400007640000000000007447673261012610 5ustar lukelukeamphetamine-0.8.10/src/0040775000076400007640000000000007447673261013377 5ustar lukelukeamphetamine-0.8.10/src/Gui.cpp0100664000076400007640000007063107447311405014620 0ustar lukeluke#include "Gui.hpp" #include "AmpHead.hpp" #include "ConstVal.hpp" #include "ShapeLd.hpp" #include "Appl.hpp" #include "Clut.hpp" #include "SndSys.hpp" extern CSystem *gSystem; extern tConstValues *gConst; extern CShapeManager *gShapeManager; extern CLevel *gLevel; extern CClutManager *gClutManager; extern tConfigData *gConfigData; extern CSoundSystem *gSoundSystem; tGUIConstants *gGUIConst; const short kHealthCurveY[10] = {0, 48, -48, 15, -15, 25, -15, 0, 0, 0}; const short kHealthCurveX = 5; const double kOxygenCurveY = 25.0; const double kOxygenCurveX = 2.0; short kMunitionStatusColors[3] = {220, 100, 220}; const short kKeyHitDelay = 300; const short kTitleTabulator = -30; const short kNameTabulator1 = 30; const short kNameTabulator2 = 20; double XLineCut(double r0x, double r0y, double r1x, double r1y, double x); void SwapBlackWhite(Graphic_file *gf); CGUI::CGUI(CGraphicSurface *curMainScreen) { tRect position; LoadMessages(); guis = read_graphic_file(gSystem->QualifyDataDir(gConst->kFileGUIs)); // by LL if (!guis) gSystem->Error("Error while reading the file kFileGUIs", 0); SwapBlackWhite(guis); healthPanel = new CGraphicSurface(gGUIConst->kHealthPanelWidth, gGUIConst->kHealthPanelHeight); oxygenPanel = new CGraphicSurface(gGUIConst->kOxygenPanelWidth, gGUIConst->kOxygenPanelHeight); weaponPanel = new CGraphicSurface(gGUIConst->kWeaponPanelWidth, gGUIConst->kWeaponPanelHeight); backgroundPanel = new CGraphicSurface(kUserPlaneWidth, kGamePlaneHeight); if (!(healthPanel && oxygenPanel && weaponPanel && backgroundPanel)) gSystem->Error("Cannot allocate panels", 0); currentMainScreen = curMainScreen; currentMessage = 0L; msgDisplayTime = 0; position.left = kGUIsPositions[3][0]; position.top = kGUIsPositions[3][1]; position.right = kGUIsPositions[3][2]; position.bottom = kGUIsPositions[3][3]; backgroundPanel->InsertGraphic(0L, guis, &position); backgroundPanel->PaintGraphic(0, 0, 0, kShapemodusNormal); backgroundPanel->FlipToScreen(kGamePlaneWidth, 0); position.left = kGUIsPositions[0][0]; position.top = kGUIsPositions[0][1]; position.right = kGUIsPositions[0][2]; position.bottom = kGUIsPositions[0][3]; healthPanel->InsertGraphic(0L, guis, &position); position.left = kGUIsPositions[1][0]; position.top = kGUIsPositions[1][1]; position.right = kGUIsPositions[1][2]; position.bottom = kGUIsPositions[1][3]; oxygenPanel->InsertGraphic(0L, guis, &position); for (short n = 0; n <= 7; n ++) { position.left = kGUIsPositions[2][0]; position.top = kGUIsPositions[2][1] + n * (kGUIsPositions[2][3]); position.right = kGUIsPositions[2][2]; position.bottom = kGUIsPositions[2][3] + n * (kGUIsPositions[2][3]); weaponPanel->InsertGraphic(0L, guis, &position); } position.left = kGUIsPositions[4][0]; position.top = kGUIsPositions[4][1]; position.right = kGUIsPositions[4][2]; position.bottom = kGUIsPositions[4][3]; curMainScreen->InsertGraphic(0L, guis, &position); position.left = kGUIsPositions[5][0]; position.top = kGUIsPositions[5][1]; position.right = kGUIsPositions[5][2]; position.bottom = kGUIsPositions[5][3]; curMainScreen->InsertGraphic(0L, guis, &position); lastHealthPanelRefresh = 0; healthCurveStart = 0; lastOxygenPanelRefresh = 0; oxygenCurveStart = 0; } CGUI::~CGUI() { free_graphic_file(guis); delete healthPanel; delete oxygenPanel; delete backgroundPanel; delete messages; } void CGUI::SetFocus(CPlayer *focus) { player = focus; } void CGUI::Update() { long time = gSystem->GetTicks(); if (player->typeID & kPlayer && lastHealthPanelRefresh < time) { DrawHealthPanel(); lastHealthPanelRefresh = time + gGUIConst->kHealthPanelRefreshRate; } if (player->typeID & kPlayer && lastOxygenPanelRefresh < time) { DrawOxygenPanel(); lastOxygenPanelRefresh = time + gGUIConst->kOxygenPanelRefreshRate; } } void CGUI::UpdateWeapon() { short drawStart = gGUIConst->kWeaponPanelHeight - player->weapons[player->currentWeapon]->munition * gGUIConst->kWeaponPanelHeight / player->weapons[player->currentWeapon]->info->munition; short drawEnd = gGUIConst->kWeaponPanelHeight; short color; weaponPanel->PaintGraphic(player->currentWeapon, 0, 0, kShapemodusNormal); for (short n = drawStart; n < drawEnd; n ++) { color = gClutManager->FindClosestColor(kMunitionStatusColors[0] - kMunitionStatusColors[0] * n / 100, kMunitionStatusColors[1] - kMunitionStatusColors[1] * n / 100, kMunitionStatusColors[2] - kMunitionStatusColors[2] * n / 100); weaponPanel->DrawAntialiasedLine(gGUIConst->kWeaponPanelWidth - gGUIConst->kWeaponStatusWidth, n, gGUIConst->kWeaponPanelWidth -1, n, (unsigned char)color, kShapemodusNormal); } weaponPanel->FlipToScreen(gGUIConst->kWeaponPanelPosX, gGUIConst->kWeaponPanelPosY); } #define ADDHEALTH(curvePoint) curvePoint == 9 ? 0 : curvePoint +1 #define SUBHEALTH(curvePoint) curvePoint == 0 ? 9 : curvePoint -1 // --------------------------------------------------- void CGUI::DrawHealthPanel() // Draws the health curve panel and blits it to the screen { double ptx, pty, cury1, cury2; short curvePoint = 0; double fak; healthCurveStart --; if (healthCurveStart < -gGUIConst->kHealthPanelWidth) healthCurveStart = 0; ptx = healthCurveStart; //healthPanel->PaintRect(0, 0, kHealthPanelWidth, kHealthPanelHeight, kBlackColor); healthPanel->PaintGraphic(0, 0, 0, kShapemodusNormal); while (ptx < gGUIConst->kHealthPanelWidth) { fak = player->health <= 0 ? SHRT_MAX : (double)player->info->energy / (double)player->health; cury1 = kHealthCurveY[curvePoint] / fak; cury2 = kHealthCurveY[ADDHEALTH(curvePoint)] / fak; if (ptx <= 0 && ptx + kHealthCurveX > 0) { pty = XLineCut(ptx, cury1, ptx + kHealthCurveX, cury2, 0); healthPanel->DrawAntialiasedLine(0, pty + gGUIConst->kHealthPanelHeight / 2, ptx + kHealthCurveX, cury2 + gGUIConst->kHealthPanelHeight / 2, gConst->kHealthPanelColor, kShapemodusNormal); }else if (ptx < gGUIConst->kHealthPanelWidth && ptx + kHealthCurveX >= gGUIConst->kHealthPanelWidth) { pty = XLineCut(ptx, cury1, ptx + kHealthCurveX, cury2, gGUIConst->kHealthPanelWidth); healthPanel->DrawAntialiasedLine(ptx, cury1 + gGUIConst->kHealthPanelHeight / 2, gGUIConst->kHealthPanelWidth, pty + gGUIConst->kHealthPanelHeight / 2, gConst->kHealthPanelColor, kShapemodusNormal); }else if (ptx > 0 && ptx + kHealthCurveX < gGUIConst->kHealthPanelWidth) { healthPanel->DrawAntialiasedLine(ptx, cury1 + gGUIConst->kHealthPanelHeight / 2, ptx + kHealthCurveX, cury2 + gGUIConst->kHealthPanelHeight / 2, gConst->kHealthPanelColor, kShapemodusNormal); } curvePoint = ADDHEALTH(curvePoint); ptx += kHealthCurveX; } healthPanel->FlipToScreen(gGUIConst->kHealthPanelPosX, gGUIConst->kHealthPanelPosY); } void CGUI::DrawOxygenPanel() { double ptx, pty1, pty2; double oxygenFactor = (double)player->oxygen / (double)gConst->kInitialOxygen; if (oxygenFactor > 1.0) oxygenFactor = 1.0; //oxygenPanel->PaintRect(0, 0, kOxygenPanelWidth, kOxygenPanelHeight, kBlackColor); oxygenPanel->PaintGraphic(0, 0, 0, kShapemodusNormal); oxygenCurveStart += 10.0 / 180.0 * 3.141; ptx = oxygenCurveStart; pty1 = kOxygenCurveY * sin(oxygenCurveStart); for (ptx = 0; ptx < 100; ptx += kOxygenCurveX) { pty2 = kOxygenCurveY * oxygenFactor * sin(ptx / 180 * 3.141 * 5.0 + oxygenCurveStart) + kOxygenCurveY * oxygenFactor / 1.5 * cos(ptx / 180 * 3.141 * 15.0 + oxygenCurveStart * 3.0); oxygenPanel->DrawAntialiasedLine(ptx, pty1 + gGUIConst->kOxygenPanelHeight / 2, ptx + kOxygenCurveX, pty2 + gGUIConst->kOxygenPanelHeight / 2, gConst->kOxygenPanelColor, kShapemodusNormal); pty1 = pty2; } oxygenPanel->FlipToScreen(gGUIConst->kOxygenPanelPosX, gGUIConst->kOxygenPanelPosY); } /* XLineCut Hinein: r0x, r0y: Anfangskoordinaten einer Linie r1x, r1y: Endkoordinaten einer Linie x: X-Abst einer zur Y-Achse parallelen Gerade Hinaus: Y-Abst des Schnittpunktes der Linie mit der Geraden */ double XLineCut(double r0x, double r0y, double r1x, double r1y, double x) { return (r0y + ((x - r0x) * (r1y - r0y)) / (r1x - r0x)); } short CGUI::ProcessKeyStrokes() { //gSystem->ProcessEvents(); if (lastKeyHit < gSystem->GetTicks() && gSystem->KeyPressed(kKeyUp) && currentNumOfItems) { lastKeyHit = gSystem->GetTicks() + gGUIConst->kKeyHitDelay; lastItem = currentItem; currentItem --; if (currentItem < 0) currentItem = currentNumOfItems; gSoundSystem->Play(gSoundSystem->selMenu, player->xm, player->ym); return kKeyUp; } if (lastKeyHit < gSystem->GetTicks() && gSystem->KeyPressed(kKeyDown) && currentNumOfItems) { lastKeyHit = gSystem->GetTicks() + gGUIConst->kKeyHitDelay; lastItem = currentItem; currentItem ++; if (currentItem > currentNumOfItems) currentItem = 0; gSoundSystem->Play(gSoundSystem->selMenu, player->xm, player->ym); return kKeyDown; } if (lastKeyHit < gSystem->GetTicks() && gSystem->KeyPressed(kKeyReturn) && currentNumOfItems) { lastKeyHit = gSystem->GetTicks() + gGUIConst->kKeyHitDelay; gSoundSystem->Play(gSoundSystem->openMenu, player->xm, player->ym); return kKeyReturn; } if (lastKeyHit < gSystem->GetTicks() && gSystem->KeyPressed(kKeyEscape)) { lastKeyHit = gSystem->GetTicks() + gGUIConst->kKeyHitDelay; gSoundSystem->Play(gSoundSystem->openMenu, player->xm, player->ym); return kKeyEscape; } return 0; } short CGUI::NewGamePageEvents() { switch (currentItem) { case 0: // New Game return kCmdNewGameLevel1; break; case 1: return kCmdNewGameLevel2; break; case 2: return kCmdNewGameLevel3; break; case 3: return kCmdNewGameLevel4; break; default: return kNoCmdEvent; break; } } short CGUI::QuitPageEvents() { switch (currentItem) { case 0: return kCmdQuit; break; case 1: OnOpenMainPage(); return kNoCmdEvent; default: return kNoCmdEvent; } } short CGUI::MainPageEvents() { switch (currentItem) { case 0: // New Game OnOpenNewGamePage(); return kNoCmdEvent; break; case 1: OnOpenLoadPage(kLoadGamePage); return kNoCmdEvent; break; case 2: OnOpenHelpPage(); return kNoCmdEvent; break; case 3: OnOpenCreditsPage(); return kNoCmdEvent; break; case 4: OnOpenQuitPage(); return kNoCmdEvent; break; default: return kNoCmdEvent; break; } } short CGUI::LoadGamePageEvents() { return (page == kLoadGamePage ? kLoadGameSlot0 + currentItem : kSaveGameSlot0 + currentItem); } short CGUI::RunUserInterface(short whichPage) { short command = kNoCmdEvent; if (lastKeyHit > gSystem->GetTicks()) return kCmdNoCommand; lastKeyHit = gSystem->GetTicks() + gGUIConst->kKeyHitDelay; gSoundSystem->Play(gSoundSystem->entrMenu, player->xm, player->ym); switch (whichPage) { case kMainPage: OnOpenMainPage(); break; case kNewGamePage: OnOpenNewGamePage(); break; case kLoadGamePage: case kSaveGamePage: OnOpenLoadPage(whichPage); break; case kHelpPage: OnOpenHelpPage(); break; case kCreditPage: OnOpenCreditsPage(); break; case kQuitPage: OnOpenQuitPage(); break; } while (command == kNoCmdEvent) { switch (ProcessKeyStrokes()) { case kKeyEscape: if (page != kMainPage) OnOpenMainPage(); else command = kCmdNoCommand; break; case kKeyReturn: switch (page) { case kMainPage: command = MainPageEvents(); break; case kNewGamePage: command = NewGamePageEvents(); break; case kLoadGamePage: case kSaveGamePage: command = LoadGamePageEvents(); break; case kQuitPage: command = QuitPageEvents(); break; } break; } SelectMenuItem(); currentMainScreen->FlipToScreen(0, 0); } return command; } void CGUI::OnOpenMainPage() { gLevel->PaintLevel(); currentMainScreen->PaintRect(gGUIConst->kUserMenuPosX, gGUIConst->kUserMenuPosY, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuWidth, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuHeight, kBlackColor, kShapemodusTransparent2); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX + kTitleTabulator, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY, gGUIConst->kUserMainPageTitle, kShapemodusLava); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 1 * gGUIConst->kUserMenuEntryDY, gGUIConst->kUserMenuEntry1, kShapemodusNormal); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 2 * gGUIConst->kUserMenuEntryDY, gGUIConst->kUserMenuEntry2, kShapemodusNormal); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 3 * gGUIConst->kUserMenuEntryDY, gGUIConst->kUserMenuEntry3, kShapemodusNormal); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 4 * gGUIConst->kUserMenuEntryDY, gGUIConst->kUserMenuEntry4, kShapemodusNormal); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 5 * gGUIConst->kUserMenuEntryDY, gGUIConst->kUserMenuEntry5, kShapemodusNormal); currentItem = lastItem = 0; currentNumOfItems = 4; page = kMainPage; currentItemStart = gGUIConst->kUserMenuEntryPosY + gGUIConst->kUserMenuEntryDY; currentEntryDY = gGUIConst->kUserMenuEntryDY; SelectMenuItem(); } void CGUI::OnOpenNewGamePage() { gLevel->PaintLevel(); currentMainScreen->PaintRect(gGUIConst->kUserMenuPosX, gGUIConst->kUserMenuPosY, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuWidth, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuHeight, kBlackColor, kShapemodusTransparent2); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX + kTitleTabulator, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY, gGUIConst->kNewGamePageTitle, kShapemodusLava); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 1 * gGUIConst->kUserMenuEntryDY, gGUIConst->kNewGameEntry1, kShapemodusNormal); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 2 * gGUIConst->kUserMenuEntryDY, gGUIConst->kNewGameEntry2, kShapemodusNormal); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 3 * gGUIConst->kUserMenuEntryDY, gGUIConst->kNewGameEntry3, kShapemodusNormal); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 4 * gGUIConst->kUserMenuEntryDY, gGUIConst->kNewGameEntry4, kShapemodusNormal); currentItem = 1; lastItem = 0; currentNumOfItems = 3; page = kNewGamePage; currentItemStart = gGUIConst->kUserMenuEntryPosY + gGUIConst->kUserMenuEntryDY; currentEntryDY = gGUIConst->kUserMenuEntryDY; SelectMenuItem(); } void CGUI::OnOpenLoadPage(short whichPage) { short n; gLevel->PaintLevel(); currentMainScreen->PaintRect(gGUIConst->kUserMenuPosX, gGUIConst->kUserMenuPosY, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuWidth, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuHeight, kBlackColor, kShapemodusTransparent2); for (n = 0; n < kNumOfSaveGameSlots; n ++) { char *filename = gSystem->QualifyHomeDir(gGUIConst->kSavedGames[n]); gLevel->GetSavedGameTitle(filename, sgTitles[n]); // by LL delete [] filename; } if (whichPage == kSaveGamePage) currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX + kTitleTabulator, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 0 * gGUIConst->kUserMenuEntryDY, gGUIConst->kSavePageTitle, kShapemodusLava); else currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX + kTitleTabulator, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 0 * gGUIConst->kUserMenuEntryDY, gGUIConst->kLoadPageTitle, kShapemodusLava); for (n = 0; n < kNumOfSaveGameSlots; n ++) { currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + (n + 1) * gGUIConst->kUserMenuEntryDY, sgTitles[n], kShapemodusNormal); } currentItem = lastItem = 0; currentNumOfItems = 5; page = whichPage; currentItemStart = gGUIConst->kUserMenuEntryPosY + gGUIConst->kUserMenuEntryDY; currentEntryDY = gGUIConst->kUserMenuEntryDY; SelectMenuItem(); } void CGUI::OnOpenHelpPage() { gLevel->PaintLevel(); currentMainScreen->PaintRect(gGUIConst->kUserMenuPosX, gGUIConst->kUserMenuPosY, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuWidth, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuHeight, kBlackColor, kShapemodusTransparent2); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX + kTitleTabulator, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 0 * gGUIConst->kUserMenuEntryDY, gGUIConst->kHelpPageTitle, kShapemodusLava); currentMainScreen->PaintGraphic(1, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 2 * gGUIConst->kCreditsEntryDY, kShapemodusTransparent2); currentItem = lastItem = -1; currentNumOfItems = 0; currentItemStart = gGUIConst->kUserMenuPosY; currentEntryDY = gGUIConst->kHelpMenuEntryDY; page = kHelpPage; } void CGUI::OnOpenCreditsPage() { gLevel->PaintLevel(); currentMainScreen->PaintRect(gGUIConst->kUserMenuPosX, gGUIConst->kUserMenuPosY, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuWidth, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuHeight, kBlackColor, kShapemodusTransparent2); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX + kTitleTabulator, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 0 * gGUIConst->kCreditsEntryDY, gGUIConst->kCreditsPageTitle, kShapemodusLava); currentMainScreen->PaintGraphic(0, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 2 * gGUIConst->kCreditsEntryDY, kShapemodusTransparent2); currentItem = lastItem = 1; currentNumOfItems = 0; currentItemStart = gGUIConst->kUserMenuEntryPosY + 7 * gGUIConst->kCreditsEntryDY; currentEntryDY = gGUIConst->kCreditsEntryDY; page = kCreditPage; } void CGUI::OnOpenQuitPage() { gLevel->PaintLevel(); currentMainScreen->PaintRect(gGUIConst->kUserMenuPosX, gGUIConst->kUserMenuPosY, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuWidth, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuHeight, kBlackColor, kShapemodusTransparent2); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX + kTitleTabulator, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 0 * gGUIConst->kCreditsEntryDY, gGUIConst->kCreditsPageTitle, kShapemodusLava); currentMainScreen->PaintGraphic(0, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 2 * gGUIConst->kCreditsEntryDY, kShapemodusTransparent2); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 8 * gGUIConst->kCreditsEntryDY, gGUIConst->kCreditsEntry4, kShapemodusNormal); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 9 * gGUIConst->kCreditsEntryDY, gGUIConst->kCreditsEntry5, kShapemodusNormal); currentItem = lastItem = 0; currentNumOfItems = 1; currentItemStart = gGUIConst->kUserMenuEntryPosY + 8 * gGUIConst->kCreditsEntryDY; currentEntryDY = gGUIConst->kCreditsEntryDY; page = kQuitPage; } void CGUI::SelectMenuItem() { char *curItem; curItem = ItemToItem(lastItem); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + currentItemStart + lastItem * currentEntryDY, curItem, kShapemodusNormal); curItem = ItemToItem(currentItem); currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + currentItemStart + currentItem * currentEntryDY, curItem, kShapemodusRandom); } char *CGUI::ItemToItem(short item) { switch (page) { case kMainPage: switch (item) { case 0: return gGUIConst->kUserMenuEntry1; break; case 1: return gGUIConst->kUserMenuEntry2; break; case 2: return gGUIConst->kUserMenuEntry3; break; case 3: return gGUIConst->kUserMenuEntry4; break; case 4: return gGUIConst->kUserMenuEntry5; break; default: return gGUIConst->kUserMenuEntry1; break; } break; case kNewGamePage: switch (item) { case 0: return gGUIConst->kNewGameEntry1; break; case 1: return gGUIConst->kNewGameEntry2; break; case 2: return gGUIConst->kNewGameEntry3; break; case 3: return gGUIConst->kNewGameEntry4; break; default: return gGUIConst->kNewGameEntry1; break; } break; case kLoadGamePage: case kSaveGamePage: return sgTitles[item]; break; case kQuitPage: switch (item) { case 0: return gGUIConst->kCreditsEntry4; break; case 1: return gGUIConst->kCreditsEntry5; break; default: return gGUIConst->kCreditsEntry5; break; } break; default: return 0L; break; } } void CGUI::DisplayInfotext(short num) { currentMessage = messages->generalMessages[num]; msgDisplayTime = gSystem->GetTicks() + gGUIConst->kInfoTextTime; } void CGUI::OnPickUpSomething(short what) { switch (what) { case kItemPhiol: currentMessage = messages->msgPhiol; break; case kItemSorcery: currentMessage = messages->msgBM; break; case kItemBow: currentMessage = messages->msgBow; break; case kItemScie: currentMessage = messages->msgScie; break; case kItemHands: currentMessage = messages->msgHands; break; case kItemBomb: currentMessage = messages->msgBombs; break; case kItemStaff: currentMessage = messages->msgStaff; break; case kItemPhiolmun: currentMessage = messages->msgPhiolMun; break; case kItemSorcerymun: currentMessage = messages->msgBMMun; break; case kItemBowmun: currentMessage = messages->msgBowMun; break; case kItemHandsmun: currentMessage = messages->msgHandsMun; break; case kItemBombmun: currentMessage = messages->msgBombsMun; break; case kItemStaffmun: currentMessage = messages->msgStaffMun; break; case kItemOxygen: currentMessage = messages->msgOxygen; break; case kItemHelppacket: currentMessage = messages->msgHealth; break; default: currentMessage = 0L; break; } msgDisplayTime = gSystem->GetTicks() + gGUIConst->kInfoTextTime; } void CGUI::DisplayMessages() { if (msgDisplayTime > gSystem->GetTicks() && currentMessage) currentMainScreen->DrawString(gGUIConst->kInfoTextLeft, gGUIConst->kInfoTextTop, currentMessage, kShapemodusTransparent1); } void CGUI::ResetTicks(long ticks) { lastKeyHit = ticks; lastHealthPanelRefresh = 0; healthCurveStart = 0; lastOxygenPanelRefresh = 0; oxygenCurveStart = 0; msgDisplayTime = 0; } long GetLongConstant(FILE *f, char *constName); double GetDoubleConstant(FILE *f, char *constName); void GetStringConstant(FILE *f, char *constName, char *buffer); void CGUI::LoadMessages() { FILE *f = fopen(gSystem->QualifyDataDir(kParFileName), "r"); // by LL char msgString[6] = "msgxx"; short n; messages = new tMessages; GetStringConstant(f, "msgPickedUpHealth", messages->msgHealth); GetStringConstant(f, "msgPickedUpOxygen", messages->msgOxygen); GetStringConstant(f, "msgPickedUpPhiol", messages->msgPhiol); GetStringConstant(f, "msgPickedUpBM", messages->msgBM); GetStringConstant(f, "msgPickedUpBow", messages->msgBow); GetStringConstant(f, "msgPickedUpScie", messages->msgScie); GetStringConstant(f, "msgPickedUpHands", messages->msgHands); GetStringConstant(f, "msgPickedUpBombs", messages->msgBombs); GetStringConstant(f, "msgPickedUpStaff", messages->msgStaff); GetStringConstant(f, "msgPickedUpPhiolMun", messages->msgPhiolMun); GetStringConstant(f, "msgPickedUpBMMun", messages->msgBMMun); GetStringConstant(f, "msgPickedUpBowMun", messages->msgBowMun); GetStringConstant(f, "msgPickedUpHandMun", messages->msgHandsMun); GetStringConstant(f, "msgPickedUpBombMun", messages->msgBombsMun); GetStringConstant(f, "msgPickedUpStaffMun", messages->msgStaffMun); for (n = 0; n < kMaxInfotexts -1; n ++) { msgString[3] = (char)(n / 10) + '0'; msgString[4] = (char)(n % 10) + '0'; GetStringConstant(f, msgString, messages->generalMessages[n]); } fclose(f); } void LoadGUIParameters() { FILE *f = fopen(gSystem->QualifyDataDir(kParFileName), "r"); // by LL gGUIConst = new tGUIConstants; gGUIConst->kHealthPanelHeight = GetLongConstant(f, "kHealthPanelHeight"); gGUIConst->kHealthPanelPosX = GetLongConstant(f, "kHealthPanelPosX"); gGUIConst->kHealthPanelPosY = GetLongConstant(f, "kHealthPanelPosY"); gGUIConst->kHealthPanelRefreshRate = GetLongConstant(f, "kHealthPanelRefreshRate"); gGUIConst->kHealthPanelWidth = GetLongConstant(f, "kHealthPanelWidth"); gGUIConst->kOxygenPanelHeight = GetLongConstant(f, "kOxygenPanelHeight"); gGUIConst->kOxygenPanelPosX = GetLongConstant(f, "kOxygenPanelPosX"); gGUIConst->kOxygenPanelPosY = GetLongConstant(f, "kOxygenPanelPosY"); gGUIConst->kOxygenPanelRefreshRate = GetLongConstant(f, "kOxygenPanelRefreshRate"); gGUIConst->kOxygenPanelWidth = GetLongConstant(f, "kOxygenPanelWidth"); gGUIConst->kWeaponPanelHeight = GetLongConstant(f, "kWeaponPanelHeight"); gGUIConst->kWeaponPanelPosX = GetLongConstant(f, "kWeaponPanelPosX"); gGUIConst->kWeaponPanelPosY = GetLongConstant(f, "kWeaponPanelPosY"); gGUIConst->kWeaponPanelWidth = GetLongConstant(f, "kWeaponPanelWidth"); gGUIConst->kWeaponStatusWidth = GetLongConstant(f, "kWeaponStatusWidth"); gGUIConst->kUserMenuEntryDY = GetLongConstant(f, "kUserMenuEntryDY"); gGUIConst->kUserMenuEntryPosX = GetLongConstant(f, "kUserMenuEntryPosX"); gGUIConst->kUserMenuEntryPosY = GetLongConstant(f, "kUserMenuEntryPosY"); gGUIConst->kUserMenuHeight = GetLongConstant(f, "kUserMenuHeight"); gGUIConst->kUserMenuPosX = GetLongConstant(f, "kUserMenuPosX"); gGUIConst->kUserMenuPosY = GetLongConstant(f, "kUserMenuPosY"); gGUIConst->kUserMenuWidth = GetLongConstant(f, "kUserMenuWidth"); gGUIConst->kHelpMenuEntryDY = GetLongConstant(f, "kHelpMenuEntryDY"); gGUIConst->kInfoTextLeft = GetLongConstant(f, "kInfoTextLeft"); gGUIConst->kInfoTextTop = GetLongConstant(f, "kInfoTextTop"); gGUIConst->kInfoTextTime = GetLongConstant(f, "kInfoTextTime"); GetStringConstant(f, "kUserMainPageTitle", gGUIConst->kUserMainPageTitle); GetStringConstant(f, "kUserMenuEntry1", gGUIConst->kUserMenuEntry1); GetStringConstant(f, "kUserMenuEntry2", gGUIConst->kUserMenuEntry2); GetStringConstant(f, "kUserMenuEntry3", gGUIConst->kUserMenuEntry3); GetStringConstant(f, "kUserMenuEntry4", gGUIConst->kUserMenuEntry4); GetStringConstant(f, "kUserMenuEntry5", gGUIConst->kUserMenuEntry5); GetStringConstant(f, "kNewGamePageTitle", gGUIConst->kNewGamePageTitle); GetStringConstant(f, "kNewGameEntry1", gGUIConst->kNewGameEntry1); GetStringConstant(f, "kNewGameEntry2", gGUIConst->kNewGameEntry2); GetStringConstant(f, "kNewGameEntry3", gGUIConst->kNewGameEntry3); GetStringConstant(f, "kNewGameEntry4", gGUIConst->kNewGameEntry4); GetStringConstant(f, "kNoSavedGame", gGUIConst->kNoSavedGame); GetStringConstant(f, "kSavePageTitle", gGUIConst->kSavePageTitle); GetStringConstant(f, "kLoadPageTitle", gGUIConst->kLoadPageTitle); GetStringConstant(f, "kHelpPageTitle", gGUIConst->kHelpPageTitle); GetStringConstant(f, "kSavedGame0", gGUIConst->kSavedGames[0]); GetStringConstant(f, "kSavedGame1", gGUIConst->kSavedGames[1]); GetStringConstant(f, "kSavedGame2", gGUIConst->kSavedGames[2]); GetStringConstant(f, "kSavedGame3", gGUIConst->kSavedGames[3]); GetStringConstant(f, "kSavedGame4", gGUIConst->kSavedGames[4]); GetStringConstant(f, "kSavedGame5", gGUIConst->kSavedGames[5]); gGUIConst->kKeyHitDelay = GetLongConstant(f, "kKeyHitDelay"); gGUIConst->kCreditsEntryDY = GetLongConstant(f, "kCreditsEntryDY"); GetStringConstant(f, "kCreditsPageTitle", gGUIConst->kCreditsPageTitle); GetStringConstant(f, "kCreditsEntry1", gGUIConst->kCreditsEntry1); GetStringConstant(f, "kCreditsEntry2", gGUIConst->kCreditsEntry2); GetStringConstant(f, "kCreditsEntry3", gGUIConst->kCreditsEntry3); GetStringConstant(f, "kCreditsEntry4", gGUIConst->kCreditsEntry4); GetStringConstant(f, "kCreditsEntry5", gGUIConst->kCreditsEntry5); fclose(f); } amphetamine-0.8.10/src/Gui.hpp0100664000076400007640000000776407447311405014634 0ustar lukeluke#ifndef __AMP_GUI__ #define __AMP_GUI__ #include "System.hpp" #include "Player.hpp" #include "Surface.hpp" const short kMaxEntryLength = 20; const short kNoCmdEvent = -1; const short kNumOfSaveGameSlots = 6; const short kMaxInfotexts = 45; enum { kMainPage, kNewGamePage, kLoadGamePage, kSaveGamePage, kCreditPage, kHelpPage, kQuitPage }; const short kGUIsPositions[6][4] = { {120, 0, 220, 100}, // health {120, 100, 220, 200}, // oxygen {0, 0, 120, 100}, // weapons {120, 200, 280, 680}, // board {0, 801, 210, 944}, // about box {0, 943, 210, 1091} // key config }; typedef struct { short kHealthPanelWidth, kHealthPanelHeight, kHealthPanelPosX, kHealthPanelPosY, kHealthPanelRefreshRate, kOxygenPanelWidth, kOxygenPanelHeight, kOxygenPanelPosX, kOxygenPanelPosY, kOxygenPanelRefreshRate, kWeaponPanelWidth, kWeaponPanelHeight, kWeaponPanelPosX, kWeaponPanelPosY, kWeaponStatusWidth, kUserMenuPosX, kUserMenuPosY, kUserMenuWidth, kUserMenuHeight, kUserMenuEntryPosX, kUserMenuEntryPosY, kUserMenuEntryDY; short kInfoTextLeft; short kInfoTextTop; short kInfoTextTime; short kHelpMenuEntryDY; short kKeyHitDelay; char kUserMainPageTitle[kMaxEntryLength]; char kUserMenuEntry1[kMaxEntryLength]; char kUserMenuEntry2[kMaxEntryLength]; char kUserMenuEntry3[kMaxEntryLength]; char kUserMenuEntry4[kMaxEntryLength]; char kUserMenuEntry5[kMaxEntryLength]; char kNewGamePageTitle[kMaxEntryLength]; char kNewGameEntry1[kMaxEntryLength]; char kNewGameEntry2[kMaxEntryLength]; char kNewGameEntry3[kMaxEntryLength]; char kNewGameEntry4[kMaxEntryLength]; char kNoSavedGame[kMaxEntryLength]; char kSavePageTitle[kMaxEntryLength]; char kLoadPageTitle[kMaxEntryLength]; char kHelpPageTitle[kMaxEntryLength]; char kSavedGames[kNumOfSaveGameSlots][kMaxEntryLength]; short kCreditsEntryDY; char kCreditsPageTitle[kMaxEntryLength]; char kCreditsEntry1[kMaxEntryLength]; char kCreditsEntry2[kMaxEntryLength]; char kCreditsEntry3[kMaxEntryLength]; char kCreditsEntry4[kMaxEntryLength]; char kCreditsEntry5[kMaxEntryLength]; } tGUIConstants; const short kMessageLength = 30; typedef struct { char msgHealth[kMessageLength]; char msgOxygen[kMessageLength]; char msgPhiol[kMessageLength]; char msgBM[kMessageLength]; char msgBow[kMessageLength]; char msgScie[kMessageLength]; char msgHands[kMessageLength]; char msgBombs[kMessageLength]; char msgStaff[kMessageLength]; char msgPhiolMun[kMessageLength]; char msgBMMun[kMessageLength]; char msgBowMun[kMessageLength]; char msgHandsMun[kMessageLength]; char msgBombsMun[kMessageLength]; char msgStaffMun[kMessageLength]; char generalMessages[kMaxInfotexts][kMessageLength]; } tMessages; class CGUI { protected: Graphic_file *guis; CGraphicSurface *backgroundPanel; CGraphicSurface *healthPanel; CGraphicSurface *oxygenPanel; CGraphicSurface *weaponPanel; CPlayer *player; tMessages *messages; long lastKeyHit; long lastHealthPanelRefresh; short healthCurveStart; long lastOxygenPanelRefresh; double oxygenCurveStart; CGraphicSurface *currentMainScreen; short currentItem, lastItem; short currentNumOfItems; short currentItemStart; short currentEntryDY; short page; char sgTitles[kNumOfSaveGameSlots][30]; char *currentMessage; long msgDisplayTime; void DrawHealthPanel(); void DrawOxygenPanel(); void SelectMenuItem(); char *ItemToItem(short item); short ProcessKeyStrokes(); short MainPageEvents(); short NewGamePageEvents(); short LoadGamePageEvents(); short QuitPageEvents(); void OnOpenMainPage(); void OnOpenNewGamePage(); void OnOpenLoadPage(short whichPage); void OnOpenHelpPage(); void OnOpenCreditsPage(); void OnOpenQuitPage(); void LoadMessages(); public: CGUI(CGraphicSurface *curMainScreen); ~CGUI(); void SetFocus(CPlayer *focus); void Update(); void UpdateWeapon(); short RunUserInterface(short page); void ResetTicks(long ticks); void OnPickUpSomething(short what); void DisplayMessages(); void DisplayInfotext(short num); }; #endifamphetamine-0.8.10/src/Main.cpp0100664000076400007640000000325607447311405014757 0ustar lukeluke#include "System.hpp" #include "Appl.hpp" #include "Clut.hpp" #include "Gui.hpp" #include "SndSys.hpp" #include "string.h" // Services CApplication *gApplication; CSystem *gSystem; CLevel *gLevel; CObjInfo *gObjInfo; CShapeManager *gShapeManager; CClutManager *gClutManager; tConstValues *gConst; tConfigData *gConfigData; CGUI *gGUI; CSoundSystem *gSoundSystem; static char **my_argv; static int my_argc; int checkParam(const char *s) { int i; for (i=1; i for comments.\n"); } int checkCommandLine() { if (checkParam("--help")) { showUsage(); return -1; } if (checkParam("--version")) { showVersion(); return -1; } gConfigData = new tConfigData; gConfigData->haveSound= !(checkParam("--nosound") || checkParam("-ns")) ; gConfigData->tryFullScreen= checkParam("--fullscreen") || checkParam("-fs"); return 0; } int main(int argc, char **argv) { my_argc = argc; my_argv = argv; if (checkCommandLine()) return 0; gApplication = new CApplication(); gApplication->InitGraphics(); gApplication->LoadData(); gApplication->Run(); gApplication->UnloadData(); gApplication->Quit(); delete gApplication; return 0; }amphetamine-0.8.10/src/File.cpp0100664000076400007640000000056607447311405014753 0ustar lukeluke#include "File.hpp" CFile::CFile() {} CFile::~CFile() {} boolVar CFile::OpenDataFile(char *name) { fileRef = fopen(name, "rb"); return fileRef != NULL; } void CFile::CloseDataFile() { fclose(fileRef); } void CFile::SetFilePos(long offset) { fseek(fileRef, offset, SEEK_SET); } long CFile::ReadData(void *data, long size) { return fread(data, size, 1, fileRef); }amphetamine-0.8.10/src/File.hpp0100664000076400007640000000353507447311405014757 0ustar lukeluke#ifndef __AMP_FILES__ #define __AMP_FILES__ #include #include "System.hpp" // Basic types for file input/output. Size of variable is very important typedef unsigned char Var1Byte; typedef short Var2Bytes; typedef long Var4Bytes ; typedef double Var8Bytes; /* Macros used to convert big endian to little endian and back. Data in the Amphetamine data files is stored in big endian (PowerPC) */ #define SWAP_SHORT(x) ((x << 8) | (((unsigned short)x) >> 8)) #define SWAP_LONG(x) ( \ (x << 24) | \ (((unsigned long)x) >> 24) | \ ((x & 0x0000FF00) << 8) | \ ((x & 0x00FF0000) >> 8) \ ) #define SWAP_PUT_SHORT(x) ((x) = (x << 8) | (((unsigned short)x) >> 8)) #define SWAP_PUT_LONG(x) ((x) = (x << 24) | (((unsigned long)x) >> 24) | \ ((x & 0x0000FF00) << 8) | ((x & 0x00FF0000) >> 8)) #define TRANS_NUM(x) ( \ (sizeof(x) == sizeof(short)) ? SWAP_SHORT(x) : \ (sizeof(x) == sizeof(long)) ? SWAP_LONG(x) : (x)\ ) #ifndef __BIG_ENDIAN__ #define TRANS_PUT_NUM(x) ((sizeof(x) == sizeof(short)) ? SWAP_PUT_SHORT(x) : \ (sizeof(x) == sizeof(long)) ? SWAP_PUT_LONG(x) : (x)) #define TRANS_PUT_NUM2(x) x #else #define TRANS_PUT_NUM(x) x #define TRANS_PUT_NUM2(x) ((sizeof(x) == sizeof(short)) ? SWAP_PUT_SHORT(x) : \ (sizeof(x) == sizeof(long)) ? SWAP_PUT_LONG(x) : (x)) #endif class CFile { protected: FILE *fileRef; short levelNumber; boolVar OpenDataFile(char *name); void SetFilePos(long offset); long ReadData(void *buffer, long size); void CloseDataFile(); public: CFile(); ~CFile(); }; // Datastructure of level element struct tLevelElement { Var2Bytes kind; // kWall = 0, kBackground = 1 Var2Bytes iconID; Var2Bytes light; Var2Bytes refNum; // LoByte: Platform switch, HiByte: Light Index Var2Bytes bitData; Var2Bytes monsterRef; Var2Bytes itemRef; }; #endif amphetamine-0.8.10/src/Shape.cpp0100664000076400007640000004322107447334444015137 0ustar lukeluke#include "Shape.hpp" #include "Appl.hpp" #include "Clut.hpp" #include #include extern CApplication *gApplication; extern CSystem *gSystem; extern CClutManager *gClutManager; extern tConstValues *gConst; extern tConfigData *gConfigData; CShape::CShape(unsigned char *bitmap, short descr[], long width) { this->id = descr[0]; this->dx = descr[3]; this->dy = descr[4]; } CShape::~CShape() { delete [] shapeForward; } unsigned char *CShape::AllowPixelAccess(short &ddx, short &ddy) { ddx = dx; ddy = dy; return shapeForward; } short CShape::RenderShape(short x, short y, tRect *clipRect, short modus, short percentage, CGraphicSurface *surface) { return dx; } #define kEndShapeToken 0L // the end of shape maker #define kLineStartToken 1L // the line start marker #define kDrawPixelsToken 2L // the draw run marker #define kSkipPixelsToken 3L // the skip pixels marker #define kClearColorIndex 0 // the index of the color defined as clear (in this case, white) #define kFalse 0 #define kTrue 1 CMaskedShape::CMaskedShape(unsigned char *bitmap, short descr[], long width) : CShape(bitmap, descr, width) { shapeForward = new unsigned char [ 8 * dy * dx + 4 * dy + 4 + 8]; Encode(shapeForward, bitmap, descr, width); shapeBackward = new unsigned char [ 8 * dy * dx + 4 * dy + 4 + 8]; Encode(shapeBackward, bitmap, descr, width); } /* Allow unaligned memory access if the architecture supports it (like IA-32) */ #ifdef __OPT_MEM_ACCESS__ #define GET_LONG(adr) *(unsigned long *)adr #define SET_LONG(adr, l) *(unsigned long *)adr = l #else #define GET_LONG(adr) ((long)((unsigned char *)(adr))[0] << 24) + ((long)((unsigned char *)(adr))[1] << 16) + ((long)((unsigned char *)(adr))[2] << 8) + ((long)((unsigned char *)(adr))[3]) #define SET_LONG(adr, l) ((unsigned char *)adr)[0] = (unsigned char)((l) >> 24); \ ((unsigned char *)adr)[1] = (unsigned char)((l) >> 16); \ ((unsigned char *)adr)[2] = (unsigned char)((l) >> 8); \ ((unsigned char *)adr)[3] = (unsigned char)(l) #endif void CMaskedShape::Encode(unsigned char *shape, unsigned char *bitmap, short descr[], long width) { unsigned short shapeHeight; // the height of the shape unsigned short shapeWidth; // the width of the shape unsigned char *destPtr; // the current position in the shape unsigned char *srcPtr; // the current position in the souce graphic data unsigned char *baseAddr; // the base address of the source pixmap unsigned long rowBytes; // the row bytes of the source pixmap unsigned char *rowStart; // the start of the current row in the pixmap unsigned long yCounter; // a counter to scan the shape vertically unsigned long xCounter; // a counter to scan the shape horizontally unsigned char drawRunFlag; // are we in a draw pixels run? unsigned char skipRunFlag; // are we in a skip pixels run? unsigned char *lineStartPtr; // where is the line start token for this line unsigned char *runTokenPtr; // where is the token for the current run unsigned long runCounter; // how long is the current run? long srcStep = (shape == shapeForward ? 1 : -1); // determine the width and height of the shape (we use these values a lot) shapeHeight = dy; shapeWidth = dx; // create a handle big enough for the worst case encoding // ( 8 bytes/pixel + 4 bytes/row + 4 bytes/shape (end token) + 8 bytes/shape (rect) ) // lock the handle and get the pointer destPtr = shape; // store the shape rect ((short *)destPtr)[0] = 0; ((short *)destPtr)[1] = 0; ((short *)destPtr)[2] = dx; ((short *)destPtr)[3] = dy; destPtr += 8; // get the location of the source data baseAddr = bitmap; rowBytes = width; rowStart = baseAddr + rowBytes * descr[2] + descr[1] + (shape == shapeForward ? 0 : dx); // scan the shape row by row for( yCounter = 0; yCounter < shapeHeight; yCounter++ ) { // store the location of this line start lineStartPtr = destPtr; destPtr += sizeof( unsigned long ); // at the beginning of each row we are not in any run drawRunFlag = kFalse; skipRunFlag = kFalse; // move to the start of the row srcPtr = rowStart; // scan each row of the shape for( xCounter = 0; xCounter < shapeWidth; xCounter++ ) { // is this pixel clear? if ( *srcPtr == kClearColorIndex ) { // are we in a draw run? if ( drawRunFlag ) { // end the draw run drawRunFlag = kFalse; // create the draw token SET_LONG(runTokenPtr, ( kDrawPixelsToken << 24 ) + runCounter); // pad to a mulitple of four SET_LONG(destPtr ,0L); destPtr += ( ( runCounter & 3L ) == 0 ) ? 0 : ( 4 - ( runCounter & 3L ) ); } // are we in a skip run if ( skipRunFlag ) { // continue it runCounter++; } else { // start one skipRunFlag = kTrue; runCounter = 1; } } else { // are we in a skip run if ( skipRunFlag ) { // end the skip run skipRunFlag = kFalse; // create the skip token //*( ( unsigned long * )destPtr ) = ( kSkipPixelsToken << 24 ) + runCounter; SET_LONG(destPtr, ( kSkipPixelsToken << 24 ) + runCounter); destPtr += sizeof( unsigned long ); } // are we in a draw run if ( drawRunFlag ) { // continue it runCounter++; // copy the pixel *destPtr = *srcPtr; destPtr++; } else { // start one drawRunFlag = kTrue; runCounter = 1; // save the location of the token (so we can fill it in later) runTokenPtr = destPtr; destPtr += sizeof( unsigned long ); // copy the pixel *destPtr = *srcPtr; destPtr++; } } // move to the next byte srcPtr += srcStep; } // are we in a draw run if( drawRunFlag ) { // end the draw run drawRunFlag = kFalse; // create the draw token SET_LONG(runTokenPtr, ( kDrawPixelsToken << 24 ) + runCounter); // pad to a mulitple of four SET_LONG(destPtr, 0L); destPtr += ( ( runCounter & 3L ) == 0 ) ? 0 : ( 4 - ( runCounter & 3L ) ); } // create the line start token SET_LONG(lineStartPtr, ( kLineStartToken << 24 ) + ( destPtr - ( lineStartPtr + 4 ) )); // move the row start to the next row rowStart += rowBytes; } // create the end of shape token SET_LONG(destPtr, kEndShapeToken << 24); destPtr += sizeof( unsigned long ); // Resize the handle to match the real size of the shape //SetHandleSize( shapeHandle, destPtr - ( unsigned char * )( *shapeHandle ) ); } CMaskedShape::~CMaskedShape() { delete [] shapeBackward; } short CMaskedShape::RenderShape(short x, short y, tRect *clipRect, short modus, short percentage, CGraphicSurface *surface) { if (clipRect->left > x || clipRect->top > y || clipRect->right < x + dx || clipRect->bottom < y + dy) RenderShapeClipped(x, y, clipRect, modus, percentage, surface); else RenderShapeUnclipped(x, y, modus, percentage, surface); return dx; } void CMaskedShape::RenderShapeClipped(short x, short y, tRect *sClipRect, short modus, short percentage, CGraphicSurface *surface) { tRect clipRect; // the rect that defines the clipped shape short pitch; unsigned char *rowStart; // the pointer to the start of this row unsigned char *srcPtr; // the current position in the sprite data unsigned char *destPtr; // the current position in the destination pixmap long miscCounter; // a counter for various purposes long extraCounter; // a counter for right clippling purposes ( how much extra was there? ) unsigned long tokenOp; // the op code from the token unsigned long tokenData; // the data from the token unsigned char exitFlag; // should we exit from the loop? long yCount; // how many lines down in the shape are we? long xCount; // where are we in this line? unsigned char *shape = (modus & kShapemodusBackwardFlag ? shapeBackward : shapeForward); modus &= ~kShapemodusBackwardFlag; // clearing the direction flag // create a clipped rect in the coordinates of the sprite clipRect.left = x < sClipRect->left ? sClipRect->left - x : 0; clipRect.right = x + dx > sClipRect->right ? sClipRect->right - x : dx; clipRect.top = y < sClipRect->top ? sClipRect->top - y : 0; clipRect.bottom = y + dy > sClipRect->bottom ? sClipRect->bottom - y : dy; // set up the counters yCount = 0; xCount = 0; // determine characteristics about the pixmap rowStart = surface->GetSurfacePtr(&pitch); rowStart += y * pitch + x; // move to the right place in the shape ( just past the size rect ) srcPtr = shape + 8; // loop until we are done exitFlag = kFalse; while( !exitFlag ) { // get a token tokenOp = GET_LONG(srcPtr ) >> 24; tokenData = GET_LONG(srcPtr ) & 0x00ffffff; srcPtr += sizeof( unsigned long ); // depending on the token switch( tokenOp ) { case kDrawPixelsToken: miscCounter = tokenData; extraCounter = 0; // if we need to, clip to the left if( xCount < clipRect.left ) { // if this run does not appear at all, don't draw it if ( miscCounter < clipRect.left - xCount ) { destPtr += miscCounter; srcPtr += miscCounter; srcPtr += ( ( tokenData & 3L ) == 0 ) ? 0 : ( 4 - ( tokenData & 3L ) ); xCount += miscCounter; break; } else { // if it does, skip to where we can draw miscCounter -= clipRect.left - xCount; destPtr += (clipRect.left - xCount); srcPtr += (clipRect.left - xCount); xCount += clipRect.left - xCount; } } // if we need to, clip to the right if ( xCount + miscCounter > clipRect.right ) { // if this run does not appear at all, skip it if ( xCount > clipRect.right ) { destPtr += miscCounter; srcPtr += miscCounter; srcPtr += ( ( tokenData & 3L ) == 0 ) ? 0 : ( 4 - ( tokenData & 3L ) ); xCount += miscCounter; break; } else { // if it does, setup to draw what we can extraCounter = miscCounter; miscCounter -= ( xCount + miscCounter ) - clipRect.right; extraCounter -= miscCounter; } } // adjust xCount for the run xCount += miscCounter; if (gConfigData->disableShapeModes) { while (miscCounter) { *(unsigned char *)destPtr = *(unsigned char *)srcPtr; destPtr += sizeof( unsigned char ); srcPtr += sizeof( unsigned char ); miscCounter -= sizeof( unsigned char ); } }else{ while (miscCounter) { gClutManager->SetPixel((unsigned char *)srcPtr, (unsigned char *)destPtr, modus, percentage); destPtr += sizeof( unsigned char ); srcPtr += sizeof( unsigned char ); miscCounter -= sizeof( unsigned char ); } } // adjust for right clipping destPtr += extraCounter; srcPtr += extraCounter; xCount += extraCounter; // adjust for the padding srcPtr += ( ( tokenData & 3L ) == 0 ) ? 0 : ( 4 - ( tokenData & 3L ) ); break; case kSkipPixelsToken: destPtr += tokenData; xCount += tokenData; break; case kLineStartToken: // if this line is above the clip rect, skip to the next line if( yCount < clipRect.top ) { srcPtr += tokenData; } // set up the destination pointer destPtr = rowStart; rowStart += pitch; // move the yCounter yCount++; // reset the xCounter xCount = 0; // if we have hit the bottom clip, exit the loop if ( yCount > clipRect.bottom ) { exitFlag = kTrue; } break; case kEndShapeToken: // signal a loop exit exitFlag = kTrue; break; default: // we should never get here break; } } surface->ReleaseSurface(); } void CMaskedShape::RenderShapeUnclipped(short x, short y, short modus, short percentage, CGraphicSurface *surface) { short pitch; unsigned char *rowStart; // the pointer to the start of this row unsigned char *srcPtr; // the current position in the sprite data unsigned char *destPtr; // the current position in the destination pixmap long miscCounter; // a counter for various purposes unsigned long tokenOp; // the op code from the token unsigned long tokenData; // the data from the token unsigned char exitFlag; // should we exit from the loop? unsigned char *shape = (modus & kShapemodusBackwardFlag ? shapeBackward : shapeForward); modus &= ~kShapemodusBackwardFlag; // clearing the direction flag // determine characteristics about the pixmap rowStart = surface->GetSurfacePtr(&pitch); rowStart += y * pitch + x; // move to the right place in the shape ( just past the size rect ) srcPtr = shape + 8; // loop until we are done exitFlag = kFalse; while( !exitFlag ) { // get a token tokenOp = GET_LONG(srcPtr) >> 24; tokenData = GET_LONG(srcPtr) & 0x00ffffff; srcPtr += sizeof( unsigned long ); // depending on the token switch( tokenOp ) { case kDrawPixelsToken: miscCounter = tokenData; if (gConfigData->disableShapeModes) { while (miscCounter) { *(unsigned char *)destPtr = *(unsigned char *)srcPtr; destPtr += sizeof( unsigned char ); srcPtr += sizeof( unsigned char ); miscCounter -= sizeof( unsigned char ); } }else{ while (miscCounter) { gClutManager->SetPixel((unsigned char *)srcPtr, (unsigned char *)destPtr, modus, percentage); destPtr += sizeof( unsigned char ); srcPtr += sizeof( unsigned char ); miscCounter -= sizeof( unsigned char ); } } // adjust for the padding srcPtr += ( ( tokenData & 3L ) == 0 ) ? 0 : ( 4 - ( tokenData & 3L ) ); break; case kSkipPixelsToken: destPtr += tokenData; break; case kLineStartToken: // set up the destination pointer destPtr = rowStart; rowStart += pitch; break; case kEndShapeToken: // signal a loop exit exitFlag = kTrue; break; default: // we should never get here break; } } surface->ReleaseSurface(); } CTexture::CTexture(unsigned char *bitmap, short descr[], long width, short light) : CShape(bitmap, descr, width) { short j, k; unsigned char *shapePtr; short size = dx * dy; shapeForward = new unsigned char[size]; bitmap = (unsigned char *)((unsigned long)bitmap + descr[2] * width + descr[1]); shapePtr = shapeForward; for (j = 0; j < dy; j ++) { for (k = 0; k < dx; k ++) { gClutManager->SetPixel(&(bitmap[k]), &(shapePtr[k]), kShapemodusNormal, light); } bitmap += width; shapePtr += dx; } } CTexture::~CTexture() { } short CTexture::RenderShape(short x, short y, tRect *clipRect, short unused, short unused2, CGraphicSurface *surface) { unsigned char *startDestPtr, *startSourcePtr, *tmpSourcePtr, *tmpDestPtr; short pitch, startX, startY, clipWidth, clipHeight, tmpWidth; startDestPtr = surface->GetSurfacePtr(&pitch); startDestPtr += MAX(y, clipRect->top) * pitch + MAX(x, clipRect->left); startY = clipRect->top > y ? clipRect->top - y : 0; startX = clipRect->left > x ? clipRect->left - x : 0; startSourcePtr = shapeForward + startY * dx + startX; clipWidth = (clipRect->right < x + dx ? clipRect->right - x : dx) - startX; clipHeight = (clipRect->bottom < y + dy ? clipRect->bottom - y : dy) - startY; if (clipWidth > 0 && clipHeight > 0) { for (short j = 0; j < clipHeight; j ++) { memcpy(startDestPtr, startSourcePtr, clipWidth); startSourcePtr += dx; startDestPtr += pitch; } } surface->ReleaseSurface(); return dx; } CBackground::CBackground(unsigned char *bitmap, short descr[], long width) : CShape(bitmap, descr, width) { shapeForward = bitmap; // For background shapes, descr[1] and descr[2] are the width and height of the background picture shapeWidth = descr[1]; shapeHeight = descr[2]; } CBackground::~CBackground() {} short CBackground::RenderShape(short x, short y, tRect *clipRect, short bkgndCoordX, short unused2, CGraphicSurface *surface) { unsigned char *startDestPtr, *startSourcePtr, *tmpSourcePtr, *tmpDestPtr; short pitch, startX, startY, clipWidth, clipHeight, tmpWidth; short bkgndPictCoordX = bkgndCoordX % shapeWidth; short n; startDestPtr = surface->GetSurfacePtr(&pitch); startDestPtr += MAX(y, clipRect->top) * pitch + MAX(x, clipRect->left); startY = MAX(clipRect->top, y); startX = (bkgndPictCoordX + MAX(x, clipRect->left)) % shapeWidth; startSourcePtr = shapeForward + MAX(y, clipRect->top) * shapeWidth; clipWidth = (clipRect->right < x + dx ? clipRect->right : x + dx) - MAX(x, clipRect->left); clipHeight = (clipRect->bottom < y + dy ? clipRect->bottom : y + dy) - startY; for (short j = 0; j < clipHeight; j ++) { tmpWidth = clipWidth; tmpDestPtr = startDestPtr; if (startX + tmpWidth >= shapeWidth) { for (n = 0; n < tmpWidth; n ++) { startDestPtr[n] = startSourcePtr[(startX + n) % shapeWidth]; } }else{ tmpSourcePtr = startSourcePtr + startX; memcpy(tmpDestPtr, tmpSourcePtr, tmpWidth); } startSourcePtr += shapeWidth; startDestPtr += pitch; } surface->ReleaseSurface(); return dx; } amphetamine-0.8.10/src/Shape.hpp0100664000076400007640000000275507447447406015156 0ustar lukeluke#ifndef __AMP_SHAPES__ #define __AMP_SHAPES__ #include "AmpHead.hpp" #include "Surface.hpp" class CShape { protected: short id; short dx, dy; unsigned char *shapeForward; public: long ID; long savedID; CShape(unsigned char *, short [], long); ~CShape(); virtual short RenderShape(short x, short y, tRect *clipRect, short modus, short percentage, CGraphicSurface *surface); unsigned char *AllowPixelAccess(short &dx, short &dy); }; class CMaskedShape : public CShape { protected: unsigned char *shapeBackward; void Encode(unsigned char *, unsigned char *, short [], long); void RenderShapeClipped(short x, short y, tRect *clipRect, short modus, short percentage, CGraphicSurface *surface); void RenderShapeUnclipped(short x, short y, short modus, short percentage, CGraphicSurface *surface); public: CMaskedShape(unsigned char *, short [], long); ~CMaskedShape(); short RenderShape(short x, short y, tRect *clipRect, short modus, short percentage, CGraphicSurface *surface); }; class CTexture : public CShape { protected: public: CTexture(unsigned char *, short [], long, short light); ~CTexture(); short RenderShape(short x, short y, tRect *clipRect, short unused, short unused2, CGraphicSurface *surface); }; class CBackground : public CShape { protected: short shapeWidth, shapeHeight; public: CBackground(unsigned char *, short [], long); ~CBackground(); short RenderShape(short x, short y, tRect *clipRect, short unused, short unused2, CGraphicSurface *surface); }; #endif amphetamine-0.8.10/src/Level.cpp0100664000076400007640000002415107447311405015137 0ustar lukeluke#include #include #include #include "Level.hpp" #include "Appl.hpp" #include "ConstVal.hpp" #include "Gui.hpp" #include "ShapeLd.hpp" extern CApplication *gApplication; extern CObjInfo *gObjInfo; extern tConstValues *gConst; extern CSystem *gSystem; extern CShapeManager *gShapeManager; extern tGUIConstants *gGUIConst; extern CGUI *gGUI; extern FILE *logFile; //---------------------------------------------------- CLevel::CLevel(short levelNumber, char *fileName) /* In: levelNumber: number of level to be loaded First loads the level data from file, then generating each level element object, and if there are monsters or items on the element, generate them Then create platforms */ { if (fileName) { ReadLevel(fileName); }else{ short j, k; tLevelElement *levelElement = new tLevelElement; CThing *thing; LoadBackground(levelNumber); gObjInfo->CreatePlatforms(); if (!OpenDataFile(gSystem->QualifyDataDir(gConst->kFileLevel))) gSystem->Error("File kFileLevel not found or not able to open it", 0); // by LL SetFilePos(levelNumber * kLevelWidth * kLevelHeight * sizeof(tLevelElement)); MSG("Creating level\n"); for (j = 0; j < kLevelHeight; j ++) { for (k = 0; k < kLevelWidth; k ++) { ReadData(levelElement, sizeof(tLevelElement)); TRANS_PUT_NUM(levelElement->kind); TRANS_PUT_NUM(levelElement->iconID); TRANS_PUT_NUM(levelElement->light); TRANS_PUT_NUM(levelElement->refNum); TRANS_PUT_NUM(levelElement->bitData); TRANS_PUT_NUM(levelElement->monsterRef); TRANS_PUT_NUM(levelElement->itemRef); if (levelElement->iconID > 0) levelElement->iconID += gConst->kShapeSets[levelNumber] * 20; if (levelElement->iconID) level[j][k] = new CElement(k * kElementSize + kElementSize / 2, j * kElementSize + kElementSize / 2, kElementSize, kElementSize, levelElement); else level[j][k] = new CBackgroundElement(k * kElementSize + kElementSize / 2, j * kElementSize + kElementSize / 2, kElementSize, kElementSize, levelElement); level[j][k]->LinkPlatforms(); if (levelElement->monsterRef != -1) { if (levelElement->monsterRef == kCameraNo) thing = new CCamera(k * kElementSize, j * kElementSize, 2, 2, 0); else thing = gObjInfo->CreateMonster(levelElement->monsterRef, k, j); if (thing->typeID & (kPlayer | kCamera)) { focus = thing; player = thing; } } if (levelElement->itemRef != -1) { thing = gObjInfo->CreateItem(levelElement->itemRef, k, j); } } } delete levelElement; CloseDataFile(); gSystem->ResetTicks(0); gGUI->ResetTicks(0); } } CLevel::~CLevel() { short j, k; for (j = 0; j < kLevelHeight; j ++) { for (k = 0; k < kLevelWidth; k ++) { delete level[j][k]; } } } void CLevel::LoadBackground(short levelNumber) { if (gConst->kBackgrounds[levelNumber] != gApplication->lastBackground) { gShapeManager->UnloadBackground(); if (gConst->kBackgrounds[levelNumber] == 1) gShapeManager->LoadBackground(gConst->kFileBackground1); else gShapeManager->LoadBackground(gConst->kFileBackground2); gApplication->lastBackground = gConst->kBackgrounds[levelNumber]; } } void CLevel::PaintLevel() { short j, k; short planeX, planeY; short startElementX, startElementY, numElementsX, numElementsY; tRect clipRect; tThingList *currentEntry; focus->CalcPlaneOffsets(planeX, planeY); clipRect.left = 0; clipRect.top = 0; clipRect.right = kGamePlaneWidth; clipRect.bottom = kGamePlaneHeight; startElementX = planeX / kElementSize; startElementY = planeY / kElementSize; numElementsX = kGamePlaneWidth / kElementSize; numElementsY = kGamePlaneHeight / kElementSize; for (j = startElementY; j < startElementY + numElementsY + 1 && j < kLevelHeight; j ++) { for (k = startElementX; k < startElementX + numElementsX + 1 && k < kLevelWidth; k ++) { level[j][k]->PaintElement(planeX, planeY, &clipRect); } } currentEntry = gApplication->preRenderQueue; while (currentEntry) { currentEntry->thing->Render(planeX, planeY, &clipRect); currentEntry = currentEntry->next; } currentEntry = gApplication->renderQueue; while (currentEntry) { currentEntry->thing->Render(planeX, planeY, &clipRect); currentEntry = currentEntry->next; } currentEntry = gApplication->postRenderQueue; while (currentEntry) { currentEntry->thing->PostRender(planeX, planeY, &clipRect); currentEntry = currentEntry->next; } } CElement *CLevel::GetElement(double x, double y) { short elemx, elemy; elemx = (short)(x / kElementSize); elemy = (short)(y / kElementSize); if (elemx >= 0 && elemy >= 0 && elemx < kLevelWidth && elemy < kLevelHeight) return level[elemy][elemx]; else return 0L; } // ----------------------------------------------- void CLevel::SwitchLight(short lightID) // Searches all elements with key equal to key, and then change their // lights. Don't call this routine too often, it's slow { short j, k; for (j = 0; j < kLevelHeight; j ++) { for (k = 0; k < kLevelWidth; k ++) { if (level[j][k]->key == lightID) level[j][k]->SwapLights(); } } } // ----------------------------------------------- CElement *CLevel::FindRefnum(short refnum) // Finds the first element with key == refnum and returns it { short j, k; for (j = 0; j < kLevelHeight; j ++) { for (k = 0; k < kLevelWidth; k ++) { if (level[j][k]->key == refnum) return level[j][k]; } } return 0L; } void CLevel::WriteLevel(char *fileName) { char tmpName[12] = "tmp.sg0"; long versionNumber = kVersionNumber; long key = kVersionKey; time_t theTime; long ticks; long size; tThingList *currentEntry; char *tmpFileName; tmpFileName = gSystem->QualifyHomeDir(tmpName); remove(tmpFileName); FILE *f = fopen(tmpFileName, "wb"); // by LL if (!f) { gSystem->Error("Cannot open the saving file", 0); } MSG("Writing save file header\n"); fwrite(&versionNumber, sizeof(versionNumber), 1, f); fwrite(&key, sizeof(key), 1, f); theTime = time(&theTime); fwrite(&theTime, sizeof(theTime), 1, f); ticks = gSystem->GetTicks(); fwrite(&ticks, sizeof(ticks), 1, f); fwrite(&gApplication->difficulty, sizeof(gApplication->difficulty), 1, f); size = 0; fwrite(&size, sizeof(size), 1, f); fwrite(&gApplication->levelNumber, sizeof(gApplication->levelNumber), 1, f); MSG("Writing level elements\n"); for (short j = 0; j < kLevelHeight; j ++) { for (short k = 0; k < kLevelWidth; k ++) { level[j][k]->Write(f); } } MSG("Writing objects\n"); currentEntry = gApplication->thingList; while (currentEntry) { currentEntry->thing->Write(f); currentEntry = currentEntry->next; } size = ftell(f); fseek(f, sizeof(versionNumber) + sizeof(key) + sizeof(theTime) + sizeof(ticks) + sizeof(gApplication->difficulty), SEEK_SET); fwrite(&size, sizeof(size), 1, f); MSG("Finishing up\n"); fflush(f); fclose(f); remove(fileName); rename(tmpFileName, fileName); delete [] tmpFileName; } void CLevel::GetSavedGameTitle(char *fileName, char *title) { long versionNumber, key; time_t time; FILE *f = fopen(fileName, "rb"); tm *tp; if (f) fread(&versionNumber, sizeof(versionNumber), 1, f); if (f) fread(&key, sizeof(key), 1, f); if (!f || versionNumber != kVersionNumber || key != kVersionKey) title = strcpy(title, gGUIConst->kNoSavedGame); else { fread(&time, sizeof(time), 1, f); tp = localtime(&time); strftime(title, 20, "%d.%m.%Y, %H.%M", tp); } if (f) fclose(f); } short CLevel::ReadLevel(char *fileName) { FILE *f = fopen(fileName, "rb"); long versionNumber, key; time_t theTime; long ticks; long size, fileSize; long typeID = -1; CThing *thing; short thingNumber; short j, k; if (!f) gSystem->Error("Cannot open the saving file", 0); MSG("Reading level header\n"); fread(&versionNumber, sizeof(versionNumber), 1, f); if (versionNumber != kVersionNumber) return 0; fread(&key, sizeof(key), 1, f); if (key != kVersionKey) return 0; fread(&theTime, sizeof(theTime), 1, f); fread(&ticks, sizeof(ticks), 1, f); fread(&gApplication->difficulty, sizeof(gApplication->difficulty), 1, f); fread(&fileSize, sizeof(fileSize), 1, f); fread(&gApplication->levelNumber, sizeof(gApplication->levelNumber), 1, f); LoadBackground(gApplication->levelNumber); MSG("Reading level elements\n"); for (j = 0; j < kLevelHeight; j ++) { for (k = 0; k < kLevelWidth; k ++) { fread(&size, sizeof(size), 1, f); fread(&typeID, sizeof(typeID), 1, f); fseek(f, - (sizeof(size) + sizeof(typeID)), SEEK_CUR); if (typeID & kBackgroundElement) level[j][k] = new CBackgroundElement(k * kElementSize, j * kElementSize, kElementSize, kElementSize, 0L); else level[j][k] = new CElement(k * kElementSize, j * kElementSize, kElementSize, kElementSize, 0L); level[j][k]->Read(f); } } MSG("Reading objects\n"); while (!feof(f) && ftell(f) < fileSize) { fread(&size, sizeof(size), 1, f); fread(&typeID, sizeof(typeID), 1, f); fread(&thingNumber, sizeof(thingNumber), 1, f); fseek(f, - (sizeof(size) + sizeof(typeID) + sizeof(thingNumber)), SEEK_CUR); if (typeID & kMonster) { thing = gObjInfo->CreateMonster(thingNumber, 0, 0); if (typeID & kPlayer) { focus = thing; player = thing; } thing->Read(f); } if (typeID & kItem) { thing = gObjInfo->CreateItem(thingNumber, 0, 0); thing->Read(f); } if (typeID & kBullet) { if (typeID & kSorceryBullet) thing = new CSorceryBullet(0, 0, 0, 0, 0, 0L, 0, 0, 0L, 0); else if (typeID & kBombBullet) thing = new CBombBullet(0, 0, 0, 0, 0, 0L, 0, 0, 0L, 0); else if (typeID & kSineBullet) thing = new CSineBullet(0, 0, 0, 0, 0, 0L, 0, 0, 0L, 0, 0, 0); else if (typeID & kGuidedBullet) thing = new CGuidedBullet(0, 0, 0, 0, 0, 0L, 0, 0, 0L, 0, 0L); else thing = new CBullet(0, 0, 0, 0, 0, 0L, 0, 0, 0L, 0); thing->Read(f); } if (typeID & kPlatform) { thing = new CPlatform(0, 0, 0, 0, 0, 0L); thing->Read(f); gApplication->platformTable[thingNumber] = (CPlatform *)thing; } } MSG("Finishing up\n"); fflush(f); fclose(f); for (j = 0; j < kLevelHeight; j ++) { for (k = 0; k < kLevelWidth; k ++) { level[j][k]->LinkPlatforms(); } } gSystem->ResetTicks(ticks); gGUI->ResetTicks(ticks); return 1; } amphetamine-0.8.10/src/Level.hpp0100664000076400007640000000122007447311405015134 0ustar lukeluke#ifndef __AMP_LEVEL__ #define __AMP_LEVEL__ #include "File.hpp" #include "Element.hpp" #include "AmpHead.hpp" #include "ShapeLd.hpp" #include "Thing.hpp" class CLevel : public CFile { protected: void LoadBackground(short levNum); public: CElement *level[kLevelHeight][kLevelWidth]; CThing *player; CThing *focus; CLevel(short levelNumber, char *fileName); ~CLevel(); void PaintLevel(); CElement *GetElement(double x, double y); void SwitchLight(short lightID); CElement *FindRefnum(short refnum); void WriteLevel(char *fileName); short ReadLevel(char *fileName); void GetSavedGameTitle(char *fileName, char *title); }; #endifamphetamine-0.8.10/src/Monster.cpp0100664000076400007640000002171407447600647015532 0ustar lukeluke#include "Monster.hpp" #include "Appl.hpp" #include "ConstVal.hpp" extern CApplication *gApplication; extern CShapeManager *gShapeManager; extern CObjInfo *gObjInfo; extern CLevel *gLevel; extern tConstValues *gConst; CMonster::CMonster(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo) : CThing(initx, inity, width, height, number) { typeID |= kMonster; background = 0; LinkInLists(); if (monsterInfo) { info = monsterInfo; OnAllocate(); lastWalkTime = 0; lastShootTime = 0; walkFrame = 0; flying = 0; teleportCounter = -1; lastBlessureTime = 0; dieFrameTime = 0; dieFrame = -1; speed = info->speed * gApplication->currentSpeedSF; } // additinal init lastCollisionCode = kNoCollision; status = kMonsterForward; doDarken = 0; } void CMonster::OnAllocate() { for (short n = 0; n < 3; n ++) { moveShapes[n] = gShapeManager->FindShape(info->moveShapes[n], 0); deathShapes[n] = gShapeManager->FindShape(info->deathShapes[n], 0); } jumpShape = gShapeManager->FindShape(info->jumpShape, 0); attackShape = gShapeManager->FindShape(info->attackShape, 0); weapon = CreateWeapon(info->weapon); currentShape = moveShapes[0]; health = info->energy * gApplication->currentHealthSF; } void CMonster::LinkInLists() { gApplication->Enqueue(&gApplication->thingList, this); gApplication->Enqueue(&gApplication->collisionThingList, this); gApplication->Enqueue(&gApplication->renderQueue, this); } void CMonster::UnlinkInLists() { gApplication->Dequeue(&gApplication->thingList, this); gApplication->Dequeue(&gApplication->collisionThingList, this); gApplication->Dequeue(&gApplication->renderQueue, this); } CMonster::~CMonster() { if (weapon) delete weapon; } CWeapon *CMonster::CreateWeapon(short weapon) { tWeaponInfo *tmp = gObjInfo->FindWeapon(weapon); CWeapon *tmpWeapon; noWeapon = 0; switch (tmp->art) { case kWeaponMultibullet: tmpWeapon = new CMultiBulletWeapon(this, tmp, attackShape, gConst->kFirehandAngle); break; case kWeaponInHand: tmpWeapon = new CWeapon(this, tmp, attackShape); noWeapon = 1; break; case kWeaponSine: tmpWeapon = new CSineWeapon(this, tmp, attackShape, gConst->kSineWeaponRad); break; case kWeaponGuided: tmpWeapon = new CGuided(this, tmp, attackShape); break; case kWeaponSorcery: tmpWeapon = new CSorcery(this, tmp, attackShape); break; case kWeaponNormal: case kWeaponHasWeight: default: tmpWeapon = new CWeapon(this, tmp, attackShape); break; } if (tmpWeapon) { tmpWeapon->weaponStatus = kWeaponReady; tmpWeapon->AddMunition(SHRT_MAX); tmpWeapon->weaponNumber = weapon; } return tmpWeapon; } void CMonster::Move() { CThing::Move(); if (ys >= kLevelHeight * kElementSize) { health = 0; OnKill(); } if (info->invisible) modus = kShapemodusShadow; currentShape = moveShapes[walkFrame]; if (forceVectorX && lastTime > lastWalkTime ) { walkFrame ++; walkFrame %= 3; lastWalkTime = lastTime + gConst->kWalkFrameTime; } if (forceVectorY < 0) currentShape = jumpShape; if (dieFrame != -1) { if (dieFrameTime < lastTime && dieFrame < 2) { dieFrame ++; dieFrameTime = lastTime + gConst->kDieFrameTime; if (dieFrame == 2) gApplication->Dequeue(&gApplication->collisionThingList, this); } currentShape = deathShapes[dieFrame]; } if (weapon) doDarken = weapon->ShootAnimation(¤tShape); } short CMonster::Forces() { short collisionObject; Gravitation(); CObject::Forces(); lastCollisionCode = ExertForce(resForceX, resForceY, collisionObject, 0L); if (lastCollisionCode & (kCollisionOnLeft | kCollisionOnRight)) forceVectorX = 0; return kNoEvent; } // -------------------------------------------------------------------- void CMonster::Render(short planeX, short planeY, tRect *clipRect) // Renders the current Shape of the monster { CElement *element = gLevel->GetElement(xm, ym); short screenPosx = xs - planeX, screenPosy = ys - planeY; // Position of monster on the screen short brightness = (element && doDarken) ? element->brightness : 0; // Teleporting... if (teleportCounter != -1) { if (teleportCounter > dx / 2) { clipRect->left = MAX(screenPosx + dx - teleportCounter, clipRect->left); clipRect->right = MIN(screenPosx + teleportCounter, clipRect->right); }else{ clipRect->left = MAX(screenPosx + teleportCounter, clipRect->left); clipRect->right = MIN(screenPosx + (xe - planeX) - teleportCounter, clipRect->right); } if (teleportDeltaTime < lastTime) { teleportCounter ++; teleportDeltaTime = lastTime + gConst->kTeleportTime / dx * 2; } if (teleportCounter == dx / 2) OnTeleport(); if (teleportCounter == dx) teleportCounter = -1; modus = kShapemodusRandom; } // Testing for blessure invulnerability if (lastBlessureTime > lastTime) modus = kShapemodusRandom; if (lookDirection == kLookingLeft) modus |= kShapemodusBackwardFlag; if (currentShape) currentShape->RenderShape(screenPosx, screenPosy, clipRect, modus, brightness, gApplication->plane); } short CMonster::Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject) { short returnValue = CThing::Collision(sender, left, top, right, bottom, forcex, forcey, pfx, pfy, sourceWeight, collisionObject); if (returnValue && sender->typeID & kPlayer) { if (dieFrame == -1) ((CThing *)sender)->OnDamage(info->touchBlessure); if (info->canExplode && dieFrame == -1) OnKill(); } return returnValue; } short CMonster::Think() { tThingList *bulletEntry; short elemx, elemy; double directionx, directiony; CObject::Think(); if (dieFrame != -1) return kNoEvent; if (gApplication->firstPlayRound) OnStart(); if (ABS(FindPlayerX()) > gConst->kActivateDistance) return kNoEvent; // Checking for a treatment event bulletEntry = gApplication->bulletList; while (bulletEntry) { if (((CBullet *)(bulletEntry->thing))->AmIATreatment(xs, ys, xe, ye, directionx, directiony)) { OnTreatment(directionx, directiony); bulletEntry = 0L; }else bulletEntry = bulletEntry->next; } // Checking for an abyss event if (forceVectorX > 0) { elemx = (short)(xe + forceVectorX) / kElementSize; elemy = (short)ym / kElementSize; }else{ elemx = (short)(xs + forceVectorX) / kElementSize; elemy = (short)ym / kElementSize; } if ((lastCollisionCode & kCollisionOnBottom) && elemx > 0 && elemy > 0 && elemx < kLevelWidth && elemy + 1 < kLevelHeight) { if (gLevel->level[elemy][elemx]->background && gLevel->level[elemy + 1][elemx]->background) OnAbyss(); } // Checking for a collision event if (lastCollisionCode & ~kCollisionOnBottom) OnCollision(); // Checking for a landing event if (flying && lastCollisionCode & kCollisionOnBottom) OnLanding(); flying = !(lastCollisionCode & kCollisionOnBottom); // Sending an idle event OnIdle(); return kNoEvent; } void CMonster::OnStart() {} void CMonster::OnAbyss() {} void CMonster::OnCollision() {} void CMonster::OnLanding() {} void CMonster::OnIdle() {} void CMonster::OnTreatment(double directionx, double directiony) {} void CMonster::OnShootSuccessful() {} void CMonster::OnShootNotSuccessful() {} void CMonster::OnTeleport() {} // --------------------------------------------- void CMonster::OnDamage(short blessure) // Event occurs, when a monster is hit by something (bullet etc.) { if (dieFrame == -1 && lastBlessureTime < lastTime) { health -= blessure; if (health < 0) OnKill(); else lastBlessureTime = lastTime + gConst->kBlessureInvulnerabilityTime; } } void CMonster::OnKill() { dieFrameTime = lastTime + gConst->kDieFrameTime; dieFrame = 0; } void CMonster::OnTouch(CObject *touch) { if (dieFrame == -1) ((CThing *)touch)->OnDamage(info->touchBlessure); } double CMonster::FindPlayerX() { return gLevel->player->xm - xm; } double CMonster::FindPlayerY() { return gLevel->player->ym - ym; } short CMonster::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(typeID); WRITEDATA(thingNumber); size += CThing::Write(f); if (weapon) size += weapon->Write(f); WRITEDATA(speed); WRITEDATA(lastWalkTime); WRITEDATA(lastShootTime); WRITEDATA(walkFrame); WRITEDATA(status); WRITEDATA(lastCollisionCode); WRITEDATA(flying); WRITEDATA(teleportDeltaTime); WRITEDATA(teleportCounter); WRITEDATA(lastBlessureTime); WRITEDATA(dieFrameTime); WRITEDATA(dieFrame); WRITEDATA(doDarken); WRITEDATA(health); FINISHWRITE; return size; } void CMonster::Read(FILE *f) { long size = 0; READDATA(size); READDATA(typeID); READDATA(thingNumber); CThing::Read(f); OnAllocate(); if (weapon) weapon->Read(f); READDATA(speed); READDATA(lastWalkTime); READDATA(lastShootTime); READDATA(walkFrame); READDATA(status); READDATA(lastCollisionCode); READDATA(flying); READDATA(teleportDeltaTime); READDATA(teleportCounter); READDATA(lastBlessureTime); READDATA(dieFrameTime); READDATA(dieFrame); READDATA(doDarken); READDATA(health); if (dieFrame != -1) gApplication->Dequeue(&gApplication->collisionThingList, this); }amphetamine-0.8.10/src/Monster.hpp0100664000076400007640000000377307447311405015533 0ustar lukeluke#ifndef __AMP_MONSTER__ #define __AMP_MONSTER__ #include "Thing.hpp" #include "ObjInfo.hpp" #include "Weapon.hpp" enum { // stati kMonsterForward, kMonsterBackward, kMonsterWaiting, kMonsterFastForward, // for Warg kMonsterFastBackward }; // if no shoots are successful, so shoot at least every 4 seconds const short kMonsterMaxShootDelay = 4000; const short kWalkerWaitAfterShooting = 800; class CMonster : public CThing { protected: CShape *moveShapes[3]; CShape *jumpShape; CShape *attackShape; CShape *deathShapes[3]; CWeapon *weapon; short noWeapon; tMonsterInfo *info; long lastWalkTime, lastShootTime; short walkFrame; CShape *currentShape; double speed; short status; short lastCollisionCode; short flying; long teleportDeltaTime; // actually only used by the player short teleportCounter; long lastBlessureTime; long dieFrameTime; short dieFrame; short doDarken; short health; // Events virtual void OnStart(); virtual void OnAbyss(); virtual void OnCollision(); virtual void OnLanding(); virtual void OnIdle(); virtual void OnTreatment(double directionx, double directiony); virtual void OnTeleport(); // actually only used by the player double FindPlayerX(); double FindPlayerY(); CWeapon *CreateWeapon(short weapon); public: CMonster(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo); ~CMonster(); void OnAllocate(); void LinkInLists(); void UnlinkInLists(); // public events virtual void OnShootSuccessful(); virtual void OnShootNotSuccessful(); virtual void OnDamage(short blessure); virtual void OnKill(); virtual void OnTouch(CObject *touch); virtual void Render(short planeX, short planeY, tRect *clipRect); short Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject); short Think(); void Move(); short Forces(); virtual short Write(FILE *f); virtual void Read(FILE *f); }; #endifamphetamine-0.8.10/src/Appl.cpp0100664000076400007640000002301607447607145014774 0ustar lukeluke#include "Appl.hpp" #include "System.hpp" #include "Clut.hpp" #include "Gui.hpp" #include "SndSys.hpp" #include extern CSystem *gSystem; extern CLevel *gLevel; extern CObjInfo *gObjInfo; extern CShapeManager *gShapeManager; extern CClutManager *gClutManager; extern tConstValues *gConst; extern CGUI *gGUI; extern tGUIConstants *gGUIConst; extern tConfigData *gConfigData; extern CSoundSystem *gSoundSystem; FILE *logFile; void LoadParameters(); void LoadGUIParameters(); // in GUI.cpp void StartupSoundSystem(); void ShutdownSoundSystem(); CApplication::CApplication() { MSG("new CSystem\n"); gSystem = new CSystem("Amphetamine"); MSG("LoadParameters()\n"); LoadParameters(); gSystem->NewWindow(0, 0, gConfigData->screenWidth, gConfigData->screenHeight); MSG("LoadGUIParameters\n"); LoadGUIParameters(); MSG("new CSoundSystem\n"); gSoundSystem = new CSoundSystem(gSystem->workingSound); } CApplication::~CApplication() { delete gSoundSystem; delete gConst; delete gGUIConst; delete gConfigData; gSystem->DisposeWindow(); delete gSystem; fclose(logFile); } void CApplication::InitGraphics() { MSG("gSystem->AllocateScreen\n"); gSystem->AllocateScreen(gConfigData->screenWidth, gConfigData->screenHeight, kScreenDepth); MSG("gSystem->LoadPalette\n"); gSystem->LoadPalette(gConst->kFilePalette); } void CApplication::LoadData() { long startupTime; MSG("new CClutManager\n"); gClutManager = new CClutManager(); MSG("Loading Palette\n"); gClutManager->LoadPalette(gSystem->palColors); MSG("Building Luminosity Table\n"); gClutManager->BuildLuminosityTable(); MSG("new CGraphicsSurface (startup)\n"); startup = new CGraphicSurface(kGamePlaneWidth + kUserPlaneWidth, kGamePlaneHeight); MSG("startup->Insert Graphic\n"); startup->InsertGraphic(gSystem->QualifyDataDir(gConst->kFileStartup), 0L, 0L); // by LL MSG("startup->PaintGraphic\n"); startup->PaintGraphic(0, 0, 0, kShapemodusNormal); MSG("startup->FlipToScreen\n"); startup->FlipToScreen(0, 0); MSG("set startupTime\n"); startupTime = gSystem->GetTicks() + gConst->kStartupTime; MSG("new CShapeManager\n"); gShapeManager = new CShapeManager(); MSG("new gShapeManager->LoadShapes\n"); gShapeManager->LoadShapes(); MSG("new gShapeManager->LoadBackground\n"); gShapeManager->LoadBackground(gConst->kFileBackground1); lastBackground = 1; MSG("creating plane (new CGraphicSurface\n"); plane = new CGraphicSurface(kGamePlaneWidth, kGamePlaneHeight); while (gSystem->GetTicks() < startupTime && !gSystem->KeyPressed(kKeySpace)) { gSystem->ProcessEvents(); } delete startup; MSG("new CGUI\n"); gGUI = new CGUI(plane); MSG("new CObjInfo\n"); gObjInfo = new CObjInfo(0); command = kCmdNewGameLevel2; } void CApplication::LoadLevelData(short levelNumber) { thingList = 0L; collisionThingList = 0L; bulletList = 0L; preRenderQueue = 0L; postRenderQueue = 0L; renderQueue = 0L; gObjInfo->LoadPlatforms(levelNumber); MSG("new CLevel\n"); if (command >= kLoadGameSlot0 && command <= kLoadGameSlot5) { char *fileName = gSystem->QualifyHomeDir(gGUIConst->kSavedGames[command - kLoadGameSlot0]); gLevel = new CLevel(levelNumber, fileName); // by LL delete [] fileName; } else gLevel = new CLevel(levelNumber, 0L); gGUI->SetFocus((CPlayer *)gLevel->focus); } void CApplication::Run() { levelNumber = 0; while (command != kCmdQuit) { if (command >= kCmdNewGameLevel1 && command <= kCmdNewGameLevel4) { difficulty = command - kCmdNewGameLevel1; levelNumber = 0; } currentWeaponSF = gConst->kWeaponSF[difficulty]; currentHealthSF = gConst->kHealthSF[difficulty]; currentSpeedSF = gConst->kSpeedSF[difficulty]; LoadLevelData(levelNumber); if (command == kCmdNextLevel) { if (gLevel->player->typeID & kPlayer) ((CPlayer *)gLevel->player)->RestoreDataFromNextLevel(&savedData); gClutManager->FadeToColor(kFadeFromColor, kWhiteCoronaTable, plane); } MSG("--- RunLevel() --- \n"); RunLevel(); if (command == kCmdNextLevel) { levelNumber ++; gClutManager->FadeToColor(kFadeToColor, kWhiteCoronaTable, plane); }else if (command == kCmdPrevLevel) levelNumber --; UnloadLevelData(); } } void CApplication::RunLevel() { char fps[5]; long savedTicks = 0, ticks = 0, ttmp; long frameCount = 0, saveFrameCount = 0; tThingList *currentEntry, *tmp; short message; CThing *tmpThing; char* fileName; firstPlayRound = 1; command = kCmdNoCommand; syncTime = gSystem->GetTicks(); aveTime = 20; while (command == kCmdNoCommand) { frameCount ++; //usleep(1000); time = gSystem->GetTicks(); deltaTime = time - syncTime; aveTime = (aveTime + deltaTime) / 2; syncTime = time; currentEntry = thingList; while (currentEntry) { message = kNoEvent; message |= currentEntry->thing->Think(); if (message == kDestroyMe) { tmp = currentEntry->next; tmpThing = currentEntry->thing; tmpThing->UnlinkInLists(); delete tmpThing; currentEntry = tmp; } else currentEntry = currentEntry->next; } currentEntry = thingList; while (currentEntry) { message = kNoEvent; message |= currentEntry->thing->Forces(); if (message == kDestroyMe) { tmp = currentEntry->next; tmpThing = currentEntry->thing; tmpThing->UnlinkInLists(); delete tmpThing; currentEntry = tmp; } else currentEntry = currentEntry->next; } currentEntry = thingList; while (currentEntry) { currentEntry->thing->Move(); currentEntry = currentEntry->next; } gLevel->PaintLevel(); gGUI->DisplayMessages(); plane->FlipToScreen(0, 0); firstPlayRound = 0; gGUI->Update(); ticks = gSystem->GetTicks(); if (gConst->kShowFPS && ticks - savedTicks > kTicksPerSecond) { sprintf(fps, "%02d", saveFrameCount); gSystem->PaintString(fps, 500, 20, 0); sprintf(fps, "%02d", frameCount); gSystem->PaintString(fps, 500, 20, 255); saveFrameCount = frameCount; frameCount = 0; savedTicks = ticks; } if (gSystem->KeyPressed(kKeyEscape)) { command = gGUI->RunUserInterface(kMainPage); syncTime = gSystem->GetTicks(); } if (command >= kSaveGameSlot0 && command <= kSaveGameSlot5) { fileName = gSystem->QualifyHomeDir(gGUIConst->kSavedGames[command - kSaveGameSlot0]); gLevel->WriteLevel(fileName); // by LL delete [] fileName; command = kCmdNoCommand; } if ((command == kCmdNextLevel) && (gLevel->player->typeID & kPlayer)) ((CPlayer *)(gLevel->player))->SaveDataToNextLevel(&savedData); } } void CApplication::UnloadLevelData() { CThing *tmp; while (thingList) { tmp = thingList->thing; tmp->UnlinkInLists(); delete tmp; } delete gLevel; } void CApplication::UnloadData() { delete gObjInfo; delete gGUI; gShapeManager->UnloadBackground(); gShapeManager->UnloadShapes(); delete gShapeManager; delete gClutManager; } void CApplication::Quit() { delete plane; gSystem->DisposeScreen(); } void CApplication::Enqueue(tThingList **list, CThing *newThing) { tThingList *tmp; if (!newThing) return; tmp = new tThingList; tmp->next = *list; tmp->prev = 0L; tmp->thing = newThing; if (*list) (*list)->prev = tmp; *list = tmp; } // INVARIANT: *list->prev is always 0L, i.e. *list points to the first valid entry in the list void CApplication::Dequeue(tThingList **list, CThing *remove) { tThingList *tmp = *list; if (remove) { while (tmp) { if (tmp->thing == remove) { if (tmp == *list) *list = tmp->next; if (tmp->next) tmp->next->prev = tmp->prev; if (tmp->prev) tmp->prev->next = tmp->next; delete tmp; return; } tmp = tmp->next; } } } /*void CApplication::InsertCollisionThing(CThing *newThing) { if (!newThing) return; if (!collisionThingList) { newThing->nextCollisionThing = 0L; newThing->prevCollisionThing = 0L; collisionThingList = newThing; } else { newThing->prevCollisionThing = 0L; newThing->nextCollisionThing = collisionThingList; collisionThingList->prevCollisionThing = newThing; collisionThingList = newThing; } } void CApplication::RemoveCollisionThing(CThing *remove) { if (collisionThingList == remove) collisionThingList = collisionThingList->nextCollisionThing; if (remove->nextCollisionThing) remove->nextCollisionThing->prevCollisionThing = remove->prevCollisionThing; if (remove->prevCollisionThing) remove->prevCollisionThing->nextCollisionThing = remove->nextCollisionThing; } void CApplication::InsertBullet(CBullet *newBullet) { if (!newBullet) return; if (!bulletList) { newBullet->nextBullet = 0L; newBullet->prevBullet = 0L; bulletList = newBullet; } else { newBullet->prevBullet = 0L; newBullet->nextBullet = bulletList; bulletList->prevBullet = newBullet; bulletList = newBullet; } } void CApplication::RemoveBullet(CBullet *remove) { if (bulletList == remove) bulletList = bulletList->nextBullet; if (remove->nextBullet) remove->nextBullet->prevBullet = remove->prevBullet; if (remove->prevBullet) remove->prevBullet->nextBullet = remove->nextBullet; } void CApplication::InsertPreRenderThing(CThing *newThing) { if (!newThing) return; if (!preRenderQueue) { newThing->nextPreRenderThing = 0L; newThing->prevPreRenderThing = 0L; collisionThingList = newThing; } else { newThing->prevPreRenderThing = 0L; newThing->nextPreRenderThing = preRenderQueue; preRenderQueue->prevPreRenderThing = newThing; preRenderQueue = newThing; } } void CApplication::RemovePreRenderThing(CThing *remove) { if (preRenderQueue == remove) bulletList = bulletList->nextBullet; if (remove->nextBullet) remove->nextBullet->prevBullet = remove->prevBullet; if (remove->prevBullet) remove->prevBullet->nextBullet = remove->nextBullet; }*/amphetamine-0.8.10/src/Appl.hpp0100664000076400007640000000405707447311405014774 0ustar lukeluke#ifndef __AMP_APPL__ #define __AMP_APPL__ #include "AmpHead.hpp" #include "System.hpp" #include "Level.hpp" #include "ObjInfo.hpp" #include "Bullet.hpp" #include "ConstVal.hpp" enum { // commands kCmdNoCommand, kCmdNextLevel, kCmdPrevLevel, kCmdQuit, kCmdNewGameLevel1, kCmdNewGameLevel2, kCmdNewGameLevel3, kCmdNewGameLevel4, kSaveGameSlot0, kSaveGameSlot1, kSaveGameSlot2, kSaveGameSlot3, kSaveGameSlot4, kSaveGameSlot5, kLoadGameSlot0, kLoadGameSlot1, kLoadGameSlot2, kLoadGameSlot3, kLoadGameSlot4, kLoadGameSlot5 }; struct tThingList { tThingList *next, *prev; CThing *thing; }; struct tPlayerData { short munition[8]; short weaponStatus[8]; short currentWeapon; short oxygen; short health; }; class CApplication { protected: tPlayerData savedData; CGraphicSurface *startup; public: tThingList *thingList; tThingList *collisionThingList; tThingList *bulletList; tThingList *preRenderQueue; tThingList *postRenderQueue; tThingList *renderQueue; CGraphicSurface *plane; CPlatform *platformTable[kNumPlatforms]; short lastBackground; short firstPlayRound; long syncTime; // current time in ticks, but only once each play round measured short command; short difficulty; double currentWeaponSF, currentHealthSF, currentSpeedSF; short levelNumber; long time; long deltaTime; long aveTime; CApplication(); ~CApplication(); void InitGraphics(); void LoadData(); void LoadLevelData(short levelNumber); void Run(); void RunLevel(); void UnloadLevelData(); void UnloadData(); void Quit(); void Enqueue(tThingList **list, CThing *newThing); void Dequeue(tThingList **list, CThing *remove); /*void InsertThing(CThing *newThing); void RemoveThing(CThing *remove); void InsertCollisionThing(CThing *newThing); void RemoveCollisionThing(CThing *remove); void InsertBullet(CBullet *newBullet); void RemoveBullet(CBullet *remove); void InsertPreRenderThing(CThing *newThing); void RemovePreRenderThing(CThing *remove); void InsertPostRenderThing(CThing *newThing); void RemovePostRenderThing(CThing *remove);*/ }; #endifamphetamine-0.8.10/src/ConstVal.cpp0100664000076400007640000003046407447311405015625 0ustar lukeluke#include "ConstVal.hpp" #include #include #include #include extern tConstValues *gConst; extern tConfigData *gConfigData; extern FILE *logFile; extern CSystem *gSystem; long GetLongConstant(FILE *f, char *constName); double GetDoubleConstant(FILE *f, char *constName); void GetStringConstant(FILE *f, char *constName, char *buffer); // ------------------------------------------ void LoadParameters() // Loads the general constants from the *.par file { char levelSetString[11] = "xxLevelSet"; char levelBkgndString[13] = "xxLevelBkgnd"; FILE *paramFile = fopen(gSystem->QualifyDataDir(kParFileName), "r"); // by LL gConst = new tConstValues; gConst->kVelocityUnit = GetDoubleConstant(paramFile, "kVelocityUnit"); gConst->kPlayerAcceleration = GetDoubleConstant(paramFile, "kPlayerAcceleration"); gConst->kPlayerLiquidAccel = GetDoubleConstant(paramFile, "kPlayerLiquidAccel"); gConst->kRunScaleFactor = GetDoubleConstant(paramFile, "kRunScaleFactor"); gConst->kJumpVelocity = GetDoubleConstant(paramFile, "kJumpVelocity"); gConst->kJumpAccelerationTime = GetLongConstant(paramFile, "kJumpAccelerationTime"); gConst->kTeleportTime = GetLongConstant(paramFile, "kTeleportTime"); gConst->kPlayerWidth = GetLongConstant(paramFile, "kPlayerWidth"); gConst->kBulletWidth = GetLongConstant(paramFile, "kBulletWidth"); gConst->kFirehandNumOfBullets = GetLongConstant(paramFile, "kFirehandNumOfBullets"); gConst->kFirehandAngle = (double)GetLongConstant(paramFile, "kFirehandAngle") * 3.141 / 180; gConst->kStaffLoadTime = GetLongConstant(paramFile, "kStaffLoadTime"); gConst->kInitialOxygen = GetLongConstant(paramFile, "kInitialOxygen"); gConst->kOxygenDecrease = GetDoubleConstant(paramFile, "kOxygenDecrease"); gConst->kLavaDamage = GetLongConstant(paramFile, "kLavaDamage"); gConst->kPlayersFirstWeaponShape = GetLongConstant(paramFile, "kPlayersFirstWeaponShape"); gConst->kPickupTime = GetLongConstant(paramFile, "kPickupTime"); gConst->kBulletTailLength = GetLongConstant(paramFile, "kBulletTailLength"); gConst->kBulletTailDistance = GetLongConstant(paramFile, "kBulletTailDistance"); gConst->kDetonationFrameTime = GetDoubleConstant(paramFile, "kDetonationFrameTime"); gConst->kWalkFrameTime = GetLongConstant(paramFile, "kWalkFrameTime"); gConst->kShootFrameTime = GetLongConstant(paramFile, "kShootFrameTime"); gConst->kWeaponChangeTime = GetLongConstant(paramFile, "kWeaponChangeTime"); gConst->kActionDelayTime = GetLongConstant(paramFile, "kActionDelayTime"); gConst->kDieFrameTime = GetLongConstant(paramFile, "kDieFrameTime"); gConst->kDriftSpeed = GetLongConstant(paramFile, "kDriftSpeed"); gConst->kWeaponCarryHeight = GetLongConstant(paramFile, "kWeaponCarryHeight"); gConst->kTeleportBlinkTime = GetLongConstant(paramFile, "kTeleportBlinkTime"); gConst->kSavePortBlinkTime = GetLongConstant(paramFile, "kSavePortBlinkTime"); gConst->kExitPortBlinkTime = GetLongConstant(paramFile, "kExitPortBlinkTime"); gConst->kGravitation = GetDoubleConstant(paramFile, "kGravitation"); gConst->kNormalFriction = GetDoubleConstant(paramFile, "kNormalFriction"); gConst->kLiquidFriction = GetDoubleConstant(paramFile, "kLiquidFriction"); gConst->kMaxFallingSpeed = GetDoubleConstant(paramFile, "kMaxFallingSpeed"); gConst->kJumperJumpAcceleration = GetDoubleConstant(paramFile, "kJumperJumpAcceleration"); gConst->kNumOfBounces = GetLongConstant(paramFile, "kNumOfBounces"); gConst->kSineWeaponRad = GetLongConstant(paramFile, "kSineWeaponRad"); gConst->kMaxTurnAngle = (double)GetLongConstant(paramFile, "kMaxTurnAngle") * 3.141 / 180.0; gConst->kWargFastSpeedup = (double)GetLongConstant(paramFile, "kWargFastSpeedup"); gConst->kWargNearWeaponRadix = GetLongConstant(paramFile, "kWargNearWeaponRadix"); gConst->kWargJumpAcceleration = GetDoubleConstant(paramFile, "kWargJumpAcceleration"); gConst->kDelayAfterWargDeath = GetLongConstant(paramFile, "kDelayAfterWargDeath"); gConst->kActivateDistance = GetLongConstant(paramFile, "kActivateDistance"); gConst->kTreatDistance = GetLongConstant(paramFile, "kTreatDistance"); gConst->kBrightnessLevels[0] = GetLongConstant(paramFile, "kLight"); gConst->kBrightnessLevels[1] = GetLongConstant(paramFile, "kMedium"); gConst->kBrightnessLevels[2] = GetLongConstant(paramFile, "kDark"); gConst->kBrightnessLevels[3] = GetLongConstant(paramFile, "kVeryDark"); gConst->kWeaponSF[0] = GetDoubleConstant(paramFile, "kWeaponSF1"); gConst->kWeaponSF[1] = GetDoubleConstant(paramFile, "kWeaponSF2"); gConst->kWeaponSF[2] = GetDoubleConstant(paramFile, "kWeaponSF3"); gConst->kWeaponSF[3] = GetDoubleConstant(paramFile, "kWeaponSF4"); gConst->kHealthSF[0] = GetDoubleConstant(paramFile, "kHealthSF1"); gConst->kHealthSF[1] = GetDoubleConstant(paramFile, "kHealthSF2"); gConst->kHealthSF[2] = GetDoubleConstant(paramFile, "kHealthSF3"); gConst->kHealthSF[3] = GetDoubleConstant(paramFile, "kHealthSF4"); gConst->kSpeedSF[0] = GetDoubleConstant(paramFile, "kSpeedSF1"); gConst->kSpeedSF[1] = GetDoubleConstant(paramFile, "kSpeedSF2"); gConst->kSpeedSF[2] = GetDoubleConstant(paramFile, "kSpeedSF3"); gConst->kSpeedSF[3] = GetDoubleConstant(paramFile, "kSpeedSF4"); gConst->kFlickeringPeriod = GetLongConstant(paramFile, "kFlickeringPeriod"); gConst->kLightningRadiant = GetLongConstant(paramFile, "kLightningRadiant"); gConst->kBkgndScrollFactor = GetDoubleConstant(paramFile, "kBkgndScrollFactor"); gConst->kCoronaFadeSpeed = GetDoubleConstant(paramFile, "kCoronaFadeSpeed"); gConst->kBlessureInvulnerabilityTime = GetLongConstant(paramFile, "kBlessureInvulnerabilityTime"); gConst->kMonsterTouchBlessure = GetLongConstant(paramFile, "kMonsterTouchBlessure"); gConst->kItemExplosionRad = GetLongConstant(paramFile, "kItemExplosionRad"); gConst->kItemExplosionStartShape = GetLongConstant(paramFile, "kItemExplosionStartShape"); gConst->kHealthPanelColor = GetLongConstant(paramFile, "kHealthPanelColor"); gConst->kOxygenPanelColor = GetLongConstant(paramFile, "kOxygenPanelColor"); gConst->kShadowmodeDarkening = GetLongConstant(paramFile, "kShadowmodeDarkening"); gConst->kFadeTime = GetLongConstant(paramFile, "kFadeTime"); gConst->kStartupTime = GetLongConstant(paramFile, "kStartupTime"); gConst->kTextYDistance = GetLongConstant(paramFile, "kTextYDistance"); gConst->kCameraSpeed = GetLongConstant(paramFile, "kCameraSpeed"); gConst->kSoundMaxDistance = GetLongConstant(paramFile, "kSoundMaxDistance"); gConst->kSoundMinDistance = GetLongConstant(paramFile, "kSoundMinDistance"); GetStringConstant(paramFile, "kFilePalette", gConst->kFilePalette); GetStringConstant(paramFile, "kFileLevel", gConst->kFileLevel); GetStringConstant(paramFile, "kFileMonster", gConst->kFileMonster); GetStringConstant(paramFile, "kFileWeapon", gConst->kFileWeapon); GetStringConstant(paramFile, "kFileInfo", gConst->kFileInfo); GetStringConstant(paramFile, "kFilePlatform", gConst->kFilePlatform); GetStringConstant(paramFile, "kFileObjects", gConst->kFileObjects); GetStringConstant(paramFile, "kFileShapes", gConst->kFileShapes); GetStringConstant(paramFile, "kFileBackground1", gConst->kFileBackground1); GetStringConstant(paramFile, "kFileBackground2", gConst->kFileBackground2); GetStringConstant(paramFile, "kFileCluts", gConst->kFileCluts); GetStringConstant(paramFile, "kFileGUIs", gConst->kFileGUIs); GetStringConstant(paramFile, "kFileConfig", gConst->kFileConfig); GetStringConstant(paramFile, "kFileStartup", gConst->kFileStartup); GetStringConstant(paramFile, "kMonsterName1", gConst->kMonsterNames[0]); GetStringConstant(paramFile, "kMonsterName2", gConst->kMonsterNames[1]); GetStringConstant(paramFile, "kMonsterName3", gConst->kMonsterNames[2]); GetStringConstant(paramFile, "kMonsterName4", gConst->kMonsterNames[3]); GetStringConstant(paramFile, "kMonsterName5", gConst->kMonsterNames[4]); GetStringConstant(paramFile, "kMonsterName6", gConst->kMonsterNames[5]); GetStringConstant(paramFile, "kMonsterName7", gConst->kMonsterNames[6]); GetStringConstant(paramFile, "kMonsterName8", gConst->kMonsterNames[7]); GetStringConstant(paramFile, "kMonsterName9", gConst->kMonsterNames[8]); GetStringConstant(paramFile, "kMonsterName10", gConst->kMonsterNames[9]); GetStringConstant(paramFile, "kMonsterName11", gConst->kMonsterNames[10]); gConst->kMonsterNameSpeed = GetLongConstant(paramFile, "kMonsterNameSpeed"); gConst->kMonsterNameX = GetLongConstant(paramFile, "kMonsterNameX"); gConst->kShowFPS = GetLongConstant(paramFile, "kShowFPS"); for (short n = 1; n <= kNumOfLevels; n ++) { levelSetString[0] = (char)(n / 10) + '0'; levelSetString[1] = (char)(n % 10) + '0'; levelBkgndString[0] = (char)(n / 10) + '0'; levelBkgndString[1] = (char)(n % 10) + '0'; gConst->kShapeSets[n -1] = GetLongConstant(paramFile, levelSetString) -1; gConst->kBackgrounds[n -1] = GetLongConstant(paramFile, levelBkgndString); } fclose(paramFile); // Hier sollte auch im Home Directory gesucht werden... paramFile = gSystem->FindFile(gConst->kFileConfig); // by LL gConfigData->leftKey = GetLongConstant(paramFile, "LeftKey"); GetStringConstant(paramFile, "LeftKeyText", gConfigData->leftKeyText); gConfigData->rightKey = GetLongConstant(paramFile, "RightKey"); GetStringConstant(paramFile, "RightKeyText", gConfigData->rightKeyText); gConfigData->jumpKey = GetLongConstant(paramFile, "JumpKey"); GetStringConstant(paramFile, "JumpKeyText", gConfigData->jumpKeyText); gConfigData->runKey = GetLongConstant(paramFile, "RunKey"); GetStringConstant(paramFile, "RunKeyText", gConfigData->runKeyText); gConfigData->shootKey = GetLongConstant(paramFile, "ShootKey"); GetStringConstant(paramFile, "ShootKeyText", gConfigData->shootKeyText); gConfigData->nextWeaponKey = GetLongConstant(paramFile, "NextWeaponKey"); GetStringConstant(paramFile, "NextWeaponKeyText", gConfigData->nextWeaponKeyText); gConfigData->prevWeaponKey = GetLongConstant(paramFile, "PrevWeaponKey"); GetStringConstant(paramFile, "PrevWeaponKeyText", gConfigData->prevWeaponKeyText); gConfigData->activateKey = GetLongConstant(paramFile, "ActivateKey"); GetStringConstant(paramFile, "ActivateKeyText", gConfigData->activateKeyText); gConfigData->weapon1Key = GetLongConstant(paramFile, "Weapon1Key"); gConfigData->weapon2Key = GetLongConstant(paramFile, "Weapon2Key"); gConfigData->weapon3Key = GetLongConstant(paramFile, "Weapon3Key"); gConfigData->weapon4Key = GetLongConstant(paramFile, "Weapon4Key"); gConfigData->weapon5Key = GetLongConstant(paramFile, "Weapon5Key"); gConfigData->weapon6Key = GetLongConstant(paramFile, "Weapon6Key"); gConfigData->weapon7Key = GetLongConstant(paramFile, "Weapon7Key"); gConfigData->weapon8Key = GetLongConstant(paramFile, "Weapon8Key"); gConfigData->soundVolume = GetLongConstant(paramFile, "SoundVolume"); gConfigData->screenWidth = GetLongConstant(paramFile, "ScreenWidth"); gConfigData->screenHeight = GetLongConstant(paramFile, "ScreenHeight"); gConfigData->disableCoronas = GetLongConstant(paramFile, "DisableCoronas"); gConfigData->disableLightning = GetLongConstant(paramFile, "DisableLightning"); gConfigData->disableShapeModes = GetLongConstant(paramFile, "DisableShapeModes"); fclose(paramFile); } #define CATCHSPACES while (c == (unsigned char)' ') {c = fgetc(f); } short GetValue(FILE *f, char *constName, char *value) { char key[30]; char c = 0; short n; fseek(f, 0, SEEK_SET); while (strcmp(key, constName)) { c = fgetc(f); n = 1; if (c == (unsigned char)'#') { // comment while (fgetc(f) != (unsigned char)'\n') {} }else if (c == (unsigned char)'@') { value[0] = '\0'; return 0; }else{ key[0] = c; while (c != (unsigned char)' ' && c != (unsigned char)'=') { c = fgetc(f); key[n] = c; n ++; } key[n - 1] = '\0'; CATCHSPACES if (c != (unsigned char)'=') return 0; c = fgetc(f); n = 1; CATCHSPACES value[0] = c; while (c != (unsigned char)' ' && c != (unsigned char)'\n') { c = fgetc(f); value[n] = c; n ++; } value[n - 1] = '\0'; while (c != (unsigned char)'\n') {c = fgetc(f); } } } if (key[0] == '@') return 0; else return 1; } long GetLongConstant(FILE *f, char *constName) { char val[30]; if (GetValue(f, constName, val)) return atoi(val); else{ return 0; } } double GetDoubleConstant(FILE *f, char *constName) { char val[30]; if (GetValue(f, constName, val)) return atof(val); else{ return 0; } } void GetStringConstant(FILE *f, char *constName, char *buffer) { GetValue(f, constName, buffer); }amphetamine-0.8.10/src/ConstVal.hpp0100664000076400007640000001217507447311405015631 0ustar lukeluke#ifndef __AMP_CONSTVAL__ #define __AMP_CONSTVAL__ #include "AmpHead.hpp" const short kFilenameLength = 12; const short kKeyDescriptionLength = 20; struct tConstValues { // The accelerations and velocities are measured // in pixel / (second * 1000) double kVelocityUnit; double kPlayerAcceleration; double kPlayerLiquidAccel; double kJumpVelocity; double kRunScaleFactor; short kJumpAccelerationTime; short kTeleportTime; // Time for a teleport process short kPlayerWidth; // Width of player used for collisions short kBulletWidth; // Width of bullets used for collisions short kFirehandNumOfBullets; // Num of bullets shots when used firehands double kFirehandAngle; // angle between two shoot directions short kStaffLoadTime; // Time to load the staff weapon short kInitialOxygen; // Inital amound of oxygen double kOxygenDecrease; // Decrease of oxygen in one second short kLavaDamage; // Damage caused by lava per tick short kPlayersFirstWeaponShape; // Players first weapon shape long kPickupTime; // Time the pickup shape is drawn short kBulletTailLength; // How many shapes are to be drawn at the tail of a bullet short kBulletTailDistance; // Distance of two shapes double kDetonationFrameTime; // Every 1/2 second a new detonation frame short kWalkFrameTime; // in ticks short kShootFrameTime; // Time for one shoot animation frame short kWeaponChangeTime; // Time between changing a weapon (Pressing x or y) short kActionDelayTime; // Time between two actions the player performs short kDieFrameTime; // Time between two die frames short kWeaponCarryHeight; // Height of carrying a weapon double kDriftSpeed; // Blinking times for player ports short kTeleportBlinkTime; short kSavePortBlinkTime; short kExitPortBlinkTime; // general physics constants double kGravitation; double kNormalFriction; double kLiquidFriction; double kMaxFallingSpeed; // max. velocity when falling // Monster movement constants double kJumperJumpAcceleration; // How often the sorcery bullet bounces off short kNumOfBounces; short kSineWeaponRad; double kMaxTurnAngle; // max angle a guided bullet can turn short kWargNearWeaponRadix; double kWargFastSpeedup; double kWargJumpAcceleration; long kDelayAfterWargDeath; // Delay before level switch after killed warg // At which distance a bullet becomes a treat for a monster short kTreatDistance; short kBrightnessLevels[4]; long kFlickeringPeriod; short kActivateDistance; // Distance from the player a monster starts to move double kWeaponSF[4]; double kHealthSF[4]; double kSpeedSF[4]; short kLightningRadiant; // Radius of lightning of a bullet double kBkgndScrollFactor; // Background scrolling speed in percent of foreground scrolling speed double kCoronaFadeSpeed; // How many percent of 1 the corona fades every tick short kBlessureInvulnerabilityTime; // How long is a monster invulnerable after a hurt short kMonsterTouchBlessure; // Blessure when touching a monster short kItemExplosionRad; short kItemExplosionStartShape; short kHealthPanelColor; short kOxygenPanelColor; short kShadowmodeDarkening; // Percent of darkness of shaded bodies short kFadeTime; // Time for entirely fading the screen short kStartupTime; // Time for displaying the startup screen short kSoundMaxDistance; // At which distance a sound can be heard short kSoundMinDistance; // At which distance a sound is maximal loud short kTextYDistance; // Distance between two lines of text displayed short kCameraSpeed; // Speed of camera short kShowFPS; // Indicates whether the FPS is displayed char kFilePalette[kFilenameLength]; char kFileLevel[kFilenameLength]; char kFileMonster[kFilenameLength]; char kFileWeapon[kFilenameLength]; char kFileInfo[kFilenameLength]; char kFilePlatform[kFilenameLength]; char kFileObjects[kFilenameLength]; char kFileShapes[kFilenameLength]; char kFileBackground1[kFilenameLength]; char kFileBackground2[kFilenameLength]; char kFileCluts[kFilenameLength]; char kFileGUIs[kFilenameLength]; char kFileConfig[kFilenameLength]; char kFileStartup[kFilenameLength]; char kMonsterNames[11][kFilenameLength]; short kMonsterNameSpeed; // Scrollspeed of monstername short kMonsterNameX; // x-pos on screen short kShapeSets[kNumOfLevels]; short kBackgrounds[kNumOfLevels]; }; struct tConfigData { short leftKey; char leftKeyText[kKeyDescriptionLength]; short rightKey; char rightKeyText[kKeyDescriptionLength]; short jumpKey; char jumpKeyText[kKeyDescriptionLength]; short runKey; char runKeyText[kKeyDescriptionLength]; short shootKey; char shootKeyText[kKeyDescriptionLength]; short nextWeaponKey; char nextWeaponKeyText[kKeyDescriptionLength]; short prevWeaponKey; char prevWeaponKeyText[kKeyDescriptionLength]; short activateKey; char activateKeyText[kKeyDescriptionLength]; short weapon1Key; short weapon2Key; short weapon3Key; short weapon4Key; short weapon5Key; short weapon6Key; short weapon7Key; short weapon8Key; short soundVolume; short haveSound; // by LL short screenWidth; short screenHeight; short tryFullScreen; // by LL short disableCoronas; short disableLightning; short disableShapeModes; }; #endifamphetamine-0.8.10/src/Bullet.cpp0100664000076400007640000003714507447311405015326 0ustar lukeluke#include "Bullet.hpp" #include "Monster.hpp" #include #include "ShapeLd.hpp" #include "Appl.hpp" #include "Clut.hpp" #include "SndSys.hpp" extern CShapeManager *gShapeManager; extern CApplication *gApplication; extern CSystem *gSystem; extern tConstValues *gConst; extern CLevel *gLevel; extern CClutManager *gClutManager; extern CObjInfo *gObjInfo; extern CSoundSystem *gSoundSystem; CBullet::CBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *source, double targetpos) : CThing(initx, inity, width, height, number) { typeID |= kBullet; LinkInLists(); if (weaponInfo) { info = weaponInfo; weight = info->art == kWeaponHasWeight ? 10 : 0; weightless = 0; background = 0; /*xs = xm - gConst->kBulletWidth / 2; ys = ym - gConst->kBulletWidth / 2; xe = xm + gConst->kBulletWidth / 2; ye = ym + gConst->kBulletWidth / 2;*/ OnAllocate(); shooter = source; targetposition = targetpos; if (projectile2) { for (short n = 0; n < gConst->kBulletTailLength; n ++) { tailX[n] = -1; tailY[n] = -1; } tailStep = 0; } directionUnitx = directionx * gConst->kVelocityUnit / sqrt(directionx * directionx + directiony * directiony); directionUnity = directiony * gConst->kVelocityUnit / sqrt(directionx * directionx + directiony * directiony); action = kInFlight; forceVectorX = 0; forceVectorY = 0; resForceX = resForceY = 0; lastTime = gSystem->GetTicks(); deltaTime = 0; } } void CBullet::OnAllocate() { projectile1 = gShapeManager->FindShape(info->projectileShapes[0], 0); projectile2 = gShapeManager->FindShape(info->projectileShapes[1], 0); if (projectile2) { tailX = new short [gConst->kBulletTailLength]; tailY = new short [gConst->kBulletTailLength]; }else{ tailX = tailY = 0L; } currentDetonationShape = 0L; for (short n = 0; n < 5; n ++) detonation[n] = gShapeManager->FindShape(info->detonationShapes[n], 0); } CBullet::~CBullet() { if (projectile2) { delete [] tailX; delete [] tailY; } } void CBullet::LinkInLists() { gApplication->Enqueue(&gApplication->thingList, this); gApplication->Enqueue(&gApplication->bulletList, this); gApplication->Enqueue(&gApplication->renderQueue, this); } void CBullet::UnlinkInLists() { gApplication->Dequeue(&gApplication->thingList, this); gApplication->Dequeue(&gApplication->bulletList, this); gApplication->Dequeue(&gApplication->renderQueue, this); } short CBullet::Think() { CObject::Think(); Gravitation(); if (directionUnitx) forceVectorX = directionUnitx * info->speed * deltaTime; if (directionUnity) forceVectorY = directionUnity * info->speed * deltaTime; return kNoEvent; } short CBullet::Forces() { short collisionCode, collisionObject; tThingList *entry; CElement *element; if (action == kInFlight) { CObject::Forces(); //collisionCode = ExertForce(resForceX, resForceY, collisionObject, &obstacle); if (xm < 0 || ym < 0 || xm > kLevelWidth * kElementSize + kElementSize || ym > kLevelHeight * kElementSize + kElementSize) { Detonate(kCollisionWithLevelBorders, 0L); return kNoEvent; } element = gLevel->GetElement(xm, ym); if (element && !element->background) { Detonate(0, 0L); return kNoEvent; } entry = gApplication->collisionThingList; while (entry) { if (entry->thing != this && entry->thing != shooter && !(entry->thing->typeID & (kBullet | kStaticItem | kPortableItem)) && entry->thing->CollisionPossible(xm, ym)) { Detonate(0, entry->thing); entry = 0L; }else entry = entry->next; } return kNoEvent; }else if (action == kInDetonation) { return DetonationAnimation(); } return kNoEvent; } void CBullet::Detonate(short collisionCode, CObject *victim) { action = kInDetonation; detonationStartTime = lastTime; noDetonation = collisionCode == kCollisionWithLevelBorders; Damage(victim); gSoundSystem->Play(gSoundSystem->weaponHitSounds[thingNumber], xm, ym); if (shooter && !(shooter->typeID & kPlayer)) { if ((directionUnitx > 0 && xe >= targetposition) || (directionUnitx < 0 && xs <= targetposition)) ((CMonster *)shooter)->OnShootSuccessful(); else ((CMonster *)shooter)->OnShootNotSuccessful(); } } short CBullet::DetonationAnimation() { long frame = (long)((double)(lastTime - detonationStartTime) * gConst->kDetonationFrameTime); if (frame > 4 || noDetonation) { currentDetonationShape = 0L; return kDestroyMe; }else{ currentDetonationShape = detonation[frame]; return kNoEvent; } } // --------------------------------------- void CBullet::Damage(CObject *victim) // called from CBullet::DetonationAnimation // sends a TestForDamage-Event to all collision objects { if (info->rad) { tThingList *currentEntry = gApplication->collisionThingList; while (currentEntry) { if (currentEntry->thing != this) currentEntry->thing->TestForDamage(xs, ys, info->rad, info->damage); currentEntry = currentEntry->next; } }else{ if (victim && victim != shooter && victim->typeID & kThing) ((CThing *)victim)->OnDamage(info->damage); } } void CBullet::Move() { if (action == kInFlight) CThing::Move(); if (projectile2) { if (tailStep > gConst->kBulletTailDistance) { for (short n = gConst->kBulletTailLength -2; n >= 0; n --) { tailX[n + 1] = tailX[n]; tailY[n + 1] = tailY[n]; } tailX[0] = (short)xs; tailY[0] = (short)ys; tailStep = 0; }else tailStep += gConst->kVelocityUnit * info->speed * deltaTime; } } void CBullet::Render(short planeX, short planeY, tRect *clipRect) { short tailMode; if (info->effect != kLightningNoEffect) gClutManager->DrawLightning(xm, ym, info->effect, gApplication->plane); if (action == kInFlight) { if (resForceX < 0) modus |= kShapemodusBackwardFlag; if (projectile1) projectile1->RenderShape(xs - planeX, ys - planeY, clipRect, modus, 0, gApplication->plane); }else{ if (currentDetonationShape) currentDetonationShape->RenderShape(xs - planeX, ys - planeY, clipRect, modus, 0, gApplication->plane); } if (projectile2) { for (short n = 0; n < gConst->kBulletTailLength; n ++) { if (n < gConst->kBulletTailLength / 3) tailMode = kShapemodusTransparent1; else if (n > gConst->kBulletTailLength * 2 / 3) tailMode = kShapemodusTransparent3; else tailMode = kShapemodusTransparent2; if (tailX[n] != -1) projectile2->RenderShape(tailX[n] + (short)xs - tailX[0] - planeX, tailY[n] + (short)ys - tailY[0] - planeY, clipRect, tailMode, 0, gApplication->plane); } } } short CBullet::Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject) { if (action != kInDetonation && ((top >= ys && top <= ye) || (bottom >= ys && bottom <= ye)) && sender != shooter && !(sender->typeID & kBullet)) { if (left >= xs && left <= xe) Detonate(kCollisionOnRight, sender); if (right >= xs && right <= xe) Detonate(kCollisionOnLeft, sender); } return kNoCollision; } short CBullet::AmIATreatment(double victimxs, double victimys, double victimxe, double victimye, double &fx, double &fy) { double coll; if ((xm - victimxs) * (xm - victimxs) + (ym - victimys) * (ym - victimys) < gConst->kTreatDistance * gConst->kTreatDistance && SIGN(victimxs - xs) == SIGN(resForceX)) { fx = resForceX; fy = resForceY; if (ABS(resForceX) > ABS(resForceY)) { coll = ym + resForceY * (victimxs - xm) / resForceX; if (coll > victimys - (ye - ys) && coll < victimye + (ye - ys)) return 1; else return 0; }else{ coll = xm + resForceX * (victimys - ym) / resForceY; if (coll > victimxs - (xe - xs) && coll < victimxe + (xe - xs)) return 1; else return 0; } }else return 0; } CSorceryBullet::CSorceryBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *source, double targetpos) : CBullet(initx, inity, width, height, number, weaponInfo, directionx, directiony, source, targetpos) { typeID |= kSorceryBullet; numBounces = 0; } CSorceryBullet::~CSorceryBullet() {} short CSorceryBullet::Forces() { short collisionCode, collisionObject; double savedForcex = forceVectorX, savedForcey = forceVectorY; CObject *collObj; if (action == kInFlight) { CObject::Forces(); collisionCode = ExertForce(resForceX, resForceY, collisionObject, &collObj); if (collisionCode && collObj != shooter) { if (collisionObject & (kElement | kItem | kPlatform) || collObj == shooter) { if (numBounces < gConst->kNumOfBounces) { numBounces ++; if (collisionCode & kCollisionOnTop || collisionCode & kCollisionOnBottom) { forceVectorY = -savedForcey; directionUnity *= -1.0; } if (collisionCode & kCollisionOnLeft || collisionCode & kCollisionOnRight) { forceVectorX = -savedForcex; directionUnitx *= -1.0; } }else{ Detonate(collisionCode, collObj); } }else{ Detonate(collisionCode, collObj); } } }else if (action == kInDetonation) { return DetonationAnimation(); } return kNoEvent; } CBombBullet::CBombBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *source, double targetpos) : CBullet(initx, inity, width, height, number, weaponInfo, directionx, directiony, source, targetpos) { weight = 5; action = kInFlight; detonate = 0; } CBombBullet::~CBombBullet() {} short CBombBullet::Forces() { short collisionObject, returnCode, collisionCode; CObject *obstacle; short dx, dy; if (action != kInDetonation) { CObject::Forces(); collisionCode = ExertForce(resForceX, resForceY, collisionObject, &obstacle); if (collisionCode) { if (collisionObject == kMonster) detonate = 1; } if (detonate == 1) { Detonate(collisionCode, obstacle); if (detonation[0]) detonation[0]->AllowPixelAccess(dx, dy); ys = ye - dy; ye = ys + dy; ym = (ye - ys) / 2; detonate = 2; } }else return DetonationAnimation(); return kNoEvent; } CSineBullet::CSineBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *source, double targetpos, short rad, short per) : CBullet(initx, inity, width, height, number, weaponInfo, directionx, directiony, source, targetpos) { typeID |= kSineBullet; distance = 0; radius = rad; period = 2.0 * 3.141 / (double)per; } CSineBullet::~CSineBullet() {} short CSineBullet::Think() { CObject::Think(); Gravitation(); forceVectorX = gConst->kVelocityUnit * info->speed * deltaTime * SIGN(directionUnitx); distance += forceVectorX; forceVectorY = -radius * period * cos(distance * period); return kNoEvent; } CGuidedBullet::CGuidedBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *source, double targetpos, CThing *tg) : CBullet(initx, inity, width, height, number, weaponInfo, directionx, directiony, source, targetpos) { typeID |= kGuidedBullet; target = tg; if (target) { initAbstSign = SIGN(target->xs - xs); lastfx = target->xs - xs; lastfy = target->ys - ys; lastf = sqrt(lastfx * lastfx + lastfy * lastfy); } } CGuidedBullet::~CGuidedBullet() {} short CGuidedBullet::Think() { double abstx, absty, abst; double alpha, tmp; double a, b, phi1, phi2, dPhi; CObject::Think(); if (target) { abstx = target->xs - xs; absty = target->ys - ys; a = sqrt(lastfx * lastfx + lastfy * lastfy); b = sqrt(abstx*abstx+absty*absty); phi1=asin(lastfy / a); if (lastfx<0) phi1=phi1*(-1.0); phi2=asin(absty/b); if (abstx<0) phi2=phi2*(-1.0); dPhi=phi2-phi1; if (fabs(dPhi)>gConst->kMaxTurnAngle) dPhi=SIGN(dPhi)*gConst->kMaxTurnAngle; tmp=cos(dPhi)*lastfx-sin(dPhi)*lastfy; lastfy=sin(dPhi)*lastfx+cos(dPhi)*lastfy; lastfx = tmp; } forceVectorX = lastfx * gConst->kVelocityUnit * info->speed * deltaTime / lastf; forceVectorY = lastfy * gConst->kVelocityUnit * info->speed * deltaTime / lastf; return kNoEvent; } CStaffBullet::CStaffBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *source, double targetpos, CThing *tg) : CGuidedBullet(initx, inity, width, height, number, weaponInfo, directionx, directiony, source, targetpos, tg) { lastMonsterScanTime = 0; } const double kStaffBulletRad = 40.0; const long kMonsterScanTime = 200; short CStaffBullet::Think() { tThingList *currentEntry; if (!target && lastMonsterScanTime < lastTime) { currentEntry = gApplication->collisionThingList; while (currentEntry) { if (currentEntry->thing->typeID & kMonster && currentEntry->thing != shooter) { if ((currentEntry->thing->xm - xm) * (currentEntry->thing->xm - xm) * 0.5 + (currentEntry->thing->ym - ym) * (currentEntry->thing->ym - ym) < kStaffBulletRad * kStaffBulletRad) { target = currentEntry->thing; } } currentEntry = currentEntry->next; } lastMonsterScanTime = lastTime + kMonsterScanTime; return CBullet::Think(); } else if (target) return CGuidedBullet::Think(); else return kNoEvent; } short CBullet::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(typeID); WRITEDATA(thingNumber); size += CThing::Write(f); if (tailX) { for (short n = 0; n < gConst->kBulletTailLength; n ++) { WRITEDATA(tailX[n]); WRITEDATA(tailY[n]); } } WRITEDATA(tailStep); WRITEDATA(targetposition); WRITEDATA(directionUnitx); WRITEDATA(directionUnity); WRITEDATA(action); WRITEDATA(detonationStartTime); WRITEDATA(noDetonation); FINISHWRITE; return size; } void CBullet::Read(FILE *f) { long size = 0; READDATA(size); READDATA(typeID); READDATA(thingNumber); CThing::Read(f); info = gObjInfo->FindWeapon(thingNumber); shooter = 0L; OnAllocate(); if (projectile2) { for (short n = 0; n < gConst->kBulletTailLength; n ++) { READDATA(tailX[n]); READDATA(tailY[n]); } } READDATA(tailStep); READDATA(targetposition); READDATA(directionUnitx); READDATA(directionUnity); READDATA(action); READDATA(detonationStartTime); READDATA(noDetonation); } short CSorceryBullet::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(typeID); WRITEDATA(thingNumber); size += CBullet::Write(f); WRITEDATA(numBounces); FINISHWRITE; return size; } void CSorceryBullet::Read(FILE *f) { long size = 0; READDATA(size); READDATA(typeID); READDATA(thingNumber); CBullet::Read(f); READDATA(numBounces); } short CBombBullet::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(typeID); WRITEDATA(thingNumber); size += CBullet::Write(f); WRITEDATA(detonate); FINISHWRITE; return size; } void CBombBullet::Read(FILE *f) { long size = 0; READDATA(size); READDATA(typeID); READDATA(thingNumber); CBullet::Read(f); READDATA(detonate); } short CSineBullet::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(typeID); WRITEDATA(thingNumber); size += CBullet::Write(f); WRITEDATA(distance); WRITEDATA(radius); WRITEDATA(period); FINISHWRITE; return size; } void CSineBullet::Read(FILE *f) { long size = 0; READDATA(size); READDATA(typeID); READDATA(thingNumber); CBullet::Read(f); READDATA(distance); READDATA(radius); READDATA(period); } short CGuidedBullet::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(typeID); WRITEDATA(thingNumber); size += CBullet::Write(f); WRITEDATA(initAbstSign); WRITEDATA(lastfx); WRITEDATA(lastfy); WRITEDATA(lastf); FINISHWRITE; return size; } void CGuidedBullet::Read(FILE *f) { long size = 0; READDATA(size); READDATA(typeID); READDATA(thingNumber); CBullet::Read(f); READDATA(initAbstSign); READDATA(lastfx); READDATA(lastfy); READDATA(lastf); } amphetamine-0.8.10/src/Bullet.hpp0100664000076400007640000000633707447567532015350 0ustar lukeluke#ifndef __AMP_BULLET__ #define __AMP_BULLET__ #include "Thing.hpp" #include "ObjInfo.hpp" #include "Shape.hpp" enum { kInFlight, kInDetonation, kWaitForDetonation // only for bombs }; class CBullet : public CThing { protected: CShape *projectile1; CShape *projectile2; CShape *detonation[5]; short *tailX, *tailY; double tailStep; CThing *shooter; double targetposition; tWeaponInfo *info; double directionUnitx; double directionUnity; short action; CShape *currentDetonationShape; long detonationStartTime; short noDetonation; void Detonate(short collisionCode, CObject *); short DetonationAnimation(); void Damage(CObject *); public: CBullet *nextBullet, *prevBullet; CBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *shooter, double targetpos); ~CBullet(); void OnAllocate(); void LinkInLists(); void UnlinkInLists(); virtual short Think(); void Move(); short Forces(); void Render(short planeX, short planeY, tRect *clipRect); short AmIATreatment(double victimxs, double victimys, double victimxe, double victimye, double &fx, double &fy); short Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject); virtual short Write(FILE *f); virtual void Read(FILE *f); }; class CSorceryBullet : public CBullet { protected: short numBounces; public: CSorceryBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *shooter, double targetpos); ~CSorceryBullet(); short Forces(); short Write(FILE *f); void Read(FILE *f); }; class CBomb; class CBombBullet : public CBullet { friend class CBomb; protected: short detonate; public: CBombBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *shooter, double targetpos); ~CBombBullet(); short Forces(); short Write(FILE *f); void Read(FILE *f); }; class CSineBullet : public CBullet { protected: double distance; double radius; double period; public: CSineBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *shooter, double targetpos, short rad, short period); ~CSineBullet(); short Think(); short Write(FILE *f); void Read(FILE *f); }; class CGuidedBullet : public CBullet { protected: CThing *target; double initAbstSign; double lastfx, lastfy, lastf; public: CGuidedBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *shooter, double targetpos, CThing *tg); ~CGuidedBullet(); virtual short Think(); short Write(FILE *f); void Read(FILE *f); }; class CStaffBullet : public CGuidedBullet { protected: long lastMonsterScanTime; public: CStaffBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *shooter, double targetpos, CThing *tg); ~CStaffBullet(); short Think(); }; #endif amphetamine-0.8.10/src/System.cpp0100664000076400007640000003373607447567157015406 0ustar lukeluke/************************************* System.cpp (c) 1999 Jonas Spillmann Contains system-depending routines such as creating windows and video buffers **************************************/ #include "System.hpp" #include "Graphfil.hpp" #include #include #include #include #include #include #include "Appl.hpp" #include "Level.hpp" #include "Player.hpp" #ifdef _USE_LIB_XPM extern "C" { #include } #endif extern FILE *logFile; extern CSystem *gSystem; extern CApplication *gApplication; extern CLevel *gLevel; extern tConfigData *gConfigData; int InitializeSoundSystem(); /* Loads the icon to a surface */ inline static unsigned char Hex2Dec(char digit) { if (digit > 64) return (digit - 55); else return (digit - 48); } static void ExtractColors(char *gstring, Uint8 *red, Uint8 *green, Uint8 *blue) { *red = Hex2Dec(gstring[1])*16+Hex2Dec(gstring[2]); *green = Hex2Dec(gstring[3])*16+Hex2Dec(gstring[4]); *blue = Hex2Dec(gstring[5])*16+Hex2Dec(gstring[6]); } #ifdef _USE_LIB_XPM SDL_Surface *CSystem::XPM2Surface(char *filename) { int x, ret; unsigned int i, y; unsigned char *buffer; unsigned int *data; short pitch; SDL_Surface *icon; XpmImage xpmimage; SDL_Color *palette; ret = XpmReadFileToXpmImage(filename, &xpmimage, NULL); if (ret != XpmSuccess || xpmimage.cpp > 1) { // only 8bit pixmaps will work return NULL; } icon = AllocateBuffer(xpmimage.width,xpmimage.height); palette = new SDL_Color[xpmimage.ncolors]; // Get color palette for (i=0; i < xpmimage.ncolors; ++i) { ExtractColors(xpmimage.colorTable[i].c_color, &(palette[i].r),&(palette[i].g),&(palette[i].b)); } buffer = GetBufferPtr(icon, &pitch); data = xpmimage.data; // Copy data for (y = 0; y < xpmimage.width; y++ ) { for (x = 0; x < xpmimage.height; x++) { *buffer = (unsigned char)*data; buffer++; data++; } } ReleaseBufferPtr(icon); SDL_SetColors(icon, palette, 0, xpmimage.ncolors); return icon; } #endif /* This function may run in a separate event thread */ static int FilterEvents(const SDL_Event *event) { /* This quit event signals the closing of the window */ if ( (event->type == SDL_QUIT) ) { exit(0); return(0); } if ( event->type == SDL_KEYDOWN ) { if (event->key.keysym.mod == KMOD_RALT || event->key.keysym.mod == KMOD_LALT){ switch (event->key.keysym.sym) { case (SDLK_s): gSystem->ScreenShot(); break; case (SDLK_n): gApplication->command = kCmdNextLevel; break; case (SDLK_p): gApplication->command = kCmdPrevLevel; break; case (SDLK_w): ((CPlayer *)gLevel->player)->GetItAll(); break; default: break; } return(0); } } return(1); } char *CSystem::QualifyHomeDir(const char *fname) { char *tmp = new char[strlen(homeDir)+strlen(fname)+2]; sprintf(tmp, "%s/%s", homeDir, fname); return tmp; } char *CSystem::QualifyDataDir(const char *fname) { char *tmp = new char[strlen(dataDir)+strlen(fname)+2]; sprintf(tmp, "%s/%s", dataDir, fname); return tmp; } void CSystem::GetHomeDir() { char *tmp; int rcode; if (tmp = getenv("HOME")) { homeDir = new char[strlen(tmp)+strlen(kHomeName)+2]; sprintf(homeDir, "%s/%s", tmp, kHomeName); } else { homeDir = strdup("."); } rcode = mkdir(homeDir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); } //--------------------------------------------------------- CSystem::CSystem(char *theName) /* In: theName: Name of the application Register the application class and allocates space for the palette WP: - */ { GetHomeDir(); dataDir = new char[strlen(INSTALL_DIR)+1]; strcpy(dataDir, INSTALL_DIR); char *logFileName = QualifyHomeDir(kLogFileName); logFile = fopen(logFileName, "w"); // by LL strcpy(name, theName); /* Initialize SDL */ if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0 ) { MSG("SDL_Init_Failed."); MSG(SDL_GetError()); exit(1); } atexit(SDL_Quit); // Ignore most events SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); SDL_EventState(SDL_MOUSEBUTTONUP, SDL_IGNORE); SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_IGNORE); SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE); SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE); /* Filter quit and mouse motion events */ SDL_SetEventFilter(FilterEvents); #ifdef _USE_LIB_XPM SDL_Surface *icon; icon = XPM2Surface(QualifyDataDir("amph.xpm")); if (icon) { SDL_WM_SetIcon(icon, 0); DisposeBuffer(icon); } #endif textout = false; palColors = new RGBcolor[256]; palette = new SDL_Color[256]; startTicks = 0; } //------------------------------------ CSystem::~CSystem() /* Releases SDL */ { } //----------------------------------------------------------------------------- void CSystem::NewWindow(short left, short top, short width, short height) /* In: left, top, width, height: position and size of windows being created Usually left and top are set to 0 and width, height are equal to the screen size Creates a new window Initializes DirectX Calls sound initialization WP: * Application class registered */ { MSG("InitializeSoundSystem\n"); workingSound = gConfigData->haveSound && !(InitializeSoundSystem()); } //---------------------------------------------------------- void CSystem::DisposeWindow() /* Destroys window */ { SDL_Quit(); } //----------------------------------------------------------------------- void CSystem::AllocateScreen(short rx, short ry, short depth) /* In: rx, ry: Width and height of the videobuffer being allocated depth: Pixeldepth of video buffer. Must be set to 8 Out: - Locks the screen Sets the screen resolution to rx x ry Creates the primary video surface (which is actually the visible screen) WP: * DirectDraw - object allocated (done in NewWindow) * Window created */ { Uint32 sdl_vid_options; MSG("Allocating screens\n"); sdl_vid_options = SDL_INIT_TIMER | SDL_HWSURFACE|SDL_HWPALETTE; if (gConfigData->tryFullScreen) { sdl_vid_options = sdl_vid_options | SDL_FULLSCREEN; } screenPort=SDL_SetVideoMode(640, 480, 8, sdl_vid_options); if (!screenPort) { fprintf(stderr, "Opening a window failed: %s \n", SDL_GetError()); exit(1); } PaintString(name,0,0,0); SDL_ShowCursor(0); } // ------------------------------------------------- tGraphicBuffer *CSystem::AllocateBuffer(short rx, short ry) /* In: rx, ry: Size of buffer being allocated Out: Reference to new graphic buffer Allocates a new graphics buffer. The buffer is allocated in main memory because read access is faster on main memory than on video memory (perhaps not true for AGP video cards) WP: * Directdraw object created */ { tGraphicBuffer *port; MSG("Allocate a buffer\n"); port = SDL_CreateRGBSurface(SDL_SWSURFACE,rx,ry,kScreenDepth,0,0,0,0); if (port == NULL) Error("Error while creating an SDL Surface", 0); return port; } //------------------------------------------------------- void CSystem::DisposeScreen() /* Disposes the screen buffer */ { if (screenPort) SDL_FreeSurface(screenPort); } //------------------------------------------------------ void CSystem::DisposeBuffer(tGraphicBuffer *buffer) /* In: buffer: buffer being disposed Disposes the indicated graphic buffer WP: * buffer exists and is not locked */ { if (buffer) SDL_FreeSurface(buffer); } // -------------------------------------------------------- void CSystem::LoadPalette(char *name) /* In: name: Name of palette file. The palette file must be a *.gif image file with a saved palette. The image itself is ignored Reads the palette file and stores the color information in the allocated palette array Transforms the palette to a DirectDraw - palette and loads it Make this palette active for the screen buffer WP: * directDraw - object allocated * palette allocated (in CSystem::CSystem) * The file name must exist */ { Graphic_file *gf = read_graphic_file(QualifyDataDir(name)); if (!gf) Error("Cannot find or open the palette file (*.pal)", 0); for (short n = 0; n < 256; n ++) { palColors[n].red = gf->palette[n].red; palColors[n].green = gf->palette[n].green; palColors[n].blue = gf->palette[n].blue; } free_graphic_file(gf); // Alle Farben der Reihe nach aus dem File lesen for (short i=0; i<256; i++) { palette[i].r = palColors[i].red; palette[i].g = palColors[i].green; palette[i].b = palColors[i].blue; } // Perform funny color switch palette[0].r = 0; palette[0].g = 0; palette[0].b = 0; palette[255].r = 255; palette[255].g = 255; palette[255].b = 255; SDL_SetColors(screenPort, palette, 0, 256); } // -------------------------------------------------------- void CSystem::SetBufferPalette(tGraphicBuffer *buffer) /* In: buffer: The buffer the palette should be made active Makes the palette active for the indicated buffer. For each buffer this routine must be called WP: * buffer exists * The palette is loaded (done in LoadPalette) */ { SDL_SetColors(buffer, palette, 0, 256); } // ------------------------------------------------------------------------- unsigned char *CSystem::GetBufferPtr(tGraphicBuffer *buffer, short *width) // In: buffer: The buffer being locked for pixel access // // Out: width: Actual width of pixel plane of this buffer // // Prepares the graphic buffer indicated for drawing and returns the actual width // and the adress of the plane // if buffer = 0L, then the standard screen buffer will be locked // // WP: * buffer exists // * width points to a valid container { if ( SDL_MUSTLOCK(buffer) ) { if ( SDL_LockSurface(buffer) < 0 ) return NULL; } *width = buffer->pitch; return (unsigned char *)buffer->pixels; } // ----------------------------------------------------------- void CSystem::ReleaseBufferPtr(tGraphicBuffer *buffer) // Unlocks the graphic buffer indicated. If buffer = 0L, then the standard // screen buffer will be unlocked { if ( SDL_MUSTLOCK(buffer) ) { SDL_UnlockSurface(buffer); } } // ---------------------------------------------------------------- void CSystem::FlipSurfaces(tGraphicBuffer *buffer, short width, short height, short posx, short posy) /* In: buffer: The buffer being flipped to screen width, height: Width and height of the plane being flipped. Usually equal to the size of the buffer posx, posy: Position of the lefttop corner of the flipped plane on the screen */ // Blittes the content of buffer to the screen, assuming the buffer to have width X height, // and blitting it on the screen to position posx / posy // If buffer = 0L, then the standard screen buffer will be blitted using standard coordinates // WP: * The screenPort is allocated (in AllocateScreen) // * buffer exists { int hRet; SDL_Rect rcRect, destRect; if (buffer) { rcRect.x = 0; rcRect.y = 0; rcRect.w = width; rcRect.h = height; destRect.x = posx; destRect.y = posy; destRect.w = width; destRect.h = height; hRet = SDL_BlitSurface( buffer, &rcRect, screenPort,&destRect); SDL_UpdateRects(screenPort, 1, &destRect); } } void CSystem::ProcessEvents() { SDL_Event event; while (SDL_PollEvent(&event)) { } // Luke } //---------------------------------------------- boolVar CSystem::KeyPressed(short key) // In: key: Virtual key code of the tested key // Out: True if the key is being pressed // // WP: - { Uint8 *keyboard_state; ProcessEvents(); keyboard_state = SDL_GetKeyState(0); return (boolVar)(keyboard_state[key] == SDL_PRESSED); } //-------------------------------------------------------- void CSystem::Error(char *message, short errorNo) /* In: message: Error text errorNo: Error number Writes the message followed by the error number in the log file WP: * logFile exists */ { MSG(message); fprintf(logFile, " %d\n", errorNo); fflush(logFile); } long CSystem::GetTickCount() { // Unused struct timeval now; long ticks; gettimeofday(&now, NULL); ticks=now.tv_sec*1000+now.tv_usec/1000; return ticks; } //--------------------------------------------- long CSystem::GetTicks() /* Out: Ticks WP: startTicks is valid (done in ResetTicks) */ { return (SDL_GetTicks() + startTicks); } //--------------------------------------------------- void CSystem::ResetTicks(long startTickOffset) /* In: startTickOffset: Reset value for ticks */ { startTicks = -SDL_GetTicks() + startTickOffset; } //----------------------------------------------------------------------------------- void CSystem::PaintString(char *text, short x, short y, unsigned long foreColor) /* In: text: Text being drawn x, y: Position on screen foreColor: color of text Draws the text on the screen. Usually you do not call this routine WP: * screenPort is allocated */ { SDL_WM_SetCaption(text,NULL); } void CSystem::ScreenShot() { if (screenPort) { char *fileName = QualifyHomeDir("screenshot.bmp"); SDL_SaveBMP(screenPort, fileName); delete [] fileName; } } FILE *CSystem::FindFile(const char *fname) { FILE *tmp; if (tmp=fopen(gSystem->QualifyHomeDir(fname), "r")) return tmp; // check home directory else delete [] tmp; if (tmp=fopen(gSystem->QualifyDataDir(fname), "r")) return tmp; // check data directory else delete [] tmp; return NULL; // failed }amphetamine-0.8.10/src/System.hpp0100664000076400007640000000502507447576441015375 0ustar lukeluke#ifndef __AMP_SYSTEM__ #define __AMP_SYSTEM__ #include #include #include #include #include "AmpHead.hpp" extern "C" { #include } #ifndef INSTALL_DIR #define INSTALL_DIR "/usr/local/games/amph" #endif #if SDL_BYTEORDER == SDL_LIL_ENDIAN #undef __BIG_ENDIAN__ #else #define __BIG_ENDIAN__ 1 #endif typedef bool boolVar; const char kHomeName[] = ".amph"; enum { kKeyLeft = SDLK_LEFT, kKeyRight = SDLK_RIGHT, kKeyUp = SDLK_UP, kKeyDown = SDLK_DOWN, kKeyD = SDLK_d, kKeyC = SDLK_c, kKeyY = SDLK_y, kKeyX = SDLK_x, kKeyScrLock = SDLK_SCROLLOCK, kKeyPrscreen = SDLK_NUMLOCK, kKeyEscape = SDLK_ESCAPE, kKeyTab = SDLK_TAB, kKeyPlus = SDLK_KP_PLUS, kKeyMinus = SDLK_KP_MINUS, kKeyControl = SDLK_LCTRL, kKeyReturn = SDLK_RETURN, kKeySpace = SDLK_SPACE }; const unsigned char kASCIISpace = 32; const unsigned char kASCIIEqual = 61; const long kTicksPerSecond = 1000; // Windows can't change the color indexes for black and white const unsigned char kWhiteColor = 255; const unsigned char kBlackColor = 0; typedef SDL_Surface tGraphicBuffer; //************************* class CSystem ******************** class CSystem { protected: //"""""""""""""""" Misc stuff char name[16]; long startTicks; bool textout; //"""""""""""""""" Graphics stuff tGraphicBuffer *screenPort; SDL_Color *palette; #ifdef _USE_LIB_XPM SDL_Surface *XPM2Surface(char *pixmap); #endif public: RGBcolor *palColors; char *homeDir; char *dataDir; int workingSound; //"""""""""""""""" System Stuff CSystem(char *); ~CSystem(); void NewWindow(short, short, short, short); void DisposeWindow(); //"""""""""""""""" SDL Stuff void AllocateScreen(short rx, short ry, short depth); tGraphicBuffer *AllocateBuffer(short rx, short ry); void DisposeBuffer(tGraphicBuffer *); void DisposeScreen(); void LoadPalette(char *name); void SetBufferPalette(tGraphicBuffer *); unsigned char *GetBufferPtr(tGraphicBuffer *, short *width); void ReleaseBufferPtr(tGraphicBuffer *); void FlipSurfaces(tGraphicBuffer *, short width, short height, short posx, short posy); //"""""""""""""""" User stuff void Error(char *message, short errorNo); boolVar KeyPressed(short key); long GetTicks(); long GetTickCount(); void ResetTicks(long startTickOffset); void PaintString(char *, short x, short y, unsigned long color); void ProcessEvents(); void GetHomeDir(); char *QualifyDataDir(const char *fname); char *QualifyHomeDir(const char *fname); void ScreenShot(); FILE *FindFile(const char *fname); }; #endif amphetamine-0.8.10/src/SndSys.cpp0100664000076400007640000000716607447311405015322 0ustar lukeluke#include "SndSys.hpp" #include "Level.hpp" #include "ConstVal.hpp" extern CSoundSystem *gSoundSystem; extern CLevel *gLevel; extern tConstValues *gConst; extern tConfigData *gConfigData; const short kMaxUserSound = 10; void Mix_Audio(void *udata, Uint8 *stream, int len) { gSoundSystem->ProcessList(udata, stream, len); } int InitializeSoundSystem() { SDL_AudioSpec wanted, obtained; /* Set the audio format */ // Not all sounds are of the same sampling rate which is why // some of them sound a little crappy. Some conversion should be performed... wanted.freq = 11025; wanted.format = (AUDIO_U8); wanted.channels = 1; wanted.samples = 512; /* Good low-latency value for callback */ wanted.callback = Mix_Audio; wanted.userdata = NULL; /* Open the audio device, forcing the desired format */ if ( SDL_OpenAudio(&wanted, &obtained) < 0 ) { fprintf(stderr, "InitSoundSystem: Couldn't open audio: %s\n", SDL_GetError()); fprintf(stderr, "Sound was disabled. \n"); return(-1); } return(0); } CSoundSystem::CSoundSystem(int status) { state=status; for (short n = 0; n < kNumWeapons; n ++) { weaponLaunchSounds[n] = new CSound(kWeaponLaunchSounds[n]); weaponHitSounds[n] = new CSound(kWeaponHitSounds[n]); } platformGo = new CSound(kPlatformGoSound); platformStop = new CSound(kPlatformStopSound); lightOn = new CSound(kLightOnSound); lightOff = new CSound(kLightOffSound); firestoneDamage = new CSound(kFirestoneDamage); selMenu = new CSound(kSelMenuSound); entrMenu = new CSound(kEntrMenuSound); openMenu = new CSound(kOpenMenuSound); playerJump = new CSound(kPlayerJumpSound); playerDive = new CSound(kPlayerDiveSound); playerPickup = new CSound(kPlayerPickupSound); minDistance = gConst->kSoundMinDistance * gConst->kSoundMinDistance; maxDistance = gConst->kSoundMaxDistance * gConst->kSoundMaxDistance; playList = new CSoundList(); currentMaxSound = (SDL_MIX_MAXVOLUME) * gConfigData->soundVolume / kMaxUserSound; if (state) { SDL_PauseAudio(0); // turn the music on... } } CSoundSystem::~CSoundSystem() { if (state) { SDL_PauseAudio(1); SDL_CloseAudio(); } delete playList; for (short n = 0; n < kNumWeapons; n ++) { delete weaponLaunchSounds[n]; delete weaponHitSounds[n]; } delete platformGo; delete platformStop; delete lightOn; delete lightOff; delete playerJump; delete playerDive; delete playerPickup; } void CSoundSystem::Play(CSound *which, double x, double y) { if (!state) return; long distance = (long)((x - gLevel->focus->xm) * (x - gLevel->focus->xm) + (y - gLevel->focus->ym) * (y - gLevel->focus->ym)); double factor; SoundState *newstate = new SoundState; if (distance < minDistance) { which->SetVol(currentMaxSound); } else if (distance < maxDistance) { factor = double(distance - minDistance) / double(maxDistance - minDistance); which->SetVol(currentMaxSound - currentMaxSound * factor); } else return; which->Play(newstate); playList->Insert(newstate); } void CSoundSystem::ProcessList(void *udata, Uint8 *stream, int len) { SoundState *theSound; int mixlen; playList->Reset(); // traverse the list of sounds being played while (theSound = playList->GetNext()) { mixlen = MIN(len, (int) theSound->bytesleft); SDL_MixAudio(stream, theSound->soundpos, mixlen, theSound->volume); theSound->soundpos += mixlen; theSound->bytesleft -= mixlen; if (!theSound->bytesleft) { // sound finished playing playList->RemoveCurrent(); } } }amphetamine-0.8.10/src/SndSys.hpp0100664000076400007640000000425607447311405015324 0ustar lukeluke#ifndef _AMPH_SOUND_SYS_ #define _AMPH_SOUND_SYS_ #include "ObjInfo.hpp" #include "SoundList.hpp" const char kWeaponLaunchSounds[kNumWeapons][21] = { "sounds/swordl.wav", "sounds/phioll.wav", "sounds/sorceryl.wav", "sounds/bowl.wav", "sounds/sciel.wav", "sounds/handsl.wav", "sounds/bombl.wav", "sounds/staffl.wav", "sounds/borkl.wav", "sounds/aimedl.wav", "sounds/guidedl.wav", "sounds/trolll.wav", "sounds/otygl.wav", "sounds/nazgull.wav", "sounds/warg1l.wav", "sounds/warg2l.wav" }; const char kWeaponHitSounds[kNumWeapons][21] = { "sounds/swordh.wav", "sounds/phiolh.wav", "sounds/sorceryh.wav", "sounds/bowh.wav", "sounds/scieh.wav", "sounds/handsh.wav", "sounds/bombh.wav", "sounds/staffh.wav", "sounds/borkh.wav", "sounds/aimedh.wav", "sounds/guidedh.wav", "sounds/trollh.wav", "sounds/otygh.wav", "sounds/nazgulh.wav", "sounds/warg1h.wav", "sounds/warg2h.wav" }; const char kPlatformGoSound[21] = "sounds/platgo.wav"; const char kPlatformStopSound[21] = "sounds/platstop.wav"; const char kLightOnSound[21] = "sounds/lighton.wav"; const char kLightOffSound[21] = "sounds/lightoff.wav"; const char kSelMenuSound[21] = "sounds/selmenu.wav"; const char kEntrMenuSound[21] = "sounds/entrmenu.wav"; const char kOpenMenuSound[21] = "sounds/openmenu.wav"; const char kFirestoneDamage[21] = "sounds/stonedam.wav"; const char kPlayerJumpSound[21] = "sounds/jump.wav"; const char kPlayerDiveSound[21] = "sounds/dive.wav"; const char kPlayerPickupSound[21] = "sounds/pickup.wav"; class CSoundSystem { private: long maxDistance, minDistance; long currentMaxSound; // List of sounds being played CSoundList *playList; public: // Weapon sounds int state; CSound *weaponLaunchSounds[kNumWeapons]; CSound *weaponHitSounds[kNumWeapons]; // Platform and light sounds CSound *platformGo; CSound *platformStop; CSound *lightOn; CSound *lightOff; // Item sounds CSound *firestoneDamage; // GUI sounds CSound *selMenu; CSound *entrMenu; CSound *openMenu; CSound *playerJump; CSound *playerDive; CSound *playerPickup; CSoundSystem(int state); ~CSoundSystem(); void ProcessList(void*, Uint8*, int ); void Play(CSound *which, double x, double y); }; #endifamphetamine-0.8.10/src/Object.cpp0100664000076400007640000002252207447600010015267 0ustar lukeluke#include "Object.hpp" #include "Appl.hpp" #include "ConstVal.hpp" #include enum { kLeftTopCorner = 0, kLeftBottomCorner = 1, kRightTopCorner = 2, kRightBottomCorner = 3 }; const double kCollisionThingDetectError = 3.0; extern CApplication *gApplication; extern CSystem *gSystem; extern CLevel *gLevel; extern tConstValues *gConst; CObject::CObject(short initx, short inity, short width, short height) { typeID = 0; typeID |= kObject; xm = initx; ym = inity; xs = xm - width / 2; ys = ym - height / 2; xe = xs + width; ye = ys + height; forceVectorX = forceVectorY = 0; gravitation = 0; environmentForceX = environmentForceY = 0; lastTime = 0; // additinal initializations weight = 0; resForceX = resForceY = 0; deltaTime = 0; background = 0; } CObject::~CObject() {} short CObject::Think() { deltaTime = gApplication->deltaTime; lastTime = gApplication->time; pusher = 0L; environmentForceX = environmentForceY = 0; return kNoEvent; } short CObject::Forces() { resForceX = forceVectorX; resForceY = forceVectorY + gravitation; return kNoEvent; } void CalcSteps(double forcex, double forcey, double &sx, double &sy) { if (ABS(forcex) > ABS(forcey)) { sx += SIGN(forcex); sy += forcey / ABS(forcex); }else{ sy += SIGN(forcey); sx += forcex / ABS(forcey); } } short CObject::ExertForce(double &forcex, double &forcey, short &collisionObject, CObject **obstacle) { double sx = 0, sy = 0; short oldElem1x = -1, elem1x, oldElem1y = -1, elem1y; short oldElem2x = -1, elem2x, oldElem2y = -1, elem2y; short oldElem3x = -1, elem3x, oldElem3y = -1, elem3y; short oldElem4x = -1, elem4x, oldElem4y = -1, elem4y; short resultCode = 0, oldResultCode; double oldForcex = forcex, oldForcey = forcey; tThingList *currentEntry; double postForcex, postForcey; short tmpResultCode; if (obstacle) *obstacle = 0L; if (!forcex && !forcey) return kNoCollision; do { if (xs + sx <= 0) { resultCode |= kCollisionOnLeft; resultCode |= kCollisionWithLevelBorders; } if (xs + sx >= kLevelWidth * kElementSize -1) { resultCode |= kCollisionOnRight; resultCode |= kCollisionWithLevelBorders; } if (ys + sy <= 0) { resultCode |= kCollisionOnTop; resultCode |= kCollisionWithLevelBorders; } postForcex = (ABS(sx) > ABS(forcex) ? forcex : forcex - sx); postForcey = (ABS(sy) > ABS(forcey) ? forcey : forcey - sy); elem1x = (xs + sx) / kElementSize; elem1y = (ys + sy) / kElementSize; if ((elem1x != oldElem1x || elem1y != oldElem1y) && elem1x >= 0 && elem1y >= 0 && elem1x < kLevelWidth && elem1y < kLevelHeight) { resultCode |= gLevel->level[elem1y][elem1x]->Collision(this, xs + sx, ys + sy, xe + sx, ye + sy, forcex, forcey, postForcex, postForcey, weight, collisionObject); oldElem1x = elem1x; oldElem1y = elem1y; } elem2x = (xe + sx) / kElementSize; elem2y = (ys + sy) / kElementSize; if ((elem2x != oldElem2x || elem2y != oldElem2y) && elem2x >= 0 && elem2y >= 0 && elem2x < kLevelWidth && elem2y < kLevelHeight) { resultCode |= gLevel->level[elem2y][elem2x]->Collision(this, xs + sx, ys + sy, xe + sx, ye + sy, forcex, forcey, postForcex, postForcey, weight, collisionObject); oldElem2x = elem2x; oldElem2y = elem2y; } elem3x = (xs + sx) / kElementSize; elem3y = (ye + sy) / kElementSize; if ((elem3x != oldElem3x || elem3y != oldElem3y) && elem3x >= 0 && elem3y >= 0 && elem3x < kLevelWidth && elem3y < kLevelHeight) { resultCode |= gLevel->level[elem3y][elem3x]->Collision(this, xs + sx, ys + sy, xe + sx, ye + sy, forcex, forcey, postForcex, postForcey, weight, collisionObject); oldElem3x = elem3x; oldElem3y = elem3y; } elem4x = (xe + sx) / kElementSize; elem4y = (ye + sy) / kElementSize; if ((elem4x != oldElem4x || elem4y != oldElem4y) && elem4x >= 0 && elem4y >= 0 && elem4x < kLevelWidth && elem4y < kLevelHeight) { resultCode |= gLevel->level[elem4y][elem4x]->Collision(this, xs + sx, ys + sy, xe + sx, ye + sy, forcex, forcey, postForcex, postForcey, weight, collisionObject); oldElem4x = elem4x; oldElem4y = elem4y; } currentEntry = gApplication->collisionThingList; while (currentEntry) { oldResultCode = resultCode; tmpResultCode = 0; if (currentEntry->thing != this) tmpResultCode = currentEntry->thing->Collision(this, xs + sx, ys + sy, xe + sx, ye + sy, forcex, forcey, postForcex, postForcey, weight, collisionObject); if (obstacle && tmpResultCode) *obstacle = currentEntry->thing; resultCode |= tmpResultCode; currentEntry = currentEntry->next; } if ((resultCode & kCollisionOnTop) || (resultCode & kCollisionOnBottom)) { if ((resultCode & kCollisionOnLeft) || (resultCode & kCollisionOnRight)) forcex = forcey = 0; } CalcSteps(forcex, forcey, sx, sy); } while ((forcex || forcey) && (ABS(sx) < ABS(forcex) || !forcex) && (ABS(sy) < ABS(forcey) || !forcey)); if (ABS(forcex) > 1.0 && ((resultCode & kCollisionOnLeft) || (resultCode & kCollisionOnRight))) forcex = sx; if (ABS(forcey) > 1.0 && ((resultCode & kCollisionOnTop) || (resultCode & kCollisionOnBottom))) forcey = sy; if ((resultCode & kCollisionOnTop) && forcey < 0) forceVectorY = forcey = 0; if (resultCode & kCollisionOnBottom) forceVectorY = forcey = 0; return resultCode; } void CObject::OnTouch(CObject *touch) {} // Determines if the line a1-a2 intersects with the line b1-b2 where equality does not count short PointIntersection(double a1, double a2, double b1, double b2) { return !((a1 >= b1 && a2 >= b1 && a1 >= b2 && a2 >= b2) || (a1 <= b1 && a2 <= b1 && a1 <= b2 && a2 <= b2)); } // Determines if the line a1-a2 intersects with the line b1-b2 where equality does count short PointTouch(double a1, double a2, double b1, double b2) { return !((a1 > b1 && a2 > b1 && a1 > b2 && a2 > b2) || (a1 < b1 && a2 < b1 && a1 < b2 && a2 < b2)); } short CObject::CollisionPossible(double ptx, double pty) { return (!background && ptx >= xs && ptx < xe && pty >= ys && pty < ye); } short CObject::Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double postForcex, double postForcey, short sourceWeight, short &collisionObject) { if (background || (!forcex && !forcey)) return kNoCollision; if (weight < sourceWeight) { short carryx = 0, carryy = 0, collCode = kCollisionWithPushing; double tmpForcex = forcex, tmpForcey = forcey; pusher = sender; sender->OnTouch(this); if (((short)left >= (short)xe - kCollisionThingDetectError && (short)(left + forcex) <= (short)xe) || ((short)right <= (short)xs + kCollisionThingDetectError && (short)(right + forcex + kCollisionThingDetectError) >= (short)xs)) { carryy = 1; forcey = 0; } if ((short)bottom <= (short)ys + kCollisionThingDetectError && (short)(bottom + forcey) >= (short)ys) { carryx = 1; forcex = 0; collCode |= kCollisionOnBottom; } collCode |= ExertForce(forcex, forcey, collisionObject, 0L); environmentForceX = forcex; environmentForceY = forcey; if (carryx) forcex = tmpForcex; if (carryy) forcey = tmpForcey; return collCode; } else { if ((short)right == (short)xs && (PointIntersection(floor(top), floor(bottom), floor(ys), floor(ye) -1) || ((short)top == (short)ys && (short)bottom == (short)ye))) { if (forcex > 0) { forcex = 0; //sender->OnTouch(this); collisionObject = typeID; return kCollisionOnRight; } } if ((short)left == (short)xe -1 && (PointIntersection(floor(top), floor(bottom), floor(ys), floor(ye) -1) || ((short)top == (short)ys && (short)bottom == (short)ye))) { if (forcex < 0) { forcex = 0; //sender->OnTouch(this); collisionObject = typeID; return kCollisionOnLeft; } } if (((short)bottom >= (short)ys && (short)bottom <= (short)ys + 3) && PointIntersection(floor(left), floor(right), floor(xs), floor(xe) -1)) { if (forcey > 0) { forcey = 0; //sender->OnTouch(this); collisionObject = typeID; return kCollisionOnBottom; } } if ((short)top == (short)ye -1 && PointIntersection(floor(left), floor(right), floor(xs), floor(xe) -1)) { if (forcey < 0) { forcey = 0; //sender->OnTouch(this); collisionObject = typeID; return kCollisionOnTop; } } return kNoCollision; } } void CObject::CollisionEvent(double friction, double externForce) { double theorForce; if (forceVectorX) { theorForce = forceVectorX - SIGN(forceVectorX) * friction * deltaTime; if (SIGN(theorForce) != SIGN(forceVectorX)) forceVectorX = 0; else forceVectorX = theorForce; } if (externForce) environmentForceX += externForce * deltaTime * gConst->kVelocityUnit; } short CObject::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(typeID); WRITEDATA(xs); WRITEDATA(ys); WRITEDATA(xe); WRITEDATA(ye); WRITEDATA(xm); WRITEDATA(ym); WRITEDATA(weight); WRITEDATA(forceVectorX); WRITEDATA(forceVectorY); WRITEDATA(environmentForceX); WRITEDATA(environmentForceY); WRITEDATA(gravitation); WRITEDATA(resForceX); WRITEDATA(resForceY); WRITEDATA(background); FINISHWRITE; return size; } void CObject::Read(FILE *f) { long size; READDATA(size); READDATA(typeID); READDATA(xs); READDATA(ys); READDATA(xe); READDATA(ye); READDATA(xm); READDATA(ym); READDATA(weight); READDATA(forceVectorX); READDATA(forceVectorY); READDATA(environmentForceX); READDATA(environmentForceY); READDATA(gravitation); READDATA(resForceX); READDATA(resForceY); READDATA(background); } amphetamine-0.8.10/src/Object.hpp0100664000076400007640000000262507447360231015306 0ustar lukeluke#ifndef __AMP_OBJECT__ #define __AMP_OBJECT__ #include "Shape.hpp" class CMonster; class CGuidedBullet; class CSoundSystem; class CObject { friend class CMonster; friend class CGuidedBullet; friend class CSoundSystem; protected: short weight; double forceVectorX, forceVectorY; double environmentForceX, environmentForceY; double gravitation; double resForceX, resForceY; long lastTime, deltaTime; CObject *pusher; public: unsigned long typeID; short background; double xs, ys, xe, ye, xm, ym; CObject(short initx, short inity, short width, short height); ~CObject(); short ExertForce(double &forcex, double &forcey, short &collisionObject, CObject **obstacle); virtual short Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject); virtual void CollisionEvent(double friction, double externForce); virtual short CollisionPossible(double ptx, double pty); virtual short Think(); virtual short Forces(); virtual void OnTouch(CObject *touch); virtual short Write(FILE *f); virtual void Read(FILE *f); }; #define WRITEDATA(data) fwrite(&data, sizeof(data), 1, f); size += sizeof(data) #define READDATA(data) fread(&data, sizeof(data), 1, f); #define FINISHWRITE fseek(f, -size, SEEK_CUR); fwrite(&size, sizeof(size), 1, f); fseek(f, size - sizeof(size), SEEK_CUR); #endif amphetamine-0.8.10/src/Item.cpp0100664000076400007640000001701407447311405014766 0ustar lukeluke#include "Item.hpp" #include "Appl.hpp" #include "Clut.hpp" #include "SndSys.hpp" extern CApplication *gApplication; extern CShapeManager *gShapeManager; extern CLevel *gLevel; extern tConstValues *gConst; extern CClutManager *gClutManager; extern CSoundSystem *gSoundSystem; CItem::CItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo) : CThing(initx, inity, width, height, number) { typeID |= kItem; info = itemInfo; shape = gShapeManager->FindShape(itemInfo->iconID, 0); currentShape = shape; detonationStartTime = -1; isCorona = info->iconID >= kCoronaIDs[0] && info->iconID <= kCoronaIDs[kNumOfCoronas -1]; coronaFader = 0.0; deltaTime = 0; dx -= 1; xe -= 1; } CItem::~CItem() {} short CItem::Think() { CObject::Think(); if (detonationStartTime != -1) { long frame = (long)((double)(lastTime - detonationStartTime) * gConst->kDetonationFrameTime); if (frame > 4) return kDestroyMe; else currentShape = gShapeManager->FindShape(gConst->kItemExplosionStartShape + frame, 0); } return kNoEvent; } void CItem::Move() { CThing::Move(); environmentForceX = environmentForceY = 0; } void CItem::Render(short planeX, short planeY, tRect *clipRect) { CElement *element = gLevel->GetElement(xm, ym); if (!isCorona && currentShape) currentShape->RenderShape(xs - planeX, ys - planeY, clipRect, modus, element ? element->brightness : 0, gApplication->plane); else if (isCorona) gClutManager->PrepareCorona(xm, ym, gApplication->plane); } void CItem::PostRender(short planeX, short planeY, tRect *clipRect) { if (isCorona) { CElement *element = gLevel->GetElement(xm, ym); gClutManager->DrawCorona(xm, ym, info->iconID - kCoronaIDs[0], element->data ? element->data : 1, gApplication->plane, coronaFader, deltaTime); } } void CItem::OnDamage(short blessure) { if (blessure && info->flags & kItemExplodesMask && detonationStartTime == -1) { tThingList *currentEntry = gApplication->collisionThingList; detonationStartTime = lastTime; while (currentEntry) { if (currentEntry->thing != this) currentEntry->thing->TestForDamage(xs, ys, gConst->kItemExplosionRad, info->data); currentEntry = currentEntry->next; } } } CStaticItem::CStaticItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo) : CItem(initx, inity, width, height, number, itemInfo) { typeID |= kStaticItem; background = 0; weight = 32000; weightless = 1; LinkInLists(); } CStaticItem::~CStaticItem() { } void CStaticItem::LinkInLists() { gApplication->Enqueue(&gApplication->thingList, this); gApplication->Enqueue(&gApplication->collisionThingList, this); if (isCorona) { gApplication->Enqueue(&gApplication->preRenderQueue, this); gApplication->Enqueue(&gApplication->postRenderQueue, this); }else gApplication->Enqueue(&gApplication->renderQueue, this); } void CStaticItem::UnlinkInLists() { gApplication->Dequeue(&gApplication->thingList, this); gApplication->Dequeue(&gApplication->collisionThingList, this); if (isCorona) { gApplication->Dequeue(&gApplication->preRenderQueue, this); gApplication->Dequeue(&gApplication->postRenderQueue, this); }else gApplication->Dequeue(&gApplication->renderQueue, this); } short CStaticItem::Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject) { short returnValue = CThing::Collision(sender, left, top, right, bottom, forcex, forcey, pfx, pfy, sourceWeight, collisionObject); if (returnValue && info->flags & kItemHurtMask) { ((CThing *)sender)->OnDamage(info->data); } return returnValue; } CBackgroundItem::CBackgroundItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo) : CItem(initx, inity, width, height, number, itemInfo) { typeID |= kBackgroundItem; weight = 0; // Background items are hanging in the air, they don't fall, so they have no weight background = 1; weightless = 1; LinkInLists(); } CBackgroundItem::~CBackgroundItem() { } void CBackgroundItem::LinkInLists() { gApplication->Enqueue(&gApplication->thingList, this); gApplication->Enqueue(&gApplication->preRenderQueue, this); if (isCorona) { gApplication->Enqueue(&gApplication->postRenderQueue, this); } } void CBackgroundItem::UnlinkInLists() { gApplication->Dequeue(&gApplication->thingList, this); gApplication->Dequeue(&gApplication->preRenderQueue, this); if (isCorona) { gApplication->Dequeue(&gApplication->postRenderQueue, this); } } CMovableItem::CMovableItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo) : CItem(initx, inity, width, height, number, itemInfo) { typeID |= kMovableItem; weight = 1; background = 0; LinkInLists(); } CMovableItem::~CMovableItem() { } void CMovableItem::LinkInLists() { gApplication->Enqueue(&gApplication->thingList, this); gApplication->Enqueue(&gApplication->collisionThingList, this); if (isCorona) { gApplication->Enqueue(&gApplication->preRenderQueue, this); gApplication->Enqueue(&gApplication->postRenderQueue, this); }else gApplication->Enqueue(&gApplication->renderQueue, this); } void CMovableItem::UnlinkInLists() { gApplication->Dequeue(&gApplication->thingList, this); gApplication->Dequeue(&gApplication->collisionThingList, this); if (isCorona) { gApplication->Dequeue(&gApplication->preRenderQueue, this); gApplication->Dequeue(&gApplication->postRenderQueue, this); }else gApplication->Dequeue(&gApplication->renderQueue, this); } CPortableItem::CPortableItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo, short itemNo) : CItem(initx, inity, width, height, number, itemInfo) { typeID |= kPortableItem; type = itemNo; background = 0; weight = 1; pickedUp = 0; LinkInLists(); } CPortableItem::~CPortableItem() { } void CPortableItem::LinkInLists() { gApplication->Enqueue(&gApplication->thingList, this); gApplication->Enqueue(&gApplication->collisionThingList, this); if (isCorona) { gApplication->Enqueue(&gApplication->preRenderQueue, this); gApplication->Enqueue(&gApplication->postRenderQueue, this); }else gApplication->Enqueue(&gApplication->renderQueue, this); } void CPortableItem::UnlinkInLists() { gApplication->Dequeue(&gApplication->thingList, this); gApplication->Dequeue(&gApplication->collisionThingList, this); if (isCorona) { gApplication->Dequeue(&gApplication->preRenderQueue, this); gApplication->Dequeue(&gApplication->postRenderQueue, this); }else gApplication->Dequeue(&gApplication->renderQueue, this); } short CPortableItem::Think() { CObject::Think(); if (pickedUp) return kDestroyMe; else return kNoEvent; } short CPortableItem::PickMeUp(short &value) { value = info->data; pickedUp = 1; return type; } short CItem::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(typeID); WRITEDATA(thingNumber); size += CThing::Write(f); WRITEDATA(isCorona); WRITEDATA(detonationStartTime); FINISHWRITE; return size; } void CItem::Read(FILE *f) { long size = 0; READDATA(size); READDATA(typeID); READDATA(thingNumber); CThing::Read(f); READDATA(isCorona); READDATA(detonationStartTime); } short CPortableItem::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(typeID); WRITEDATA(thingNumber); size += CItem::Write(f); WRITEDATA(pickedUp); WRITEDATA(type); FINISHWRITE; return size; } void CPortableItem::Read(FILE *f) { long size = 0; READDATA(size); READDATA(typeID); READDATA(thingNumber); CItem::Read(f); READDATA(pickedUp); READDATA(type); }amphetamine-0.8.10/src/Item.hpp0100664000076400007640000000351607447323020014771 0ustar lukeluke#ifndef __AMP_ITEM__ #define __AMP_ITEM__ #include "Thing.hpp" #include "ObjInfo.hpp" #include "Shape.hpp" class CItem : public CThing { protected: CShape *shape; CShape *currentShape; tItemInfo *info; long detonationStartTime; short isCorona; double coronaFader; public: CItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo); ~CItem(); short Think(); void Render(short planeX, short planeY, tRect *clipRect); void PostRender(short planeX, short planeY, tRect *clipRect); void Move(); void OnDamage(short blessure); short Write(FILE *f); void Read(FILE *f); }; class CStaticItem : public CItem { protected: public: CStaticItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo); ~CStaticItem(); void LinkInLists(); void UnlinkInLists(); short Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject); }; class CBackgroundItem : public CItem { protected: public: CBackgroundItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo); ~CBackgroundItem(); void LinkInLists(); void UnlinkInLists(); }; class CMovableItem : public CItem { protected: public: CMovableItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo); ~CMovableItem(); void LinkInLists(); void UnlinkInLists(); }; class CPortableItem : public CItem { protected: short pickedUp; short type; public: CPortableItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo, short type); ~CPortableItem(); void LinkInLists(); void UnlinkInLists(); short Think(); short PickMeUp(short &value); short Write(FILE *f); void Read(FILE *f); }; #endifamphetamine-0.8.10/src/Creeper.cpp0100664000076400007640000000002707447311405015451 0ustar lukeluke#include "Creeper.hpp" amphetamine-0.8.10/src/Creeper.hpp0100664000076400007640000000012007447311405015450 0ustar lukeluke#ifndef __AMP_CREEPER__ #define __AMP_CREEPER__ #include "Monster.hpp" #endifamphetamine-0.8.10/src/Weapon.cpp0100664000076400007640000003044307447311405015322 0ustar lukeluke#include "Weapon.hpp" #include "System.hpp" #include "Bullet.hpp" #include "Appl.hpp" #include "Thing.hpp" #include "ConstVal.hpp" #include "SndSys.hpp" extern CSystem *gSystem; extern CApplication *gApplication; extern tConstValues *gConst; extern CLevel *gLevel; extern CSoundSystem *gSoundSystem; short *FindDescriptor(short id); CWeapon::CWeapon(CThing *own, tWeaponInfo *weaponInfo, CShape *attack) { owner = own; info = weaponInfo; attackShape = attack; lastShoot = 0; lastShootFrame = 0; // by LL weaponStatus = kWeaponDoesntExist; munition = 0; repetition = (owner->typeID & kPlayer) ? info->repetition : info->repetition * gApplication->currentWeaponSF; } CWeapon::~CWeapon() {} void CWeapon::AddMunition(short mun) { munition += mun; munition = MIN(munition, info->munition); if (weaponStatus == kWeaponOutOfMunition) weaponStatus = kWeaponReady; } short CWeapon::Shoot(double directionx, double directiony, double targetpos) { CBullet *temp; short *descr; if (weaponStatus == kWeaponReady && lastShoot <= gSystem->GetTicks()) { gSoundSystem->Play(gSoundSystem->weaponLaunchSounds[weaponNumber], owner->xm, owner->ym); lastShoot = gSystem->GetTicks() + repetition; lastShootFrame = gSystem->GetTicks() + gConst->kShootFrameTime; descr = FindDescriptor(info->projectileShapes[0]); temp = new CBullet((owner->lookDirection == kLookingRight ? owner->xe - descr[3] / 2 - kWeaponBodyOffset : owner->xs + kWeaponBodyOffset + descr[3] / 2), owner->ye - gConst->kWeaponCarryHeight, descr[3], descr[4], weaponNumber, info, directionx, directiony, owner, targetpos); munition --; if (!munition) weaponStatus = kWeaponOutOfMunition; return 1; }else return 0; } short CWeapon::ShootAnimation(CShape **currentShape) { if (owner->lastTime < lastShootFrame) { *currentShape = attackShape; return 0; }else return 1; } void CWeapon::SaveDataToNextLevel(short *mun, short *stat) { *mun = munition; *stat = weaponStatus; } void CWeapon::RestoreDataFromPrevLevel(short mun, short stat) { munition = mun; weaponStatus = stat; } CHandWeapon::CHandWeapon(CThing *own, tWeaponInfo *weaponInfo, CShape *attack1, CShape *attack2, CShape *attack3) : CWeapon(own, weaponInfo, attack1) { numAnimFrames = 1; attackShape2 = attack2; if (attackShape2) numAnimFrames = 2; attackShape3 = attack3; if (attackShape3) numAnimFrames = 3; animationFrame = 4; shootFrameTime = gConst->kShootFrameTime * (4 - numAnimFrames); } CHandWeapon::~CHandWeapon() {} short CHandWeapon::Shoot(double directionx, double unused, double unused2) { if (weaponStatus == kWeaponReady && lastShoot <= gSystem->GetTicks()) { gSoundSystem->Play(gSoundSystem->weaponLaunchSounds[weaponNumber], owner->xm, owner->ym); lastShoot = gSystem->GetTicks() + repetition; lastShootFrame = gSystem->GetTicks() + gConst->kShootFrameTime; animationFrame = 0; return 1; }else return 0; } short CHandWeapon::ShootAnimation(CShape **currentShape) { if (animationFrame < numAnimFrames) { switch (animationFrame) { case 0: *currentShape = attackShape; break; case 1: *currentShape = attackShape2; break; case 2: *currentShape = attackShape3; break; } if (owner->lastTime > lastShootFrame) { animationFrame ++; lastShootFrame = owner->lastTime + shootFrameTime; } return 0; }else if (animationFrame == numAnimFrames) { tThingList *currentEntry = gApplication->collisionThingList; while (currentEntry) { if (currentEntry->thing != owner) currentEntry->thing->TestForDamage(owner->lookDirection == kLookingRight ? owner->xe : owner->xs, owner->ye - gConst->kWeaponCarryHeight, info->rad, info->damage); currentEntry = currentEntry->next; } animationFrame = SHRT_MAX; } return 1; } CSorcery::CSorcery(CThing *own, tWeaponInfo *weaponInfo, CShape *attack) : CWeapon(own, weaponInfo, attack) {} CSorcery::~CSorcery() {} short CSorcery::Shoot(double directionx, double directiony, double unused) { CBullet *temp; short *descr; if (weaponStatus == kWeaponReady && lastShoot <= gSystem->GetTicks()) { gSoundSystem->Play(gSoundSystem->weaponLaunchSounds[weaponNumber], owner->xm, owner->ym); lastShoot = gSystem->GetTicks() + repetition; lastShootFrame = gSystem->GetTicks() + gConst->kShootFrameTime; descr = FindDescriptor(info->projectileShapes[0]); temp = new CSorceryBullet((owner->lookDirection == kLookingRight ? owner->xe - descr[3] / 2 - kWeaponBodyOffset : owner->xs + kWeaponBodyOffset + descr[3] / 2), owner->ye - gConst->kWeaponCarryHeight, descr[3], descr[4], weaponNumber, info, directionx, ABS(directionx), owner, 0); munition --; if (!munition) weaponStatus = kWeaponOutOfMunition; return 1; }else return 0; } CBomb::CBomb(CThing *own, tWeaponInfo *weaponInfo, CShape *attack, CShape *det) : CWeapon(own, weaponInfo, attack) { status = kReady; detonator = det; } CBomb::~CBomb() {} short CBomb::Shoot(double directionx, double directiony, double unused) { CBombBullet *temp; short *descr; if (weaponStatus == kWeaponReady && lastShoot <= gSystem->GetTicks()) { lastShoot = gSystem->GetTicks() + repetition; lastShootFrame = gSystem->GetTicks() + gConst->kShootFrameTime; if (status == kReady) { gSoundSystem->Play(gSoundSystem->weaponLaunchSounds[weaponNumber], owner->xm, owner->ym); status = kDetonation; descr = FindDescriptor(info->projectileShapes[0]); temp = new CBombBullet((owner->lookDirection == kLookingRight ? owner->xe - descr[3] / 2 - kWeaponBodyOffset : owner->xs + kWeaponBodyOffset + descr[3] / 2), owner->ye - gConst->kWeaponCarryHeight, descr[3], descr[4], weaponNumber, info, directionx, directiony, owner, 0); bomb = temp; munition --; }else{ gSoundSystem->Play(gSoundSystem->weaponHitSounds[weaponNumber], bomb->xm, bomb->ym); if (bomb) ((CBombBullet *)bomb)->detonate = 1; bomb = 0L; status = kReady; if (!munition) weaponStatus = kWeaponOutOfMunition; } return 1; }else return 0; } short CBomb::ShootAnimation(CShape **currentShape) { if (status == kDetonation) *currentShape = detonator; if (owner->lastTime < lastShootFrame && status == kDetonation) *currentShape = attackShape; return 1; } CMultiBulletWeapon::CMultiBulletWeapon(CThing *own, tWeaponInfo *weaponInfo, CShape *attack, double angle) : CWeapon(own, weaponInfo, attack) { numOfBullets = weaponInfo->error; alpha = angle; initAlpha = (double)(numOfBullets - 1) / 2.0 * alpha; } CMultiBulletWeapon::~CMultiBulletWeapon() {} short CMultiBulletWeapon::Shoot(double directionx, double directiony, double targetpos) { CBullet *temp; short *descr; double dx, dy, tmp; if (weaponStatus == kWeaponReady && lastShoot <= gSystem->GetTicks()) { gSoundSystem->Play(gSoundSystem->weaponLaunchSounds[weaponNumber], owner->xm, owner->ym); lastShoot = gSystem->GetTicks() + repetition; lastShootFrame = gSystem->GetTicks() + gConst->kShootFrameTime; descr = FindDescriptor(info->projectileShapes[0]); dx = directionx * cos(initAlpha) - directiony * sin(initAlpha); dy = directionx * sin(initAlpha) + directiony * cos(initAlpha); for (short n = 0; n < numOfBullets && weaponStatus == kWeaponReady; n ++) { temp = new CBullet((owner->lookDirection == kLookingRight ? owner->xe - descr[3] / 2 - kWeaponBodyOffset : owner->xs + kWeaponBodyOffset + descr[3] / 2), owner->ye - gConst->kWeaponCarryHeight, descr[3], descr[4], weaponNumber, info, dx, dy, owner, targetpos); munition --; if (!munition) weaponStatus = kWeaponOutOfMunition; tmp = dx * cos(alpha) + dy * sin(alpha); dy = -dx * sin(alpha) + dy * cos(alpha); dx = tmp; } return 1; }else return 0; } CStaff::CStaff(CThing *own, tWeaponInfo *weaponInfo, CShape *attack, CShape *load) : CWeapon(own, weaponInfo, attack) { loaded = load; inLoad = 0; lastLoad = 0; } CStaff::~CStaff() {} short CStaff::Shoot(double directionx, double directiony, double targetpos) { long time = gSystem->GetTicks(); dx = directionx; dy = directiony; if (time - lastLoad < 100) { lastLoad = time; if (time - staffLoadTime >= gConst->kStaffLoadTime) inLoad = 1; }else if (lastShoot <= time && weaponStatus == kWeaponReady) { lastLoad = time; staffLoadTime = time; } return 0; } short CStaff::ShootAnimation(CShape **currentShape) { long time = gSystem->GetTicks(); if (time - lastLoad < 100) { // Weapon is in load if (time - staffLoadTime < gConst->kStaffLoadTime) *currentShape = attackShape; else *currentShape = loaded; return 0; }else if (inLoad) { // Weapon is released CBullet *temp; short *descr; gSoundSystem->Play(gSoundSystem->weaponLaunchSounds[weaponNumber], owner->xm, owner->ym); lastShoot = gSystem->GetTicks() + repetition; lastShootFrame = gSystem->GetTicks() + gConst->kShootFrameTime; descr = FindDescriptor(info->projectileShapes[0]); temp = new CSineBullet((owner->lookDirection == kLookingRight ? owner->xe - descr[3] / 2 - kWeaponBodyOffset : owner->xs + kWeaponBodyOffset + descr[3] / 2), owner->ye - gConst->kWeaponCarryHeight, descr[3], descr[4], weaponNumber, info, dx, 0, owner, 0, gConst->kSineWeaponRad, info->error); munition --; if (!munition) weaponStatus = kWeaponOutOfMunition; inLoad = 0; } if (time < lastShootFrame) { *currentShape = loaded; return 0; } return 1; } CSineWeapon::CSineWeapon(CThing *own, tWeaponInfo *weaponInfo, CShape *attack, short rad) : CWeapon(own, weaponInfo, attack) { radius = rad; } CSineWeapon::~CSineWeapon() {} short CSineWeapon::Shoot(double directionx, double directiony, double targetpos) { CBullet *temp; short *descr; if (lastShoot <= gSystem->GetTicks()) { gSoundSystem->Play(gSoundSystem->weaponLaunchSounds[weaponNumber], owner->xm, owner->ym); lastShoot = gSystem->GetTicks() + repetition; lastShootFrame = gSystem->GetTicks() + gConst->kShootFrameTime; descr = FindDescriptor(info->projectileShapes[0]); temp = new CSineBullet((owner->lookDirection == kLookingRight ? owner->xe - descr[3] / 2 - kWeaponBodyOffset : owner->xs + kWeaponBodyOffset + descr[3] / 2), owner->ye - gConst->kWeaponCarryHeight, descr[3], descr[4], weaponNumber, info, directionx, directiony, owner, targetpos, radius, info->error); return 1; }else return 0; } CGuided::CGuided(CThing *own, tWeaponInfo *weaponInfo, CShape *attack) : CWeapon(own, weaponInfo, attack) { } CGuided::~CGuided() {} short CGuided::Shoot(double directionx, double directiony, double targetpos) { CBullet *temp; short *descr; if (lastShoot <= gSystem->GetTicks()) { gSoundSystem->Play(gSoundSystem->weaponLaunchSounds[weaponNumber], owner->xm, owner->ym); lastShoot = gSystem->GetTicks() + repetition; lastShootFrame = gSystem->GetTicks() + gConst->kShootFrameTime; descr = FindDescriptor(info->projectileShapes[0]); temp = new CGuidedBullet((owner->lookDirection == kLookingRight ? owner->xe - descr[3] / 2 - kWeaponBodyOffset : owner->xs + kWeaponBodyOffset + descr[3] / 2), owner->ye - gConst->kWeaponCarryHeight, descr[3], descr[4], weaponNumber, info, directionx, directiony, owner, targetpos, gLevel->player); return 1; }else return 0; } short CWeapon::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(munition); WRITEDATA(lastShoot); WRITEDATA(lastShootFrame); WRITEDATA(weaponStatus); WRITEDATA(repetition); FINISHWRITE; return size; } void CWeapon::Read(FILE *f) { long size = 0; READDATA(size); READDATA(munition); READDATA(lastShoot); READDATA(lastShootFrame); READDATA(weaponStatus); READDATA(repetition); } short CHandWeapon::Write(FILE *f) { long size = 0; WRITEDATA(size); size += CWeapon::Write(f); WRITEDATA(animationFrame); WRITEDATA(numAnimFrames); WRITEDATA(shootFrameTime); FINISHWRITE; return size; } void CHandWeapon::Read(FILE *f) { long size = 0; READDATA(size); CWeapon::Read(f); READDATA(animationFrame); READDATA(numAnimFrames); READDATA(shootFrameTime); } short CBomb::Write(FILE *f) { long size = 0; WRITEDATA(size); size += CWeapon::Write(f); WRITEDATA(status); FINISHWRITE; return size; } void CBomb::Read(FILE *f) { long size = 0; READDATA(size); CWeapon::Read(f); READDATA(status); } short CStaff::Write(FILE *f) { long size = 0; WRITEDATA(size); size += CWeapon::Write(f); WRITEDATA(staffLoadTime); WRITEDATA(lastLoad); WRITEDATA(inLoad); WRITEDATA(dx); WRITEDATA(dy); FINISHWRITE; return size; } void CStaff::Read(FILE *f) { long size = 0; READDATA(size); CWeapon::Read(f); READDATA(staffLoadTime); READDATA(lastLoad); READDATA(inLoad); READDATA(dx); READDATA(dy); }amphetamine-0.8.10/src/Weapon.hpp0100664000076400007640000000575607447375716015357 0ustar lukeluke#ifndef __AMP_WEAPON__ #define __AMP_WEAPON__ #include "ObjInfo.hpp" #include "Thing.hpp" #include "SoundList.hpp" const short kWeaponBodyOffset = 3; // At which direction of the body the shooted bullet is placed class CGUI; class CWeapon { friend class CGUI; protected: CThing *owner; tWeaponInfo *info; CShape *attackShape; short munition; long lastShoot, lastShootFrame; short repetition; CSound *launchSound, *hitSound; public: long ID; long savedID; short weaponStatus; short weaponNumber; CWeapon(CThing *own, tWeaponInfo *weaponInfo, CShape *attack); ~CWeapon(); void SetID(long); void AddMunition(short munition); virtual short Shoot(double directionx, double directiony, double targetpos); virtual short ShootAnimation(CShape **); void SaveDataToNextLevel(short *, short *); void RestoreDataFromPrevLevel(short, short); virtual short Write(FILE *f); virtual void Read(FILE *f); }; class CHandWeapon : public CWeapon { protected: CShape *attackShape2, *attackShape3; short animationFrame; short numAnimFrames; long shootFrameTime; public: CHandWeapon(CThing *own, tWeaponInfo *weaponInfo, CShape *attack1, CShape *attack2, CShape *attack3); ~CHandWeapon(); short Shoot(double directionx, double directiony, double targetpos); short ShootAnimation(CShape **); short Write(FILE *f); void Read(FILE *f); }; class CSorcery : public CWeapon { protected: public: CSorcery(CThing *own, tWeaponInfo *weaponInfo, CShape *attack); ~CSorcery(); short Shoot(double directionx, double directiony, double unused); }; enum { // stati kReady, kDetonation }; class CBomb : public CWeapon { protected: short status; CThing *bomb; CShape *detonator; public: CBomb(CThing *own, tWeaponInfo *info, CShape *attack, CShape *det); ~CBomb(); short Shoot(double directionx, double directiony, double unused); short ShootAnimation(CShape **); short Write(FILE *f); void Read(FILE *f); }; class CMultiBulletWeapon : public CWeapon { protected: short numOfBullets; double alpha, initAlpha; public: CMultiBulletWeapon(CThing *own, tWeaponInfo *info, CShape *attack, double angle); ~CMultiBulletWeapon(); short Shoot(double directionx, double directiony, double targetpos); }; class CStaff : public CWeapon { protected: long staffLoadTime; long lastLoad; short inLoad; CShape *loaded; double dx, dy; public: CStaff(CThing *own, tWeaponInfo *info, CShape *attack, CShape *load); ~CStaff(); short Shoot(double directionx, double directiony, double unused); short ShootAnimation(CShape **); short Write(FILE *f); void Read(FILE *f); }; class CSineWeapon : public CWeapon { protected: short radius; public: CSineWeapon(CThing *own, tWeaponInfo *info, CShape *attack, short rad); ~CSineWeapon(); short Shoot(double directionx, double directiony, double targetpos); }; class CGuided : public CWeapon { public: CGuided(CThing *own, tWeaponInfo *info, CShape *attack); ~CGuided(); short Shoot(double directionx, double directiony, double targetpos); }; #endifamphetamine-0.8.10/src/Pltform.cpp0100664000076400007640000001631207447311405015513 0ustar lukeluke#include "Pltform.hpp" #include "Appl.hpp" #include "Player.hpp" #include "ConstVal.hpp" #include "SndSys.hpp" extern CApplication *gApplication; extern CShapeManager *gShapeManager; extern tConstValues *gConst; extern CLevel *gLevel; extern CSoundSystem *gSoundSystem; const short kPlatformCollisionHeight = 30; CPlatform::CPlatform(short initx, short inity, short width, short height, short number, tPlatformInfo *platformInfo) : CThing(initx, inity, width, height, number) { typeID |= kPlatform; LinkInLists(); if (platformInfo) { info = platformInfo; isLocal = 0; weight = SHRT_MAX; background = 0; origHeight = dy; ys = ym - kPlatformCollisionHeight / 2; ye = ym + kPlatformCollisionHeight / 2; dy = kPlatformCollisionHeight; dx -= 1; ye -= 1; OnAllocate(); startx = info->startx * kElementSize; starty = info->starty * kElementSize + (kElementSize - kPlatformCollisionHeight) / 2; endx = info->endx * kElementSize; endy = info->endy * kElementSize + (kElementSize - kPlatformCollisionHeight) / 2; maxDistance = sqrt((endx - startx) * (endx - startx) + (endy - starty) * (endy - starty)); if (info->activ) action = kRunsStartToEnd; else action = kStopsAtStart; }else info = 0L; } void CPlatform::OnAllocate() { shape = gShapeManager->FindShape(info->iconID, 0); } CPlatform::~CPlatform() { if (isLocal) delete info; } void CPlatform::LinkInLists() { gApplication->Enqueue(&gApplication->thingList, this); gApplication->Enqueue(&gApplication->collisionThingList, this); gApplication->Enqueue(&gApplication->renderQueue, this); } void CPlatform::UnlinkInLists() { gApplication->Dequeue(&gApplication->thingList, this); gApplication->Dequeue(&gApplication->collisionThingList, this); gApplication->Dequeue(&gApplication->renderQueue, this); } short CPlatform::Think() { double speedVector, distance; CObject::Think(); switch (action) { case kRunsStartToEnd: distance = sqrt((xs - startx) * (xs - startx) + (ys - starty) * (ys - starty)); if (distance >= maxDistance) { if (info->stopsAtEnd) action = kStopsAtEnd; else action = kDelaysAtEnd; xs = endx; ys = endy; xe = xs + kElementSize -1; ye = ys + kElementSize -1; delayTime = lastTime; gSoundSystem->Play(gSoundSystem->platformStop, xm, ym); }else{ speedVector = info->speed * gConst->kVelocityUnit * deltaTime; forceVectorX = (endx - startx) * speedVector / maxDistance; forceVectorY = (endy - starty) * speedVector / maxDistance; } break; case kRunsEndToStart: distance = sqrt((xs - endx) * (xs - endx) + (ys - endy) * (ys - endy)); if (distance >= maxDistance) { if (info->stopsAtStart) action = kStopsAtStart; else action = kDelaysAtStart; xs = startx; ys = starty; xe = xs + kElementSize -1; ye = ys + kElementSize -1; delayTime = lastTime; gSoundSystem->Play(gSoundSystem->platformStop, xm, ym); }else{ speedVector = info->speed * gConst->kVelocityUnit * deltaTime; forceVectorX = (startx - endx) * speedVector / maxDistance; forceVectorY = (starty - endy) * speedVector / maxDistance; } break; case kDelaysAtStart: if (lastTime - delayTime > info->delay * kTimeFactor) { action = kRunsStartToEnd; gSoundSystem->Play(gSoundSystem->platformGo, xm, ym); } forceVectorX = forceVectorY = 0; break; case kDelaysAtEnd: if (lastTime - delayTime > info->delay * kTimeFactor) { action = kRunsEndToStart; gSoundSystem->Play(gSoundSystem->platformGo, xm, ym); } forceVectorX = forceVectorY = 0; break; case kStopsAtStart: case kStopsAtEnd: forceVectorX = forceVectorY = 0; break; } return kNoEvent; } short CPlatform::Forces() { short collisionObject, collisionCode; CObject *collObj; CObject::Forces(); double oldfx = resForceX, oldfy = resForceY; collisionCode = ExertForce(resForceX, resForceY, collisionObject, &collObj); if (!(collisionCode & kCollisionWithPushing)) { if (collisionObject & (kElement | kItem | kPlatform)) { // Platforms can go through level elements resForceX = oldfx; resForceY = oldfy; } }else if (collisionCode & ~kCollisionWithPushing) { action = (action == kRunsStartToEnd ? kRunsEndToStart : kRunsStartToEnd); if (info->returnsOnHit && collObj->typeID & kThing) ((CThing *)collObj)->OnDamage(info->returnsOnHit); } return kNoEvent; } void CPlatform::Render(short planeX, short planeY, tRect *clipRect) { CElement *element = gLevel->GetElement(xm, ym); if (shape) shape->RenderShape(xs - planeX, ym - planeY - origHeight / 2, clipRect, modus, element ? element->brightness : 0, gApplication->plane); } short CPlatform::Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject) { if (right + 2 < xs || left - 2 > xe || bottom + 2 < ys || top - 2 > ye) return kNoCollision; short returnValue; if ((returnValue = CObject::Collision(sender, left, top, right, bottom, forcex, forcey, pfx, pfy, sourceWeight, collisionObject)) & kCollisionOnBottom) { sender->CollisionEvent(gConst->kNormalFriction, 0); if (info->hurts) ((CThing *)sender)->OnDamage(info->hurts); if ((sender->typeID & kPlayer) && info->playerControls) { if (action == kStopsAtStart) { action = kRunsStartToEnd; gSoundSystem->Play(gSoundSystem->platformGo, xm, ym); } if (action == kStopsAtEnd) { action = kRunsEndToStart; gSoundSystem->Play(gSoundSystem->platformGo, xm, ym); } } } return returnValue; } void CPlatform::OnTouch(CObject *touch) { if ((touch->typeID & kThing) && info->hurts) ((CThing *)touch)->OnDamage(info->hurts); } void CPlatform::Switch() { switch (action) { case kRunsStartToEnd: case kDelaysAtStart: action = kStopsAtStart; gSoundSystem->Play(gSoundSystem->platformStop, xm, ym); break; case kRunsEndToStart: case kDelaysAtEnd: action = kStopsAtEnd; gSoundSystem->Play(gSoundSystem->platformStop, xm, ym); break; case kStopsAtStart: action = kRunsStartToEnd; gSoundSystem->Play(gSoundSystem->platformGo, xm, ym); if (info->refNum > 0) gApplication->platformTable[info->refNum]->Switch(); break; case kStopsAtEnd: action = kRunsEndToStart; gSoundSystem->Play(gSoundSystem->platformGo, xm, ym); if (info->refNum > 0) gApplication->platformTable[info->refNum]->Switch(); break; } } CShape *CPlatform::GetCurrentState(CShape *active, CShape *inactive) { if (action == kStopsAtStart || action == kStopsAtEnd) return inactive; else return active; } short CPlatform::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(typeID); WRITEDATA(thingNumber); size += CThing::Write(f); WRITEDATA(origHeight); WRITEDATA(action); WRITEDATA(startx); WRITEDATA(starty); WRITEDATA(endx); WRITEDATA(endy); WRITEDATA(maxDistance); WRITEDATA(delayTime); fwrite(info, sizeof(tPlatformInfo), 1, f); size += sizeof(tPlatformInfo); FINISHWRITE; return size; } void CPlatform::Read(FILE *f) { long size = 0; READDATA(size); READDATA(typeID); READDATA(thingNumber); CThing::Read(f); READDATA(origHeight); READDATA(action); READDATA(startx); READDATA(starty); READDATA(endx); READDATA(endy); READDATA(maxDistance); READDATA(delayTime); isLocal = 1; info = new tPlatformInfo; fread(info, sizeof(tPlatformInfo), 1, f); OnAllocate(); }amphetamine-0.8.10/src/Pltform.hpp0100664000076400007640000000243207447323020015512 0ustar lukeluke#ifndef __AMP_PLATTFORMS__ #define __AMP_PLATTFORMS__ #include "Thing.hpp" #include "ObjInfo.hpp" enum { kRunsStartToEnd = 0, kRunsEndToStart, kDelaysAtStart, kDelaysAtEnd, kStopsAtStart, // Platform stopped at start or while running start -> end kStopsAtEnd // Platform stopped at end or while running end -> start }; const short kTimeFactor = 100; class CPlatform : public CThing { protected: tPlatformInfo *info; short isLocal; // whether info is allocated by the platform itself (after loading) or by ObjInfo CShape *shape; short origHeight; short action; double startx, starty; double endx, endy; double maxDistance; long delayTime; public: CPlatform(short initx, short inity, short width, short height, short number, tPlatformInfo *platformInfo); ~CPlatform(); void OnAllocate(); void LinkInLists(); void UnlinkInLists(); short Think(); short Forces(); void Render(short planeX, short planeY, tRect *clipRect); short Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject); void Switch(); CShape *GetCurrentState(CShape *active, CShape *inactive); void OnTouch(CObject *touch); short Write(FILE *f); void Read(FILE *f); }; #endif amphetamine-0.8.10/src/Gifload.cpp0100664000076400007640000003172407447311405015441 0ustar lukeluke /* * xgifload.c - based strongly on... * * gif2ras.c - Converts from a Compuserve GIF (tm) image to a Sun Raster image. * * Copyright (c) 1988, 1989 by Patrick J. Naughton * * Author: Patrick J. Naughton * naughton@wind.sun.com * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * * */ #include #include #include //#include "wt.h" //#include "gApplication->system->Error.h" //#include "wtmem.h" #include "Graphfil.hpp" #include "Appl.hpp" extern CApplication *gApplication; extern CSystem *gSystem; #define mfputc fputc #define mfgetc fgetc #define mfopen fopen #define mfclose fclose #define mfread fread #define mfseek fseek #define mftell ftell #define mrewind rewind #define mfprintf fprintf /* malloc or die . . . */ void *wtmalloc(size_t size) { void *news; if ((news = malloc(size)) == NULL) gSystem->Error("could not allocate %x bytes", size); return news; } /* realloc or die . . . */ void *wtrealloc(void *v, size_t size) { void *news; if ((news = realloc(v, size)) == NULL) gSystem->Error("could not reallocate %x bytes", size); return news; } void wtfree(void *v) { if (v == NULL) gSystem->Error("wtfree(NULL)", 0); else free(v); } typedef int gBOOLean; typedef unsigned char byte; #define NEXTBYTE (*ptr++) #define IMAGESEP 0x2c #define GRAPHIC_EXT 0xf9 #define PLAINTEXT_EXT 0x01 #define APPLICATION_EXT 0xff #define COMMENT_EXT 0xfe #define START_EXTENSION 0x21 #define INTERLACEMASK 0x40 #define COLORMAPMASK 0x80 int BitOffset = 0, /* Bit Offset of next code */ XC = 0, YC = 0, /* Output X and Y coords of current pixel */ Pass = 0, /* Used by output routine if interlaced pic */ OutCount = 0, /* Decompressor output 'stack count' */ RWidth, RHeight, /* screen dimensions */ Width, Height, /* image dimensions */ LeftOfs, TopOfs, /* image offset */ BitsPerPixel, /* Bits per pixel, read from GIF header */ BytesPerScanline, /* bytes per scanline in output raster */ ColorMapSize, /* number of colors */ Background, /* background color */ CodeSize, /* Code size, read from GIF header */ InitCodeSize, /* Starting code size, used during Clear */ Code, /* Value returned by ReadCode */ MaxCode, /* limiting value for current code size */ ClearCode, /* GIF clear code */ EOFCode, /* GIF end-of-information code */ CurCode, OldCode, InCode, /* Decompressor variables */ FirstFree, /* First free code, generated per GIF spec */ FreeCode, /* Decompressor, next free slot in hash table*/ FinChar, /* Decompressor variable */ BitMask, /* AND mask for data size */ ReadMask; /* Code AND mask for current code size */ gBOOLean Interlace, HasColormap; gBOOLean Verbose = 0; byte *Image; /* The result array */ byte *RawGIF; /* The heap array to hold it, raw */ byte *Raster; /* The raster data stream, unblocked */ /* The hash table used by the decompressor */ short Prefix[4096]; short Suffix[4096]; /* An output array used by the decompressor */ int OutCode[1025]; /* The color map, read from the GIF header */ byte Red[256], Green[256], Blue[256], used[256]; int numused; char *id87 = "GIF87a"; char *id89 = "GIF89a"; int ReadCode( void ); int log2( int ); void AddToPixel( byte ); Graphic_file *LoadGIF(FILE *fp, char *fname ) { Graphic_file *gfile; int filesize, numcols; register unsigned char ch, ch1; register byte *ptr, *ptr1; register int i; short transparency = -1; BitOffset = 0; XC = YC = 0; Pass = 0; OutCount = 0; /* find the size of the file */ mfseek(fp, 0L, 2); filesize = mftell(fp); mfseek(fp, 0L, 0); if (!(ptr = RawGIF = (byte *) malloc(filesize))) gSystem->Error("not enough memory to read gif file",0); if (!(Raster = (byte *) malloc(filesize))) { free( ptr ); gSystem->Error("not enough memory to read gif file",0); } if (mfread(ptr, filesize, 1, fp) != 1) gSystem->Error("GIF data read failed",0); if (strncmp((char *) ptr, id87, 6)) if (strncmp((char *) ptr, id89, 6)) gSystem->Error("not a GIF file",0); ptr += 6; /* Get variables from the GIF screen descriptor */ ch = NEXTBYTE; RWidth = ch + 0x100 * NEXTBYTE; /* screen dimensions... not used. */ ch = NEXTBYTE; RHeight = ch + 0x100 * NEXTBYTE; if (Verbose) mfprintf(stderr, "screen dims: %dx%d.\n", RWidth, RHeight); ch = NEXTBYTE; HasColormap = ((ch & COLORMAPMASK) ? 1 : 0); BitsPerPixel = (ch & 7) + 1; numcols = ColorMapSize = 1 << BitsPerPixel; BitMask = ColorMapSize - 1; Background = NEXTBYTE; /* background color... not used. */ if (NEXTBYTE) /* supposed to be NULL */ gSystem->Error("corrupt GIF file (bad screen descriptor)",0); /* Read in global colormap. */ if (HasColormap) { if (Verbose) mfprintf(stderr, "%s is %dx%d, %d bits per pixel, (%d colors).\n", fname, RWidth,RHeight,BitsPerPixel, ColorMapSize); for (i = 0; i < ColorMapSize; i++) { Red[i] = NEXTBYTE; Green[i] = NEXTBYTE; Blue[i] = NEXTBYTE; used[i] = 0; } numused = 0; } /* else no colormap in GIF file */ /* look for image separator */ for (ch = NEXTBYTE ; ch != IMAGESEP ; ch = NEXTBYTE) { i = ch; mfprintf(stderr, "EXTENSION CHARACTER: %x\n", i); if (ch != START_EXTENSION) gSystem->Error("corrupt GIF89a file",0); /* handle image extensions */ switch (ch = NEXTBYTE) { case GRAPHIC_EXT: ch = NEXTBYTE; if (ptr[0] & 0x1) { transparency = ptr[3]; /* transparent color index */ mfprintf(stderr, "transparency index: %i\n", transparency); } ptr += ch; break; case PLAINTEXT_EXT: break; case APPLICATION_EXT: break; case COMMENT_EXT: break; default: gSystem->Error("invalid GIF89 extension",0); } while ((ch = NEXTBYTE)) ptr += ch; } /* Now read in values from the image descriptor */ ch = NEXTBYTE; LeftOfs = ch + 0x100 * NEXTBYTE; ch = NEXTBYTE; TopOfs = ch + 0x100 * NEXTBYTE; ch = NEXTBYTE; Width = ch + 0x100 * NEXTBYTE; ch = NEXTBYTE; Height = ch + 0x100 * NEXTBYTE; Interlace = ((NEXTBYTE & INTERLACEMASK) ? 1 : 0); if (Verbose) mfprintf(stderr, "Reading a %d by %d %sinterlaced image...", Width, Height, (Interlace) ? "" : "non-"); gfile = new_graphic_file(); gfile->palette = (RGBcolor *)wtmalloc(sizeof(RGBcolor) * ColorMapSize); for (i = 0; i < ColorMapSize; i++) { gfile->palette[i].red = Red[i]; gfile->palette[i].green = Green[i]; gfile->palette[i].blue = Blue[i]; } gfile->bitmap = (unsigned char *)wtmalloc(Width * Height); gfile->type = gfPaletted; gfile->width = Width; gfile->height = Height; gfile->transparent_entry = transparency; /* Note that I ignore the possible existence of a local color map. * I'm told there aren't many files around that use them, and the spec * says it's defined for future use. This could lead to an gApplication->system->Error * reading some files. */ /* Start reading the raster data. First we get the intial code size * and compute decompressor constant values, based on this code size. */ CodeSize = NEXTBYTE; ClearCode = (1 << CodeSize); EOFCode = ClearCode + 1; FreeCode = FirstFree = ClearCode + 2; /* The GIF spec has it that the code size is the code size used to * compute the above values is the code size given in the file, but the * code size used in compression/decompression is the code size given in * the file plus one. (thus the ++). */ CodeSize++; InitCodeSize = CodeSize; MaxCode = (1 << CodeSize); ReadMask = MaxCode - 1; /* Read the raster data. Here we just transpose it from the GIF array * to the Raster array, turning it from a series of blocks into one long * data stream, which makes life much easier for ReadCode(). */ ptr1 = Raster; do { ch = ch1 = NEXTBYTE; while (ch--) *ptr1++ = NEXTBYTE; if ((ptr1 - Raster) > filesize) gSystem->Error("corrupt GIF file (unblock)",0); } while(ch1); free(RawGIF); /* We're done with the raw data now... */ if (Verbose) { mfprintf(stderr, "done.\n"); mfprintf(stderr, "Decompressing..."); } Image = gfile->bitmap; BytesPerScanline = Width; /* Decompress the file, continuing until you see the GIF EOF code. * One obvious enhancement is to add checking for corrupt files here. */ Code = ReadCode(); while (Code != EOFCode) { /* Clear code sets everything back to its initial value, then reads the * immediately subsequent code as uncompressed data. */ if (Code == ClearCode) { CodeSize = InitCodeSize; MaxCode = (1 << CodeSize); ReadMask = MaxCode - 1; FreeCode = FirstFree; CurCode = OldCode = Code = ReadCode(); FinChar = CurCode & BitMask; AddToPixel(FinChar); } else { /* If not a clear code, then must be data: save same as CurCode and InCode */ CurCode = InCode = Code; /* If greater or equal to FreeCode, not in the hash table yet; * repeat the last character decoded */ if (CurCode >= FreeCode) { CurCode = OldCode; OutCode[OutCount++] = FinChar; } /* Unless this code is raw data, pursue the chain pointed to by CurCode * through the hash table to its end; each code in the chain puts its * associated output code on the output queue. */ while (CurCode > BitMask) { if (OutCount > 1024) { gSystem->Error("Corrupt GIF file (OutCount)!", 0); // mfprintf(stderr,"\nCorrupt GIF file (OutCount)!\n"); // _exit(-1); /* calling 'exit(-1)' dumps core, so I don't */ } OutCode[OutCount++] = Suffix[CurCode]; CurCode = Prefix[CurCode]; } /* The last code in the chain is treated as raw data. */ FinChar = CurCode & BitMask; OutCode[OutCount++] = FinChar; /* Now we put the data out to the Output routine. * It's been stacked LIFO, so deal with it that way... */ for (i = OutCount - 1; i >= 0; i--) AddToPixel(OutCode[i]); OutCount = 0; /* Build the hash table on-the-fly. No table is stored in the file. */ Prefix[FreeCode] = OldCode; Suffix[FreeCode] = FinChar; OldCode = InCode; /* Point to the next slot in the table. If we exceed the current * MaxCode value, increment the code size unless it's already 12. If it * is, do nothing: the next code decompressed better be CLEAR */ FreeCode++; if (FreeCode >= MaxCode) { if (CodeSize < 12) { CodeSize++; MaxCode *= 2; ReadMask = (1 << CodeSize) - 1; } } } Code = ReadCode(); } free(Raster); if (Verbose) mfprintf(stderr, "done.\n"); //else //mfprintf(stderr,"(of which %d are used)\n",numused); return gfile; } /* Fetch the next code from the raster data stream. The codes can be * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to * maintain our location in the Raster array as a BIT Offset. We compute * the byte Offset into the raster array by dividing this by 8, pick up * three bytes, compute the bit Offset into our 24-bit chunk, shift to * bring the desired code to the bottom, then mask it off and return it. */ int ReadCode( void ) { int RawCode, ByteOffset; ByteOffset = BitOffset / 8; RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]); if (CodeSize >= 8) RawCode += (0x10000 * Raster[ByteOffset + 2]); RawCode >>= (BitOffset % 8); BitOffset += CodeSize; return(RawCode & ReadMask); } void AddToPixel(byte Index) { if (YC= Height) { Pass++; YC = 4; } break; case 1: YC += 8; if (YC >= Height) { Pass++; YC = 2; } break; case 2: YC += 4; if (YC >= Height) { Pass++; YC = 1; } break; case 3: YC += 2; break; default: break; } } } } amphetamine-0.8.10/src/Element.cpp0100664000076400007640000002660407447311405015466 0ustar lukeluke#include "Element.hpp" #include "Appl.hpp" #include "Gui.hpp" #include "SndSys.hpp" extern CApplication *gApplication; extern CShapeManager *gShapeManager; extern CSystem *gSystem; extern tConstValues *gConst; extern CLevel *gLevel; extern CGUI *gGUI; extern CSoundSystem *gSoundSystem; CElement::CElement(short initx, short inity, short width, short height, tLevelElement *levelElement) : CObject(initx, inity, width, height) { typeID |= kElement; if (levelElement) { brightness = 3 - LOBYTE(levelElement->light); brightness2 = 3 - HIBYTE(levelElement->light); iconID = levelElement->iconID; bitData = levelElement->bitData; lastState = 0; refNum = LOBYTE(levelElement->refNum); key = HIBYTE(levelElement->refNum); data = HIBYTE(levelElement->kind); OnAllocate(); weight = SHRT_MAX; background = levelElement->kind; } } void CElement::OnAllocate() { if (iconID > 0) { shape = gShapeManager->FindShape(iconID, brightness); shape2 = gShapeManager->FindShape(iconID, brightness2); } // If there's something on that element, allocate the struct which holds the several shapes if (bitData & (kPlatformSwitchMask | kLightSwitchMask | kTeleportMask | kSaveMask | kExitMask | kPassiveLightMask | kPassivePlatformMask | kRightDriftMask | kLeftDriftMask | kInfotextMask)) { elementThings = new tElementThings; if (bitData & kPlatformSwitchMask) { elementThings->platformSwitchInactive = gShapeManager->FindShape(kPlatformSwitchInactiveID, 0); elementThings->platformSwitchActive = gShapeManager->FindShape(kPlatformSwitchActiveID, 0); elementThings->referencedPlatform = gApplication->platformTable[refNum]; }else{ elementThings->platformSwitchInactive = elementThings->platformSwitchActive = 0L; elementThings->referencedPlatform = 0L; } if (bitData & kPassivePlatformMask) { elementThings->referencedPlatform = gApplication->platformTable[refNum]; elementThings->passiveHasChanged = 0; } if (bitData & kLightSwitchMask) { elementThings->lightSwitch = gShapeManager->FindShape(kLightSwitchInactiveID, 0); elementThings->lightSwitch2 = gShapeManager->FindShape(kLightSwitchActiveID, 0); }else{ elementThings->lightSwitch = elementThings->lightSwitch2 = 0L; } if (bitData & kTeleportMask) { elementThings->teleporter = gShapeManager->FindShape(kTeleportStateOne, 0); elementThings->teleporter2 = gShapeManager->FindShape(kTeleportStateTwo, 0); }else{ elementThings->teleporter = elementThings->teleporter2 = 0L; } elementThings->teleportBlinkTime = 0; if (bitData & kSaveMask) { elementThings->savePort = gShapeManager->FindShape(kSavePortStateOne, 0); elementThings->savePort2 = gShapeManager->FindShape(kSavePortStateTwo, 0); }else{ elementThings->savePort = elementThings->savePort2 = 0L; } elementThings->savePortBlinkTime = 0; if (bitData & kExitMask) { elementThings->exitPort = gShapeManager->FindShape(kExitStateOne, 0); elementThings->exitPort2 = gShapeManager->FindShape(kExitStateTwo, 0); }else{ elementThings->exitPort = elementThings->exitPort2 = 0L; } elementThings->exitPortBlinkTime = 0; elementThings->passiveHasChanged = 0; elementThings->drift = 0L; if (bitData & kLeftDriftMask) elementThings->drift = gShapeManager->FindShape (kDriftLeftID, 0); if (bitData & kRightDriftMask) elementThings->drift = gShapeManager->FindShape(kDriftRightID, 0); if (bitData & kInfotextMask) { elementThings->infoPort = gShapeManager->FindShape(kInfotextStateOne, 0); elementThings->infoPort2 = gShapeManager->FindShape(kInfotextStateTwo, 0); }else{ elementThings->infoPort = elementThings->infoPort2 = 0L; } elementThings->infoPortBlinkTime = 0; }else elementThings = 0L; } CElement::~CElement() { if (elementThings) delete elementThings; } void CElement::LinkPlatforms() { if (elementThings) { if (bitData & kPlatformSwitchMask) { elementThings->referencedPlatform = gApplication->platformTable[refNum]; }else{ elementThings->referencedPlatform = 0L; } if (bitData & kPassivePlatformMask) { elementThings->referencedPlatform = gApplication->platformTable[refNum]; elementThings->passiveHasChanged = 0; } } } void CElement::PaintElementThings(short planeX, short planeY, tRect *clipRect) { CShape *tmp; if (bitData & kPlatformSwitchMask && elementThings->referencedPlatform) elementThings->referencedPlatform->GetCurrentState(elementThings->platformSwitchActive, elementThings->platformSwitchInactive)->RenderShape(xs - planeX, ys - planeY, clipRect, kShapemodusNormal, 0, gApplication->plane); if (elementThings->lightSwitch) elementThings->lightSwitch->RenderShape(xs - planeX, ys - planeY, clipRect, kShapemodusNormal, 0, gApplication->plane); if (elementThings->teleporter) { elementThings->teleporter->RenderShape(xs - planeX, ys - planeY, clipRect, kShapemodusNormal, 0, gApplication->plane); if (elementThings->teleportBlinkTime < gSystem->GetTicks()) { tmp = elementThings->teleporter; elementThings->teleporter = elementThings->teleporter2; elementThings->teleporter2 = tmp; elementThings->teleportBlinkTime = gSystem->GetTicks() + gConst->kTeleportBlinkTime; } } if (elementThings->savePort) { elementThings->savePort->RenderShape(xs - planeX, ys - planeY, clipRect, kShapemodusNormal, 0, gApplication->plane); if (elementThings->savePortBlinkTime < gSystem->GetTicks()) { tmp = elementThings->savePort; elementThings->savePort = elementThings->savePort2; elementThings->savePort2 = tmp; elementThings->savePortBlinkTime = gSystem->GetTicks() + gConst->kSavePortBlinkTime; } } if (elementThings->exitPort) { elementThings->exitPort->RenderShape(xs - planeX, ys - planeY, clipRect, kShapemodusNormal, 0, gApplication->plane); if (elementThings->exitPortBlinkTime < gSystem->GetTicks()) { tmp = elementThings->exitPort; elementThings->exitPort = elementThings->exitPort2; elementThings->exitPort2 = tmp; elementThings->exitPortBlinkTime = gSystem->GetTicks() + gConst->kExitPortBlinkTime; } } if (elementThings->drift) elementThings->drift->RenderShape(xs - planeX, ys - planeY, clipRect, kShapemodusNormal, 0, gApplication->plane); if (elementThings->infoPort) { elementThings->infoPort->RenderShape(xs - planeX, ys - planeY, clipRect, kShapemodusNormal, 0, gApplication->plane); if (elementThings->infoPortBlinkTime < gSystem->GetTicks()) { tmp = elementThings->infoPort; elementThings->infoPort = elementThings->infoPort2; elementThings->infoPort2 = tmp; elementThings->infoPortBlinkTime = gSystem->GetTicks() + gConst->kExitPortBlinkTime; } } } void CElement::PaintElement(short planeX, short planeY, tRect *clipRect) { long timeStamp; if (shape) shape->RenderShape(xs - planeX, ys - planeY, clipRect, 0, 0, gApplication->plane); if (bitData & kFlickeringMask) { timeStamp = (gApplication->syncTime / gConst->kFlickeringPeriod) & 1; if ((long)(timeStamp) != lastState) { SwapLights(); lastState = timeStamp; } } if (elementThings) PaintElementThings(planeX, planeY, clipRect); } short CElement::Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject) { short returnValue; double driftSpeed = 0; double friction = bitData & kIceMask ? 0 : gConst->kNormalFriction; if ((returnValue = CObject::Collision(sender, left, top, right, bottom, forcex, forcey, pfx, pfy, sourceWeight, collisionObject)) & kCollisionOnBottom) { if (bitData & kRightDriftMask) driftSpeed = gConst->kDriftSpeed; if (bitData & kLeftDriftMask) driftSpeed = -gConst->kDriftSpeed; sender->CollisionEvent(friction, driftSpeed); } return returnValue; } // ----------------------------------------- short CElement::Action() // Is called from CPlayer::Think, when the player performs an action on that element // Looks if there is some action possible, and do it { if (elementThings) { // is there any action possible? if(elementThings->referencedPlatform) { elementThings->referencedPlatform->Switch(); } if (bitData & kLightSwitchMask) { SWAP(elementThings->lightSwitch, elementThings->lightSwitch2, CShape *) gLevel->SwitchLight(refNum); } if (bitData & kSaveMask) gApplication->command = gGUI->RunUserInterface(kSaveGamePage); if (bitData & kInfotextMask) gGUI->DisplayInfotext(data); } return bitData; } void CElement::PassiveAction() { if (elementThings) { if ((bitData & kPassiveLightMask) && !elementThings->passiveHasChanged) { gLevel->SwitchLight(refNum); elementThings->passiveHasChanged = 1; } if ((bitData & kPassivePlatformMask) && !elementThings->passiveHasChanged && elementThings->referencedPlatform) { elementThings->referencedPlatform->Switch(); elementThings->passiveHasChanged = 1; } } } // -------------------------------- void CElement::SwapLights() // Swaps the light textures for that element { SWAP(shape, shape2, CShape *); SWAP(brightness, brightness2, short); } // -------------------------------- void CElement::Teleport(double &xp, double &yp) // Moves the coordinates to this element { if (background) { xp = xs; yp = ys; } } // --------------------------------------------- short CElement::GetElementLiquid() // Returns the liquid on this element, expressed by the shape drawing modus { if (bitData & kLavaMask) return kShapemodusLava; if (bitData & kWaterMask) return kShapemodusWater; if (bitData & kFogMask) return kShapemodusFog; return kShapemodusNormal; } CBackgroundElement::CBackgroundElement(short initx, short inity, short width, short height, tLevelElement *levelElement) : CElement(initx, inity, width, height, levelElement) { typeID |= kBackgroundElement; if (levelElement) OnAllocate(); brightness = 0; } void CBackgroundElement::OnAllocate() { short params[5] = {-1, xs, ys, xe - xs, ye - ys}; unsigned char *tmpBmp; tmpBmp = gShapeManager->GetBackground(params[1], params[2]); shape = new CBackground(tmpBmp, params, 0); } CBackgroundElement::~CBackgroundElement() { delete shape; } void CBackgroundElement::PaintElement(short planeX, short planeY, tRect *clipRect) { long timeStamp; if (shape) shape->RenderShape(xs - planeX, ys - planeY, clipRect, planeX * gConst->kBkgndScrollFactor, 0, gApplication->plane); if (elementThings) PaintElementThings(planeX, planeY, clipRect); } short CElement::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(typeID); size += CObject::Write(f); WRITEDATA(bitData); WRITEDATA(lastState); WRITEDATA(iconID); WRITEDATA(brightness); WRITEDATA(brightness2); WRITEDATA(key); WRITEDATA(refNum); WRITEDATA(data); WRITEDATA(elementThings); if (elementThings) { WRITEDATA(elementThings->teleportBlinkTime); WRITEDATA(elementThings->savePortBlinkTime); WRITEDATA(elementThings->exitPortBlinkTime); WRITEDATA(elementThings->passiveHasChanged); } FINISHWRITE; return size; } void CElement::Read(FILE *f) { long size = 0; long elemThings; READDATA(size); READDATA(typeID); CObject::Read(f); READDATA(bitData); READDATA(lastState); READDATA(iconID); READDATA(brightness); READDATA(brightness2); READDATA(key); READDATA(refNum); READDATA(data); OnAllocate(); READDATA(elemThings); if (elementThings) { READDATA(elementThings->teleportBlinkTime); READDATA(elementThings->savePortBlinkTime); READDATA(elementThings->exitPortBlinkTime); READDATA(elementThings->passiveHasChanged); } } void CBackgroundElement::Read(FILE *f) { CElement::Read(f); OnAllocate(); }amphetamine-0.8.10/src/Element.hpp0100664000076400007640000000451207447311405015465 0ustar lukeluke#ifndef __AMP_ELEMENT__ #define __AMP_ELEMENT__ #include "Object.hpp" #include "File.hpp" #include "Pltform.hpp" // Added by Luke #define LOBYTE(x) ((unsigned char)((x) & 0xff)) #define HIBYTE(x) ((unsigned char)((unsigned short)(x) >> 8)) enum { kPlatformSwitchInactiveID = 200, kPlatformSwitchActiveID = 201, kLightSwitchInactiveID = 208, kLightSwitchActiveID = 209, kInfotextStateOne = 210, kInfotextStateTwo = 211, kSavePortStateOne = 202, kSavePortStateTwo = 203, kExitStateOne = 204, kExitStateTwo = 205, kTeleportStateOne = 206, kTeleportStateTwo = 207, kDriftLeftID = 4015, kDriftRightID = 4016 }; struct tElementThings { CShape *lightSwitch; CShape *lightSwitch2; CShape *platformSwitchActive; CShape *platformSwitchInactive; CPlatform *referencedPlatform; CShape *drift; CShape *teleporter; CShape *teleporter2; long teleportBlinkTime; CShape *savePort; CShape *savePort2; long savePortBlinkTime; CShape *exitPort; CShape *exitPort2; long exitPortBlinkTime; CShape *infoPort; CShape *infoPort2; long infoPortBlinkTime; short passiveHasChanged; }; class CPlayer; class CElement : public CObject { friend class CPlayer; protected: CShape *shape; CShape *shape2; short bitData; short lastState; short iconID; tElementThings *elementThings; public: short brightness; short brightness2; short key; short refNum; short data; CElement(short initx, short inity, short width, short height, tLevelElement *element); ~CElement(); void OnAllocate(); void LinkPlatforms(); virtual void PaintElement(short planeLeft, short planeTop, tRect *clipRect); void PaintElementThings(short planeLeft, short planeTop, tRect *clipRect); virtual short Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject); short Action(); void PassiveAction(); void SwapLights(); void Teleport(double &xs, double &ys); short GetElementLiquid(); virtual short Write(FILE *f); virtual void Read(FILE *f); }; class CBackgroundElement : public CElement { public: CBackgroundElement(short initx, short inity, short width, short height, tLevelElement *element); ~CBackgroundElement(); void OnAllocate(); void PaintElement(short planeLeft, short planeTop, tRect *clipRect); void Read(FILE *f); }; #endif amphetamine-0.8.10/src/Surface.cpp0100664000076400007640000001411107447334611015457 0ustar lukeluke#include "Surface.hpp" #include "Shape.hpp" #include "ShapeLd.hpp" #include "Clut.hpp" #include "ConstVal.hpp" #include const short kNoCharSpace = 20; const char kNoCharChar = '_'; extern CSystem *gSystem; extern CShapeManager *gShapeManager; extern CClutManager *gClutManager; extern tConstValues *gConst; CGraphicSurface::CGraphicSurface(short dx, short dy) { buffer = gSystem->AllocateBuffer(dx, dy); gSystem->SetBufferPalette(buffer); width = dx; height = dy; numGraphics = 0; } CGraphicSurface::~CGraphicSurface() { for (short n = 0; n < numGraphics; n ++) { if (graphicTypes[n] == kGraphicEmbedded) free_graphic_file(graphics[n]); } gSystem->DisposeBuffer(buffer); } unsigned char *CGraphicSurface::GetSurfacePtr(short *pitch) { unsigned char *tmp = gSystem->GetBufferPtr(buffer, pitch); return tmp; } void CGraphicSurface::ReleaseSurface() { gSystem->ReleaseBufferPtr(buffer); } void CGraphicSurface::InsertGraphic(char *filename, Graphic_file *graphic, tRect *position) { if (filename) { graphics[numGraphics] = read_graphic_file(filename); SwapBlackWhite(graphics[numGraphics]); graphicsPositions[numGraphics].left = 0; graphicsPositions[numGraphics].top = 0; graphicsPositions[numGraphics].right = graphics[numGraphics]->width; graphicsPositions[numGraphics].bottom = graphics[numGraphics]->height; graphicTypes[numGraphics] = kGraphicEmbedded; numGraphics ++; } if (graphic && position) { graphics[numGraphics] = graphic; graphicsPositions[numGraphics].left = position->left; graphicsPositions[numGraphics].top = position->top; graphicsPositions[numGraphics].right = position->right; graphicsPositions[numGraphics].bottom = position->bottom; graphicTypes[numGraphics] = kGraphicReferenced; numGraphics ++; } } void CGraphicSurface::PaintGraphic(short num, short left, short top, short modus) { short j, k; short bottom, right; unsigned char *baseAddr, *linePtr, *sourcePtr, *sourceLinePtr; short pitch; baseAddr = gSystem->GetBufferPtr(buffer, &pitch); // Luke hat hier das -1 entfernt bottom = MIN(top + graphicsPositions[num].bottom - graphicsPositions[num].top, height); right = MIN(left + graphicsPositions[num].right - graphicsPositions[num].left, pitch); baseAddr += top * pitch + left; sourcePtr = graphics[num]->bitmap + graphicsPositions[num].top * graphics[num]->width + graphicsPositions[num].left; for (j = top; j < bottom; j ++) { k = right - left; sourceLinePtr = sourcePtr; linePtr = baseAddr; if (modus == kShapemodusNormal) { memcpy(linePtr, sourcePtr, k); } else { while (k) { gClutManager->SetPixel((unsigned char *)sourceLinePtr, (unsigned char *)linePtr, modus, 0); linePtr++; sourceLinePtr++; k--; } } baseAddr += pitch; sourcePtr += graphics[num]->width; } gSystem->ReleaseBufferPtr(buffer); } #define INT_TO_FIXED(i) ((i) << 16) #define FIXED_TO_INT(f) ((f) >> 16) #define FIXED_TO_FLOAT(f) (((double) (f)) * 1.52587890625e-5) #define FLOAT_TO_FIXED(f) ((long) ((f) * 65536.0)) void CGraphicSurface::DrawAntialiasedLine(short x1, short y1, short x2, short y2, unsigned char color, short modus) { unsigned char *baseAddr; short pitch; baseAddr = gSystem->GetBufferPtr(buffer, &pitch); x1 = MAX(0, x1); x1 = MIN(pitch, x1); x2 = MAX(0, x2); x2 = MIN(pitch, x2); y1 = MAX(0, y1); y1 = MIN(height -1, y1); y2 = MAX(0, y2); y2 = MIN(height -1, y2); short dx = x2 - x1, dy = y2 - y1, dmax; long ex, ey, curx = 0, cury = 0; long lastx, lasty; short counter; if (abs(dx) > abs(dy)) { ex = FLOAT_TO_FIXED(SIGN(dx) * 1.0); ey = FLOAT_TO_FIXED((double)dy / (double)abs(dx)); counter = SIGN(dx) * dx; }else{ ex = FLOAT_TO_FIXED((double)dx / (double)abs(dy)); ey = FLOAT_TO_FIXED(SIGN(dy) * 1.0); counter = SIGN(dy) * dy; } curx = INT_TO_FIXED(x1); cury = INT_TO_FIXED(y1); lastx = INT_TO_FIXED(x1); lasty = INT_TO_FIXED(y1); baseAddr += (FIXED_TO_INT(lasty) * pitch + FIXED_TO_INT(lastx)); while (counter) { gClutManager->SetPixel((unsigned char *)&color, baseAddr, modus, 0); curx += ex; cury += ey; counter --; if (lasty >> 16 != cury >> 16) { baseAddr += (SIGN(cury - lasty)) * pitch; lasty = cury; } if (lastx >> 16 != curx >> 16) { baseAddr += SIGN(curx - lastx); lastx = curx; } } gSystem->ReleaseBufferPtr(buffer); } void CGraphicSurface::PaintRect(short left, short top, short right, short bottom, unsigned char color, short modus) { short j, k; unsigned char *baseAddr; short pitch; baseAddr = gSystem->GetBufferPtr(buffer, &pitch); left = MAX(0, left); top = MAX(0, top); left = MIN(pitch, left); top = MIN(height, top); right = MAX(0, right); bottom = MAX(0, bottom); right = MIN(pitch, right); bottom = MIN(height, bottom); baseAddr += top * pitch; for (j = top; j < bottom; j ++) { for (k = left; k < right; k ++) { gClutManager->SetPixel((unsigned char *)&color, baseAddr + k, modus, 0); } baseAddr += pitch; } gSystem->ReleaseBufferPtr(buffer); } void CGraphicSurface::DrawString(short left, short top, char *text, short modus) { short n = 0, x, startWord, startShapePos; short shapePos = left; short dx, unused; CShape *shape; unsigned char *unused2; tRect clipRect; clipRect.left = clipRect.top = 0; clipRect.right = width; clipRect.bottom = height; while (text && text[n] != '\0') { startWord = n; startShapePos = shapePos; x = n; while (text[x] != kNoCharChar && text[x] != '\0') { shape = gShapeManager->FindShape((short)text[x], 0); if (shape) unused2 = shape->AllowPixelAccess(dx, unused); else dx = 0; shapePos += dx; x ++; } if (shapePos >= width) { top += gConst->kTextYDistance; shapePos = left; }else shapePos = startShapePos; x = startWord; while (text[x] != kNoCharChar && text[x] != '\0') { shape = gShapeManager->FindShape((short)text[x], 0); if (shape) shapePos += shape->RenderShape(shapePos, top, &clipRect, modus, 0, this); x ++; } if (text[x] == kNoCharChar) { shapePos += kNoCharSpace; x ++; } n = x; } } void CGraphicSurface::FlipToScreen(short left, short top) { gSystem->FlipSurfaces(buffer, width, height, left, top); } amphetamine-0.8.10/src/Surface.hpp0100664000076400007640000000207007447311405015461 0ustar lukeluke#ifndef __AMP_GRAPHSURFACE__ #define __AMP_GRAPHSURFACE__ #include "System.hpp" #include "Graphfil.hpp" const short kMaxGraphics = 32; const short kNumChars = 40; enum { kGraphicEmbedded, kGraphicReferenced }; // graphicType class CShape; class CGraphicSurface { protected: tGraphicBuffer *buffer; Graphic_file *graphics[kMaxGraphics]; short graphicTypes[kMaxGraphics]; short numGraphics; tRect graphicsPositions[kMaxGraphics]; public: short width, height; CGraphicSurface(short dx, short dy); ~CGraphicSurface(); void InsertGraphic(char *filename, Graphic_file *graphic, tRect *position); void PaintGraphic(short num, short left, short top, short modus); void DrawAntialiasedLine(short x1, short y1, short x2, short y2, unsigned char color, short modus); void PaintRect(short left, short top, short right, short bottom, unsigned char color, short modus); void DrawString(short left, short top, char *text, short modus); void FlipToScreen(short left, short top); unsigned char *GetSurfacePtr(short *pitch); void ReleaseSurface(); }; #endif amphetamine-0.8.10/src/SoundList.cpp0100664000076400007640000000344007447311405016012 0ustar lukeluke// SoundList.cpp: Implementierung der Klasse CSoundList. // ////////////////////////////////////////////////////////////////////// #include #include #include #include #include "SoundList.hpp" #include "System.hpp" extern CSystem *gSystem; ////////////////////////////////////////////////////////////////////// // Konstruktion/Destruktion ////////////////////////////////////////////////////////////////////// extern FILE *logFile; CSound::CSound(const char* wav) { if (wav) { // MSG("Loading "); // MSG(wav); if (!SDL_LoadWAV(gSystem->QualifyDataDir(wav),&specs, &data, &soundlen)) { // MSG(" failed"); } else { // MSG(" succeeded\n"); } state = 1; } Reset(); } void CSound::Reset() { playing = 0; } CSound::~CSound() { delete [] data; } void CSound::Play(SoundState *newstate) { newstate->sound=this; newstate->bytesleft=soundlen; newstate->volume=volume; newstate->soundpos=data; newstate->next=NULL; } bool CSound::isPlaying() { if (state) { return (bool)playing; }else return 0; } void CSound::SetVol(long vol) { volume=vol; } // -------------------------------------------------------- void CSoundList::Reset() { current = first; prev = first; } CSoundList::CSoundList() { first = new SoundState; first->sound=NULL; first->next=NULL; Reset(); } CSoundList::~CSoundList() { delete first; } SoundState *CSoundList::GetNext() { if (current) { prev = current; current = current->next; } return current; } void CSoundList::Insert(SoundState *s) { s->sound->playing ++; s->next=first->next; first->next=s; } void CSoundList::RemoveCurrent() { SoundState *tmp; tmp =current; if (current->sound) { current->sound->playing --; } prev->next = current->next; current = current->next; delete tmp; } amphetamine-0.8.10/src/SoundList.hpp0100664000076400007640000000171507447311405016022 0ustar lukeluke// SoundList.hpp: Schnittstelle für die Klasse CSoundList. // ////////////////////////////////////////////////////////////////////// #if !defined(_AMPH_SOUND_LIST_) #define _AMPH_SOUND_LIST_ extern "C" { #include #include #include } class CSound; struct SoundState { Uint8 *soundpos; Uint32 bytesleft; int volume; CSound *sound; SoundState *next; }; class CSound { private: short state; // 0 if sound doesn't exist, 1 if ok public: Uint8 *data; Uint32 soundlen, playing; int volume; SDL_AudioSpec specs; CSound(const char* wav); ~CSound(); void Play(SoundState *newstate); void Reset(); bool isPlaying(); void SetVol(long vol); }; class CSoundList { public: CSoundList(); ~CSoundList(); void Reset(); void Insert(SoundState *s); SoundState *GetNext(); void RemoveCurrent(); private: SoundState *first, *prev, *current; }; #endif amphetamine-0.8.10/src/Monstrxx.cpp0100664000076400007640000003056307447655502015747 0ustar lukeluke#include "Monstrxx.hpp" #include "Level.hpp" #include "ConstVal.hpp" #include "Appl.hpp" #include "System.hpp" extern CLevel *gLevel; extern tConstValues *gConst; extern CApplication *gApplication; extern CSystem *gSystem; /* ########################################### CREEPER CLASS EVENTS ############################################### */ CCreeper::CCreeper(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo) : CMonster(initx, inity, width, height, number, monsterInfo) { } CCreeper::~CCreeper() {} void CCreeper::OnStart() { OnLanding(); } void CCreeper::OnLanding() { status = (FindPlayerX() < 0 ? kMonsterBackward : kMonsterForward); } void CCreeper::OnCollision() { status = (status == kMonsterForward ? kMonsterBackward : kMonsterForward); } void CCreeper::OnAbyss() { if (FindPlayerY() < 0) status = (status == kMonsterForward ? kMonsterBackward : kMonsterForward); } void CCreeper::OnIdle() { lookDirection = (status == kMonsterBackward ? kLookingLeft : kLookingRight); forceVectorX = speed * deltaTime * gConst->kVelocityUnit * (status == kMonsterForward ? 1.0 : -1.0); } /* ########################################### WALKER CLASS EVENTS ############################################### */ CWalker::CWalker(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo) : CMonster(initx, inity, width, height, number, monsterInfo) { lastShoot = 0; currentShootDelay = 0; nextShootTime = 0; } CWalker::~CWalker() {} void CWalker::OnStart() { status = (FindPlayerX() < 0 ? kMonsterBackward : kMonsterForward); } void CWalker::OnCollision() { status = (status == kMonsterForward ? kMonsterBackward : kMonsterForward); } void CWalker::OnAbyss() { status = (status == kMonsterForward ? kMonsterBackward : kMonsterForward); } void CWalker::OnIdle() { double px = FindPlayerX(); if (!noWeapon && lastTime > nextShootTime) { lookDirection = (FindPlayerX() < 0 ? kLookingLeft : kLookingRight); if (weapon->Shoot(px, FindPlayerY(), (px > 0 ? px + xs : px + xe))) { nextShootTime = lastTime + currentShootDelay; lastShoot = lastTime + kWalkerWaitAfterShooting; status = (FindPlayerX() < 0 ? kMonsterBackward : kMonsterForward); }; } lookDirection = (status == kMonsterBackward ? kLookingLeft : kLookingRight); if (lastTime > lastShoot && lastTime > lastBlessureTime) forceVectorX = speed * deltaTime * gConst->kVelocityUnit * (status == kMonsterForward ? 1.0 : -1.0); } void CWalker::OnTreatment(double directionx, double directiony) { if (directiony > 0) { if (directionx > 0) status = kMonsterForward; else status = kMonsterBackward; } } void CWalker::OnShootSuccessful() { currentShootDelay = 0; } void CWalker::OnShootNotSuccessful() { if (currentShootDelay < kMonsterMaxShootDelay) currentShootDelay += kMonsterMaxShootDelay / 4; } /* ########################################### JUMPER CLASS EVENTS ############################################### */ CJumper::CJumper(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo) : CMonster(initx, inity, width, height, number, monsterInfo) { inJump = 0; nextShootTime = 0; currentShootDelay = 0; lastShoot = 0; } CJumper::~CJumper() {} void CJumper::OnStart() { status = (FindPlayerX() < 0 ? kMonsterBackward : kMonsterForward); } void CJumper::OnCollision() { short elemx, elemy; short condition; // Is there only a step, so the jumper can jump onto the step (but only when the player // is in this direction) if (status == kMonsterForward) { elemx = (short)((xs + (xe - xs) * 0.5) / kElementSize) +1; condition = FindPlayerX() > 0 && elemx < kLevelWidth; }else{ elemx = (short)((xs + (xe - xs) * 0.5) / kElementSize) -1; condition = FindPlayerX() < 0 && elemx > 0; } elemy = (short)((ys + (ye - ys) * 0.5) / kElementSize) -1; if (condition && elemy >= 0 && gLevel->level[elemy][elemx]->background) Jump(); else if (!inJump) status = (status == kMonsterForward ? kMonsterBackward : kMonsterForward); } void CJumper::OnAbyss() { short condition; // If there's an abyss, the jumper just jumps (only if the player is in the right direction) if (status == kMonsterForward) { condition = FindPlayerX() > 0; }else{ condition = FindPlayerX() < 0; } if (condition) Jump(); else status = (status == kMonsterForward ? kMonsterBackward : kMonsterForward); } void CJumper::OnIdle() { double px = FindPlayerX(); short oldStatus = status; if (!noWeapon && lastTime > nextShootTime) { lookDirection = (FindPlayerX() < 0 ? kLookingLeft : kLookingRight); if (weapon->Shoot(px, FindPlayerY(), (px > 0 ? px + xs : px + xe))) { nextShootTime = lastTime + currentShootDelay; lastShoot = lastTime + kWalkerWaitAfterShooting; } } lookDirection = (status == kMonsterBackward ? kLookingLeft : kLookingRight); if (lastTime > lastShoot && lastTime > lastBlessureTime) forceVectorX = speed * deltaTime * gConst->kVelocityUnit * (status == kMonsterForward ? 1.0 : -1.0); } void CJumper::OnTreatment(double directionx, double directiony) { if (ABS(directiony / directionx) > 1.0) { // the bullet comes vertical if (directiony > 0) { if (directionx > 0) status = kMonsterForward; else status = kMonsterBackward; } }else{ Jump(); } } void CJumper::OnLanding() { status = (FindPlayerX() < 0 ? kMonsterBackward : kMonsterForward); inJump = 0; } void CJumper::OnShootSuccessful() { currentShootDelay = 0; } void CJumper::OnShootNotSuccessful() { if (currentShootDelay < kMonsterMaxShootDelay) currentShootDelay += kMonsterMaxShootDelay / 4; } void CJumper::Jump() { if (!inJump) { forceVectorY = -gConst->kJumperJumpAcceleration * gConst->kVelocityUnit * deltaTime; inJump = 1; } } /* ########################################### FLYER CLASS EVENTS ############################################### */ CFlyer::CFlyer(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo) : CMonster(initx, inity, width, height, number, monsterInfo) { weight = 10; rescueMeX = 0; rescueMeY = 0; weightless = 1; nextShootTime = 0; currentShootDelay = 0; lastShoot = 0; } CFlyer::~CFlyer() {} void CFlyer::OnIdle() { double px = FindPlayerX(); if (!noWeapon && lastTime > nextShootTime) { lookDirection = (FindPlayerX() < 0 ? kLookingLeft : kLookingRight); if (weapon->Shoot(px, FindPlayerY(), (px > 0 ? px + xs : px + xe))) { nextShootTime = lastTime + currentShootDelay; lastShoot = lastTime + kWalkerWaitAfterShooting; } } if (lastTime > lastShoot) { if (!rescueMeX && !rescueMeY) { forceVectorX = speed * deltaTime * gConst->kVelocityUnit * SIGN(FindPlayerX()); forceVectorY = speed * deltaTime * gConst->kVelocityUnit * SIGN(FindPlayerY()); }else{ forceVectorX = rescueMeX * deltaTime; forceVectorY = rescueMeY * deltaTime; rescueMeX = 0; rescueMeY = 0; } } lookDirection = SIGN(forceVectorX); } void CFlyer::OnTreatment(double directionx, double directiony) { double len = sqrt(directionx * directionx + directiony * directiony); rescueMeX = SIGN(directionx) * directiony * speed * gConst->kVelocityUnit / len * 2.0; rescueMeY = SIGN(directiony) * -1.0 * directionx * speed * gConst->kVelocityUnit / len * 2.0; } void CFlyer::OnShootSuccessful() { currentShootDelay = 0; } void CFlyer::OnShootNotSuccessful() { if (currentShootDelay < kMonsterMaxShootDelay) currentShootDelay += kMonsterMaxShootDelay / 4; } void CFlyer::OnKill() { weightless = 0; CMonster::OnKill(); } /* ########################################### WARG CLASS EVENTS ############################################### */ CWarg::CWarg(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo) : CMonster(initx, inity, width, height, number, monsterInfo) { inJump = 0; if (monsterInfo) OnAllocate(); deathTime = 0; nextShootTime = 0; currentShootDelay = 0; lastShoot = 0; speedup = 1; } void CWarg::OnAllocate() { farWeapon = CreateWeapon(info->weapon + 1); } CWarg::~CWarg() { if (farWeapon) delete farWeapon; } void CWarg::OnStart() { status = (FindPlayerX() < 0 ? kMonsterBackward : kMonsterForward); } void CWarg::OnCollision() { status = (lastCollisionCode & kCollisionOnRight ? kMonsterBackward : kMonsterForward); speedup = 1; } void CWarg::OnAbyss() { status = (status == kMonsterForward ? kMonsterBackward : kMonsterForward); speedup = 1.0; } void CWarg::OnIdle() { double px = FindPlayerX(); CWeapon *currentWeapon; if (!noWeapon && lastTime > nextShootTime) { lookDirection = (px < 0 ? kLookingLeft : kLookingRight); currentWeapon = (ABS(px) > gConst->kWargNearWeaponRadix ? farWeapon : weapon); if (currentWeapon->Shoot(px, FindPlayerY(), (px > 0 ? px + xs : px + xe))) { nextShootTime = lastTime + currentShootDelay; lastShoot = lastTime + kWalkerWaitAfterShooting; status = (FindPlayerX() < 0 ? kMonsterBackward : kMonsterForward); }; } lookDirection = (status == kMonsterBackward ? kLookingLeft : kLookingRight); if (lastTime > lastShoot) forceVectorX = speed * deltaTime * lookDirection * gConst->kVelocityUnit * speedup; } void CWarg::OnTreatment(double directionx, double directiony) { if (ABS(directiony / directionx) > 1.0) { // the bullet comes vertical if (directiony > 0) { if (directionx > 0) status = kMonsterForward; else status = kMonsterBackward; } }else{ Jump(); status = (FindPlayerX() < 0 ? kMonsterBackward : kMonsterForward); } } void CWarg::OnLanding() { inJump = 0; } void CWarg::Jump() { if (!inJump) { forceVectorY = -gConst->kWargJumpAcceleration; inJump = 1; } } // --------------------------------------------- void CWarg::OnDamage(short blessure) // Event occurs, when a monster is hit by something (bullet etc.) { if (dieFrame == -1 && lastBlessureTime < lastTime) { health -= blessure; if (health < 0) { OnKill(); deathTime = lastTime + gConst->kDelayAfterWargDeath; } else { lastBlessureTime = lastTime + gConst->kBlessureInvulnerabilityTime; speedup = gConst->kWargFastSpeedup; } } } void CWarg::TestForDamage(double xb, double yb, short rad, short blessure) { CThing::TestForDamage(xb, yb, rad + dx / 2, blessure); } void CWarg::Render(short planeX, short planeY, tRect *clipRect) { CMonster::Render(planeX, planeY, clipRect); if (deathTime && deathTime < gSystem->GetTicks()) gApplication->command = kCmdNextLevel; } short CWalker::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(typeID); WRITEDATA(thingNumber); size += CMonster::Write(f); WRITEDATA(nextShootTime); WRITEDATA(currentShootDelay); WRITEDATA(lastShoot); FINISHWRITE; return size; } void CWalker::Read(FILE *f) { long size = 0; READDATA(size); READDATA(typeID); READDATA(thingNumber); CMonster::Read(f); READDATA(nextShootTime); READDATA(currentShootDelay); READDATA(lastShoot); } short CJumper::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(typeID); WRITEDATA(thingNumber); size += CMonster::Write(f); WRITEDATA(nextShootTime); WRITEDATA(currentShootDelay); WRITEDATA(lastShoot); WRITEDATA(inJump); FINISHWRITE; return size; } void CJumper::Read(FILE *f) { long size = 0; READDATA(size); READDATA(typeID); READDATA(thingNumber); CMonster::Read(f); READDATA(nextShootTime); READDATA(currentShootDelay); READDATA(lastShoot); READDATA(inJump); } short CFlyer::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(typeID); WRITEDATA(thingNumber); size += CMonster::Write(f); WRITEDATA(nextShootTime); WRITEDATA(currentShootDelay); WRITEDATA(lastShoot); WRITEDATA(rescueMeX); WRITEDATA(rescueMeY); FINISHWRITE; return size; } void CFlyer::Read(FILE *f) { long size = 0; READDATA(size); READDATA(typeID); READDATA(thingNumber); CMonster::Read(f); READDATA(nextShootTime); READDATA(currentShootDelay); READDATA(lastShoot); READDATA(rescueMeX); READDATA(rescueMeY); } short CWarg::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(typeID); WRITEDATA(thingNumber); size += CMonster::Write(f); if (farWeapon) size += farWeapon->Write(f); WRITEDATA(nextShootTime); WRITEDATA(currentShootDelay); WRITEDATA(lastShoot); WRITEDATA(inJump); WRITEDATA(speedup); FINISHWRITE; return size; } void CWarg::Read(FILE *f) { long size = 0; READDATA(size); READDATA(typeID); READDATA(thingNumber); CMonster::Read(f); OnAllocate(); if (farWeapon) farWeapon->Read(f); READDATA(nextShootTime); READDATA(currentShootDelay); READDATA(lastShoot); READDATA(inJump); READDATA(speedup); } amphetamine-0.8.10/src/Monstrxx.hpp0100664000076400007640000000464407447311405015744 0ustar lukeluke#ifndef __MONSTER_XTRAS__ #define __MONSTER_XTRAS__ #include "Monster.hpp" #include "ObjInfo.hpp" class CCreeper : public CMonster { protected: void OnStart(); void OnCollision(); void OnLanding(); void OnIdle(); void OnAbyss(); public: CCreeper(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo); ~CCreeper(); }; class CWalker : public CMonster { protected: long nextShootTime; long currentShootDelay; long lastShoot; void OnStart(); void OnCollision(); void OnIdle(); void OnAbyss(); void OnTreatment(double dirx, double diry); public: CWalker(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo); ~CWalker(); void OnShootSuccessful(); void OnShootNotSuccessful(); short Write(FILE *f); void Read(FILE *f); }; class CJumper : public CMonster { protected: long nextShootTime; long currentShootDelay; long lastShoot; short inJump; void OnStart(); void OnCollision(); void OnIdle(); void OnAbyss(); void OnTreatment(double dirx, double diry); void OnLanding(); void Jump(); public: CJumper(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo); ~CJumper(); void OnShootSuccessful(); void OnShootNotSuccessful(); short Write(FILE *f); void Read(FILE *f); }; class CFlyer : public CMonster { protected: long nextShootTime; long currentShootDelay; long lastShoot; double rescueMeX, rescueMeY; void OnIdle(); void OnTreatment(double dirx, double diry); public: CFlyer(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo); ~CFlyer(); void OnShootSuccessful(); void OnShootNotSuccessful(); void OnKill(); short Write(FILE *f); void Read(FILE *f); }; class CWarg : public CMonster { protected: CWeapon *farWeapon; long nextShootTime; long currentShootDelay; long lastShoot; short inJump; double speedup; long deathTime; void OnStart(); void OnCollision(); void OnIdle(); void OnAbyss(); void OnTreatment(double dirx, double diry); void OnLanding(); void Jump(); public: CWarg(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo); ~CWarg(); void OnAllocate(); void TestForDamage(double xb, double yb, short rad, short blessure); void OnDamage(short blessure); void Render(short planeX, short planeY, tRect *clipRect); short Write(FILE *f); void Read(FILE *f); }; #endifamphetamine-0.8.10/src/ShapeDes.hpp0100664000076400007640000002442007447311405015570 0ustar lukeluke#ifndef __AMP_SHAPEDESCRIPTOR__ #define __AMP_SHAPEDESCRIPTOR__ #include "ShapeLd.hpp" static short kShapeDescriptor[kNumShapes][5] = { // Items // ID x y dx dy //--------------------- {4100, 0, 576, 32, 32}, // Schwert {4101, 32, 576, 32, 32}, // Phiole {4102, 64, 576, 32, 32}, {4103, 96, 576, 32, 32}, {4104, 128, 576, 32, 32}, {4105, 160, 576, 32, 32}, {4106, 192, 576, 32, 32}, {4107, 224, 576, 32, 32}, {4110, 0, 608, 32, 32}, // Munition {4111, 32, 608, 32, 32}, {4112, 64, 608, 32, 32}, {4113, 96, 608, 32, 32}, {4114, 128, 608, 32, 32}, {4115, 160, 608, 32, 32}, {4120, 192, 608, 32, 32}, // Helppacket {4121, 224, 608, 32, 32}, // Sauerstoff {4122, 256, 608, 32, 32}, // Feuerstein {4000, 0, 512, 32, 32}, // Fenster 1 {4001, 32, 512, 32, 32}, // Fenster 2 {4002, 64, 512, 32, 32}, // Tor solid {4003, 96, 512, 32, 32}, // Gitter {4004, 128, 512, 32, 32}, // Dach l {4005, 160, 512, 32, 32}, // Dach R {4006, 192, 512, 32, 32}, // Busch 1 {4007, 224, 512, 32, 32}, // Busch 2 {4008, 256, 512, 32, 32}, // Tropfstein {4009, 288, 512, 32, 32}, {4010, 320, 512, 32, 32}, {4011, 352, 512, 32, 32}, {4012, 384, 512, 32, 32}, {4013, 416, 512, 32, 32}, {4014, 448, 512, 32, 32}, {4015, 0, 544, 32, 32}, {4016, 32, 544, 32, 32}, {4017, 64, 544, 32, 32}, {4018, 96, 544, 32, 32}, {4020, 128, 544, 32, 32}, {4019, 416, 544, 64, 64}, // Player {500, 0 * 32, 32, 32, 32}, // Sword {501, 1 * 32, 32, 32, 32}, {502, 2 * 32, 32, 32, 32}, {503, 3 * 32, 32, 32, 32}, {504, 4 * 32, 32, 32, 32}, {505, 5 * 32, 32, 32, 32}, {506, 6 * 32, 32, 32, 32}, {507, 7 * 32, 32, 32, 32}, {520, 0 * 32, 64, 32, 32}, // Phiole {521, 1 * 32, 64, 32, 32}, {522, 2 * 32, 64, 32, 32}, {523, 3 * 32, 64, 32, 32}, {524, 4 * 32, 64, 32, 32}, {510, 5 * 32, 64, 32, 32}, // Bacchetta {511, 6 * 32, 64, 32, 32}, {512, 7 * 32, 64, 32, 32}, {513, 8 * 32, 64, 32, 32}, {514, 9 * 32, 64, 32, 32}, {530, 10 * 32, 64, 32, 32}, // Bow {531, 11 * 32, 64, 32, 32}, {532, 12 * 32, 64, 32, 32}, {533, 13 * 32, 64, 32, 32}, {534, 14 * 32, 64, 32, 32}, {535, 15 * 32, 64, 32, 32}, {540, 0 * 32, 96, 32, 32}, // Scie {541, 1 * 32, 96, 32, 32}, {542, 2 * 32, 96, 32, 32}, {543, 3 * 32, 96, 32, 32}, {544, 4 * 32, 96, 32, 32}, {545, 5 * 32, 96, 32, 32}, {546, 6 * 32, 96, 32, 32}, {550, 7 * 32, 96, 32, 32}, // Hands {551, 8 * 32, 96, 32, 32}, {552, 9 * 32, 96, 32, 32}, {553, 10 * 32, 96, 32, 32}, {554, 11 * 32, 96, 32, 32}, {560, 0 * 32, 128, 32, 32}, // Bombs {561, 1 * 32, 128, 32, 32}, {562, 2 * 32, 128, 32, 32}, {563, 3 * 32, 128, 32, 32}, {564, 4 * 32, 128, 32, 32}, {570, 5 * 32, 128, 32, 32}, // Staff {571, 6 * 32, 128, 32, 32}, {572, 7 * 32, 128, 32, 32}, {573, 8 * 32, 128, 32, 32}, {574, 9 * 32, 128, 32, 32}, {575, 10 * 32, 128, 32, 32}, // Creeper {1000, 0 * 32, 160, 32, 32}, {1001, 1 * 32, 160, 32, 32}, {1002, 2 * 32, 160, 32, 32}, {1003, 3 * 32, 160, 32, 32}, {1004, 4 * 32, 160, 32, 32}, {1005, 5 * 32, 160, 32, 32}, {1006, 6 * 32, 160, 32, 32}, {1007, 7 * 32, 160, 32, 32}, // Saqqraq {1010, 8 * 32, 160, 32, 32}, {1011, 9 * 32, 160, 32, 32}, {1012, 10 * 32, 160, 32, 32}, {1013, 11 * 32, 160, 32, 32}, {1014, 12 * 32, 160, 32, 32}, {1015, 13 * 32, 160, 32, 32}, {1016, 14 * 32, 160, 32, 32}, {1017, 15 * 32, 160, 32, 32}, // Deadfish {1020, 0 * 32, 192, 32, 32}, {1021, 1 * 32, 192, 32, 32}, {1022, 2 * 32, 192, 32, 32}, {1023, 3 * 32, 192, 32, 32}, {1024, 4 * 32, 192, 32, 32}, {1025, 5 * 32, 192, 32, 32}, {1026, 6 * 32, 192, 32, 32}, {1027, 7 * 32, 192, 32, 32}, // Ork {1030, 8 * 32, 192, 32, 32}, {1031, 9 * 32, 192, 32, 32}, {1032, 10 * 32, 192, 32, 32}, {1033, 11 * 32, 192, 32, 32}, {1034, 12 * 32, 192, 32, 32}, {1035, 13 * 32, 192, 32, 32}, {1036, 14 * 32, 192, 32, 32}, {1037, 15 * 32, 192, 32, 32}, // Libelle {1050, 0 * 32, 224, 32, 32}, {1051, 1 * 32, 224, 32, 32}, {1052, 2 * 32, 224, 32, 32}, {1053, 3 * 32, 224, 32, 32}, {1054, 4 * 32, 224, 32, 32}, {1055, 5 * 32, 224, 32, 32}, {1056, 6 * 32, 224, 32, 32}, {1057, 7 * 32, 224, 32, 32}, // BlackOrk {1060, 8 * 32, 224, 32, 32}, {1061, 9 * 32, 224, 32, 32}, {1062, 10 * 32, 224, 32, 32}, {1063, 11 * 32, 224, 32, 32}, {1064, 12 * 32, 224, 32, 32}, {1065, 13 * 32, 224, 32, 32}, {1066, 14 * 32, 224, 32, 32}, {1067, 15 * 32, 224, 32, 32}, // Oger {1070, 0 * 32, 256, 32, 32}, {1071, 1 * 32, 256, 32, 32}, {1072, 2 * 32, 256, 32, 32}, {1073, 3 * 32, 256, 32, 32}, {1074, 4 * 32, 256, 32, 32}, {1075, 5 * 32, 256, 32, 32}, {1076, 6 * 32, 256, 32, 32}, {1077, 7 * 32, 256, 32, 32}, // Nazgul {1040, 8 * 32, 256, 32, 32}, {1041, 9 * 32, 256, 32, 32}, {1042, 10 * 32, 256, 32, 32}, {1043, 11 * 32, 256, 32, 32}, {1044, 12 * 32, 256, 32, 32}, {1045, 13 * 32, 256, 32, 32}, {1046, 14 * 32, 256, 32, 32}, {1047, 15 * 32, 256, 32, 32}, // Otyg {1080, 0 * 32, 288, 32, 32}, {1081, 1 * 32, 288, 32, 32}, {1082, 2 * 32, 288, 32, 32}, {1083, 3 * 32, 288, 32, 32}, {1084, 4 * 32, 288, 32, 32}, {1085, 5 * 32, 288, 32, 32}, {1086, 6 * 32, 288, 32, 32}, {1087, 7 * 32, 288, 32, 32}, // Grieg {1090, 8 * 32, 288, 32, 32}, {1091, 9 * 32, 288, 32, 32}, {1092, 10 * 32, 288, 32, 32}, {1093, 11 * 32, 288, 32, 32}, {1094, 12 * 32, 288, 32, 32}, {1095, 13 * 32, 288, 32, 32}, {1096, 14 * 32, 288, 32, 32}, {1097, 15 * 32, 288, 32, 32}, // Warg {1100, 0 * 64, 320, 64, 64}, {1101, 1 * 64, 320, 64, 64}, {1102, 2 * 64, 320, 64, 64}, {1103, 3 * 64, 320, 64, 64}, {1104, 4 * 64, 320, 64, 64}, {1105, 5 * 64, 320, 64, 64}, {1106, 6 * 64, 320, 64, 64}, {1107, 7 * 64, 320, 64, 64}, // Weapons {4803, 105, 649, 14, 14}, // Phiole {5100, 7 * 32, 672, 32, 32}, {5101, 8 * 32, 672, 32, 32}, {4804, 138, 650, 12, 12}, // Zauberstab {5110, 9 * 32, 672, 32, 32}, {5111, 10 * 32, 672, 32, 32}, {4802, 71, 650, 18, 10}, // Pfeilbogen {5000, 0 * 32, 672, 32, 32}, {5001, 1 * 32, 672, 32, 32}, {5002, 2 * 32, 672, 32, 32}, {5003, 3 * 32, 672, 32, 32}, {5004, 4 * 32, 672, 32, 32}, {4805, 167, 650, 16, 14}, // Hand {5120, 11 * 32, 672, 32, 32}, {5121, 12 * 32, 672, 32, 32}, {5122, 13 * 32, 672, 32, 32}, {5123, 14 * 32, 672, 32, 32}, {4806, 202, 652, 12, 12}, // Bombe {5160, 0 * 64, 800, 64, 64}, {5161, 1 * 64, 800, 64, 64}, {5162, 2 * 64, 800, 64, 64}, {5163, 3 * 64, 800, 64, 64}, {5164, 4 * 64, 800, 64, 64}, {4807, 7 * 32, 640, 32, 32}, // Staff {5126, 1 * 64, 704, 64, 64}, {5127, 2 * 64, 704, 64, 64}, {5128, 3 * 64, 704, 64, 64}, {5129, 4 * 64, 704, 64, 64}, {5130, 5 * 64, 704, 64, 64}, {4800, 9, 650, 14, 14}, // Unguided {4801, 38, 646, 18, 18}, // aimed {4810, 328, 649, 16, 16}, // guided {5180, 4, 741, 27, 28}, {5181, 33, 736, 31, 31}, {5182, 159, 769, 30, 30}, //{4811, 6 * 32, 672, 32, 32}, {5138, 7 * 32, 768, 32, 32}, {5139, 8 * 32, 768, 32, 32}, {5140, 9 * 32, 768, 32, 32}, {5141, 10 * 32, 768, 32, 32}, {5142, 11 * 32, 768, 32, 32}, {4808, 263, 651, 18, 18}, // Trollbombs {5124, 0 * 32, 704, 32, 32}, {5125, 1 * 32, 704, 32, 32}, {4809, 297, 650, 14, 12}, // Otyg {5131, 0 * 32, 768, 32, 32}, {5132, 1 * 32, 768, 32, 32}, {5133, 2 * 32, 768, 32, 32}, {5134, 3 * 32, 768, 32, 32}, {5135, 4 * 32, 768, 32, 32}, {4113, 327, 649, 18, 18}, // Violett {5120, 6 * 32, 736, 32, 32}, {5121, 7 * 32, 736, 32, 32}, {5122, 8 * 32, 736, 32, 32}, {5123, 9 * 32, 736, 32, 32}, {5124, 10 * 32, 736, 32, 32}, {4811, 356, 647, 25, 23}, // Warg 1 {5150, 12 * 32, 768, 32, 32}, {5151, 13 * 32, 768, 32, 32}, {4812, 384, 651, 34, 14}, // Warg 2 {2000, 0, 384, 32, 32}, // Türe {2001, 33, 384, 30, 32}, // Lift // Schalter etc. {200, 0 * 32, 0, 32, 32}, {201, 1 * 32, 0, 32, 32}, {202, 2 * 32, 0, 32, 32}, {203, 3 * 32, 0, 32, 32}, {204, 4 * 32, 0, 32, 32}, {205, 5 * 32, 0, 32, 32}, {206, 6 * 32, 0, 32, 32}, {207, 7 * 32, 0, 32, 32}, {208, 8 * 32, 0, 32, 32}, {209, 9 * 32, 0, 32, 32}, {210, 362, 0, 32, 37}, {211, 394, 0, 32, 37}, {300, 10 * 32, 0, 32, 32}, // Letters {65, 0, 864, 31, 24}, {66, 31, 864, 32, 24}, {67, 66, 864, 25, 24}, {68, 95, 864, 31, 24}, {69, 130, 864, 28, 24}, {70, 162, 864, 32, 24}, {71, 197, 864, 26, 24}, {72, 228, 864, 29, 24}, {73, 261, 864, 23, 24}, {74, 6, 888, 25, 25}, {75, 33, 888, 42, 25}, {76, 79, 888, 34, 25}, {77, 118, 888, 36, 25}, {78, 164, 888, 34, 25}, {79, 202, 888, 28, 25}, {80, 234, 888, 28, 25}, {81, 266, 888, 32, 25}, {82, 299, 888, 39, 25}, {83, 0, 914, 26, 25}, {84, 32, 914, 30, 25}, {85, 62, 914, 30, 25}, {86, 96, 914, 29, 25}, {87, 131, 914, 39, 25}, {88, 170, 914, 36, 25}, {89, 209, 914, 30, 25}, {90, 243, 914, 26, 25}, {33, 270, 914, 15, 25}, {63, 291, 914, 22, 25}, {49, 3, 939, 15, 21}, {50, 25, 939, 17, 21}, {51, 49, 939, 16, 21}, {52, 73, 939, 17, 21}, {53, 96, 939, 18, 21}, {54, 121, 939, 17, 21}, {55, 144, 939, 20, 21}, {56, 169, 939, 16, 21}, {57, 193, 939, 17, 21}, {48, 217, 939, 17, 21}, {46, 241, 939, 12, 21}, {44, 259, 939, 11, 21}, {45, 278, 939, 18, 21}, {10000, 317, 543, 94, 92}, {10001, 382, 806, 126, 126}, {10002, 322, 802, 40, 40} }; static short kTextureDescriptor[kNumTextures][5] = { // Texset 1 {3000, 0 * 32, 416, 32, 32}, {3001, 1 * 32, 416, 32, 32}, {3002, 2 * 32, 416, 32, 32}, {3003, 3 * 32, 416, 32, 32}, {3004, 4 * 32, 416, 32, 32}, {3005, 5 * 32, 416, 32, 32}, {3006, 6 * 32, 416, 32, 32}, {3007, 7 * 32, 416, 32, 32}, {3008, 8 * 32, 416, 32, 32}, {3009, 9 * 32, 416, 32, 32}, {3010, 10 * 32, 416, 32, 32}, {3011, 11 * 32, 416, 32, 32}, {3012, 12 * 32, 416, 32, 32}, {3013, 13 * 32, 416, 32, 32}, {3014, 14 * 32, 416, 32, 32}, // Texset 2 {3020, 0 * 32, 448, 32, 32}, {3021, 1 * 32, 448, 32, 32}, {3022, 2 * 32, 448, 32, 32}, {3023, 3 * 32, 448, 32, 32}, {3024, 4 * 32, 448, 32, 32}, {3025, 5 * 32, 448, 32, 32}, {3026, 6 * 32, 448, 32, 32}, {3027, 7 * 32, 448, 32, 32}, {3028, 8 * 32, 448, 32, 32}, {3029, 9 * 32, 448, 32, 32}, {3030, 10 * 32, 448, 32, 32}, {3031, 11 * 32, 448, 32, 32}, {3032, 12 * 32, 448, 32, 32}, {3033, 13 * 32, 448, 32, 32}, {3034, 14 * 32, 448, 32, 32}, // Texset 3 {3040, 0 * 32, 480, 32, 32}, {3041, 1 * 32, 480, 32, 32}, {3042, 2 * 32, 480, 32, 32}, {3043, 3 * 32, 480, 32, 32}, {3044, 4 * 32, 480, 32, 32}, {3045, 5 * 32, 480, 32, 32}, {3046, 6 * 32, 480, 32, 32}, {3047, 7 * 32, 480, 32, 32}, {3048, 8 * 32, 480, 32, 32}, {3049, 9 * 32, 480, 32, 32}, {3050, 10 * 32, 480, 32, 32}, {3051, 11 * 32, 480, 32, 32}, {3052, 12 * 32, 480, 32, 32}, {3053, 13 * 32, 480, 32, 32}, {3054, 14 * 32, 480, 32, 32} }; #endifamphetamine-0.8.10/src/Thing.cpp0100664000076400007640000000712607447606137015155 0ustar lukeluke#include "Thing.hpp" #include "Appl.hpp" #include "ConstVal.hpp" extern CApplication *gApplication; extern tConstValues *gConst; extern CLevel *gLevel; CThing::CThing(short initx, short inity, short width, short height, short number) : CObject(initx, inity, width, height) { typeID |= kThing; dx = xe - xs; dy = ye - ys; weight = 10; next = prev = nextCollisionThing = prevCollisionThing = 0L; lookDirection = kLookingRight; weightless = 0; thingNumber = number; // additinal initializations modus = 0; } CThing::~CThing() {} void CThing::Gravitation() { if (weight && !weightless && forceVectorY < gConst->kMaxFallingSpeed * deltaTime * gConst->kVelocityUnit) forceVectorY += gConst->kGravitation * deltaTime; } void CThing::LinkInLists() { gApplication->Enqueue(&gApplication->thingList, this); } void CThing::UnlinkInLists() { gApplication->Dequeue(&gApplication->thingList, this); } void CThing::Render(short planeX, short planeY, tRect *clipRect) {} void CThing::PostRender(short planeX, short planeY, tRect *clipRect) {} short CThing::Forces() { short collisionObject; Gravitation(); CObject::Forces(); ExertForce(resForceX, resForceY, collisionObject, 0L); return kNoEvent; } void CThing::Move() { CElement *element; //CObject::Forces(); if (ys < kLevelHeight * kElementSize) { xs += resForceX + environmentForceX; xe += resForceX + environmentForceX; ys += resForceY + environmentForceY; ye += resForceY + environmentForceY; xm = xs + (xe - xs) * 0.5; ym = ys + (ye - ys) * 0.5; } element = gLevel->GetElement(xm, ym); modus = (element ? element->GetElementLiquid() : kShapemodusNormal); } void CThing::CalcPlaneOffsets(short &planex, short &planey) { short midx = xm; short midy = ym; if (midx <= kGamePlaneWidth / 2) planex = 0; else if (midx >= kLevelWidth * kElementSize - kGamePlaneWidth / 2) planex = kLevelWidth * kElementSize - kGamePlaneWidth; else planex = midx - kGamePlaneWidth / 2; if (midy <= kGamePlaneHeight / 2) planey = 0; else if (midy >= kLevelHeight * kElementSize - kGamePlaneHeight / 2) planey = kLevelHeight * kElementSize - kGamePlaneHeight; else planey = midy - kGamePlaneHeight / 2; } short CThing::Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject) { if (right + forcex < xs || left + forcex > xe || bottom + forcey < ys || top + forcey > ye) return kNoCollision; short returnValue = CObject::Collision(sender, left, top, right, bottom, forcex, forcey, pfx, pfy, sourceWeight, collisionObject); if (returnValue & (kCollisionOnBottom | kCollisionWithPushing)) { sender->CollisionEvent(gConst->kNormalFriction, 0); } return returnValue; } // ------------------------------------------------------------------------------ void CThing::TestForDamage(double xb, double yb, short rad, short blessure) // Sending a damage event to the thing if the distance to the bullet is less than rad { if ((xm - xb) * (xm - xb) + (ym - yb) * (ym - yb) <= rad * rad) OnDamage(blessure); } void CThing::OnDamage(short blessure) { } short CThing::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(typeID); WRITEDATA(thingNumber); size += CObject::Write(f); WRITEDATA(lookDirection); WRITEDATA(weightless); WRITEDATA(dx); WRITEDATA(dy); WRITEDATA(modus); FINISHWRITE; return size; } void CThing::Read(FILE *f) { long size = 0; READDATA(size); READDATA(typeID); READDATA(thingNumber); CObject::Read(f); READDATA(lookDirection); READDATA(weightless); READDATA(dx); READDATA(dy); READDATA(modus); } amphetamine-0.8.10/src/Thing.hpp0100664000076400007640000000313007447375700015150 0ustar lukeluke#ifndef __AMP_THING__ #define __AMP_THING__ #include "Object.hpp" class CWeapon; class CHandWeapon; class CSorcery; class CBomb; class CMultiBulletWeapon; class CStaff; class CSineWeapon; class CGuided; enum { // Looking values kLookingRight = 1, kLookingLeft = -1 }; class CThing : public CObject { friend class CWeapon; friend class CHandWeapon; friend class CSorcery; friend class CBomb; friend class CMultiBulletWeapon; friend class CStaff; friend class CSineWeapon; friend class CGuided; protected: short lookDirection; // in which direction the thing looks short weightless; short dx, dy; short modus; short thingNumber; public: CThing *next, *prev, *nextCollisionThing, *prevCollisionThing; CThing *nextPreRenderThing, *prevPreRenderThing; CThing *nextPostRenderThing, *prevPostRenderThing; CThing(short initx, short inity, short width, short height, short number); ~CThing(); void Gravitation(); virtual void LinkInLists(); virtual void UnlinkInLists(); virtual void Render(short planeX, short planeY, tRect *clipRect); virtual void PostRender(short planeX, short planeY, tRect *clipRect); virtual void Move(); virtual short Forces(); void CalcPlaneOffsets(short &planex, short &planey); short Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject); virtual void TestForDamage(double xb, double yb, short rad, short blessure); virtual void OnDamage(short blessure); virtual short Write(FILE *f); virtual void Read(FILE *f); }; #endifamphetamine-0.8.10/src/AmpHead.hpp0100664000076400007640000000714107447577027015412 0ustar lukeluke#ifndef __AMP_HEADER__ #define __AMP_HEADER__ #include "limits.h" #include "float.h" const long kVersionNumber = 0x0090; const char kVersionString[] = "0.8.10"; // by LL const long kVersionKey = 10835; const char kMyName1[6] = "JONAS"; const char kMyName2[10] = "SPILLMANN"; const char kParFileName[] = "amph.conf"; // by LL const char kLogFileName[] = "logfile"; enum { // Gameplane kGamePlaneWidth = 480, kGamePlaneHeight = 480, kUserPlaneWidth = 160, // Num and size of level elements kElementSize = 32, kLevelWidth = 100, kLevelHeight = 20, // Screen resolution kScreenWidth = 1280, kScreenHeight = 1024, kScreenDepth = 8, kNumOfLevels = 15, // Monster classes kClassPlayer = 0, kClassCreeper = 1, kClassJumper = 2, kClassFlyer = 3, kClassWalker = 4, kClassWarg = 5, // Item classes kClassBackgroundItem = 0, kClassUnpassableItem = 1, kClassMovableItem = 2, kClassPortableItem = 3, // Flags for flags field in item info kItemUnpassableMask = 32768, kItemPortableMask = 16384, kItemHurtMask = 8192, kItemExplodesMask = 4096, // Flags for data field kPassiveLightMask = 1, kPassivePlatformMask = 2, kRightDriftMask = 4, kLeftDriftMask = 8, kIceMask = 16, kFlickeringMask = 32, kInfotextMask = 64, kHurtMask = 128, kFogMask = 256, kWaterMask = 512, kLavaMask = 1024, kTeleportMask = 2048, kExitMask = 4096, kSaveMask = 8192, kLightSwitchMask = 16384, kPlatformSwitchMask = 32768, // Collision codes kNoCollision = 0, kCollisionOnTop = 1, kCollisionOnLeft = 2, kCollisionOnRight = 4, kCollisionOnBottom = 8, kCollisionWithPushing = 16, kCollisionWithLevelBorders = 32, // Return codes for ::Think and ::Move kNoEvent = 0, kDestroyMe = 1, kCameraNo = 12 }; // Type IDs enum { kObject = 1, kElement = 1 << 1, kBackgroundElement =1 << 2, kThing = 1 << 3, kMonster = 1 << 4, kPlayer = 1 << 5, kItem = 1 << 6, kStaticItem = 1 << 7, kBackgroundItem = 1 << 8, kMovableItem = 1 << 9, kPortableItem = 1 << 10, kPlatform = 1 << 11, kBullet = 1 << 12, kSorceryBullet = 1 << 13, kBombBullet = 1 << 14, kSineBullet = 1 << 15, kGuidedBullet = 1 << 16, kCreeper = 1 << 17, kWalker = 1 << 18, kJumper = 1 << 19, kFlyer = 1 << 20, kWarg = 1 << 21, kCamera = 1 << 22 }; // Modi for drawing a shape enum { kShapemodusNormal = 0, kShapemodusTransparent1, kShapemodusTransparent2, kShapemodusTransparent3, kShapemodusRandom, kShapemodusWater, kShapemodusLava, kShapemodusFog, kShapemodusShadow, kShapemodusBackwardFlag = 32768 // when set, the shape is drawn horizontally inverted }; enum { kWeaponNormal = 0, kWeaponSorcery, kWeaponMultibullet, kWeaponBomb, kWeaponStaff, kWeaponInHand, kWeaponSine, kWeaponGuided, kWeaponHasWeight }; // Weapon stati enum { kWeaponDoesntExist, kWeaponOutOfMunition, kWeaponReady }; enum { // Portable Items kItemSword = 0, kItemPhiol, kItemSorcery, kItemBow, kItemScie, kItemHands, kItemBomb, kItemStaff, kItemPhiolmun, kItemSorcerymun, kItemBowmun, kItemSciemun, // not used kItemHandsmun, kItemBombmun, kItemStaffmun, kItemOxygen, kItemHelppacket }; struct tRect { short left, top, right, bottom; }; typedef struct { unsigned char red, green, blue; } RGBcolor; #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define ABS(a) ((a) > 0 ? (a) : (-(a))) #define SIGN(a) ((a) >= 0 ? 1 : -1) #define SWAP(a, b, _t) (a) = (_t)((long)a ^ (long)(b)); (b) = (_t)((long)(a) ^ (long)(b)); (a) = (_t)((long)(a) ^ (long)(b)); #define NZ(a, b) ((a) == 0 ? (b) : (a)) #define MSG(message) if (logFile) fprintf(logFile, message); fflush(logFile) #endifamphetamine-0.8.10/src/Clut.cpp0100664000076400007640000004700407447311405015001 0ustar lukeluke#include "Clut.hpp" #include "System.hpp" #include "ConstVal.hpp" #include "Level.hpp" #include "ShapeLd.hpp" extern tConstValues *gConst; extern tConfigData *gConfigData; extern CLevel *gLevel; extern CSystem *gSystem; extern CShapeManager *gShapeManager; extern FILE *logFile; const short kWaterTransparence = 60; // percent of blue const short kLavaTransparence = 80; // percent of red and *3 percent of green const double kFogFactor = 0.8; short WeightenedRandom(short anz); CClutManager::CClutManager() { long maxRadiant, radiant; short j, k, val; for (short n = 0; n < kMaxLuminosityLevel * 2; n ++) { luminosityTable[n] = new unsigned char [256]; } transparentTable1 = new unsigned char * [256]; transparentTable2 = new unsigned char * [256]; transparentTable3 = new unsigned char * [256]; for (j = 0; j < 256; j ++) { transparentTable1[j] = new unsigned char [256]; transparentTable2[j] = new unsigned char [256]; transparentTable3[j] = new unsigned char [256]; } blueLightningTable = new unsigned char * [gConst->kLightningRadiant]; redLightningTable = new unsigned char * [gConst->kLightningRadiant]; greenLightningTable = new unsigned char * [gConst->kLightningRadiant]; yellowLightningTable = new unsigned char * [gConst->kLightningRadiant]; purpleLightningTable = new unsigned char * [gConst->kLightningRadiant]; whiteCoronaTable = new unsigned char * [gConst->kLightningRadiant]; yellowCoronaTable = new unsigned char * [gConst->kLightningRadiant]; blueCoronaTable = new unsigned char * [gConst->kLightningRadiant]; for (j = 0; j < gConst->kLightningRadiant; j ++) { blueLightningTable[j] = new unsigned char [256]; redLightningTable[j] = new unsigned char [256]; greenLightningTable[j] = new unsigned char [256]; yellowLightningTable[j] = new unsigned char [256]; purpleLightningTable[j] = new unsigned char [256]; whiteCoronaTable[j] = new unsigned char [256]; yellowCoronaTable[j] = new unsigned char [256]; blueCoronaTable[j] = new unsigned char [256]; } radiantTable = new unsigned char [gConst->kLightningRadiant * gConst->kLightningRadiant]; maxRadiant = gConst->kLightningRadiant * gConst->kLightningRadiant; for (j = 0; j < gConst->kLightningRadiant; j ++) { for (k = 0; k < gConst->kLightningRadiant; k ++) { radiant = j * j + k * k; if (radiant > maxRadiant) radiantTable [j * gConst->kLightningRadiant + k] = gConst->kLightningRadiant -1; else { val = radiant * gConst->kLightningRadiant / maxRadiant + WeightenedRandom(5) - 1; radiantTable [j * gConst->kLightningRadiant + k] = MIN(val, gConst->kLightningRadiant - 1); } } } coronas[0].values = coronas[1].values = coronas[2].values = 0L; } CClutManager::~CClutManager() { short n; if (coronas[0].values) delete [] coronas[0].values; if (coronas[1].values) delete [] coronas[1].values; if (coronas[2].values) delete [] coronas[2].values; for (n = 0; n < kMaxLuminosityLevel * 2; n ++) { delete [] luminosityTable[n]; } for (n = 0; n < gConst->kLightningRadiant; n ++) { delete [] blueLightningTable[n]; delete [] redLightningTable[n]; delete [] greenLightningTable[n]; delete [] yellowLightningTable[n]; delete [] purpleLightningTable[n]; delete [] whiteCoronaTable[n]; delete [] yellowCoronaTable[n]; delete [] blueCoronaTable[n]; } delete [] blueLightningTable; delete [] redLightningTable; delete [] greenLightningTable; delete [] yellowLightningTable; delete [] purpleLightningTable; delete [] whiteCoronaTable; delete [] yellowCoronaTable; delete [] blueCoronaTable; delete [] radiantTable; } // -------------------------------------- short WeightenedRandom(short anz) // Returns a number which the possibility that the number is 1 is 1/2, for 2 is 1 / 3, for 3 is 1/4 etc. { long maxSum = 0, n; long randValue; for (n = 1; n <= anz; n ++) maxSum += 100 / n; randValue = rand() * maxSum / RAND_MAX; maxSum = 0; for (n = 1; n <= anz; n ++) { if (randValue >= maxSum && randValue < maxSum + 100 / n) return n; maxSum += 100 / n; } return 1; } // ---------------------------------------------- void CClutManager::LoadPalette(RGBcolor *pal) // Writing the palette from the AmpGraf.gif file into the color manager { short j, k; for (short n = 0; n < 256; n ++) { palette[n].red = pal[n].red; palette[n].green = pal[n].green; palette[n].blue = pal[n].blue; } SWAP(palette[0].red, palette[255].red, unsigned char); SWAP(palette[0].green, palette[255].green, unsigned char); SWAP(palette[0].blue, palette[255].blue, unsigned char); } // -------------------------------------------------------- void CClutManager::BuildLuminosityTable() // Builds the luminosity and the color tables { unsigned char color; short j, k; FILE *fClut = fopen(gSystem->QualifyDataDir(gConst->kFileCluts), "rb"); // by LL short index, index2; short mode = 0; if (!fClut) { fClut = fopen(gSystem->QualifyDataDir(gConst->kFileCluts), "wb"); // by LL if (!fClut) MSG("!!! File not found: "); MSG(gConst->kFileCluts); MSG("\n"); mode = 1; } fseek(fClut, 0, SEEK_SET); for (short n = -kMaxLuminosityLevel; n < kMaxLuminosityLevel; n ++) { for (short j = 0; j < 256; j ++) { if (mode) { color = ChangeColorValues(j, SIGN(n) * gConst->kBrightnessLevels[ABS(n)], SIGN(n) * gConst->kBrightnessLevels[ABS(n)], SIGN(n) * gConst->kBrightnessLevels[ABS(n)]); luminosityTable[kMaxLuminosityLevel + n][j] = color; fputc(color, fClut); }else{ luminosityTable[kMaxLuminosityLevel + n][j] = (unsigned char)fgetc(fClut); } } } for (j = 0; j < 256; j ++) { for (k = 0; k < 256; k ++) { if (mode) { transparentTable1[j][k] = ChangeColorValues(j, (palette[k].red - palette[j].red) / 4 * 100 / 256, (palette[k].green - palette[j].green) / 4 * 100 / 256, (palette[k].blue - palette[j].blue) / 4 * 100 / 256); fputc(transparentTable1[j][k], fClut); transparentTable2[j][k] = ChangeColorValues(j, (palette[k].red - palette[j].red) / 2 * 100 / 256, (palette[k].green - palette[j].green) / 2 * 100 / 256, (palette[k].blue - palette[j].blue) / 2 * 100 / 256); fputc(transparentTable2[j][k], fClut); transparentTable3[j][k] = ChangeColorValues(j, (palette[k].red - palette[j].red) * 3 / 4 * 100 / 256, (palette[k].green - palette[j].green) * 3 / 4 * 100 / 256, (palette[k].blue - palette[j].blue) * 3 / 4 * 100 / 256); fputc(transparentTable3[j][k], fClut); }else{ transparentTable1[j][k] = (unsigned char)fgetc(fClut); transparentTable2[j][k] = (unsigned char)fgetc(fClut); transparentTable3[j][k] = (unsigned char)fgetc(fClut); } } } // Calculating the lightning tables which are used to calculate the lightning around bullets for (j = 0; j < gConst->kLightningRadiant; j ++) { for (k = 0; k < 256; k ++) { if (mode) { blueLightningTable[j][k] = ChangeColorValues(k, 0, 0, (gConst->kLightningRadiant - j) * 100 / gConst->kLightningRadiant); fputc(blueLightningTable[j][k], fClut); redLightningTable[j][k] = ChangeColorValues(k, (gConst->kLightningRadiant - j) * 70 / gConst->kLightningRadiant, 0, 0); fputc(redLightningTable[j][k], fClut); greenLightningTable[j][k] = ChangeColorValues(k, 0, (gConst->kLightningRadiant - j) * 60 / gConst->kLightningRadiant, 0); fputc(greenLightningTable[j][k], fClut); yellowLightningTable[j][k] = ChangeColorValues(k, (gConst->kLightningRadiant - j) * 40 / gConst->kLightningRadiant, (gConst->kLightningRadiant - j) * 40 / gConst->kLightningRadiant, 0); fputc(yellowLightningTable[j][k], fClut); purpleLightningTable[j][k] = ChangeColorValues(k, (gConst->kLightningRadiant - j) * 40 / gConst->kLightningRadiant, 0, (gConst->kLightningRadiant - j) * 40 / gConst->kLightningRadiant); fputc(purpleLightningTable[j][k], fClut); whiteCoronaTable[j][k] = ChangeColorValues(k, (gConst->kLightningRadiant - j) * 100 / gConst->kLightningRadiant, (gConst->kLightningRadiant - j) * 100 / gConst->kLightningRadiant, (gConst->kLightningRadiant - j) * 100 / gConst->kLightningRadiant); fputc(whiteCoronaTable[j][k], fClut); yellowCoronaTable[j][k] = ChangeColorValues(k, (gConst->kLightningRadiant - j) * 100 / gConst->kLightningRadiant, (gConst->kLightningRadiant - j) * 100 / gConst->kLightningRadiant, (gConst->kLightningRadiant - j) * 80 / gConst->kLightningRadiant); fputc(yellowCoronaTable[j][k], fClut); blueCoronaTable[j][k] = ChangeColorValues(k, (gConst->kLightningRadiant - j) * 40 / gConst->kLightningRadiant, (gConst->kLightningRadiant - j) * 40 / gConst->kLightningRadiant, (gConst->kLightningRadiant - j) * 100 / gConst->kLightningRadiant); }else{ blueLightningTable[j][k] = (unsigned char)fgetc(fClut); redLightningTable[j][k] = (unsigned char)fgetc(fClut); greenLightningTable[j][k] = (unsigned char)fgetc(fClut); yellowLightningTable[j][k] = (unsigned char)fgetc(fClut); purpleLightningTable[j][k] = (unsigned char)fgetc(fClut); whiteCoronaTable[j][k] = (unsigned char)fgetc(fClut); yellowCoronaTable[j][k] = (unsigned char)fgetc(fClut); //blueCoronaTable[j][k] = (unsigned char)fgetc(fClut); } } } for (j = 0; j < 256; j ++) { if (mode) { waterColorTable[j] = ChangeColorValues(j, 0, 0, kWaterTransparence); fputc(waterColorTable[j], fClut); lavaColorTable[j] = ChangeColorValues(j, kLavaTransparence, kLavaTransparence / 3, 0); fputc(lavaColorTable[j], fClut); shadowTable[j] = ChangeColorValues(j, -gConst->kShadowmodeDarkening, -gConst->kShadowmodeDarkening, -gConst->kShadowmodeDarkening); fputc(shadowTable[j], fClut); fogTable[j] = FindClosestColor(palette[j].red + (short)(double(128 - palette[j].red) * kFogFactor), palette[j].green + (short)(double(128 - palette[j].green) * kFogFactor), palette[j].blue + (short)(double(128 - palette[j].blue) * kFogFactor)); fputc(fogTable[j], fClut); }else{ waterColorTable[j] = (unsigned char)fgetc(fClut); lavaColorTable[j] = (unsigned char)fgetc(fClut); shadowTable[j] = (unsigned char)fgetc(fClut); fogTable[j] = (unsigned char)fgetc(fClut); } } fclose(fClut); } void CClutManager::CalculateCoronas(unsigned char *bmp, short width) { unsigned char *tmp; short coronaColor; short value; unsigned char *bitmap; for (short n = 0; n < kNumOfCoronas; n ++) { coronas[n].dx = kCoronaDescriptor[n][3]; coronas[n].dy = kCoronaDescriptor[n][4]; coronas[n].values = new unsigned char [coronas[n].dx * coronas[n].dy]; coronas[n].table = 0L; bitmap = bmp + kCoronaDescriptor[n][2] * width + kCoronaDescriptor[n][1]; for (short j = 0; j < coronas[n].dy; j ++) { for (short k = 0; k < coronas[n].dx; k ++) { if (bitmap[k] == 255) bitmap[k] = kBlackColor; else if (bitmap[k] == 0) bitmap[k] = kWhiteColor; value = (palette[bitmap[k]].red + palette[bitmap[k]].green + palette[bitmap[k]].blue) / 3; coronas[n].values[j * coronas[n].dx + k] = (unsigned char)(value * gConst->kLightningRadiant / 256); } bitmap += width; } } } // -------------------------------------------------- short CClutManager::FindClosestColor(unsigned char red, unsigned char green, unsigned char blue) /* In: an exact color value Out: color index to a color in the palette which matches the color value the exactest */ { long distance, minDistance = LONG_MAX; short n, minn = -1; for (n = 0; n < 256; n ++) { distance = (long)(palette[n].red - red) * (long)(palette[n].red - red) + (long)(palette[n].green - green) * (long)(palette[n].green - green) + (long)(palette[n].blue - blue) * (long)(palette[n].blue - blue); if (distance < minDistance) { minDistance = distance; minn = n; } } return minn; } // -------------------------------------------------------------- unsigned char CClutManager::ChangeColorValues(unsigned char color, short percentageRed, short percentageGreen, short percentageBlue) /* In: color which red, green and blue parts are to change How many percent each color has to change 100% <= x <= -100% Out: changed color */ { if (color == 0) color = kWhiteColor; if (color == 255) color = kBlackColor; short red = palette[color].red, green = palette[color].green, blue = palette[color].blue; if (percentageRed > 0) red += (unsigned char)((long)(255 - (long)palette[color].red) * percentageRed / 100); else red -= (unsigned char)((long)(palette[color].red) * ABS(percentageRed) / 100); red = MAX(0, red); red = MIN(255, red); if (percentageGreen > 0) green += (unsigned char)((long)(255 - (long)palette[color].green) * percentageGreen / 100); else green -= (unsigned char)((long)(palette[color].green) * ABS(percentageGreen) / 100); green = MAX(0, green); green = MIN(255, green); if (percentageBlue > 0) blue += (unsigned char)((long)(255 - (long)palette[color].blue) * percentageBlue / 100); else blue -= (unsigned char)((long)(palette[color].blue) * ABS(percentageBlue) / 100); blue = MAX(0, blue); blue = MIN(255, blue); return (unsigned char)FindClosestColor((unsigned char)red, (unsigned char)green, (unsigned char)blue); } void CClutManager::SetPixel(unsigned char *source, unsigned char *dest, short modus, short luminosity) { switch (modus) { case kShapemodusNormal: *dest = luminosityTable[kMaxLuminosityLevel + luminosity][*source]; break; case kShapemodusRandom: *dest = rand() & 255; break; case kShapemodusWater: *dest = waterColorTable[luminosityTable[kMaxLuminosityLevel + luminosity][*source]]; break; case kShapemodusLava: *dest = lavaColorTable[luminosityTable[kMaxLuminosityLevel + luminosity][*source]]; break; case kShapemodusShadow: *dest = shadowTable[luminosityTable[kMaxLuminosityLevel + luminosity][*dest]]; break; case kShapemodusFog: *dest = fogTable[luminosityTable[kMaxLuminosityLevel + luminosity][*source]]; break; case kShapemodusTransparent1: *dest = transparentTable1[*source][*dest]; break; case kShapemodusTransparent2: *dest = transparentTable2[*source][*dest]; break; case kShapemodusTransparent3: *dest = transparentTable3[*source][*dest]; break; default: *dest = *source; } } unsigned char **CClutManager::EffectToTable(short effect) { switch (effect) { case kLightningBlueEffect: return blueLightningTable; break; case kLightningRedEffect: return redLightningTable; break; case kLightningGreenEffect: return greenLightningTable; break; case kLightningYellowEffect: return yellowLightningTable; break; case kLightningPurpleEffect: return purpleLightningTable; break; case kWhiteCoronaTable: return whiteCoronaTable; break; case kYellowCoronaTable: return yellowCoronaTable; break; case kBlueCoronaTable: return blueCoronaTable; break; default: return 0L; } } // ------------------------------------------------------------------------ void CClutManager::DrawLightning(double xm, double ym, short effect, CGraphicSurface *surface) // Draws a gConst->kLightningRadinant * 2 - sqare on the screen which illuminates // the background in the color effect { short planeX, planeY; long startx, starty, endx, endy, midx, midy; unsigned char *baseAddr; short pitch; short j, k; CElement *element; unsigned char **table; if (gConfigData->disableLightning) return; table = EffectToTable(effect); gLevel->focus->CalcPlaneOffsets(planeX, planeY); midx = xm - planeX; midy = ym - planeY; startx = midx - gConst->kLightningRadiant; startx = MAX(startx, 0); startx = MIN(startx, kGamePlaneWidth); starty = midy - gConst->kLightningRadiant; starty = MAX(starty, 0); starty = MIN(starty, kGamePlaneHeight); endx = midx + gConst->kLightningRadiant; endx = MAX(endx, 0); endx = MIN(endx, kGamePlaneWidth); endy = midy + gConst->kLightningRadiant; endy = MAX(endy, 0); endy = MIN(endy, kGamePlaneHeight); baseAddr = surface->GetSurfacePtr(&pitch); baseAddr += starty * pitch; for (j = starty + 1; j < endy; j ++) { for (k = startx + 1; k < endx; k ++) { element = gLevel->level[(j + planeY) / kElementSize][(k + planeX) / kElementSize]; if (element->background && !(element->typeID & kBackgroundElement)) baseAddr[k] = table[radiantTable[ABS(j - midy) * gConst->kLightningRadiant + ABS(k - midx)]][baseAddr[k]]; } baseAddr += pitch; } surface->ReleaseSurface(); } void CClutManager::PrepareCorona(double xm, double ym, CGraphicSurface *surface) { short planeX, planeY; short midx, midy; short pitch; unsigned char *baseAddr; gLevel->focus->CalcPlaneOffsets(planeX, planeY); midx = xm - planeX; midy = ym - planeY; if (midx >= 0 && midx < kGamePlaneWidth && midy >= 0 && midy < kGamePlaneHeight) { baseAddr = surface->GetSurfacePtr(&pitch); baseAddr += midy * pitch + midx; *baseAddr = (unsigned char)kWhiteColor; surface->ReleaseSurface(); } } void CClutManager::DrawCorona(double xm, double ym, short coronaNum, short effect, CGraphicSurface *surface, double &coronaFader, long deltaTime) { // Draws a gConst->kLightningRadinant * 2 - sqare on the screen which illuminates // the background in the color effect short planeX, planeY; long startx, starty, endx, endy, midx, midy; short smidx, smidy; unsigned char *baseAddr, *origBaseAddr; short pitch; short j, k; if (gConfigData->disableCoronas) return; tCorona *corona = &coronas[coronaNum]; unsigned char **table = EffectToTable(effect); gLevel->focus->CalcPlaneOffsets(planeX, planeY); midx = xm - planeX; midy = ym - planeY; smidx = corona->dx / 2; startx = midx - smidx; startx = MAX(startx, 0); startx = MIN(startx, kGamePlaneWidth); smidy = corona->dy / 2; starty = midy - smidy; starty = MAX(starty, 0); starty = MIN(starty, kGamePlaneHeight); endx = midx + corona->dx / 2; endx = MAX(endx, 0); endx = MIN(endx, kGamePlaneWidth); endy = midy + corona->dy / 2; endy = MAX(endy, 0); endy = MIN(endy, kGamePlaneHeight); origBaseAddr = surface->GetSurfacePtr(&pitch); baseAddr = origBaseAddr + midy * pitch + midx; if (midx >= 0 && midy >= 0 && midx < kGamePlaneWidth && midy < kGamePlaneHeight && *(unsigned char *)baseAddr == kWhiteColor) { coronaFader += gConst->kCoronaFadeSpeed * deltaTime; coronaFader = MIN(1.0, coronaFader); }else{ coronaFader -= gConst->kCoronaFadeSpeed * deltaTime; coronaFader = MAX(0, coronaFader); } baseAddr = origBaseAddr + starty * pitch; for (j = starty + 1; j < endy; j ++) { for (k = startx + 1; k < endx; k ++) { baseAddr[k] = table[gConst->kLightningRadiant - 1 - (short)((double)corona->values[(smidy + (midy - j)) * corona->dx + smidx + midx - k] * coronaFader)][baseAddr[k]]; } baseAddr += pitch; } surface->ReleaseSurface(); } void SwapBlackWhite(Graphic_file *gf) { for (long n = 0; n < gf->width * gf->height; n ++) if (gf->bitmap[n] == 0) gf->bitmap[n] = kWhiteColor; else if (gf->bitmap[n] == 255) gf->bitmap[n] = kBlackColor; } void CClutManager::FadeToColor(short direction, short effect, CGraphicSurface *surface) { short fadeCounter = 0; long lastFadeTime = 0; short pitch, height; unsigned char *baseAddr; long size; unsigned char **table = EffectToTable(effect); short j, k; short border, step; if (direction == kFadeFromColor) { border = gConst->kLightningRadiant; fadeCounter = 0; step = 1; }else{ border = -1; fadeCounter = gConst->kLightningRadiant -1; step = -1; } while (fadeCounter != border) { if (lastFadeTime < gSystem->GetTicks()) { lastFadeTime = gSystem->GetTicks() + gConst->kFadeTime / gConst->kLightningRadiant; gLevel->PaintLevel(); baseAddr = surface->GetSurfacePtr(&pitch); size = surface->width * surface->height; for (j = 0; j < surface->height; j ++) { for (k = 0; k < surface->width; k ++) { baseAddr[k] = table[fadeCounter][baseAddr[k]]; } baseAddr += pitch; } surface->ReleaseSurface(); surface->FlipToScreen(0, 0); fadeCounter += step; } } } amphetamine-0.8.10/src/Clut.hpp0100664000076400007640000000442507447311405015006 0ustar lukeluke#ifndef __AMP_CLUTMANAGER__ #define __AMP_CLUTMANAGER__ #include "AmpHead.hpp" #include "Surface.hpp" const short kMaxLuminosityLevel = 4; const short kNumOfCoronas = 3; const short kCoronaIDs[kNumOfCoronas] = {10000, 10001, 10002}; static short kCoronaDescriptor[kNumOfCoronas][5] = { {10000, 317, 543, 94, 92}, {10001, 382, 806, 126, 126}, {10002, 322, 802, 40, 40} }; enum { kLightningNoEffect, kLightningBlueEffect, kLightningRedEffect, kLightningGreenEffect, kLightningYellowEffect, kLightningPurpleEffect, kYellowCoronaTable, kWhiteCoronaTable, kBlueCoronaTable }; enum { kFadeToColor, kFadeFromColor }; struct tCorona { unsigned char *values; unsigned char **table; short dx, dy; }; class CClutManager { protected: RGBcolor palette[256]; unsigned char *luminosityTable[256]; unsigned char waterColorTable[256]; unsigned char lavaColorTable[256]; unsigned char shadowTable[256]; unsigned char fogTable[256]; unsigned char **transparentTable1; unsigned char **transparentTable2; unsigned char **transparentTable3; unsigned char **blueLightningTable; unsigned char **redLightningTable; unsigned char **greenLightningTable; unsigned char **yellowLightningTable; unsigned char **purpleLightningTable; unsigned char **whiteCoronaTable; unsigned char **yellowCoronaTable; unsigned char **blueCoronaTable; unsigned char *radiantTable; tCorona coronas[kNumOfCoronas]; unsigned char **EffectToTable(short effect); public: CClutManager(); ~CClutManager(); short FindClosestColor(unsigned char red, unsigned char green, unsigned char blue); void LoadPalette(RGBcolor *pal); void BuildLuminosityTable(); void CalculateCoronas(unsigned char *, short); unsigned char ChangeColorValues(unsigned char color, short percentageRed, short percentageGreen, short percentageBlue); void SetPixel(unsigned char *source, unsigned char *dest, short modus, short luminosity); void DrawLightning(double xm, double ym, short effect, CGraphicSurface *surface); void PrepareCorona(double xm, double ym, CGraphicSurface *surface); void DrawCorona(double xm, double ym, short corona, short effect, CGraphicSurface *surface, double &coronaFade, long deltaTime); void FadeToColor(short direction, short effect, CGraphicSurface *surface); }; void SwapBlackWhite(Graphic_file *gf); #endifamphetamine-0.8.10/src/ObjInfo.cpp0100664000076400007640000002020107447311405015406 0ustar lukeluke#include "ObjInfo.hpp" #include "Monster.hpp" #include "Monstrxx.hpp" #include "Player.hpp" #include "Item.hpp" #include "ShapeDes.hpp" #include "Appl.hpp" #include "Pltform.hpp" #include "ConstVal.hpp" #include "System.hpp" #include extern CApplication *gApplication; extern tConstValues *gConst; extern CSystem *gSystem; extern FILE *logFile; short *FindDescriptor(short id); CObjInfo::CObjInfo(short levelNumber) { MSG("LoadMonsters\n"); LoadMonsters(levelNumber); MSG("LoadItems\n"); LoadItems(levelNumber); MSG("LoadWeapons\n"); LoadWeapons(levelNumber); for (short n = 0; n < kNumPlatforms; n ++) platformInfo[n] = new tPlatformInfo; } CObjInfo::~CObjInfo() { short n; for (n = 0; n < kNumMonster; n ++) delete monsterInfo[n]; for (n = 0; n < kNumItems; n ++) delete itemInfo[n]; for (n = 0; n < kNumWeapons; n ++) delete weaponInfo[n]; for (n = 0; n < kNumPlatforms; n ++) delete platformInfo[n]; } void CObjInfo::LoadMonsters(short levelNumber) { if (!OpenDataFile(gSystem->QualifyDataDir(gConst->kFileMonster))) gSystem->Error("Cannot find file kFileMonster or unable to open it", 0); // by LL SetFilePos(levelNumber * kNumMonster * sizeof(tMonsterInfo)); for (short n = 0; n < kNumMonster; n ++) { monsterInfo[n] = new tMonsterInfo; ReadData(monsterInfo[n], sizeof(tMonsterInfo)); TRANS_PUT_NUM(monsterInfo[n]->canExplode); for (short m = 0; m < 3; m ++) { TRANS_PUT_NUM(monsterInfo[n]->moveShapes[m]); TRANS_PUT_NUM(monsterInfo[n]->additionalData[m]); TRANS_PUT_NUM(monsterInfo[n]->deathShapes[m]); } TRANS_PUT_NUM(monsterInfo[n]->touchBlessure); TRANS_PUT_NUM(monsterInfo[n]->additionalData[0]); TRANS_PUT_NUM(monsterInfo[n]->additionalData[1]); //TRANS_PUT_NUM(monsterInfo[n]->jumpShape); TRANS_PUT_NUM(monsterInfo[n]->attackShape); TRANS_PUT_NUM(monsterInfo[n]->unused); TRANS_PUT_NUM(monsterInfo[n]->kind); TRANS_PUT_NUM(monsterInfo[n]->speed); TRANS_PUT_NUM(monsterInfo[n]->energy); TRANS_PUT_NUM(monsterInfo[n]->weapon); TRANS_PUT_NUM(monsterInfo[n]->aggression); TRANS_PUT_NUM(monsterInfo[n]->invisible); } CloseDataFile(); } void CObjInfo::LoadItems(short levelNumber) { if (!OpenDataFile(gSystem->QualifyDataDir(gConst->kFileObjects))) gSystem->Error("Cannot find file kFileObjects or uable to open it", 0); // by LL SetFilePos(levelNumber * kNumItems * sizeof(tItemInfo)); for (short n = 0; n < kNumItems; n ++) { itemInfo[n] = new tItemInfo; ReadData(itemInfo[n], sizeof(tItemInfo)); TRANS_PUT_NUM(itemInfo[n]->iconID); TRANS_PUT_NUM(itemInfo[n]->data); TRANS_PUT_NUM(itemInfo[n]->flags); } CloseDataFile(); } void CObjInfo::LoadWeapons(short levelNumber) { if (!OpenDataFile(gSystem->QualifyDataDir(gConst->kFileWeapon))) gSystem->Error("Cannot find file kFileWeapon or unable to open it", 0); // by LL SetFilePos(levelNumber * kNumWeapons * sizeof(tWeaponInfo)); for (short n = 0; n < kNumWeapons; n ++) { weaponInfo[n] = new tWeaponInfo; ReadData(weaponInfo[n], sizeof(tWeaponInfo)); TRANS_PUT_NUM(weaponInfo[n]->art); TRANS_PUT_NUM(weaponInfo[n]->projectileShapes[0]); TRANS_PUT_NUM(weaponInfo[n]->projectileShapes[1]); for (short m = 0; m < 5; m ++) { TRANS_PUT_NUM(weaponInfo[n]->detonationShapes[m]); } TRANS_PUT_NUM(weaponInfo[n]->effect); TRANS_PUT_NUM(weaponInfo[n]->speed); TRANS_PUT_NUM(weaponInfo[n]->error); TRANS_PUT_NUM(weaponInfo[n]->repetition); TRANS_PUT_NUM(weaponInfo[n]->munition); TRANS_PUT_NUM(weaponInfo[n]->rad); TRANS_PUT_NUM(weaponInfo[n]->damage); } CloseDataFile(); } void CObjInfo::LoadPlatforms(short levelNumber) { if (!OpenDataFile(gSystem->QualifyDataDir(gConst->kFilePlatform))) gSystem->Error("Cannot find file kFilePlatform or unable to open it", 0); // by LL SetFilePos(levelNumber * kNumPlatforms * sizeof(tPlatformInfo)); for (short n = 0; n < kNumPlatforms; n ++) { ReadData(platformInfo[n], sizeof(tPlatformInfo)); TRANS_PUT_NUM2(platformInfo[n]->ID); TRANS_PUT_NUM2(platformInfo[n]->startx); TRANS_PUT_NUM2(platformInfo[n]->starty); TRANS_PUT_NUM2(platformInfo[n]->endx); TRANS_PUT_NUM2(platformInfo[n]->endy); TRANS_PUT_NUM2(platformInfo[n]->speed); TRANS_PUT_NUM2(platformInfo[n]->delay); TRANS_PUT_NUM2(platformInfo[n]->iconID); TRANS_PUT_NUM2(platformInfo[n]->refNum); //for (short m = 0; m < 8; m ++) TRANS_PUT_NUM2(platformInfo[n]->vars[m]); } } short *FindDescriptor(short id) { short n; for (n = 0; n < kNumShapes && id != kShapeDescriptor[n][0]; n++) {} if (n < kNumShapes) return kShapeDescriptor[n]; else{ for (n = 0; n < kNumTextures && id != kTextureDescriptor[n][0]; n++) {} if (n < kNumTextures) return kTextureDescriptor[n]; else return 0L; } } //----------------------------------------------------------------- CThing *CObjInfo::CreateMonster(short monsterNo, short j, short k) /* In: monsterNo: Number of monster in monster info table j, k: position in level elements Out: new monster object Creates a new monster object at position j, k (in level elements) */ { short *descriptor; if (monsterNo != -1) { descriptor = FindDescriptor(monsterInfo[monsterNo]->moveShapes[0]); switch (monsterInfo[monsterNo]->kind) { case kClassPlayer: return new CPlayer(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], monsterNo, monsterInfo[monsterNo]); break; case kClassCreeper: return new CCreeper(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], monsterNo, monsterInfo[monsterNo]); break; case kClassWalker: return new CWalker(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], monsterNo, monsterInfo[monsterNo]); break; case kClassJumper: return new CJumper(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], monsterNo, monsterInfo[monsterNo]); break; case kClassFlyer: return new CFlyer(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], monsterNo, monsterInfo[monsterNo]); break; case kClassWarg: return new CWarg(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], monsterNo, monsterInfo[monsterNo]); break; } } return 0L; } //------------------------------------------------------------------ CThing *CObjInfo::CreateItem(short itemNo, short j, short k) /* In: itemNo: Number of item in item info record j, k: position in level elements Out: new item object */ { short *descriptor; if (itemNo >= 0 && itemNo < kNumItems) { descriptor = FindDescriptor(itemInfo[itemNo]->iconID); switch (itemInfo[itemNo]->flags & 3) { case kClassBackgroundItem: return new CBackgroundItem(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], itemNo, itemInfo[itemNo]); break; case kClassUnpassableItem: return new CStaticItem(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], itemNo, itemInfo[itemNo]); break; case kClassMovableItem: return new CMovableItem(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], itemNo, itemInfo[itemNo]); break; case kClassPortableItem: return new CPortableItem(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], itemNo, itemInfo[itemNo], itemNo); break; } } return 0L; } void CObjInfo::CreatePlatforms() { short *descriptor; CThing *temp; for (short n = 0; n < kNumPlatforms; n ++) { if (platformInfo[n]->exists) { descriptor = FindDescriptor(platformInfo[n]->iconID); temp = new CPlatform(platformInfo[n]->startx * kElementSize + kElementSize / 2, platformInfo[n]->starty * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], n, platformInfo[n]); gApplication->platformTable[n] = (CPlatform *)temp; }else gApplication->platformTable[n] = 0L; } } short CObjInfo::GetMonsterType(short ref) { return (ref == -1 ? -1 : monsterInfo[ref]->kind); } tItemInfo *CObjInfo::GetItemInfo(short ref) { return (ref == -1 ? 0L : itemInfo[ref]); } tWeaponInfo *CObjInfo::FindWeapon(short ref) { return weaponInfo[ref]; } amphetamine-0.8.10/src/ObjInfo.hpp0100664000076400007640000000361007447311405015420 0ustar lukeluke#ifndef __AMP_THINGINFO__ #define __AMP_THINGINFO__ #include "File.hpp" #include "Thing.hpp" const short kNumMonster = 12; const short kNumItems = 42; const short kNumWeapons = 16; const short kNumPlatforms = 10; struct tMonsterInfo { Var2Bytes canExplode; Var2Bytes moveShapes[3]; Var2Bytes touchBlessure; Var2Bytes additionalData[2]; Var2Bytes jumpShape; Var2Bytes attackShape; Var1Byte unused; Var2Bytes deathShapes[3]; Var2Bytes kind; Var2Bytes speed; Var2Bytes energy; Var2Bytes weapon; Var2Bytes aggression; Var2Bytes invisible; }; struct tItemInfo { Var2Bytes iconID; Var2Bytes data; Var2Bytes flags; }; struct tWeaponInfo { Var2Bytes art; Var2Bytes projectileShapes[2]; Var2Bytes detonationShapes[5]; Var2Bytes effect; Var2Bytes speed; Var2Bytes error; Var2Bytes repetition; Var2Bytes munition; Var2Bytes rad; Var2Bytes damage; }; struct tPlatformInfo { Var1Byte exists; Var1Byte isElevator; Var2Bytes ID; Var2Bytes starty; Var2Bytes startx; Var2Bytes endy; Var2Bytes endx; Var2Bytes speed; Var2Bytes delay; Var2Bytes iconID; Var2Bytes refNum; Var1Byte playerControls; Var1Byte stopsAtStart; Var1Byte stopsAtEnd; Var1Byte delaysBeforeStart; Var1Byte hurts; Var1Byte returnsOnHit; Var1Byte activ; Var1Byte unused; }; class CObjInfo : public CFile { protected: void LoadMonsters(short levNum); void LoadItems(short levNum); void LoadWeapons(short levNum); public: tMonsterInfo* monsterInfo[kNumMonster]; tItemInfo* itemInfo[kNumItems]; tWeaponInfo* weaponInfo[kNumWeapons]; tPlatformInfo* platformInfo[kNumPlatforms]; CObjInfo(short levNum); ~CObjInfo(); void LoadPlatforms(short levNum); CThing *CreateMonster(short monsterNum, short j, short k); CThing *CreateItem(short itemNum, short j, short k); void CreatePlatforms(); short GetMonsterType(short ref); tItemInfo *GetItemInfo(short ref); tWeaponInfo *FindWeapon(short ref); }; #endifamphetamine-0.8.10/src/Player.cpp0100664000076400007640000003513307447311405015326 0ustar lukeluke#include "Player.hpp" #include "ShapeDes.hpp" #include "Appl.hpp" #include "ConstVal.hpp" #include "Gui.hpp" #include "Item.hpp" #include "SndSys.hpp" extern CApplication *gApplication; extern CSystem *gSystem; extern CShapeManager *gShapeManager; extern CObjInfo *gObjInfo; extern CLevel *gLevel; extern tConstValues *gConst; extern CGUI *gGUI; extern tConfigData *gConfigData; extern CSoundSystem *gSoundSystem; CPlayer::CPlayer(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo) : CMonster(initx, inity, width, height, number, monsterInfo) { short n; typeID |= kPlayer; xs += (dx - gConst->kPlayerWidth) / 2; xe -= (dx - gConst->kPlayerWidth) / 2; ys += 2; weight = 2; jumpTime = LONG_MAX; jumped = 0; for (short m = 0; m < 3; m ++) { playerMoveShapes[0][m] = moveShapes[m]; } attackShapes[0][0] = gShapeManager->FindShape(504, 0); attackShapes[0][1] = attackShapes[0][2] = 0L; jumpShapes[0] = jumpShape; for (n = 1; n < 8; n ++) { for (short m = 0; m < 3; m ++) { playerMoveShapes[n][m] = gShapeManager->FindShape(500 + n * 10 + m, 0); attackShapes[n][m] = gShapeManager->FindShape(504 + n * 10 + m, 0); } jumpShapes[n] = gShapeManager->FindShape(503 + n * 10, 0); } unused = weapon; weapons[0] = new CHandWeapon(this, gObjInfo->FindWeapon(0), attackShapes[0][0], attackShapes[0][1], attackShapes[0][2]); weapons[1] = new CWeapon(this, gObjInfo->FindWeapon(1), attackShapes[1][0]); weapons[2] = new CSorcery(this, gObjInfo->FindWeapon(2), attackShapes[2][0]); weapons[3] = new CWeapon(this, gObjInfo->FindWeapon(3), attackShapes[3][0]); weapons[4] = new CHandWeapon(this, gObjInfo->FindWeapon(4), attackShapes[4][0], attackShapes[4][1], attackShapes[4][2]); weapons[5] = new CMultiBulletWeapon(this, gObjInfo->FindWeapon(5), attackShapes[5][0], gConst->kFirehandAngle); weapons[6] = new CBomb(this, gObjInfo->FindWeapon(6), attackShapes[6][0], attackShapes[3][1]); weapons[7] = new CStaff(this, gObjInfo->FindWeapon(7), attackShapes[7][0], attackShapes[7][1]); weapon = weapons[0]; for (n = 0; n <= 7; n ++) weapons[n]->weaponNumber = n; teleportCounter = -1; lastOxygenDecTime = 0; lastWeaponChanging = 0; // by LL lastActionTime = 0; // by LL // teleportRefNum = 0; ? by LL lastOxygenDecTime = 0; // by LL lastPickupTime = 0; currentWeapon = 0; weapons[0]->weaponStatus = kWeaponReady; oxygen = gConst->kInitialOxygen; } CPlayer::~CPlayer() { for (short n = 1; n < 8; n ++) delete weapons[n]; } short CPlayer::Think() { CElement *element; short action; short liquid; double currentSpeed; CObject::Think(); if (gApplication->firstPlayRound) OnStart(); Gravitation(); element = gLevel->GetElement(xm, ym); if (element) liquid = element->GetElementLiquid(); else liquid = kShapemodusNormal; if (dieFrame == -1) { currentSpeed = (gSystem->KeyPressed(gConfigData->runKey) && lastCollisionCode & kCollisionOnBottom ? info->speed * gConst->kRunScaleFactor : info->speed) * gConst->kVelocityUnit * deltaTime; if (gSystem->KeyPressed(gConfigData->leftKey)) { if (forceVectorX > -currentSpeed) forceVectorX -= gConst->kPlayerAcceleration * deltaTime; lookDirection = kLookingLeft; } if (gSystem->KeyPressed(gConfigData->rightKey)) { if (forceVectorX < currentSpeed) forceVectorX += gConst->kPlayerAcceleration * deltaTime; lookDirection = kLookingRight; } if (gSystem->KeyPressed(gConfigData->jumpKey)) { if (liquid == kShapemodusWater || liquid == kShapemodusLava) { if (forceVectorY > -info->speed * gConst->kVelocityUnit * deltaTime) forceVectorY = -gConst->kPlayerLiquidAccel * deltaTime; if (!gSoundSystem->playerDive->isPlaying()) gSoundSystem->Play(gSoundSystem->playerDive, xm, ym); }else if (jumpTime > lastTime){ forceVectorY = -gConst->kJumpVelocity * gConst->kVelocityUnit * deltaTime; if (!jumped) gSoundSystem->Play(gSoundSystem->playerJump, xm, ym); jumped = 1; } }else jumpTime = 0; if (gSystem->KeyPressed(gConfigData->shootKey)) { weapons[currentWeapon]->Shoot(lookDirection == kLookingRight ? 1 : -1, 0, 0); gGUI->UpdateWeapon(); } if (gSystem->KeyPressed(gConfigData->prevWeaponKey) && lastTime > lastWeaponChanging) { do { currentWeapon ++; if (currentWeapon > 7) currentWeapon = 0; } while (weapons[currentWeapon]->weaponStatus != kWeaponReady); lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; gGUI->UpdateWeapon(); } if (gSystem->KeyPressed(gConfigData->nextWeaponKey) && lastTime > lastWeaponChanging) { do { currentWeapon --; if (currentWeapon < 0) currentWeapon = 7; } while (weapons[currentWeapon]->weaponStatus != kWeaponReady); lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; gGUI->UpdateWeapon(); } if (gSystem->KeyPressed(gConfigData->activateKey) && lastActionTime < lastTime) { PerformAction(); lastActionTime = lastTime + gConst->kActionDelayTime; } if (gSystem->KeyPressed(gConfigData->weapon1Key) && weapons[0]->weaponStatus == kWeaponReady && lastTime > lastWeaponChanging) { currentWeapon = 0; gGUI->UpdateWeapon(); lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; } if (gSystem->KeyPressed(gConfigData->weapon2Key) && weapons[1]->weaponStatus == kWeaponReady && lastTime > lastWeaponChanging) { currentWeapon = 1; gGUI->UpdateWeapon(); lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; } if (gSystem->KeyPressed(gConfigData->weapon3Key) && weapons[2]->weaponStatus == kWeaponReady && lastTime > lastWeaponChanging) { currentWeapon = 2; gGUI->UpdateWeapon(); lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; } if (gSystem->KeyPressed(gConfigData->weapon4Key) && weapons[3]->weaponStatus == kWeaponReady && lastTime > lastWeaponChanging) { currentWeapon = 3; gGUI->UpdateWeapon(); lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; } if (gSystem->KeyPressed(gConfigData->weapon5Key) && weapons[4]->weaponStatus == kWeaponReady && lastTime > lastWeaponChanging) { currentWeapon = 4; gGUI->UpdateWeapon(); lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; } if (gSystem->KeyPressed(gConfigData->weapon6Key) && weapons[5]->weaponStatus == kWeaponReady && lastTime > lastWeaponChanging) { currentWeapon = 5; gGUI->UpdateWeapon(); lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; } if (gSystem->KeyPressed(gConfigData->weapon7Key) && weapons[6]->weaponStatus == kWeaponReady && lastTime > lastWeaponChanging) { currentWeapon = 6; gGUI->UpdateWeapon(); lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; } if (gSystem->KeyPressed(gConfigData->weapon8Key) && weapons[7]->weaponStatus == kWeaponReady && lastTime > lastWeaponChanging) { currentWeapon = 7; gGUI->UpdateWeapon(); lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; } if (liquid == kShapemodusWater || liquid == kShapemodusLava) { oxygen -= gConst->kOxygenDecrease * deltaTime; } if (liquid == kShapemodusLava) OnDamage(gConst->kLavaDamage); } if (liquid == kShapemodusWater || liquid == kShapemodusLava) { forceVectorX *= gConst->kLiquidFriction; forceVectorY *= gConst->kLiquidFriction; } if (element) element->PassiveAction(); return kNoEvent; } // ------------------------------------------------ void CPlayer::PerformAction() // Performs the action which is returned by CElement::Action { short action = 0; CElement *element = gLevel->GetElement(xm, ym); if (element) action = element->Action(); if (action & kTeleportMask) { // Player used a teleporter teleportCounter = 0; teleportRefNum = element->refNum; teleportDeltaTime = lastTime; currentJob = kJobTeleporting; } if (action & kExitMask) gApplication->command = kCmdNextLevel; } short CPlayer::Forces() { short collisionObject, collisionCode; CObject::Forces(); lastCollisionCode = ExertForce(resForceX, resForceY, collisionObject, 0L); if (lastCollisionCode & kCollisionOnBottom) { jumpTime = lastTime + gConst->kJumpAccelerationTime; jumped = 0; } if (lastCollisionCode & kCollisionOnTop) { jumpTime = 0; forceVectorY = 0; } if (lastCollisionCode & (kCollisionOnLeft | kCollisionOnRight)) forceVectorX = 0; return kNoEvent; } void CPlayer::Move() { moveShapes[0] = playerMoveShapes[currentWeapon][0]; moveShapes[1] = playerMoveShapes[currentWeapon][1]; moveShapes[2] = playerMoveShapes[currentWeapon][2]; jumpShape = jumpShapes[currentWeapon]; weapon = weapons[currentWeapon]; CMonster::Move(); } void CPlayer::OnStart() { gGUI->UpdateWeapon(); } // ------------------------------------ void CPlayer::OnTeleport() // Teleport event, sent by CMonster::Render { if (currentJob == kJobTeleporting) { CElement *element = gLevel->FindRefnum(teleportRefNum); if (element) { element->Teleport(xs, ys); xe = xs + dx; ye = ys + dy; } } } void CPlayer::GetItAll() // cheat { int i; for (i = 0; i < 7; ++i) { //if (weapons[i]->weaponStatus != kWeaponReady) currentWeapon = i; weapons[i]->weaponStatus = kWeaponReady; weapons[i]->AddMunition(100); oxygen += 100; oxygen = MIN(oxygen, gConst->kInitialOxygen); health += 100; health = MIN(health, info->energy); } } void CPlayer::OnTouch(CObject *touch) { short value; short what; if (touch->typeID & kPortableItem) { what = ((CPortableItem *)touch)->PickMeUp(value); gSoundSystem->Play(gSoundSystem->playerPickup, xm, ym); switch (what) { case kItemSword: if (weapons[0]->weaponStatus != kWeaponReady) currentWeapon = 0; weapons[0]->weaponStatus = kWeaponReady; weapons[0]->AddMunition(0); break; case kItemPhiol: if (weapons[1]->weaponStatus != kWeaponReady) currentWeapon = 1; weapons[1]->weaponStatus = kWeaponReady; weapons[1]->AddMunition(gObjInfo->GetItemInfo(kItemPhiolmun)->data); break; case kItemSorcery: if (weapons[2]->weaponStatus != kWeaponReady) currentWeapon = 2; weapons[2]->weaponStatus = kWeaponReady; weapons[2]->AddMunition(gObjInfo->GetItemInfo(kItemSorcerymun)->data); break; case kItemBow: if (weapons[3]->weaponStatus != kWeaponReady) currentWeapon = 3; weapons[3]->weaponStatus = kWeaponReady; weapons[3]->AddMunition(gObjInfo->GetItemInfo(kItemBowmun)->data); break; case kItemScie: if (weapons[4]->weaponStatus != kWeaponReady) currentWeapon = 4; weapons[4]->weaponStatus = kWeaponReady; weapons[4]->AddMunition(0); break; case kItemHands: if (weapons[5]->weaponStatus != kWeaponReady) currentWeapon = 5; weapons[5]->weaponStatus = kWeaponReady; weapons[5]->AddMunition(gObjInfo->GetItemInfo(kItemHandsmun)->data); break; case kItemBomb: if (weapons[6]->weaponStatus != kWeaponReady) currentWeapon = 6; weapons[6]->weaponStatus = kWeaponReady; weapons[6]->AddMunition(gObjInfo->GetItemInfo(kItemBombmun)->data); break; case kItemStaff: if (weapons[7]->weaponStatus != kWeaponReady) currentWeapon = 7; weapons[7]->weaponStatus = kWeaponReady; weapons[7]->AddMunition(gObjInfo->GetItemInfo(kItemStaffmun)->data); break; case kItemPhiolmun: weapons[1]->AddMunition(value); break; case kItemSorcerymun: weapons[2]->AddMunition(value); break; case kItemBowmun: weapons[3]->AddMunition(value); break; case kItemSciemun: weapons[4]->AddMunition(value); break; case kItemHandsmun: weapons[5]->AddMunition(value); break; case kItemBombmun: weapons[6]->AddMunition(value); break; case kItemStaffmun: weapons[7]->AddMunition(value); break; case kItemOxygen: oxygen += value; oxygen = MIN(oxygen, gConst->kInitialOxygen); break; case kItemHelppacket: health += value; health = MIN(health, info->energy); break; } lastPickupTime = lastTime + gConst->kPickupTime; gGUI->UpdateWeapon(); gGUI->OnPickUpSomething(what); } } void CPlayer::OnDamage(short blessure) { gSoundSystem->Play(gSoundSystem->firestoneDamage, xm, ym); CMonster::OnDamage(blessure); } void CPlayer::SaveDataToNextLevel(tPlayerData *playerData) { for (short n = 0; n <= 7; n ++) weapons[n]->SaveDataToNextLevel(&(playerData->munition[n]), &(playerData->weaponStatus[n])); playerData->currentWeapon = currentWeapon; playerData->health = health; playerData->oxygen = oxygen; } void CPlayer::RestoreDataFromNextLevel(tPlayerData *savedData) { currentWeapon = savedData->currentWeapon; oxygen = savedData->oxygen; health = savedData->health; for (short n = 0; n <= 7; n ++) { weapons[n]->RestoreDataFromPrevLevel(savedData->munition[n], savedData->weaponStatus[n]); } } CCamera::CCamera(short initx, short inity, short width, short height, short thingNumber) : CThing(initx, inity, width, height, thingNumber) { typeID |= kCamera; weightless = 1; gApplication->Enqueue(&gApplication->thingList, this); gApplication->Enqueue(&gApplication->renderQueue, this); } CCamera::~CCamera() { gApplication->Dequeue(&gApplication->thingList, this); gApplication->Dequeue(&gApplication->renderQueue, this); } short CCamera::Forces() { if (xm < kLevelWidth * kElementSize - kGamePlaneWidth / 2) forceVectorX = gConst->kCameraSpeed * deltaTime * gConst->kVelocityUnit; else forceVectorX = 0; return kNoEvent; } short CCamera::Think() { CElement *element; CObject::Think(); element = gLevel->GetElement(xm, ym); if (element && element->GetElementLiquid() == kShapemodusFog) { currentMessage = gConst->kMonsterNames[element->data -1]; msgY = kGamePlaneHeight; } msgY -= gConst->kMonsterNameSpeed * deltaTime * gConst->kVelocityUnit; return kNoEvent; } void CCamera::Move() { xm += forceVectorX; } void CCamera::Render(short planeX, short planeY, tRect *clipRect) { if (msgY > -kElementSize) gApplication->plane->DrawString(gConst->kMonsterNameX, (short)msgY, currentMessage, kShapemodusNormal); } short CPlayer::Write(FILE *f) { long size = 0; WRITEDATA(size); WRITEDATA(typeID); WRITEDATA(thingNumber); weapon = unused; size += CMonster::Write(f); weapon = unused; for (short n = 0; n < 8; n ++) { size += weapons[n]->Write(f); } WRITEDATA(jumpTime); WRITEDATA(currentWeapon); WRITEDATA(lastWeaponChanging); WRITEDATA(lastPickupTime); WRITEDATA(lastActionTime); WRITEDATA(teleportRefNum); WRITEDATA(currentJob); WRITEDATA(oxygen); WRITEDATA(lastOxygenDecTime); FINISHWRITE; return size; } void CPlayer::Read(FILE *f) { long size = 0; READDATA(size); READDATA(typeID); READDATA(thingNumber); CMonster::Read(f); for (short n = 0; n < 8; n ++) { weapons[n]->Read(f); } READDATA(jumpTime); READDATA(currentWeapon); READDATA(lastWeaponChanging); READDATA(lastPickupTime); READDATA(lastActionTime); READDATA(teleportRefNum); READDATA(currentJob); READDATA(oxygen); READDATA(lastOxygenDecTime); }amphetamine-0.8.10/src/Player.hpp0100664000076400007640000000251707447323020015327 0ustar lukeluke#ifndef __AMP_PLAYER__ #define __AMP_PLAYER__ #include "Monster.hpp" #include "SoundList.hpp" enum { kJobTeleporting, kJobExiting }; class CGUI; struct tPlayerData; class CPlayer : public CMonster { friend class CGUI; protected: CShape *playerMoveShapes[8][3]; CShape *jumpShapes[8]; CShape *attackShapes[8][3]; CWeapon *weapons[8]; CWeapon *unused; CSound *jumpSound; long jumpTime; short jumped; short currentWeapon; long lastWeaponChanging; long lastPickupTime; long lastActionTime; short teleportRefNum; short currentJob; void PerformAction(); void OnTeleport(); double oxygen; long lastOxygenDecTime; void OnStart(); public: CPlayer(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo); ~CPlayer(); short Forces(); void Move(); short Think(); void OnTouch(CObject *touch); void OnDamage(short blessure); void SaveDataToNextLevel(tPlayerData *); void RestoreDataFromNextLevel(tPlayerData *); short Write(FILE *f); void Read(FILE *f); // cheat void GetItAll(); }; class CCamera : public CThing { private: char *currentMessage; double msgY; public: CCamera(short initx, short inity, short width, short height, short number); ~CCamera(); short Forces(); void Move(); short Think(); void Render(short planeX, short planeY, tRect *clipRect); }; #endifamphetamine-0.8.10/src/Graphfil.cpp0100664000076400007640000000735307447311405015631 0ustar lukeluke /* ** MacWT -- a 3d game engine for the Macintosh ** © 1995, Bill Hayden and Nikol Software ** ** On the Internet: ** bmoc1@aol.com (my personal address) ** nikolsw@grove.ufl.edu (my school address) ** MacWT anonymous FTP site: ftp.circa.ufl.edu/pub/software/ufmug/mirrors/LocalSW/Hayden/ ** http://grove.ufl.edu:80/~nikolsw (my WWW page, containing MacWT info) ** ** based on wt, by Chris Laurel (claurel@mr.net) ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include #include //#include "wt.h" //#include "gApplication->system->Error.h" //#include "wtmem.h" //#include "color.h" #include "Graphfil.hpp" #include "Appl.hpp" extern CApplication *gApplication; extern CSystem *gSystem; #define mfputc fputc #define mfgetc fgetc #define mfopen fopen #define mfclose fclose #define mfread fread #define mfseek fseek #define mftell ftell #define mrewind rewind #define mfprintf fprintf /* MAGIC_LENGTH must be the length of the longest MAGIC string. */ #define MAGIC_LENGTH 5 #define GIF_MAGIC "GIF87" #define GIF89_MAGIC "GIF89" extern Graphic_file *LoadGIF(FILE *fp, char *filename); static Graphic_file_format check_format(FILE *fp, char *filename); Graphic_file *new_graphic_file() { Graphic_file *gf = (Graphic_file *)wtmalloc(sizeof(Graphic_file)); gf->transparent_entry = -1; return gf; } void free_graphic_file(Graphic_file *gfile) { if (gfile != NULL) { if (gfile->palette != NULL) wtfree(gfile->palette); if (gfile->bitmap != NULL) wtfree(gfile->bitmap); } wtfree(gfile); } /* Return 0 if the pixel is transparent, 1 if it is opaque. In any ** case, stuff dest with the pixel RGB value. */ short graphic_file_pixel(Graphic_file *gfile, int x, int y, RGBcolor *rgb) { if (gfile->type == gfPaletted) { int index; index = gfile->bitmap[y * gfile->width + x]; if (index == gfile->transparent_entry) return 0; else { *rgb = gfile->palette[index]; return 1; } } else { unsigned char *pixel = gfile->bitmap + (y * gfile->width + x) * 3; rgb->red = *pixel++; rgb->green = *pixel++; rgb->blue = *pixel; /* For now, let pure cyan be the transparent color for 1 color images. */ if (rgb->red == 0 && rgb->green == 255 && rgb->blue == 255) return 0; else return 1; } } Graphic_file *read_graphic_file(char *filename) { FILE *fp; Graphic_file_format format; Graphic_file *gfile = 0L; if ((fp = mfopen(filename, "rb")) == NULL) gSystem->Error("Could not open texture", 0); format = check_format(fp, filename); mrewind(fp); switch (format) { case formatGIF89: case formatGIF87: gfile = LoadGIF(fp, filename); break; case formatUnknown: gSystem->Error("Unknown graphic file format.", 0); break; default: gSystem->Error("The graphic file reading code is really broken.", 0); break; } if (gfile == NULL) gSystem->Error("gApplication->system->Error reading texture", 0); mfclose(fp); return gfile; } static Graphic_file_format check_format(FILE *fp, char *filename) { char magic[MAGIC_LENGTH]; #if __MWERKS__ || __THINKC__ // to read PICT or PICTR files, which are further along on the // evolutionary chain than to need MagicCookies or the like. mfread(magic, 1, MAGIC_LENGTH, fp); #else if (mfread(magic, 1, MAGIC_LENGTH, fp) != MAGIC_LENGTH) gSystem->Error("gApplication->system->Error reading texture", 0); #endif if (strncmp(magic, GIF_MAGIC, sizeof(GIF_MAGIC) - 1) == 0) return formatGIF87; else if (strncmp(magic, GIF89_MAGIC, sizeof(GIF89_MAGIC) - 1) == 0) return formatGIF89; else return formatPICTR; // return formatUnknown; } amphetamine-0.8.10/src/Graphfil.hpp0100664000076400007640000000352007447311405015626 0ustar lukeluke/* ** wt -- a 3d game engine ** ** Copyright (C) 1994 by Chris Laurel ** email: claurel@mr.net ** snail mail: Chris Laurel, 5700 W Lake St #208, St. Louis Park, MN 55416 ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "AmpHead.hpp" #include "System.hpp" #ifndef __GRAPHFIL__ #define __GRAPHFIL__ typedef enum { formatGIF87, formatGIF89, formatPPM, formatPICTR, formatUnknown } Graphic_file_format; typedef enum { gfTrueColor, gfPaletted } Graphic_file_type; typedef struct { Graphic_file_type type; int height, width; int palette_entries; long transparent_entry; RGBcolor *palette; unsigned char *bitmap; } Graphic_file; void *wtmalloc(size_t size); void *wtrealloc(void *v, size_t size); void wtfree(void *v); void FatalerFehler(char *errorStr, long error); extern Graphic_file *new_graphic_file(void); extern void free_graphic_file(Graphic_file *gfile); extern short graphic_file_pixel(Graphic_file *gfile, int x, int y, RGBcolor *rgb); extern Graphic_file *read_graphic_file(char *filename); Graphic_file *LoadPPM(FILE *fp, char *filename); Graphic_file *LoadGIF(FILE *fp, char *fname ); Graphic_file *LoadPICTR(FILE *fp, char *fname ); #endifamphetamine-0.8.10/src/ShapeLd.cpp0100664000076400007640000000447507447311405015417 0ustar lukeluke#include "ShapeLd.hpp" #include "Graphfil.hpp" #include "Appl.hpp" #include "Clut.hpp" #include "ShapeDes.hpp" #include "ConstVal.hpp" #include extern CApplication *gApplication; extern CSystem *gSystem; extern CClutManager *gClutManager; extern tConstValues *gConst; extern CClutManager *gClutManager; extern FILE *logFile; CShapeManager::CShapeManager() { } CShapeManager::~CShapeManager() { } void CShapeManager::LoadShapes() { short n; Graphic_file *plane; MSG("Opening shape file\n"); plane = read_graphic_file(gSystem->QualifyDataDir(gConst->kFileShapes)); // by LL if (!plane) gSystem->Error("Cannot find kFileShapes or cannot open it. Perhaps lack of memory?", 0); MSG("Creating shapes and textures\n"); for (n = 0; n < kNumShapes; n ++) { shapes[n] = new CMaskedShape(plane->bitmap, &kShapeDescriptor[n][0], plane->width); } for (n = 0; n < kNumTextures; n ++) { for (short m = 0; m < 4; m ++) { textures[n][m] = new CTexture(plane->bitmap, &kTextureDescriptor[n][0], plane->width, m); } } gClutManager->CalculateCoronas(plane->bitmap, plane->width); free_graphic_file(plane); } void CShapeManager::UnloadShapes() { short n; for (n = 0; n < kNumShapes; n ++) { delete shapes[n]; } for (n = 0; n < kNumTextures; n ++) { for (short m = 0; m < 4; m ++) { delete textures[n][m]; } } } void CShapeManager::LoadBackground(char *background) { MSG("Opening background image\n"); backgroundPicture = read_graphic_file(gSystem->QualifyDataDir(background)); if (!backgroundPicture) gSystem->Error("Cannot open background file. Lack of memory?", 0); SwapBlackWhite(backgroundPicture); } void CShapeManager::UnloadBackground() { free_graphic_file(backgroundPicture); } CShape* CShapeManager::FindShape(short id, short light) { short n; if (id == -1) return NULL; else { if (id >= kTextureStart && id <= kTextureEnd) { for (n = 0; n < kNumTextures && kTextureDescriptor[n][0] != id; n ++) {} if (n != kNumTextures) return textures[n][light]; else return 0L; }else{ for (n = 0; n < kNumShapes && kShapeDescriptor[n][0] != id; n ++) {} if (n != kNumShapes) return shapes[n]; else return 0L; } } } unsigned char *CShapeManager::GetBackground(short &width, short &height) { width = backgroundPicture->width; height = backgroundPicture->height; return backgroundPicture->bitmap; }amphetamine-0.8.10/src/ShapeLd.hpp0100664000076400007640000000134307447311405015413 0ustar lukeluke#ifndef __AMP_SHAPEMANAGER__ #define __AMP_SHAPEMANAGER__ #include "System.hpp" #include "Shape.hpp" #include "Graphfil.hpp" enum { kTotalShapes = 336, kTextureStart = 3000, kTextureEnd = 3054, kNumTextures = 45, kNumShapes = kTotalShapes - kNumTextures, kAddPlayerStart = 510, kAddPlayerEnd = 574 }; class CShapeManager { protected: CShape *shapes[kNumShapes]; CShape *textures[kNumTextures][4]; unsigned char *coronas; Graphic_file *backgroundPicture; public: CShapeManager(); ~CShapeManager(); void LoadShapes(); void LoadBackground(char *name); void UnloadShapes(); void UnloadBackground(); CShape *FindShape(short id, short light); unsigned char *GetBackground(short &width, short &height); }; #endif amphetamine-0.8.10/BUGS0100664000076400007640000000167307447661355013300 0ustar lukelukeKNOWN PROBLEMS - Clipping sometimes fails, i.e. you can walk through walls or get stuck - There's a problem with flying monsters. They sometimes get stuck in the wall or will stick at the top of the screen an won't go away until a new level is entered. Sometimes, the game gets completely corrupted; the player may end up in the wall with the monster and die. - There is a problem with C++ destructors not being called because they are not declared "virtual" when the actually should. E.g. in CApplication::UnloadLevelData(), instances of different subclasses of CThing are deleted through a CThing pointer; as a result only CThing::~CThing() is actually called, but not the destructor of the actual subclasses. Unfortunately, there seem to be bugs in some of those destructors. When just declaring CThings's of even CObject's destructor virtual, the game becomes very unstable and crashes on changing between different levels. amphetamine-0.8.10/NEWS0100664000076400007640000000240407447660603013300 0ustar lukelukeMarch 25th, 2002, 0.8.10 - Fixed the bug where monsters just froze after playing a while. - Endianness autodetected by SDL - Minor bugfixes September 17th, 2001, 0.8.9 - Fixed compilation bug under Linux Mandrake 8.0 (gcc 2.96) - Simplified configuration of the build process February 27th, 2000, 0.8.8 - Compiles smoother with SDL 1.0 - Using sdl-config in the Makefile - Minor bugfixes November 18th, 1999, 0.8.7 - An old version of ObjInfo.cpp was included with version 0.8.6, that prevented the game from running on big-endian machines. November 11th, 1999: 0.8.6 - Compiles and works under SPARC/Solaris Check the TARGET_ARCH variable in the Makefile! October 30th, 1999: 0.8.5 - Compiles without libXpm (no icon) October 18th, 1999: 0.8.4 - Even cleaner sound system :) September 4th, 1999: 0.8.3 - Fixed a bug that crashed the game in some situations if you had no sound card. September 3rd, 1999: 0.8.2 - Fixed some bugs in ObjInfo.cpp and ShapeLd.cpp that prevented compilation with gcc 2.95 (thanks to Ralph Giles and Bernhard Trummer)). - More fixes to the sound system - New command line options (try --help) - DGA support (option --fullscreen) July 16th, 1999: 0.8.1 - Fixed some bug in the sound system - Added some cheats (unsupported) - Added an icon amphetamine-0.8.10/amph.xpm0100664000076400007640000000672107447311405014253 0ustar lukeluke/* XPM */ static char * amph_xpm[] = { "48 48 66 1", " c None", ". c #FFCC66", "+ c #FFCC99", "@ c #FF9966", "# c #CC9966", "$ c #CC9933", "% c #996633", "& c #663333", "* c #996666", "= c #666633", "- c #555555", "; c #993333", "> c #FFCC33", ", c #FF9933", "' c #444444", ") c #CCCC66", "! c #666666", "~ c #220000", "{ c #FFFF66", "] c #330000", "^ c #111111", "/ c #CC6633", "( c #110000", "_ c #222222", ": c #FFFF99", "< c #CC6666", "[ c #993366", "} c #333300", "| c #663300", "1 c #333333", "2 c #CC9900", "3 c #996600", "4 c #66FFCC", "5 c #66FFFF", "6 c #66CCCC", "7 c #000000", "8 c #CCFFFF", "9 c #DDDDDD", "0 c #336600", "a c #004400", "b c #003300", "c c #666600", "d c #005500", "e c #006600", "f c #CC3333", "g c #007700", "h c #999999", "i c #CC9999", "j c #66CC66", "k c #999966", "l c #99FFFF", "m c #FFCCCC", "n c #002200", "o c #BBBBBB", "p c #001100", "q c #CCCC99", "r c #CCCCCC", "s c #888888", "t c #CC99CC", "u c #996699", "v c #EEEEEE", "w c #FFFFFF", "x c #440000", "y c #AAAAAA", "z c #FF9999", "A c #CC3366", ".+................@@@.#.@#$$%&&*&=&-;-&&%*;%*%-;", ".......+.+.+.+......>....,#@%'=*%*&%-&=*;=%;%;%%", "..............)@).@.@.@$,#,$%&*%*%!;%*~~~~~%*%*%", "+......+.+{+....+.....,@@,$@#*%*%%%*]~-&^~^~~%;*", "....++........+.$$/$#)@#,$//$/*;%;*~~~~(_~~(~~*%", "..+++{+.+.+.+:..@@#$@,,$<%<*%%%%[&;]]}|]|1~~~~%;", "....+.+........#/%/<$. The Unix/SDL version is maintained by Lukas Loehrer REQUIREMENTS SDL (Simple DirectMedia Layer) version >= 1.0 Get it from: http://www.devolution.com/~slouken/projects/SDL/index.html CONTROLS left/right arrows move left control fire space bar jump tab action (press buttons) ESC menu ALT+s screenshot You can customize most controls by copying the file user.conf from the Amphetamine data directory to your ~/.amph directory. Modify it to suit your needs. GAMEPLAY Many aspect of the gameplay are controlled by the file amph.conf in the main Amphetamine directory. Of most interest are the options right at the beginning of the file that control the physics. If the game seems to slow/fast to you, changing some of those values may help. DGA MODE Use the option --fullscreen to enable DGA fullscreen support. I cannot test this myself, because my X Server does not support it properly. I am grateful for any feedback regarding this option. SPARC/Solaris I was told that Amphetamine runs very slow on some SPARC machines. LICENCE This program is licensed under the terms of the GNU GPL, a copy of which you should have received with this package. PLANS - Fixing the clipping bugs - Fixing the strange bug involving flying monsters amphetamine-0.8.10/mkinstalldirs0100775000076400007640000000133406707243101015374 0ustar lukeluke#! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain # $Id: mkinstalldirs,v 1.10 1996/05/03 07:37:52 friedman Exp $ errstatus=0 for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" 1>&2 mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here amphetamine-0.8.10/INSTALL0100664000076400007640000000171707447576715013652 0ustar lukeluke1. Make sure SDL is installed correctly. 2. Have a look at the 'Makefile' and edit it where appropriate. - 'USE_LIB_XPM=FALSE' if you don't have libXpm 3. Type 'make'. This should build the Amphetamine binary. You can safely ignore the numerous warnings. If the compilation fails, you are in in trouble. Try to tweak the 'Makefile'. You have to delete '-funroll-loops' if you are still using gcc 2.7.2.3 4. Become root and type 'make install'. This will install the binary to the directory specified in the makefile (default is '/usr/local/games/amph'). It will also create a symbolic link. 5. You have managed the difficult bit. Now, you have to install the data files required by the game. Get 'amphetamine-${VERSION}.tar.bz' an do: - cd /usr/local/games - bzip2 -cd ~/amphetamine-data-0.8.tar.bz | tar xv (Note: the exact commands depend on your syste configuration) 6. type 'amph' in order to run the game and have fun! amphetamine-0.8.10/ChangeLog0100664000076400007640000000365507447660716014371 0ustar lukelukeMarch 25th, 2002: Shape.cpp, Surface.cpp: - included System.hpp, Makefile: Endianness is now autodetected through SDL_BYTEORDER, so there is no need for the BYTE_ORDER variable in the Makefile anymore. Object.cpp, Things.cpp, Monster.cpp, Monstrxx.cpp: Initialize some more member variables in the constructors, especially in Monstrxx.cpp. Some of the variables where indeed uninitialized, e.g. "lastShoot", "currentShootDelay", and "nextShootTime". These changes fix the bug where mosters just seem to freeze and don't move and shoot despite being "alive". September 17th, 2001: Level.cpp: - included . Amphetamine should now compile under Linux Mandrake 8.0. March 27th, 2001: Endianess is now controlled by a seperate variable "BYTE_ORDER", which can be set to either "LITTLE_ENDIAN" (the default) or "BIG_ENDIAN". -------------------------------------------------------------------------- CMaskedShape::Encode(), CMaskedShape::RenderShapeClipped() CMaskedShape::RenderShapeUnclipped() These functions make must read/write 4-byte words at unaligned memory locations. To avoid problems on architectures that require strict alignment, the macros SET_LONG and GET_LONG perform slow byte-wise access by default. If you are on IA-32 and "make" detects this, the macro __OPT_MEM_ACCESS__ will be defined to enable faster versions of SET_LONG and GET_LONG. -------------------------------------------------------------------------- Surface.cpp: CGraphicSurface::PaintGraphic() - replaced alignment dependent memory copy code by a call to "memcpy", because it's fast enough and simpler this way Shape.cpp: CTexture::RenderShape() and CBackground::RenderShape() - replaced alignment dependent memory copy code by a call to "memcpy", because it's fast enough and simpler this way System.cpp/.hpp: - removed support for libsge amphetamine-0.8.10/COPYING0100644000076400007640000003545106560014640013627 0ustar lukeluke GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS