#define OLC_PGE_APPLICATION #include "pixelGameEngine.h" #define OLC_PGEX_SPLASHSCREEN #include "splash.h" #define OLC_SOUNDWAVE #include "soundwaveEngine.h" #include "tiles.h" #include "references.h" #include "states.h" #include "flags.h" #define WIDTH 256 #define HEIGHT 224 #define CAMERA_MOVESPD 5 #define TILEMAP_SIZE_X 512 #define TILEMAP_SIZE_Y 512 #define TILEMAP_EDITOR_DRAW_MULT 0.4375 #define TILEMAP_EDITOR_TILESIZE (32*TILEMAP_EDITOR_DRAW_MULT) using namespace olc; namespace layer{ enum layer{ INTERFACE, //Interface items should be on this layer. On top of everything. COLLISION, //Collision checking layer. This layer is HIGH, DYNAMIC, GROUND, BACKGROUND }; } class Map{ public: std::string filename; std::string l2filename; std::string l3filename; std::string l4filename; std::string l5filename; Decal*tileset; Map(std::string fname,std::string layer2_fname,std::string layer3_fname,std::string layer4_fname,std::string layer5_fname,Decal*tileset) { this->filename=fname; this->l2filename=layer2_fname; this->l3filename=layer3_fname; this->l4filename=layer4_fname; this->l5filename=layer5_fname; this->tileset=tileset; } }; class Animation{ public: Decal*spr; int frames=1; int width=0; Animation(Decal*spr,int width){ this->frames=spr->sprite->width/width; this->width=width; this->spr=spr; } }; class Object{ public: int id; Animation*spr; vd2d pos; int frameIndex=0; int frameCount=0; int animationSpd=12; //How many frames to wait between each frame. std::string name; vd2d scale={1,1}; Pixel color=WHITE; vd2d originPoint={0,0}; bool drawn=false; int disableFlag; int enableFlag; //animationSpd is how long to wait before switching frames. Object(int id,std::string name,vi2d pos,Animation*spr,vi2d scale={1,1},Pixel color=WHITE,int animationSpd=1) { this->spr=spr; this->pos=pos; this->id=id; this->name=name; this->scale=scale; this->color=color; this->animationSpd=animationSpd; this->originPoint={spr->width/2,spr->spr->sprite->height-4}; } }; class SeasonI : public PixelGameEngine { public: SeasonI() { sAppName = "Season I: Winters of Loneliness"; } public: int frameCount=0; float elapsedTime=0; const float TARGET_RATE = 1/60.0; int MAP_WIDTH; int MAP_HEIGHT; Map*CURRENT_MAP; Map*MAP_ONETT; vd2d cameraPos = {0,0}; GameState GAME_STATE = GameState::EDITOR; vi2d SELECTED_TILE={0,0}; vi2d HIGHLIGHTED_TILE={0,0}; int EDITING_LAYER=layer::DYNAMIC; bool GAME_FLAGS[128]={}; bool MOUSE_PRESSED_DOWN=false,MOUSE_DOWN=false,MOUSE_RELEASED=false; //TODO Implement Mouse things. std::vector> MAP; //The foreground layer. std::vector> MAP2; std::vector> MAP3; std::vector> MAP4; std::vector> MAP5; //Collision Layer std::map SPRITES; std::map ANIMATIONS; std::map OBJ_INFO; std::vector OBJECTS; bool OnUserCreate() override { for (int i=1;i<6;i++) { CreateLayer(); EnableLayer(i,true); } SetPixelMode(Pixel::ALPHA); ConsoleCaptureStdOut(true); // Called once at the start, so create things here EnableLayer(layer::COLLISION,false); SetupAnimations(); SetupObjectInfo(); GAME_FLAGS[Flag::TEST_FLAG1]=true; GAME_FLAGS[Flag::TEST_FLAG2]=false; GAME_FLAGS[Flag::TEST_FLAG3]=true; MAP_ONETT=new Map("map0","map0_2","map0_3","map0_4","map0_5",SPRITES[TILESET1]); CURRENT_MAP=MAP_ONETT; //OBJ_INFO["PLAYER"]=PLAYER_ANIMATION; LoadMap(MAP_ONETT); return true; } bool OnUserUpdate(float fElapsedTime) override { elapsedTime+=fElapsedTime; while (elapsedTime>TARGET_RATE) { elapsedTime-=TARGET_RATE; updateGame(); } keyUpdates(); SetDrawTarget(nullptr); Clear(BLANK); SetDrawTarget(layer::COLLISION); if (EDITING_LAYER!=layer::COLLISION) { Clear(MAGENTA); } else { Clear(BLANK); } SetDrawTarget(layer::HIGH); Clear(BLANK); SetDrawTarget(layer::DYNAMIC); Clear(BLANK); SetDrawTarget(layer::GROUND); Clear(BLANK); SetDrawTarget(layer::BACKGROUND); Clear(BLANK); drawGame(); return true; } void updateGame(){ frameCount++; for (auto&obj:OBJECTS) { if (obj->frameCount++>obj->animationSpd) { obj->frameCount=0; obj->frameIndex++; } } std::cout << Collision(GetMousePos()); switch (GAME_STATE) { case GameState::TILE_SELECT:{ if (!TabHeld()) { GAME_STATE=GameState::EDITOR; } if (GetMouse(0).bHeld) { int selectedTileX=GetMouseX()/TILEMAP_EDITOR_TILESIZE; int selectedTileY=GetMouseY()/TILEMAP_EDITOR_TILESIZE; if (selectedTileX*TILEMAP_EDITOR_DRAW_MULT>=0&&selectedTileX*TILEMAP_EDITOR_DRAW_MULT=0) { SELECTED_TILE={selectedTileX,selectedTileY}; } } }break; case GameState::EDITOR:{ if (TabHeld()) { GAME_STATE=GameState::TILE_SELECT; } if (OBJECTS.size()>0) { if (GetKey(I).bHeld) { if (!Collision({OBJECTS[0]->pos.x+OBJECTS[0]->originPoint.x,OBJECTS[0]->pos.y-1+OBJECTS[0]->originPoint.y})) { OBJECTS[0]->pos.y-=1; } } if (GetKey(K).bHeld) { if (!Collision({OBJECTS[0]->pos.x+OBJECTS[0]->originPoint.x,OBJECTS[0]->pos.y+1+OBJECTS[0]->originPoint.y})) { OBJECTS[0]->pos.y+=1; } } if (GetKey(J).bHeld) { if (!Collision({OBJECTS[0]->pos.x-1+OBJECTS[0]->originPoint.x,OBJECTS[0]->pos.y+OBJECTS[0]->originPoint.y})) { OBJECTS[0]->pos.x-=1; } } if (GetKey(L).bHeld) { if (!Collision({OBJECTS[0]->pos.x+1+OBJECTS[0]->originPoint.x,OBJECTS[0]->pos.y+OBJECTS[0]->originPoint.y})) { OBJECTS[0]->pos.x+=1; } } } int selectedTileX=(GetMouseX()+cameraPos.x)/32; int selectedTileY=(GetMouseY()+cameraPos.y)/32; if (selectedTileX=0&&selectedTileY>=0) { HIGHLIGHTED_TILE={selectedTileX,selectedTileY}; } if (GetMouse(0).bHeld) { switch (EDITING_LAYER) { case layer::COLLISION:{ TILE*tile=MAP5[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x]; tile->tileX=SELECTED_TILE.x; tile->tileY=SELECTED_TILE.y; }break; case layer::HIGH:{ TILE*tile=MAP[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x]; tile->tileX=SELECTED_TILE.x; tile->tileY=SELECTED_TILE.y; }break; case layer::DYNAMIC:{ TILE*tile=MAP2[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x]; tile->tileX=SELECTED_TILE.x; tile->tileY=SELECTED_TILE.y; }break; case layer::GROUND:{ TILE*tile=MAP3[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x]; tile->tileX=SELECTED_TILE.x; tile->tileY=SELECTED_TILE.y; }break; case layer::BACKGROUND:{ TILE*tile=MAP4[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x]; tile->tileX=SELECTED_TILE.x; tile->tileY=SELECTED_TILE.y; }break; } } else if (GetMouse(1).bHeld) { switch (EDITING_LAYER) { case layer::COLLISION:{ TILE*tile=MAP5[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x]; tile->tileX=tile->tileY=15; }break; case layer::HIGH:{ TILE*tile=MAP[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x]; tile->tileX=tile->tileY=15; }break; case layer::DYNAMIC:{ TILE*tile=MAP2[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x]; tile->tileX=tile->tileY=15; }break; case layer::GROUND:{ TILE*tile=MAP3[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x]; tile->tileX=tile->tileY=15; }break; case layer::BACKGROUND:{ TILE*tile=MAP4[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x]; tile->tileX=tile->tileY=15; }break; } } }break; } //CAMERA UPDATES MUST BE LAST!!! COLLISIONS RELY ON THE GAME POSITION STATES REMAINING THE SAME! cameraUpdate(); } //CAMERA UPDATES MUST BE LAST!!! COLLISIONS RELY ON THE GAME POSITION STATES REMAINING THE SAME! void cameraUpdate() { switch (GAME_STATE) { case GameState::EDITOR:{ //CAMERA MOVEMENTS MUST BE LAST!!! if (UpHeld()) { cameraPos.y-=CAMERA_MOVESPD; } if (RightHeld()) { cameraPos.x+=CAMERA_MOVESPD; } if (LeftHeld()) { cameraPos.x-=CAMERA_MOVESPD; } if (DownHeld()) { cameraPos.y+=CAMERA_MOVESPD; } }break; } } void keyUpdates() { if (GetKey(F1).bPressed) { ConsoleShow(F1,false); } if (GetKey(F2).bPressed) { SaveMap(CURRENT_MAP); printf("Map Saved\n"); } switch (GAME_STATE) { case GameState::TILE_SELECT:{ if (UpPressed()) { SELECTED_TILE.y=SELECTED_TILE.y-1; if (SELECTED_TILE.y<0) { SELECTED_TILE.y=TILEMAP_SIZE_Y/32-1; } } if (RightPressed()) { SELECTED_TILE.x=(SELECTED_TILE.x+1)%(TILEMAP_SIZE_X/32); } if (LeftPressed()) { SELECTED_TILE.x=SELECTED_TILE.x-1; if (SELECTED_TILE.x<0) { SELECTED_TILE.x=TILEMAP_SIZE_X/32-1; } } if (DownPressed()) { SELECTED_TILE.y=(SELECTED_TILE.y+1)%(TILEMAP_SIZE_Y/32); } }break; case GameState::EDITOR:{ if (GetKey(K1).bPressed) { EDITING_LAYER=layer::COLLISION; EnableLayer(layer::COLLISION,true); SetLayerTint(layer::COLLISION,{255,0,0,215}); } if (GetKey(K2).bPressed) { EDITING_LAYER=layer::HIGH; EnableLayer(layer::COLLISION,false); } if (GetKey(K3).bPressed) { EDITING_LAYER=layer::DYNAMIC; EnableLayer(layer::COLLISION,false); } if (GetKey(K4).bPressed) { EDITING_LAYER=layer::GROUND; EnableLayer(layer::COLLISION,false); } if (GetKey(K5).bPressed) { EDITING_LAYER=layer::BACKGROUND; EnableLayer(layer::COLLISION,false); } }break; } } void drawGame(){ for (auto&obj:OBJECTS) { obj->drawn=false; } switch (GAME_STATE) { case GameState::EDITOR:{ for (int y=-1;ydrawn&&obj->pos.y+obj->originPoint.y>(y+yTileOffset)*32&&obj->pos.y+obj->originPoint.y<=(y+yTileOffset+1)*32) { obj->drawn=true; SetDrawTarget(layer::DYNAMIC); DrawPartialDecal(obj->pos-cameraPos,obj->spr->spr,{(obj->frameIndex%obj->spr->frames)*obj->spr->width,0},{obj->spr->width,obj->spr->spr->sprite->height},obj->scale,obj->color); } } for (int x=-1;x=0&&x+xTileOffset=0&&y+yTileOffsettileX*MAP5[y+yTileOffset][x+xTileOffset]->tileY!=225) { SetDrawTarget(layer::COLLISION); DrawPartialSprite({x*32-fmod(cameraPos.x,32),y*32-fmod(cameraPos.y,32)},SPRITES[TILESET1]->sprite,{MAP5[y+yTileOffset][x+xTileOffset]->tileX*32,MAP5[y+yTileOffset][x+xTileOffset]->tileY*32},{32,32}); } if(MAP4[y+yTileOffset][x+xTileOffset]->tileX*MAP4[y+yTileOffset][x+xTileOffset]->tileY!=225) { SetDrawTarget(layer::BACKGROUND); DrawPartialDecal({x*32-fmod(cameraPos.x,32),y*32-fmod(cameraPos.y,32)},SPRITES[TILESET1],{MAP4[y+yTileOffset][x+xTileOffset]->tileX*32,MAP4[y+yTileOffset][x+xTileOffset]->tileY*32},{32,32}); } if(MAP3[y+yTileOffset][x+xTileOffset]->tileX*MAP3[y+yTileOffset][x+xTileOffset]->tileY!=225) { SetDrawTarget(layer::GROUND); DrawPartialDecal({x*32-fmod(cameraPos.x,32),y*32-fmod(cameraPos.y,32)},SPRITES[TILESET1],{MAP3[y+yTileOffset][x+xTileOffset]->tileX*32,MAP3[y+yTileOffset][x+xTileOffset]->tileY*32},{32,32}); } if(MAP2[y+yTileOffset][x+xTileOffset]->tileX*MAP2[y+yTileOffset][x+xTileOffset]->tileY!=225) { SetDrawTarget(layer::DYNAMIC); DrawPartialDecal({x*32-fmod(cameraPos.x,32),y*32-fmod(cameraPos.y,32)},SPRITES[TILESET1],{MAP2[y+yTileOffset][x+xTileOffset]->tileX*32,MAP2[y+yTileOffset][x+xTileOffset]->tileY*32},{32,32}); } if(MAP[y+yTileOffset][x+xTileOffset]->tileX*MAP[y+yTileOffset][x+xTileOffset]->tileY!=225) { SetDrawTarget(layer::HIGH); DrawPartialDecal({x*32-fmod(cameraPos.x,32),y*32-fmod(cameraPos.y,32)},SPRITES[TILESET1],{MAP[y+yTileOffset][x+xTileOffset]->tileX*32,MAP[y+yTileOffset][x+xTileOffset]->tileY*32},{32,32}); } } } } SetDrawTarget(nullptr); DrawRectDecal((HIGHLIGHTED_TILE)*32-cameraPos,{32,32},YELLOW); DrawStringPropDecal({2,2},"Editing Layer "+std::to_string(EDITING_LAYER)); }break; case GameState::TILE_SELECT:{ //14x14 pixels per tile. DrawDecal({0,0},SPRITES[TILESET1],{TILEMAP_EDITOR_DRAW_MULT,TILEMAP_EDITOR_DRAW_MULT}); DrawRectDecal(SELECTED_TILE*(TILEMAP_EDITOR_TILESIZE),{TILEMAP_EDITOR_TILESIZE,TILEMAP_EDITOR_TILESIZE},RED); }break; } }; void LoadMap(Map*map) { std::ifstream f("assets/maps/"+map->filename,std::ios::binary); std::ifstream f2("assets/maps/"+map->l2filename,std::ios::binary); std::ifstream f3("assets/maps/"+map->l3filename,std::ios::binary); std::ifstream f4("assets/maps/"+map->l4filename,std::ios::binary); std::ifstream f5("assets/maps/"+map->l5filename,std::ios::binary); for (int i=0;i>data; if (MAP_WIDTH==-1) { MAP_WIDTH=data.length()/2; printf("Map Width: %d\n",MAP_WIDTH); } if (data.find("OBJECT")!=std::string::npos) { int marker=data.find_first_of(';'); int lastMarker=marker; std::stringstream split1(data.substr(6,marker-6)); marker=data.find_first_of(';',marker+1); std::stringstream split2(data.substr(lastMarker+1,marker-lastMarker-1)); lastMarker=marker; marker=data.find_first_of(';',marker+1); std::stringstream split3(data.substr(lastMarker+1,marker-lastMarker-1)); lastMarker=marker; double x,y; split1>>x; split2>>y; int id; split3>>id; bool enabled=true; if (OBJ_INFO[id]->disableFlag!=Flag::NONE) { if (GAME_FLAGS[OBJ_INFO[id]->disableFlag]) { enabled=false; } } if (OBJ_INFO[id]->enableFlag!=Flag::NONE) { if (!GAME_FLAGS[OBJ_INFO[id]->enableFlag]) { enabled=false; } } if (enabled) { Object*newObj = new Object(id,OBJ_INFO[id]->name,{x,y},OBJ_INFO[id]->spr); OBJECTS.push_back(newObj); } printf("Object %s Loaded.\n",OBJ_INFO[id]->name.c_str()); } else { std::vector tiles; printf("%s\n",data.c_str()); for (int i=0;i>data; std::vector tiles; for (int i=0;i>data; std::vector tiles; for (int i=0;i>data; std::vector tiles; for (int i=0;i>data; std::vector tiles; for (int i=0;ifilename.c_str()); f.close(); f2.close(); f3.close(); f4.close(); f5.close(); } void SaveMap(Map*map) { std::ofstream f("assets/maps/"+map->filename,std::ios::binary); std::ofstream f2("assets/maps/"+map->l2filename,std::ios::binary); std::ofstream f3("assets/maps/"+map->l3filename,std::ios::binary); std::ofstream f4("assets/maps/"+map->l4filename,std::ios::binary); std::ofstream f5("assets/maps/"+map->l5filename,std::ios::binary); printf("Map width: %d, Map Height: %d::\n",MAP_WIDTH,MAP_HEIGHT); for (int y=0;ytileX+'0');f.put(MAP[y][x]->tileY+'0'); f2.put(MAP2[y][x]->tileX+'0');f2.put(MAP2[y][x]->tileY+'0'); f3.put(MAP3[y][x]->tileX+'0');f3.put(MAP3[y][x]->tileY+'0'); f4.put(MAP4[y][x]->tileX+'0');f4.put(MAP4[y][x]->tileY+'0'); f5.put(MAP5[y][x]->tileX+'0');f5.put(MAP5[y][x]->tileY+'0'); } if (y!=MAP_HEIGHT-1) { f.put('\n'); f2.put('\n'); f3.put('\n'); f4.put('\n'); f5.put('\n'); } } for (int i=0;ipos.x)+";"+std::to_string(OBJECTS[i]->pos.y)+";"+std::to_string(OBJECTS[i]->id); for (int i=0;idisableFlag=disableFlag; newObj->enableFlag=enableFlag; return newObj; } void SetupObjectInfo() { OBJ_INFO[PLAYER]=CreateObject(PLAYER,"player",{0,0}); } bool Collision(vd2d pos) { SetDrawTarget(layer::COLLISION); Pixel collisionData = GetDrawTarget()->GetPixel((int)pos.x-cameraPos.x,(int)pos.y-cameraPos.y); return collisionData!=MAGENTA; } bool TabHeld(){ return GetKey(TAB).bHeld; } bool UpPressed(){ return GetKey(W).bPressed||GetKey(UP).bPressed||GetKey(NP8).bPressed||MOUSE_PRESSED_DOWN&&GetMouseY()<=HEIGHT-128+32&&GetMouseY()>=HEIGHT-128&&GetMouseX()<=HEIGHT-128; } bool DownPressed(){ return GetKey(S).bPressed||GetKey(DOWN).bPressed||GetKey(NP5).bPressed||GetKey(NP2).bPressed||MOUSE_PRESSED_DOWN&&GetMouseY()<=HEIGHT&&GetMouseY()>=HEIGHT-32&&GetMouseX()<=HEIGHT-128; } bool LeftPressed(){ return GetKey(A).bPressed||GetKey(LEFT).bPressed||GetKey(NP4).bPressed||MOUSE_PRESSED_DOWN&&GetMouseX()<=32&&GetMouseX()>=0&&GetMouseY()>=HEIGHT-128; } bool RightPressed(){ return GetKey(D).bPressed||GetKey(RIGHT).bPressed||GetKey(NP6).bPressed||MOUSE_PRESSED_DOWN&&GetMouseX()<=128&&GetMouseX()>=96&&GetMouseY()>=HEIGHT-128; } bool UpHeld(){ return GetKey(W).bHeld||GetKey(UP).bHeld||GetKey(NP8).bHeld||MOUSE_DOWN&&GetMouseY()<=HEIGHT-128+32&&GetMouseY()>=HEIGHT-128&&GetMouseX()<=HEIGHT-128; } bool DownHeld(){ return GetKey(S).bHeld||GetKey(DOWN).bHeld||GetKey(NP5).bHeld||GetKey(NP2).bHeld||MOUSE_DOWN&&GetMouseY()<=HEIGHT&&GetMouseY()>=HEIGHT-32&&GetMouseX()<=HEIGHT-128; } bool LeftHeld(){ return GetKey(A).bHeld||GetKey(LEFT).bHeld||GetKey(NP4).bHeld||MOUSE_DOWN&&GetMouseX()<=32&&GetMouseX()>=0&&GetMouseY()>=HEIGHT-128; } bool RightHeld(){ return GetKey(D).bHeld||GetKey(RIGHT).bHeld||GetKey(NP6).bHeld||MOUSE_DOWN&&GetMouseX()<=128&&GetMouseX()>=96&&GetMouseY()>=HEIGHT-128; } bool UpReleased(){ return GetKey(W).bReleased||GetKey(UP).bReleased||GetKey(NP8).bReleased||MOUSE_RELEASED&&GetMouseY()<=HEIGHT-128+32&&GetMouseY()>=HEIGHT-128&&GetMouseX()<=HEIGHT-128; } bool DownReleased(){ return GetKey(S).bReleased||GetKey(DOWN).bReleased||GetKey(NP5).bReleased||GetKey(NP2).bReleased||MOUSE_RELEASED&&GetMouseY()<=HEIGHT&&GetMouseY()>=HEIGHT-32&&GetMouseX()<=HEIGHT-128; } bool LeftReleased(){ return GetKey(A).bReleased||GetKey(LEFT).bReleased||GetKey(NP4).bReleased||MOUSE_RELEASED&&GetMouseX()<=32&&GetMouseX()>=0&&GetMouseY()>=HEIGHT-128; } bool RightReleased(){ return GetKey(D).bReleased||GetKey(RIGHT).bReleased||GetKey(NP6).bReleased||MOUSE_RELEASED&&GetMouseX()<=128&&GetMouseX()>=96&&GetMouseY()>=HEIGHT-128; } }; int main() { SeasonI demo; if (demo.Construct(WIDTH, HEIGHT, 4, 4)) demo.Start(); return 0; }