2dkg/2dgk_7/2dgk_7/KGame.cpp
2021-12-04 11:24:34 +01:00

233 lines
5.9 KiB
C++

#include "KGame.h"
#include "SDL.h"
#include <cstdio>
#include <cmath>
#include <string>
#include <fstream>
#include <vector>
#include "Utils.h"
#include "Constants.h"
#include "KTexture.h"
#include "KTile.h"
#include "KVector2d.h"
namespace KapitanGame {
KGame::KGame() : HasSeparation(true), HasCollision(true) {
//Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
throw std::runtime_error(Utils::StringFormat("SDL could not initialize! SDL_Error: %s", SDL_GetError()));
}
//Set texture filtering to linear
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
{
printf("Warning: Linear texture filtering not enabled!\n");
}
Input.Init();
//Create window
Window = SDL_CreateWindow(Constants::WINDOW_TITLE, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, Constants::SCREEN_WIDTH, Constants::SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (Window == nullptr)
{
throw std::runtime_error(Utils::StringFormat("Window could not be created! SDL_Error: %s", SDL_GetError()));
}
//Create renderer for window
Renderer = SDL_CreateRenderer(Window, -1, SDL_RENDERER_ACCELERATED);
if (Renderer == nullptr)
{
throw std::runtime_error(Utils::StringFormat("Renderer could not be created! SDL Error: %s", SDL_GetError()));
}
//Initialize renderer color
SDL_SetRenderDrawColor(Renderer, 0, 0xFF, 0, 0xFF);
}
KGame::~KGame() {
//Free loaded images
CircleTexture.Free();
Input.Free();
//Destroy window
SDL_DestroyRenderer(Renderer);
SDL_DestroyWindow(Window);
Window = nullptr;
Renderer = nullptr;
//Quit SDL subsystems
SDL_Quit();
}
bool KGame::LoadMedia()
{
//Loading success flag
bool success = true;
if (!PlayerTexture.LoadFromFile("textures/player.bmp", Renderer))
{
printf("Failed to load player texture image!\n");
success = false;
}
if (!PlayerTexture2.LoadFromFile("textures/player2.bmp", Renderer))
{
printf("Failed to load player texture image!\n");
success = false;
}
for (int i = static_cast<int>(TileType::Default); i <= static_cast<int>(TileType::Dot); ++i)
{
if (!TileTextures[i].LoadFromFile("textures/0" + std::to_string(i) + ".bmp", Renderer))
{
printf("Failed to load 0%d texture image!\n", i);
success = false;
}
}
Tiles.clear();
std::ifstream levelFile;
levelFile.open("level.txt");
if (levelFile.fail())
{
printf("Failed to load level.txt!\n");
success = false;
}
else
{
int y = 0;
std::string line;
while (std::getline(levelFile, line)) {
if (MapWidth < static_cast<int>(line.length() * Constants::TILE_WIDTH))
MapWidth = static_cast<int>(line.length()) * Constants::TILE_WIDTH;
for (auto i = 0ull; i < line.length(); ++i) {
auto type = TileType::Default;
switch (line[i])
{
case '|':
type = TileType::VerticalWall;
break;
case '-':
type = TileType::HorizontalWall;
break;
case '.':
type = TileType::Dot;
break;
default:;
}
Tiles.emplace_back(i * Constants::TILE_WIDTH, y * Constants::TILE_HEIGHT, type);
}
++y;
}
MapHeight = y * Constants::TILE_HEIGHT;
levelFile.close();
}
return success;
}
SDL_Texture* KGame::LoadTexture(const std::string& path) const {
//The final optimized image
SDL_Texture* newTexture = nullptr;
//Load image at specified path
SDL_Surface* loadedSurface = SDL_LoadBMP(path.c_str());
if (loadedSurface == nullptr)
{
printf("Unable to load image %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
}
else
{
//Create texture from surface pixels
newTexture = SDL_CreateTextureFromSurface(Renderer, loadedSurface);
if (newTexture == nullptr)
{
printf("Unable to optimize image %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
}
//Get rid of old loaded surface
SDL_FreeSurface(loadedSurface);
}
return newTexture;
}
int KGame::Run(int argc, char* args[])
{
//Load media
if (!LoadMedia())
{
printf("Failed to load media!\n");
}
else
{
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
SDL_Rect map{ 0,0,Constants::SCREEN_WIDTH, Constants::SCREEN_HEIGHT };
for (int i = 0; i < Constants::CIRCLES_COUNT; ++i) {
KVector2D position(Utils::RandomNumber() * (Constants::SCREEN_WIDTH - 2 * CircleTexture.GetWidth()) + CircleTexture.GetWidth(), Utils::RandomNumber() * (Constants::SCREEN_HEIGHT - 2 * CircleTexture.GetHeight()) + CircleTexture.GetHeight());
Circles.emplace_back(position, KVector2D(100.f, 100.f), CircleTexture.GetWidth() / 2, CircleTexture);
}
uint32_t previousTime;
uint32_t time = previousTime = SDL_GetTicks();
printf("\n");
//While application is running
while (!quit)
{
previousTime = time;
time = SDL_GetTicks();
Input.HandleInputPreEvents();
//Handle events on queue
while (SDL_PollEvent(&e))
{
//User requests quit
if (e.type == SDL_QUIT)
{
quit = true;
continue;
}
Input.HandleEvent(e);
}
Input.HandleInputPostEvents();
if (Input.IsKeyboardButtonPressed(SDL_SCANCODE_S) || Input.IsControllerButtonPressed(Controllers::Controller1, SDL_CONTROLLER_BUTTON_START))
{
HasSeparation = !HasSeparation;
}
if (Input.IsKeyboardButtonPressed(SDL_SCANCODE_C) || Input.IsControllerButtonPressed(Controllers::Controller1, SDL_CONTROLLER_BUTTON_BACK))
{
HasCollision = !HasCollision;
}
for (auto& circle : Circles)
circle.CollisionDetectionStep(Circles, HasSeparation, HasCollision);
for (auto& circle : Circles)
circle.CollisionDetectionWithMapStep(map);
for (auto& circle : Circles)
circle.MovementStep(static_cast<float>(time - previousTime) / 1000.f);
//Clear screen
SDL_SetRenderDrawColor(Renderer, 0, 0xFF, 0, 0xFF);
SDL_RenderClear(Renderer);
for (auto& circle : Circles)
circle.Render(Renderer);
//Update screen
SDL_RenderPresent(Renderer);
}
}
return 0;
}
}