#define OLC_PGE_APPLICATION #include "pixelGameEngine.h" #include "data.h" #define OLC_PGEX_SPLASHSCREEN #include "splash.h" using namespace std; enum GAMESTATE{ CUTSCENE_1, CUTSCENE_2, CUTSCENE_3, GAMEWORLD, WAITING_FOR_CUTSCENE_3, }; enum CUTSCENE{ NONE, PAN_DOME, PAUSE_TO_CUTSCENE_3, CUTSCENE_4, }; #define WIDTH 256 #define HEIGHT 224 #define ALPHA_SCREEN1 128 #define ALPHA_SCREEN2 20 #define FADE_SPD 6 #define MOVE_SPD 0.2 #define MESSAGE_SCROLL_WAIT_SPD 2 //Number of frames to wait. class Object{ public: float x,y; olc::Decal*spr; std::string name; }; class Animation{ public: olc::Decal*spr; std::vector frames; int frame=0; bool flipped=false; olc::vi2d getCurrentFrame() { return frames[frame]; } }; class SeasonsOfLoneliness : public olc::PixelGameEngine { public: SeasonsOfLoneliness() { sAppName = "Seasons of Loneliness"; } 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 CUTSCENE_CONSOLE_TEXT = ""; int**MAP=NULL; int MAP_WIDTH=-1; int MAP_HEIGHT=-1; olc::Decal*TILES; float PLAYER_COORDS[2] = {}; std::vector OBJECTS; bool CUTSCENE_ACTIVE=false; CUTSCENE CURRENT_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; olc::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; olc::Decal*DOME_DECAL,*FOOD_METER_DECAL,*OXYGEN_METER_DECAL,*PLANT_DECAL, *PLAYER_DECAL; std::map BASE_OBJECTS; bool OnUserCreate() override { SetPixelMode(olc::Pixel::ALPHA); ConsoleCaptureStdOut(true); //ConsoleShow(olc::F1,false); // Called once at the start, so create things here TILES=new olc::Decal(new olc::Sprite("assets/tiles.png")); DOME_DECAL=new olc::Decal(new olc::Sprite("assets/dome.png")); FOOD_METER_DECAL=new olc::Decal(new olc::Sprite("assets/corn.png")); OXYGEN_METER_DECAL=new olc::Decal(new olc::Sprite("assets/co2.png")); PLANT_DECAL=new olc::Decal(new olc::Sprite("assets/plant.png")); PLAYER_DECAL=new olc::Decal(new olc::Sprite("assets/player.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; BASE_OBJECTS["DOME"]=DOME_DECAL; BASE_OBJECTS["PLANT"]=PLANT_DECAL; BASE_OBJECTS["EXIT"]=NULL; LoadMap("assets/maps/map2"); return true; } void GetAnyKeyPress() override { if (!GetKey(olc::W).bPressed&&!GetKey(olc::A).bPressed&&!GetKey(olc::S).bPressed&&!GetKey(olc::D).bPressed&& !GetKey(olc::UP).bPressed&&!GetKey(olc::RIGHT).bPressed&&!GetKey(olc::DOWN).bPressed&&!GetKey(olc::LEFT).bPressed) { ActionButtonPress(); } if (messageBoxVisible) { if (messageBoxCursor!=messageBoxRefText.length()) { while (messageBoxCursor=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 "<TARGET_RATE) { elapsedTime-=TARGET_RATE; updateGame(); } if (GetKey(olc::F1).bPressed) { ConsoleShow(olc::F1,false); } if (GetKey(olc::D).bPressed||GetKey(olc::RIGHT).bPressed) { changeAnimation(playerAnimWalkRight); } if (GetKey(olc::A).bPressed||GetKey(olc::LEFT).bPressed) { changeAnimation(playerAnimWalkLeft); } if (GetKey(olc::W).bPressed||GetKey(olc::UP).bPressed) { changeAnimation(playerAnimWalkUp); } if (GetKey(olc::S).bPressed||GetKey(olc::DOWN).bPressed) { changeAnimation(playerAnimWalkDown); } if (!GetKey(olc::D).bHeld&&!GetKey(olc::RIGHT).bHeld&& !GetKey(olc::A).bHeld&&!GetKey(olc::LEFT).bHeld&& !GetKey(olc::S).bHeld&&!GetKey(olc::UP).bHeld&& !GetKey(olc::W).bHeld&&!GetKey(olc::DOWN).bHeld) { if (GetKey(olc::D).bReleased||GetKey(olc::RIGHT).bReleased) { changeAnimation(playerAnimRight); } if (GetKey(olc::A).bReleased||GetKey(olc::LEFT).bReleased) { changeAnimation(playerAnimLeft); } if (GetKey(olc::W).bReleased||GetKey(olc::UP).bReleased) { changeAnimation(playerAnim); } if (GetKey(olc::S).bReleased||GetKey(olc::DOWN).bReleased) { changeAnimation(playerAnimDown); } } drawGame(); // called once per frame return true; } void fadeOutCompleted() { switch (GAME_STATE) { case CUTSCENE_1:{ GAME_STATE=CUTSCENE_2; PlayCutscene(PAN_DOME); fadeIn(); }break; case CUTSCENE_2:{ fadeIn(); PlayCutscene(CUTSCENE_4); GAME_STATE=GAMEWORLD; }break; } } void fadeInCompleted() { } void PlayCutscene(CUTSCENE scene) { CURRENT_CUTSCENE=scene; switch (scene) { case PAN_DOME:{ PLAYER_COORDS[0]=14; PLAYER_COORDS[1]=18+(64/2/32); }break; case PAUSE_TO_CUTSCENE_3:{ CUTSCENE_CONSOLE_TEXT.clear(); textInd=0; }break; case 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!=NONE) { CUTSCENE_TIMER++; } if (fade&&transparency<255) { transparency=clamp(transparency+FADE_SPD,0,255); if (transparency==255) { fadeOutCompleted(); } } else if (!fade&&transparency>0) { transparency=clamp(transparency-FADE_SPD,0,255); if (transparency==0) { fadeInCompleted(); } } if (messageBoxVisible) { if (frameCount%MESSAGE_SCROLL_WAIT_SPD==0) { if (messageBoxCursor=current_playerAnim.frames.size())?0:current_playerAnim.frame+1; if (CURRENT_CUTSCENE==NONE&&!messageBoxVisible) { bool changed=false; if (GetKey(olc::D).bHeld||GetKey(olc::RIGHT).bHeld) { PLAYER_COORDS[0]=clamp(PLAYER_COORDS[0]+MOVE_SPD,0.1,(double)MAP_WIDTH); ConsoleClear(); cout<<"("<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 (tempIndex120) { 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=0&&(int)(xOffset+x)=0&&(int)(yOffset+y)>getPlantId(x,y)*2&0b11; } void DrawDialogBox(const olc::vi2d &pos, const olc::vi2d &size, olc::Pixel p = olc::WHITE, olc::Pixel p2 = olc::DARK_GREY, olc::Pixel p3 = olc::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},olc::BLACK); Draw({pos.x+size.x,pos.y+size.y},olc::BLACK); Draw({pos.x+size.x,pos.y},olc::BLACK); Draw({pos.x,pos.y+size.y},olc::BLACK); } void fadeOut() { fade=true; } void fadeIn() { fade=false; } void EndCutscene() { CURRENT_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_WIDTH=MAP_HEIGHT=-1; if (MAP!=NULL) { for (int y=0;y>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>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]; } 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