# define OLC_PGE_APPLICATION
# include "pixelGameEngine.h"
# include "data.h"
# define OLC_PGEX_SPLASHSCREEN
# include "splash.h"
# include <stack>
using namespace olc ;
enum GAMESTATE {
CUTSCENE_1 ,
CUTSCENE_2 ,
CUTSCENE_3 ,
GAMEWORLD ,
WAITING_FOR_CUTSCENE_3 ,
GAME_OVER ,
} ;
namespace cutscene {
enum CUTSCENE {
NONE ,
PAN_DOME ,
PAUSE_TO_CUTSCENE_3 ,
CUTSCENE_4 ,
TRANSITION_CUTSCENE ,
} ;
}
namespace battle {
enum BATTLESTATE {
NONE ,
WAITING_FOR_CAMERA ,
PLAYER_SELECTION ,
PLAYER_TARGET_SELECTION ,
ENEMY_SELECTION ,
MOVE_RESOLUTION ,
PERFORM_TURN ,
WAIT_TURN_ANIMATION ,
DAMAGE_RESOLUTION ,
} ;
}
# define WIDTH 256
# define HEIGHT 224
# define ALPHA_SCREEN1 128
# define ALPHA_SCREEN2 20
# define FADE_SPD 6
# define MOVE_SPD 0.1
# define MESSAGE_SCROLL_WAIT_SPD 2 //Number of frames to wait.
# define BATTLE_CAMERA_SCROLL_SPD 0.05 //How fast to scroll over to the battle.
class DisplayNumber {
public :
int number ; //Negative means healing.
int frame ; //Frame it was created.
float x , y ;
int alpha = 255 ;
DisplayNumber ( int numb , int x , int y , int frameCount ) {
this - > number = numb ;
this - > x = x ;
this - > y = y ;
this - > frame = frameCount ;
}
} ;
class Animation {
public :
Decal * spr ;
std : : vector < vi2d > frames ;
int frame = 0 ;
bool flipped = false ;
int skip_frames = 1 ; //Essentially the animation speed. Number of frames to wait for next frame.
int width = 32 ;
int height = 32 ;
vi2d getCurrentFrame ( ) {
return frames [ frame ] ;
}
} ;
std : : vector < Animation * > updateAnimationsList ; //Used to store animations in the game that we need to keep track of and update. Probably don't touch this.
class ObjectLoadInfo {
public :
Decal * spr ;
bool hasanim = false ;
Animation * anim ;
ObjectLoadInfo ( Decal * spr ) {
this - > spr = spr ;
}
ObjectLoadInfo ( Decal * spr , Animation * anim ) {
this - > spr = spr ;
this - > anim = anim ;
this - > hasanim = true ;
updateAnimationsList . push_back ( anim ) ;
}
} ;
class Object {
public :
float x , y ;
Decal * spr ;
std : : string name ;
bool hasAnim = false ;
Animation * anim ;
} ;
class WEATHER_POWER {
public :
std : : string description ;
std : : string name ;
Animation * anim ;
Animation * effectAnim ;
int damage ;
int damageRoll ;
int range ;
int playerOwnCount ;
Pixel bgcol ;
Pixel textcol ;
int effectTime ;
WEATHER_POWER ( std : : string name , std : : string desc , Animation * icon , Animation * effect , int dmg , int dmgRoll , int range , Pixel bgcol , Pixel textcol , int effectTime ) {
this - > description = desc ;
this - > name = name ;
this - > anim = icon ;
this - > effectAnim = effect ;
this - > damage = dmg ;
this - > damageRoll = dmgRoll ;
this - > range = range ;
this - > bgcol = bgcol ;
this - > textcol = textcol ;
this - > effectTime = effectTime ;
}
} ;
class Entity {
public :
bool ally ;
int hp ;
int maxhp ;
Decal * spr ;
int x ;
int y ;
std : : string name ;
WEATHER_POWER * selectedMove ;
std : : vector < WEATHER_POWER * > moveSet ;
bool turnComplete = false ;
bool slowed = false ;
int damageFrame = 0 ;
Entity ( Decal * spr , std : : string name , int x , int y , int hp , int maxhp , std : : vector < WEATHER_POWER * > moveset ) {
this - > spr = spr ;
this - > name = name ;
this - > x = x ;
this - > y = y ;
this - > maxhp = hp ;
this - > hp = hp ;
this - > maxhp = maxhp ;
this - > moveSet = moveset ;
}
} ;
class Encounter {
public :
int x , y ;
std : : vector < Entity > entities ;
std : : vector < int > turnOrder ;
} ;
class SeasonsOfLoneliness : public PixelGameEngine
{
public :
SeasonsOfLoneliness ( )
{
sAppName = " Seasons of Loneliness " ;
}
# define STARTING_MAP "assets / maps / map2"
public :
GAMESTATE GAME_STATE = GAMEWORLD ;
int textInd = 0 ;
int cursorX = 0 ;
int transitionTime = 0 ;
bool fade = false ;
int transparency = 0 ;
int frameCount = 0 ;
float elapsedTime = 0 ;
const float TARGET_RATE = 1 / 60.0 ;
std : : string MAP_NAME = " " ;
std : : string CUTSCENE_CONSOLE_TEXT = " " ;
int * * MAP = NULL ;
int MAP_WIDTH = - 1 ;
int MAP_HEIGHT = - 1 ;
Decal * TILES ;
float PLAYER_COORDS [ 2 ] = { 14 , 4 } ;
std : : vector < Object > OBJECTS ;
bool CUTSCENE_ACTIVE = false ;
cutscene : : CUTSCENE CURRENT_CUTSCENE = cutscene : : NONE ;
int CUTSCENE_TIMER = 0 ;
bool CUTSCENE_FLAGS [ 8 ] ;
bool messageBoxVisible = false ;
int messageBoxCursor ;
std : : string messageBoxSpeaker ;
std : : string messageBoxText ;
std : : string messageBoxRefText ;
bool firstNewline = false ;
bool secondNewline = false ;
bool foodMeterVisible = false ;
int foodCount = 3 ;
bool oxygenMeterVisible = false ;
int oxygenQualityLevel = 34 ;
int plantState = 0b10010110101000101010100110101010 ;
SplashScreen splash ;
Animation current_playerAnim ;
Animation playerAnim ;
Animation playerAnimRight ;
Animation playerAnimLeft ;
Animation playerAnimDown ;
Animation playerAnimWalkUp ;
Animation playerAnimWalkDown ;
Animation playerAnimWalkRight ;
Animation playerAnimWalkLeft ;
Animation playerAnimPlantUp ;
Animation playerAnimPlantDown ;
Animation playerAnimPlantRight ;
Animation playerAnimPlantLeft ;
Animation POWER_HAILSTORM_ANIMATION ;
Animation POWER_HURRICANE_ANIMATION ;
Animation POWER_METEOR_SHOWER_ANIMATION ;
Animation POWER_METEOR_STORM_ANIMATION ;
Animation POWER_SNOWSTORM_ANIMATION ;
std : : vector < Entity > entityList ;
WEATHER_POWER * HAILSTORM = new WEATHER_POWER ( " Hailstorm " , " Causes a flurry of hard cold rocks to be unleashed in target area. 60+30d " , & POWER_HAILSTORM_ANIMATION , & POWER_HAILSTORM_ANIMATION , 60 , 30 , 160 , Pixel ( 72 , 160 , 212 , 255 ) , Pixel ( 93 , 161 , 163 , 255 ) , 120 ) ;
WEATHER_POWER * HURRICANE = new WEATHER_POWER ( " Hurricane " , " Causes heavy winds, scattering seeds, heavy rain. 20+10d " , & POWER_HURRICANE_ANIMATION , & POWER_HURRICANE_ANIMATION , 20 , 10 , 200 , Pixel ( 99 , 148 , 132 , 255 ) , Pixel ( 121 , 132 , 140 , 255 ) , 120 ) ;
WEATHER_POWER * METEOR_RAIN = new WEATHER_POWER ( " Meteor Rain " , " Causes space rocks to fall on target area. 50+50d " , & POWER_METEOR_SHOWER_ANIMATION , & POWER_METEOR_SHOWER_ANIMATION , 50 , 50 , 96 , Pixel ( 96 , 86 , 153 , 255 ) , Pixel ( 170 , 103 , 201 , 255 ) , 120 ) ;
WEATHER_POWER * METEOR_STORM = new WEATHER_POWER ( " Meteor Storm " , " Larger space rocks. 120+60d " , & POWER_METEOR_STORM_ANIMATION , & POWER_METEOR_STORM_ANIMATION , 120 , 60 , 140 , Pixel ( 89 , 4 , 33 , 255 ) , Pixel ( 130 , 56 , 1 , 255 ) , 120 ) ;
WEATHER_POWER * SNOWSTORM = new WEATHER_POWER ( " Snowstorm " , " Slows down targets and causes rapid temperature drops. 15+10d " , & POWER_SNOWSTORM_ANIMATION , & POWER_SNOWSTORM_ANIMATION , 15 , 10 , 140 , Pixel ( 183 , 196 , 194 , 255 ) , Pixel ( 222 , 255 , 254 , 255 ) , 120 ) ;
WEATHER_POWER * SANDSTORM = new WEATHER_POWER ( " Sandstorm " , " " , & POWER_HAILSTORM_ANIMATION , & POWER_HAILSTORM_ANIMATION , 5 , 10 , 64 , Pixel ( 93 , 161 , 163 , 255 ) , Pixel ( 72 , 160 , 212 , 255 ) , 120 ) ;
WEATHER_POWER * SEED_STORM = new WEATHER_POWER ( " Seed Storm " , " " , & POWER_HAILSTORM_ANIMATION , & POWER_HAILSTORM_ANIMATION , - 10 , 15 , 30 , Pixel ( 93 , 161 , 163 , 255 ) , Pixel ( 72 , 160 , 212 , 255 ) , 120 ) ;
WEATHER_POWER * AVALANCHE = new WEATHER_POWER ( " Avalanche " , " " , & POWER_HAILSTORM_ANIMATION , & POWER_HAILSTORM_ANIMATION , 15 , 10 , 200 , Pixel ( 93 , 161 , 163 , 255 ) , Pixel ( 72 , 160 , 212 , 255 ) , 120 ) ;
bool IN_BATTLE_ENCOUNTER = false ;
int BATTLE_ENTRY_TIMER = 0 ;
int EFFECT_TIMER = 0 ;
# define WEATHER_POWER_COUNT 5 //Number of powers that are in the game. Update storage array accordingly.
WEATHER_POWER * WEATHER_POWERS [ WEATHER_POWER_COUNT ] = {
HAILSTORM ,
HURRICANE ,
METEOR_RAIN ,
METEOR_STORM ,
SNOWSTORM , } ;
battle : : BATTLESTATE BATTLE_STATE = battle : : NONE ;
std : : vector < WEATHER_POWER * > availablePowers ;
WEATHER_POWER * BATTLE_CARD_SELECTION = HAILSTORM ;
int BATTLE_CARD_SELECTION_IND = 0 ;
int PLAYER_SELECTED_TARGET = - 1 ;
int PLAYER_MAXHP = 60 ;
int PLAYER_HP = PLAYER_MAXHP ;
int BATTLE_CURRENT_TURN_ENTITY = - 1 ;
int CURRENT_ENCOUNTER_IND = - 1 ;
std : : vector < DisplayNumber * > BATTLE_DISPLAY_NUMBERS ;
std : : vector < WEATHER_POWER * > MOVESET_SPIDEY ;
Decal * DOME_DECAL , * FOOD_METER_DECAL , * OXYGEN_METER_DECAL , * PLANT_DECAL ,
* PLAYER_DECAL ,
* WEATHERNODE_EFFECT_DECAL , * POWER_HAILSTORM_DECAL , * POWER_HURRICANE_DECAL , * POWER_METEOR_SHOWER_DECAL , * POWER_METEOR_STORM_DECAL , * POWER_SNOWSTORM_DECAL ,
* SPIDEY_DECAL , * TARGETING_CIRCLE , * TARGETING_RANGE_CIRCLE , * HEALTHBAR_DECAL ;
std : : map < std : : string , ObjectLoadInfo * > BASE_OBJECTS ;
std : : vector < Encounter > ENCOUNTERS ;
Encounter ENCOUNTER_SPIDEY_1 ;
Encounter CURRENT_ENCOUNTER ;
std : : stack < int > turnOrder ;
bool OnUserCreate ( ) override
{
SetPixelMode ( Pixel : : ALPHA ) ;
ConsoleCaptureStdOut ( true ) ;
//ConsoleShow(F1,false);
// Called once at the start, so create things here
TILES = new Decal ( new Sprite ( " assets/tiles.png " ) ) ;
DOME_DECAL = new Decal ( new Sprite ( " assets/dome.png " ) ) ;
FOOD_METER_DECAL = new Decal ( new Sprite ( " assets/corn.png " ) ) ;
OXYGEN_METER_DECAL = new Decal ( new Sprite ( " assets/co2.png " ) ) ;
PLANT_DECAL = new Decal ( new Sprite ( " assets/plant.png " ) ) ;
PLAYER_DECAL = new Decal ( new Sprite ( " assets/player.png " ) ) ;
WEATHERNODE_EFFECT_DECAL = new Decal ( new Sprite ( " assets/weathernode_effect.png " ) ) ;
POWER_HAILSTORM_DECAL = new Decal ( new Sprite ( " assets/hailstorm_icon.png " ) ) ;
POWER_HURRICANE_DECAL = new Decal ( new Sprite ( " assets/hurricane_icon.png " ) ) ;
POWER_METEOR_SHOWER_DECAL = new Decal ( new Sprite ( " assets/meteor_shower_icon.png " ) ) ;
POWER_METEOR_STORM_DECAL = new Decal ( new Sprite ( " assets/meteor_storm.png " ) ) ;
POWER_SNOWSTORM_DECAL = new Decal ( new Sprite ( " assets/snowstorm_icon.png " ) ) ;
SPIDEY_DECAL = new Decal ( new Sprite ( " assets/spidey.png " ) ) ;
TARGETING_CIRCLE = new Decal ( new Sprite ( " assets/targetCircle.png " ) ) ;
TARGETING_RANGE_CIRCLE = new Decal ( new Sprite ( " assets/targetRange.png " ) ) ;
HEALTHBAR_DECAL = new Decal ( new Sprite ( " assets/healthbar.png " ) ) ;
current_playerAnim . spr = PLAYER_DECAL ;
playerAnim . spr = PLAYER_DECAL ;
playerAnimRight . spr = PLAYER_DECAL ;
playerAnimLeft . spr = PLAYER_DECAL ;
playerAnimLeft . flipped = true ;
playerAnimDown . spr = PLAYER_DECAL ;
playerAnimWalkUp . spr = PLAYER_DECAL ;
playerAnimWalkDown . spr = PLAYER_DECAL ;
playerAnimWalkRight . spr = PLAYER_DECAL ;
playerAnimWalkLeft . spr = PLAYER_DECAL ;
playerAnimWalkLeft . flipped = true ;
playerAnimPlantUp . spr = PLAYER_DECAL ;
playerAnimPlantDown . spr = PLAYER_DECAL ;
playerAnimPlantRight . spr = PLAYER_DECAL ;
playerAnimPlantLeft . spr = PLAYER_DECAL ;
playerAnimPlantLeft . flipped = true ;
playerAnim . frames . push_back ( { 64 , 0 } ) ;
playerAnimRight . frames . push_back ( { 32 , 0 } ) ;
playerAnimLeft . frames . push_back ( { 32 , 0 } ) ;
playerAnimDown . frames . push_back ( { 0 , 0 } ) ;
playerAnimWalkUp . frames . push_back ( { 0 , 96 } ) ;
playerAnimWalkUp . frames . push_back ( { 32 , 96 } ) ;
playerAnimWalkUp . frames . push_back ( { 64 , 96 } ) ;
playerAnimWalkRight . frames . push_back ( { 0 , 64 } ) ;
playerAnimWalkLeft . frames . push_back ( { 0 , 64 } ) ;
playerAnimWalkRight . frames . push_back ( { 32 , 64 } ) ;
playerAnimWalkLeft . frames . push_back ( { 32 , 64 } ) ;
playerAnimWalkRight . frames . push_back ( { 64 , 64 } ) ;
playerAnimWalkLeft . frames . push_back ( { 64 , 64 } ) ;
playerAnimWalkDown . frames . push_back ( { 0 , 32 } ) ;
playerAnimWalkDown . frames . push_back ( { 32 , 32 } ) ;
playerAnimWalkDown . frames . push_back ( { 64 , 32 } ) ;
playerAnimPlantUp . frames . push_back ( { 64 , 128 } ) ;
playerAnimPlantRight . frames . push_back ( { 32 , 128 } ) ;
playerAnimPlantLeft . frames . push_back ( { 32 , 128 } ) ;
playerAnimPlantDown . frames . push_back ( { 0 , 128 } ) ;
current_playerAnim = playerAnimWalkDown ;
const int nodeAnimationSkipFrames = 12 ;
POWER_HAILSTORM_ANIMATION . spr = POWER_HAILSTORM_DECAL ;
POWER_HAILSTORM_ANIMATION . frames . push_back ( { 0 , 0 } ) ;
POWER_HAILSTORM_ANIMATION . frames . push_back ( { 32 , 0 } ) ;
POWER_HAILSTORM_ANIMATION . frames . push_back ( { 64 , 0 } ) ;
POWER_HAILSTORM_ANIMATION . skip_frames = nodeAnimationSkipFrames ;
POWER_HURRICANE_ANIMATION . spr = POWER_HURRICANE_DECAL ;
POWER_HURRICANE_ANIMATION . frames . push_back ( { 0 , 0 } ) ;
POWER_HURRICANE_ANIMATION . frames . push_back ( { 32 , 0 } ) ;
POWER_HURRICANE_ANIMATION . frames . push_back ( { 64 , 0 } ) ;
POWER_HURRICANE_ANIMATION . skip_frames = nodeAnimationSkipFrames ;
POWER_METEOR_SHOWER_ANIMATION . spr = POWER_METEOR_SHOWER_DECAL ;
POWER_METEOR_SHOWER_ANIMATION . frames . push_back ( { 0 , 0 } ) ;
POWER_METEOR_SHOWER_ANIMATION . frames . push_back ( { 32 , 0 } ) ;
POWER_METEOR_SHOWER_ANIMATION . frames . push_back ( { 64 , 0 } ) ;
POWER_METEOR_SHOWER_ANIMATION . skip_frames = nodeAnimationSkipFrames ;
POWER_METEOR_STORM_ANIMATION . spr = POWER_METEOR_STORM_DECAL ;
POWER_METEOR_STORM_ANIMATION . frames . push_back ( { 0 , 0 } ) ;
POWER_METEOR_STORM_ANIMATION . frames . push_back ( { 32 , 0 } ) ;
POWER_METEOR_STORM_ANIMATION . frames . push_back ( { 64 , 0 } ) ;
POWER_METEOR_STORM_ANIMATION . skip_frames = nodeAnimationSkipFrames ;
POWER_SNOWSTORM_ANIMATION . spr = POWER_SNOWSTORM_DECAL ;
POWER_SNOWSTORM_ANIMATION . frames . push_back ( { 0 , 0 } ) ;
POWER_SNOWSTORM_ANIMATION . frames . push_back ( { 32 , 0 } ) ;
POWER_SNOWSTORM_ANIMATION . frames . push_back ( { 64 , 0 } ) ;
POWER_SNOWSTORM_ANIMATION . skip_frames = nodeAnimationSkipFrames ;
HAILSTORM - > playerOwnCount = 3 ;
HURRICANE - > playerOwnCount = 1 ;
METEOR_RAIN - > playerOwnCount = 5 ;
MOVESET_SPIDEY . push_back ( SANDSTORM ) ;
MOVESET_SPIDEY . push_back ( SEED_STORM ) ;
MOVESET_SPIDEY . push_back ( AVALANCHE ) ;
ENCOUNTER_SPIDEY_1 . entities . push_back ( * new Entity ( SPIDEY_DECAL , " Spidey " , 2 , 3 , 80 , 80 , MOVESET_SPIDEY ) ) ;
ENCOUNTER_SPIDEY_1 . entities . push_back ( * new Entity ( SPIDEY_DECAL , " Spidey " , 4 , 4 , 80 , 80 , MOVESET_SPIDEY ) ) ;
ENCOUNTER_SPIDEY_1 . entities . push_back ( * new Entity ( SPIDEY_DECAL , " Spidey " , 6 , 2 , 80 , 80 , MOVESET_SPIDEY ) ) ;
ENCOUNTER_SPIDEY_1 . x = 79 ;
ENCOUNTER_SPIDEY_1 . y = 47 ;
ENCOUNTERS . push_back ( ENCOUNTER_SPIDEY_1 ) ;
BASE_OBJECTS [ " DOME " ] = new ObjectLoadInfo ( DOME_DECAL ) ;
BASE_OBJECTS [ " PLANT " ] = new ObjectLoadInfo ( PLANT_DECAL ) ;
BASE_OBJECTS [ " EXIT " ] = new ObjectLoadInfo ( NULL ) ;
BASE_OBJECTS [ " HAILSTORM_NODE " ] = new ObjectLoadInfo ( POWER_HAILSTORM_DECAL , & POWER_HAILSTORM_ANIMATION ) ;
BASE_OBJECTS [ " HURRICANE_NODE " ] = new ObjectLoadInfo ( POWER_HURRICANE_DECAL , & POWER_HURRICANE_ANIMATION ) ;
BASE_OBJECTS [ " METEORSHOWER_NODE " ] = new ObjectLoadInfo ( POWER_METEOR_SHOWER_DECAL , & POWER_METEOR_SHOWER_ANIMATION ) ;
BASE_OBJECTS [ " METEORSTORM_NODE " ] = new ObjectLoadInfo ( POWER_METEOR_STORM_DECAL , & POWER_METEOR_STORM_ANIMATION ) ;
BASE_OBJECTS [ " SNOWSTORM_NODE " ] = new ObjectLoadInfo ( POWER_SNOWSTORM_DECAL , & POWER_SNOWSTORM_ANIMATION ) ;
LoadMap ( STARTING_MAP ) ;
return true ;
}
void GetAnyKeyPress ( ) override {
if ( ! GetKey ( W ) . bPressed & & ! GetKey ( A ) . bPressed & & ! GetKey ( S ) . bPressed & & ! GetKey ( D ) . bPressed & &
! GetKey ( UP ) . bPressed & & ! GetKey ( RIGHT ) . bPressed & & ! GetKey ( DOWN ) . bPressed & & ! GetKey ( LEFT ) . bPressed ) {
ActionButtonPress ( ) ;
}
if ( messageBoxVisible ) {
if ( messageBoxCursor ! = messageBoxRefText . length ( ) ) {
while ( messageBoxCursor < messageBoxRefText . length ( ) ) {
advanceMessageBox ( ) ;
}
} else {
messageBoxVisible = false ;
}
}
switch ( GAME_STATE ) {
case CUTSCENE_1 : {
if ( textInd > = STORY_TEXT1 . length ( ) ) {
fadeOut ( ) ;
}
} break ;
}
}
void ActionButtonPress ( ) {
switch ( GAME_STATE ) {
case GAMEWORLD : {
if ( PLAYER_COORDS [ 0 ] > = 8 & & PLAYER_COORDS [ 0 ] < 12 & &
PLAYER_COORDS [ 1 ] > = 2 & & PLAYER_COORDS [ 1 ] < 6 ) {
//cout<<"You are standing over plant "<<getPlantId((int)PLAYER_COORDS[0],(int)PLAYER_COORDS[1])<<" in state "<<getPlantStatus((int)PLAYER_COORDS[0],(int)PLAYER_COORDS[1]);
if ( getPlantStatus ( ( int ) PLAYER_COORDS [ 0 ] , ( int ) PLAYER_COORDS [ 1 ] ) = = 2 ) {
setPlantStatus ( ( int ) PLAYER_COORDS [ 0 ] , ( int ) PLAYER_COORDS [ 1 ] , 0 ) ;
}
}
} break ;
}
switch ( BATTLE_STATE ) {
case battle : : PLAYER_SELECTION : {
BATTLE_STATE = battle : : PLAYER_TARGET_SELECTION ;
if ( PLAYER_SELECTED_TARGET = = - 1 | | CURRENT_ENCOUNTER . entities [ PLAYER_SELECTED_TARGET ] . hp < = 0 ) {
for ( int i = 0 ; i < CURRENT_ENCOUNTER . entities . size ( ) ; i + + ) {
Entity ent = CURRENT_ENCOUNTER . entities [ i ] ;
if ( ! ent . ally & & ent . hp > 0 ) {
PLAYER_SELECTED_TARGET = i ;
break ;
}
}
}
} break ;
case battle : : PLAYER_TARGET_SELECTION : {
//Remove the card from inventory.
BATTLE_CARD_SELECTION - > playerOwnCount - - ;
BATTLE_STATE = battle : : ENEMY_SELECTION ;
for ( int i = 0 ; i < CURRENT_ENCOUNTER . entities . size ( ) ; i + + ) {
if ( CURRENT_ENCOUNTER . entities [ i ] . hp > 0 ) {
CURRENT_ENCOUNTER . entities [ i ] . selectedMove = CURRENT_ENCOUNTER . entities [ i ] . moveSet [ rand ( ) % CURRENT_ENCOUNTER . entities [ i ] . moveSet . size ( ) ] ;
CURRENT_ENCOUNTER . entities [ i ] . turnComplete = false ;
}
}
BATTLE_STATE = battle : : MOVE_RESOLUTION ;
//Seed Storm has prio.
if ( BATTLE_CARD_SELECTION_IND ! = - 1 & & BATTLE_CARD_SELECTION - > name . compare ( " Seed Storm " ) = = 0 ) {
turnOrder . push ( - 1 ) ;
BATTLE_CARD_SELECTION_IND = - 1 ;
}
for ( int i = 0 ; i < CURRENT_ENCOUNTER . entities . size ( ) ; i + + ) {
if ( CURRENT_ENCOUNTER . entities [ i ] . hp > 0 & & ! CURRENT_ENCOUNTER . entities [ i ] . turnComplete & &
CURRENT_ENCOUNTER . entities [ i ] . selectedMove - > name . compare ( " Seed Storm " ) = = 0 ) {
turnOrder . push ( i ) ;
CURRENT_ENCOUNTER . entities [ i ] . turnComplete = true ;
}
}
//Otherwise, every enemy has a chance to go before the player unless they are slowed, then they always go after.
for ( int i = 0 ; i < CURRENT_ENCOUNTER . entities . size ( ) ; i + + ) {
Entity * ent = & CURRENT_ENCOUNTER . entities [ i ] ;
if ( ent - > hp > 0 & & ! ent - > turnComplete & &
! ent - > slowed & & rand ( ) % 2 = = 0 ) {
turnOrder . push ( i ) ;
ent - > turnComplete = true ;
}
}
if ( BATTLE_CARD_SELECTION_IND ! = - 1 ) {
turnOrder . push ( - 1 ) ;
BATTLE_CARD_SELECTION_IND = - 1 ;
}
//Finally, any enemies that haven't gone will now go.
for ( int i = 0 ; i < CURRENT_ENCOUNTER . entities . size ( ) ; i + + ) {
Entity * ent = & CURRENT_ENCOUNTER . entities [ i ] ;
if ( ent - > hp > 0 & & ! ent - > turnComplete ) {
turnOrder . push ( i ) ;
ent - > turnComplete = true ;
}
}
BATTLE_STATE = battle : : PERFORM_TURN ;
BATTLE_CURRENT_TURN_ENTITY = turnOrder . top ( ) ;
turnOrder . pop ( ) ;
BATTLE_STATE = battle : : WAIT_TURN_ANIMATION ;
EFFECT_TIMER = 0 ;
} break ;
}
}
bool OnUserUpdate ( float fElapsedTime ) override
{
elapsedTime + = fElapsedTime ;
while ( elapsedTime > TARGET_RATE ) {
elapsedTime - = TARGET_RATE ;
updateGame ( ) ;
}
if ( GetKey ( F1 ) . bPressed ) {
ConsoleShow ( F1 , false ) ;
}
if ( playerCanMove ( ) ) {
if ( GetKey ( D ) . bPressed | | GetKey ( RIGHT ) . bPressed | | GetKey ( NP6 ) . bPressed ) {
changeAnimation ( playerAnimWalkRight ) ;
}
if ( GetKey ( A ) . bPressed | | GetKey ( LEFT ) . bPressed | | GetKey ( NP4 ) . bPressed ) {
changeAnimation ( playerAnimWalkLeft ) ;
}
if ( GetKey ( W ) . bPressed | | GetKey ( UP ) . bPressed | | GetKey ( NP8 ) . bPressed ) {
changeAnimation ( playerAnimWalkUp ) ;
}
if ( GetKey ( S ) . bPressed | | GetKey ( DOWN ) . bPressed | | GetKey ( NP5 ) . bPressed | | GetKey ( NP2 ) . bPressed ) {
changeAnimation ( playerAnimWalkDown ) ;
}
if ( ! GetKey ( D ) . bHeld & & ! GetKey ( RIGHT ) . bHeld & & ! GetKey ( NP6 ) . bHeld & &
! GetKey ( A ) . bHeld & & ! GetKey ( LEFT ) . bHeld & & ! GetKey ( NP4 ) . bHeld & &
! GetKey ( S ) . bHeld & & ! GetKey ( UP ) . bHeld & & ! GetKey ( NP8 ) . bHeld & &
! GetKey ( W ) . bHeld & & ! GetKey ( DOWN ) . bHeld & & ! GetKey ( NP5 ) . bHeld & & ! GetKey ( NP2 ) . bHeld ) {
if ( GetKey ( D ) . bReleased | | GetKey ( RIGHT ) . bReleased | | GetKey ( NP6 ) . bReleased ) {
changeAnimation ( playerAnimRight ) ;
}
if ( GetKey ( A ) . bReleased | | GetKey ( LEFT ) . bReleased | | GetKey ( NP4 ) . bReleased ) {
changeAnimation ( playerAnimLeft ) ;
}
if ( GetKey ( W ) . bReleased | | GetKey ( UP ) . bReleased | | GetKey ( NP8 ) . bReleased ) {
changeAnimation ( playerAnim ) ;
}
if ( GetKey ( S ) . bReleased | | GetKey ( DOWN ) . bReleased | | GetKey ( NP5 ) . bReleased | | GetKey ( NP2 ) . bReleased ) {
changeAnimation ( playerAnimDown ) ;
}
}
} else
if ( IN_BATTLE_ENCOUNTER ) {
switch ( BATTLE_STATE ) {
case battle : : PLAYER_SELECTION : {
if ( GetKey ( D ) . bPressed | | GetKey ( RIGHT ) . bPressed | | GetKey ( NP6 ) . bPressed ) {
BATTLE_CARD_SELECTION_IND = ( BATTLE_CARD_SELECTION_IND + 1 ) % availablePowers . size ( ) ;
BATTLE_CARD_SELECTION = availablePowers [ BATTLE_CARD_SELECTION_IND ] ;
}
if ( GetKey ( A ) . bPressed | | GetKey ( LEFT ) . bPressed | | GetKey ( NP4 ) . bPressed ) {
if ( - - BATTLE_CARD_SELECTION_IND < 0 ) {
BATTLE_CARD_SELECTION_IND = availablePowers . size ( ) - 1 ;
}
BATTLE_CARD_SELECTION = availablePowers [ BATTLE_CARD_SELECTION_IND ] ;
}
} break ;
case battle : : PLAYER_TARGET_SELECTION : {
if ( GetKey ( D ) . bPressed | | GetKey ( RIGHT ) . bPressed | | GetKey ( NP6 ) . bPressed ) {
while ( true ) {
PLAYER_SELECTED_TARGET = ( PLAYER_SELECTED_TARGET + 1 ) % CURRENT_ENCOUNTER . entities . size ( ) ;
if ( CURRENT_ENCOUNTER . entities [ PLAYER_SELECTED_TARGET ] . hp > 0 ) {
break ;
}
}
}
if ( GetKey ( W ) . bPressed | | GetKey ( UP ) . bPressed | | GetKey ( NP8 ) . bPressed ) {
PLAYER_SELECTED_TARGET = - 1 ;
BATTLE_STATE = battle : : PLAYER_SELECTION ;
}
if ( GetKey ( A ) . bPressed | | GetKey ( LEFT ) . bPressed | | GetKey ( NP4 ) . bPressed ) {
while ( true ) {
if ( - - PLAYER_SELECTED_TARGET < 0 ) {
PLAYER_SELECTED_TARGET = CURRENT_ENCOUNTER . entities . size ( ) - 1 ;
}
if ( CURRENT_ENCOUNTER . entities [ PLAYER_SELECTED_TARGET ] . hp > 0 ) {
break ;
}
}
}
} break ;
}
}
drawGame ( ) ;
// called once per frame
return true ;
}
void fadeOutCompleted ( ) {
switch ( GAME_STATE ) {
case CUTSCENE_1 : {
GAME_STATE = CUTSCENE_2 ;
PlayCutscene ( cutscene : : PAN_DOME ) ;
fadeIn ( ) ;
} break ;
case CUTSCENE_2 : {
fadeIn ( ) ;
PlayCutscene ( cutscene : : CUTSCENE_4 ) ;
GAME_STATE = GAMEWORLD ;
} break ;
}
switch ( CURRENT_CUTSCENE ) {
case cutscene : : TRANSITION_CUTSCENE : {
LoadMap ( " assets/maps/map1 " ) ;
PLAYER_COORDS [ 0 ] = 40 ;
PLAYER_COORDS [ 1 ] = 37 ;
fadeIn ( ) ;
EndCutscene ( ) ;
} break ;
}
}
void fadeInCompleted ( ) {
}
void PlayCutscene ( cutscene : : CUTSCENE scene ) {
CURRENT_CUTSCENE = scene ;
switch ( scene ) {
case cutscene : : PAN_DOME : {
PLAYER_COORDS [ 0 ] = 14 ;
PLAYER_COORDS [ 1 ] = 35 + ( 64 / 2 / 32 ) ;
} break ;
case cutscene : : PAUSE_TO_CUTSCENE_3 : {
CUTSCENE_CONSOLE_TEXT . clear ( ) ;
textInd = 0 ;
} break ;
case cutscene : : CUTSCENE_4 : {
LoadMap ( " assets/maps/map2 " ) ;
PLAYER_COORDS [ 0 ] = 16 ;
PLAYER_COORDS [ 1 ] = 6 ;
} break ;
}
for ( int i = 0 ; i < 8 ; i + + ) {
CUTSCENE_FLAGS [ i ] = false ;
}
CUTSCENE_TIMER = 0 ;
}
void updateGame ( ) {
frameCount + + ;
if ( CURRENT_CUTSCENE ! = cutscene : : NONE ) {
CUTSCENE_TIMER + + ;
}
if ( fade & & transparency < 255 ) {
transparency = std : : clamp ( transparency + FADE_SPD , 0 , 255 ) ;
if ( transparency = = 255 ) {
fadeOutCompleted ( ) ;
}
} else
if ( ! fade & & transparency > 0 ) {
transparency = std : : clamp ( transparency - FADE_SPD , 0 , 255 ) ;
if ( transparency = = 0 ) {
fadeInCompleted ( ) ;
}
}
if ( messageBoxVisible ) {
if ( frameCount % MESSAGE_SCROLL_WAIT_SPD = = 0 ) {
if ( messageBoxCursor < messageBoxRefText . length ( ) ) {
advanceMessageBox ( ) ;
}
}
}
if ( frameCount % current_playerAnim . skip_frames = = 0 ) {
current_playerAnim . frame = ( current_playerAnim . frame + 1 ) % current_playerAnim . frames . size ( ) ;
}
for ( auto anim : updateAnimationsList ) {
if ( frameCount % anim - > skip_frames = = 0 ) {
anim - > frame = ( anim - > frame + 1 ) % anim - > frames . size ( ) ;
}
}
if ( playerCanMove ( ) ) {
bool changed = false ;
if ( GetKey ( D ) . bHeld | | GetKey ( RIGHT ) . bHeld | | GetKey ( NP6 ) . bHeld ) {
PLAYER_COORDS [ 0 ] = std : : clamp ( PLAYER_COORDS [ 0 ] + MOVE_SPD , 0.1 , ( double ) MAP_WIDTH ) ;
//ConsoleClear();
//cout<<"("<<PLAYER_COORDS[0]<<","<<PLAYER_COORDS[1]<<+")";
if ( ! changed & & & current_playerAnim ! = & playerAnimWalkRight ) {
changeAnimation ( playerAnimWalkRight ) ;
changed = true ;
}
}
if ( GetKey ( A ) . bHeld | | GetKey ( LEFT ) . bHeld | | GetKey ( NP4 ) . bHeld ) {
PLAYER_COORDS [ 0 ] = std : : clamp ( PLAYER_COORDS [ 0 ] - MOVE_SPD , 0.1 , ( double ) MAP_WIDTH ) ;
//ConsoleClear();
//cout<<"("<<PLAYER_COORDS[0]<<","<<PLAYER_COORDS[1]<<+")";
if ( ! changed & & & current_playerAnim ! = & playerAnimWalkLeft ) {
changeAnimation ( playerAnimWalkLeft ) ;
changed = true ;
}
}
if ( GetKey ( W ) . bHeld | | GetKey ( UP ) . bHeld | | GetKey ( NP8 ) . bHeld ) {
PLAYER_COORDS [ 1 ] = std : : clamp ( PLAYER_COORDS [ 1 ] - MOVE_SPD , 0.1 , ( double ) MAP_HEIGHT ) ;
//ConsoleClear();
//cout<<"("<<PLAYER_COORDS[0]<<","<<PLAYER_COORDS[1]<<+")";
if ( ! changed & & & current_playerAnim ! = & playerAnimWalkUp ) {
changeAnimation ( playerAnimWalkUp ) ;
changed = true ;
}
}
if ( GetKey ( S ) . bHeld | | GetKey ( DOWN ) . bHeld | | GetKey ( NP5 ) . bHeld | | GetKey ( NP2 ) . bHeld ) {
PLAYER_COORDS [ 1 ] = std : : clamp ( PLAYER_COORDS [ 1 ] + MOVE_SPD , 0.1 , ( double ) MAP_HEIGHT ) ;
//ConsoleClear();
//cout<<"("<<PLAYER_COORDS[0]<<","<<PLAYER_COORDS[1]<<+")";
if ( ! changed & & & current_playerAnim ! = & playerAnimWalkDown ) {
changeAnimation ( playerAnimWalkDown ) ;
changed = true ;
}
}
}
for ( int i = 0 ; i < OBJECTS . size ( ) ; i + + ) {
Object obj = OBJECTS [ i ] ;
if ( obj . name . compare ( " HAILSTORM_NODE " ) = = 0 & & collidesWithPlayer ( obj ) ) {
int amountGained = rand ( ) % 4 + 2 ;
HAILSTORM - > playerOwnCount + = amountGained ;
std : : cout < < " Increased HAILSTORM power inventory count by " < < amountGained < < " . \n " ;
OBJECTS . erase ( OBJECTS . begin ( ) + i - - ) ;
} else
if ( obj . name . compare ( " HURRICANE_NODE " ) = = 0 & & collidesWithPlayer ( obj ) ) {
int amountGained = rand ( ) % 4 + 2 ;
HURRICANE - > playerOwnCount + = amountGained ;
std : : cout < < " Increased HURRICANE power inventory count by " < < amountGained < < " . \n " ;
OBJECTS . erase ( OBJECTS . begin ( ) + i - - ) ;
} else
if ( obj . name . compare ( " METEORSHOWER_NODE " ) = = 0 & & collidesWithPlayer ( obj ) ) {
int amountGained = rand ( ) % 4 + 2 ;
METEOR_RAIN - > playerOwnCount + = amountGained ;
std : : cout < < " Increased METEORSHOWER power inventory count by " < < amountGained < < " . \n " ;
OBJECTS . erase ( OBJECTS . begin ( ) + i - - ) ;
} else
if ( obj . name . compare ( " METEORSTORM_NODE " ) = = 0 & & collidesWithPlayer ( obj ) ) {
int amountGained = rand ( ) % 4 + 2 ;
METEOR_STORM - > playerOwnCount + = amountGained ;
std : : cout < < " Increased METEORSTORM power inventory count by " < < amountGained < < " . \n " ;
OBJECTS . erase ( OBJECTS . begin ( ) + i - - ) ;
} else
if ( obj . name . compare ( " SNOWSTORM_NODE " ) = = 0 & & collidesWithPlayer ( obj ) ) {
int amountGained = rand ( ) % 4 + 2 ;
SNOWSTORM - > playerOwnCount + = amountGained ;
std : : cout < < " Increased SNOWSTORM power inventory count by " < < amountGained < < " . \n " ;
OBJECTS . erase ( OBJECTS . begin ( ) + i - - ) ;
}
if ( obj . name . compare ( " EXIT " ) = = 0 & & collidesWithPlayer ( obj ) ) {
fadeOut ( ) ;
PlayCutscene ( cutscene : : TRANSITION_CUTSCENE ) ;
}
}
if ( ! IN_BATTLE_ENCOUNTER & & MAP_NAME . compare ( " assets/maps/map1 " ) = = 0 ) {
for ( int i = 0 ; i < ENCOUNTERS . size ( ) ; i + + ) {
Encounter enc = ENCOUNTERS [ i ] ;
if ( collidesWithPlayer ( enc ) ) {
availablePowers . erase ( availablePowers . begin ( ) , availablePowers . end ( ) ) ;
IN_BATTLE_ENCOUNTER = true ;
CURRENT_ENCOUNTER = enc ;
CURRENT_ENCOUNTER_IND = i ;
BATTLE_ENTRY_TIMER = 0 ;
BATTLE_STATE = battle : : WAITING_FOR_CAMERA ;
for ( int i = 0 ; i < WEATHER_POWER_COUNT ; i + + ) {
if ( WEATHER_POWERS [ i ] - > playerOwnCount > 0 ) {
availablePowers . push_back ( WEATHER_POWERS [ i ] ) ;
//cout<<"There are x"<<WEATHER_POWERS[i]->playerOwnCount<<" of "<<WEATHER_POWERS[i]->name<<"\n";
}
}
BATTLE_CARD_SELECTION_IND = 0 ;
BATTLE_CARD_SELECTION = availablePowers [ BATTLE_CARD_SELECTION_IND ] ;
PLAYER_SELECTED_TARGET = - 1 ;
}
}
}
for ( int i = 0 ; i < BATTLE_DISPLAY_NUMBERS . size ( ) ; i + + ) {
DisplayNumber * numb = BATTLE_DISPLAY_NUMBERS [ i ] ;
if ( frameCount - numb - > frame > 60 ) {
BATTLE_DISPLAY_NUMBERS . erase ( BATTLE_DISPLAY_NUMBERS . begin ( ) + i - - ) ;
delete numb ;
} else {
numb - > y - = 0.01 ;
numb - > alpha - = 4 ;
}
}
if ( IN_BATTLE_ENCOUNTER ) {
BATTLE_ENTRY_TIMER + + ;
switch ( BATTLE_STATE ) {
case battle : : WAITING_FOR_CAMERA : {
if ( BATTLE_ENTRY_TIMER > 45 ) {
int TARGET_COORDS_X = CURRENT_ENCOUNTER . x + WIDTH / 32 / 2 ;
int TARGET_COORDS_Y = CURRENT_ENCOUNTER . y + HEIGHT / 32 / 2 ;
if ( PLAYER_COORDS [ 0 ] = = TARGET_COORDS_X & & PLAYER_COORDS [ 1 ] = = TARGET_COORDS_Y ) {
BATTLE_STATE = battle : : PLAYER_SELECTION ;
EFFECT_TIMER = 0 ;
} else
if ( PLAYER_COORDS [ 0 ] ! = TARGET_COORDS_X ) {
if ( PLAYER_COORDS [ 0 ] < TARGET_COORDS_X ) {
PLAYER_COORDS [ 0 ] + = BATTLE_CAMERA_SCROLL_SPD ;
if ( PLAYER_COORDS [ 0 ] > TARGET_COORDS_X ) {
PLAYER_COORDS [ 0 ] = TARGET_COORDS_X ;
}
} else {
PLAYER_COORDS [ 0 ] - = BATTLE_CAMERA_SCROLL_SPD ;
if ( PLAYER_COORDS [ 0 ] < TARGET_COORDS_X ) {
PLAYER_COORDS [ 0 ] = TARGET_COORDS_X ;
}
}
}
if ( PLAYER_COORDS [ 1 ] ! = TARGET_COORDS_Y ) {
if ( PLAYER_COORDS [ 1 ] < TARGET_COORDS_Y ) {
PLAYER_COORDS [ 1 ] + = BATTLE_CAMERA_SCROLL_SPD ;
if ( PLAYER_COORDS [ 1 ] > TARGET_COORDS_Y ) {
PLAYER_COORDS [ 1 ] = TARGET_COORDS_Y ;
}
} else {
PLAYER_COORDS [ 1 ] - = BATTLE_CAMERA_SCROLL_SPD ;
if ( PLAYER_COORDS [ 1 ] < TARGET_COORDS_Y ) {
PLAYER_COORDS [ 1 ] = TARGET_COORDS_Y ;
}
}
}
}
} break ;
case battle : : WAIT_TURN_ANIMATION : {
EFFECT_TIMER + + ;
WEATHER_POWER * ref ;
if ( BATTLE_CURRENT_TURN_ENTITY = = - 1 ) {
ref = BATTLE_CARD_SELECTION ;
} else {
ref = CURRENT_ENCOUNTER . entities [ BATTLE_CURRENT_TURN_ENTITY ] . selectedMove ;
}
if ( EFFECT_TIMER = = 30 & & ref - > name . compare ( " Seed Storm " ) = = 0 ) {
if ( BATTLE_CURRENT_TURN_ENTITY = = - 1 ) {
effectRadius ( { PLAYER_COORDS [ 0 ] , PLAYER_COORDS [ 1 ] } , ref , true ) ;
} else {
effectRadius ( { CURRENT_ENCOUNTER . entities [ BATTLE_CURRENT_TURN_ENTITY ] . x + CURRENT_ENCOUNTER . x , CURRENT_ENCOUNTER . entities [ BATTLE_CURRENT_TURN_ENTITY ] . y + CURRENT_ENCOUNTER . y } , ref , false ) ;
}
} else
if ( EFFECT_TIMER = = ref - > effectTime - 10 ) {
if ( BATTLE_CURRENT_TURN_ENTITY = = - 1 ) {
effectRadius ( { CURRENT_ENCOUNTER . entities [ PLAYER_SELECTED_TARGET ] . x + CURRENT_ENCOUNTER . x , CURRENT_ENCOUNTER . entities [ PLAYER_SELECTED_TARGET ] . y + CURRENT_ENCOUNTER . y } , ref , true ) ;
} else {
effectRadius ( { PLAYER_COORDS [ 0 ] , PLAYER_COORDS [ 1 ] } , ref , false ) ;
}
}
if ( EFFECT_TIMER > ref - > effectTime ) {
BATTLE_STATE = battle : : DAMAGE_RESOLUTION ;
EFFECT_TIMER = 0 ;
}
} break ;
case battle : : DAMAGE_RESOLUTION : {
EFFECT_TIMER + + ;
if ( EFFECT_TIMER > 60 ) {
std : : cout < < " In here: " < < EFFECT_TIMER < < " \n " ;
if ( turnOrder . empty ( ) ) {
bool allDead = true ;
for ( auto & ent : CURRENT_ENCOUNTER . entities ) {
if ( ent . hp > 0 ) {
allDead = false ;
break ;
}
}
if ( allDead ) {
IN_BATTLE_ENCOUNTER = false ;
ENCOUNTERS . erase ( ENCOUNTERS . begin ( ) + CURRENT_ENCOUNTER_IND ) ;
BATTLE_CARD_SELECTION_IND = 0 ;
PLAYER_SELECTED_TARGET = - 1 ;
BATTLE_STATE = battle : : NONE ;
} else {
BATTLE_STATE = battle : : PLAYER_SELECTION ;
PLAYER_SELECTED_TARGET = - 1 ;
}
} else {
BATTLE_CURRENT_TURN_ENTITY = turnOrder . top ( ) ;
turnOrder . pop ( ) ;
if ( BATTLE_CURRENT_TURN_ENTITY = = - 1 ) {
if ( PLAYER_HP < = 0 ) {
GAME_STATE = GAME_OVER ;
break ;
}
} else {
if ( CURRENT_ENCOUNTER . entities [ BATTLE_CURRENT_TURN_ENTITY ] . hp < = 0 ) {
break ;
}
}
BATTLE_STATE = battle : : WAIT_TURN_ANIMATION ;
EFFECT_TIMER = 0 ;
}
}
} break ;
}
}
switch ( CURRENT_CUTSCENE ) {
case cutscene : : CUTSCENE_4 : {
if ( ! messageBoxVisible ) {
if ( ! CUTSCENE_FLAGS [ 0 ] ) {
CUTSCENE_FLAGS [ 0 ] = true ;
DisplayMessageBox ( 0 ) ;
} else
if ( ! CUTSCENE_FLAGS [ 1 ] ) {
CUTSCENE_FLAGS [ 1 ] = true ;
DisplayMessageBox ( 1 ) ;
} else
if ( ! CUTSCENE_FLAGS [ 2 ] ) {
CUTSCENE_FLAGS [ 2 ] = true ;
DisplayMessageBox ( 2 ) ;
foodMeterVisible = true ;
} else
if ( ! CUTSCENE_FLAGS [ 3 ] ) {
CUTSCENE_FLAGS [ 3 ] = true ;
DisplayMessageBox ( 3 ) ;
oxygenMeterVisible = true ;
}
}
} break ;
}
switch ( GAME_STATE ) {
case CUTSCENE_1 :
case CUTSCENE_3 : {
std : : string refText ;
switch ( GAME_STATE ) {
case CUTSCENE_1 : {
refText = STORY_TEXT1 ;
} break ;
case CUTSCENE_3 : {
refText = STORY_TEXT2 ;
} break ;
}
if ( GAME_STATE = = CUTSCENE_3 & & frameCount % 4 ! = 0 ) { break ; }
if ( textInd < refText . length ( ) ) {
char c = refText [ textInd + + ] ;
CUTSCENE_CONSOLE_TEXT + = c ;
if ( c ! = ' \n ' ) {
cursorX + + ;
} else {
cursorX = 0 ;
}
if ( GetTextSize ( CUTSCENE_CONSOLE_TEXT ) . x > WIDTH - 32 ) {
int tempIndex = textInd ;
while ( CUTSCENE_CONSOLE_TEXT [ - - tempIndex ] ! = ' ' ) {
CUTSCENE_CONSOLE_TEXT . erase ( tempIndex ) ;
cursorX - - ;
}
CUTSCENE_CONSOLE_TEXT . erase ( tempIndex + + ) ;
CUTSCENE_CONSOLE_TEXT + = ' \n ' ;
cursorX = 0 ;
while ( tempIndex < textInd ) {
CUTSCENE_CONSOLE_TEXT + = refText [ tempIndex + + ] ;
cursorX + + ;
}
}
}
} break ;
case CUTSCENE_2 : {
//FLAG 0 - When flipped on, camera stops.
if ( ! CUTSCENE_FLAGS [ 0 ] ) {
PLAYER_COORDS [ 0 ] + = 0.06 ;
} else {
if ( CUTSCENE_TIMER > 120 ) {
fadeOut ( ) ;
}
}
if ( PLAYER_COORDS [ 0 ] > 38 + ( 128 / 2 / 32 ) ) {
PLAYER_COORDS [ 0 ] = 38 + ( 128 / 2 / 32 ) ;
CUTSCENE_FLAGS [ 0 ] = true ;
CUTSCENE_TIMER = 0 ;
}
} break ;
case WAITING_FOR_CUTSCENE_3 : {
if ( transparency > 200 ) {
GAME_STATE = CUTSCENE_3 ;
}
} break ;
}
}
void advanceMessageBox ( ) {
char c = messageBoxRefText [ messageBoxCursor + + ] ;
printf ( " %c " , c ) ;
if ( c = = ' \n ' ) {
if ( ! firstNewline ) {
firstNewline = true ;
return ;
} else if ( ! secondNewline ) {
secondNewline = true ;
return ;
}
}
if ( firstNewline & & ! secondNewline ) {
messageBoxSpeaker + = c ;
return ;
}
messageBoxText + = c ;
if ( GetTextSizeProp ( messageBoxText ) . x > WIDTH - 16 ) {
int tempIndex = messageBoxCursor ;
while ( messageBoxText [ - - tempIndex ] ! = ' ' ) {
messageBoxText . erase ( tempIndex ) ;
}
messageBoxText . erase ( tempIndex + + ) ;
messageBoxText + = ' \n ' ;
while ( tempIndex < messageBoxCursor ) {
messageBoxText + = messageBoxRefText [ tempIndex + + ] ;
}
}
}
void drawGame ( ) {
switch ( GAME_STATE ) {
case CUTSCENE_1 : {
DrawStringDecal ( { 16 , 16 } , CUTSCENE_CONSOLE_TEXT , GREEN , { 1 , 1 } ) ;
if ( textInd < STORY_TEXT1 . length ( ) ) {
FillRectDecal ( { ( float ) ( 16 + ( cursorX ) * 8 % ( WIDTH - 32 ) ) , ( float ) ( 8 + GetTextSize ( CUTSCENE_CONSOLE_TEXT ) . y + ( ( cursorX = = 28 ) ? 8 : 0 ) ) } , { 4 , 8 } , GREEN ) ;
} else {
FillRectDecal ( { ( float ) ( 16 + ( cursorX ) * 8 % ( WIDTH - 32 ) ) , ( float ) ( 8 + GetTextSize ( CUTSCENE_CONSOLE_TEXT ) . y + ( ( cursorX = = 28 ) ? 8 : 0 ) ) } , { 4 , 8 } , Pixel ( 0 , 255 , 0 , ( 0.5 * sin ( frameCount * 4 / 60.0 ) + 0.5 ) * 256 ) ) ;
}
GradientFillRectDecal ( { 0 , 0 } , { WIDTH / 2 , HEIGHT / 2 } , { 20 , 28 , 22 , ALPHA_SCREEN1 } , { 20 , 28 , 22 , ALPHA_SCREEN1 } , { 20 , 28 , 22 , ALPHA_SCREEN2 } , { 20 , 28 , 22 , ALPHA_SCREEN1 } ) ;
GradientFillRectDecal ( { WIDTH / 2 , 0 } , { WIDTH / 2 , HEIGHT / 2 } , { 20 , 28 , 22 , ALPHA_SCREEN1 } , { 20 , 28 , 22 , ALPHA_SCREEN2 } , { 20 , 28 , 22 , ALPHA_SCREEN1 } , { 20 , 28 , 22 , ALPHA_SCREEN1 } ) ;
GradientFillRectDecal ( { 0 , HEIGHT / 2 } , { WIDTH / 2 , HEIGHT / 2 } , { 20 , 28 , 22 , ALPHA_SCREEN1 } , { 20 , 28 , 22 , ALPHA_SCREEN1 } , { 20 , 28 , 22 , ALPHA_SCREEN1 } , { 20 , 28 , 22 , ALPHA_SCREEN2 } ) ;
GradientFillRectDecal ( { WIDTH / 2 , HEIGHT / 2 } , { WIDTH / 2 , HEIGHT / 2 } , { 20 , 28 , 22 , ALPHA_SCREEN2 } , { 20 , 28 , 22 , ALPHA_SCREEN1 } , { 20 , 28 , 22 , ALPHA_SCREEN1 } , { 20 , 28 , 22 , ALPHA_SCREEN1 } ) ;
} break ;
case CUTSCENE_2 :
case GAMEWORLD : {
DrawGameWorld ( ) ;
int meterYOffset = 2 ;
if ( CURRENT_CUTSCENE = = cutscene : : NONE ) {
if ( foodMeterVisible ) {
DrawStringDecal ( { WIDTH - 36 * 0.4 - GetTextSize ( std : : to_string ( foodCount ) ) . x * 1 - 8 , meterYOffset + 2 } , std : : to_string ( foodCount ) , BLUE , { 1 , 1 } ) ;
DrawStringDecal ( { WIDTH - 36 * 0.4 - GetTextSize ( std : : to_string ( foodCount ) ) . x * 1 - 7 , meterYOffset + 2 } , std : : to_string ( foodCount ) , BLACK , { 1 , 1 } ) ;
DrawDecal ( { WIDTH - 52 * 0.4 , meterYOffset } , FOOD_METER_DECAL , { 0.4 , 0.4 } ) ;
meterYOffset + = ( 2 + 48 * 0.4 ) ;
}
if ( oxygenMeterVisible ) {
DrawStringDecal ( { WIDTH - 36 * 0.4 - GetTextSize ( std : : to_string ( oxygenQualityLevel ) + " % " ) . x * 1 - 8 , meterYOffset + 2 } , std : : to_string ( oxygenQualityLevel ) + " % " , BLUE , { 1 , 1 } ) ;
DrawStringDecal ( { WIDTH - 36 * 0.4 - GetTextSize ( std : : to_string ( oxygenQualityLevel ) + " % " ) . x * 1 - 7 , meterYOffset + 2 } , std : : to_string ( oxygenQualityLevel ) + " % " , BLACK , { 1 , 1 } ) ;
DrawDecal ( { WIDTH - 52 * 0.4 , meterYOffset } , OXYGEN_METER_DECAL , { 0.4 , 0.4 } ) ;
meterYOffset + = ( 2 + 48 * 0.4 ) ;
}
DrawPartialDecal ( { WIDTH / 2 - 16 + ( current_playerAnim . flipped ? 32 : 0 ) , HEIGHT / 2 - 16 } , current_playerAnim . spr , current_playerAnim . getCurrentFrame ( ) , { 32 , 32 } , { current_playerAnim . flipped ? - 1 : 1 , 1 } ) ;
if ( IN_BATTLE_ENCOUNTER & & BATTLE_ENTRY_TIMER < 45 ) {
DrawStringDecal ( { WIDTH / 2 - 16 + ( current_playerAnim . flipped ? 32 : 0 ) + 8 , HEIGHT / 2 - 16 - sin ( frameCount * 12 / 60.0 ) * 4 - 12 } , " !! " , RED ) ;
}
}
} break ;
case CUTSCENE_3 : {
DrawStringDecal ( { 48 , 16 } , CUTSCENE_CONSOLE_TEXT , Pixel ( 100 , 10 , 255 ) , { 2 , 2 } ) ;
if ( textInd < STORY_TEXT2 . length ( ) ) {
FillRectDecal ( { ( float ) ( 48 + ( cursorX ) * 16 % ( WIDTH - 32 ) ) , ( float ) ( GetTextSize ( CUTSCENE_CONSOLE_TEXT ) . y * 2 + ( ( cursorX = = 28 ) ? 16 : 0 ) ) } , { 4 * 2 , 8 * 2 } , Pixel ( 100 , 10 , 255 ) ) ;
} else {
FillRectDecal ( { ( float ) ( 48 + ( cursorX ) * 16 % ( WIDTH - 32 ) ) , ( float ) ( GetTextSize ( CUTSCENE_CONSOLE_TEXT ) . y * 2 + ( ( cursorX = = 28 ) ? 16 : 0 ) ) } , { 4 * 2 , 8 * 2 } , Pixel ( 100 , 10 , 255 , ( 0.5 * sin ( frameCount * 4 / 60.0 ) + 0.5 ) * 256 ) ) ;
}
GradientFillRectDecal ( { 0 , 0 } , { WIDTH / 2 , HEIGHT / 2 } , { 100 , 10 , 255 , ALPHA_SCREEN1 } , { 100 , 10 , 255 , ALPHA_SCREEN1 } , { 100 , 10 , 255 , ALPHA_SCREEN2 } , { 100 , 10 , 255 , ALPHA_SCREEN1 } ) ;
GradientFillRectDecal ( { WIDTH / 2 , 0 } , { WIDTH / 2 , HEIGHT / 2 } , { 100 , 10 , 255 , ALPHA_SCREEN1 } , { 100 , 10 , 255 , ALPHA_SCREEN2 } , { 100 , 10 , 255 , ALPHA_SCREEN1 } , { 100 , 10 , 255 , ALPHA_SCREEN1 } ) ;
GradientFillRectDecal ( { 0 , HEIGHT / 2 } , { WIDTH / 2 , HEIGHT / 2 } , { 100 , 10 , 255 , ALPHA_SCREEN1 } , { 100 , 10 , 255 , ALPHA_SCREEN1 } , { 100 , 10 , 255 , ALPHA_SCREEN1 } , { 100 , 10 , 255 , ALPHA_SCREEN2 } ) ;
GradientFillRectDecal ( { WIDTH / 2 , HEIGHT / 2 } , { WIDTH / 2 , HEIGHT / 2 } , { 100 , 10 , 255 , ALPHA_SCREEN2 } , { 100 , 10 , 255 , ALPHA_SCREEN1 } , { 100 , 10 , 255 , ALPHA_SCREEN1 } , { 100 , 10 , 255 , ALPHA_SCREEN1 } ) ;
} break ;
}
switch ( BATTLE_STATE ) {
case battle : : PLAYER_SELECTION : {
SetDrawTarget ( nullptr ) ;
DrawCard ( availablePowers [ ( BATTLE_CARD_SELECTION_IND + 1 ) % availablePowers . size ( ) ] , { WIDTH - 96 , 32 } , { 0.7 , 0.7 } , 0.4 ) ;
DrawCard ( availablePowers [ ( BATTLE_CARD_SELECTION_IND - 1 < 0 ) ? availablePowers . size ( ) - 1 : BATTLE_CARD_SELECTION_IND - 1 ] , { - 96 , 32 } , { 0.7 , 0.7 } , 0.4 ) ;
DrawCard ( BATTLE_CARD_SELECTION ) ;
} break ;
case battle : : PLAYER_TARGET_SELECTION : {
if ( PLAYER_SELECTED_TARGET > = 0 ) {
DrawWrappedText ( { 5 , 5 } , " Target " + CURRENT_ENCOUNTER . entities [ PLAYER_SELECTED_TARGET ] . name + " " + ( char ) ( ' A ' + PLAYER_SELECTED_TARGET ) + " with " + BATTLE_CARD_SELECTION - > name , WIDTH - 8 , BLACK , { 2 , 2 } ) ;
DrawWrappedText ( { 4 , 4 } , " Target " + CURRENT_ENCOUNTER . entities [ PLAYER_SELECTED_TARGET ] . name + " " + ( char ) ( ' A ' + PLAYER_SELECTED_TARGET ) + " with " + BATTLE_CARD_SELECTION - > name , WIDTH - 8 , WHITE , { 2 , 2 } ) ;
DrawStringDecal ( { WIDTH - GetTextSize ( " <UP> Back " ) . x - 1 , HEIGHT - GetTextSize ( " <UP> Back " ) . y - 1 } , " <UP> Back " , BLACK , { 1 , 1 } ) ;
DrawStringDecal ( { WIDTH - GetTextSize ( " <UP> Back " ) . x - 2 , HEIGHT - GetTextSize ( " <UP> Back " ) . y - 2 } , " <UP> Back " , GREEN , { 1 , 1 } ) ;
}
} break ;
case battle : : WAIT_TURN_ANIMATION : {
if ( BATTLE_CURRENT_TURN_ENTITY = = - 1 ) {
DrawWrappedText ( { 4 , 4 } , " Player uses " + BATTLE_CARD_SELECTION - > name , WIDTH - 8 , WHITE , { 2 , 2 } ) ;
} else {
DrawWrappedText ( { 4 , 4 } , CURRENT_ENCOUNTER . entities [ BATTLE_CURRENT_TURN_ENTITY ] . name + " " + ( char ) ( ' A ' + BATTLE_CURRENT_TURN_ENTITY ) + " with " + CURRENT_ENCOUNTER . entities [ BATTLE_CURRENT_TURN_ENTITY ] . selectedMove - > name , WIDTH - 8 , WHITE , { 2 , 2 } ) ;
}
} break ;
}
if ( IN_BATTLE_ENCOUNTER | | ( ! CUTSCENE_ACTIVE & & PLAYER_HP ! = PLAYER_MAXHP ) ) {
DrawStringDecal ( { 4 + 1 , HEIGHT - 10 - GetTextSize ( " HP: " ) . y + 1 } , " HP: " + std : : to_string ( PLAYER_HP ) , BLACK ) ;
DrawStringDecal ( { 4 , HEIGHT - 10 - GetTextSize ( " HP: " ) . y } , " HP: " + std : : to_string ( PLAYER_HP ) ) ;
DrawHealthbar ( { 2 , HEIGHT - 10 } , WIDTH / 2 , PLAYER_HP / PLAYER_MAXHP , BLACK ) ;
for ( auto & numb : BATTLE_DISPLAY_NUMBERS ) {
std : : string display = ( ( numb - > number > 0 ) ? " - " + std : : to_string ( numb - > number ) : " + " + std : : to_string ( numb - > number * - 1 ) ) ;
for ( int x = - 1 ; x < = 1 ; x + + ) {
for ( int y = - 1 ; y < = 1 ; y + + ) {
if ( x ! = 0 & & y ! = 0 ) {
DrawStringDecal ( { ( ( numb - > x - PLAYER_COORDS [ 0 ] ) * 32 + WIDTH / 2 ) - GetTextSize ( display ) . x / 2 + x , ( ( numb - > y - PLAYER_COORDS [ 1 ] ) * 32 + HEIGHT / 2 ) - 8 - GetTextSize ( display ) . y / 2 + y } , display , ( numb - > number > 0 ) ? Pixel ( 255 , 0 , 0 , numb - > alpha ) : Pixel ( 0 , 255 , 0 , numb - > alpha ) , { 2 , 2 } ) ;
}
}
}
DrawStringDecal ( { ( ( numb - > x - PLAYER_COORDS [ 0 ] ) * 32 + WIDTH / 2 ) - GetTextSize ( display ) . x / 2 , ( ( numb - > y - PLAYER_COORDS [ 1 ] ) * 32 + HEIGHT / 2 ) - 8 - GetTextSize ( display ) . y / 2 } , display , Pixel ( 255 , 255 , 255 , numb - > alpha ) , { 2 , 2 } ) ;
//std::cout<<numb->x<<"/"<<numb->y<<" "<<(((numb->x-PLAYER_COORDS[0])*32+WIDTH/2)-GetTextSize(display).x/2)<<","<<(((numb->y-PLAYER_COORDS[1])*32+HEIGHT/2)-8-GetTextSize(display).y/2)<<": ("<<numb->alpha<<")"<<display<<"\n";
}
}
if ( messageBoxVisible ) {
DrawDialogBox ( { 4 , HEIGHT - 60 } , { WIDTH / 2 , 16 } , Pixel ( 18 , 0 , 33 , 180 ) ) ;
DrawDialogBox ( { 0 , HEIGHT - 48 } , { WIDTH , 48 } , Pixel ( 18 , 0 , 33 , 180 ) ) ;
DrawStringPropDecal ( { 8 , HEIGHT - 40 } , messageBoxText ) ;
DrawStringPropDecal ( { 8 , HEIGHT - 57 } , messageBoxSpeaker ) ;
if ( messageBoxCursor = = messageBoxRefText . length ( ) ) {
DrawStringPropDecal ( { WIDTH - 16 - ( float ) sin ( frameCount * 8 / 60.0 ) * 3 , HEIGHT - 8 + ( float ) ( cos ( frameCount * 6 / 60.0 ) * 0.6 ) } , " v " , Pixel ( 173 , 74 , 255 , ( 0.5 * sin ( frameCount * 8 / 60.0 ) + 0.5 ) * 128 + 128 ) , { ( float ) sin ( frameCount * 8 / 60.0 ) , 0.5 } ) ;
}
}
FillRectDecal ( { 0 , 0 } , { WIDTH , HEIGHT } , Pixel ( 0 , 0 , 0 , transparency ) ) ;
//FillRectDecal({WIDTH/2-2,HEIGHT/2-2},{4,4},WHITE);
}
void DrawGameWorld ( ) {
for ( int y = - 1 ; y < = HEIGHT / 32 + 1 ; y + + ) {
for ( int x = - 1 ; x < = WIDTH / 32 + 1 ; x + + ) {
float xOffset = PLAYER_COORDS [ 0 ] - ( WIDTH / 32 / 2 ) ;
float yOffset = PLAYER_COORDS [ 1 ] - ( HEIGHT / 32 / 2 ) ;
srand ( ( int ) ( yOffset + y ) * MAP_WIDTH + ( int ) ( xOffset + x ) ) ;
int tileX = 0 ;
int tileRot = 0 ;
while ( tileX < 3 & & rand ( ) % 4 = = 0 ) {
tileX + + ;
}
while ( tileRot < 3 & & rand ( ) % 8 < 5 ) {
tileRot + + ;
}
if ( ( int ) ( xOffset + x ) > = 0 & & ( int ) ( xOffset + x ) < MAP_WIDTH & & ( int ) ( yOffset + y ) > = 0 & & ( int ) ( yOffset + y ) < MAP_HEIGHT ) {
DrawPartialRotatedDecal ( { ( x - ( PLAYER_COORDS [ 0 ] - ( int ) PLAYER_COORDS [ 0 ] ) + 1 ) * 32 - 16 , ( y - ( PLAYER_COORDS [ 1 ] - ( int ) PLAYER_COORDS [ 1 ] ) + 1 ) * 32 } , TILES , tileRot * M_PI_2 , { 16 , 16 } , { tileX * 32 , 0 } , { 32 , 32 } , { 1 , 1 } , TILE_COLORS [ MAP [ ( int ) ( yOffset + y ) ] [ ( int ) ( xOffset + x ) ] ] ) ;
}
}
}
for ( auto & obj : OBJECTS ) {
if ( obj . spr ! = NULL ) {
if ( obj . name . compare ( " PLANT " ) = = 0 ) {
DrawPartialDecal ( { ( obj . x - PLAYER_COORDS [ 0 ] ) * 32 + WIDTH / 2 , ( obj . y - PLAYER_COORDS [ 1 ] ) * 32 + HEIGHT / 2 } , { 32 , 32 } , obj . spr , { getPlantStatus ( obj . x , obj . y ) * 32 , 0 } , { 32 , 32 } ) ;
} else {
if ( obj . name . find ( " NODE " ) ! = std : : string : : npos ) {
DrawDecal ( { ( obj . x - PLAYER_COORDS [ 0 ] ) * 32 + WIDTH / 2 - 32 + 18 , ( obj . y - PLAYER_COORDS [ 1 ] ) * 32 + HEIGHT / 2 - 32 + 26 } , WEATHERNODE_EFFECT_DECAL ) ;
DrawPartialDecal ( { ( obj . x - PLAYER_COORDS [ 0 ] ) * 32 + WIDTH / 2 - 16 * ( float ) sin ( frameCount * 2 / 60.0 ) + 16 , ( obj . y - PLAYER_COORDS [ 1 ] ) * 32 + HEIGHT / 2 } , obj . anim - > spr , { obj . anim - > getCurrentFrame ( ) . x , obj . anim - > getCurrentFrame ( ) . y } , { obj . anim - > width , obj . anim - > height } , { ( float ) sin ( frameCount * 2 / 60.0 ) , 1 } , Pixel ( ( float ) sin ( frameCount * 4 / 60.0 ) * 55 + 200 , ( float ) sin ( frameCount * 4 / 60.0 ) * 55 + 200 , ( float ) sin ( frameCount * 4 / 60.0 + M_PI ) + 65 * 125 , 255 ) ) ;
} else
if ( obj . hasAnim ) {
DrawPartialDecal ( { ( obj . x - PLAYER_COORDS [ 0 ] ) * 32 + WIDTH / 2 + ( obj . anim - > flipped ? 32 : 0 ) , ( obj . y - PLAYER_COORDS [ 1 ] ) * 32 + HEIGHT / 2 } , obj . anim - > spr , { obj . anim - > getCurrentFrame ( ) . x , obj . anim - > getCurrentFrame ( ) . y } , { obj . anim - > width , obj . anim - > height } , { obj . anim - > flipped ? - 1 : 1 , 1 } ) ;
} else {
DrawDecal ( { ( obj . x - PLAYER_COORDS [ 0 ] ) * 32 + WIDTH / 2 , ( obj . y - PLAYER_COORDS [ 1 ] ) * 32 + HEIGHT / 2 } , obj . spr ) ;
}
}
} else
if ( obj . name . compare ( " EXIT " ) = = 0 ) {
GradientFillRectDecal ( { ( obj . x - PLAYER_COORDS [ 0 ] ) * 32 + WIDTH / 2 , ( obj . y - PLAYER_COORDS [ 1 ] ) * 32 + HEIGHT / 2 } , { 32 , 32 } , Pixel ( 0 , 0 , 0 , 0 ) , WHITE , WHITE , Pixel ( 0 , 0 , 0 , 0 ) ) ;
}
}
for ( auto & enc : ENCOUNTERS ) {
int targetX = - 1 , targetY = - 1 ;
for ( auto & ent : enc . entities ) {
if ( BATTLE_STATE = = battle : : PLAYER_TARGET_SELECTION & & PLAYER_SELECTED_TARGET > = 0 & & CURRENT_ENCOUNTER . entities [ PLAYER_SELECTED_TARGET ] . hp > 0 & & CURRENT_ENCOUNTER . entities [ PLAYER_SELECTED_TARGET ] . x = = ent . x & & CURRENT_ENCOUNTER . entities [ PLAYER_SELECTED_TARGET ] . y = = ent . y ) {
DrawDecal ( { ( enc . x + ent . x - PLAYER_COORDS [ 0 ] ) * 32 + WIDTH / 2 , ( enc . y + ent . y - PLAYER_COORDS [ 1 ] ) * 32 + HEIGHT / 2 } , TARGETING_CIRCLE , { ent . spr - > sprite - > width / 32 , ent . spr - > sprite - > height / 32 } , { 255 , 210 , 0 , 255 } ) ;
DrawDecal ( { ( enc . x + ent . x - PLAYER_COORDS [ 0 ] ) * 32 + WIDTH / 2 , ( enc . y + ent . y - PLAYER_COORDS [ 1 ] ) * 32 + HEIGHT / 2 } , ent . spr , { 1 , 1 } , { ( 0.5 * ( float ) sin ( frameCount * 4 / 60.0 ) + 0.5 ) * 80 + 175 , ( 0.5 * ( float ) sin ( frameCount * 4 / 60.0 ) + 0.5 ) * 80 + 175 , ( 0.5 * ( float ) sin ( frameCount * 4 / 60.0 ) + 0.5 ) * 80 + 175 , 255 } ) ;
targetX = ent . x ; targetY = ent . y ;
} else {
DrawDecal ( { ( enc . x + ent . x - PLAYER_COORDS [ 0 ] ) * 32 + WIDTH / 2 , ( enc . y + ent . y - PLAYER_COORDS [ 1 ] ) * 32 + HEIGHT / 2 } , ent . spr ) ;
}
DrawHealthbar ( { ( enc . x + ent . x - PLAYER_COORDS [ 0 ] ) * 32 + WIDTH / 2 , ( enc . y + ent . y - PLAYER_COORDS [ 1 ] ) * 32 + HEIGHT / 2 + ent . spr - > sprite - > height + 2 } , ent . spr - > sprite - > width , ent . hp / ent . maxhp , BLACK ) ;
}
if ( targetX ! = - 1 & & targetY ! = - 1 ) {
DrawDecal ( { ( enc . x + targetX - PLAYER_COORDS [ 0 ] ) * 32 + WIDTH / 2 - BATTLE_CARD_SELECTION - > range + 16 , ( enc . y + targetY - PLAYER_COORDS [ 1 ] ) * 32 + HEIGHT / 2 - BATTLE_CARD_SELECTION - > range + 16 } , TARGETING_RANGE_CIRCLE , { BATTLE_CARD_SELECTION - > range * 2 / 32.0 , BATTLE_CARD_SELECTION - > range * 2 / 32.0 } , { 255 , 60 , 0 , ( 0.5 * ( float ) sin ( frameCount * 4 / 60.0 ) + 0.5 ) * 100 } ) ;
}
}
}
void DrawHealthbar ( vf2d pos , float width , float pct , Pixel col ) {
GradientFillRectDecal ( pos , { width * pct , 8 } , RED , RED , Pixel ( ( 1 / pct ) * 255 , 255 * pct , 0 , 255 ) , Pixel ( ( 1 / pct ) * 255 , 255 * pct , 0 , 255 ) ) ;
DrawDecal ( pos , HEALTHBAR_DECAL , { width / 32 , 1 } , col ) ;
}
int getPlantId ( int x , int y ) {
return ( ( int ) x - 8 ) % 4 + ( ( int ) y - 2 ) * 4 ;
}
int getPlantStatus ( int x , int y ) {
return plantState > > getPlantId ( x , y ) * 2 & 0b11 ;
}
void setPlantStatus ( int x , int y , char state ) {
int numb = 0b11111111111111111111111111111111 ;
int numb2 = 0 ;
numb - = 3 < < getPlantId ( x , y ) * 2 ;
plantState & = numb ;
}
void DrawDialogBox ( const vi2d & pos , const vi2d & size , Pixel p = WHITE , Pixel p2 = DARK_GREY , Pixel p3 = VERY_DARK_GREY ) {
FillRectDecal ( { ( float ) pos . x , ( float ) pos . y } , size , p2 ) ;
FillRectDecal ( { ( float ) pos . x + 1 , ( float ) pos . y + 1 } , { ( float ) size . x - 2 , ( float ) size . y - 2 } , p ) ;
FillRectDecal ( { ( float ) pos . x + 2 , ( float ) pos . y + 2 } , { ( float ) size . x - 4 , ( float ) size . y - 4 } , p3 ) ;
FillRectDecal ( { ( float ) pos . x + 3 , ( float ) pos . y + 3 } , { ( float ) size . x - 5 , ( float ) size . y - 5 } , p ) ;
Draw ( { pos . x , pos . y } , BLACK ) ;
Draw ( { pos . x + size . x , pos . y + size . y } , BLACK ) ;
Draw ( { pos . x + size . x , pos . y } , BLACK ) ;
Draw ( { pos . x , pos . y + size . y } , BLACK ) ;
}
void fadeOut ( ) {
fade = true ;
}
void fadeIn ( ) {
fade = false ;
}
void EndCutscene ( ) {
CURRENT_CUTSCENE = cutscene : : NONE ;
}
void DisplayMessageBox ( int dialogNumber ) {
messageBoxVisible = true ;
messageBoxCursor = 0 ;
std : : string split1 = STORY_DIALOG [ dialogNumber ] . substr ( 0 , STORY_DIALOG [ dialogNumber ] . find ( ' \n ' ) ) ; //Unused for now.
std : : string split2 = STORY_DIALOG [ dialogNumber ] . substr ( STORY_DIALOG [ dialogNumber ] . find ( ' \n ' ) + 1 , STORY_DIALOG [ dialogNumber ] . find ( ' \n ' , STORY_DIALOG [ dialogNumber ] . find ( ' \n ' ) + 1 ) - ( STORY_DIALOG [ dialogNumber ] . find ( ' \n ' ) + 1 ) ) ;
std : : string split3 = STORY_DIALOG [ dialogNumber ] . substr ( STORY_DIALOG [ dialogNumber ] . find ( ' \n ' , STORY_DIALOG [ dialogNumber ] . find ( ' \n ' ) + 1 ) + 1 , STORY_DIALOG [ dialogNumber ] . length ( ) - ( STORY_DIALOG [ dialogNumber ] . find ( ' \n ' , STORY_DIALOG [ dialogNumber ] . find ( ' \n ' ) + 1 ) + 1 ) ) ;
messageBoxSpeaker = split2 ;
messageBoxText = " " ;
messageBoxRefText = split3 ;
}
void LoadMap ( char * mapName ) {
std : : ifstream f ( mapName ) ;
std : : string data ;
MAP_NAME = mapName ;
MAP_WIDTH = MAP_HEIGHT = - 1 ;
if ( MAP ! = NULL ) {
for ( int y = 0 ; y < MAP_HEIGHT ; y + + ) {
free ( MAP [ y ] ) ;
}
free ( MAP ) ;
MAP = NULL ;
}
OBJECTS . clear ( ) ;
int y = 0 ;
if ( f . is_open ( ) ) {
while ( f . good ( ) ) {
f > > data ;
if ( MAP_WIDTH = = - 1 ) {
std : : stringstream stream ( data ) ;
stream > > MAP_WIDTH ;
} else
if ( MAP_HEIGHT = = - 1 ) {
std : : stringstream stream ( data ) ;
stream > > MAP_HEIGHT ;
} else
if ( y < MAP_HEIGHT ) {
if ( MAP = = NULL ) {
MAP = ( int * * ) malloc ( sizeof ( int * * ) * MAP_HEIGHT ) ;
}
MAP [ y ] = ( int * ) malloc ( sizeof ( int * ) * MAP_WIDTH ) ;
for ( int i = 0 ; i < data . length ( ) ; i + + ) {
MAP [ y ] [ i ] = data [ i ] - ' 0 ' ;
}
y + + ;
} else {
Object obj ;
std : : stringstream split1 ( data . substr ( 0 , data . find ( ' ; ' ) ) ) ;
split1 > > obj . x ;
std : : stringstream split2 ( data . substr ( data . find ( ' ; ' ) + 1 , data . find ( ' ; ' , data . find ( " ; " ) + 1 ) - ( data . find ( ' ; ' ) + 1 ) ) ) ;
split2 > > obj . y ;
std : : string split3 = data . substr ( data . find ( ' ; ' , data . find ( " ; " ) + 1 ) + 1 , data . length ( ) - ( data . find ( ' ; ' , data . find ( " ; " ) + 1 ) + 1 ) ) ;
if ( split3 . compare ( " NULL " ) ! = 0 ) {
obj . spr = BASE_OBJECTS [ split3 ] - > spr ;
if ( BASE_OBJECTS [ split3 ] - > hasanim ) {
obj . hasAnim = true ;
obj . anim = BASE_OBJECTS [ split3 ] - > anim ;
}
} else {
obj . spr = NULL ;
}
obj . name = split3 ;
printf ( " Loaded object %s: (%f,%f) \n " , split3 . c_str ( ) , obj . x , obj . y ) ;
OBJECTS . push_back ( obj ) ;
}
}
}
printf ( " Loaded %dx%d map: \n " , MAP_WIDTH , MAP_HEIGHT ) ;
for ( int y = 0 ; y < MAP_HEIGHT ; y + + ) {
for ( int x = 0 ; x < MAP_WIDTH ; x + + ) {
printf ( " %d " , MAP [ y ] [ x ] ) ;
}
printf ( " \n " ) ;
}
}
void changeAnimation ( Animation anim ) {
current_playerAnim = anim ;
current_playerAnim . frame = 0 ;
}
bool collidesWithPlayer ( Object obj ) {
if ( obj . hasAnim ) {
return PLAYER_COORDS [ 0 ] > = obj . x & & PLAYER_COORDS [ 0 ] < = obj . x + obj . anim - > width / 32.0 & &
PLAYER_COORDS [ 1 ] > = obj . y & & PLAYER_COORDS [ 1 ] < = obj . y + obj . anim - > height / 32.0 ;
} else {
if ( obj . spr = = NULL ) {
return PLAYER_COORDS [ 0 ] > = obj . x & & PLAYER_COORDS [ 0 ] < = obj . x + 1 & &
PLAYER_COORDS [ 1 ] > = obj . y & & PLAYER_COORDS [ 1 ] < = obj . y + 1 ;
} else {
return PLAYER_COORDS [ 0 ] > = obj . x & & PLAYER_COORDS [ 0 ] < = obj . x + obj . spr - > sprite - > width / 32.0 & &
PLAYER_COORDS [ 1 ] > = obj . y & & PLAYER_COORDS [ 1 ] < = obj . y + obj . spr - > sprite - > height / 32.0 ;
}
}
}
bool collidesWithPlayer ( Encounter obj ) {
return PLAYER_COORDS [ 0 ] > = obj . x & & PLAYER_COORDS [ 0 ] < = obj . x + WIDTH / 32 & &
PLAYER_COORDS [ 1 ] > = obj . y & & PLAYER_COORDS [ 1 ] < = obj . y + HEIGHT / 32 ;
}
void DrawWrappedText ( vf2d pos , std : : string text , int targetWidth , Pixel col , vf2d scale ) {
std : : string wrappedText ;
int marker = 0 ;
while ( marker < text . length ( ) ) {
wrappedText + = text [ marker ] ;
if ( GetTextSize ( wrappedText ) . x * scale . x > targetWidth ) {
int tempMarker = marker ;
while ( wrappedText [ tempMarker ] ! = ' ' ) {
wrappedText . erase ( tempMarker - - ) ;
}
wrappedText . erase ( tempMarker + + ) ;
wrappedText + = ' \n ' ;
while ( tempMarker < marker + 1 ) {
wrappedText + = text [ tempMarker + + ] ;
}
}
marker + + ;
}
DrawStringDecal ( pos , wrappedText , col , scale ) ;
}
void DrawWrappedPropText ( vf2d pos , std : : string text , int targetWidth , Pixel col , vf2d scale ) {
std : : string wrappedText ;
int marker = 0 ;
while ( marker < text . length ( ) ) {
wrappedText + = text [ marker ] ;
if ( GetTextSizeProp ( wrappedText ) . x * scale . x > targetWidth ) {
int tempMarker = marker ;
while ( wrappedText [ tempMarker ] ! = ' ' ) {
wrappedText . erase ( tempMarker - - ) ;
}
wrappedText . erase ( tempMarker + + ) ;
wrappedText + = ' \n ' ;
while ( tempMarker < marker + 1 ) {
wrappedText + = text [ tempMarker + + ] ;
}
}
marker + + ;
}
DrawStringPropDecal ( pos , wrappedText , col , scale ) ;
}
bool playerCanMove ( ) {
return CURRENT_CUTSCENE = = cutscene : : NONE & & ! messageBoxVisible & & ! IN_BATTLE_ENCOUNTER ;
}
void DrawCard ( WEATHER_POWER * data , vf2d offset = { 0 , 0 } , vf2d scale = { 1 , 1 } , float darknessFactor = 1.0 ) {
GradientFillRectDecal ( { ( WIDTH / 6 ) * scale . x + offset . x , ( HEIGHT / 6 ) * scale . y + offset . y } , { WIDTH / 3 * scale . x , HEIGHT / 6 * 2 * scale . y } , data - > bgcol * darknessFactor , data - > bgcol * darknessFactor , Pixel ( 72 , 160 , 212 , 0 ) , data - > bgcol * darknessFactor ) ;
GradientFillRectDecal ( { ( WIDTH / 6 * 3 + 1 ) * scale . x + offset . x , ( HEIGHT / 6 ) * scale . y + offset . y } , { WIDTH / 3 * scale . x , HEIGHT / 6 * 2 * scale . y } , data - > bgcol * darknessFactor , Pixel ( 72 , 160 , 212 , 0 ) , data - > bgcol * darknessFactor , data - > bgcol * darknessFactor ) ;
GradientFillRectDecal ( { ( WIDTH / 6 ) * scale . x + offset . x , ( HEIGHT / 6 * 3 ) * scale . y + offset . y } , { WIDTH / 3 * scale . x , HEIGHT / 6 * 2 * scale . y } , data - > bgcol * darknessFactor , data - > bgcol * darknessFactor , data - > bgcol * darknessFactor , Pixel ( 72 , 160 , 212 , 0 ) ) ;
GradientFillRectDecal ( { ( WIDTH / 6 * 3 + 1 ) * scale . x + offset . x , ( HEIGHT / 6 * 3 ) * scale . y + offset . y } , { WIDTH / 3 * scale . x , HEIGHT / 6 * 2 * scale . y } , Pixel ( 72 , 160 , 212 , 0 ) , data - > bgcol * darknessFactor , data - > bgcol * darknessFactor , data - > bgcol * darknessFactor ) ;
DrawPartialDecal ( { ( WIDTH / 2 - data - > anim - > width / 2 * 3 ) * scale . x + offset . x , ( HEIGHT / 6 + 16 - data - > anim - > height / 2 ) * scale . y + offset . y } , data - > anim - > spr , data - > anim - > getCurrentFrame ( ) , { data - > anim - > width , data - > anim - > height } , { 3 * scale . x , 3 * scale . y } , WHITE * darknessFactor ) ;
for ( int x = - 1 ; x < = 1 ; x + + ) {
for ( int y = - 1 ; y < = 1 ; y + + ) {
if ( x ! = 0 & & y ! = 0 ) {
DrawStringPropDecal ( { ( WIDTH / 6 + 4 + x ) * scale . x + offset . x , ( HEIGHT / 2 + 8 + y ) * scale . y + offset . y } , data - > name , BLACK , { 2 * scale . x , 2 * scale . y } ) ;
}
}
}
DrawStringPropDecal ( { ( WIDTH / 6 + 4 ) * scale . x + offset . x , ( HEIGHT / 2 + 8 ) * scale . y + offset . y } , data - > name , data - > textcol * darknessFactor , { 2 * scale . x , 2 * scale . y } ) ;
DrawWrappedPropText ( { ( WIDTH / 6 + 4 + 1 ) * scale . x + offset . x , ( HEIGHT / 2 + 24 + 1 ) * scale . y + offset . y } , data - > description , ( WIDTH / 3 * 2 - 8 ) * scale . x , BLACK , { scale . x , scale . y } ) ;
DrawWrappedPropText ( { ( WIDTH / 6 + 4 ) * scale . x + offset . x , ( HEIGHT / 2 + 24 ) * scale . y + offset . y } , data - > description , ( WIDTH / 3 * 2 - 8 ) * scale . x , Pixel ( 227 , 245 , 255 , 255 ) * darknessFactor , { scale . x , scale . y } ) ;
for ( int x = - 1 ; x < = 1 ; x + + ) {
for ( int y = - 1 ; y < = 1 ; y + + ) {
if ( x ! = 0 & & y ! = 0 ) {
DrawStringPropDecal ( { ( WIDTH / 6 + 4 + WIDTH / 3 * 2 - 8 - GetTextSizeProp ( std : : to_string ( data - > playerOwnCount ) + " uses remaining. " ) . x * 1.5 + x ) * scale . x + offset . x , ( HEIGHT / 6 * 3 + HEIGHT / 6 * 2 - GetTextSizeProp ( std : : to_string ( data - > playerOwnCount ) + " uses remaining. " ) . y * 1.5 - 4 + y ) * scale . y + offset . y } , std : : to_string ( data - > playerOwnCount ) + " uses remaining. " , olc : : BLACK , { 1.5 * scale . x , 1.5 * scale . y } ) ;
}
}
}
DrawStringPropDecal ( { ( WIDTH / 6 + 4 + WIDTH / 3 * 2 - 8 - GetTextSizeProp ( std : : to_string ( data - > playerOwnCount ) + " uses remaining. " ) . x * 1.5 ) * scale . x + offset . x , ( HEIGHT / 6 * 3 + HEIGHT / 6 * 2 - GetTextSizeProp ( std : : to_string ( data - > playerOwnCount ) + " uses remaining. " ) . y * 1.5 - 4 ) * scale . y + offset . y } , std : : to_string ( data - > playerOwnCount ) + " uses remaining. " , olc : : WHITE * darknessFactor , { 1.5 * scale . x , 1.5 * scale . y } ) ;
}
void effectRadius ( vi2d coords , WEATHER_POWER * power , bool playerForce ) {
int finalDamage = power - > damage + rand ( ) % power - > damageRoll * sign ( power - > damage ) ;
std : : cout < < " Emitting effect radius for " < < power - > name < < " for PlayerForce: " < < playerForce < < " \n " ;
if ( finalDamage < 0 ) {
//This is a healing effect.
if ( playerForce ) {
PLAYER_HP = std : : clamp ( PLAYER_HP - finalDamage , 0 , PLAYER_MAXHP ) ;
DisplayNumber * numb = new DisplayNumber ( finalDamage , PLAYER_COORDS [ 0 ] , PLAYER_COORDS [ 1 ] , frameCount ) ;
BATTLE_DISPLAY_NUMBERS . push_back ( numb ) ;
} else {
for ( int i = 0 ; i < CURRENT_ENCOUNTER . entities . size ( ) ; i + + ) {
Entity * ent = & CURRENT_ENCOUNTER . entities [ i ] ;
if ( distancetoCoords ( { ( ent - > x + CURRENT_ENCOUNTER . x ) * 32 , ( ent - > y + CURRENT_ENCOUNTER . y ) * 32 } , coords * 32 ) < = power - > range ) {
ent - > hp = std : : clamp ( ent - > hp - finalDamage , 0 , ent - > maxhp ) ;
DisplayNumber * numb = new DisplayNumber ( finalDamage , ent - > x + CURRENT_ENCOUNTER . x , ent - > y + CURRENT_ENCOUNTER . y , frameCount ) ;
BATTLE_DISPLAY_NUMBERS . push_back ( numb ) ;
ent - > damageFrame = frameCount ;
}
}
}
} else {
//Damaging effect.
if ( playerForce ) {
for ( int i = 0 ; i < CURRENT_ENCOUNTER . entities . size ( ) ; i + + ) {
Entity * ent = & CURRENT_ENCOUNTER . entities [ i ] ;
std : : cout < < " Distance was " < < distancetoCoords ( { ( ent - > x + CURRENT_ENCOUNTER . x ) * 32 , ( ent - > y + CURRENT_ENCOUNTER . y ) * 32 } , coords * 32 ) < < " \n " ;
if ( distancetoCoords ( { ( ent - > x + CURRENT_ENCOUNTER . x ) * 32 , ( ent - > y + CURRENT_ENCOUNTER . y ) * 32 } , coords * 32 ) < = power - > range ) {
ent - > hp = std : : clamp ( ent - > hp - finalDamage , 0 , ent - > maxhp ) ;
DisplayNumber * numb = new DisplayNumber ( finalDamage , ent - > x + CURRENT_ENCOUNTER . x , ent - > y + CURRENT_ENCOUNTER . y , frameCount ) ;
BATTLE_DISPLAY_NUMBERS . push_back ( numb ) ;
ent - > damageFrame = frameCount ;
}
}
} else {
PLAYER_HP = std : : clamp ( PLAYER_HP - finalDamage , 0 , PLAYER_MAXHP ) ;
DisplayNumber * numb = new DisplayNumber ( finalDamage , PLAYER_COORDS [ 0 ] , PLAYER_COORDS [ 1 ] , frameCount ) ;
BATTLE_DISPLAY_NUMBERS . push_back ( numb ) ;
}
}
}
double distancetoCoords ( vf2d c1 , vf2d c2 ) {
return sqrt ( pow ( c1 . x - c2 . x , 2 ) + pow ( c2 . y - c1 . y , 2 ) ) ;
}
int sign ( int x ) {
return ( x > 0 ) - ( x < 0 ) ;
}
} ;
int main ( )
{
SeasonsOfLoneliness demo ;
if ( demo . Construct ( 256 , 224 , 4 , 4 ) )
demo . Start ( ) ;
return 0 ;
}