0
0
mirror of https://github.com/Nimac0/SDL_Minigame synced 2026-01-12 10:13:42 +00:00

restructured project to compile with CMake

This commit is contained in:
Benedikt Galbavy 2024-01-08 19:32:50 +01:00
parent b73c295363
commit f59059860a
39 changed files with 913 additions and 1 deletions

74
.gitignore vendored
View File

@ -1 +1,73 @@
TestProject/.vs
# CMake
CMakeFiles/
CMakeCache.txt
cmake_install.cmake
Makefile
install_manifest.txt
.cache/
build/
# Compiled files
*.suo
*.user
*.userprefs
*.sln.docstates
# Compiled dynamic libraries
*.so
*.dylib
*.dll
# Compiled executables
*.exe
*.out
*.app
# Generated by Visual Studio
.vscode/
.vs/
*.suo
*.user
*.sln.docstates
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Sublime Text
*.sublime-workspace
*.sublime-project
# macOS
.DS_Store
.AppleDouble
.LSOverride
Icon
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Windows
Desktop.ini

8
.gitmodules vendored Normal file
View File

@ -0,0 +1,8 @@
[submodule "lib/SDL"]
path = lib/SDL
url = https://github.com/libsdl-org/SDL.git
branch = release-2.28.x
[submodule "lib/SDL_image"]
path = lib/SDL_image
url = https://github.com/libsdl-org/SDL_image.git
branch = release-2.8.x

19
CMakeLists.txt Normal file
View File

@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 3.10)
project(SDL_Minigame)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_subdirectory(lib/SDL)
add_subdirectory(lib/SDL_image)
find_package(SDL2 REQUIRED CONFIG REQUIRED COMPONENTS SDL2)
find_package(SDL2 REQUIRED CONFIG COMPONENTS SDL2main)
find_package(SDL_image REQUIRED)
file(GLOB_RECURSE SOURCES src/*.cpp)
add_executable(game ${SOURCES})
target_link_libraries(game PRIVATE SDL2::SDL2main)
target_link_libraries(game PRIVATE SDL2::SDL2 SDL2_image ${SDL2_LIBRARIES} ${SDL_IMAGE_LIBRARIES})

0
README.md Normal file
View File

38
compile_commands.json Normal file
View File

@ -0,0 +1,38 @@
[
{
"directory": "/home/nano/Documents/inno/SDL_Minigame",
"command": "/usr/bin/c++ -I/usr/include/SDL -isystem /usr/include/SDL2 -std=gnu++20 -o CMakeFiles/game.dir/src/Game.cpp.o -c /home/nano/Documents/inno/SDL_Minigame/src/Game.cpp",
"file": "/home/nano/Documents/inno/SDL_Minigame/src/Game.cpp",
"output": "CMakeFiles/game.dir/src/Game.cpp.o"
},
{
"directory": "/home/nano/Documents/inno/SDL_Minigame",
"command": "/usr/bin/c++ -I/usr/include/SDL -isystem /usr/include/SDL2 -std=gnu++20 -o CMakeFiles/game.dir/src/GameObject.cpp.o -c /home/nano/Documents/inno/SDL_Minigame/src/GameObject.cpp",
"file": "/home/nano/Documents/inno/SDL_Minigame/src/GameObject.cpp",
"output": "CMakeFiles/game.dir/src/GameObject.cpp.o"
},
{
"directory": "/home/nano/Documents/inno/SDL_Minigame",
"command": "/usr/bin/c++ -I/usr/include/SDL -isystem /usr/include/SDL2 -std=gnu++20 -o CMakeFiles/game.dir/src/Map.cpp.o -c /home/nano/Documents/inno/SDL_Minigame/src/Map.cpp",
"file": "/home/nano/Documents/inno/SDL_Minigame/src/Map.cpp",
"output": "CMakeFiles/game.dir/src/Map.cpp.o"
},
{
"directory": "/home/nano/Documents/inno/SDL_Minigame",
"command": "/usr/bin/c++ -I/usr/include/SDL -isystem /usr/include/SDL2 -std=gnu++20 -o CMakeFiles/game.dir/src/TextureManager.cpp.o -c /home/nano/Documents/inno/SDL_Minigame/src/TextureManager.cpp",
"file": "/home/nano/Documents/inno/SDL_Minigame/src/TextureManager.cpp",
"output": "CMakeFiles/game.dir/src/TextureManager.cpp.o"
},
{
"directory": "/home/nano/Documents/inno/SDL_Minigame",
"command": "/usr/bin/c++ -I/usr/include/SDL -isystem /usr/include/SDL2 -std=gnu++20 -o CMakeFiles/game.dir/src/Vector2D.cpp.o -c /home/nano/Documents/inno/SDL_Minigame/src/Vector2D.cpp",
"file": "/home/nano/Documents/inno/SDL_Minigame/src/Vector2D.cpp",
"output": "CMakeFiles/game.dir/src/Vector2D.cpp.o"
},
{
"directory": "/home/nano/Documents/inno/SDL_Minigame",
"command": "/usr/bin/c++ -I/usr/include/SDL -isystem /usr/include/SDL2 -std=gnu++20 -o CMakeFiles/game.dir/src/main.cpp.o -c /home/nano/Documents/inno/SDL_Minigame/src/main.cpp",
"file": "/home/nano/Documents/inno/SDL_Minigame/src/main.cpp",
"output": "CMakeFiles/game.dir/src/main.cpp.o"
}
]

1
lib/SDL Submodule

@ -0,0 +1 @@
Subproject commit 05eb08053d48fea9052ad02b3d619244aeb868d3

1
lib/SDL_image Submodule

@ -0,0 +1 @@
Subproject commit abcf63aa71b4e3ac32120fa9870a6500ddcdcc89

36
src/ColliderComponent.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#include <string>
#include "SDL.h"
#include "Components.h"
class ColliderComponent : public Component
{
public:
SDL_Rect collider;
const char* tag;
TransformComponent* transform;
ColliderComponent(const char* tag)
{
this->tag = tag;
}
void init() override
{
if (!entity->hasComponent<TransformComponent>())
{
entity->addComponent<TransformComponent>();
}
transform = &entity->getComponent<TransformComponent>();
Game::colliders.push_back(this);
}
void update() override
{
collider.x = transform->position.x;
collider.y = transform->position.y;
collider.w = transform->width * transform->scale;
collider.h = transform->height * transform->scale;
}
};

8
src/Components.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include "ECS.h"
#include "TransformComponent.h"
#include "SpriteComponent.h"
#include "KeyboardController.h"
#include "ColliderComponent.h"
#include "TileComponent.h"

12
src/Defines.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#define SCREEN_SIZE_HEIGHT 640
#define SCREEN_SIZE_WIDTH 800
#define FPS 60
#define TILE_SIZE 32
#define MAP_SIZE_X 25
#define MAP_SIZE_Y 20

127
src/ECS.h Normal file
View File

@ -0,0 +1,127 @@
#pragma once
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
#include <bitset>
#include <array>
class Component;
class Entity;
using ComponentID = std::size_t;
inline ComponentID getComponentTypeID()
{
static ComponentID lastID = 0;
return lastID++;
}
template <typename T> inline ComponentID getComponentTypeID() noexcept
{
static ComponentID typeID = getComponentTypeID();
return typeID;
}
constexpr std::size_t maxComponents = 32;
using ComponentBitSet = std::bitset<maxComponents>;
using ComponentArray = std::array<Component*, maxComponents>;
class Component
{
public:
Entity* entity;
virtual void init() {}
virtual void update() {}
virtual void draw() {}
virtual ~Component() {}
};
class Entity
{
public:
void update()
{
for (auto& c : components) c->update();
}
void draw()
{
for (auto& c : components) c->draw();
}
bool isActive() const { return this->active; }
void destroy() { this->active = false; }
template <typename T> bool hasComponent() const
{
return componentBitSet[getComponentTypeID<T>()];
}
template <typename T, typename...TArgs>
T& addComponent(TArgs&&...mArgs)
{
T* c(new T(std::forward<TArgs>(mArgs)...));
c->entity = this;
std::unique_ptr<Component> uPtr{ c };
this->components.emplace_back(std::move(uPtr));
componentArray[getComponentTypeID<T>()] = c;
componentBitSet[getComponentTypeID<T>()] = true;
c->init();
return *c;
};
template<typename T> T& getComponent() const
{
auto ptr(componentArray[getComponentTypeID<T>()]);
return *static_cast<T*>(ptr);
}
private:
bool active = true;
std::vector<std::unique_ptr<Component>> components;
ComponentArray componentArray;
ComponentBitSet componentBitSet;
};
class Manager
{
public:
void update()
{
for (auto& e : entities) e->update();
}
void draw()
{
for (auto& e : entities) e->draw();
}
void refresh()
{
entities.erase(std::remove_if(std::begin(entities), std::end(entities),
[](const std::unique_ptr<Entity>& mEntity)
{
return !mEntity->isActive();
}),
std::end(entities));
}
Entity& addEntity()
{
Entity* e = new Entity();
std::unique_ptr<Entity> uPtr{ e };
entities.emplace_back(std::move(uPtr));
return *e;
}
private:
std::vector<std::unique_ptr<Entity>> entities;
};

127
src/Game.cpp Normal file
View File

@ -0,0 +1,127 @@
#include "Game.h"
#include "TextureManager.h"
#include "Map.h"
#include "ECS.h"
#include "Components.h"
#include "Vector2D.h"
Map* map;
Manager manager;
SDL_Renderer* Game::renderer = nullptr;
SDL_Event Game::event;
std::vector<ColliderComponent*> Game::colliders;
auto& player(manager.addEntity());
auto& wall(manager.addEntity());
Game::Game()
{
}
Game::~Game()
{
}
void Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen)
{
int flags = 0;
if (fullscreen) {
flags = SDL_WINDOW_FULLSCREEN;
}
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
std::cout << "ERROR. Subsystem couldnt be initialized!" << std::endl;
return;
}
window = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
if (!window) {
std::cout << "ERROR: Window couldnt be created!" << std::endl;
return;
}
renderer = SDL_CreateRenderer(window, -1, 0);
if (!renderer) {
std::cout << "ERROR: Renderer couldnt be created!" << std::endl;
return;
}
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
this->isRunning = true;
map = new Map();
//ecs implementation
player.addComponent<TransformComponent>(2);
player.addComponent<SpriteComponent>("assets/chicken_neutral_knight.png");
player.addComponent<KeyboardController>();
player.addComponent<ColliderComponent>("player");
wall.addComponent<TransformComponent>(300.0f, 300.0f, 300, 20, 1);
wall.addComponent<SpriteComponent>("assets/stone.png");
wall.addComponent<ColliderComponent>("wall");
}
void Game::handleEvents()
{
SDL_PollEvent(&event);
switch (event.type)
{
case SDL_QUIT: this->isRunning = false;
break;
default:
break;
}
}
void Game::update()
{
Vector2D playerPos = player.getComponent<TransformComponent>().position;
manager.refresh();
manager.update();
for (auto cc : colliders)
{
if (SDL_HasIntersection(&player.getComponent<ColliderComponent>().collider, &cc->collider) && strcmp(cc->tag, "player"))
{
player.getComponent<TransformComponent>().position = playerPos;
}
}
}
void Game::render()
{
SDL_RenderClear(renderer);
manager.draw();
SDL_RenderPresent(renderer);
}
void Game::clean()
{
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
std::cout << "Game Cleaned!" << std::endl;
}
void Game::addTile(int id, int x, int y)
{
auto& tile(manager.addEntity());
tile.addComponent<TileComponent>(x, y, 32, 32, id);
}
bool Game::running()
{
return isRunning;
}

35
src/Game.h Normal file
View File

@ -0,0 +1,35 @@
#pragma once
#include <stdio.h>
#include <iostream>
#include <SDL.h>
#include <SDL_image.h>
#include <vector>
#include <string.h>
class ColliderComponent;
class Game
{
public:
Game();
~Game();
void init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen);
void handleEvents();
void update();
void render();
void clean();
bool running();
static void addTile(int id, int x, int y);
static SDL_Renderer* renderer;
static SDL_Event event;
static std::vector<ColliderComponent*> colliders;
private:
int counter = 0;
bool isRunning = false;
SDL_Window* window;
};

35
src/GameObject.cpp Normal file
View File

@ -0,0 +1,35 @@
#include "GameObject.h"
#include "TextureManager.h"
GameObject::GameObject(const char* texturesheet, int x, int y)
{
this->objTexture = TextureManager::loadTexture(texturesheet);
this->xPos = x;
this->yPos = y;
}
GameObject::~GameObject()
{
}
void GameObject::update()
{
xPos++;
yPos++;
srcRect.h = 32;
srcRect.w = 32;
srcRect.x = 0;
srcRect.y = 0;
destRect.h = srcRect.h *2;
destRect.w = srcRect.w *2;
destRect.x = xPos;
destRect.y = yPos;
}
void GameObject::render()
{
SDL_RenderCopy(Game::renderer, objTexture, &srcRect, &destRect);
}

20
src/GameObject.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include "Game.h"
class GameObject
{
public:
GameObject(const char* texturesheet, int x, int y);
~GameObject();
void update();
void render();
private:
int xPos;
int yPos;
SDL_Texture* objTexture;
SDL_Rect srcRect, destRect;
};

35
src/KeyboardController.h Normal file
View File

@ -0,0 +1,35 @@
#pragma once
#include "Game.h"
#include "ECS.h"
#include "Components.h"
class KeyboardController : public Component
{
public:
TransformComponent* transform;
const Uint8* keystates = SDL_GetKeyboardState(NULL);
void init() override
{
transform = &entity->getComponent<TransformComponent>();
}
void update() override
{
transform->velocity.x = 0;
transform->velocity.y = 0;
if (keystates[SDL_SCANCODE_UP] || keystates[SDL_SCANCODE_W]) {
transform->velocity.y = -1;
}
if (keystates[SDL_SCANCODE_LEFT] || keystates[SDL_SCANCODE_A]) {
transform->velocity.x = -1;
}
if (keystates[SDL_SCANCODE_DOWN] || keystates[SDL_SCANCODE_S]) {
transform->velocity.y = 1;
}
if (keystates[SDL_SCANCODE_RIGHT] || keystates[SDL_SCANCODE_D]) {
transform->velocity.x = 1;
}
}
};

31
src/Map.cpp Normal file
View File

@ -0,0 +1,31 @@
#include "Map.h"
#include "Game.h"
#include <fstream>
Map::Map()
{
}
Map::~Map()
{
}
void Map::loadMap(const char* path, int sizeX, int sizeY)
{
char tile;
std::fstream mapFile;
mapFile.open(path);
for (int y = 0; y < sizeY; y++)
{
for (int x = 0; x < sizeX; x++)
{
mapFile.get(tile);
Game::addTile(atoi(&tile), x * TILE_SIZE, y * TILE_SIZE);
mapFile.ignore();
}
}
mapFile.close();
}

16
src/Map.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include "Defines.h"
class Map
{
public:
Map();
~Map();
static void loadMap(const char* path, int sizeX, int sizeY);
private:
};

55
src/SpriteComponent.h Normal file
View File

@ -0,0 +1,55 @@
#pragma once
#include "Components.h"
#include "SDL.h"
#include "TextureManager.h"
class SpriteComponent : public Component
{
public:
SpriteComponent() = default;
SpriteComponent(const char* path)
{
setTexture(path);
}
~SpriteComponent()
{
SDL_DestroyTexture(this->texture);
}
void setTexture(const char* path)
{
//SDL_DestroyTexture(this->texture);
this->texture = TextureManager::loadTexture(path);
}
void init() override
{
this->transform = &entity->getComponent<TransformComponent>();
this->srcRect.x = this->srcRect.y = 0;
this->srcRect.w = transform->width;
this->srcRect.h = transform->height;
;
}
void update() override
{
this->destRect.x = this->transform->position.x;
this->destRect.y = this->transform->position.y;
this->destRect.w = transform->width * transform->scale;
this->destRect.h = transform->height * transform->scale;
}
void draw() override
{
TextureManager::draw(this->texture, this->srcRect, this->destRect);
}
private:
TransformComponent* transform;
SDL_Texture* texture;
SDL_Rect srcRect, destRect;
};

12
src/TextureDict.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include <map>
#include <string>
std::map<int, const char*> textureDict =
{
{0, "assets/water.png"},
{1, "assets/dirt.png"},
{2, "assets/grass.png"}
};

12
src/TextureManager.cpp Normal file
View File

@ -0,0 +1,12 @@
#include "TextureManager.h"
SDL_Texture* TextureManager::loadTexture(const char* fileName)
{
return IMG_LoadTexture(Game::renderer, fileName);
}
void TextureManager::draw(SDL_Texture* texture, SDL_Rect src, SDL_Rect dest)
{
SDL_RenderCopy(Game::renderer, texture, &src, &dest);
}

10
src/TextureManager.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include "Game.h"
class TextureManager
{
public:
static SDL_Texture* loadTexture(const char* fileName);
static void draw(SDL_Texture* texture, SDL_Rect src, SDL_Rect dest);
};

41
src/TileComponent.h Normal file
View File

@ -0,0 +1,41 @@
#pragma once
#include "ECS.h"
#include "TransformComponent.h"
#include "SDL.h"
#include "TextureDict.h"
class TileComponent : public Component
{
public:
TransformComponent* transform;
SpriteComponent* sprite;
SDL_Rect tileRect;
int tileID;
const char* path;
TileComponent() = default;
TileComponent(int x, int y, int w, int h, int id)
{
this->tileRect.x = x;
this->tileRect.y = y;
this->tileRect.w = w;
this->tileRect.h = h;
tileID = id;
auto it = textureDict.find(tileID)->second;
this->path = it;
}
~TileComponent() = default;
void init() override
{
this->entity->addComponent<TransformComponent>(this->tileRect.x, this->tileRect.y, this->tileRect.w, this->tileRect.h, 1);
this->transform = &entity->getComponent<TransformComponent>();
this->entity->addComponent<SpriteComponent>(this->path);
this->sprite = &entity->getComponent<SpriteComponent>();
}
};

55
src/TransformComponent.h Normal file
View File

@ -0,0 +1,55 @@
#pragma once
#include "Components.h"
#include "Vector2D.h"
class TransformComponent : public Component
{
public:
Vector2D position;
Vector2D velocity;
int height = 32;
int width = 32;
int scale = 1;
int speed = 3;
TransformComponent()
{
position.zero();
}
TransformComponent(int scale)
{
position.zero();
this->scale = scale;
}
TransformComponent(float x, float y)
{
this->position.x = x;
this->position.y = y;
}
TransformComponent(float x, float y, int w, int h, int scale)
{
this->position.x = x;
this->position.y = y;
this->width = w;
this->height = h;
this->scale = scale;
}
void init() override
{
velocity.zero();
}
void update() override
{
position.x += velocity.x * speed;
position.y += velocity.y * speed;
}
};

52
src/Vector2D.cpp Normal file
View File

@ -0,0 +1,52 @@
#include "Vector2D.h"
Vector2D::Vector2D()
{
this->x = 0.0f;
this->y = 0.0f;
}
Vector2D::Vector2D(float x, float y)
{
this->x = x;
this->y = y;
}
Vector2D& operator+(Vector2D& vector1, const Vector2D& vector2)
{
vector1.x += vector2.x;
vector1.y += vector2.y;
return vector1;
}
Vector2D& operator-(Vector2D& vector1, const Vector2D& vector2)
{
vector1.x -= vector2.x;
vector1.y -= vector2.y;
return vector1;
}
Vector2D& operator*(Vector2D& vector1, const Vector2D& vector2)
{
vector1.x *= vector2.x;
vector1.y *= vector2.y;
return vector1;
}
Vector2D& operator/(Vector2D& vector1, const Vector2D& vector2)
{
vector1.x /= vector2.x;
vector1.y /= vector2.y;
return vector1;
}
Vector2D& Vector2D::operator*(const int& i)
{
this->x *= i;
this->y *= i;
return *this;
}
Vector2D& Vector2D::zero()
{
this->x = 0.0f;
this->y = 0.0f;
return *this;
}

19
src/Vector2D.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
class Vector2D
{
public:
float x;
float y;
Vector2D();
Vector2D(float x, float y);
friend Vector2D& operator+(Vector2D& vector1, const Vector2D& vector2);
friend Vector2D& operator-(Vector2D& vector1, const Vector2D& vector2);
friend Vector2D& operator*(Vector2D& vector1, const Vector2D& vector2);
friend Vector2D& operator/(Vector2D& vector1, const Vector2D& vector2);
Vector2D& operator*(const int& i);
Vector2D& zero();
};

BIN
src/assets/Map.aseprite Normal file

Binary file not shown.

BIN
src/assets/MapNew.aseprite Normal file

Binary file not shown.

BIN
src/assets/cat.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 751 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 949 B

BIN
src/assets/cow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
src/assets/dirt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

BIN
src/assets/grass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

BIN
src/assets/stone.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

BIN
src/assets/water.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

BIN
src/assets/water1.ase Normal file

Binary file not shown.

BIN
src/assets/water1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

35
src/main.cpp Normal file
View File

@ -0,0 +1,35 @@
#include "Game.h"
#include "Defines.h"
Game* game = nullptr;
int main(int argc, char* argv[])
{
const int frameDelay = 1000 / FPS;
Uint32 frameStart;
int frameTime;
game = new Game();
game->init("RPG_Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_SIZE_WIDTH, SCREEN_SIZE_HEIGHT, false);
while (game->running())
{
frameStart = SDL_GetTicks();
game->handleEvents();
game->update();
game->render();
frameTime = SDL_GetTicks() - frameStart;
if (frameDelay > frameTime)
{
SDL_Delay(frameDelay - frameTime);
}
}
game->clean();
return 0;
}