# include "../entity.h"
# include "../item.h"
# include "../layers.h"
# include <string>
# 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 <assert.h>
# 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 < Entity * , 7 > PARTY_MEMBER_STATS ;
extern Entity : : pstats_t partyMemberDefaultStats ;
extern std : : map < std : : string , Decal * > SPRITES ;
extern std : : map < std : : string , Animation * > ANIMATIONS ;
extern std : : array < NPC_Obj * , 4 > PARTY_MEMBER_OBJ ;
extern std : : map < int , Object * > OBJ_INFO ;
extern std : : map < BattleMoveName , Battle : : Move * > MOVELIST ;
extern std : : vector < Encounter * > ENCOUNTER_LIST ;
extern std : : map < Property , BattleProperty * > BATTLE_PROPERTIES ;
extern std : : map < MapName : : Map , Map * > MAPS ;
extern std : : vector < CutsceneAction * > CUTSCENE_QUEUE ;
int testCount = 0 ;
int MAX_ITERATIONS = 1000 ;
int iterations = 0 ;
enum 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 } ;
}
bool GetKeyPressed ( SeasonI & instance , TestKey & k ) {
if ( k = = key : : UP ) {
return instance . UpPressed ( ) ;
}
if ( k = = key : : DOWN ) {
return instance . DownPressed ( ) ;
}
if ( k = = key : : RIGHT ) {
return instance . RightPressed ( ) ;
}
if ( k = = key : : LEFT ) {
return instance . LeftPressed ( ) ;
}
if ( k = = key : : BACK ) {
return instance . BackPressed ( ) ;
}
std : : cerr < < " Something went terribly wrong! THIS SHOULD NOT BE HAPPENING! \n " ;
return false ;
}
bool GetKeyHeld ( SeasonI & instance , TestKey & k ) {
if ( k = = key : : UP ) {
return instance . UpHeld ( ) ;
}
if ( k = = key : : DOWN ) {
return instance . DownHeld ( ) ;
}
if ( k = = key : : RIGHT ) {
return instance . RightHeld ( ) ;
}
if ( k = = key : : LEFT ) {
return instance . LeftHeld ( ) ;
}
if ( k = = key : : BACK ) {
return instance . BackHeld ( ) ;
}
std : : cerr < < " Something went terribly wrong! THIS SHOULD NOT BE HAPPENING! \n " ;
return false ;
}
bool GetKeyReleased ( SeasonI & instance , TestKey & k ) {
if ( k = = key : : UP ) {
return instance . UpReleased ( ) ;
}
if ( k = = key : : DOWN ) {
return instance . DownReleased ( ) ;
}
if ( k = = key : : RIGHT ) {
return instance . RightReleased ( ) ;
}
if ( k = = key : : LEFT ) {
return instance . LeftReleased ( ) ;
}
if ( k = = key : : BACK ) {
return instance . BackReleased ( ) ;
}
std : : cerr < < " Something went terribly wrong! THIS SHOULD NOT BE HAPPENING! \n " ;
return false ;
}
void Test ( std : : string name , bool success ) {
testCount + + ;
std : : cout < < " Test ( " < < testCount < < " ) " < < name < < " ... " < < std : : endl ;
assert ( success ) ;
std : : cout < < " Passed " < < std : : endl ;
} ;
void _TestWait ( std : : string name ) {
testCount + + ;
std : : cout < < " Test ( " < < testCount < < " ) " < < name < < " ... " < < std : : endl ;
iterations = 0 ;
} ;
bool _TestResolve ( bool testCase , int maxIterations = MAX_ITERATIONS ) {
if ( ! testCase ) {
std : : cout < < " Passed " < < std : : endl ;
return false ;
}
if ( iterations + + > MAX_ITERATIONS ) {
std : : cout < < " FAILED! (Iterations> " < < maxIterations < < " ) " < < std : : endl ;
assert ( ! testCase ) ;
}
return true ;
} ;
void TestSpriteUndefined ( std : : vector < std : : string > sprList ) {
for ( int i = 0 ; i < sprList . size ( ) ; i + + ) {
Test ( " Sprite " + sprList [ i ] + " should not be initialized " ,
SPRITES [ sprList [ i ] ] = = nullptr ) ;
}
}
void TestSpriteInitialized ( std : : vector < std : : string > sprList ) {
for ( int i = 0 ; i < sprList . size ( ) ; i + + ) {
Test ( " Sprite " + sprList [ i ] + " should be initialized " ,
SPRITES [ sprList [ i ] ] ! = nullptr ) ;
Test ( " Sprite " + sprList [ i ] + " should have a non-zero width and height " ,
SPRITES [ sprList [ i ] ] - > sprite - > width ! = 0 & & SPRITES [ sprList [ i ] ] - > sprite - > height ! = 0 ) ;
}
}
bool SeasonI : : OnUserCreate ( ) {
for ( int i = 0 ; i < PARTY_MEMBER_STATS . size ( ) ; i + + ) {
Test ( " Party Member stats should not be initialized " ,
PARTY_MEMBER_STATS [ i ] = = nullptr ) ;
}
Test ( " No battle moves are loaded " ,
MOVELIST . size ( ) = = 0 ) ;
SetupPartyMemberStats ( ) ;
Test ( " Battle moves now exist (still not defined) " ,
MOVELIST . size ( ) > 0 ) ;
for ( int i = 0 ; i < PARTY_MEMBER_STATS . size ( ) ; i + + ) {
Test ( " Party Members get initialized with correct defaults " ,
PARTY_MEMBER_STATS [ i ] - > stats = = 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 , 4 > { vd2d
{ grid ( 1 , 2 ) } , { grid ( 2 , 2 ) } , { grid ( 3 , 2 ) } , { grid ( 4 , 2 ) } } ,
std : : vector < Entity * > {
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 < Battle : : Move * > {
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 < Battle : : Move * > {
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 < Battle : : Move * > {
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 , 4 > { 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 , 4 > { 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 < Battle : : Move * > {
MOVELIST [ BattleMoveName : : TESTMOVE1 ] ,
MOVELIST [ BattleMoveName : : TESTMOVE2 ] ,
MOVELIST [ BattleMoveName : : TESTMOVE3 ] ,
} ) ;
Test ( " Enemy 1 has a cookie as a drop " ,
testEncounter - > objs [ 0 ] - > inventory = = std : : vector < Item * > { 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 < Battle : : Move * > {
MOVELIST [ BattleMoveName : : TESTMOVE1 ] ,
MOVELIST [ BattleMoveName : : TESTMOVE2 ] ,
} ) ;
Test ( " Enemy 2 has a pizza as a drop " ,
testEncounter - > objs [ 1 ] - > inventory = = std : : vector < Item * > { 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 < Battle : : Move * > {
MOVELIST [ BattleMoveName : : TESTMOVE1 ] ,
} ) ;
Test ( " Enemy 3 has no items to drop " ,
testEncounter - > objs [ 2 ] - > inventory = = std : : vector < Item * > { } ) ;
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 ) ;
updateGame ( ) ;
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 ) {
updateGame ( ) ;
}
std : : cout < < " Frame Count: " < < ( frameCount - startFrame ) < < std : : endl ;
Test ( " Cutscene is now finished " ,
CurrentAction = = ActionType : : NONE ) ;
Test ( " Test Flag 1 is set " ,
GetGameFlag ( Flag : : TEST_FLAG1 ) ) ;
Test ( " Test Flag 2 is not set " ,
! GetGameFlag ( Flag : : TEST_FLAG2 ) ) ;
Test ( " Test Flag 1 (int cast) is still set " ,
GetGameFlag ( ( int ) Flag : : TEST_FLAG1 ) ) ;
Test ( " Test Flag 2 (int cast) is still not set " ,
! GetGameFlag ( ( int ) Flag : : TEST_FLAG2 ) ) ;
Test ( " Test Flag 1 (Flag cast) is still set " ,
GetGameFlag ( ( Flag ) 1 ) ) ;
Test ( " Test Flag 2 (Flag cast) is still not set " ,
! GetGameFlag ( ( Flag ) 2 ) ) ;
Test ( " Current Map is not set " ,
CURRENT_MAP = = nullptr ) ;
Test ( " Main Character flag is not set " ,
! GetGameFlag ( Flag : : HAS_MAIN ) ) ;
SetGameFlag ( Flag : : HAS_MAIN , true ) ;
Test ( " Main Character flag is set " ,
GetGameFlag ( Flag : : HAS_MAIN ) ) ;
SetGameFlag ( Flag : : HAS_MAIN , false ) ;
Test ( " Main Character flag is unset " ,
! GetGameFlag ( Flag : : HAS_MAIN ) ) ;
SetGameFlag ( Flag : : HAS_MAIN , true ) ;
Cutscene * FeatureTestCutscene = new Cutscene ( {
액 션 Fade ( ) ,
액 션 CreateObjects ( {
new Standard_Obj ( PLAYER , " player " , { 64 , 64 } , ANIMATIONS [ " player.png " ] , { 1 , 1 } , MAGENTA ) ,
new Standard_Obj ( PLAYER , " player " , { 136 , 136 } , ANIMATIONS [ " player.png " ] , { 1 , 1 } , RED ) ,
new Standard_Obj ( PLAYER , " player " , { 96 , 96 } , ANIMATIONS [ " player.png " ] , { 1 , 1 } , DARK_GREEN ) ,
} ) ,
액 션 Fade ( true ) ,
액 션 SetFlagWhenCutsceneEnds ( Flag : : TEST_FLAG3 ) ,
액 션 SetFlag ( Flag : : TEST_FLAG2 , true ) ,
액 션 PanCamera ( { 128 , 128 } , BOTH , 1 ) ,
액 션 MoveCutsceneObjectAsync ( 1 , { 80 , 64 } , 50 ) ,
액 션 PanCameraAsync ( { 64 , 0 } , BOTH ) ,
액 션 DialogBoxAsync ( R " (Hello!
This is a test message that lets us trigger straight from a cutscene ! Cool ! ) " ),
액 션 ModifyObject ( 0 , ANIMATIONS [ " player.png " ] , { 5 , 5 } , MAGENTA ) ,
액 션 MoveCutsceneObject ( 1 , { 320 , 64 } , 1 ) ,
액 션 DialogBox ( R " (Hello!) " ) ,
액 션 class LoadMap ( MAPS [ MapName : : TWOSON ] ) ,
액 션 MovePlayerObjects ( { 16 , 16 } ) , } ) ;
Test ( " No cutscene is playing " ,
CurrentCutscene = = nullptr ) ;
StartCutscene ( FeatureTestCutscene ) ;
updateGame ( ) ;
Test ( " Current action should be fading " ,
CurrentAction = = ActionType : : FADE ) ;
double previous_fade_value = CUTSCENE_FADE_VALUE ;
updateGame ( ) ;
Test ( " Fading causes CUTSCENE_FADE_VALUE to increase " ,
CUTSCENE_FADE_VALUE > previous_fade_value ) ;
Test ( " There should be no objects in the game " ,
OBJECTS . size ( ) = = 0 ) ;
TestWhile ( " Fade out should finish " , CurrentAction = = ActionType : : FADE ) {
updateGame ( ) ;
}
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 ) ;
updateGame ( ) ;
Test ( " Next cutscene action should be Fade back in " ,
CurrentAction = = ActionType : : FADE ) ;
previous_fade_value = CUTSCENE_FADE_VALUE ;
updateGame ( ) ;
Test ( " Fading in causes CUTSCENE_FADE_VALUE to decrease " ,
CUTSCENE_FADE_VALUE < previous_fade_value ) ;
TestWhile ( " Fade in should finish " , CurrentAction = = ActionType : : FADE ) {
updateGame ( ) ;
}
Test ( " Next cutscene action should be setting a flag when the cutscene ends " ,
CurrentAction = = ActionType : : SET_FLAG_WHEN_CUTSCENE_ENDS ) ;
Test ( " Ending cutscene flag is stored properly with proper flag and value " ,
CurrentCutscene - > GetEndingCutsceneFlag ( ) = = Flag : : TEST_FLAG3 & & CurrentCutscene - > GetEndingCutsceneVal ( ) ) ;
updateGame ( ) ;
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 ) ;
updateGame ( ) ;
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 ) {
updateGame ( ) ;
}
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 ( ) ;
updateGame ( ) ;
Test ( " Cutscene object is moving towards {80,64} " ,
CurrentCutscene - > GetCutsceneObjects ( ) [ 1 ] - > GetPos ( ) . x < prevCutsceneObjPosition . x & & CurrentCutscene - > GetCutsceneObjects ( ) [ 1 ] - > GetPos ( ) . y < prevCutsceneObjPosition . y ) ;
vd2d prevCameraPos = cameraPos ;
Test ( " Due to async actions, next cutscene action should be Pan Camera Async " ,
CurrentAction = = ActionType : : PAN_CAMERA_ASYNC ) ;
updateGame ( ) ;
Test ( " Camera is moving towards {64,0} " ,
prevCameraPos . x > cameraPos . 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 ) ;
updateGame ( ) ;
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 ) ;
updateGame ( ) ;
Test ( " Next cutscene action should be Move Cutscene Object 1 " ,
CurrentAction = = ActionType : : MOVE_CUTSCENE_OBJ ) ;
prevCutsceneObjPosition = CurrentCutscene - > GetCutsceneObjects ( ) [ 1 ] - > GetPos ( ) ;
updateGame ( ) ;
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 ) {
updateGame ( ) ;
}
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 ;
updateGame ( ) ;
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 ) ;
updateGame ( ) ;
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 ) ;
updateGame ( ) ;
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 ) ) ;
updateGame ( ) ;
Test ( k . keyName + " key is no longer pressed " ,
! GetKeyPressed ( * this , k ) ) ;
Test ( k . keyName + " key is held down " ,
GetKeyHeld ( * this , k ) ) ;
updateGame ( ) ;
Test ( k . keyName + " key is still held down " ,
GetKeyHeld ( * this , k ) ) ;
for ( int i = 0 ; i < 50 ; i + + ) {
updateGame ( ) ;
}
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 ) ) ;
updateGame ( ) ;
Test ( k . keyName + " key is no longer released " ,
! GetKeyReleased ( * this , k ) ) ;
}
return true ;
}
bool SeasonI : : OnUserUpdate ( float fElapsedTime )
{
return true ;
}
int main ( ) {
SeasonI demo ;
if ( demo . Construct ( WIDTH , HEIGHT , 4 , 4 ) )
demo . Start ( ) ;
return 0 ;
}