/* * Game.cpp * * Created on: Feb 9, 2020 * Author: ayoungblood * Special Thanks to: Carl Birch of Let's Make Games * Nic Allen * Brian Lhota */ #include "Game.hpp" #include "../assetmgr/TextureManager.h" #include "../assetmgr/Map.h" #include "../ecs/Components.h" #include "Collision.h" #include #include #include #include #include "../assetmgr/AssetManager.h" #include "../ui/UIText.h" #include "../ui/UINineSlice.h" #include "../cjson/cJSON.h" #include "../tileson/tileson.hpp" #include #include Manager manager; UINineSlice* my9Slice; UINineSlice* scoreboard9Slice; UINineSlice* debugBox; GameStateManager* Game::gsm = new GameStateManager(); SDL_Renderer* Game::renderer = nullptr; SDL_Event Game::event; SDL_Rect Game::camera; SDL_Rect Game::levelMap; AssetManager* Game::assets = new AssetManager(&manager); bool Game::isRunning = false; bool Game::debugMenu = false; auto& player(manager.addEntity()); Vector2D Game::playerPosition; Vector2D Game::pVel; Vector2D Game::fontSize; Vector2D Game::nineSliceSize; int Game::nineSliceX0 = 4; int Game::nineSliceX1 = 12; int Game::nineSliceY0 = 4; int Game::nineSliceY1 = 12; // auto& enemy(manager.addEntity()); auto& puppy(manager.addEntity()); // auto& scoreboard(manager.addEntity()); auto& uiInfo(manager.addEntity()); auto& uiJumpInfo(manager.addEntity()); auto& uiCamXInfo(manager.addEntity()); auto& uiCamYInfo(manager.addEntity()); auto& uiPlayerXInfo(manager.addEntity()); auto& uiPlayerYInfo(manager.addEntity()); auto& uiBoundary1Info(manager.addEntity()); auto& uiBoundary2Info(manager.addEntity()); auto& uiBoundary3Info(manager.addEntity()); auto& uiTextInstructions(manager.addEntity()); auto& gameScene(manager.addEntity()); bool Game::debugCollisionBoxes = false; bool Game::gravityOnPlayer = true; bool Game::playerIsGrounded = false; bool Game::playerIsJumping = false; int gScale = 0; int last_time; int current_time; int diff_time; tson::Tileson t; int Game::pTileX = 0; int Game::pTileY = 0; std::string Game::BoolToString(bool b) { std::string myString; if (b) { myString = "true"; } else { myString = "false"; } return myString; } Game::Game() { // TODO Auto-generated constructor stub } Game::~Game() { // TODO Auto-generated destructor stub } void Game::init(const char *title, int width, int height, bool fullscreen, int globalScale) { camera = { 0, 0, width, height }; int flags = 0; gScale = globalScale; if(fullscreen) { flags = SDL_WINDOW_FULLSCREEN; } if(SDL_Init(SDL_INIT_EVERYTHING & ~(SDL_INIT_TIMER | SDL_INIT_HAPTIC)) == 0) { window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, flags); SDL_SetWindowBordered(window,SDL_FALSE); if(!window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,"Couldn't create window: %s", SDL_GetError()); } renderer = SDL_CreateRenderer(window, -1, 0); if(!renderer) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s", SDL_GetError()); isRunning = false; } else { SDL_SetRenderDrawColor(renderer, 255,255,255,255); SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1"); isRunning = true; } //Initialize SDL_mixer if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048)<0) { SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Couldn't initialize SDL audio mixer!, Error: %s", SDL_GetError()); } assets->AddTexture("player", "assets/textures/actors/kaijuturtle.png"); assets->AddTexture("font", "assets/textures/ui/ui-font-lorez5.png"); assets->AddTexture("textBox", "assets/textures/ui/ui-element-bubble.png"); assets->AddTexture("collider","assets/textures/ColTex.png"); assets->AddMusicTrack("simonZ","assets/audio/music/sillypuppy.ogg"); assets->AddMusicTrack("simonZ","assets/audio/music/victory.ogg"); assets->AddSoundClip("bwoop","assets/audio/sfx/bwoop.wav"); // map = new Map("terrain",globalScale,16); // std::string myText = "Find lost puppies!\nThey need your help!"; std::string myText = "U to Start"; //Set Font and UI NineSlice Sizes here fontSize = Vector2D(5,5); nineSliceSize = Vector2D(16,16); uiTextInstructions.addComponent(4,4,62*gScale,8*gScale,gScale); uiTextInstructions.addComponent("font",myText,fontSize.x,fontSize.y,gScale); uiTextInstructions.addGroup(groupUI_Layer1); SDL_Rect myDestRect = SDL_Rect(); myDestRect.x = 1; myDestRect.y = 1; myDestRect.w = 62; myDestRect.h = 16; my9Slice = new UINineSlice("textBox"); my9Slice->MakeSlices("textBox",nineSliceSize.x,nineSliceSize.y,nineSliceX0,nineSliceX1,nineSliceY0,nineSliceY1,myDestRect,globalScale,Game::groupUI_Layer0); // std::cout << "camera.w " << camera.w << std::endl; // uiInfo.addComponent(camera.w/gScale-94,10,72*gScale,96*gScale,gScale); // uiInfo.addComponent("font", "CollisionHori: Vert: Jump: P.y : P.dy: YVec: ", fontSize.x,fontSize.y, 1); // uiInfo.addComponent("font", "Player PTiX: PTiY: P.x: P.y : coll: Px2: tson: ", fontSize.x,fontSize.y, gScale); // uiInfo.addComponent("font", "Player PTiX: PTiY: P.x: P.y : coll: ", fontSize.x,fontSize.y, gScale); // uiInfo.addGroup(groupUI_Layer3); // // uiCamXInfo.addComponent(camera.w/gScale-48,23,40*gScale,12*gScale,gScale); // uiCamXInfo.addComponent("font", "nan", fontSize.x,fontSize.y, gScale); // uiCamXInfo.addGroup(groupUI_Layer3); // // uiCamYInfo.addComponent(camera.w/gScale-48,36,40*gScale,12*gScale,gScale); // uiCamYInfo.addComponent("font", "nan", fontSize.x,fontSize.y, gScale); // uiCamYInfo.addGroup(groupUI_Layer3); // // uiPlayerXInfo.addComponent(camera.w/gScale-49,49,40*gScale,12*gScale,gScale); // uiPlayerXInfo.addComponent("font", "nan", fontSize.x,fontSize.y, gScale); // uiPlayerXInfo.addGroup(groupUI_Layer3); // // uiPlayerYInfo.addComponent(camera.w/gScale-48,62,40*gScale,12*gScale,gScale); // uiPlayerYInfo.addComponent("font", "nan",fontSize.x,fontSize.y, gScale); // uiPlayerYInfo.addGroup(groupUI_Layer3); // // uiBoundary1Info.addComponent(camera.w/gScale-48,75,128*gScale,12*gScale,gScale); // uiBoundary1Info.addComponent("font", "nan",fontSize.x,fontSize.y, gScale); // uiBoundary1Info.addGroup(groupUI_Layer3); // uiBoundary2Info.addComponent(camera.w/gScale-64,88,128*gScale,12*gScale,gScale); // uiBoundary2Info.addComponent("font", "nan",fontSize.x,fontSize.y, gScale); // uiBoundary2Info.addGroup(groupUI_Layer3); // // uiBoundary3Info.addComponent(camera.w/gScale-64,101,128*gScale,12*gScale,gScale); // uiBoundary3Info.addComponent("font", "nan",fontSize.x,fontSize.y, gScale); // uiBoundary3Info.addGroup(groupUI_Layer3); // debug UI box // SDL_Rect debugBoxRect = SDL_Rect(); // debugBoxRect.x = camera.w-(100*gScale); // debugBoxRect.y = 4*gScale; // debugBoxRect.w = 98*gScale; // debugBoxRect.h = 112*gScale; // debugBox = new UINineSlice("textBox"); // debugBox->MakeSlices("textBox",nineSliceSize.x,nineSliceSize.y,nineSliceX0,nineSliceX1,nineSliceY0,nineSliceY1,debugBoxRect,globalScale,Game::groupUI_Layer2); //ecs implementation // player.addComponent(860*globalScale,640*globalScale,22,42,globalScale); player.addComponent(150*gScale,100*gScale,32,32,globalScale,3); // 180,120 player.addComponent("player", SpriteComponent::spriteAnimation, "assets/textures/actors/kaijuturtle.json"); // player.addComponent(0.0,0.0,false,false,Vector2D().Zero()); player.addComponent("player",16*globalScale,32*globalScale, true, 2*globalScale,10*globalScale, "collider"); player.addComponent(); player.addGroup(groupPlayers); levelMap.x = 0; levelMap.y = 0; // printf("Trying to load Tilemap\n"); gameScene.addComponent("assets/maps/kaiju-city-map.json","kaiju-city","Tile Layer 1","Collision",gScale,player.getComponent().position.x+player.getComponent().width/2,player.getComponent().position.y+player.getComponent().height/2); //150,100 gameScene.addGroup(groupMap); // printf("Completed loading Tilemap\n"); // std::cout << "LevelMap: " << levelMap.x << ", " << levelMap.y << ", " << levelMap.w << ", " << levelMap.h << std::endl; playerPosition = Vector2D().Zero(); pVel = Vector2D().Zero(); // puppy.addComponent(1024*globalScale,210*globalScale,36,30,globalScale); // puppy.addComponent("puppy", SpriteComponent::spriteObject); // puppy.addGroup(groupObjects); //printf("Init Completed\n"); } else { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't Initialize SDL: %s", SDL_GetError()); isRunning = false; } } // ====== Setup groups auto& tiles(manager.getGroup(Game::groupMap)); auto& players(manager.getGroup(Game::groupPlayers)); auto& colliders(manager.getGroup(Game::groupColliders)); auto& objects(manager.getGroup(Game::groupObjects)); // auto& enemies(manager.getGroup(Game::groupEnemies)); // auto& projectiles(manager.getGroup(Game::groupProjectiles)); auto& gui(manager.getGroup(Game::groupUI_Layer0)); auto& uiText(manager.getGroup(Game::groupUI_Layer1)); auto& debugBG(manager.getGroup(Game::groupUI_Layer2)); auto& debugText(manager.getGroup(Game::groupUI_Layer3)); void Game::handleEvents() { SDL_PollEvent(&event); switch (event.type) { case SDL_QUIT: isRunning = false; break; default: break; } } void Game::update() { SDL_Rect playerCol = player.getComponent().collider; Vector2D playerPos = player.getComponent().position; // if (gsm->currentState == GameStateManager::ST_INIT) // { // const char* initText = "Loading..."; // text->ParseString(initText,12,22,gScale,"init"); // const char* titleText = "Beagle Rescue"; // const char* gameOverText = "Game Over"; // } if (Mix_PlayingMusic() == 0 && gsm->currentState == GameStateManager::ST_COREGAME) { // std::cout << "Play Music Now" << std::endl; // Mix_PlayMusic(assets->GetMusicTrack("simonZ"), -1); } if (Mix_PlayingMusic() != 0 && gsm->currentState != GameStateManager::ST_COREGAME) { Mix_HaltMusic(); } // if (Mix_PlayChannel(-1, Game::assets->GetSoundClip("bark1"),0) == 0) // { // Mix_PlayChannel(-1, Game::assets->GetSoundClip("bark1"),0); // } manager.refresh(); manager.update(); for (auto& c : colliders) { // SDL_Rect cCol = c->getComponent().collider; // if(Collision::AABB(cCol, playerCol)) // { // // if(!playerIsGrounded){ // // player.getComponent().Play("Idle"); // // } // // playerIsGrounded = true; // // player.getComponent().position.y = player.getComponent().lastSafePos.y; // // gravityOnPlayer = false; // } } // Gravity // if (gravityOnPlayer){ // player.getComponent().position.y += 3*gScale; // uiJumpInfo.getComponent().updateString("true"); // } else { // uiJumpInfo.getComponent().updateString("false"); // } // for(auto& p: projectiles) // { // if(Collision::AABB(player.getComponent().collider, p->getComponent().collider)) // { // std::cout << "Projectile hit player" << std::endl; // p->destroy(); // } // } auto& tileMap = gameScene.getComponent(); camera.x = player.getComponent().position.x - camera.w/2 + player.getComponent().width/2; camera.y = player.getComponent().position.y - camera.h/2 + player.getComponent().height/2; pTileX = (player.getComponent().position.x+player.getComponent().width/2)/gScale/tileMap.tileWidth; pTileY = (player.getComponent().position.y+player.getComponent().height/2)/gScale/tileMap.tileWidth; player.getComponent().updateTilePosition(pTileX,pTileY); // uiCamXInfo.getComponent().updateString(std::to_string((int)player.getComponent().tilePos.x)); // uiCamYInfo.getComponent().updateString(std::to_string((int)player.getComponent().tilePos.y)); int playerX = player.getComponent().position.x; int playerY = player.getComponent().position.y; // uiPlayerXInfo.getComponent().updateString(std::to_string(playerX)); // uiPlayerYInfo.getComponent().updateString(std::to_string(playerY)); // int * foundBoundaries = predictCollisions(); // int max = foundBoundaries[0]; // for (int b=0;b<3;b++){ // if (foundBoundaries[b]>max){ // max = foundBoundaries[b]; // } // } float desiredMovementX = -1*player.getComponent().speed*0.016; // int desiredMovementY = player.getComponent().velocity.y*player.getComponent().speed*player.getComponent().scale; // uiBoundary1Info.getComponent().updateString(std::to_string((int)foundBoundaries[0])); // uiBoundary1Info.getComponent().updateString(std::to_string((float)desiredMovementX)); if (playerIsGrounded) { // uiBoundary1Info.getComponent().updateString("yes"); } else { // uiBoundary1Info.getComponent().updateString("no"); } // uiBoundary2Info.getComponent().updateString(std::to_string((int)foundBoundaries[1])); // float difference = player.getComponent().position.x+desiredMovementX; //uiBoundary2Info.getComponent().updateString(std::to_string((float)difference)); //uiBoundary3Info.getComponent().updateString(std::to_string((int)(max*gScale))); // uiBoundary3Info.getComponent().updateString(std::to_string((int)foundBoundaries[2])); playerPosition.x = playerX; playerPosition.y = playerY; pVel.x = player.getComponent().velocity.x; pVel.y = player.getComponent().velocity.y; if(camera.x < 0) camera.x = 0; if (camera.y < 0) camera.y = 0; if (camera.x > levelMap.w-camera.w) camera.x = levelMap.w-camera.w; if (camera.y > levelMap.h-camera.h) camera.y = levelMap.h-camera.h; if (Game::debugCollisionBoxes) { for (auto& c: colliders) { c->getComponent().hidden = false; } for (auto& p: players) { p->getComponent().hidden = false; } } else { for (auto& c: colliders) { c->getComponent().hidden = true; } for (auto& p: players) { p->getComponent().hidden = true; } } } void Game::render() { SDL_RenderClear(renderer); // if (gsm->currentState==GameStateManager::ST_COREGAME) // { // printf("Core Game state\n"); // } for (auto& t : tiles) { t->draw(); } for (auto& c : colliders) { c->draw(); } for (auto& o : objects) { o->draw(); } // // for (auto& e : enemies) // { // e->draw(); // } for (auto& p : players) { p->draw(); } if (gsm->currentState==GameStateManager::ST_TITLESCREEN||gsm->currentState==GameStateManager::ST_INIT||gsm->currentState==GameStateManager::ST_GAMEOVER){ for (auto& guiElement : gui) { guiElement->draw(); } for (auto& text : uiText) { text->draw(); } } if (debugMenu) { for (auto& guiElement : debugBG) { guiElement->draw(); } for (auto& text : debugText) { text->draw(); } } SDL_RenderPresent(renderer); } void Game::clean() { SDL_DestroyWindow(window); SDL_DestroyRenderer(renderer); IMG_Quit(); Mix_Quit(); SDL_Quit(); printf("Game Cleaned\n"); } void Game::drawLine(Vector2D srcpt, Vector2D destpt, int red, int green, int blue) { SDL_SetRenderDrawColor(renderer, red, green, blue, 200); SDL_RenderDrawLine(renderer, srcpt.x, srcpt.y, destpt.x, destpt.y); } int * Game::predictCollisions(){ static int boundaries[3]; // ===== LEFT ===== /*if (player.getComponent().velocity.x<0){ // ====== For Each Row ==== int i = 0; for (int r=Game::pTileY-1;r<=Game::pTileY+1;r++){ // ====== For Each Tile (Column) ===== if(r<0){r=0;} for (int c=Game::pTileX;c>Game::pTileX-Game::camera.w/gameScene.getComponent().tileWidth;c--){ if(c<0){c=0;} if(gameScene.getComponent().colliders[r][c]>0){ boundaries[i] = c*gameScene.getComponent().tileWidth+gameScene.getComponent().tileWidth; i++; break; } } } }*/ /* // ====== RIGHT ==== if (player.getComponent().velocity.x>0){ // ====== For Each Row ==== int i = 0; for (int r=Game::pTileY-1;r<=Game::pTileY+1;r++){ if(r<0){r=0;} // ====== For Each Tile (Column) ===== for (int c=Game::pTileX;c().tileWidth;c++){ if(c<0){c=0;} if(gameScene.getComponent().colliders[r][c]>0){ boundaries[i] = c*gameScene.getComponent().tileWidth; i++; break; } } } } // ===== UP ==== if (player.getComponent().velocity.y<0){ // ====== For Each Column ==== int i = 0; for (int c=Game::pTileX-1;c<=Game::pTileX+1;c++){ if(c<0){c=0;} // ====== For Each Tile (Row) ===== for (int r=Game::pTileY;r>Game::pTileY-Game::camera.h/gameScene.getComponent().tileWidth;r--){ if(r<0){r=0;} if(gameScene.getComponent().colliders[r][c]>0){ boundaries[i] = r*gameScene.getComponent().tileWidth+gameScene.getComponent().tileWidth; i++; break; } } } } // ===== DOWN ==== if (player.getComponent().velocity.y>0){ // ====== For Each Column ==== int i = 0; for (int c=Game::pTileX-1;c<=Game::pTileX+1;c++){ if(c<0){c=0;} // ====== For Each Tile (Row) ===== for (int r=Game::pTileY;r().tileWidth;r++){ if(r<0){r=0;} if(gameScene.getComponent().colliders[r][c]>0){ boundaries[i] = r*gameScene.getComponent().tileWidth+gameScene.getComponent().tileWidth; i++; break; } } } } */ return boundaries; }