#include "../entity.h" #include "../item.h" #include "../layers.h" #include #define OLC_PGE_APPLICATION #include "../pixelGameEngine.h" #define OLC_PGEX_SPLASHSCREEN #include "../splash.h" #define OLC_SOUNDWAVE #include "../defines.h" #include "../soundwaveEngine.h" #include "../tiles.h" #include "../references.h" #include "../states.h" #include "../flags.h" #include #include "../cutscene.h" #include "../encounters.h" #include "../particle.h" #include "../effect.h" #include "../battleproperty.h" #include "test.h" #include "../SeasonI.h" #include "../map.h" #define TestWhileMax(testname,condition,maxIterations) _TestWait(testname);while(_TestResolve(condition,maxIterations)) #define TestWhile(testname,condition) TestWhileMax(testname,condition,1000) extern int frameCount; extern double CUTSCENE_FADE_VALUE; extern Cutscene*CurrentCutscene; extern ActionType CurrentAction; extern vd2d cameraPos; extern bool messageBoxVisible; extern std::string messageBoxText; extern std::array PARTY_MEMBER_STATS; extern Entity::pstats_t partyMemberDefaultStats; extern std::map SPRITES; extern std::map ANIMATIONS; extern std::array PARTY_MEMBER_OBJ; extern std::map OBJ_INFO; extern std::mapMOVELIST; extern std::vectorENCOUNTER_LIST; extern std::map BATTLE_PROPERTIES; extern std::map MAPS; extern std::vectorCUTSCENE_QUEUE; extern std::vector> MAP; extern std::vector> MAP2; extern std::vector> MAP3; extern std::vector> MAP4; extern std::vector> MAP5; extern std::vector> MAP6; int testCount=0; int MAX_ITERATIONS=1000; int iterations=0; enum class KeyIdentifier{ UP, RIGHT, DOWN, LEFT, BACK, }; struct TestKey{ Key k; std::string keyName; KeyIdentifier id; bool operator==(TestKey&other){ return id==other.id; } }; namespace key{ TestKey UP{Key::UP,"UP",KeyIdentifier::UP}; TestKey DOWN{Key::DOWN,"DOWN",KeyIdentifier::DOWN}; TestKey LEFT{Key::LEFT,"LEFT",KeyIdentifier::LEFT}; TestKey RIGHT{Key::RIGHT,"RIGHT",KeyIdentifier::RIGHT}; TestKey BACK{Key::BACK,"BACKSPACE",KeyIdentifier::BACK}; TestKey ESCAPE{Key::ESCAPE,"ESCAPE",KeyIdentifier::BACK}; TestKey X{Key::X,"X",KeyIdentifier::BACK}; TestKey CTRL{Key::CTRL,"CTRL",KeyIdentifier::BACK}; TestKey DEL{Key::DEL,"DEL",KeyIdentifier::BACK}; TestKey END{Key::END,"END",KeyIdentifier::BACK}; TestKey NP_DECIMAL{Key::NP_DECIMAL,"Numpad Decimal",KeyIdentifier::BACK}; TestKey NP_SUB{Key::NP_SUB,"Numpad Subtract",KeyIdentifier::BACK}; TestKey MINUS{Key::MINUS,"MINUS",KeyIdentifier::BACK}; TestKey PAUSE{Key::PAUSE,"PAUSE",KeyIdentifier::BACK}; TestKey TAB{Key::TAB,"TAB",KeyIdentifier::BACK}; TestKey CAPS_LOCK{Key::CAPS_LOCK,"CAPS LOCK",KeyIdentifier::BACK}; TestKey W{Key::W,"W",KeyIdentifier::UP}; TestKey A{Key::A,"A",KeyIdentifier::LEFT}; TestKey S{Key::S,"S",KeyIdentifier::DOWN}; TestKey D{Key::D,"D",KeyIdentifier::RIGHT}; TestKey NP8{Key::NP8,"NP8",KeyIdentifier::UP}; TestKey NP4{Key::NP4,"NP4",KeyIdentifier::LEFT}; TestKey NP5{Key::NP5,"NP5",KeyIdentifier::DOWN}; TestKey NP6{Key::NP6,"NP6",KeyIdentifier::RIGHT}; TestKey NP2{Key::NP2,"NP2",KeyIdentifier::DOWN}; } void CopyMapContents(std::vector>&from,std::vector>&to) { for (int x=0;x tiles; for (int y=0;ytileX,from[x][y]->tileY,from[x][y]->tileDegree)); } to.push_back(tiles); } } bool ValidateEntireMap(std::vector>&mapref1,std::vector>&mapref2) { for (int x=0;xMAX_ITERATIONS) { std::cout<<" FAILED! (Iterations>"< sprList) { for (int i=0;i sprList) { for (int i=0;isprite->width!=0&&SPRITES[sprList[i]]->sprite->height!=0); } } bool SeasonI::OnUserCreate(){ srand(time(NULL)); GAME=this; for (int i=1;i<7;i++) { CreateLayer(); EnableLayer(i,true); } SetPixelMode(Pixel::ALPHA); GAME_STATE=GameState::TEST_GAME; Test("We start in the TEST_GAME state", GAME_STATE==GameState::TEST_GAME); for (int i=0;i0); for (int i=0;istats==partyMemberDefaultStats); } TestSpriteUndefined({"terrainmap.png","pixel.png","bufficons.png","rollingcounter.png","additionalFont.png"}); SetupAnimations(); TestSpriteInitialized({"terrainmap.png","pixel.png","bufficons.png","rollingcounter.png","additionalFont.png"}); Test("Player animation is undefined", ANIMATIONS.count("player.png")==0); Test("Party Member Object is not setup", PARTY_MEMBER_OBJ[0]==nullptr); vd2d testPos={0,0},testScale={2,2}; CreateObjectInfo(new Standard_Obj(PLAYER,"player",testPos,nullptr,testScale,MAGENTA,32),"player.png",{24,32}); Test("Player animation is defined", ANIMATIONS["player.png"]!=nullptr); Decal*playerAnimPointer=ANIMATIONS["player.png"]->spr; Test("Player animation is setup correctly", ANIMATIONS["player.png"]->frames>0&&ANIMATIONS["player.png"]->spr!=nullptr); Test("Object Info database now has 1 entry", OBJ_INFO.size()==1); Test("Object Info is correctly assigned", OBJ_INFO[0]->name=="player"&&OBJ_INFO[0]->id==PLAYER&&OBJ_INFO[0]->GetPos()==testPos&&OBJ_INFO[0]->GetScale()==testScale&&OBJ_INFO[0]->color==MAGENTA&&OBJ_INFO[0]->spr->sprSize.x==24&&OBJ_INFO[0]->spr->sprSize.y==32); delete OBJ_INFO[PLAYER]; OBJ_INFO.erase(PLAYER); Test("Object Info is cleared", OBJ_INFO.size()==0); SetupObjectInfo(); Test("Using the same sprite definition does not cause memory leak", playerAnimPointer==OBJ_INFO[0]->spr->spr); Test("No encounters are loaded", ENCOUNTER_LIST.size()==0); SetupEncounters(); Test("SetupEncounters() loads up new encounters", ENCOUNTER_LIST.size()>0); Encounter*testEncounter=new Encounter(encounter::ENCOUNTER_1,{0,0},std::array{vd2d {grid(1,2)},{grid(2,2)},{grid(3,2)},{grid(4,2)}}, std::vector{ new Entity(new Standard_Obj( NPC1_4,"Test Obj",3,2,ANIMATIONS["player.png"]), {HP:70,maxHP:70,PP:10,maxPP:10,baseAtk:14,speed:5,resistances:{0,0,0,0}},std::vector{ MOVELIST[BattleMoveName::TESTMOVE1], MOVELIST[BattleMoveName::TESTMOVE2], MOVELIST[BattleMoveName::TESTMOVE3], }, {ITEMLIST[ItemName::COOKIE]}, 돈 20), new Entity(new Standard_Obj( NPC1_4,"Test Obj 2",1,3,ANIMATIONS["player.png"]), {HP:70,maxHP:70,PP:10,maxPP:10,baseAtk:14,speed:5,resistances:{0,0,0,0}},std::vector{ MOVELIST[BattleMoveName::TESTMOVE1], MOVELIST[BattleMoveName::TESTMOVE2], }, {ITEMLIST[ItemName::PIZZA]}), new Entity(new Standard_Obj( NPC1_4,"Test Obj 3",2,2,ANIMATIONS["player.png"]), {HP:70,maxHP:70,PP:10,maxPP:10,baseAtk:14,speed:5,resistances:{0,0,0,0}},std::vector{ MOVELIST[BattleMoveName::TESTMOVE1], }), }); Test("Test encounter has three entities", testEncounter->objs.size()==3); Test("Test encounter uses ID ENCOUNTER_1", testEncounter->id==encounter::ENCOUNTER_1); testPos={0,0}; Test("Test encounter uses position ("+std::to_string(testPos.x)+","+std::to_string(testPos.y)+")", testEncounter->pos==testPos); Test("Test encounter player positions are correct", testEncounter->playerPos==std::array{vd2d{grid(1,2)},{grid(2,2)},{grid(3,2)},{grid(4,2)}}); Test("Test encounter grid positions are correct", testEncounter->playerPos==std::array{vd2d{grid(1,2)},{grid(2,2)},{grid(3,2)},{grid(4,2)}}); Test("Enemy 1 has 3 battle moves", testEncounter->objs[0]->moveSet==std::vector{ MOVELIST[BattleMoveName::TESTMOVE1], MOVELIST[BattleMoveName::TESTMOVE2], MOVELIST[BattleMoveName::TESTMOVE3], }); Test("Enemy 1 has a cookie as a drop", testEncounter->objs[0]->inventory==std::vector{ITEMLIST[ItemName::COOKIE]}); Test("Enemy 1 gives 20 money.", testEncounter->objs[0]->money==20); Test("Enemy 2 has 2 battle moves.", testEncounter->objs[1]->moveSet==std::vector{ MOVELIST[BattleMoveName::TESTMOVE1], MOVELIST[BattleMoveName::TESTMOVE2], }); Test("Enemy 2 has a pizza as a drop", testEncounter->objs[1]->inventory==std::vector{ITEMLIST[ItemName::PIZZA]}); Test("Enemy 2 gives 0 money.", testEncounter->objs[1]->money==0); Test("Enemy 3 has 1 battle move.", testEncounter->objs[2]->moveSet==std::vector{ MOVELIST[BattleMoveName::TESTMOVE1], }); Test("Enemy 3 has no items to drop", testEncounter->objs[2]->inventory==std::vector{}); Test("Enemy 3 gives 0 money.", testEncounter->objs[2]->money==0); Test("There are no battle properties", BATTLE_PROPERTIES.size()==0); SetupBattleProperties(); Test("Battle Properties populated", BATTLE_PROPERTIES.size()>0); Test("Test Move 1 exists in the map.", MOVELIST.count(BattleMoveName::TESTMOVE1)); Test("Test Move 1 is undefined", MOVELIST[BattleMoveName::TESTMOVE1]==nullptr); MOVELIST[BattleMoveName::TESTMOVE1]=SetupMove(TESTMOVE1)"Test Move 1","An attack",baseDmg:30,randomDmg:5,range:6,channelTime:27,friendly:false}; Test("Verify Test Move 1's now set properly", MOVELIST[BattleMoveName::TESTMOVE1]!=nullptr); Test("Verify Test Move 1's Power Name shows up correctly", MOVELIST[BattleMoveName::TESTMOVE1]->GetPowerName()=="Test Move 1"); MOVELIST[BattleMoveName::TESTMOVE1]->grade=GAMMA; Test("Verify Test Move 1's Power Name shows up correctly with a grade", MOVELIST[BattleMoveName::TESTMOVE1]->GetPowerName()=="Test Move 1 "+std::string(1,(char)GAMMA)); Test("Cookie is undefined", ITEMLIST[ItemName::COOKIE]==nullptr); SetupItemList(); Test("Cookie is defined", ITEMLIST[ItemName::COOKIE]!=nullptr); delete ITEMLIST[ItemName::COOKIE]; ITEMLIST.erase(ItemName::COOKIE); ITEMLIST[ItemName::COOKIE]=SetupItem(COOKIE)"Cookie","A delightful little treat. Restores 40 HP.",2,{hpRecovery:40,consumable:Consumable::FRIENDLY,sellPrice:2}); Test("Cookie name is set properly", ITEMLIST[ItemName::COOKIE]->name=="Cookie"); Test("Cookie description is set properly", ITEMLIST[ItemName::COOKIE]->description=="A delightful little treat. Restores 40 HP."); Test("Cookie drop chance is set properly", ITEMLIST[ItemName::COOKIE]->dropChance==2); delete ITEMLIST[ItemName::FREEZE_PACKET]; ITEMLIST.erase(ItemName::FREEZE_PACKET); ITEMLIST[ItemName::FREEZE_PACKET]=SetupItem(FREEZE_PACKET)"Freeze Packet","Lets out some blistering cold weather.",256,{consumable:Consumable::ENEMY,sellPrice:36},MOVELIST[BattleMoveName::FREEZE_PACKET]); Test("Freeze Packet name is set properly", ITEMLIST[ItemName::FREEZE_PACKET]->name=="Freeze Packet"); Test("Freeze Packet description is set properly", ITEMLIST[ItemName::FREEZE_PACKET]->description=="Lets out some blistering cold weather."); Test("Freeze Packet drop chance is set properly", ITEMLIST[ItemName::FREEZE_PACKET]->dropChance==256); Test("No Maps are loaded", MAPS.size()==0); SetupMapList(); Test("Maps are loaded", MAPS.size()!=0); Test("No Cutscenes are loaded", CUTSCENES.size()==0); SetupCutscenes(); Test("Calling SetupCutscenes() loads up different cutscenes", CUTSCENES.size()!=0); Test("No active cutscene yet", CurrentCutscene==nullptr); StartCutscene(CUTSCENES[CutsceneName::TEST_CUTSCENE]); Test("Starting a cutscene sets the current cutscene", CurrentCutscene!=nullptr); Test("Current Action should not be updated yet", CurrentAction==ActionType::NONE); OnUserUpdate(1/60.f); Test("HandleCutscenes should get called in updateGame(), updating the current action", CurrentAction!=ActionType::NONE); int startFrame=frameCount; TestWhile("Cutscene should complete entirely",CurrentAction!=ActionType::NONE) { OnUserUpdate(1/60.f); } std::cout<<"Frame Count: "<<(frameCount-startFrame)<previous_fade_value); Test("There should be no objects in the game", OBJECTS.size()==0); Test("Player should not be able to move during a cutscene", !PlayerCanMove()); TestWhile("Fade out should finish",CurrentAction==ActionType::FADE) { OnUserUpdate(1/60.f); } Test("When faded out, CUTSCENE_FADE_VALUE should be 255", CUTSCENE_FADE_VALUE==255); Test("Next cutscene action should be CreateObjects", CurrentAction==ActionType::CREATE_OBJECTS); Test("There should be 3 objects in the game", OBJECTS.size()==3); Test("Cutscene objects should have the temp flag set", OBJECTS[0]->temp&&OBJECTS[1]->temp&&OBJECTS[2]->temp); OnUserUpdate(1/60.f); Test("Next cutscene action should be Fade back in", CurrentAction==ActionType::FADE); previous_fade_value=CUTSCENE_FADE_VALUE; OnUserUpdate(1/60.f); Test("Fading in causes CUTSCENE_FADE_VALUE to decrease", CUTSCENE_FADE_VALUEGetEndingCutsceneFlag()==Flag::TEST_FLAG3&&CurrentCutscene->GetEndingCutsceneVal()); OnUserUpdate(1/60.f); Test("Next cutscene action should be setting a flag on the spot", CurrentAction==ActionType::SET_FLAG); Test("Test Flag 2 should now be set", GetGameFlag(Flag::TEST_FLAG2)); Test("Test Flag 2 should still not be set", !GetGameFlag(Flag::TEST_FLAG3)); cameraPos={0,0}; Test("Camera position should be {0,0}", cameraPos.x==0&&cameraPos.y==0); OnUserUpdate(1/60.f); Test("Next cutscene action should be panning the camera", CurrentAction==ActionType::PAN_CAMERA); Test("Camera position should be moving towards {128,128}", cameraPos.x>0&&cameraPos.y>0); Test("Temporary cutscene object 1 is at position {136,136}", CurrentCutscene->GetCutsceneObjects()[1]->GetPos().x==136&&CurrentCutscene->GetCutsceneObjects()[1]->GetPos().y==136); TestWhile("Panning Camera should finish",CurrentAction==ActionType::PAN_CAMERA) { OnUserUpdate(1/60.f); } Test("Camera position should be {128,128}", cameraPos.x==128&&cameraPos.y==128); Test("Next cutscene action is the async cutscene object movement", CurrentAction==ActionType::MOVE_CUTSCENE_OBJ_ASYNC); vd2d prevCutsceneObjPosition=CurrentCutscene->GetCutsceneObjects()[1]->GetPos(); OnUserUpdate(1/60.f); Test("Cutscene object is moving towards {80,64}", CurrentCutscene->GetCutsceneObjects()[1]->GetPos().xGetCutsceneObjects()[1]->GetPos().ycameraPos.x&&prevCameraPos.y>cameraPos.y); Test("Due to async actions, next cutscene action should be Dialog Box Async", CurrentAction==ActionType::DIALOG_ASYNC); Test("A message box should be on-screen", messageBoxVisible); GetAnyKeyPress(H); GetAnyKeyPress(H); Test("Pressing any key should close the message box", !messageBoxVisible); OnUserUpdate(1/60.f); Test("Next cutscene action should be Modify Object 0", CurrentAction==ActionType::MODIFY_OBJECT); Test("Cutscene Object 0 is now size {5,5}", CurrentCutscene->GetCutsceneObjects()[0]->GetScale().x==5&&CurrentCutscene->GetCutsceneObjects()[0]->GetScale().y==5); OnUserUpdate(1/60.f); Test("Next cutscene action should be Move Cutscene Object 1", CurrentAction==ActionType::MOVE_CUTSCENE_OBJ); prevCutsceneObjPosition=CurrentCutscene->GetCutsceneObjects()[1]->GetPos(); OnUserUpdate(1/60.f); Test("Cutscene Object 1 is moving towards position {320,64}", CurrentCutscene->GetCutsceneObjects()[1]->GetPos().x>prevCutsceneObjPosition.x&&CurrentCutscene->GetCutsceneObjects()[1]->GetPos().y==prevCutsceneObjPosition.y); TestWhile("Move Cutscene Object should finish",CurrentAction==ActionType::MOVE_CUTSCENE_OBJ) { OnUserUpdate(1/60.f); } Test("Cutscene Object 1 should be at position {320,64}", CurrentCutscene->GetCutsceneObjects()[1]->GetPos().x==320&&CurrentCutscene->GetCutsceneObjects()[1]->GetPos().y==64); Test("Next cutscene action is Dialog Box", CurrentAction==ActionType::DIALOG); Test("Dialog box should be visible", messageBoxVisible); GetAnyKeyPress(S); Test("Pressing a key should show the entire message", messageBoxText=="Hello!"); GetAnyKeyPress(S); Test("Pressing a key should close the message box", !messageBoxVisible); int prevDestructionCount=OBJECT_DESTRUCTION_COUNT; OnUserUpdate(1/60.f); Test("Next cutscene action should be loading a map", CurrentAction==ActionType::LOAD_MAP); Test("Current Map should now be TWOSON", CURRENT_MAP==MAPS[MapName::TWOSON]); Test("All temporary objects should now be destroyed", OBJECT_DESTRUCTION_COUNT-3==prevDestructionCount); OnUserUpdate(1/60.f); Test("Next action should be moving player objects", CurrentAction==ActionType::MOVE_PLAYER_OBJS); Test("All player objects should now be at position {16,16}", PARTY_MEMBER_OBJ[0]->GetPos().x==16&&PARTY_MEMBER_OBJ[0]->GetPos().y==16); Test("Next cutscene action should be cleanup", CurrentCutscene->CurrentAction()==ActionType::CLEANUP); OnUserUpdate(1/60.f); Test("All cutscene and action variables should be cleaned up", CurrentCutscene==nullptr&& CurrentAction==ActionType::NONE); TestKey testkeys[] = {key::UP,key::DOWN,key::LEFT,key::RIGHT,key::W,key::A,key::S,key::D,key::NP8,key::NP4,key::NP5,key::NP6,key::NP2,key::BACK,key::ESCAPE,key::X,key::CTRL,key::DEL,key::END,key::NP_DECIMAL,key::NP_SUB,key::MINUS,key::PAUSE,key::TAB,key::CAPS_LOCK}; for (TestKey k : testkeys) { PressTestKey(k.k); Test(k.keyName+" key is pressed", GetKeyPressed(*this,k)); OnUserUpdate(1/60.f); Test(k.keyName+" key is no longer pressed", !GetKeyPressed(*this,k)); Test(k.keyName+" key is held down", GetKeyHeld(*this,k)); OnUserUpdate(1/60.f); Test(k.keyName+" key is still held down", GetKeyHeld(*this,k)); for (int i=0;i<50;i++) { OnUserUpdate(1/60.f); } Test(k.keyName+" key is still held down after multiple updates", GetKeyHeld(*this,k)); ReleaseTestKey(k.k); Test(k.keyName+" key is no longer held down", !GetKeyHeld(*this,k)); Test(k.keyName+" key is released", GetKeyReleased(*this,k)); OnUserUpdate(1/60.f); Test(k.keyName+" key is no longer released", !GetKeyReleased(*this,k)); } Test("We are still in the TEST_GAME state", GAME_STATE==GameState::TEST_GAME); TestKey testRepeatKeys[] = {key::UP,key::DOWN,key::LEFT,key::RIGHT}; for (TestKey k : testRepeatKeys) { frameCount=0; PressTestKey(k.k); for (int i=0;i<23;i++) { updateGame(); Test(k.keyName+" key is not considered pressed", !GetKeyPressed(*this,k)); keyUpdates(); } int attemptCount=1; updateGame(); Test(k.keyName+" key is considered pressed again (Attempt "+std::to_string(attemptCount++)+")", GetKeyPressed(*this,k)); keyUpdates(); for (int j=0;j<2;j++) { for (int i=0;i<3;i++) { updateGame(); Test(k.keyName+" key is not considered pressed", !GetKeyPressed(*this,k)); keyUpdates(); } updateGame(); Test(k.keyName+" key is considered pressed again (Attempt "+std::to_string(attemptCount++)+")", GetKeyPressed(*this,k)); keyUpdates(); } ResetTestKeys(); SetDrawTarget(nullptr); GetDrawTarget()->GetData()[0].a=4; } LoadMap(MAPS[MapName::TEST]); GAME_STATE=GameState::GAME_WORLD; Test("Player can move when there is no cutscene and the game is in a normal state", PlayerCanMove()); GAME_STATE=GameState::TEST_GAME; Test("Player cannot move during testing", !PlayerCanMove()); SetGameFlag(Flag::INTRO_COMPLETED,true); GAME_STATE=GameState::GAME_WORLD; vd2d prevPlayerPos = PARTY_MEMBER_OBJ[0]->GetPos(); CenterCameraOnPlayer(); PressTestKeyAndRun(RIGHT); Test("Player has moved to the right", PARTY_MEMBER_OBJ[0]->GetPos().x>prevPlayerPos.x&&PARTY_MEMBER_OBJ[0]->GetPos().y==prevPlayerPos.y); prevPlayerPos = PARTY_MEMBER_OBJ[0]->GetPos(); PressTestKeyAndRun(UP); Test("Player has moved up-right", PARTY_MEMBER_OBJ[0]->GetPos().x>prevPlayerPos.x&&PARTY_MEMBER_OBJ[0]->GetPos().yGetPos(); PressTestKeyAndRun(DOWN); Test("Player has moved down-right", PARTY_MEMBER_OBJ[0]->GetPos().x>prevPlayerPos.x&&PARTY_MEMBER_OBJ[0]->GetPos().y>prevPlayerPos.y); ResetTestKeys(); prevPlayerPos = PARTY_MEMBER_OBJ[0]->GetPos(); PressTestKeyAndRun(LEFT); Test("Player has moved to the left", PARTY_MEMBER_OBJ[0]->GetPos().xGetPos().y==prevPlayerPos.y); prevPlayerPos = PARTY_MEMBER_OBJ[0]->GetPos(); PressTestKeyAndRun(UP); Test("Player has moved up-left", PARTY_MEMBER_OBJ[0]->GetPos().xGetPos().yGetPos(); PressTestKeyAndRun(DOWN); Test("Player has moved down-left", PARTY_MEMBER_OBJ[0]->GetPos().xGetPos().y>prevPlayerPos.y); ReleaseTestKey(LEFT); prevPlayerPos = PARTY_MEMBER_OBJ[0]->GetPos(); OnUserUpdate(1/60.f); Test("Player has moved down", PARTY_MEMBER_OBJ[0]->GetPos().x==prevPlayerPos.x&&PARTY_MEMBER_OBJ[0]->GetPos().y>prevPlayerPos.y); ReleaseTestKey(DOWN); prevPlayerPos = PARTY_MEMBER_OBJ[0]->GetPos(); PressTestKeyAndRun(UP); Test("Player has moved up", PARTY_MEMBER_OBJ[0]->GetPos().x==prevPlayerPos.x&&PARTY_MEMBER_OBJ[0]->GetPos().ySetPos({32-PARTY_MEMBER_OBJ[0]->originPoint.x,16-PARTY_MEMBER_OBJ[0]->originPoint.y}); Test("Player is now centered at 32,16", PARTY_MEMBER_OBJ[0]->GetPosWithOrigin().x==32&&PARTY_MEMBER_OBJ[0]->GetPosWithOrigin().y==16); CenterCameraOnPlayer(); for (int i=0;i<10;i++) { PressTestKeyAndRun(LEFT); ReleaseTestKey(LEFT); } Test("Player does not move due to tile collision", PARTY_MEMBER_OBJ[0]->GetPosWithOrigin().x==32&&PARTY_MEMBER_OBJ[0]->GetPosWithOrigin().y==16); SetupGameDrawing(); SetDrawTarget(layer::COLLISION); bool isAllMagenta=true; for (int x=0;xGetData()[y*WIDTH+x]!=MAGENTA) { isAllMagenta=false; goto endOfScreenCheck; } } } endOfScreenCheck: Test("Entire screen should be wiped to magenta before drawing anything", isAllMagenta); std::vector> TEMPMAP; std::vector> TEMPMAP2; std::vector> TEMPMAP3; std::vector> TEMPMAP4; std::vector> TEMPMAP5; std::vector> TEMPMAP6; CopyMapContents(MAP,TEMPMAP); CopyMapContents(MAP2,TEMPMAP2); CopyMapContents(MAP3,TEMPMAP3); CopyMapContents(MAP4,TEMPMAP4); CopyMapContents(MAP5,TEMPMAP5); CopyMapContents(MAP6,TEMPMAP6); Test("Entire map should be copied over properly for testing", ValidateEntireMap(MAP,TEMPMAP)&& ValidateEntireMap(MAP2,TEMPMAP2)&& ValidateEntireMap(MAP3,TEMPMAP3)&& ValidateEntireMap(MAP4,TEMPMAP4)&& ValidateEntireMap(MAP5,TEMPMAP5)&& ValidateEntireMap(MAP6,TEMPMAP6)); TILE prevTile1=TEMPMAP[6][4]; TILE prevTile2=TEMPMAP2[2][0]; TILE prevTile3=TEMPMAP3[7][2]; TILE prevTile4=TEMPMAP4[1][14]; TILE prevTile5=TEMPMAP5[7][2]; TILE prevTile6=TEMPMAP6[9][6]; TEMPMAP[6][4]=TILE(9,4,0); TEMPMAP2[2][0]=TILE(4,7,0); TEMPMAP3[7][2]=TILE(4,9,0); TEMPMAP4[1][14]=TILE(1,2,-1); TEMPMAP5[7][2]=TILE(6,8,0); TEMPMAP6[9][6]=TILE(4,17,0); Test("After modifications, some parts of the map should no longer be equal", !ValidateEntireMap(MAP,TEMPMAP)&& !ValidateEntireMap(MAP2,TEMPMAP2)&& !ValidateEntireMap(MAP3,TEMPMAP3)&& !ValidateEntireMap(MAP4,TEMPMAP4)&& !ValidateEntireMap(MAP5,TEMPMAP5)&& !ValidateEntireMap(MAP6,TEMPMAP6)); TEMPMAP[6][4]=prevTile1; TEMPMAP2[2][0]=prevTile2; TEMPMAP3[7][2]=prevTile3; TEMPMAP4[1][14]=prevTile4; TEMPMAP5[7][2]=prevTile5; TEMPMAP6[9][6]=prevTile6; LoadMap(MAPS[MapName::ONETT]); Test("Loading a wrong map should not validate correctly", !ValidateEntireMap(MAP,TEMPMAP)&& !ValidateEntireMap(MAP2,TEMPMAP2)&& !ValidateEntireMap(MAP3,TEMPMAP3)&& !ValidateEntireMap(MAP4,TEMPMAP4)&& !ValidateEntireMap(MAP5,TEMPMAP5)&& !ValidateEntireMap(MAP6,TEMPMAP6)); LoadMap(MAPS[MapName::TEST]); Test("Upon reloading a map every tile should match up once again", ValidateEntireMap(MAP,TEMPMAP)&& ValidateEntireMap(MAP2,TEMPMAP2)&& ValidateEntireMap(MAP3,TEMPMAP3)&& ValidateEntireMap(MAP4,TEMPMAP4)&& ValidateEntireMap(MAP5,TEMPMAP5)&& ValidateEntireMap(MAP6,TEMPMAP6)); TEMPMAP[6][4]=TILE(9,4,0); delete MAP[6][4]; MAP[6][4]=new TILE(TEMPMAP[6][4].tileX,TEMPMAP[6][4].tileY,TEMPMAP[6][4].tileDegree); delete MAP2[2][0]; TEMPMAP2[2][0]=TILE(4,7,0); MAP2[2][0]=new TILE(TEMPMAP2[2][0].tileX,TEMPMAP2[2][0].tileY,TEMPMAP2[2][0].tileDegree); delete MAP3[7][2]; TEMPMAP3[7][2]=TILE(4,9,0); MAP3[7][2]=new TILE(TEMPMAP3[7][2].tileX,TEMPMAP3[7][2].tileY,TEMPMAP3[7][2].tileDegree); TEMPMAP4[1][14]=TILE(12,1,-1); delete MAP4[1][14]; MAP4[1][14]=new TILE(TEMPMAP4[1][14].tileX,TEMPMAP4[1][14].tileY,TEMPMAP4[1][14].tileDegree); TEMPMAP5[7][2]=TILE(6,8,0); delete MAP5[7][2]; MAP5[7][2]=new TILE(TEMPMAP5[7][2].tileX,TEMPMAP5[7][2].tileY,TEMPMAP5[7][2].tileDegree); TEMPMAP6[9][6]=TILE(4,17,0); delete MAP6[9][6]; MAP6[9][6]=new TILE(TEMPMAP6[9][6].tileX,TEMPMAP6[9][6].tileY,TEMPMAP6[9][6].tileDegree); SaveMap(MAPS[MapName::TEST]); Test("Saving a test map should have no side effects", ValidateEntireMap(MAP,TEMPMAP)&& ValidateEntireMap(MAP2,TEMPMAP2)&& ValidateEntireMap(MAP3,TEMPMAP3)&& ValidateEntireMap(MAP4,TEMPMAP4)&& ValidateEntireMap(MAP5,TEMPMAP5)&& ValidateEntireMap(MAP6,TEMPMAP6)); LoadMap(MAPS[MapName::TEST]); Test("Loading the same map should result in the same map", ValidateEntireMap(MAP,TEMPMAP)&& ValidateEntireMap(MAP2,TEMPMAP2)&& ValidateEntireMap(MAP3,TEMPMAP3)&& ValidateEntireMap(MAP4,TEMPMAP4)&& ValidateEntireMap(MAP5,TEMPMAP5)&& ValidateEntireMap(MAP6,TEMPMAP6)); TEMPMAP[6][4]=TILE(15,15,0); TEMPMAP2[2][0]=TILE(15,15,0); TEMPMAP3[7][2]=TILE(15,15,0); TEMPMAP4[1][14]=TILE(15,15,0); TEMPMAP5[7][2]=TILE(15,15,0); TEMPMAP6[9][6]=TILE(15,15,0); Test("Loading the same map should result in the same map (2)", !ValidateEntireMap(MAP,TEMPMAP)&& !ValidateEntireMap(MAP2,TEMPMAP2)&& !ValidateEntireMap(MAP3,TEMPMAP3)&& !ValidateEntireMap(MAP4,TEMPMAP4)&& !ValidateEntireMap(MAP5,TEMPMAP5)&& !ValidateEntireMap(MAP6,TEMPMAP6)); MAP[6][4]->tileX=MAP[6][4]->tileY=15;MAP[6][4]->tileDegree=0; MAP2[2][0]->tileX=MAP2[2][0]->tileY=15;MAP2[2][0]->tileDegree=0; MAP3[7][2]->tileX=MAP3[7][2]->tileY=15;MAP3[7][2]->tileDegree=0; MAP4[1][14]->tileX=MAP4[1][14]->tileY=15;MAP4[1][14]->tileDegree=0; MAP5[7][2]->tileX=MAP5[7][2]->tileY=15;MAP5[7][2]->tileDegree=0; MAP6[9][6]->tileX=MAP6[9][6]->tileY=15;MAP6[9][6]->tileDegree=0; SaveMap(MAPS[MapName::TEST]); Test("Map is back to normal", ValidateEntireMap(MAP,TEMPMAP)&& ValidateEntireMap(MAP2,TEMPMAP2)&& ValidateEntireMap(MAP3,TEMPMAP3)&& ValidateEntireMap(MAP4,TEMPMAP4)&& ValidateEntireMap(MAP5,TEMPMAP5)&& ValidateEntireMap(MAP6,TEMPMAP6)); return true; } bool SeasonI::OnUserUpdate(float fElapsedTime) { updateGame(); keyUpdates(); SetupGameDrawing(); drawGame(); return true; } int main() { SeasonI demo; if (demo.Construct(WIDTH, HEIGHT, 4, 4)) demo.Start(); return 0; }