Yikes, very convoluted game structure
This commit is contained in:
parent
ed20e7a1e0
commit
e19972ae7c
22 changed files with 8089 additions and 98 deletions
|
@ -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)
|
||||
|
|
|
@ -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`
|
||||
|
|
57
src/coordinates/coordinates.h
Normal file
57
src/coordinates/coordinates.h
Normal 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
|
23
src/coordinates/isometric_coordinate_transformer.cpp
Normal file
23
src/coordinates/isometric_coordinate_transformer.cpp
Normal 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()
|
||||
};
|
||||
}
|
21
src/coordinates/isometric_coordinate_transformer.h
Normal file
21
src/coordinates/isometric_coordinate_transformer.h
Normal 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
|
32
src/coordinates/translated_coordinates.cpp
Normal file
32
src/coordinates/translated_coordinates.cpp
Normal 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) {
|
||||
}
|
||||
|
||||
|
35
src/coordinates/translated_coordinates.h
Normal file
35
src/coordinates/translated_coordinates.h
Normal 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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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))) {
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
5
src/game/input_handler.cpp
Normal file
5
src/game/input_handler.cpp
Normal file
|
@ -0,0 +1,5 @@
|
|||
//
|
||||
// Created by max on 27.04.23.
|
||||
//
|
||||
|
||||
#include "input_handler.h"
|
14
src/game/input_handler.h
Normal file
14
src/game/input_handler.h
Normal 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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
64
src/main.cpp
64
src/main.cpp
|
@ -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;
|
||||
}
|
||||
|
||||
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.addGameObject(new CircleObject(50, sf::Color::Red));
|
||||
|
||||
game.run();
|
||||
}
|
||||
|
|
20
src/primitives/circle_object.cpp
Normal file
20
src/primitives/circle_object.cpp
Normal 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);
|
||||
}
|
||||
|
||||
|
24
src/primitives/circle_object.h
Normal file
24
src/primitives/circle_object.h
Normal 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
3120
src/util/easylogging++.cc
Normal file
File diff suppressed because it is too large
Load diff
4576
src/util/easylogging++.h
Normal file
4576
src/util/easylogging++.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
}
|
|
@ -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
|
Loading…
Reference in a new issue