Merge branch 'dev'
3
.gitmodules
vendored
@ -14,6 +14,9 @@
|
|||||||
path = extern/SDL_ttf
|
path = extern/SDL_ttf
|
||||||
url = https://github.com/libsdl-org/SDL_ttf.git
|
url = https://github.com/libsdl-org/SDL_ttf.git
|
||||||
branch = release-2.22.x
|
branch = release-2.22.x
|
||||||
|
[submodule "extern/tmxlite"]
|
||||||
|
path = extern/tmxlite
|
||||||
|
url = https://github.com/fallahn/tmxlite.git
|
||||||
[submodule "docs/doxygen-awesome-css"]
|
[submodule "docs/doxygen-awesome-css"]
|
||||||
path = docs/doxygen-awesome-css
|
path = docs/doxygen-awesome-css
|
||||||
url = https://github.com/jothepro/doxygen-awesome-css.git
|
url = https://github.com/jothepro/doxygen-awesome-css.git
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
cmake_minimum_required(VERSION 3.15)
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
|
||||||
project(SDL_Minigame)
|
project(engine)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
set(PROJECT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
set(ENGINE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
set(PROJECT_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
|
set(ENGINE_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
|
||||||
set(PROJECT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
set(ENGINE_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
set(BUILD_SHARED_LIBS FALSE)
|
set(BUILD_SHARED_LIBS FALSE)
|
||||||
@ -15,22 +15,28 @@ set(BUILD_SHARED_LIBS FALSE)
|
|||||||
set(SDL2MIXER_VENDORED ON)
|
set(SDL2MIXER_VENDORED ON)
|
||||||
set(SDL2TTF_VENDORED ON)
|
set(SDL2TTF_VENDORED ON)
|
||||||
|
|
||||||
|
set(SDL2_SOURCE_DIR “${ENGINE_SOURCE_DIR}/extern/SDL”)
|
||||||
|
|
||||||
|
set(TMXLITE_STATIC_LIB TRUE)
|
||||||
|
|
||||||
add_subdirectory(extern/SDL EXCLUDE_FROM_ALL)
|
add_subdirectory(extern/SDL EXCLUDE_FROM_ALL)
|
||||||
add_subdirectory(extern/SDL_image EXCLUDE_FROM_ALL)
|
add_subdirectory(extern/SDL_image EXCLUDE_FROM_ALL)
|
||||||
add_subdirectory(extern/SDL_mixer EXCLUDE_FROM_ALL)
|
add_subdirectory(extern/SDL_mixer EXCLUDE_FROM_ALL)
|
||||||
add_subdirectory(extern/SDL_ttf EXCLUDE_FROM_ALL)
|
add_subdirectory(extern/SDL_ttf EXCLUDE_FROM_ALL)
|
||||||
|
add_subdirectory(extern/tmxlite/tmxlite EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
file(GLOB_RECURSE SOURCES ${PROJECT_SOURCE_DIR}/src/*.cpp)
|
file(GLOB_RECURSE SOURCES ${ENGINE_SOURCE_DIR}/src/*.cpp)
|
||||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
add_library(${PROJECT_NAME} ${SOURCES})
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_INCLUDE_DIR})
|
target_include_directories(${PROJECT_NAME} PUBLIC ${ENGINE_INCLUDE_DIR})
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
target_link_libraries(${PROJECT_NAME} PUBLIC # should be private when all SDL functionality has a wrapper
|
||||||
SDL2::SDL2main
|
SDL2::SDL2main
|
||||||
SDL2::SDL2-static
|
SDL2::SDL2-static
|
||||||
SDL2_image::SDL2_image-static
|
SDL2_image::SDL2_image-static
|
||||||
SDL2_mixer::SDL2_mixer-static
|
SDL2_mixer::SDL2_mixer-static
|
||||||
SDL2_ttf::SDL2_ttf-static
|
SDL2_ttf::SDL2_ttf-static
|
||||||
|
tmxlite
|
||||||
)
|
)
|
||||||
|
|
||||||
if(CMAKE_BUILD_TYPE MATCHES "Debug")
|
if(CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||||
@ -38,5 +44,11 @@ if(CMAKE_BUILD_TYPE MATCHES "Debug")
|
|||||||
#target_link_libraries(${PROJECT_NAME} PRIVATE "-fsanitize=address")
|
#target_link_libraries(${PROJECT_NAME} PRIVATE "-fsanitize=address")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# link/copy compile commands to root dir
|
||||||
file(COPY ${PROJECT_SOURCE_DIR}/assets DESTINATION ${PROJECT_BINARY_DIR})
|
if(EXISTS ${PROJECT_BINARY_DIR}/compile_commands.json)
|
||||||
|
file(CREATE_LINK
|
||||||
|
${PROJECT_BINARY_DIR}/compile_commands.json
|
||||||
|
${PROJECT_SOURCE_DIR}/compile_commands.json
|
||||||
|
COPY_ON_ERROR SYMBOLIC
|
||||||
|
)
|
||||||
|
endif()
|
||||||
@ -1,106 +0,0 @@
|
|||||||
{ "frames": [
|
|
||||||
{
|
|
||||||
"filename": "MapNew.aseprite",
|
|
||||||
"frame": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"sourceSize": { "w": 32, "h": 32 },
|
|
||||||
"duration": 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "MapNew.aseprite",
|
|
||||||
"frame": { "x": 32, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"sourceSize": { "w": 32, "h": 32 },
|
|
||||||
"duration": 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "MapNew.aseprite",
|
|
||||||
"frame": { "x": 64, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"sourceSize": { "w": 32, "h": 32 },
|
|
||||||
"duration": 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "MapNew.aseprite",
|
|
||||||
"frame": { "x": 96, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"sourceSize": { "w": 32, "h": 32 },
|
|
||||||
"duration": 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "MapNew.aseprite",
|
|
||||||
"frame": { "x": 128, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"sourceSize": { "w": 32, "h": 32 },
|
|
||||||
"duration": 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "MapNew.aseprite",
|
|
||||||
"frame": { "x": 160, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"sourceSize": { "w": 32, "h": 32 },
|
|
||||||
"duration": 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "MapNew.aseprite",
|
|
||||||
"frame": { "x": 192, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"sourceSize": { "w": 32, "h": 32 },
|
|
||||||
"duration": 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "MapNew.aseprite",
|
|
||||||
"frame": { "x": 224, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"sourceSize": { "w": 32, "h": 32 },
|
|
||||||
"duration": 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "MapNew.aseprite",
|
|
||||||
"frame": { "x": 256, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"sourceSize": { "w": 32, "h": 32 },
|
|
||||||
"duration": 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "MapNew.aseprite",
|
|
||||||
"frame": { "x": 288, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"sourceSize": { "w": 32, "h": 32 },
|
|
||||||
"duration": 100
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"meta": {
|
|
||||||
"app": "https://www.aseprite.org/",
|
|
||||||
"version": "1.3.2-x64",
|
|
||||||
"format": "RGBA8888",
|
|
||||||
"size": { "w": 320, "h": 32 },
|
|
||||||
"scale": "1",
|
|
||||||
"frameTags": [
|
|
||||||
],
|
|
||||||
"layers": [
|
|
||||||
],
|
|
||||||
"slices": [
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 7.3 KiB |
@ -1,20 +0,0 @@
|
|||||||
3,3,3,3,3,3,3,3,3,3,7,1,1,1,9,3,3,3,3,3,3,3,3,3,3
|
|
||||||
3,3,3,3,3,3,3,3,3,3,7,1,1,1,9,3,3,3,3,3,3,3,2,3,3
|
|
||||||
3,3,3,3,3,3,3,3,3,3,7,1,1,1,9,3,3,3,3,3,3,2,2,2,3
|
|
||||||
3,3,3,2,3,3,3,3,2,3,7,1,1,1,9,3,3,3,3,3,3,3,2,2,3
|
|
||||||
3,3,2,2,3,3,3,3,3,3,7,1,1,1,9,3,3,3,3,3,3,3,3,3,3
|
|
||||||
3,3,2,2,2,3,3,3,3,3,7,1,1,1,9,3,3,2,3,3,3,3,3,3,3
|
|
||||||
3,3,2,2,2,3,3,3,3,3,7,1,1,1,9,3,3,3,3,3,3,3,3,3,3
|
|
||||||
3,3,3,2,2,3,3,3,3,3,7,1,1,1,9,3,3,3,3,3,3,3,3,3,3
|
|
||||||
3,3,3,3,2,3,3,3,3,3,7,1,1,1,9,3,3,3,3,3,3,3,3,3,3
|
|
||||||
3,3,3,3,3,3,3,3,3,3,7,1,1,1,9,3,3,3,3,3,3,3,3,3,3
|
|
||||||
3,3,3,3,3,3,3,3,3,3,7,1,1,1,9,3,3,3,3,3,3,3,3,3,3
|
|
||||||
3,3,3,3,3,3,3,3,3,3,7,1,1,1,9,3,3,3,3,3,2,3,3,3,3
|
|
||||||
3,3,3,2,2,3,3,3,3,3,7,1,1,1,9,3,3,3,3,2,2,3,3,3,3
|
|
||||||
3,3,3,3,3,3,3,3,3,3,7,1,1,1,9,3,3,3,3,2,2,2,3,3,3
|
|
||||||
3,3,3,3,3,3,3,3,3,3,7,1,1,1,9,3,3,3,3,2,2,3,3,3,3
|
|
||||||
3,3,3,3,3,3,3,2,3,3,7,1,1,1,9,3,2,3,3,2,3,3,3,3,3
|
|
||||||
3,3,3,3,3,3,3,3,3,3,7,1,1,1,9,3,2,3,3,3,3,3,3,3,3
|
|
||||||
2,2,3,3,3,3,3,3,3,3,7,1,1,1,9,3,3,3,3,3,3,3,3,3,3
|
|
||||||
3,2,2,3,3,3,3,3,3,3,7,1,1,1,9,3,3,3,3,3,3,3,3,3,3
|
|
||||||
3,3,3,3,3,3,3,3,3,3,7,1,1,1,9,3,3,3,3,3,3,3,3,3,3
|
|
||||||
|
Before Width: | Height: | Size: 571 B |
BIN
assets/cat.png
|
Before Width: | Height: | Size: 407 B |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 751 B |
|
Before Width: | Height: | Size: 913 B |
|
Before Width: | Height: | Size: 836 B |
|
Before Width: | Height: | Size: 847 B |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
BIN
assets/cow.png
|
Before Width: | Height: | Size: 5.3 KiB |
BIN
assets/dirt.png
|
Before Width: | Height: | Size: 877 B |
BIN
assets/egg.png
|
Before Width: | Height: | Size: 271 B |
BIN
assets/grass.png
|
Before Width: | Height: | Size: 943 B |
|
Before Width: | Height: | Size: 1011 B |
|
Before Width: | Height: | Size: 1.1 KiB |
BIN
assets/heart.png
|
Before Width: | Height: | Size: 279 B |
|
Before Width: | Height: | Size: 550 B |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 643 B |
|
Before Width: | Height: | Size: 35 KiB |
BIN
assets/stone.png
|
Before Width: | Height: | Size: 279 B |
|
Before Width: | Height: | Size: 33 KiB |
BIN
assets/water.png
|
Before Width: | Height: | Size: 914 B |
|
Before Width: | Height: | Size: 1.2 KiB |
1
extern/tmxlite
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit fcef1a28ade8406e290d5fd168a8950e6996844f
|
||||||
@ -16,11 +16,5 @@ struct Animation
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AnimationType //TODO enum class
|
|
||||||
{
|
|
||||||
IDLE = 0,
|
|
||||||
WALK = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
#include <SDL_mixer.h>
|
#include <SDL_mixer.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
|
|
||||||
@ -23,8 +24,8 @@ public:
|
|||||||
AssetManager(Manager* manager);
|
AssetManager(Manager* manager);
|
||||||
~AssetManager();
|
~AssetManager();
|
||||||
|
|
||||||
void createProjectile(Vector2D pos, Vector2D velocity, int scale, int range, int speed, const char* texturePath, Entity::TeamLabel teamLabel);
|
void createProjectile(Vector2D pos, Vector2D velocity, int scale, int range, int speed, const char* texturePath, Entity* owner);
|
||||||
void createPowerup(Vector2D pos, PowerupType type);
|
void createPowerup(Vector2D pos, std::function<void (Entity*)> pickupFunc, std::string texturePath);
|
||||||
|
|
||||||
Vector2D calculateSpawnPosition();
|
Vector2D calculateSpawnPosition();
|
||||||
PowerupType calculateType();
|
PowerupType calculateType();
|
||||||
@ -35,12 +36,16 @@ public:
|
|||||||
// sound management
|
// sound management
|
||||||
void addSoundEffect(std::string id, const char* path);
|
void addSoundEffect(std::string id, const char* path);
|
||||||
|
|
||||||
|
void addMusic(std::string id, const char* path);
|
||||||
|
|
||||||
SDL_Texture* getTexture(std::string id);
|
SDL_Texture* getTexture(std::string id);
|
||||||
Mix_Chunk* getSound(std::string id);
|
Mix_Chunk* getSound(std::string id);
|
||||||
|
Mix_Music* getMusic(std::string id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Manager* man;
|
Manager* man;
|
||||||
std::map<std::string, SDL_Texture*> textures;
|
std::map<std::string, SDL_Texture*> textures;
|
||||||
std::map<std::string, Mix_Chunk*> soundEffects;
|
std::map<std::string, Mix_Chunk*> soundEffects;
|
||||||
|
std::map<std::string, Mix_Music*> music;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -50,8 +50,7 @@ public:
|
|||||||
// temporary function, remove once game.cpp cleaned up
|
// temporary function, remove once game.cpp cleaned up
|
||||||
std::vector<ColliderComponent*> getColliders(
|
std::vector<ColliderComponent*> getColliders(
|
||||||
std::initializer_list<Entity::GroupLabel> const& groupLabels,
|
std::initializer_list<Entity::GroupLabel> const& groupLabels,
|
||||||
std::initializer_list<Entity::TeamLabel> const& teamLabels = {},
|
std::initializer_list<Entity*> const& excludedEntities = {});
|
||||||
bool negateTeam = false);
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
@ -72,8 +71,7 @@ public:
|
|||||||
Entity* entity,
|
Entity* entity,
|
||||||
Vector2D posMod = {},
|
Vector2D posMod = {},
|
||||||
std::initializer_list<Entity::GroupLabel> const& groupLabels = {},
|
std::initializer_list<Entity::GroupLabel> const& groupLabels = {},
|
||||||
std::initializer_list<Entity::TeamLabel> const& teamLabels = {},
|
std::initializer_list<Entity*> const& excludedEntities = {});
|
||||||
bool negateTeam = false);
|
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
};
|
};
|
||||||
@ -9,7 +9,6 @@ public:
|
|||||||
|
|
||||||
virtual void init() {}
|
virtual void init() {}
|
||||||
virtual void update() {}
|
virtual void update() {}
|
||||||
virtual void draw() {}
|
|
||||||
|
|
||||||
virtual ~Component() = default;
|
virtual ~Component() = default;
|
||||||
};
|
};
|
||||||
@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "ECS.h"
|
|
||||||
#include "Component.h"
|
|
||||||
#include "Manager.h"
|
|
||||||
#include "Entity.h"
|
|
||||||
#include "TransformComponent.h"
|
|
||||||
#include "SpriteComponent.h"
|
|
||||||
#include "KeyboardController.h"
|
|
||||||
#include "ColliderComponent.h"
|
|
||||||
#include "TileComponent.h"
|
|
||||||
#include "ProjectileComponent.h"
|
|
||||||
#include "HealthComponent.h"
|
|
||||||
@ -3,7 +3,6 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
using Group = std::size_t;
|
using Group = std::size_t;
|
||||||
using Team = std::size_t;
|
|
||||||
|
|
||||||
constexpr int CHARACTER_COUNT = 4;
|
constexpr int CHARACTER_COUNT = 4;
|
||||||
|
|
||||||
@ -24,7 +23,8 @@ constexpr int MAP_SIZE_Y = 20;
|
|||||||
|
|
||||||
constexpr int SPAWN_ATTEMPTS = 20;
|
constexpr int SPAWN_ATTEMPTS = 20;
|
||||||
|
|
||||||
constexpr int BUFF_DURATION = 240;
|
constexpr int PLAY_LOOPED = -1;
|
||||||
|
constexpr int PLAY_ONCE = 0;
|
||||||
|
|
||||||
constexpr int BUFF_VALUE = 1;
|
constexpr int MAX_VOLUME = 128;
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,12 @@
|
|||||||
#include "ECS.h"
|
#include "ECS.h"
|
||||||
#include "Constants.h"
|
#include "Constants.h"
|
||||||
|
|
||||||
|
// TODO: remove here if possible
|
||||||
|
// temporary fix: addComponent function template doesnt know TransformComponent -> error undefined type
|
||||||
|
#include "InputComponent.h"
|
||||||
|
#include "TransformComponent.h"
|
||||||
|
#include "SpriteComponent.h"
|
||||||
|
|
||||||
class Manager;
|
class Manager;
|
||||||
class Component;
|
class Component;
|
||||||
|
|
||||||
@ -47,16 +53,6 @@ public:
|
|||||||
POWERUPS //!< \todo Document
|
POWERUPS //!< \todo Document
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Allows grouping entities by team association for hits, win conditions, etc.
|
|
||||||
*/
|
|
||||||
enum class TeamLabel
|
|
||||||
{
|
|
||||||
NONE, //!< No team, should be skipped in any checks
|
|
||||||
BLUE, //!< Team blue
|
|
||||||
RED //!< Team red
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \todo Document
|
* \todo Document
|
||||||
*/
|
*/
|
||||||
@ -64,9 +60,6 @@ public:
|
|||||||
manager(mManager) { };
|
manager(mManager) { };
|
||||||
|
|
||||||
void update() const; //!< Call each frame to update all components
|
void update() const; //!< Call each frame to update all components
|
||||||
//! Call after update to render components.
|
|
||||||
//! \sa SpriteComponent::draw()
|
|
||||||
void draw() const;
|
|
||||||
|
|
||||||
bool isActive() const { return this->active; } //!< \sa destroy()
|
bool isActive() const { return this->active; } //!< \sa destroy()
|
||||||
//! Mark for destruction for Manager::refresh() and disables collision
|
//! Mark for destruction for Manager::refresh() and disables collision
|
||||||
@ -85,9 +78,6 @@ public:
|
|||||||
//! \sa GroupLabel
|
//! \sa GroupLabel
|
||||||
std::bitset<MAX_GROUPS> getGroupBitSet();
|
std::bitset<MAX_GROUPS> getGroupBitSet();
|
||||||
|
|
||||||
void setTeam(TeamLabel teamLabel); //!< \sa TeamLabel
|
|
||||||
TeamLabel getTeam(); //!< \sa TeamLabel
|
|
||||||
|
|
||||||
//! \sa Manager
|
//! \sa Manager
|
||||||
Manager& getManager() { return manager; };
|
Manager& getManager() { return manager; };
|
||||||
|
|
||||||
@ -126,5 +116,4 @@ private:
|
|||||||
ComponentArray componentArray = {};
|
ComponentArray componentArray = {};
|
||||||
ComponentBitSet componentBitSet;
|
ComponentBitSet componentBitSet;
|
||||||
GroupBitSet groupBitSet;
|
GroupBitSet groupBitSet;
|
||||||
TeamLabel teamLabel;
|
|
||||||
};
|
};
|
||||||
@ -1,49 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL.h>
|
class GameInternal;
|
||||||
#include <SDL_image.h>
|
|
||||||
#include <SDL_mixer.h>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "Vector2D.h"
|
// TODO: add managers here
|
||||||
#include "Entity.h"
|
class Game {
|
||||||
|
|
||||||
class AssetManager;
|
|
||||||
class CollisionHandler;
|
|
||||||
class TextureManager;
|
|
||||||
class SoundManager;
|
|
||||||
|
|
||||||
class Game
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Game();
|
virtual ~Game() {}
|
||||||
~Game();
|
|
||||||
|
|
||||||
void init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen);
|
virtual void init() = 0;
|
||||||
void selectCharacters(const char* &playerSprite, const char* &enemySprite);
|
virtual void update() = 0;
|
||||||
|
|
||||||
void handleEvents();
|
GameInternal* gameInternal; //!< \deprecated
|
||||||
void update();
|
|
||||||
void render();
|
|
||||||
void clean();
|
|
||||||
bool running() const;
|
|
||||||
|
|
||||||
static void addTile(unsigned long id, int x, int y);
|
|
||||||
static SDL_Renderer* renderer;
|
|
||||||
static SDL_Event event;
|
|
||||||
static CollisionHandler* collisionHandler;
|
|
||||||
static AssetManager* assets;
|
|
||||||
static TextureManager* textureManager;
|
|
||||||
static SoundManager* soundManager;
|
|
||||||
|
|
||||||
void refreshPlayers();
|
|
||||||
Entity::TeamLabel getWinner() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void setWinner(Entity::TeamLabel winningTeam);
|
|
||||||
|
|
||||||
int counter = 0;
|
|
||||||
bool isRunning = false;
|
|
||||||
SDL_Window* window;
|
|
||||||
Entity::TeamLabel winner;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// game factory include to simplify imports in implementation
|
||||||
|
#include "GameFactory.h"
|
||||||
39
include/GameFactory.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "Game.h"
|
||||||
|
|
||||||
|
class GameInternal;
|
||||||
|
|
||||||
|
class GameFactory {
|
||||||
|
public:
|
||||||
|
using CreateFunc = std::function<Game*()>;
|
||||||
|
|
||||||
|
static GameFactory& instance() {
|
||||||
|
static GameFactory factory;
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerClass(CreateFunc createFunc) {
|
||||||
|
this->creatorFunc = createFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Game* create(GameInternal* gameInternal) {
|
||||||
|
if (this->creatorFunc == nullptr) {
|
||||||
|
throw std::runtime_error("No game implementation registered!");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
Game* game = (this->creatorFunc)();
|
||||||
|
game->gameInternal = gameInternal;
|
||||||
|
return game;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
CreateFunc creatorFunc = nullptr;
|
||||||
|
};
|
||||||
66
include/GameInternal.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <SDL_image.h>
|
||||||
|
#include <SDL_mixer.h>
|
||||||
|
#include <functional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Manager.h"
|
||||||
|
#include "Vector2D.h"
|
||||||
|
#include "Entity.h"
|
||||||
|
#include "RenderManager.h"
|
||||||
|
|
||||||
|
typedef std::function<void()> gamefunction;
|
||||||
|
|
||||||
|
class AssetManager;
|
||||||
|
class CollisionHandler;
|
||||||
|
class TextureManager;
|
||||||
|
class SoundManager;
|
||||||
|
class Map;
|
||||||
|
class Game;
|
||||||
|
|
||||||
|
class GameInternal
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GameInternal();
|
||||||
|
~GameInternal();
|
||||||
|
|
||||||
|
void init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen);
|
||||||
|
|
||||||
|
void handleEvents();
|
||||||
|
void update();
|
||||||
|
void render();
|
||||||
|
void clean();
|
||||||
|
bool isRunning() const;
|
||||||
|
void setRunning(bool running); // TODO: should be private/not accesible for game dev
|
||||||
|
void stopGame();
|
||||||
|
|
||||||
|
/* static */ SDL_Renderer* renderer = nullptr;
|
||||||
|
/* static */ SDL_Event event;
|
||||||
|
/* static */ CollisionHandler* collisionHandler;
|
||||||
|
/* static */ AssetManager* assets;
|
||||||
|
/* static */ TextureManager* textureManager;
|
||||||
|
/* static */ SoundManager* soundManager;
|
||||||
|
|
||||||
|
Manager manager;
|
||||||
|
RenderManager renderManager;
|
||||||
|
Map* map; // game specific, might not be needed for all types of games
|
||||||
|
|
||||||
|
std::vector<Entity*>& tiles;
|
||||||
|
std::vector<Entity*>& players;
|
||||||
|
std::vector<Entity*>& projectiles;
|
||||||
|
std::vector<Entity*>& hearts;
|
||||||
|
std::vector<Entity*>& powerups;
|
||||||
|
// end moved globals
|
||||||
|
|
||||||
|
void refreshPlayers();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Game* gameInstance;
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
bool running = true;
|
||||||
|
SDL_Window* window;
|
||||||
|
};
|
||||||
@ -1,21 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <SDL.h>
|
|
||||||
|
|
||||||
class GameObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GameObject(const char* texturesheet, int x, int y);
|
|
||||||
~GameObject() = default;
|
|
||||||
|
|
||||||
void update();
|
|
||||||
void render();
|
|
||||||
|
|
||||||
private:
|
|
||||||
int xPos;
|
|
||||||
int yPos;
|
|
||||||
|
|
||||||
SDL_Texture* objTexture;
|
|
||||||
SDL_Rect srcRect;
|
|
||||||
SDL_Rect destRect;
|
|
||||||
};
|
|
||||||
|
|
||||||
24
include/GameRegistryHelper.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "GameFactory.h"
|
||||||
|
|
||||||
|
namespace vego {
|
||||||
|
template<typename T>
|
||||||
|
class GameRegistryHelper {
|
||||||
|
public:
|
||||||
|
[[deprecated("GameRegistryHelper() does not take a className anymore")]]
|
||||||
|
GameRegistryHelper(const std::string& className) {
|
||||||
|
static_assert(std::is_base_of<Game, T>::value, "Your class must inherit from Game");
|
||||||
|
GameFactory::instance().registerClass(
|
||||||
|
[]() -> Game* { return new T; }
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
GameRegistryHelper() {
|
||||||
|
static_assert(std::is_base_of<Game, T>::value, "Your class must inherit from Game");
|
||||||
|
GameFactory::instance().registerClass(
|
||||||
|
[]() -> Game* { return new T; }
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -1,5 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "Direction.h"
|
#include "Direction.h"
|
||||||
#include "Component.h"
|
#include "Component.h"
|
||||||
|
|
||||||
@ -9,7 +12,7 @@ class HealthComponent : public Component
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HealthComponent(int health, Direction side) : health(health), side(side) {}
|
HealthComponent(int health) : health(health) {}
|
||||||
~HealthComponent() {}
|
~HealthComponent() {}
|
||||||
|
|
||||||
void modifyHealth(int health = -1);
|
void modifyHealth(int health = -1);
|
||||||
@ -25,5 +28,4 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
int health;
|
int health;
|
||||||
Direction side;
|
|
||||||
};
|
};
|
||||||
106
include/InputComponent.h
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "Component.h"
|
||||||
|
|
||||||
|
enum class Key
|
||||||
|
{
|
||||||
|
UP,
|
||||||
|
DOWN,
|
||||||
|
LEFT,
|
||||||
|
RIGHT,
|
||||||
|
SPACE,
|
||||||
|
ENTER,
|
||||||
|
ESCAPE,
|
||||||
|
TAB,
|
||||||
|
BACKSPACE,
|
||||||
|
DELETE,
|
||||||
|
HOME,
|
||||||
|
END,
|
||||||
|
PAGE_UP,
|
||||||
|
PAGE_DOWN,
|
||||||
|
INSERT,
|
||||||
|
CAPS_LOCK,
|
||||||
|
LEFT_SHIFT,
|
||||||
|
RIGHT_SHIFT,
|
||||||
|
LEFT_CTRL,
|
||||||
|
RIGHT_CTRL,
|
||||||
|
LEFT_ALT,
|
||||||
|
RIGHT_ALT,
|
||||||
|
F1,
|
||||||
|
F2,
|
||||||
|
F3,
|
||||||
|
F4,
|
||||||
|
F5,
|
||||||
|
F6,
|
||||||
|
F7,
|
||||||
|
F8,
|
||||||
|
F9,
|
||||||
|
F10,
|
||||||
|
F11,
|
||||||
|
F12,
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
C,
|
||||||
|
D,
|
||||||
|
E,
|
||||||
|
F,
|
||||||
|
G,
|
||||||
|
H,
|
||||||
|
I,
|
||||||
|
J,
|
||||||
|
K,
|
||||||
|
L,
|
||||||
|
M,
|
||||||
|
N,
|
||||||
|
O,
|
||||||
|
P,
|
||||||
|
Q,
|
||||||
|
R,
|
||||||
|
S,
|
||||||
|
T,
|
||||||
|
U,
|
||||||
|
V,
|
||||||
|
W,
|
||||||
|
X,
|
||||||
|
Y,
|
||||||
|
Z,
|
||||||
|
NUM_0,
|
||||||
|
NUM_1,
|
||||||
|
NUM_2,
|
||||||
|
NUM_3,
|
||||||
|
NUM_4,
|
||||||
|
NUM_5,
|
||||||
|
NUM_6,
|
||||||
|
NUM_7,
|
||||||
|
NUM_8,
|
||||||
|
NUM_9,
|
||||||
|
LEFT_BRACKET,
|
||||||
|
RIGHT_BRACKET,
|
||||||
|
SEMICOLON,
|
||||||
|
APOSTROPHE,
|
||||||
|
COMMA,
|
||||||
|
PERIOD,
|
||||||
|
SLASH,
|
||||||
|
BACKSLASH,
|
||||||
|
GRAVE
|
||||||
|
};
|
||||||
|
|
||||||
|
class InputComponent : public Component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InputComponent();
|
||||||
|
~InputComponent();
|
||||||
|
|
||||||
|
void init() override;
|
||||||
|
void update() override;
|
||||||
|
|
||||||
|
bool isKeyDown(Key key);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Uint8* m_keyStates;
|
||||||
|
SDL_Scancode mapKeyToSDL(Key key);
|
||||||
|
std::map<Key, SDL_Scancode> m_keyMappings;
|
||||||
|
void InitKeyMappings();
|
||||||
|
};
|
||||||
@ -1,44 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <SDL.h>
|
|
||||||
|
|
||||||
#include "Component.h"
|
|
||||||
#include "Vector2D.h"
|
|
||||||
#include "Constants.h"
|
|
||||||
#include "SoundManager.h"
|
|
||||||
|
|
||||||
class TransformComponent;
|
|
||||||
class SpriteComponent;
|
|
||||||
|
|
||||||
class KeyboardController : public Component
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TransformComponent* transform;
|
|
||||||
const uint8_t* keystates = SDL_GetKeyboardState(NULL);
|
|
||||||
SDL_Scancode up;
|
|
||||||
SDL_Scancode down;
|
|
||||||
SDL_Scancode left;
|
|
||||||
SDL_Scancode right;
|
|
||||||
SDL_Scancode fire;
|
|
||||||
|
|
||||||
SpriteComponent* sprite;
|
|
||||||
|
|
||||||
//for attack cooldown in between shots
|
|
||||||
uint32_t lastFireTime = 0;
|
|
||||||
uint32_t fireCooldown = 1000; //in ms can be adjusted to change possible attack-speed
|
|
||||||
|
|
||||||
KeyboardController() = default;
|
|
||||||
KeyboardController(SDL_Scancode up, SDL_Scancode down, SDL_Scancode left, SDL_Scancode right, SDL_Scancode fire, Vector2D fireVelocity);
|
|
||||||
~KeyboardController() = default;
|
|
||||||
|
|
||||||
void init() override;
|
|
||||||
void update() override;
|
|
||||||
|
|
||||||
void modifyAtkSpeed(int8_t modifier);
|
|
||||||
|
|
||||||
private:
|
|
||||||
//for creation of projectiles
|
|
||||||
TransformComponent* player; //for starting position of projectile
|
|
||||||
Vector2D fireVelocity; //decide source of projectile and flying direction
|
|
||||||
// SoundManager* soundEffect = Game::assets->getSound;
|
|
||||||
//SoundManager* soundEffect = new SoundManager();
|
|
||||||
};
|
|
||||||
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -7,6 +9,7 @@
|
|||||||
#include "Constants.h"
|
#include "Constants.h"
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
|
|
||||||
|
class GameInternal;
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
* \brief Is responsible for managing all entities
|
* \brief Is responsible for managing all entities
|
||||||
@ -19,8 +22,9 @@
|
|||||||
class Manager
|
class Manager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Manager(GameInternal* game) : game(game) {};
|
||||||
|
|
||||||
void update(); //!< \sa Entity::update()
|
void update(); //!< \sa Entity::update()
|
||||||
void draw(); //!< \sa Entity::draw()
|
|
||||||
//! Disables all functionality of entities marked for destruction
|
//! Disables all functionality of entities marked for destruction
|
||||||
//! \sa Entity::destroy()
|
//! \sa Entity::destroy()
|
||||||
void refresh();
|
void refresh();
|
||||||
@ -28,15 +32,14 @@ public:
|
|||||||
void addToGroup(Entity* mEntity, Group mGroup); //!< \todo `friend` to Entity
|
void addToGroup(Entity* mEntity, Group mGroup); //!< \todo `friend` to Entity
|
||||||
std::vector<Entity*>& getGroup(Group mGroup); //!< \returns std::vector containing all entities in group Entity::GroupLabel
|
std::vector<Entity*>& getGroup(Group mGroup); //!< \returns std::vector containing all entities in group Entity::GroupLabel
|
||||||
|
|
||||||
void addToTeam(Entity* mEntity, Team mTeam); //!< \todo `friend` to Entity
|
|
||||||
std::vector<Entity*>& getTeam(Team mTeam); //!< \returns std::vector containing all entities in team Entity::TeamLabel
|
|
||||||
|
|
||||||
std::vector<Entity*> getAll(); //!< \returns std::vector containing all entities
|
std::vector<Entity*> getAll(); //!< \returns std::vector containing all entities
|
||||||
|
|
||||||
Entity& addEntity(); //!< Creates and returns a new, empty entity
|
Entity& addEntity(); //!< Creates and returns a new, empty entity
|
||||||
|
|
||||||
|
GameInternal* getGame() { return this->game; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
GameInternal* game;
|
||||||
std::vector<std::unique_ptr<Entity>> entities;
|
std::vector<std::unique_ptr<Entity>> entities;
|
||||||
std::array<std::vector<Entity*>, MAX_GROUPS> entitiesByGroup;
|
std::array<std::vector<Entity*>, MAX_GROUPS> entitiesByGroup;
|
||||||
std::array<std::vector<Entity*>, MAX_TEAMS> entitiesByTeam;
|
|
||||||
};
|
};
|
||||||
@ -1,13 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <tmxlite/Types.hpp>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class GameInternal;
|
||||||
class Map
|
class Map
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Map() = default;
|
Map() = default;
|
||||||
~Map() = default;
|
~Map() = default;
|
||||||
|
|
||||||
// code comment below is a test for doxygen - do not remove
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
* \brief
|
* \brief
|
||||||
@ -17,5 +20,17 @@ public:
|
|||||||
* \return Boolean for success
|
* \return Boolean for success
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static bool loadMap(const char* path, int sizeX, int sizeY);
|
[[deprecated("ID based text files are not supported anymore, use .txm maps instead")]]
|
||||||
|
static void loadMap(const char* path, int sizeX, int sizeY, GameInternal* game, const std::map<int, std::pair<std::string, bool>>* textureDict /* backreference */);
|
||||||
|
[[deprecated]]
|
||||||
|
static void addTile(unsigned long id, int x, int y, GameInternal* game, const std::map<int, std::pair<std::string, bool>>* textureDict);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Loads a .tmx map
|
||||||
|
* \param path Path to the `.tmx` map file
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void loadMapTmx(const char* path);
|
||||||
|
private:
|
||||||
|
static void addTile(float x, float y, const tmx::Vector2u& mapTileSize, int u, int v, int zIndex, const char* texturePath);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,28 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <SDL.h>
|
|
||||||
#include <SDL_ttf.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "Entity.h"
|
|
||||||
|
|
||||||
class Game;
|
|
||||||
|
|
||||||
class PopupWindow {
|
|
||||||
|
|
||||||
public:
|
|
||||||
PopupWindow(const char* title, const std::string& message);
|
|
||||||
~PopupWindow();
|
|
||||||
|
|
||||||
void handleWinnerEvents();
|
|
||||||
bool shouldContinue() const;
|
|
||||||
|
|
||||||
bool interacted;
|
|
||||||
|
|
||||||
void renderWinnerPopup(Entity::TeamLabel winner);
|
|
||||||
|
|
||||||
private:
|
|
||||||
SDL_Renderer* renderer;
|
|
||||||
SDL_Window* window;
|
|
||||||
SDL_Texture* texture;
|
|
||||||
bool continueGame;
|
|
||||||
};
|
|
||||||
@ -1,19 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include "Component.h"
|
#include "Component.h"
|
||||||
#include "AssetManager.h"
|
|
||||||
|
|
||||||
class PowerupComponent : public Component
|
class PowerupComponent : public Component
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PowerupComponent(PowerupType type);
|
PowerupComponent(std::function<void (Entity*)> func);
|
||||||
~PowerupComponent() {};
|
~PowerupComponent() {};
|
||||||
|
|
||||||
void update() override;
|
void update() override;
|
||||||
void heartEffect(Entity* player);
|
|
||||||
void movementSpeedEffect(Entity* player);
|
|
||||||
void atkSpeedEffect(Entity* player);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void (PowerupComponent::*pickupFunc)(Entity* player);
|
std::function<void (Entity*)> pickupFunc;
|
||||||
};
|
};
|
||||||
@ -11,7 +11,8 @@ class ProjectileComponent : public Component
|
|||||||
//can maybe be split in separate .cpp file
|
//can maybe be split in separate .cpp file
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ProjectileComponent(int range, int speed, Vector2D direction) : range(range), speed(speed), direction(direction) {}
|
ProjectileComponent(int range, int speed, Vector2D direction, Entity* owner)
|
||||||
|
: range(range), speed(speed), direction(direction), owner(owner) {}
|
||||||
~ProjectileComponent() {}
|
~ProjectileComponent() {}
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
@ -24,5 +25,7 @@ private:
|
|||||||
int speed = 0;
|
int speed = 0;
|
||||||
int distance = 0;
|
int distance = 0;
|
||||||
|
|
||||||
|
Entity* owner = nullptr;
|
||||||
|
|
||||||
Vector2D direction;
|
Vector2D direction;
|
||||||
};
|
};
|
||||||
29
include/RenderManager.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "RenderObject.h"
|
||||||
|
|
||||||
|
class RenderManager {
|
||||||
|
public:
|
||||||
|
RenderManager() {};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove an object from the list of objects to be rendered
|
||||||
|
* \param renderObject The object to be removed
|
||||||
|
* \sa RenderObject
|
||||||
|
*/
|
||||||
|
void remove(RenderObject* obj);
|
||||||
|
/*
|
||||||
|
* Add an object to be rendered
|
||||||
|
* \param renderObject The object to be rendered
|
||||||
|
* \sa RenderObject
|
||||||
|
*/
|
||||||
|
void add(RenderObject* obj);
|
||||||
|
|
||||||
|
void renderAll(); //!< Render all objects. If the list has been modified, sorts it based on z-index first
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<RenderObject*> renderObjects;
|
||||||
|
bool isSorted;
|
||||||
|
};
|
||||||
27
include/RenderObject.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class RenderManager;
|
||||||
|
|
||||||
|
class RenderObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void draw() = 0;
|
||||||
|
|
||||||
|
RenderObject(int zIndex, RenderManager& renderManager);
|
||||||
|
~RenderObject();
|
||||||
|
|
||||||
|
int getZIndex() { return this->zIndex; };
|
||||||
|
|
||||||
|
//! Comparitor to compare two ptr based on z-index
|
||||||
|
struct ZIndexComparator {
|
||||||
|
bool operator()(RenderObject const *lhs, RenderObject const *rhs ) const {
|
||||||
|
return lhs->zIndex < rhs->zIndex;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
int zIndex = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
RenderManager& renderManager;
|
||||||
|
};
|
||||||
@ -4,14 +4,17 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "ECS.h"
|
||||||
#include "TextureManager.h"
|
#include "TextureManager.h"
|
||||||
|
|
||||||
enum SoundTypes
|
class GameInternal;
|
||||||
{
|
|
||||||
STEPS,
|
|
||||||
THROW_EGG,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*
|
||||||
|
* \brief Handles music and sound.
|
||||||
|
* \details SoundManager handles loading in music and sound effects from files, playing music and sound effects and toggling the audio volume.
|
||||||
|
*
|
||||||
|
*/
|
||||||
class SoundManager
|
class SoundManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -20,13 +23,55 @@ class SoundManager
|
|||||||
for (auto& it : this->sound_cache) {
|
for (auto& it : this->sound_cache) {
|
||||||
Mix_FreeChunk(it.second);
|
Mix_FreeChunk(it.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto& it : this->music_cache) {
|
||||||
|
Mix_FreeMusic(it.second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundManager(SoundManager const&) = delete;
|
SoundManager(SoundManager const&) = delete;
|
||||||
void operator=(SoundManager const&) = delete;
|
void operator=(SoundManager const&) = delete;
|
||||||
|
|
||||||
|
std::map<const char*, Mix_Music*> music_cache;
|
||||||
std::map<const char*, Mix_Chunk*> sound_cache;
|
std::map<const char*, Mix_Chunk*> sound_cache;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Loads music from a file (mp3)
|
||||||
|
* \returns a pointer to Mix_Music
|
||||||
|
* \sa AssetManager::AddMusic(std::string id, const char* path)
|
||||||
|
*/
|
||||||
|
Mix_Music* loadMusic(const char* fileName);
|
||||||
|
/*!
|
||||||
|
* \brief Loads sound effects from a file (wav)
|
||||||
|
* \returns a pointer to Mix_Chunk
|
||||||
|
* \sa AssetManager::AddSound(std::string id, const char* path)
|
||||||
|
*/
|
||||||
Mix_Chunk* loadSound(const char* fileName);
|
Mix_Chunk* loadSound(const char* fileName);
|
||||||
static void playSound(SoundTypes sound);
|
|
||||||
|
/*!
|
||||||
|
* \brief Handles playing of sound effects
|
||||||
|
*
|
||||||
|
* Handles if sounds can overlap, how often they can loop, as well as the volume at which the specified sound effect should play
|
||||||
|
* and on which channel the soundeffect should play.
|
||||||
|
*/
|
||||||
|
static void playSound(GameInternal* game, std::string sound, bool canOverlap, int loops, int volume, int channel);
|
||||||
|
/*!
|
||||||
|
* \brief Handles playing of music
|
||||||
|
*
|
||||||
|
* Handles how often track can loop, as well as the volume at which the specified track should play and if it fades in.
|
||||||
|
*/
|
||||||
|
static void playMusic(GameInternal* game, std::string sound, int loops, int volume, int ms);
|
||||||
|
|
||||||
|
static void setSoundVolume(int volume, int channel); //!< Volume handling for sound effects (either all or on a specific channel)
|
||||||
|
static void setMusicVolume(int volume); //!< Volume handling for music track
|
||||||
|
|
||||||
|
static void pauseSound(int channel); //!< Handles pausing sound effects (either all or on a specific channel)
|
||||||
|
static void pauseMusic(); //!< Handles pausing music track
|
||||||
|
|
||||||
|
static void restartSound(int channel); //!< Handles resuming sound effects (either all or on a specific channel)
|
||||||
|
static void restartMusic(); //!< Handles resuming music track
|
||||||
|
|
||||||
|
static void fadeOutMusic(int ms); //!< Handles fading out a music track
|
||||||
|
|
||||||
|
private:
|
||||||
};
|
};
|
||||||
@ -3,34 +3,46 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <SDL_render.h>
|
#include <SDL_render.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "AnimationHandler.h"
|
#include "AnimationHandler.h"
|
||||||
#include "Component.h"
|
#include "Component.h"
|
||||||
#include "Direction.h"
|
#include "Direction.h"
|
||||||
|
#include "RenderObject.h"
|
||||||
|
|
||||||
class TransformComponent;
|
class TransformComponent;
|
||||||
|
|
||||||
class SpriteComponent : public Component
|
class SpriteComponent : public Component, public RenderObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int animationIndex = 0;
|
int animationIndex = 0;
|
||||||
|
|
||||||
std::map<AnimationType, std::unique_ptr<Animation>> animations;
|
std::map<std::string, std::unique_ptr<Animation>>* animations = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TransformComponent* transform;
|
TransformComponent* transform;
|
||||||
SDL_Texture* texture;
|
SDL_Texture* texture;
|
||||||
SDL_Rect srcRect, destRect;
|
SDL_Rect srcRect, destRect;
|
||||||
|
|
||||||
|
const char* texturePath;
|
||||||
|
|
||||||
bool animated = false;
|
bool animated = false;
|
||||||
uint8_t frames = 0;
|
uint8_t frames = 0;
|
||||||
uint8_t speed = 100;
|
uint8_t speed = 100;
|
||||||
bool flipped = false;
|
bool flipped = false;
|
||||||
|
|
||||||
|
int textureXOffset;
|
||||||
|
int textureYOffset;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SpriteComponent() = default;
|
SpriteComponent(const char* path, int zIndex);
|
||||||
SpriteComponent(const char* path);
|
SpriteComponent(const char* path, int xOffset, int yOffset, int zIndex);
|
||||||
SpriteComponent(const char* path, bool isAnimated);
|
SpriteComponent(
|
||||||
|
const char* path,
|
||||||
|
bool isAnimated,
|
||||||
|
std::map<std::string, std::unique_ptr<Animation>>* animationList,
|
||||||
|
std::string defaultAnimation,
|
||||||
|
int zIndex);
|
||||||
~SpriteComponent();
|
~SpriteComponent();
|
||||||
|
|
||||||
void setTexture(const char* path);
|
void setTexture(const char* path);
|
||||||
@ -38,6 +50,6 @@ public:
|
|||||||
void init() override;
|
void init() override;
|
||||||
void update() override;
|
void update() override;
|
||||||
void draw() override;
|
void draw() override;
|
||||||
void playAnimation(AnimationType type);
|
void playAnimation(std::string type);
|
||||||
void setDirection(Direction direction);
|
void setDirection(Direction direction);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -18,9 +18,10 @@ public:
|
|||||||
void init() override;
|
void init() override;
|
||||||
void update() override;
|
void update() override;
|
||||||
|
|
||||||
void modifyStatDur(Stats stat, int duration);
|
void modifyStatDur(Stats stat, int duration, int value);
|
||||||
|
|
||||||
void modifyStatValue(Stats stat, int modifier);
|
void modifyStatValue(Stats stat, int modifier);
|
||||||
|
void resetStatValue(Stats stat);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<int, MAX_STATS> buffs = { 0 };
|
std::array<int, MAX_STATS> buffs = { 0 };
|
||||||
|
|||||||
@ -1,24 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
#include "AssetManager.h"
|
|
||||||
|
|
||||||
class TextureDict
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
const std::map<int, std::string> tileDictionary = {
|
|
||||||
{1, "assets/water.png"},
|
|
||||||
{2, "assets/dirt.png"},
|
|
||||||
{3, "assets/grass.png"},
|
|
||||||
{7, "assets/grass_water_left.png"},
|
|
||||||
{9, "assets/grass_water_right.png"}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
std::map<PowerupType, std::string> powerupDictionary = {
|
|
||||||
{PowerupType::HEART, "assets/heart_powerup.png"},
|
|
||||||
{PowerupType::WALKINGSPEED, "assets/movement_speed_powerup.png"},
|
|
||||||
{PowerupType::SHOOTINGSPEED, "assets/atk_speed_powerup.png"}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "ECS.h"
|
||||||
#include <SDL_render.h>
|
#include <SDL_render.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -9,7 +10,7 @@
|
|||||||
class TextureManager
|
class TextureManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TextureManager() {}
|
TextureManager(Manager* manager) : manager(manager) {}
|
||||||
~TextureManager() {
|
~TextureManager() {
|
||||||
for (auto& it : this->texture_cache) {
|
for (auto& it : this->texture_cache) {
|
||||||
SDL_DestroyTexture(it.second);
|
SDL_DestroyTexture(it.second);
|
||||||
@ -20,5 +21,7 @@ class TextureManager
|
|||||||
|
|
||||||
SDL_Texture* loadTexture(const char* fileName);
|
SDL_Texture* loadTexture(const char* fileName);
|
||||||
static std::vector<SDL_Rect> splitSpriteSheet(SDL_Texture* spriteSheet, int width, int height, int spritesOnSheet);
|
static std::vector<SDL_Rect> splitSpriteSheet(SDL_Texture* spriteSheet, int width, int height, int spritesOnSheet);
|
||||||
static void draw(SDL_Texture* texture, SDL_Rect src, SDL_Rect dest, bool flipped = false);
|
static void draw(SDL_Renderer* renderer, SDL_Texture* texture, SDL_Rect src, SDL_Rect dest, bool flipped = false);
|
||||||
|
private:
|
||||||
|
Manager* manager;
|
||||||
};
|
};
|
||||||
@ -1,9 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "Component.h"
|
#include "Component.h"
|
||||||
#include "TextureDict.h"
|
|
||||||
|
|
||||||
class SpriteComponent;
|
class SpriteComponent;
|
||||||
class TransformComponent;
|
class TransformComponent;
|
||||||
@ -13,15 +14,20 @@ class TileComponent : public Component
|
|||||||
public:
|
public:
|
||||||
TransformComponent* transform;
|
TransformComponent* transform;
|
||||||
SpriteComponent* sprite;
|
SpriteComponent* sprite;
|
||||||
TextureDict textureDict;
|
|
||||||
|
|
||||||
SDL_Rect tileRect;
|
SDL_Rect tileRect;
|
||||||
int tileID;
|
int tileID;
|
||||||
const char* path;
|
const char* path;
|
||||||
|
|
||||||
TileComponent() = default;
|
TileComponent() = default;
|
||||||
TileComponent(int x, int y, int w, int h, int id);
|
TileComponent(int x, int y, int w, int h, int id, const std::map<int, std::pair<std::string, bool>>* textureDict);
|
||||||
~TileComponent() = default;
|
~TileComponent() = default;
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
|
|
||||||
|
bool hasCollision(){return this->collision;}
|
||||||
|
std::string getName(){return this->tileName;}
|
||||||
|
private:
|
||||||
|
bool collision;
|
||||||
|
std::string tileName;
|
||||||
};
|
};
|
||||||
@ -7,14 +7,15 @@
|
|||||||
class TransformComponent : public Component
|
class TransformComponent : public Component
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Vector2D position; // TODO: change to int to safe CPU time -> possibly subpixel coordinates
|
Vector2D position; // TODO: change to int to save CPU time -> possibly subpixel coordinates
|
||||||
Vector2D direction;
|
Vector2D direction;
|
||||||
|
|
||||||
int height = 32;
|
int height = 32;
|
||||||
int width = 32;
|
int width = 32;
|
||||||
int scale = 1;
|
int scale = 1;
|
||||||
|
|
||||||
int speed = 3;
|
int getSpeed() { return speed + speedMod; };
|
||||||
|
void resetSpeedMod() { speedMod = 0; };
|
||||||
|
|
||||||
TransformComponent();
|
TransformComponent();
|
||||||
explicit TransformComponent(int scale);
|
explicit TransformComponent(int scale);
|
||||||
@ -25,5 +26,10 @@ public:
|
|||||||
void init() override;
|
void init() override;
|
||||||
/*! TODO: document usage of collision handler */
|
/*! TODO: document usage of collision handler */
|
||||||
void update() override;
|
void update() override;
|
||||||
|
void setPositionAfterCollision(Vector2D& positionChange);
|
||||||
void modifySpeed(int8_t modifier);
|
void modifySpeed(int8_t modifier);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int speed = 3;
|
||||||
|
int speedMod = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
9
include/VEGO.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include "GameInternal.h"
|
||||||
|
|
||||||
|
namespace vego {
|
||||||
|
extern GameInternal* game;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline GameInternal& VEGO_Game() {
|
||||||
|
return *vego::game;
|
||||||
|
};
|
||||||
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
#include "TextureManager.h"
|
#include "TextureManager.h"
|
||||||
#include "SoundManager.h"
|
#include "SoundManager.h"
|
||||||
#include "Components.h"
|
#include "ProjectileComponent.h"
|
||||||
#include "Game.h"
|
#include "GameInternal.h"
|
||||||
|
|
||||||
#include "TransformComponent.h"
|
#include "TransformComponent.h"
|
||||||
|
|
||||||
@ -11,7 +11,6 @@
|
|||||||
#include "ColliderComponent.h"
|
#include "ColliderComponent.h"
|
||||||
#include "Constants.h"
|
#include "Constants.h"
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "Game.h"
|
|
||||||
#include "Vector2D.h"
|
#include "Vector2D.h"
|
||||||
#include "PowerupComponent.h"
|
#include "PowerupComponent.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -21,12 +20,17 @@ AssetManager::AssetManager(Manager* manager) : man(manager) {}
|
|||||||
AssetManager::~AssetManager() {}
|
AssetManager::~AssetManager() {}
|
||||||
|
|
||||||
void AssetManager::addTexture(std::string id, const char* path) {
|
void AssetManager::addTexture(std::string id, const char* path) {
|
||||||
textures.emplace(id, Game::textureManager->loadTexture(path));
|
textures.emplace(id, this->man->getGame()->textureManager->loadTexture(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetManager::addSoundEffect(std::string id, const char* path)
|
void AssetManager::addSoundEffect(std::string id, const char* path)
|
||||||
{
|
{
|
||||||
soundEffects.emplace(id, Game::soundManager->loadSound(path));
|
soundEffects.emplace(id, this->man->getGame()->soundManager->loadSound(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetManager::addMusic(std::string id, const char* path)
|
||||||
|
{
|
||||||
|
music.emplace(id, this->man->getGame()->soundManager->loadMusic(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Texture* AssetManager::getTexture(std::string id) {
|
SDL_Texture* AssetManager::getTexture(std::string id) {
|
||||||
@ -37,36 +41,35 @@ Mix_Chunk* AssetManager::getSound(std::string id) {
|
|||||||
return soundEffects.at(id);
|
return soundEffects.at(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetManager::createProjectile(Vector2D pos, Vector2D velocity, int scale, int range, int speed, const char* texturePath, Entity::TeamLabel teamLabel) {
|
Mix_Music* AssetManager::getMusic(std::string id)
|
||||||
|
{
|
||||||
|
return music.at(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetManager::createProjectile(Vector2D pos, Vector2D velocity, int scale, int range, int speed, const char* texturePath, Entity* owner) {
|
||||||
|
|
||||||
auto& projectile(man->addEntity());
|
auto& projectile(man->addEntity());
|
||||||
projectile.addComponent<TransformComponent>(pos.x, pos.y, 32, 32, scale); //32x32 is standard size for objects
|
projectile.addComponent<TransformComponent>(pos.x, pos.y, 32, 32, scale); //32x32 is standard size for objects
|
||||||
projectile.addComponent<SpriteComponent>(texturePath);
|
projectile.addComponent<SpriteComponent>(texturePath, 4);
|
||||||
projectile.addComponent<ProjectileComponent>(range, speed, velocity);
|
projectile.addComponent<ProjectileComponent>(range, speed, velocity, owner);
|
||||||
projectile.addComponent<ColliderComponent>("projectile", 0.6f);
|
projectile.addComponent<ColliderComponent>("projectile", 0.6f);
|
||||||
projectile.addGroup((size_t)Entity::GroupLabel::PROJECTILE);
|
projectile.addGroup((size_t)Entity::GroupLabel::PROJECTILE);
|
||||||
projectile.setTeam(teamLabel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetManager::createPowerup(Vector2D pos, PowerupType type) {
|
void AssetManager::createPowerup(Vector2D pos, std::function<void (Entity*)> pickupFunc, std::string texturePath) {
|
||||||
TextureDict textureDict;
|
|
||||||
|
|
||||||
auto& powerups(man->addEntity());
|
auto& powerups(man->addEntity());
|
||||||
powerups.addComponent<TransformComponent>(pos.x, pos.y, 32, 32, 1); //32x32 is standard size for objects
|
powerups.addComponent<TransformComponent>(pos.x, pos.y, 32, 32, 1); //32x32 is standard size for objects
|
||||||
auto it = textureDict.powerupDictionary.find(type);
|
|
||||||
if (it == textureDict.powerupDictionary.end()) {
|
|
||||||
std::cout << "it end" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
powerups.addComponent<SpriteComponent>(it->second.data());
|
powerups.addComponent<SpriteComponent>(texturePath.c_str(), 3);
|
||||||
}
|
}
|
||||||
catch (std::runtime_error e) {
|
catch (std::runtime_error e) {
|
||||||
std::cout << e.what() << std::endl;
|
std::cout << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
powerups.addComponent<ColliderComponent>("powerup", 0.6f);
|
powerups.addComponent<ColliderComponent>("powerup", 0.6f);
|
||||||
powerups.addComponent<PowerupComponent>(type);
|
powerups.addComponent<PowerupComponent>(pickupFunc);
|
||||||
powerups.addGroup((size_t)Entity::GroupLabel::POWERUPS);
|
powerups.addGroup((size_t)Entity::GroupLabel::POWERUPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +84,7 @@ Vector2D AssetManager::calculateSpawnPosition()
|
|||||||
spawnRect.x = rand() % (SCREEN_SIZE_WIDTH - spawnRect.w);
|
spawnRect.x = rand() % (SCREEN_SIZE_WIDTH - spawnRect.w);
|
||||||
spawnRect.y = rand() % (SCREEN_SIZE_HEIGHT - spawnRect.h);
|
spawnRect.y = rand() % (SCREEN_SIZE_HEIGHT - spawnRect.h);
|
||||||
conflict = false;
|
conflict = false;
|
||||||
for (auto cc : Game::collisionHandler->getColliders({ Entity::GroupLabel::MAPTILES }))
|
for (auto cc : this->man->getGame()->collisionHandler->getColliders({ Entity::GroupLabel::MAPTILES }))
|
||||||
{
|
{
|
||||||
if (SDL_HasIntersection(&spawnRect, &cc->collider) && strcmp(cc->tag, "projectile"))
|
if (SDL_HasIntersection(&spawnRect, &cc->collider) && strcmp(cc->tag, "projectile"))
|
||||||
{
|
{
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "CollisionHandler.h"
|
#include "CollisionHandler.h"
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "Game.h"
|
#include "GameInternal.h"
|
||||||
#include "TransformComponent.h"
|
#include "TransformComponent.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
@ -31,7 +31,6 @@ void ColliderComponent::init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
transform = &entity->getComponent<TransformComponent>();
|
transform = &entity->getComponent<TransformComponent>();
|
||||||
//Game::collisionHandler->add(this);
|
|
||||||
this->update();
|
this->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -87,8 +87,7 @@ IntersectionBitSet CollisionHandler::getIntersectionWithBounds(Entity* entity, V
|
|||||||
|
|
||||||
std::vector<ColliderComponent*> CollisionHandler::getColliders(
|
std::vector<ColliderComponent*> CollisionHandler::getColliders(
|
||||||
std::initializer_list<Entity::GroupLabel> const& groupLabels,
|
std::initializer_list<Entity::GroupLabel> const& groupLabels,
|
||||||
std::initializer_list<Entity::TeamLabel> const& teamLabels,
|
std::initializer_list<Entity*> const& excludedEntities)
|
||||||
bool negateTeam)
|
|
||||||
{
|
{
|
||||||
std::vector<ColliderComponent*> colliders;
|
std::vector<ColliderComponent*> colliders;
|
||||||
|
|
||||||
@ -97,15 +96,10 @@ std::vector<ColliderComponent*> CollisionHandler::getColliders(
|
|||||||
groupBitSet.set((size_t) groupLabel);
|
groupBitSet.set((size_t) groupLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::bitset<MAX_TEAMS> teamBitSet;
|
|
||||||
for (auto& teamLabel : teamLabels) {
|
|
||||||
teamBitSet.set((size_t) teamLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& entity : manager.getAll()) {
|
for (auto& entity : manager.getAll()) {
|
||||||
if ((groupBitSet & entity->getGroupBitSet()).none())
|
if ((groupBitSet & entity->getGroupBitSet()).none())
|
||||||
continue;
|
continue;
|
||||||
if (teamBitSet.any() && negateTeam != (teamBitSet.test((size_t) entity->getTeam())))
|
if (std::ranges::find(excludedEntities, entity) != excludedEntities.end())
|
||||||
continue;
|
continue;
|
||||||
if (!entity->hasComponent<ColliderComponent>())
|
if (!entity->hasComponent<ColliderComponent>())
|
||||||
continue;
|
continue;
|
||||||
@ -131,12 +125,11 @@ IntersectionBitSet CollisionHandler::getAnyIntersection<IntersectionBitSet>(
|
|||||||
Entity* entity,
|
Entity* entity,
|
||||||
Vector2D posMod,
|
Vector2D posMod,
|
||||||
std::initializer_list<Entity::GroupLabel> const& groupLabels,
|
std::initializer_list<Entity::GroupLabel> const& groupLabels,
|
||||||
std::initializer_list<Entity::TeamLabel> const& teamLabels,
|
std::initializer_list<Entity*> const& excludedEntities)
|
||||||
bool negateTeam)
|
|
||||||
{
|
{
|
||||||
if (!entity->hasComponent<ColliderComponent>()) return std::bitset<DIRECTION_C>();
|
if (!entity->hasComponent<ColliderComponent>()) return std::bitset<DIRECTION_C>();
|
||||||
IntersectionBitSet intersections;
|
IntersectionBitSet intersections;
|
||||||
for (auto& collider : getColliders(groupLabels, teamLabels)) {
|
for (auto& collider : getColliders(groupLabels, excludedEntities)) {
|
||||||
intersections |= getIntersection(entity, collider->entity, posMod);
|
intersections |= getIntersection(entity, collider->entity, posMod);
|
||||||
}
|
}
|
||||||
return intersections;
|
return intersections;
|
||||||
@ -154,11 +147,10 @@ Entity* CollisionHandler::getAnyIntersection<Entity*>(
|
|||||||
Entity* entity,
|
Entity* entity,
|
||||||
Vector2D posMod,
|
Vector2D posMod,
|
||||||
std::initializer_list<Entity::GroupLabel> const& groupLabels,
|
std::initializer_list<Entity::GroupLabel> const& groupLabels,
|
||||||
std::initializer_list<Entity::TeamLabel> const& teamLabels,
|
std::initializer_list<Entity*> const& excludedEntities)
|
||||||
bool negateTeam)
|
|
||||||
{
|
{
|
||||||
if (!entity->hasComponent<ColliderComponent>()) return nullptr;
|
if (!entity->hasComponent<ColliderComponent>()) return nullptr;
|
||||||
for (auto& collider : getColliders(groupLabels, teamLabels)) {
|
for (auto& collider : getColliders(groupLabels, excludedEntities)) {
|
||||||
SDL_Rect rect = entity->getComponent<ColliderComponent>().collider + posMod;
|
SDL_Rect rect = entity->getComponent<ColliderComponent>().collider + posMod;
|
||||||
if (SDL_HasIntersection(&rect, &collider->collider)) {
|
if (SDL_HasIntersection(&rect, &collider->collider)) {
|
||||||
return collider->entity;
|
return collider->entity;
|
||||||
@ -178,11 +170,10 @@ bool CollisionHandler::getAnyIntersection<bool>(
|
|||||||
Entity* entity,
|
Entity* entity,
|
||||||
Vector2D posMod,
|
Vector2D posMod,
|
||||||
std::initializer_list<Entity::GroupLabel> const& groupLabels,
|
std::initializer_list<Entity::GroupLabel> const& groupLabels,
|
||||||
std::initializer_list<Entity::TeamLabel> const& teamLabels,
|
std::initializer_list<Entity*> const& excludedEntities)
|
||||||
bool negateTeam)
|
|
||||||
{
|
{
|
||||||
if (!entity->hasComponent<ColliderComponent>()) return false;
|
if (!entity->hasComponent<ColliderComponent>()) return false;
|
||||||
for (auto& collider : getColliders(groupLabels, teamLabels)) {
|
for (auto& collider : getColliders(groupLabels, excludedEntities)) {
|
||||||
SDL_Rect rect = entity->getComponent<ColliderComponent>().collider + posMod;
|
SDL_Rect rect = entity->getComponent<ColliderComponent>().collider + posMod;
|
||||||
if (SDL_HasIntersection(&rect, &collider->collider)) {
|
if (SDL_HasIntersection(&rect, &collider->collider)) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -9,11 +9,6 @@ void Entity::update() const
|
|||||||
for (auto const& c : components) c->update();
|
for (auto const& c : components) c->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::draw() const
|
|
||||||
{
|
|
||||||
for (auto const& c : components) c->draw();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Entity::hasGroup(Group mGroup)
|
bool Entity::hasGroup(Group mGroup)
|
||||||
{
|
{
|
||||||
return groupBitSet[mGroup];
|
return groupBitSet[mGroup];
|
||||||
@ -34,14 +29,3 @@ std::bitset<MAX_GROUPS> Entity::getGroupBitSet()
|
|||||||
{
|
{
|
||||||
return groupBitSet;
|
return groupBitSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::setTeam(Entity::TeamLabel teamLabel)
|
|
||||||
{
|
|
||||||
this->teamLabel = teamLabel;
|
|
||||||
manager.addToTeam(this, (size_t) teamLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
Entity::TeamLabel Entity::getTeam()
|
|
||||||
{
|
|
||||||
return teamLabel;
|
|
||||||
}
|
|
||||||
|
|||||||
390
src/Game.cpp
@ -1,390 +0,0 @@
|
|||||||
#include "Game.h"
|
|
||||||
|
|
||||||
#include <SDL_error.h>
|
|
||||||
|
|
||||||
#include "CollisionHandler.h"
|
|
||||||
#include "Components.h"
|
|
||||||
#include "AssetManager.h"
|
|
||||||
#include "Direction.h"
|
|
||||||
#include "Entity.h"
|
|
||||||
#include "HealthComponent.h"
|
|
||||||
#include "Map.h"
|
|
||||||
#include "TextureManager.h"
|
|
||||||
#include "StatEffectsComponent.h"
|
|
||||||
#include "Constants.h"
|
|
||||||
|
|
||||||
Map* map;
|
|
||||||
Manager manager;
|
|
||||||
|
|
||||||
AssetManager* Game::assets = new AssetManager(&manager);
|
|
||||||
TextureManager* Game::textureManager = new TextureManager();
|
|
||||||
SoundManager* Game::soundManager = new SoundManager();
|
|
||||||
|
|
||||||
CollisionHandler* Game::collisionHandler = new CollisionHandler(manager);
|
|
||||||
|
|
||||||
SDL_Renderer* Game::renderer = nullptr;
|
|
||||||
|
|
||||||
SDL_Event Game::event;
|
|
||||||
|
|
||||||
auto& player1(manager.addEntity());
|
|
||||||
auto& player2(manager.addEntity());
|
|
||||||
|
|
||||||
auto& wall(manager.addEntity());
|
|
||||||
|
|
||||||
Game::Game() = default;
|
|
||||||
|
|
||||||
Game::~Game() = default;
|
|
||||||
|
|
||||||
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! " << SDL_GetError() << std::endl;
|
|
||||||
SDL_ClearError();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Mix_Init(MIX_INIT_MP3) != MIX_INIT_MP3) {
|
|
||||||
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! " << SDL_GetError() << std::endl;
|
|
||||||
SDL_ClearError();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_Surface* icon = SDL_LoadBMP("assets/iconImage.bmp");
|
|
||||||
if(!icon)
|
|
||||||
{
|
|
||||||
std::cout << "ERROR: Couldn't create icon!" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_SetWindowIcon(window, icon);
|
|
||||||
|
|
||||||
renderer = SDL_CreateRenderer(window, -1, 0);
|
|
||||||
if (!renderer)
|
|
||||||
{
|
|
||||||
std::cout << "ERROR: Renderer couldnt be created! " << SDL_GetError() << std::endl;
|
|
||||||
SDL_ClearError();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
|
||||||
|
|
||||||
SDL_Texture* backgroundTexture = Game::textureManager->loadTexture("assets/startscreen.png");
|
|
||||||
|
|
||||||
SDL_RenderClear(renderer);
|
|
||||||
SDL_RenderCopy(renderer, backgroundTexture, NULL, NULL);
|
|
||||||
SDL_RenderPresent(renderer);
|
|
||||||
|
|
||||||
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
|
|
||||||
{
|
|
||||||
std::cout << "ERROR: Mixer couldnt be initialized! " << SDL_GetError() << std::endl;
|
|
||||||
SDL_ClearError();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mix_Volume(-1, MIX_MAX_VOLUME);
|
|
||||||
Mix_AllocateChannels(16);
|
|
||||||
|
|
||||||
//SDL_Event event;
|
|
||||||
bool hasQuit = false;
|
|
||||||
|
|
||||||
while (!hasQuit)
|
|
||||||
{
|
|
||||||
SDL_PollEvent(&event);
|
|
||||||
|
|
||||||
if (event.type == SDL_QUIT)
|
|
||||||
{
|
|
||||||
hasQuit = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.type == SDL_KEYDOWN)
|
|
||||||
{
|
|
||||||
if (event.key.keysym.scancode == SDL_SCANCODE_RETURN)
|
|
||||||
{
|
|
||||||
std::cout << "Enter pressed > Game start..." << std::endl;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.key.keysym.scancode == SDL_SCANCODE_ESCAPE)
|
|
||||||
{
|
|
||||||
std::cout << "Escape pressed > Game quit..." << std::endl;
|
|
||||||
hasQuit = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasQuit)
|
|
||||||
{
|
|
||||||
this->isRunning = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// character selection
|
|
||||||
const char* player1Sprite;
|
|
||||||
const char* player2Sprite;
|
|
||||||
|
|
||||||
selectCharacters(player1Sprite, player2Sprite);
|
|
||||||
if (this->isRunning == false) return;
|
|
||||||
|
|
||||||
map = new Map();
|
|
||||||
if (!map->loadMap("assets/SDL_map_test.txt", 25, 20)) {
|
|
||||||
std::cout << "ERROR: Map couldnt be loaded! " << SDL_GetError() << std::endl;
|
|
||||||
SDL_ClearError();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//adding textures to the library in AssetManager
|
|
||||||
|
|
||||||
/*
|
|
||||||
assets->addTexture("player1", "assets/chicken_neutral_knight.png");
|
|
||||||
assets->addTexture("player2", "assets/chicken_neutral.png");
|
|
||||||
assets->addTexture("egg", "assets/egg.png");
|
|
||||||
*/
|
|
||||||
// loading sounds
|
|
||||||
assets->addSoundEffect("throw_egg", "assets/sound/throw_egg.wav");
|
|
||||||
assets->addSoundEffect("steps", "assets/sound/steps.wav");
|
|
||||||
|
|
||||||
//ecs implementation
|
|
||||||
|
|
||||||
player1.setTeam(Entity::TeamLabel::BLUE);
|
|
||||||
player1.addComponent<TransformComponent>(80,80,2); //posx, posy, scale
|
|
||||||
player1.addComponent<SpriteComponent>(player1Sprite, true); //adds sprite (32x32px), path needed
|
|
||||||
player1.addComponent<KeyboardController>(SDL_SCANCODE_W, SDL_SCANCODE_S, SDL_SCANCODE_A, SDL_SCANCODE_D, SDL_SCANCODE_E, Vector2D(2, 0));//custom keycontrols can be added
|
|
||||||
player1.addComponent<ColliderComponent>("player", 0.8f); //adds tag (for further use, reference tag)
|
|
||||||
player1.addComponent<HealthComponent>(5, Direction::LEFT);
|
|
||||||
player1.addComponent<StatEffectsComponent>();
|
|
||||||
player1.addGroup((size_t) Entity::GroupLabel::PLAYERS); //tell programm what group it belongs to for rendering order
|
|
||||||
|
|
||||||
|
|
||||||
player2.setTeam(Entity::TeamLabel::RED);
|
|
||||||
player2.addComponent<TransformComponent>(600, 500, 2);
|
|
||||||
player2.addComponent<SpriteComponent>(player2Sprite, true);
|
|
||||||
player2.addComponent<KeyboardController>(SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_RCTRL, Vector2D(-2, 0));
|
|
||||||
player2.addComponent<ColliderComponent>("enemy", 0.8f);
|
|
||||||
player2.addComponent<HealthComponent>(5, Direction::RIGHT);
|
|
||||||
player2.addComponent<StatEffectsComponent>();
|
|
||||||
player2.addGroup((size_t) Entity::GroupLabel::PLAYERS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::selectCharacters(const char* &playerSprite, const char* &enemySprite)
|
|
||||||
{
|
|
||||||
// TODO: move this whereever it makes sense (maybe game as a member)
|
|
||||||
std::map<int, std::pair<const char*, const char*>> characterSprites;
|
|
||||||
characterSprites[0] = std::make_pair("assets/chicken_neutral_knight.png", "assets/chicken_knight_spritesheet.png");
|
|
||||||
characterSprites[1] = std::make_pair("assets/chicken_neutral.png", "assets/chicken_spritesheet.png");
|
|
||||||
characterSprites[2] = std::make_pair("assets/chicken_neutral_wizard.png", "assets/chicken_wizard_spritesheet.png");
|
|
||||||
characterSprites[3] = std::make_pair("assets/chicken_neutral_mlady.png", "assets/chicken_mlady_spritesheet.png");
|
|
||||||
|
|
||||||
SDL_Rect playerCharacterRects[CHARACTER_COUNT];
|
|
||||||
SDL_Rect enemyCharacterRects[CHARACTER_COUNT];
|
|
||||||
SDL_Texture* characterTextures[CHARACTER_COUNT];
|
|
||||||
|
|
||||||
int playerSelection = 0;
|
|
||||||
int enemySelection = 0;
|
|
||||||
|
|
||||||
// load textures
|
|
||||||
for (int i = 0; i < CHARACTER_COUNT; ++i)
|
|
||||||
{
|
|
||||||
characterTextures[i] = IMG_LoadTexture(renderer, characterSprites.find(i)->second.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set up initial positions for character rects
|
|
||||||
for (int i = 0; i < CHARACTER_COUNT; ++i)
|
|
||||||
{
|
|
||||||
playerCharacterRects[i] = { 134 + (i % 2) * 118, 272 + ((i >= 2) ? 114 : 0), 64, 64 };
|
|
||||||
enemyCharacterRects[i] = { 485 + (i % 2) * 118, 273 + ((i >= 2) ? 114 : 0), 64, 64 };
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasQuit = false;
|
|
||||||
|
|
||||||
while (!hasQuit)
|
|
||||||
{
|
|
||||||
SDL_PollEvent(&event);
|
|
||||||
|
|
||||||
if (event.type == SDL_QUIT)
|
|
||||||
{
|
|
||||||
hasQuit = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.type == SDL_KEYDOWN)
|
|
||||||
{
|
|
||||||
if (event.key.keysym.scancode == SDL_SCANCODE_RETURN)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (event.key.keysym.scancode)
|
|
||||||
{
|
|
||||||
case SDL_SCANCODE_A:
|
|
||||||
playerSelection = (playerSelection - 1 + CHARACTER_COUNT) % CHARACTER_COUNT;
|
|
||||||
break;
|
|
||||||
case SDL_SCANCODE_D:
|
|
||||||
playerSelection = (playerSelection + 1) % CHARACTER_COUNT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_SCANCODE_LEFT:
|
|
||||||
enemySelection = (enemySelection - 1 + CHARACTER_COUNT) % CHARACTER_COUNT;
|
|
||||||
break;
|
|
||||||
case SDL_SCANCODE_RIGHT:
|
|
||||||
enemySelection = (enemySelection + 1) % CHARACTER_COUNT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_Texture* backgroundTexture = Game::textureManager->loadTexture("assets/characterSelection.png");
|
|
||||||
SDL_RenderClear(renderer);
|
|
||||||
SDL_RenderCopy(renderer, backgroundTexture, NULL, NULL);
|
|
||||||
|
|
||||||
for (int i = 0; i < CHARACTER_COUNT; ++i)
|
|
||||||
{
|
|
||||||
SDL_RenderCopy(renderer, characterTextures[i], nullptr, &playerCharacterRects[i]);
|
|
||||||
SDL_RenderCopy(renderer, characterTextures[i], nullptr, &enemyCharacterRects[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
|
|
||||||
SDL_RenderDrawRect(renderer, &playerCharacterRects[playerSelection]);
|
|
||||||
SDL_RenderDrawRect(renderer, &enemyCharacterRects[enemySelection]);
|
|
||||||
|
|
||||||
SDL_RenderPresent(renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasQuit)
|
|
||||||
{
|
|
||||||
this->isRunning = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
playerSprite = characterSprites.find(playerSelection)->second.second;
|
|
||||||
enemySprite = characterSprites.find(enemySelection)->second.second;
|
|
||||||
this->isRunning = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& tiles(manager.getGroup((size_t)Entity::GroupLabel::MAPTILES));
|
|
||||||
auto& players(manager.getGroup((size_t)Entity::GroupLabel::PLAYERS));
|
|
||||||
auto& projectiles(manager.getGroup((size_t)Entity::GroupLabel::PROJECTILE));
|
|
||||||
auto& hearts(manager.getGroup((size_t)Entity::GroupLabel::HEARTS));
|
|
||||||
auto& powerups(manager.getGroup((size_t)Entity::GroupLabel::POWERUPS));
|
|
||||||
|
|
||||||
void Game::handleEvents()
|
|
||||||
{
|
|
||||||
SDL_PollEvent(&event);
|
|
||||||
|
|
||||||
switch (event.type)
|
|
||||||
{
|
|
||||||
case SDL_QUIT: this->isRunning = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::update()
|
|
||||||
{
|
|
||||||
Vector2D playerPos = player1.getComponent<TransformComponent>().position;
|
|
||||||
Vector2D enemyPos = player2.getComponent<TransformComponent>().position;
|
|
||||||
|
|
||||||
int powerupSpawn = rand() % 500;
|
|
||||||
|
|
||||||
manager.refresh();
|
|
||||||
manager.update();
|
|
||||||
|
|
||||||
if (powerupSpawn == 0)
|
|
||||||
{
|
|
||||||
assets->createPowerup(assets->calculateSpawnPosition(), assets->calculateType());
|
|
||||||
}
|
|
||||||
|
|
||||||
// needs to be in game.cpp to have access to internal functions
|
|
||||||
for (auto& player : manager.getGroup((size_t) Entity::GroupLabel::PLAYERS)) {
|
|
||||||
if (player->getComponent<HealthComponent>().getHealth() <= 0) {
|
|
||||||
this->setWinner(player->getTeam());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::render()
|
|
||||||
{
|
|
||||||
SDL_RenderClear(renderer);
|
|
||||||
for (auto& t : tiles)
|
|
||||||
t->draw();
|
|
||||||
|
|
||||||
for (auto& p : powerups)
|
|
||||||
p->draw();
|
|
||||||
|
|
||||||
for (auto& p : players)
|
|
||||||
p->draw();
|
|
||||||
|
|
||||||
for (auto& p : projectiles)
|
|
||||||
p->draw();
|
|
||||||
|
|
||||||
for (auto& h : hearts)
|
|
||||||
h->draw();
|
|
||||||
|
|
||||||
SDL_RenderPresent(renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::clean()
|
|
||||||
{
|
|
||||||
delete(textureManager);
|
|
||||||
SDL_DestroyRenderer(renderer);
|
|
||||||
SDL_DestroyWindow(window);
|
|
||||||
SDL_Quit();
|
|
||||||
std::cout << "Game Cleaned!" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::addTile(unsigned long id, int x, int y)
|
|
||||||
{
|
|
||||||
auto& tile(manager.addEntity());
|
|
||||||
tile.addComponent<TileComponent>(x, y, TILE_SIZE, TILE_SIZE, id);
|
|
||||||
if (id == 1) tile.addComponent<ColliderComponent>("water");
|
|
||||||
tile.addGroup((size_t)Entity::GroupLabel::MAPTILES);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Game::running() const
|
|
||||||
{
|
|
||||||
return isRunning;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::setWinner(Entity::TeamLabel winningTeam)
|
|
||||||
{
|
|
||||||
this->winner = winningTeam;
|
|
||||||
this->isRunning = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Entity::TeamLabel Game::getWinner() const
|
|
||||||
{
|
|
||||||
return this->winner;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::refreshPlayers() {
|
|
||||||
|
|
||||||
for(auto& p : projectiles) {
|
|
||||||
p->destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
player1.getComponent<TransformComponent>().position = Vector2D(80, 80);
|
|
||||||
player2.getComponent<TransformComponent>().position = Vector2D(600, 500);
|
|
||||||
|
|
||||||
player1.getComponent<HealthComponent>().setHealth(5);
|
|
||||||
player2.getComponent<HealthComponent>().setHealth(5);
|
|
||||||
|
|
||||||
isRunning = true;
|
|
||||||
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
159
src/GameInternal.cpp
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
#include "GameInternal.h"
|
||||||
|
|
||||||
|
#include <SDL_error.h>
|
||||||
|
|
||||||
|
#include "CollisionHandler.h"
|
||||||
|
#include "AssetManager.h"
|
||||||
|
#include "RenderManager.h"
|
||||||
|
#include "SDL_mixer.h"
|
||||||
|
#include "SoundManager.h"
|
||||||
|
#include "TileComponent.h"
|
||||||
|
#include "Direction.h"
|
||||||
|
#include "Entity.h"
|
||||||
|
#include "HealthComponent.h"
|
||||||
|
#include "Map.h"
|
||||||
|
#include "TextureManager.h"
|
||||||
|
#include "StatEffectsComponent.h"
|
||||||
|
#include "Constants.h"
|
||||||
|
#include "Game.h"
|
||||||
|
#include "GameFactory.h"
|
||||||
|
|
||||||
|
GameInternal::GameInternal() :
|
||||||
|
manager(this),
|
||||||
|
renderManager(),
|
||||||
|
tiles(manager.getGroup((size_t)Entity::GroupLabel::MAPTILES)),
|
||||||
|
players(manager.getGroup((size_t)Entity::GroupLabel::PLAYERS)),
|
||||||
|
projectiles(manager.getGroup((size_t)Entity::GroupLabel::PROJECTILE)),
|
||||||
|
hearts(manager.getGroup((size_t)Entity::GroupLabel::HEARTS)),
|
||||||
|
powerups(manager.getGroup((size_t)Entity::GroupLabel::POWERUPS))
|
||||||
|
{};
|
||||||
|
|
||||||
|
GameInternal::~GameInternal() = default;
|
||||||
|
|
||||||
|
void GameInternal::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen)
|
||||||
|
{
|
||||||
|
GameInternal::assets = new AssetManager(&manager);
|
||||||
|
GameInternal::textureManager = new TextureManager(&manager);
|
||||||
|
GameInternal::soundManager = new SoundManager();
|
||||||
|
GameInternal::collisionHandler = new CollisionHandler(manager); // why does this use a referrence, but AssetManager a pointer?
|
||||||
|
|
||||||
|
int flags = 0;
|
||||||
|
if (fullscreen)
|
||||||
|
{
|
||||||
|
flags = SDL_WINDOW_FULLSCREEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
|
||||||
|
{
|
||||||
|
std::cout << "ERROR. Subsystem couldnt be initialized! " << SDL_GetError() << std::endl;
|
||||||
|
SDL_ClearError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Mix_Init(MIX_INIT_MP3) != MIX_INIT_MP3) {
|
||||||
|
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! " << SDL_GetError() << std::endl;
|
||||||
|
SDL_ClearError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bad
|
||||||
|
SDL_Surface* icon;
|
||||||
|
if((icon = SDL_LoadBMP("assets/iconImage.bmp")))
|
||||||
|
{
|
||||||
|
SDL_SetWindowIcon(window, icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetWindowIcon(window, icon);
|
||||||
|
|
||||||
|
renderer = SDL_CreateRenderer(window, -1, 0);
|
||||||
|
if (!renderer)
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: Renderer couldnt be created! " << SDL_GetError() << std::endl;
|
||||||
|
SDL_ClearError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
||||||
|
|
||||||
|
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: Mixer couldnt be initialized! " << SDL_GetError() << std::endl;
|
||||||
|
SDL_ClearError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mix_Volume(-1, MIX_MAX_VOLUME);
|
||||||
|
Mix_AllocateChannels(16);
|
||||||
|
|
||||||
|
map = new Map();
|
||||||
|
|
||||||
|
// loading sounds
|
||||||
|
// assets->addSoundEffect("throw_egg", "assets/sound/throw_egg.wav");
|
||||||
|
// assets->addSoundEffect("steps", "assets/sound/steps.wav");
|
||||||
|
|
||||||
|
// loading music
|
||||||
|
// assets->addMusic("background_music", "assets/sound/background_music.mp3");
|
||||||
|
|
||||||
|
this->gameInstance = GameFactory::instance().create(this);
|
||||||
|
this->gameInstance->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameInternal::handleEvents()
|
||||||
|
{
|
||||||
|
SDL_PollEvent(&event);
|
||||||
|
|
||||||
|
switch (event.type)
|
||||||
|
{
|
||||||
|
case SDL_QUIT: this->setRunning(false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameInternal::update()
|
||||||
|
{
|
||||||
|
manager.refresh();
|
||||||
|
manager.update();
|
||||||
|
|
||||||
|
this->gameInstance->update(); // TODO: this might have to be split up into two update functions, before and after manager...
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameInternal::render()
|
||||||
|
{
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
this->renderManager.renderAll();
|
||||||
|
SDL_RenderPresent(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameInternal::clean()
|
||||||
|
{
|
||||||
|
delete(textureManager);
|
||||||
|
SDL_DestroyRenderer(renderer);
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
SDL_Quit();
|
||||||
|
std::cout << "Game Cleaned!" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameInternal::isRunning() const
|
||||||
|
{
|
||||||
|
return running;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameInternal::setRunning(bool running) //TODO: might be depracted
|
||||||
|
{
|
||||||
|
this->running = running;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameInternal::stopGame()
|
||||||
|
{
|
||||||
|
this->running = false;
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
#include "GameObject.h"
|
|
||||||
|
|
||||||
#include "TextureManager.h"
|
|
||||||
#include "Game.h"
|
|
||||||
|
|
||||||
GameObject::GameObject(const char* texturesheet, int x, int y)
|
|
||||||
{
|
|
||||||
this->objTexture = Game::textureManager->loadTexture(texturesheet);
|
|
||||||
this->xPos = x;
|
|
||||||
this->yPos = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
@ -1,64 +1,19 @@
|
|||||||
#include "HealthComponent.h"
|
#include "HealthComponent.h"
|
||||||
|
|
||||||
#include "Components.h"
|
|
||||||
#include "Direction.h"
|
#include "Direction.h"
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "Game.h"
|
#include "GameInternal.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
void HealthComponent::init()
|
void HealthComponent::init()
|
||||||
{
|
{}
|
||||||
refreshHearts();
|
|
||||||
}
|
|
||||||
|
|
||||||
void HealthComponent::modifyHealth(int health)
|
void HealthComponent::modifyHealth(int health)
|
||||||
{
|
{
|
||||||
this->health += health;
|
this->health += health;
|
||||||
this->refreshHearts();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HealthComponent::setHealth(int health)
|
void HealthComponent::setHealth(int health)
|
||||||
{
|
{
|
||||||
this->health = health;
|
this->health = health;
|
||||||
this->refreshHearts();
|
|
||||||
}
|
|
||||||
|
|
||||||
void HealthComponent::refreshHearts()
|
|
||||||
{
|
|
||||||
// clear hearts if exist
|
|
||||||
for (auto& heart : this->entity->getManager().getGroup((size_t) Entity::GroupLabel::HEARTS)) {
|
|
||||||
if (heart->getTeam() == this->entity->getTeam()) {
|
|
||||||
heart->destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int x; //starting position for first health icon
|
|
||||||
|
|
||||||
if(side == Direction::LEFT) {
|
|
||||||
x = 10;
|
|
||||||
} else {
|
|
||||||
x = 730;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < health; i++) {
|
|
||||||
|
|
||||||
//checks for player side
|
|
||||||
if (side == Direction::LEFT) {
|
|
||||||
createHeartComponents(x);
|
|
||||||
x += 50;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
createHeartComponents(x);
|
|
||||||
x -= 50;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HealthComponent::createHeartComponents(int x)
|
|
||||||
{
|
|
||||||
auto& heart(this->entity->getManager().addEntity());
|
|
||||||
heart.addComponent<TransformComponent>(x,5,2);
|
|
||||||
heart.addComponent<SpriteComponent>("assets/heart.png");
|
|
||||||
heart.addGroup((size_t)Entity::GroupLabel::HEARTS);
|
|
||||||
heart.setTeam(this->entity->getTeam());
|
|
||||||
}
|
}
|
||||||
117
src/InputComponent.cpp
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#include "InputComponent.h"
|
||||||
|
|
||||||
|
InputComponent::InputComponent()
|
||||||
|
{
|
||||||
|
m_keyStates = SDL_GetKeyboardState(NULL);
|
||||||
|
InitKeyMappings();
|
||||||
|
}
|
||||||
|
|
||||||
|
InputComponent::~InputComponent() = default;
|
||||||
|
|
||||||
|
void InputComponent::init(){}
|
||||||
|
|
||||||
|
void InputComponent::update()
|
||||||
|
{
|
||||||
|
SDL_PumpEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputComponent::isKeyDown(Key key)
|
||||||
|
{
|
||||||
|
return m_keyStates[mapKeyToSDL(key)];
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Scancode InputComponent::mapKeyToSDL(Key key)
|
||||||
|
{
|
||||||
|
auto it = m_keyMappings.find(key);
|
||||||
|
if (it == m_keyMappings.end())
|
||||||
|
{
|
||||||
|
return SDL_SCANCODE_UNKNOWN;
|
||||||
|
}
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputComponent::InitKeyMappings()
|
||||||
|
{
|
||||||
|
m_keyMappings =
|
||||||
|
{
|
||||||
|
{Key::UP, SDL_SCANCODE_UP},
|
||||||
|
{Key::DOWN, SDL_SCANCODE_DOWN},
|
||||||
|
{Key::LEFT, SDL_SCANCODE_LEFT},
|
||||||
|
{Key::RIGHT, SDL_SCANCODE_RIGHT},
|
||||||
|
{Key::SPACE, SDL_SCANCODE_SPACE},
|
||||||
|
{Key::ENTER, SDL_SCANCODE_RETURN},
|
||||||
|
{Key::ESCAPE, SDL_SCANCODE_ESCAPE},
|
||||||
|
{Key::TAB, SDL_SCANCODE_TAB},
|
||||||
|
{Key::BACKSPACE, SDL_SCANCODE_BACKSPACE},
|
||||||
|
{Key::DELETE, SDL_SCANCODE_DELETE},
|
||||||
|
{Key::HOME, SDL_SCANCODE_HOME},
|
||||||
|
{Key::END, SDL_SCANCODE_END},
|
||||||
|
{Key::PAGE_UP, SDL_SCANCODE_PAGEUP},
|
||||||
|
{Key::PAGE_DOWN, SDL_SCANCODE_PAGEDOWN},
|
||||||
|
{Key::INSERT, SDL_SCANCODE_INSERT},
|
||||||
|
{Key::CAPS_LOCK, SDL_SCANCODE_CAPSLOCK},
|
||||||
|
{Key::LEFT_SHIFT, SDL_SCANCODE_LSHIFT},
|
||||||
|
{Key::RIGHT_SHIFT, SDL_SCANCODE_RSHIFT},
|
||||||
|
{Key::LEFT_CTRL, SDL_SCANCODE_LCTRL},
|
||||||
|
{Key::RIGHT_CTRL, SDL_SCANCODE_RCTRL},
|
||||||
|
{Key::LEFT_ALT, SDL_SCANCODE_LALT},
|
||||||
|
{Key::RIGHT_ALT, SDL_SCANCODE_RALT},
|
||||||
|
{Key::F1, SDL_SCANCODE_F1},
|
||||||
|
{Key::F2, SDL_SCANCODE_F2},
|
||||||
|
{Key::F3, SDL_SCANCODE_F3},
|
||||||
|
{Key::F4, SDL_SCANCODE_F4},
|
||||||
|
{Key::F5, SDL_SCANCODE_F5},
|
||||||
|
{Key::F6, SDL_SCANCODE_F6},
|
||||||
|
{Key::F7, SDL_SCANCODE_F7},
|
||||||
|
{Key::F8, SDL_SCANCODE_F8},
|
||||||
|
{Key::F9, SDL_SCANCODE_F9},
|
||||||
|
{Key::F10, SDL_SCANCODE_F10},
|
||||||
|
{Key::F11, SDL_SCANCODE_F11},
|
||||||
|
{Key::F12, SDL_SCANCODE_F12},
|
||||||
|
{Key::A, SDL_SCANCODE_A},
|
||||||
|
{Key::B, SDL_SCANCODE_B},
|
||||||
|
{Key::C, SDL_SCANCODE_C},
|
||||||
|
{Key::D, SDL_SCANCODE_D},
|
||||||
|
{Key::E, SDL_SCANCODE_E},
|
||||||
|
{Key::F, SDL_SCANCODE_F},
|
||||||
|
{Key::G, SDL_SCANCODE_G},
|
||||||
|
{Key::H, SDL_SCANCODE_H},
|
||||||
|
{Key::I, SDL_SCANCODE_I},
|
||||||
|
{Key::J, SDL_SCANCODE_J},
|
||||||
|
{Key::K, SDL_SCANCODE_K},
|
||||||
|
{Key::L, SDL_SCANCODE_L},
|
||||||
|
{Key::M, SDL_SCANCODE_M},
|
||||||
|
{Key::N, SDL_SCANCODE_N},
|
||||||
|
{Key::O, SDL_SCANCODE_O},
|
||||||
|
{Key::P, SDL_SCANCODE_P},
|
||||||
|
{Key::Q, SDL_SCANCODE_Q},
|
||||||
|
{Key::R, SDL_SCANCODE_R},
|
||||||
|
{Key::S, SDL_SCANCODE_S},
|
||||||
|
{Key::T, SDL_SCANCODE_T},
|
||||||
|
{Key::U, SDL_SCANCODE_U},
|
||||||
|
{Key::V, SDL_SCANCODE_V},
|
||||||
|
{Key::W, SDL_SCANCODE_W},
|
||||||
|
{Key::X, SDL_SCANCODE_X},
|
||||||
|
{Key::Y, SDL_SCANCODE_Y},
|
||||||
|
{Key::Z, SDL_SCANCODE_Z},
|
||||||
|
{Key::NUM_0, SDL_SCANCODE_0},
|
||||||
|
{Key::NUM_1, SDL_SCANCODE_1},
|
||||||
|
{Key::NUM_2, SDL_SCANCODE_2},
|
||||||
|
{Key::NUM_3, SDL_SCANCODE_3},
|
||||||
|
{Key::NUM_4, SDL_SCANCODE_4},
|
||||||
|
{Key::NUM_5, SDL_SCANCODE_5},
|
||||||
|
{Key::NUM_6, SDL_SCANCODE_6},
|
||||||
|
{Key::NUM_7, SDL_SCANCODE_7},
|
||||||
|
{Key::NUM_8, SDL_SCANCODE_8},
|
||||||
|
{Key::NUM_9, SDL_SCANCODE_9},
|
||||||
|
{Key::LEFT_BRACKET, SDL_SCANCODE_LEFTBRACKET},
|
||||||
|
{Key::RIGHT_BRACKET, SDL_SCANCODE_RIGHTBRACKET},
|
||||||
|
{Key::SEMICOLON, SDL_SCANCODE_SEMICOLON},
|
||||||
|
{Key::APOSTROPHE, SDL_SCANCODE_APOSTROPHE},
|
||||||
|
{Key::COMMA, SDL_SCANCODE_COMMA},
|
||||||
|
{Key::PERIOD, SDL_SCANCODE_PERIOD},
|
||||||
|
{Key::SLASH, SDL_SCANCODE_SLASH},
|
||||||
|
{Key::BACKSLASH, SDL_SCANCODE_BACKSLASH},
|
||||||
|
{Key::GRAVE, SDL_SCANCODE_GRAVE}
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -1,82 +0,0 @@
|
|||||||
#include "KeyboardController.h"
|
|
||||||
|
|
||||||
#include "Game.h"
|
|
||||||
#include "Components.h"
|
|
||||||
#include "AssetManager.h"
|
|
||||||
#include "SpriteComponent.h"
|
|
||||||
|
|
||||||
KeyboardController::KeyboardController(SDL_Scancode up, SDL_Scancode down, SDL_Scancode left, SDL_Scancode right, SDL_Scancode fire, Vector2D fireVelocity)
|
|
||||||
{
|
|
||||||
this->up = up;
|
|
||||||
this->down = down;
|
|
||||||
this->left = left;
|
|
||||||
this->right = right;
|
|
||||||
this->fire = fire;
|
|
||||||
this->fireVelocity = fireVelocity;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyboardController::init()
|
|
||||||
{
|
|
||||||
sprite = &entity->getComponent<SpriteComponent>();
|
|
||||||
transform = &entity->getComponent<TransformComponent>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyboardController::update()
|
|
||||||
{
|
|
||||||
transform->direction.x = 0;
|
|
||||||
transform->direction.y = 0;
|
|
||||||
sprite->playAnimation(IDLE);
|
|
||||||
|
|
||||||
if (keystates[this->up]) {
|
|
||||||
transform->direction.y = -1;
|
|
||||||
sprite->playAnimation(WALK);
|
|
||||||
SoundManager::playSound(STEPS);
|
|
||||||
}
|
|
||||||
if (keystates[this->left]) {
|
|
||||||
transform->direction.x = -1;
|
|
||||||
sprite->playAnimation(WALK);
|
|
||||||
sprite->setDirection(Direction::LEFT);
|
|
||||||
SoundManager::playSound(STEPS);
|
|
||||||
}
|
|
||||||
if (keystates[this->down]) {
|
|
||||||
transform->direction.y = 1;
|
|
||||||
sprite->playAnimation(WALK);
|
|
||||||
SoundManager::playSound(STEPS);
|
|
||||||
}
|
|
||||||
if (keystates[this->right]) {
|
|
||||||
transform->direction.x = 1;
|
|
||||||
sprite->playAnimation(WALK);
|
|
||||||
sprite->setDirection(Direction::RIGHT);
|
|
||||||
SoundManager::playSound(STEPS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keystates[this->fire]) {
|
|
||||||
|
|
||||||
Uint32 currentTicks = SDL_GetTicks();
|
|
||||||
|
|
||||||
if (currentTicks - lastFireTime >= fireCooldown) {
|
|
||||||
|
|
||||||
player = &entity->getComponent<TransformComponent>();
|
|
||||||
|
|
||||||
//checks player source via the firing velocity
|
|
||||||
//TODO: adding actual projectile textures
|
|
||||||
if (fireVelocity.x > 0) {
|
|
||||||
sprite->setDirection(Direction::RIGHT);
|
|
||||||
Game::assets->createProjectile(Vector2D(player->position.x, player->position.y), fireVelocity,
|
|
||||||
1, 180, 2, "assets/egg.png", this->entity->getTeam());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sprite->setDirection(Direction::LEFT);
|
|
||||||
Game::assets->createProjectile(Vector2D(player->position.x, player->position.y), fireVelocity,
|
|
||||||
1, 180, 2, "assets/egg.png", this->entity->getTeam());
|
|
||||||
}
|
|
||||||
|
|
||||||
lastFireTime = currentTicks;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyboardController::modifyAtkSpeed(int8_t modifier)
|
|
||||||
{
|
|
||||||
this->fireCooldown -= modifier * 400;
|
|
||||||
}
|
|
||||||
@ -6,11 +6,6 @@
|
|||||||
#include "Constants.h"
|
#include "Constants.h"
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
|
|
||||||
void Manager::draw()
|
|
||||||
{
|
|
||||||
for (auto& e : entities) e->draw();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Manager::refresh()
|
void Manager::refresh()
|
||||||
{
|
{
|
||||||
for (auto i(0u); i < MAX_GROUPS; i++)
|
for (auto i(0u); i < MAX_GROUPS; i++)
|
||||||
@ -24,17 +19,6 @@ void Manager::refresh()
|
|||||||
}), std::end(v));
|
}), std::end(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto i(0u); i < MAX_TEAMS; i++)
|
|
||||||
{
|
|
||||||
auto& v(entitiesByTeam[i]);
|
|
||||||
v.erase(
|
|
||||||
std::remove_if(std::begin(v), std::end(v),
|
|
||||||
[i](Entity* mEntity)
|
|
||||||
{
|
|
||||||
return !mEntity->isActive() || (size_t)(mEntity->getTeam()) != i;
|
|
||||||
}), std::end(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
entities.erase(std::remove_if(std::begin(entities), std::end(entities),
|
entities.erase(std::remove_if(std::begin(entities), std::end(entities),
|
||||||
[](const std::unique_ptr<Entity>& mEntity)
|
[](const std::unique_ptr<Entity>& mEntity)
|
||||||
{
|
{
|
||||||
@ -58,16 +42,6 @@ std::vector<Entity*>& Manager::getGroup(Group mGroup)
|
|||||||
return entitiesByGroup.at(mGroup);
|
return entitiesByGroup.at(mGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::addToTeam(Entity* mEntity, Team mTeam)
|
|
||||||
{
|
|
||||||
entitiesByTeam.at(mTeam).emplace_back(mEntity); //
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Entity*>& Manager::getTeam(Team mTeam)
|
|
||||||
{
|
|
||||||
return entitiesByTeam.at(mTeam);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Entity*> Manager::getAll()
|
std::vector<Entity*> Manager::getAll()
|
||||||
{
|
{
|
||||||
std::vector<Entity*> entity_vec;
|
std::vector<Entity*> entity_vec;
|
||||||
|
|||||||
137
src/Map.cpp
@ -1,15 +1,32 @@
|
|||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <cstdio>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <SDL_error.h>
|
||||||
|
#include <SDL_render.h>
|
||||||
|
|
||||||
|
#include <tmxlite/Layer.hpp>
|
||||||
|
#include <tmxlite/Map.hpp>
|
||||||
|
#include <tmxlite/Tileset.hpp>
|
||||||
|
#include <tmxlite/Property.hpp>
|
||||||
|
#include <tmxlite/TileLayer.hpp>
|
||||||
|
|
||||||
#include "Constants.h"
|
#include "Constants.h"
|
||||||
#include "Game.h"
|
#include "GameInternal.h"
|
||||||
#include "SDL_error.h"
|
#include "SpriteComponent.h"
|
||||||
|
#include "TextureManager.h"
|
||||||
|
#include "TileComponent.h"
|
||||||
|
#include "VEGO.h"
|
||||||
|
#include "tmxlite/Types.hpp"
|
||||||
|
|
||||||
bool Map::loadMap(const char* path, int sizeX, int sizeY)
|
void Map::loadMap(const char* path, int sizeX, int sizeY, GameInternal* game, const std::map<int, std::pair<std::string, bool>>* textureDict /* backreference */)
|
||||||
{
|
{
|
||||||
std::string tileIDstr;
|
std::string tileIDstr;
|
||||||
char singleChar = 0;
|
char singleChar = 0;
|
||||||
@ -18,23 +35,24 @@ bool Map::loadMap(const char* path, int sizeX, int sizeY)
|
|||||||
|
|
||||||
if (!mapFile.is_open()) {
|
if (!mapFile.is_open()) {
|
||||||
SDL_SetError("Error loading map: Couldn't open map file!");
|
SDL_SetError("Error loading map: Couldn't open map file!");
|
||||||
return false;
|
std::cout << "ERROR: Map couldnt be loaded! " << SDL_GetError() << std::endl;
|
||||||
|
SDL_ClearError();
|
||||||
}
|
}
|
||||||
|
|
||||||
int x = 0, y = 0; // needed outside for-loop for error handling
|
int x = 0, y = 0; // needed outside for-loop for error handling
|
||||||
bool success = true;
|
|
||||||
for (; !mapFile.eof(); mapFile.get(singleChar))
|
for (; !mapFile.eof(); mapFile.get(singleChar))
|
||||||
{
|
{
|
||||||
if (singleChar == ',' || singleChar == '\n') {
|
if (singleChar == ',' || singleChar == '\n') {
|
||||||
if (tileIDstr.empty())
|
if (tileIDstr.empty())
|
||||||
continue;
|
continue;
|
||||||
Game::addTile(std::stoi(tileIDstr), x * TILE_SIZE, y * TILE_SIZE);
|
Map::addTile(std::stoi(tileIDstr), x * TILE_SIZE, y * TILE_SIZE, game, textureDict);
|
||||||
tileIDstr.clear();
|
tileIDstr.clear();
|
||||||
x++;
|
x++;
|
||||||
if (singleChar == '\n') {
|
if (singleChar == '\n') {
|
||||||
if (x != sizeX) {
|
if (x != sizeX) {
|
||||||
SDL_SetError("Error loading map: specified x size doesn't match map file!");
|
SDL_SetError("Error loading map: specified x size doesn't match map file!");
|
||||||
success = false;
|
std::cout << "ERROR: Map couldnt be loaded! " << SDL_GetError() << std::endl;
|
||||||
|
SDL_ClearError();
|
||||||
}
|
}
|
||||||
x = 0;
|
x = 0;
|
||||||
y++;
|
y++;
|
||||||
@ -47,10 +65,107 @@ bool Map::loadMap(const char* path, int sizeX, int sizeY)
|
|||||||
}
|
}
|
||||||
if (y != sizeY) {
|
if (y != sizeY) {
|
||||||
SDL_SetError("Error loading map: specified y size doesn't match map file!");
|
SDL_SetError("Error loading map: specified y size doesn't match map file!");
|
||||||
success = false;
|
std::cout << "ERROR: Map couldnt be loaded! " << SDL_GetError() << std::endl;
|
||||||
|
SDL_ClearError();
|
||||||
}
|
}
|
||||||
|
|
||||||
mapFile.close();
|
mapFile.close();
|
||||||
|
}
|
||||||
return success;
|
|
||||||
|
void Map::addTile(unsigned long id, int x, int y, GameInternal* game, const std::map<int, std::pair<std::string, bool>>* textureDict) // tile entity
|
||||||
|
{
|
||||||
|
auto& tile(game->manager.addEntity());
|
||||||
|
tile.addComponent<TileComponent>(x, y, TILE_SIZE, TILE_SIZE, id, textureDict);
|
||||||
|
|
||||||
|
if(tile.getComponent<TileComponent>().hasCollision()) tile.addComponent<ColliderComponent>("tile"/*tile.getComponent<TileComponent>().getName().data()*/);
|
||||||
|
tile.addGroup((size_t)Entity::GroupLabel::MAPTILES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Map::loadMapTmx(const char* path)
|
||||||
|
{
|
||||||
|
tmx::Map map;
|
||||||
|
if (!map.load(path)) {
|
||||||
|
// TODO: log to console
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<tmx::Tileset>& tileSets = map.getTilesets();
|
||||||
|
|
||||||
|
const std::vector<tmx::Layer::Ptr>& mapLayers = map.getLayers();
|
||||||
|
const auto mapSize = map.getTileCount();
|
||||||
|
const auto mapTileSize = map.getTileSize();
|
||||||
|
|
||||||
|
std::vector<std::string> texturePaths = {};
|
||||||
|
|
||||||
|
for (auto tileSet : tileSets) {
|
||||||
|
texturePaths.emplace_back(tileSet.getImagePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& layer : mapLayers) {
|
||||||
|
|
||||||
|
if (layer->getType() == tmx::Layer::Type::Tile) {
|
||||||
|
auto& tileLayer = layer->getLayerAs<tmx::TileLayer>();
|
||||||
|
|
||||||
|
int zIndex = 0;
|
||||||
|
|
||||||
|
const std::vector<tmx::Property>& properties = layer->getProperties();
|
||||||
|
auto zIndexIterator = std::find_if(properties.begin(), properties.end(), [](const tmx::Property& property) {
|
||||||
|
return property.getName() == "zIndex";
|
||||||
|
});
|
||||||
|
|
||||||
|
if (zIndexIterator != properties.end() && std::is_nothrow_convertible<decltype(zIndexIterator->getType()), int>::value) {
|
||||||
|
zIndex = zIndexIterator->getIntValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& tiles = tileLayer.getTiles();
|
||||||
|
|
||||||
|
for (auto i = 0u; i < tileSets.size(); i++) {
|
||||||
|
auto tilesetTexture = VEGO_Game().textureManager->loadTexture(texturePaths.at(i).c_str());
|
||||||
|
tmx::Vector2i textureSize;
|
||||||
|
SDL_QueryTexture(tilesetTexture, nullptr, nullptr, &(textureSize.x), &(textureSize.y));
|
||||||
|
|
||||||
|
const auto tileCountX = textureSize.x / mapTileSize.x;
|
||||||
|
const auto tileCountY = textureSize.y / mapTileSize.y;
|
||||||
|
|
||||||
|
for (auto idx = 0ul; idx < mapSize.x * mapSize.y; idx++) {
|
||||||
|
|
||||||
|
if (idx >= tiles.size() || tiles[idx].ID < tileSets.at(i).getFirstGID()
|
||||||
|
|| tiles[idx].ID >= (tileSets.at(i).getFirstGID() + tileSets.at(i).getTileCount())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto x = idx % mapSize.x;
|
||||||
|
const auto y = idx / mapSize.x;
|
||||||
|
|
||||||
|
auto idIndex = (tiles[idx].ID - tileSets.at(i).getFirstGID());
|
||||||
|
|
||||||
|
int u = idIndex % tileCountX;
|
||||||
|
int v = idIndex / tileCountY;
|
||||||
|
u *= mapTileSize.x; //TODO we should be using the tile set size, as this may be different from the map's grid size
|
||||||
|
v *= mapTileSize.y;
|
||||||
|
|
||||||
|
//normalise the UV
|
||||||
|
u /= textureSize.x;
|
||||||
|
v /= textureSize.y;
|
||||||
|
|
||||||
|
//vert pos
|
||||||
|
const float tilePosX = static_cast<float>(x) * mapTileSize.x;
|
||||||
|
const float tilePosY = (static_cast<float>(y) * mapTileSize.y);
|
||||||
|
|
||||||
|
Map::addTile(tilePosX, tilePosY, mapTileSize, u, v, zIndex, texturePaths.at(i).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (layer->getType() == tmx::Layer::Type::Object) {
|
||||||
|
// spawn objects
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Map::addTile(float x, float y, const tmx::Vector2u& mapTileSize, int u, int v, int zIndex, const char* texturePath)
|
||||||
|
{
|
||||||
|
auto& tile(VEGO_Game().manager.addEntity());
|
||||||
|
|
||||||
|
tile.addComponent<TransformComponent>(x, y, mapTileSize.x, mapTileSize.y, 1);
|
||||||
|
tile.addComponent<SpriteComponent>(texturePath, v, u, zIndex); // why does uv need to be reversed?
|
||||||
}
|
}
|
||||||
@ -1,85 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <SDL_image.h>
|
|
||||||
|
|
||||||
#include "Entity.h"
|
|
||||||
#include "PopupWindow.h"
|
|
||||||
#include "TextureManager.h"
|
|
||||||
#include "Game.h"
|
|
||||||
|
|
||||||
PopupWindow::PopupWindow(const char* title, const std::string &message) :
|
|
||||||
continueGame(false), interacted(false) {
|
|
||||||
this->window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 400, 250, 0);
|
|
||||||
//font = TTF_OpenFont("assets/Trajan.ttf", 24); // Change the path and size as needed
|
|
||||||
|
|
||||||
this->renderer = SDL_CreateRenderer(window, -1, 0);
|
|
||||||
SDL_SetRenderDrawColor(this->renderer, 255, 255, 255, 255);
|
|
||||||
|
|
||||||
//SDL_Surface* surface = TTF_RenderText_Blended(font, message.c_str(), {255, 255, 255});
|
|
||||||
//texture = SDL_CreateTextureFromSurface(renderer, surface);
|
|
||||||
|
|
||||||
//SDL_FreeSurface(surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
PopupWindow::~PopupWindow() {
|
|
||||||
SDL_DestroyTexture(this->texture);
|
|
||||||
SDL_DestroyRenderer(this->renderer);
|
|
||||||
SDL_DestroyWindow(this->window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PopupWindow::handleWinnerEvents() {
|
|
||||||
|
|
||||||
SDL_Event e;
|
|
||||||
|
|
||||||
while (SDL_PollEvent(&e))
|
|
||||||
{
|
|
||||||
if (e.type == SDL_QUIT)
|
|
||||||
{
|
|
||||||
continueGame = false;
|
|
||||||
interacted = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(e.type != SDL_KEYDOWN)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch (e.key.keysym.sym) {
|
|
||||||
|
|
||||||
case SDLK_q: {
|
|
||||||
continueGame = false;
|
|
||||||
interacted = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SDLK_c: {
|
|
||||||
continueGame = true;
|
|
||||||
interacted = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PopupWindow::shouldContinue() const {
|
|
||||||
return continueGame;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PopupWindow::renderWinnerPopup(Entity::TeamLabel winner) {
|
|
||||||
|
|
||||||
SDL_RenderClear(this->renderer);
|
|
||||||
|
|
||||||
//Maybe use texture manager (changes need to be made that it does not use game::renderer automatically, but receives one instead)
|
|
||||||
this->texture = winner == Entity::TeamLabel::BLUE ?
|
|
||||||
IMG_LoadTexture(this->renderer, "assets/Player1Victory.png") :
|
|
||||||
IMG_LoadTexture(this->renderer, "assets/Player2Victory.png");
|
|
||||||
|
|
||||||
SDL_RenderCopy(this->renderer, this->texture, NULL, NULL);
|
|
||||||
|
|
||||||
SDL_RenderPresent(this->renderer);
|
|
||||||
|
|
||||||
//Error handling for debugging
|
|
||||||
const char* sdlError = SDL_GetError();
|
|
||||||
if (*sdlError != '\0') {
|
|
||||||
std::cerr << "SDL Error: " << sdlError << std::endl;
|
|
||||||
SDL_ClearError();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#include "PowerupComponent.h"
|
#include "PowerupComponent.h"
|
||||||
#include "Game.h"
|
#include "GameInternal.h"
|
||||||
#include "CollisionHandler.h"
|
#include "CollisionHandler.h"
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "HealthComponent.h"
|
#include "HealthComponent.h"
|
||||||
@ -7,51 +7,20 @@
|
|||||||
#include "Constants.h"
|
#include "Constants.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
PowerupComponent::PowerupComponent(PowerupType type)
|
PowerupComponent::PowerupComponent(std::function<void (Entity*)> func)
|
||||||
{
|
{
|
||||||
switch (type)
|
this->pickupFunc = func;
|
||||||
{
|
|
||||||
case PowerupType::HEART:
|
|
||||||
this->pickupFunc = (&PowerupComponent::heartEffect);
|
|
||||||
break;
|
|
||||||
case PowerupType::WALKINGSPEED:
|
|
||||||
this->pickupFunc = (&PowerupComponent::movementSpeedEffect);
|
|
||||||
break;
|
|
||||||
case PowerupType::SHOOTINGSPEED:
|
|
||||||
this->pickupFunc = (&PowerupComponent::atkSpeedEffect);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PowerupComponent::update()
|
void PowerupComponent::update()
|
||||||
{
|
{
|
||||||
Entity* player;
|
Entity* player;
|
||||||
if ((player = Game::collisionHandler->getAnyIntersection<Entity*>(
|
if ((player = this->entity->getManager().getGame()->collisionHandler->getAnyIntersection<Entity*>(
|
||||||
entity,
|
entity,
|
||||||
Vector2D(0, 0),
|
Vector2D(0, 0),
|
||||||
{ Entity::GroupLabel::PLAYERS },
|
{ Entity::GroupLabel::PLAYERS })) != nullptr)
|
||||||
{},
|
|
||||||
true)) != nullptr)
|
|
||||||
{
|
{
|
||||||
(this->*pickupFunc)(player);
|
(this->pickupFunc)(player);
|
||||||
this->entity->destroy();
|
this->entity->destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PowerupComponent::heartEffect(Entity* player)
|
|
||||||
{
|
|
||||||
if(player->getComponent<HealthComponent>().getHealth() < 5)
|
|
||||||
player->getComponent<HealthComponent>().modifyHealth(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PowerupComponent::movementSpeedEffect(Entity* player)
|
|
||||||
{
|
|
||||||
player->getComponent<StatEffectsComponent>().modifyStatDur(Stats::MOVEMENT_SPEED, BUFF_DURATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PowerupComponent::atkSpeedEffect(Entity* player)
|
|
||||||
{
|
|
||||||
player->getComponent<StatEffectsComponent>().modifyStatDur(Stats::ATTACK_SPEED, BUFF_DURATION);
|
|
||||||
}
|
|
||||||
@ -1,9 +1,10 @@
|
|||||||
#include "ProjectileComponent.h"
|
#include "ProjectileComponent.h"
|
||||||
|
|
||||||
#include "CollisionHandler.h"
|
#include "CollisionHandler.h"
|
||||||
#include "Components.h"
|
#include "SoundManager.h"
|
||||||
|
#include "TransformComponent.h"
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "Game.h"
|
#include "GameInternal.h"
|
||||||
#include "HealthComponent.h"
|
#include "HealthComponent.h"
|
||||||
#include "Vector2D.h"
|
#include "Vector2D.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@ -13,14 +14,14 @@ void ProjectileComponent::init()
|
|||||||
{
|
{
|
||||||
transformComponent = &entity->getComponent<TransformComponent>();
|
transformComponent = &entity->getComponent<TransformComponent>();
|
||||||
transformComponent->direction = direction;
|
transformComponent->direction = direction;
|
||||||
SoundManager::playSound(THROW_EGG);
|
SoundManager::playSound(this->entity->getManager().getGame(), "throw_egg", true, PLAY_ONCE, MAX_VOLUME, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectileComponent::update()
|
void ProjectileComponent::update()
|
||||||
{
|
{
|
||||||
distance += speed;
|
distance += speed;
|
||||||
|
|
||||||
IntersectionBitSet boundsIntersection = Game::collisionHandler->getIntersectionWithBounds(entity);
|
IntersectionBitSet boundsIntersection = this->entity->getManager().getGame()->collisionHandler->getIntersectionWithBounds(entity);
|
||||||
|
|
||||||
if ((boundsIntersection | IntersectionBitSet("1100")).all() || (boundsIntersection | IntersectionBitSet("0011")).all()) {
|
if ((boundsIntersection | IntersectionBitSet("1100")).all() || (boundsIntersection | IntersectionBitSet("0011")).all()) {
|
||||||
this->entity->destroy();
|
this->entity->destroy();
|
||||||
@ -31,12 +32,11 @@ void ProjectileComponent::update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
Entity* player;
|
Entity* player;
|
||||||
if ((player = Game::collisionHandler->getAnyIntersection<Entity*>(
|
if ((player = this->entity->getManager().getGame()->collisionHandler->getAnyIntersection<Entity*>(
|
||||||
entity,
|
entity,
|
||||||
Vector2D(0,0),
|
Vector2D(0,0),
|
||||||
{Entity::GroupLabel::PLAYERS},
|
{Entity::GroupLabel::PLAYERS},
|
||||||
{entity->getTeam()},
|
{this->owner})) != nullptr) {
|
||||||
true)) != nullptr) {
|
|
||||||
player->getComponent<HealthComponent>().modifyHealth();
|
player->getComponent<HealthComponent>().modifyHealth();
|
||||||
this->entity->destroy();
|
this->entity->destroy();
|
||||||
}
|
}
|
||||||
|
|||||||
24
src/RenderManager.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "RenderManager.h"
|
||||||
|
#include "RenderObject.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
void RenderManager::renderAll()
|
||||||
|
{
|
||||||
|
if (!this->isSorted) {
|
||||||
|
std::ranges::sort(this->renderObjects, RenderObject::ZIndexComparator());
|
||||||
|
}
|
||||||
|
for (RenderObject* obj : this->renderObjects) {
|
||||||
|
obj->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderManager::add(RenderObject* renderObject) {
|
||||||
|
this->renderObjects.emplace_back(renderObject);
|
||||||
|
this->isSorted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderManager::remove(RenderObject* renderObject)
|
||||||
|
{
|
||||||
|
this->renderObjects.erase(std::remove(this->renderObjects.begin(), this->renderObjects.end(), renderObject), this->renderObjects.end());
|
||||||
|
this->isSorted = false;
|
||||||
|
}
|
||||||
10
src/RenderObject.cpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include "RenderObject.h"
|
||||||
|
#include "RenderManager.h"
|
||||||
|
|
||||||
|
RenderObject::RenderObject(int zIndex, RenderManager& renderManager) : zIndex(zIndex), renderManager(renderManager) {
|
||||||
|
renderManager.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderObject::~RenderObject() {
|
||||||
|
this->renderManager.remove(this);
|
||||||
|
}
|
||||||
@ -4,9 +4,29 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "Game.h"
|
#include "GameInternal.h"
|
||||||
#include "AssetManager.h"
|
#include "AssetManager.h"
|
||||||
|
|
||||||
|
Mix_Music* SoundManager::loadMusic(const char* fileName)
|
||||||
|
{
|
||||||
|
auto it = this->music_cache.find(fileName);
|
||||||
|
|
||||||
|
if (it != this->music_cache.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto music = Mix_LoadMUS(fileName);
|
||||||
|
|
||||||
|
if (music == NULL)
|
||||||
|
std::cerr << "Couldn't load music '" << fileName << "'" << std::endl;
|
||||||
|
|
||||||
|
this->music_cache.emplace(fileName, music);
|
||||||
|
|
||||||
|
std::cout << "Loaded music at " << fileName << std::endl;
|
||||||
|
|
||||||
|
return music;
|
||||||
|
}
|
||||||
|
|
||||||
Mix_Chunk* SoundManager::loadSound(const char* fileName)
|
Mix_Chunk* SoundManager::loadSound(const char* fileName)
|
||||||
{
|
{
|
||||||
auto it = this->sound_cache.find(fileName);
|
auto it = this->sound_cache.find(fileName);
|
||||||
@ -18,33 +38,98 @@ Mix_Chunk* SoundManager::loadSound(const char* fileName)
|
|||||||
auto sound = Mix_LoadWAV(fileName);
|
auto sound = Mix_LoadWAV(fileName);
|
||||||
|
|
||||||
if (sound == NULL)
|
if (sound == NULL)
|
||||||
throw std::runtime_error(std::string("Couldn't load sound '") + fileName + "'");
|
std::cerr << "Couldn't load sound '" << fileName << "'" << std::endl;
|
||||||
|
|
||||||
this->sound_cache.emplace(fileName, sound);
|
this->sound_cache.emplace(fileName, sound);
|
||||||
|
|
||||||
printf("Loaded sound at '%s'\n", fileName);
|
std::cout << "Loaded sound at " << fileName << std::endl;
|
||||||
|
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundManager::playSound(SoundTypes sound)
|
void SoundManager::playSound(GameInternal* game, std::string sound, bool canOverlap, int loops, int volume, int channel)
|
||||||
{
|
{
|
||||||
switch (sound)
|
if(!canOverlap)
|
||||||
{
|
{
|
||||||
case SoundTypes::STEPS:
|
// dev needs to specify a channel for this check to work, if they set it to -1 and let sdl pick the first available
|
||||||
if (Mix_Playing(-1) != 0)
|
// channel mix_getchunk() won't work
|
||||||
break;
|
if (Mix_Playing(channel) != 0 &&
|
||||||
|
Mix_GetChunk(channel) == game->assets->getSound(sound) &&
|
||||||
if (Mix_PlayChannel(-1, Game::assets->getSound("steps"), 0) == -1) {
|
channel != -1)
|
||||||
std::cerr << "Error playing sound 'steps': " << Mix_GetError() << std::endl;
|
{
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
Mix_HaltChannel(channel);
|
||||||
|
|
||||||
case SoundTypes::THROW_EGG:
|
|
||||||
if (Mix_PlayChannel(-1, Game::assets->getSound("throw_egg"), 0) == -1) {
|
|
||||||
std::cerr << "Error playing sound 'throw_egg': " << Mix_GetError() << std::endl;
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
if(Mix_VolumeChunk(game->assets->getSound(sound), volume) == -1)
|
||||||
|
{
|
||||||
|
std::cerr << "Error adjusting volume: " << Mix_GetError() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Mix_PlayChannel(channel, game->assets->getSound(sound), loops) == -1)
|
||||||
|
{
|
||||||
|
std::cerr << "Error playing sound '" << sound << "': " << Mix_GetError() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SoundManager::playMusic(GameInternal* game, std::string music, int loops, int volume, int ms)
|
||||||
|
{
|
||||||
|
if (Mix_PlayingMusic() != 0 || Mix_Fading() == Mix_Fading::MIX_FADING_IN)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(ms > 0)
|
||||||
|
{
|
||||||
|
Mix_FadeInMusic(game->assets->getMusic(music), loops, ms);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Mix_VolumeMusic(volume) == -1)
|
||||||
|
{
|
||||||
|
std::cerr << "Error adjusting volume: " << Mix_GetError() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Mix_PlayMusic(game->assets->getMusic(music), loops) == -1)
|
||||||
|
{
|
||||||
|
std::cerr << "Error playing music '" << music << "': " << Mix_GetError() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundManager::setSoundVolume(int volume, int channel)
|
||||||
|
{
|
||||||
|
Mix_Volume(channel, volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundManager::setMusicVolume(int volume)
|
||||||
|
{
|
||||||
|
Mix_VolumeMusic(volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundManager::pauseSound(int channel)
|
||||||
|
{
|
||||||
|
Mix_Pause(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundManager::pauseMusic()
|
||||||
|
{
|
||||||
|
Mix_PauseMusic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundManager::restartSound(int channel)
|
||||||
|
{
|
||||||
|
Mix_Resume(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundManager::restartMusic()
|
||||||
|
{
|
||||||
|
Mix_ResumeMusic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundManager::fadeOutMusic(int ms)
|
||||||
|
{
|
||||||
|
if(Mix_Fading() == Mix_Fading::MIX_FADING_OUT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Mix_FadeOutMusic(ms);
|
||||||
|
}
|
||||||
|
|||||||
@ -1,60 +1,75 @@
|
|||||||
#include "SpriteComponent.h"
|
#include "SpriteComponent.h"
|
||||||
|
|
||||||
#include <SDL_timer.h>
|
#include <SDL_timer.h>
|
||||||
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "AnimationHandler.h"
|
#include "AnimationHandler.h"
|
||||||
#include "Direction.h"
|
#include "Direction.h"
|
||||||
|
#include "ProjectileComponent.h"
|
||||||
|
#include "RenderObject.h"
|
||||||
#include "TextureManager.h"
|
#include "TextureManager.h"
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "TransformComponent.h"
|
#include "TransformComponent.h"
|
||||||
#include "Game.h"
|
#include "GameInternal.h"
|
||||||
|
#include "Manager.h"
|
||||||
|
#include "VEGO.h"
|
||||||
|
|
||||||
SpriteComponent::SpriteComponent(const char* path)
|
SpriteComponent::SpriteComponent(const char* path, int zIndex) : RenderObject(zIndex, VEGO_Game().renderManager), textureXOffset(0), textureYOffset(0)
|
||||||
{
|
{
|
||||||
setTexture(path);
|
this->texturePath = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpriteComponent::SpriteComponent(const char* path, bool isAnimated)
|
SpriteComponent::SpriteComponent(const char* path, int xOffset, int yOffset, int zIndex) : RenderObject(zIndex, VEGO_Game().renderManager), textureXOffset(xOffset), textureYOffset(yOffset)
|
||||||
|
{
|
||||||
|
this->texturePath = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpriteComponent::SpriteComponent(
|
||||||
|
const char* path,
|
||||||
|
bool isAnimated,
|
||||||
|
std::map<std::string, std::unique_ptr<Animation>>* animationMap,
|
||||||
|
std::string defaultAnimation,
|
||||||
|
int zIndex) : RenderObject(zIndex, VEGO_Game().renderManager), textureXOffset(0), textureYOffset(0)
|
||||||
{
|
{
|
||||||
animated = isAnimated;
|
animated = isAnimated;
|
||||||
|
|
||||||
animations.emplace(IDLE, std::make_unique<Animation>((uint8_t)AnimationType::IDLE, 2, 200));
|
animations = animationMap;
|
||||||
animations.emplace(WALK, std::make_unique<Animation>((uint8_t)AnimationType::WALK, 2, 200));
|
|
||||||
|
|
||||||
playAnimation(IDLE);
|
playAnimation(defaultAnimation);
|
||||||
|
|
||||||
setTexture(path);
|
this->texturePath = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpriteComponent::~SpriteComponent()
|
SpriteComponent::~SpriteComponent() {}
|
||||||
{
|
|
||||||
// SDL_DestroyTexture(this->texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpriteComponent::setTexture(const char* path)
|
void SpriteComponent::setTexture(const char* path)
|
||||||
{
|
{
|
||||||
this->texture = Game::textureManager->loadTexture(path);
|
this->texture = VEGO_Game().textureManager->loadTexture(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteComponent::init()
|
void SpriteComponent::init()
|
||||||
{
|
{
|
||||||
|
setTexture(this->texturePath);
|
||||||
|
|
||||||
this->transform = &entity->getComponent<TransformComponent>();
|
this->transform = &entity->getComponent<TransformComponent>();
|
||||||
|
|
||||||
this->srcRect.x = this->srcRect.y = 0;
|
|
||||||
this->srcRect.w = transform->width;
|
this->srcRect.w = transform->width;
|
||||||
this->srcRect.h = transform->height;
|
this->srcRect.h = transform->height;
|
||||||
|
this->srcRect.x = this->textureXOffset * this->srcRect.w;
|
||||||
|
this->srcRect.y = this->textureYOffset * this->srcRect.h;;
|
||||||
|
|
||||||
this->update();
|
this->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteComponent::update()
|
void SpriteComponent::update()
|
||||||
{
|
{
|
||||||
|
// This code is not compatible for animated tiles
|
||||||
if (animated) {
|
if (animated) {
|
||||||
srcRect.x = srcRect.w * static_cast<int>((SDL_GetTicks() / speed) % frames);
|
srcRect.x = srcRect.w * static_cast<int>((SDL_GetTicks() / speed) % frames);
|
||||||
}
|
|
||||||
|
|
||||||
srcRect.y = animationIndex * transform->height;
|
srcRect.y = animationIndex * transform->height;
|
||||||
|
}
|
||||||
|
|
||||||
this->destRect.x = this->transform->position.x;
|
this->destRect.x = this->transform->position.x;
|
||||||
this->destRect.y = this->transform->position.y;
|
this->destRect.y = this->transform->position.y;
|
||||||
@ -64,14 +79,14 @@ void SpriteComponent::update()
|
|||||||
|
|
||||||
void SpriteComponent::draw()
|
void SpriteComponent::draw()
|
||||||
{
|
{
|
||||||
Game::textureManager->draw(this->texture, this->srcRect, this->destRect, this->animated && this->flipped);
|
this->entity->getManager().getGame()->textureManager->draw(VEGO_Game().renderer, this->texture, this->srcRect, this->destRect, this->animated && this->flipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteComponent::playAnimation(AnimationType type)
|
void SpriteComponent::playAnimation(std::string type)
|
||||||
{
|
{
|
||||||
this->animationIndex = animations.at(type)->index;
|
this->animationIndex = animations->at(type)->index;
|
||||||
this->frames = animations.at(type)->frames;
|
this->frames = animations->at(type)->frames;
|
||||||
this->speed = animations.at(type)->speed;
|
this->speed = animations->at(type)->speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteComponent::setDirection(Direction direction)
|
void SpriteComponent::setDirection(Direction direction)
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#include "StatEffectsComponent.h"
|
#include "StatEffectsComponent.h"
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "TransformComponent.h"
|
#include "TransformComponent.h"
|
||||||
#include "KeyboardController.h"
|
// #include "KeyboardController.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
@ -15,15 +15,15 @@ void StatEffectsComponent::update()
|
|||||||
if (this->buffs.at(i) == 0) continue;
|
if (this->buffs.at(i) == 0) continue;
|
||||||
if (this->buffs.at(i) - 1 == 0)
|
if (this->buffs.at(i) - 1 == 0)
|
||||||
{
|
{
|
||||||
this->modifyStatValue((Stats)i, BUFF_VALUE * -1);
|
this->resetStatValue((Stats)i);
|
||||||
}
|
}
|
||||||
this->buffs.at(i) -= 1;
|
this->buffs.at(i) -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatEffectsComponent::modifyStatDur(Stats stat, int duration)
|
void StatEffectsComponent::modifyStatDur(Stats stat, int duration, int value)
|
||||||
{
|
{
|
||||||
if(this->buffs.at((uint8_t)stat) == 0) this->modifyStatValue(stat, BUFF_VALUE);
|
if(this->buffs.at((uint8_t)stat) == 0) this->modifyStatValue(stat, value);
|
||||||
this->buffs.at((uint8_t)stat) += duration;
|
this->buffs.at((uint8_t)stat) += duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +35,21 @@ void StatEffectsComponent::modifyStatValue(Stats stat, int modifier) //modifier
|
|||||||
this->entity->getComponent<TransformComponent>().modifySpeed(modifier);
|
this->entity->getComponent<TransformComponent>().modifySpeed(modifier);
|
||||||
break;
|
break;
|
||||||
case Stats::ATTACK_SPEED:
|
case Stats::ATTACK_SPEED:
|
||||||
this->entity->getComponent<KeyboardController>().modifyAtkSpeed(modifier);
|
// this->entity->getComponent<KeyboardController>().modifyAtkSpeed(modifier);
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatEffectsComponent::resetStatValue(Stats stat)
|
||||||
|
{
|
||||||
|
switch (stat)
|
||||||
|
{
|
||||||
|
case Stats::MOVEMENT_SPEED:
|
||||||
|
this->entity->getComponent<TransformComponent>().resetSpeedMod();
|
||||||
|
break;
|
||||||
|
case Stats::ATTACK_SPEED:
|
||||||
|
// this->entity->getComponent<KeyboardController>().resetAtkSpeedMod();
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Game.h"
|
#include "GameInternal.h"
|
||||||
|
|
||||||
SDL_Texture* TextureManager::loadTexture(const char* fileName)
|
SDL_Texture* TextureManager::loadTexture(const char* fileName)
|
||||||
{
|
{
|
||||||
@ -12,15 +12,15 @@ SDL_Texture* TextureManager::loadTexture(const char* fileName)
|
|||||||
if (it != this->texture_cache.end()) {
|
if (it != this->texture_cache.end()) {
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
auto texture = IMG_LoadTexture(Game::renderer, fileName);
|
auto texture = IMG_LoadTexture(this->manager->getGame()->renderer, fileName);
|
||||||
if (texture == NULL) throw std::runtime_error(std::string("Couldn't load texture '") + fileName + "'");
|
if (texture == NULL) throw std::runtime_error(std::string("Couldn't load texture '") + fileName + "'");
|
||||||
this->texture_cache.emplace(std::string(fileName), texture);
|
this->texture_cache.emplace(std::string(fileName), texture);
|
||||||
printf("Loaded texture at '%s'\n", fileName);
|
printf("Loaded texture at '%s'\n", fileName);
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureManager::draw(SDL_Texture* texture, SDL_Rect src, SDL_Rect dest, bool flipped)
|
void TextureManager::draw(SDL_Renderer* renderer, SDL_Texture* texture, SDL_Rect src, SDL_Rect dest, bool flipped)
|
||||||
{
|
{
|
||||||
SDL_RendererFlip flip = flipped ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE;
|
SDL_RendererFlip flip = flipped ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE;
|
||||||
SDL_RenderCopyEx(Game::renderer, texture, &src, &dest, 0, NULL, flip);
|
SDL_RenderCopyEx(renderer, texture, &src, &dest, 0, NULL, flip);
|
||||||
}
|
}
|
||||||
@ -7,7 +7,7 @@
|
|||||||
#include "SpriteComponent.h"
|
#include "SpriteComponent.h"
|
||||||
#include "TileComponent.h"
|
#include "TileComponent.h"
|
||||||
|
|
||||||
TileComponent::TileComponent(int x, int y, int w, int h, int id)
|
TileComponent::TileComponent(int x, int y, int w, int h, int id, const std::map<int, std::pair<std::string, bool>>* textureDict)
|
||||||
{
|
{
|
||||||
this->tileRect.x = x;
|
this->tileRect.x = x;
|
||||||
this->tileRect.y = y;
|
this->tileRect.y = y;
|
||||||
@ -15,12 +15,15 @@ TileComponent::TileComponent(int x, int y, int w, int h, int id)
|
|||||||
this->tileRect.h = h;
|
this->tileRect.h = h;
|
||||||
tileID = id;
|
tileID = id;
|
||||||
|
|
||||||
auto it = textureDict.tileDictionary.find(tileID); //every id has its own distinct texture (in texturedict.h)
|
auto it = textureDict->find(tileID); //every id has its own distinct texture (in texturedict.h)
|
||||||
if (it == textureDict.tileDictionary.end()) {
|
if (it == textureDict->end()) {
|
||||||
std::cout << "it end" << std::endl;
|
std::cout << "it end" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->path = it->second.data();
|
|
||||||
|
this->collision = it->second.second;
|
||||||
|
this->tileName = it->second.first;
|
||||||
|
this->path = it->second.first.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileComponent::init()
|
void TileComponent::init()
|
||||||
@ -28,7 +31,7 @@ void TileComponent::init()
|
|||||||
this->entity->addComponent<TransformComponent>(this->tileRect.x, this->tileRect.y, this->tileRect.w, this->tileRect.h, 1);
|
this->entity->addComponent<TransformComponent>(this->tileRect.x, this->tileRect.y, this->tileRect.w, this->tileRect.h, 1);
|
||||||
this->transform = &entity->getComponent<TransformComponent>();
|
this->transform = &entity->getComponent<TransformComponent>();
|
||||||
|
|
||||||
this->entity->addComponent<SpriteComponent>(this->path);
|
this->entity->addComponent<SpriteComponent>(this->path, 0);
|
||||||
this->sprite = &entity->getComponent<SpriteComponent>();
|
this->sprite = &entity->getComponent<SpriteComponent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
#include "ColliderComponent.h"
|
#include "ColliderComponent.h"
|
||||||
#include "Constants.h"
|
#include "Constants.h"
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "Game.h"
|
#include "GameInternal.h"
|
||||||
#include "Vector2D.h"
|
#include "Vector2D.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
@ -52,25 +52,36 @@ void TransformComponent::init()
|
|||||||
|
|
||||||
void TransformComponent::update()
|
void TransformComponent::update()
|
||||||
{
|
{
|
||||||
// if(velocity.x != 0 && velocity.y != 0)
|
|
||||||
|
|
||||||
float multiplier = direction.x != 0 && direction.y != 0 ? 0.707 : 1; // normalizes vector; only works if directions are in increments of 45°
|
float multiplier = direction.x != 0 && direction.y != 0 ? 0.707 : 1; // normalizes vector; only works if directions are in increments of 45°
|
||||||
Vector2D positionChange(
|
Vector2D positionChange(
|
||||||
direction.x * speed * multiplier,
|
direction.x * this->getSpeed() * multiplier,
|
||||||
direction.y * speed * multiplier
|
direction.y * this->getSpeed() * multiplier
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: move to separate functions
|
if (this->entity->hasGroup((size_t)Entity::GroupLabel::PLAYERS)){
|
||||||
|
this->setPositionAfterCollision(positionChange);
|
||||||
|
}
|
||||||
|
|
||||||
if (this->entity->hasGroup((size_t)Entity::GroupLabel::PLAYERS)) {
|
position += positionChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransformComponent::modifySpeed(int8_t modifier)
|
||||||
|
{
|
||||||
|
this->speedMod += modifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransformComponent::setPositionAfterCollision(Vector2D& positionChange)
|
||||||
|
{
|
||||||
|
std::initializer_list<Entity::GroupLabel> colliders = { Entity::GroupLabel::MAPTILES, Entity::GroupLabel::COLLIDERS };
|
||||||
// [getAnyIntersection example code]
|
// [getAnyIntersection example code]
|
||||||
IntersectionBitSet intersections =
|
IntersectionBitSet intersections =
|
||||||
(CollisionHandler::getIntersectionWithBounds(entity, Vector2D(positionChange.x, 0)) |
|
(CollisionHandler::getIntersectionWithBounds(entity, Vector2D(positionChange.x, 0)) |
|
||||||
(Game::collisionHandler->getAnyIntersection<IntersectionBitSet>(entity, Vector2D(positionChange.x, 0), { Entity::GroupLabel::MAPTILES, Entity::GroupLabel::COLLIDERS })) &
|
(this->entity->getManager()
|
||||||
|
.getGame()->collisionHandler->getAnyIntersection<IntersectionBitSet>(entity, Vector2D(positionChange.x, 0), colliders)) &
|
||||||
IntersectionBitSet("0011")) |
|
IntersectionBitSet("0011")) |
|
||||||
(CollisionHandler::getIntersectionWithBounds(entity, Vector2D(0, positionChange.y)) |
|
(CollisionHandler::getIntersectionWithBounds(entity, Vector2D(0, positionChange.y)) |
|
||||||
(Game::collisionHandler->getAnyIntersection<IntersectionBitSet>(entity, Vector2D(0, positionChange.y), { Entity::GroupLabel::MAPTILES, Entity::GroupLabel::COLLIDERS })) &
|
(this->entity->getManager()
|
||||||
|
.getGame()->collisionHandler->getAnyIntersection<IntersectionBitSet>(entity, Vector2D(0, positionChange.y), colliders)) &
|
||||||
IntersectionBitSet("1100"));
|
IntersectionBitSet("1100"));
|
||||||
|
|
||||||
if (intersections.test((size_t)Direction::LEFT) || intersections.test((size_t)Direction::RIGHT))
|
if (intersections.test((size_t)Direction::LEFT) || intersections.test((size_t)Direction::RIGHT))
|
||||||
@ -79,12 +90,4 @@ void TransformComponent::update()
|
|||||||
if (intersections.test((size_t)Direction::UP) || intersections.test((size_t)Direction::DOWN))
|
if (intersections.test((size_t)Direction::UP) || intersections.test((size_t)Direction::DOWN))
|
||||||
positionChange.y = 0;
|
positionChange.y = 0;
|
||||||
// [getAnyIntersection example code]
|
// [getAnyIntersection example code]
|
||||||
}
|
|
||||||
|
|
||||||
position += positionChange;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransformComponent::modifySpeed(int8_t modifier)
|
|
||||||
{
|
|
||||||
this->speed += modifier;
|
|
||||||
}
|
}
|
||||||
36
src/main.cpp
@ -1,12 +1,12 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
#include "VEGO.h"
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "Game.h"
|
#include "GameInternal.h"
|
||||||
#include "Constants.h"
|
#include "Constants.h"
|
||||||
#include "PopupWindow.h"
|
|
||||||
|
|
||||||
Game* game = nullptr;
|
GameInternal* vego::game = nullptr;
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
@ -18,16 +18,15 @@ int main(int argc, char* argv[])
|
|||||||
Uint32 frameStart;
|
Uint32 frameStart;
|
||||||
int frameTime;
|
int frameTime;
|
||||||
|
|
||||||
game = new Game();
|
vego::game = new GameInternal();
|
||||||
|
|
||||||
game->init("No_Name_Chicken_Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_SIZE_WIDTH, SCREEN_SIZE_HEIGHT, false);
|
vego::game->init("No_Name_Chicken_Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_SIZE_WIDTH, SCREEN_SIZE_HEIGHT, false);
|
||||||
while(playing) {
|
while (vego::game->isRunning()) {
|
||||||
while (game->running()) {
|
|
||||||
frameStart = SDL_GetTicks();
|
frameStart = SDL_GetTicks();
|
||||||
|
|
||||||
game->handleEvents();
|
vego::game->handleEvents();
|
||||||
game->update();
|
vego::game->update();
|
||||||
game->render();
|
vego::game->render();
|
||||||
|
|
||||||
frameTime = SDL_GetTicks() - frameStart;
|
frameTime = SDL_GetTicks() - frameStart;
|
||||||
|
|
||||||
@ -35,23 +34,8 @@ int main(int argc, char* argv[])
|
|||||||
SDL_Delay(frameDelay - frameTime);
|
SDL_Delay(frameDelay - frameTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Entity::TeamLabel winner = game->getWinner();
|
|
||||||
|
|
||||||
PopupWindow popupWindow("Game over", winner == Entity::TeamLabel::BLUE ?
|
vego::game->clean();
|
||||||
"Player1 won! Press 'C' to continue or 'Q' to quit." :
|
|
||||||
"Player2 won! Press 'C' to continue or 'Q' to quit.");
|
|
||||||
|
|
||||||
popupWindow.renderWinnerPopup(winner);
|
|
||||||
|
|
||||||
while (!popupWindow.interacted) {
|
|
||||||
popupWindow.handleWinnerEvents();
|
|
||||||
SDL_Delay(10);
|
|
||||||
}
|
|
||||||
playing = popupWindow.shouldContinue();
|
|
||||||
game->refreshPlayers();
|
|
||||||
}
|
|
||||||
|
|
||||||
game->clean();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||