Yikes, very convoluted game structure

This commit is contained in:
Maximilian Giller 2023-04-27 23:05:19 +02:00
parent ed20e7a1e0
commit e19972ae7c
22 changed files with 8089 additions and 98 deletions

View file

@ -7,14 +7,36 @@ set(CMAKE_CXX_STANDARD 20)
find_package(SFML 2.5 COMPONENTS graphics audio REQUIRED)
include_directories(${SFML_INCLUDE_DIR})
# Find and include Eigen
find_package(Eigen3 3.3 REQUIRED NO_MODULE)
include_directories(${EIGEN3_INCLUDE_DIR})
# Set up your project's source files
set(SOURCES
src/main.cpp
src/game/renderer.h
src/game/renderer.cpp src/game/game_object.cpp src/game/game_object.h src/game/game.cpp src/game/game.h src/util/logger.cpp src/util/logger.h)
src/game/renderer.cpp
src/game/game_object.cpp
src/game/game_object.h
src/game/game.cpp
src/game/game.h
src/util/easylogging++.cc
src/util/easylogging++.h
src/coordinates/isometric_coordinate_transformer.cpp
src/coordinates/isometric_coordinate_transformer.h
src/coordinates/translated_coordinates.cpp
src/coordinates/translated_coordinates.h
src/coordinates/coordinates.h
src/game/input_handler.cpp
src/game/input_handler.h
src/primitives/circle_object.cpp
src/primitives/circle_object.h
)
# Add an executable target
add_executable(Holesome ${SOURCES})
# Link SFML to your executable target
# Link SFML and other libraries to your executable target
target_link_libraries(Holesome sfml-graphics sfml-audio)
target_link_libraries(Holesome Eigen3::Eigen)

View file

@ -48,4 +48,4 @@ Potential expansions:
## Project Setup
Install SFML: `sudo apt install libsfml-dev libsfml-doc`
Install SFML and Eigen: `sudo apt install libsfml-dev libsfml-doc libeigen3-dev`

View file

@ -0,0 +1,57 @@
//
// Created by max on 27.04.23.
//
#ifndef HOLESOME_COORDINATES_H
#define HOLESOME_COORDINATES_H
struct WorldCoordinates {
float x;
float y;
float z; // Height
WorldCoordinates operator+(WorldCoordinates other) const {
return {
x + other.x,
y + other.y,
z + other.z
};
}
WorldCoordinates operator-(WorldCoordinates other) const {
return (*this) + (other * -1);
}
WorldCoordinates operator*(float factor) const {
return {
x * factor,
y * factor,
z * factor
};
}
WorldCoordinates operator/(float factor) const {
return (*this) * (1 / factor);
}
bool operator==(WorldCoordinates other) const {
return x == other.x && y == other.y && z == other.z;
}
bool operator!=(WorldCoordinates other) const {
return !(*this == other);
}
};
struct ScreenCoordinates {
float x;
float y;
};
struct GridCoordinates {
float x;
float y;
};
#endif //HOLESOME_COORDINATES_H

View file

@ -0,0 +1,23 @@
//
// Created by max on 27.04.23.
//
#include "isometric_coordinate_transformer.h"
IsometricCoordinateTransformer::IsometricCoordinateTransformer() {
worldToScreenMatrix = Eigen::Matrix<float, 2, 3>();
worldToScreenMatrix << 0.5f, 0.5f, 0,
-0.5f, 0.5f, -1;
}
ScreenCoordinates IsometricCoordinateTransformer::worldToScreen(WorldCoordinates worldCoordinates) const {
Eigen::Vector3f worldCoordinatesVector;
worldCoordinatesVector << worldCoordinates.x, worldCoordinates.y, worldCoordinates.z;
Eigen::Vector2f screenCoordinatesVector = worldToScreenMatrix * worldCoordinatesVector;
return {
screenCoordinatesVector.x(),
screenCoordinatesVector.y()
};
}

View file

@ -0,0 +1,21 @@
//
// Created by max on 27.04.23.struct
//
#ifndef HOLESOME_ISOMETRIC_COORDINATE_TRANSFORMER_H
#define HOLESOME_ISOMETRIC_COORDINATE_TRANSFORMER_H
#include <Eigen/Dense>
#include "coordinates.h"
class IsometricCoordinateTransformer {
private:
Eigen::Matrix<float, 2, 3> worldToScreenMatrix;
public:
IsometricCoordinateTransformer();
ScreenCoordinates worldToScreen(WorldCoordinates worldCoordinates) const;
};
#endif //HOLESOME_ISOMETRIC_COORDINATE_TRANSFORMER_H

View file

@ -0,0 +1,32 @@
//
// Created by max on 27.04.23.
//
#include "translated_coordinates.h"
WorldCoordinates TranslatedCoordinates::getWorldCoordinates() const {
return worldCoordinates;
}
ScreenCoordinates TranslatedCoordinates::getScreenCoordinates() const {
return isoCoordTransformer->worldToScreen(worldCoordinates);
}
GridCoordinates TranslatedCoordinates::getGridCoordinates() const {
// Grid coords are just world coords without height, and scaled differently
return {worldCoordinates.x * worldToGridFactor, worldCoordinates.y * worldToGridFactor};
}
void TranslatedCoordinates::set(WorldCoordinates newWorldCoordinates) {
this->worldCoordinates = newWorldCoordinates;
}
void TranslatedCoordinates::move(WorldCoordinates deltaWorldCoordinates) {
this->worldCoordinates = this->worldCoordinates + deltaWorldCoordinates;
}
TranslatedCoordinates::TranslatedCoordinates(WorldCoordinates worldCoordinates)
: worldCoordinates(worldCoordinates) {
}

View file

@ -0,0 +1,35 @@
//
// Created by max on 27.04.23.
//
#ifndef HOLESOME_TRANSLATED_COORDINATES_H
#define HOLESOME_TRANSLATED_COORDINATES_H
#include <memory>
#include "coordinates.h"
#include "isometric_coordinate_transformer.h"
#define INITIAL_WORLD_TO_GRID_FACTOR 0.25f
class TranslatedCoordinates {
public:
explicit TranslatedCoordinates(WorldCoordinates worldCoordinates);
WorldCoordinates getWorldCoordinates() const;
ScreenCoordinates getScreenCoordinates() const;
GridCoordinates getGridCoordinates() const;
void set(WorldCoordinates newWorldCoordinates);
void move(WorldCoordinates deltaWorldCoordinates);
private:
WorldCoordinates worldCoordinates;
const float worldToGridFactor = INITIAL_WORLD_TO_GRID_FACTOR;
const std::shared_ptr<IsometricCoordinateTransformer> isoCoordTransformer = std::make_shared<IsometricCoordinateTransformer>();
};
#endif //HOLESOME_TRANSLATED_COORDINATES_H

View file

@ -3,24 +3,57 @@
//
#include <utility>
#include <SFML/Window/Event.hpp>
#include "game.h"
Game::Game(std::shared_ptr<Renderer> renderer) : renderer(std::move(renderer)) {
Game::Game(std::shared_ptr<Renderer> renderer) : renderer(std::move(renderer)), isRunning(false), gameObjects() {
}
void Game::run() {
if (isRunning) {
Logger::debug("Game is already running", "Game::run");
LOG(WARNING) << "Game is already running";
return;
}
isRunning = true;
while (isRunning) {
renderFrame();
// Process any events that have occurred since the last iteration
sf::Event event{};
while (renderer->pollEvent(event)) {
// If the event is to close the window, then close it
if (event.type == sf::Event::Closed) {
exit();
}
if (event.key.code == sf::Keyboard::Escape || event.key.code == sf::Keyboard::Q) {
exit();
}
}
}
}
void Game::stop() {
void Game::exit() {
isRunning = false;
renderer->close();
}
void Game::renderFrame() {
for (auto &gameObject: gameObjects) {
renderer->draw(gameObject);
}
renderer->display();
}
Game::~Game() {
for (auto &gameObject: gameObjects) {
delete gameObject;
}
}
void Game::addGameObject(GameObject *gameObject) {
gameObjects.push_back(gameObject);
}

View file

@ -8,21 +8,28 @@
#include <memory>
#include "renderer.h"
#include "../util/logger.h"
#include "../util/easylogging++.h"
#include "game_object.h"
class Game {
private:
std::shared_ptr<Renderer> renderer;
std::vector<GameObject *> gameObjects;
bool isRunning = false;
public:
explicit Game(std::shared_ptr<Renderer> renderer);
~Game();
void run();
/***
* Stops the game and sets isRunning to false.
* Stops the game and closes the window.
*/
void stop();
void exit();
void addGameObject(GameObject *gameObject);
void renderFrame();
};

View file

@ -1 +1,9 @@
#include "game_object.h"
TranslatedCoordinates *GameObject::getCoordinates() const {
return coordinates.get();
}
GameObject::GameObject() : coordinates(std::make_shared<TranslatedCoordinates>(WorldCoordinates(0, 0, 0))) {
}

View file

@ -2,9 +2,20 @@
#define HOLESOME_GAME_OBJECT_H
class game_object {
#include <memory>
#include <SFML/Graphics/Drawable.hpp>
#include "../coordinates/translated_coordinates.h"
class GameObject : public sf::Drawable {
public:
GameObject();
void draw(sf::RenderTarget &target, sf::RenderStates states) const override = 0;
TranslatedCoordinates* getCoordinates() const;
protected:
std::shared_ptr<TranslatedCoordinates> coordinates;
};
#endif //HOLESOME_GAME_OBJECT_H

View file

@ -0,0 +1,5 @@
//
// Created by max on 27.04.23.
//
#include "input_handler.h"

14
src/game/input_handler.h Normal file
View file

@ -0,0 +1,14 @@
//
// Created by max on 27.04.23.
//
#ifndef HOLESOME_INPUT_HANDLER_H
#define HOLESOME_INPUT_HANDLER_H
class InputHandler {
};
#endif //HOLESOME_INPUT_HANDLER_H

View file

@ -1 +1,45 @@
#include "renderer.h"
void Renderer::draw(sf::Drawable *drawable) {
window->draw(*drawable);
}
void Renderer::close() {
window->close();
}
Renderer::~Renderer() {
delete window;
}
std::shared_ptr<Renderer> Renderer::createWindow(const std::string &title, int width, int height) {
auto renderer = std::make_shared<Renderer>();
renderer->window = new sf::RenderWindow(sf::VideoMode(width, height), title);
return renderer;
}
std::shared_ptr<Renderer> Renderer::createFullscreen(const std::string &title) {
sf::VideoMode fullScreenMode;
auto availableModes = sf::VideoMode::getFullscreenModes();
if (availableModes.empty()) {
LOG(INFO) << "No fullscreen modes available, falling back to Desktop Mode.";
fullScreenMode = sf::VideoMode::getDesktopMode();
} else {
fullScreenMode = availableModes[0];
fullScreenMode.bitsPerPixel = sf::VideoMode::getDesktopMode().bitsPerPixel;
}
auto renderer = std::make_shared<Renderer>();
renderer->window = new sf::RenderWindow(fullScreenMode, title, sf::Style::Fullscreen);
return renderer;
}
void Renderer::display() {
window->display();
window->clear(sf::Color::Black);
}
bool Renderer::pollEvent(sf::Event &event) {
return window->pollEvent(event);
}

View file

@ -1,12 +1,26 @@
#ifndef HOLESOME_RENDERER_H
#define HOLESOME_RENDERER_H
#include <SFML/Graphics/RenderWindow.hpp>
#include "../util/easylogging++.h"
class Renderer {
public:
static Renderer *createWindow(std::string title, int width, int height);
static Renderer *createFullscreen(std::string title);
static std::shared_ptr<Renderer> createWindow(const std::string &title, int width = 960, int height = 540);
void draw();
static std::shared_ptr<Renderer> createFullscreen(const std::string &title);
~Renderer();
bool pollEvent(sf::Event &event);
void draw(sf::Drawable *drawable);
void display();
void close();
private:
sf::RenderWindow *window;
};

View file

@ -1,61 +1,17 @@
#include <SFML/Graphics.hpp>
#include <iostream>
#include "util/easylogging++.h"
#include "game/game.h"
#include "primitives/circle_object.h"
int main() {
// Create a window with a resolution of 800x600 pixels
sf::RenderWindow window = sf::RenderWindow();
INITIALIZE_EASYLOGGINGPP
int main(int argc, char *argv[]) {
START_EASYLOGGINGPP(argc, argv);
sf::VideoMode mode = sf::VideoMode::getDesktopMode();
std::cout << "Desktop Mode: "
<< mode.width << "x" << mode.height << " - "
<< mode.bitsPerPixel << " bpp" << std::endl;
auto game = Game(Renderer::createFullscreen("Holesome"));
// Display the list of all the video modes available for fullscreen
std::vector<sf::VideoMode> modes = sf::VideoMode::getFullscreenModes();
for (std::size_t i = 0; i < modes.size(); ++i) {
sf::VideoMode mode = modes[i];
std::cout << "Mode #" << i << ": "
<< mode.width << "x" << mode.height << " - "
<< mode.bitsPerPixel << " bpp" << std::endl;
}
game.addGameObject(new CircleObject(50, sf::Color::Red));
window.create(sf::VideoMode::getDesktopMode(), "Sample Game", sf::Style::Fullscreen);
// Main loop that runs until the window is closed
while (window.isOpen()) {
// Process any events that have occurred since the last iteration
sf::Event event;
while (window.pollEvent(event)) {
// If the event is to close the window, then close it
if (event.type == sf::Event::Closed) {
window.close();
}
if (event.key.code == sf::Keyboard::Escape || event.key.code == sf::Keyboard::Q) {
window.close();
}
}
// Clear the window to a solid color
window.clear(sf::Color::Black);
// Draw any objects that you want to display in the window
// Create a circle shape with a radius of 50 pixels
sf::CircleShape circle(50.f);
// Set the position of the circle shape to the center of the window
circle.setPosition(window.getSize().x / 2.f, window.getSize().y / 2.f);
// Set the color of the circle shape to red
circle.setFillColor(sf::Color::Red);
// Draw the circle shape on the window
window.draw(circle);
// Display the objects on the window
window.display();
}
return 0;
game.run();
}

View file

@ -0,0 +1,20 @@
//
// Created by max on 27.04.23.
//
#include <SFML/Graphics/CircleShape.hpp>
#include "circle_object.h"
CircleObject::CircleObject(int radius, sf::Color color) : radius(radius), color(color) {
}
void CircleObject::draw(sf::RenderTarget &target, sf::RenderStates states) const {
sf::CircleShape circle(radius);
circle.setFillColor(color);
circle.setPosition(coordinates->getScreenCoordinates().x, coordinates->getScreenCoordinates().y);
target.draw(circle);
}

View file

@ -0,0 +1,24 @@
//
// Created by max on 27.04.23.
//
#ifndef HOLESOME_CIRCLE_OBJECT_H
#define HOLESOME_CIRCLE_OBJECT_H
#include "../game/game_object.h"
#include <SFML/Graphics/RenderTarget.hpp>
class CircleObject : public GameObject {
public:
CircleObject(int radius, sf::Color color);
void draw(sf::RenderTarget &target, sf::RenderStates states) const override;
private:
int radius;
sf::Color color;
};
#endif //HOLESOME_CIRCLE_OBJECT_H

3120
src/util/easylogging++.cc Normal file

File diff suppressed because it is too large Load diff

4576
src/util/easylogging++.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,13 +0,0 @@
//
// Created by max on 26.04.23.
//
#include "logger.h"
void Logger::debug(const std::string& msg, const std::string& source) {
log(msg, source, "DBG");
}
void Logger::log(const std::string& msg, const std::string& source, const std::string& level) {
std::cout << level << " [" << source << "] " << msg << std::endl;
}

View file

@ -1,18 +0,0 @@
//
// Created by max on 26.04.23.
//
#ifndef HOLESOME_LOGGER_H
#define HOLESOME_LOGGER_H
#include <string>
#include <iostream>
class Logger {
public:
static void debug(const std::string& msg, const std::string& source);
static void log(const std::string& msg, const std::string& source, const std::string& level);
};
#endif //HOLESOME_LOGGER_H