2dkg/2dgk_6/2dgk_6/KGame.cpp

181 lines
4.6 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 (!CircleTexture.LoadFromFile("textures/00.bmp", Renderer))
{
printf("Failed to load player texture image!\n");
success = false;
}
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;
}
}