Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F133957
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
24 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8b53919..1372c3c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,10 +1,10 @@
cmake_minimum_required(VERSION 3.14)
project(SDL_Game)
set(CMAKE_CXX_STANDARD 17)
include_directories(include)
find_package(Boost REQUIRED COMPONENTS filesystem)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(lib)
link_libraries(mingw32 SDL2main SDL2 SDL2_image SDL2_gfx)
-add_executable(SDL_Game src/main.cpp src/Game.cpp src/Game.h src/Entity.h src/Component.h src/System.h src/systems/RenderSystem.cpp src/systems/RenderSystem.h src/components/Visibility.cpp src/components/Visibility.h src/components/Velocity.cpp src/components/Velocity.h src/systems/MovementSystem.cpp src/systems/MovementSystem.h src/components/Position.h src/components/PathIndex.h src/GameData.h src/components/Speed.h src/components/Sequence.cpp src/components/Sequence.h src/components/Kind.h src/systems/SpawnSystem.cpp src/systems/SpawnSystem.h src/GameData.cpp src/components/Action.h src/systems/EventSystem.cpp src/systems/EventSystem.h src/components/Draggable.h src/systems/DraggingSystem.cpp src/systems/DraggingSystem.h src/Settings.h src/components/Type.h src/systems/RemoveEntitiesSystem.cpp src/systems/RemoveEntitiesSystem.h src/eventComponents/RemoveEntityEvent.h src/eventComponents/MoveEntityEvent.h src/systems/HandleMoveEntitiySystem.cpp src/systems/HandleMoveEntitiySystem.h src/components/Range.h)
+add_executable(SDL_Game src/main.cpp src/Game.cpp src/Game.h src/Entity.h src/Component.h src/System.h src/systems/RenderSystem.cpp src/systems/RenderSystem.h src/components/Visibility.cpp src/components/Visibility.h src/components/Velocity.cpp src/components/Velocity.h src/systems/MovementSystem.cpp src/systems/MovementSystem.h src/components/Position.h src/components/PathIndex.h src/GameData.h src/components/Speed.h src/components/Sequence.cpp src/components/Sequence.h src/components/Kind.h src/systems/SpawnSystem.cpp src/systems/SpawnSystem.h src/GameData.cpp src/components/Action.h src/systems/EventSystem.cpp src/systems/EventSystem.h src/components/Draggable.h src/systems/DraggingSystem.cpp src/systems/DraggingSystem.h src/Settings.h src/components/Type.h src/systems/RemoveEntitiesSystem.cpp src/systems/RemoveEntitiesSystem.h src/eventComponents/RemoveEntityEvent.h src/eventComponents/MoveEntityEvent.h src/systems/HandleMoveEntitiySystem.cpp src/systems/HandleMoveEntitiySystem.h src/components/Range.h src/components/RangeShadow.h)
target_link_libraries(SDL_Game ${Boost_LIBRARIES})
\ No newline at end of file
diff --git a/src/Component.h b/src/Component.h
index 8ab6c76..1bd14a4 100644
--- a/src/Component.h
+++ b/src/Component.h
@@ -1,29 +1,29 @@
//
// Created by Ido Mozes on 20/06/2019.
//
#ifndef SDL2_GAME_COMPONENT_H
#define SDL2_GAME_COMPONENT_H
struct Point {
short X;
short Y;
};
class Entity;
enum ComponentType {
- VISIBILITY, POSITION, VELOCITY, SPEED, ACCELERATION, PATH_INDEX, HEALTH, KIND, TYPE,RANGE, DAMAGE, PIERCE, SPREAD, SEQUENCE, ACTION, DRAGGABLE,
+ VISIBILITY, POSITION, VELOCITY, SPEED, ACCELERATION, PATH_INDEX, HEALTH, KIND, TYPE,RANGE, DAMAGE, PIERCE, SPREAD, SEQUENCE, ACTION, DRAGGABLE,RANGE_SHADOW,
MOVE_ENTITY_EVENT, REMOVE_ENTITY_EVENT,
LENGTH
};
class Component {
public:
Component() = default;
virtual ~Component() = default;
};
#endif //SDL2_GAME_COMPONENT_H
diff --git a/src/Game.cpp b/src/Game.cpp
index 195b2de..1287469 100644
--- a/src/Game.cpp
+++ b/src/Game.cpp
@@ -1,124 +1,124 @@
//
// Created by Ido Mozes on 18/06/2019.
//
#include <array>
#include "Game.h"
using namespace boost::filesystem;
Game::Game(bool fullscreen, float mapScale) {
gameData.mapScale = mapScale;
gameData.fullscreen = fullscreen;
path p = path("../assets/Bloons");
directory_iterator it{p};
for (auto &p :it) {
gameData.assets[p.path().filename().string().substr(0, p.path().filename().string().length() - 4)] = IMG_Load(
p.path().string().c_str());
}
gameData.assets["map"] = IMG_Load("../assets/map0.jpg");
gameData.assets["upgrade_bar"] = IMG_Load("../assets/upgrade_bar.jpg");
gameData.assets["upgrade_bar2"] = IMG_Load("../assets/upgrade_bar2.jpg");
gameData.assets["menu"] = IMG_Load("../assets/menu.jpg");
gameData.assets["Super_Monkey"] = IMG_Load("../assets/Super_Monkey.png");
gameData.assets["Sniper_Monkey"] = IMG_Load("../assets/Sniper_Monkey.png");
renderSystem = new RenderSystem();
renderSystem->init(gameData);
loadMap();
std::initializer_list<std::pair<std::string, Point>> sprites[]{
{{"map", {SIDEBAR_WIDTH, 0}}},
{},
{{"upgrade_bar", {0, 0}}, {"menu", {MAP_WIDTH + SIDEBAR_WIDTH, 0}}},
{}
};
for (int i = 0; i < N_LAYERS; i++) {
for (auto &sprite :sprites[i]) {
auto spriteEntity = new Entity();
spriteEntity->addComponent<Visibility>(gameData.renderer, gameData.assets[sprite.first],
SDL_Rect{sprite.second.X, sprite.second.Y,
gameData.assets[sprite.first]->w,
gameData.assets[sprite.first]->h});
layers[i].emplace_back(spriteEntity);
}
}
auto button = new Entity();
button->addComponent<Kind>("Super_Monkey");
button->addComponent<Visibility>(gameData.renderer, gameData.assets["Super_Monkey"],
SDL_Rect{SIDEBAR_WIDTH + MAP_WIDTH + 10, 10,
int(gameData.assets["Super_Monkey"]->w / 1.5), 0});
button->addComponent<Action>(DRAG);
button->addComponent<Range>(200);
layers[MENU_LAYER].emplace_back(button);
button = new Entity();
button->addComponent<Kind>("Sniper_Monkey");
button->addComponent<Visibility>(gameData.renderer, gameData.assets["Sniper_Monkey"],
SDL_Rect{SIDEBAR_WIDTH + MAP_WIDTH + 100, 10,
int(gameData.assets["Sniper_Monkey"]->w / 1.5), 0});
button->addComponent<Action>(DRAG);
button->addComponent<Range>(50);
layers[MENU_LAYER].emplace_back(button);
- auto s = new Entity();
- s->addComponent<Sequence>(100, 10, 0);
- s->addComponent<Kind>(std::string("Ceramic"));
- s->addComponent<Speed>(3.5);
- layers[GAME_LAYER].emplace_back(s);
- s = new Entity();
- s->addComponent<Sequence>(100, 10, 60 * 5);
- s->addComponent<Kind>(std::string("Blue"));
- s->addComponent<Speed>(1.5);
- layers[GAME_LAYER].emplace_back(s);
+// auto s = new Entity();
+// s->addComponent<Sequence>(100, 10, 0);
+// s->addComponent<Kind>(std::string("Ceramic"));
+// s->addComponent<Speed>(3.5);
+// layers[GAME_LAYER].emplace_back(s);
+// s = new Entity();
+// s->addComponent<Sequence>(100, 10, 60 * 5);
+// s->addComponent<Kind>(std::string("Blue"));
+// s->addComponent<Speed>(1.5);
+// layers[GAME_LAYER].emplace_back(s);
systems.emplace_back(new EventSystem);
systems.emplace_back(new SpawnSystem);
systems.emplace_back(new DraggingSystem);
systems.emplace_back(new MovementSystem);
systems.emplace_back(new HandleMoveEntitiySystem);
systems.emplace_back(new RemoveEntitiesSystem);
systems.emplace_back(renderSystem);
}
Game::~Game() {
SDL_Quit();
}
void Game::update() {
for (auto &system : systems) {
system->update(layers, gameData);
}
}
void Game::loadMap() {
std::string fileName = "../assets/map" + std::to_string(gameData.map);
std::ifstream obstaclesFile(fileName + "_obstacles.data", std::ios::binary);
int x = 0, y = 0;
for (int i = 0; i < ceilf(MAP_WIDTH * MAP_HEIGHT / 8.0); ++i) {
unsigned char byte;
obstaclesFile.read((char *) &byte, 1);
for (int j = 0; j < 8; ++j) {
char bit = (byte & 2 << j) >> j;
gameData.mapData[x][y] = bit;
x++;
if (x == MAP_WIDTH) {
x = 0;
y++;
}
if (x * y >= MAP_WIDTH * MAP_HEIGHT)
goto readPathFile;
}
}
readPathFile:
gameData.path.clear();
std::ifstream pathFile(fileName + "_path.data", std::ios::binary);
unsigned int length;
pathFile.read((char *) &gameData.startingPoint, 4);
pathFile.read((char *) &length, 4);
gameData.path.resize(length);
pathFile.read(&gameData.path[0], length);
pathFile.read((char *) &gameData.finishPoint, 4);
}
diff --git a/src/GameData.h b/src/GameData.h
index 3013f1a..3a544d9 100644
--- a/src/GameData.h
+++ b/src/GameData.h
@@ -1,39 +1,40 @@
//
// Created by Ido Mozes on 03/07/2019.
//
#ifndef SDL_GAME_GAMEDATA_H
#define SDL_GAME_GAMEDATA_H
#include <vector>
#include <memory>
#include <unordered_map>
#include "Component.h"
#include "Settings.h"
#include "SDL.h"
constexpr char FREE = 0;
constexpr char OBSTACLE = 1;
constexpr char TOWER = 2;
constexpr char BLOON = 3;
class GameData {
public:
bool isRunning = true;
bool isDragging = false;
int level = 0;
int map = 0;
float mapScale = 1.5;
bool fullscreen;
std::vector<char> path;
char mapData[MAP_WIDTH][MAP_HEIGHT];
Point startingPoint;
Point finishPoint;
std::unordered_map<std::string, SDL_Surface *> assets;
SDL_Window *window = nullptr;
SDL_Renderer *renderer = nullptr;
std::shared_ptr<Entity> selected;
+ bool selectedHasRangeShadow = false;
~GameData();
};
#endif //SDL_GAME_GAMEDATA_H
diff --git a/src/Settings.h b/src/Settings.h
index dca535e..4fecf71 100644
--- a/src/Settings.h
+++ b/src/Settings.h
@@ -1,15 +1,15 @@
//
// Created by Ido Mozes on 09/07/2019.
//
#ifndef SDL_GAME_SETTINGS_H
#define SDL_GAME_SETTINGS_H
-enum Layers{
- BACKGROUND_LAYER,GAME_LAYER,MENU_LAYER,
+enum Layers {
+ BACKGROUND_LAYER, SHADOW_LAYER, GAME_LAYER, MENU_LAYER,
N_LAYERS
};
constexpr int SIDEBAR_WIDTH = 150;
constexpr int MENU_WIDTH = 250;
constexpr int MAP_WIDTH = 686;
constexpr int MAP_HEIGHT = 511;
#endif //SDL_GAME_SETTINGS_H
diff --git a/src/System.h b/src/System.h
index b86504d..4098306 100644
--- a/src/System.h
+++ b/src/System.h
@@ -1,39 +1,40 @@
//
// Created by Ido Mozes on 23/06/2019.
//
#ifndef SDL2_GAME_SYSTEM_H
#define SDL2_GAME_SYSTEM_H
#include <initializer_list>
#include <vector>
#include <cmath>
#include "Entity.h"
#include "GameData.h"
#include "components/Sequence.h"
#include "components/Speed.h"
#include "components/Kind.h"
#include "components/Position.h"
#include "components/Visibility.h"
#include "components/PathIndex.h"
#include "components/Velocity.h"
#include "components/Draggable.h"
#include "components/Action.h"
#include "components/Range.h"
+#include "components/RangeShadow.h"
#include "eventComponents/MoveEntityEvent.h"
#include "eventComponents/RemoveEntityEvent.h"
typedef std::vector<std::shared_ptr<Entity>> Entities;
inline void
operator+=(Entities &originalVector, Entities &newVector) {
originalVector.insert(originalVector.end(), std::make_move_iterator(newVector.begin()),
std::make_move_iterator(newVector.end()));
}
class System {
public:
virtual void update(Entities *entities, GameData &gameData) = 0;
};
#endif //SDL2_GAME_SYSTEM_H
diff --git a/src/components/Action.h b/src/components/Action.h
index 38cc02a..dc31713 100644
--- a/src/components/Action.h
+++ b/src/components/Action.h
@@ -1,28 +1,28 @@
//
// Created by Ido Mozes on 08/07/2019.
//
#ifndef SDL_GAME_ACTION_H
#define SDL_GAME_ACTION_H
#include "../Component.h"
enum ActionType {
- DRAG, CLICK, DROP, CHOOSE
+ DRAG, CLICK, DROP, SELECT
};
class Action : public Component {
public:
bool disabled;
ActionType actionType;
static constexpr ComponentType type = ComponentType::ACTION;
explicit Action(ActionType actionType, bool disabled = false) :actionType(actionType),
disabled(disabled) {}
~Action() override = default;
};
#endif //SDL_GAME_ACTION_H
diff --git a/src/components/RangeShadow.h b/src/components/RangeShadow.h
new file mode 100644
index 0000000..1dc0d14
--- /dev/null
+++ b/src/components/RangeShadow.h
@@ -0,0 +1,22 @@
+//
+// Created by Ido Mozes on 10/07/2019.
+//
+
+#ifndef SDL_GAME_RANGESHADOW_H
+#define SDL_GAME_RANGESHADOW_H
+
+#include "../Component.h"
+#include <memory>
+
+class RangeShadow : public Component {
+
+public:
+ std::shared_ptr<Entity> entity;
+ static constexpr ComponentType type = ComponentType::RANGE_SHADOW;
+
+ RangeShadow(std::shared_ptr<Entity> &entity) : entity(entity) {};
+
+ ~RangeShadow() override = default;
+};
+
+#endif //SDL_GAME_RANGESHADOW_H
diff --git a/src/systems/EventSystem.cpp b/src/systems/EventSystem.cpp
index 31d020f..7854e84 100644
--- a/src/systems/EventSystem.cpp
+++ b/src/systems/EventSystem.cpp
@@ -1,116 +1,125 @@
//
// Created by Ido Mozes on 08/07/2019.
//
#include "EventSystem.h"
void EventSystem::update(Entities *layers, GameData &gameData) {
SDL_PumpEvents();
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT: {
gameData.isRunning = false;
break;
}
case SDL_MOUSEBUTTONDOWN: {
if (!gameData.isDragging)
gameData.selected.reset();
int mouseX, mouseY, originalMouseX;
SDL_GetMouseState(&mouseX, &mouseY);
mouseX = originalMouseX = int(mouseX / gameData.mapScale);
mouseY = int(mouseY / gameData.mapScale);
bool entityClicked = false;
Entities newEntities[N_LAYERS];
for (int i = N_LAYERS - 1; i >= 0; --i) {
for (auto &entity: layers[i]) {
if (auto components = entity->getComponents<Action, Visibility>()) {
auto[action, visibility] = components.value();
if (action.disabled or (action.actionType != DROP and gameData.isDragging))
continue;
int entityX, entityY, w, h;
SDL_Rect *dstRect = visibility.getDstRect();
entityX = dstRect->x;
entityY = dstRect->y;
w = dstRect->w;
h = dstRect->h;
if (auto positionP = entity->getComponent<Position>()) {
auto &position = *positionP;
entityX = int(position.getX() - w / 2.0);
entityY = int(position.getY() - h / 2.0);
mouseX = originalMouseX - SIDEBAR_WIDTH;
} else
mouseX = originalMouseX;
if (entityX <= mouseX and mouseX <= entityX + w and entityY <= mouseY and
mouseY <= entityY + h) {
switch (action.actionType) {
case DRAG: {
auto &kind = *entity->getComponent<Kind>();
auto &range = *entity->getComponent<Range>();
auto draggable = new Entity();
SDL_Surface *surface = gameData.assets[kind.kind];
draggable->addComponent<Visibility>(gameData.renderer, surface, SDL_Rect{
originalMouseX - int(surface->w / 4.0), mouseY - int(surface->h / 4.0),
int(surface->w / 1.5), int(surface->h / 1.5)});
draggable->addComponent<Draggable>();
draggable->addComponent<Action>(DROP);
draggable->addComponent<Kind>(kind);
draggable->addComponent<Range>(range);
std::shared_ptr<Entity> ptr(draggable);
gameData.selected = ptr;
newEntities[MENU_LAYER].emplace_back(ptr);
gameData.isDragging = true;
+ gameData.selectedHasRangeShadow = false;
goto entityClicked;
}
case CLICK: {
goto entityClicked;
}
case DROP: {
auto &draggable = *entity->getComponent<Draggable>();
if (draggable.isPlaceable) {
entity->removeComponent<Draggable>();
- entity->getComponent<Action>()->actionType = CLICK;
+ entity->getComponent<Action>()->actionType = SELECT;
gameData.isDragging = false;
for (int x = std::max(mouseX - SIDEBAR_WIDTH - 20, 0);
x < std::min(mouseX - SIDEBAR_WIDTH + 21, MAP_WIDTH); ++x) {
for (int y = std::max(mouseY - 20, 0);
y < std::min(mouseY + 21, MAP_HEIGHT); ++y) {
if (gameData.mapData[x][y] == FREE)
gameData.mapData[x][y] = TOWER;
}
}
- if (i == MENU_LAYER)
+ if (i == MENU_LAYER){
+ gameData.selectedHasRangeShadow=true;
+ auto rangeShadow = new Entity();
+ rangeShadow->addComponent<RangeShadow>(entity);
+ newEntities[SHADOW_LAYER].emplace_back(rangeShadow);
entity->addComponent<MoveEntityEvent>(GAME_LAYER);
+ }
+
}
goto entityClicked;
}
- case CHOOSE: {
+ case SELECT: {
+ gameData.selected = entity;
+ gameData.selectedHasRangeShadow=true;
goto entityClicked;
}
}
}
}
}
}
entityClicked:
for (int i = 0; i < N_LAYERS; ++i) {
if (!newEntities[i].empty())
layers[i] += newEntities[i];
}
break;
}
default:
break;
}
}
}
diff --git a/src/systems/RenderSystem.cpp b/src/systems/RenderSystem.cpp
index 876055a..163899b 100644
--- a/src/systems/RenderSystem.cpp
+++ b/src/systems/RenderSystem.cpp
@@ -1,61 +1,71 @@
//
// Created by Ido Mozes on 23/06/2019.
//
#include "RenderSystem.h"
#include "../components/Visibility.h"
#include "../components/Position.h"
void RenderSystem::init(GameData &gameData) {
if (gameData.window != nullptr)
SDL_DestroyWindow(gameData.window);
if (gameData.renderer != nullptr)
SDL_DestroyRenderer(gameData.renderer);
- gameData.window = SDL_CreateWindow("BloonsTD", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, // NOLINT(hicpp-signed-bitwise)
+ gameData.window = SDL_CreateWindow("BloonsTD", SDL_WINDOWPOS_CENTERED,
+ SDL_WINDOWPOS_CENTERED, // NOLINT(hicpp-signed-bitwise)
int((MAP_WIDTH + SIDEBAR_WIDTH + MENU_WIDTH) * gameData.mapScale),
- int(MAP_HEIGHT * gameData.mapScale), gameData.fullscreen ? SDL_WINDOW_FULLSCREEN : 0);
+ int(MAP_HEIGHT * gameData.mapScale),
+ gameData.fullscreen ? SDL_WINDOW_FULLSCREEN : 0);
gameData.renderer = SDL_CreateRenderer(gameData.window, -1, 0);
SDL_SetRenderDrawColor(gameData.renderer, 255, 255, 255, 255);
}
void RenderSystem::update(Entities *layers, GameData &gameData) {
SDL_RenderClear(gameData.renderer);
for (int i = 0; i < N_LAYERS; ++i) {
for (auto &entity: layers[i]) {
- if (auto visibilityP = entity->getComponent<Visibility>()) {
+ auto rangeShadowP = entity->getComponent<RangeShadow>();
+ auto ¤tEntity = (rangeShadowP and rangeShadowP->entity == gameData.selected) ? rangeShadowP->entity
+ : entity;
+
+ if (auto visibilityP = currentEntity->getComponent<Visibility>()) {
auto &visibility = *visibilityP;
- auto positionP = entity->getComponent<Position>();
- SDL_Rect * dstRect = visibility.getDstRect();
+ auto positionP = currentEntity->getComponent<Position>();
+ SDL_Rect *dstRect = visibility.getDstRect();
SDL_Rect r = {int(dstRect->x * gameData.mapScale), int(dstRect->y * gameData.mapScale),
int(dstRect->w * gameData.mapScale), int(dstRect->h * gameData.mapScale)};
if (positionP) {
auto &position = *positionP;
- r.x = int((position.getX() + SIDEBAR_WIDTH) * gameData.mapScale -r.w / 2.0);
- r.y = int(position.getY() * gameData.mapScale -r.h / 2.0);
+ r.x = int((position.getX() + SIDEBAR_WIDTH) * gameData.mapScale - r.w / 2.0);
+ r.y = int(position.getY() * gameData.mapScale - r.h / 2.0);
}
- SDL_RenderCopy(gameData.renderer, visibility.getTexture(), nullptr, &r);
- if (gameData.selected == entity) {
- int entityX, entityY;
+
+ if (gameData.selected == currentEntity and
+ ((gameData.selectedHasRangeShadow and currentEntity != entity) or
+ (!gameData.selectedHasRangeShadow and currentEntity == entity))) {
+ int currentEntityX, currentEntityY;
if (positionP) {
- entityX = r.x;
- entityY = r.y;
+ currentEntityX = r.x;
+ currentEntityY = r.y;
} else {
- entityX = r.x + int((dstRect->w / 2.0) * gameData.mapScale);
- entityY = r.y + int((dstRect->h / 2.0) * gameData.mapScale);
+ currentEntityX = r.x + int((dstRect->w / 2.0) * gameData.mapScale);
+ currentEntityY = r.y + int((dstRect->h / 2.0) * gameData.mapScale);
}
- auto draggableP = entity->getComponent<Draggable>();
+ auto draggableP = currentEntity->getComponent<Draggable>();
bool isRed = draggableP ? !draggableP->isPlaceable : false;
- float range = entity->getComponent<Range>()->range;
- filledCircleRGBA(gameData.renderer, entityX, entityY, range, isRed ? 255 : 0, 0, 0, 100);
- aacircleRGBA(gameData.renderer, entityX, entityY, range, isRed ? 255 : 0, 0, 0, 150);
+ float range = currentEntity->getComponent<Range>()->range;
+ filledCircleRGBA(gameData.renderer, currentEntityX, currentEntityY, range, isRed ? 255 : 0, 0, 0,
+ 100);
+ aacircleRGBA(gameData.renderer, currentEntityX, currentEntityY, range, isRed ? 255 : 0, 0, 0, 150);
}
+ if (entity == currentEntity)
+ SDL_RenderCopy(gameData.renderer, visibility.getTexture(), nullptr, &r);
}
}
}
-
SDL_RenderPresent(gameData.renderer);
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Wed, Jun 17, 9:11 PM (1 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
72397
Default Alt Text
(24 KB)
Attached To
Mode
R74 BloonsTD
Attached
Detach File
Event Timeline