Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F134367
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
45 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e46f7c2..d1baa6c 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/components/Range.h src/components/RangeShadow.h src/Physics.cpp src/Physics.h src/components/Strategy.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/BloonsSpawnSystem.cpp src/systems/BloonsSpawnSystem.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/components/Range.h src/components/RangeShadow.h src/Physics.cpp src/Physics.h src/components/Strategy.h src/systems/CollisionSystem.cpp src/systems/CollisionSystem.h src/systems/ShotsSpawnSystem.cpp src/systems/ShotsSpawnSystem.h)
target_link_libraries(SDL_Game ${Boost_LIBRARIES})
\ No newline at end of file
diff --git a/src/Game.cpp b/src/Game.cpp
index 83179f9..23c2f12 100644
--- a/src/Game.cpp
+++ b/src/Game.cpp
@@ -1,134 +1,144 @@
//
// 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());
}
p = path("../assets/Sprites");
it = directory_iterator{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");
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{int(sprite.second.X), int(sprite.second.Y),
gameData.assets[sprite.first]->w,
gameData.assets[sprite.first]->h});
layers[i].emplace_back(spriteEntity);
}
}
auto tower = new Entity();
tower->addComponent<Kind>("Super_Monkey");
tower->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});
tower->addComponent<Action>(DRAG);
tower->addComponent<Range>(100);
layers[MENU_LAYER].emplace_back(tower);
tower = new Entity();
tower->addComponent<Kind>("Sniper_Monkey");
tower->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});
tower->addComponent<Action>(DRAG);
tower->addComponent<Range>(30);
layers[MENU_LAYER].emplace_back(tower);
auto s = new Entity();
s->addComponent<Sequence>(100, 10, 0);
s->addComponent<Kind>(std::string("Ceramic"));
s->addComponent<Type>(SEQUENCE_T);
s->addComponent<Speed>(3.5);
- layers[GAME_LAYER].emplace_back(s);
+ layers[SEQUENCES_LAYER].emplace_back(s);
s = new Entity();
s->addComponent<Sequence>(100, 10, 60 * 5);
s->addComponent<Kind>(std::string("Blue"));
s->addComponent<Type>(SEQUENCE_T);
s->addComponent<Speed>(1.5);
- layers[GAME_LAYER].emplace_back(s);
+ layers[SEQUENCES_LAYER].emplace_back(s);
+ s = new Entity();
+ s->addComponent<Sequence>(1000, 0.5);
+ s->addComponent<Kind>(std::string("Pink"));
+ s->addComponent<Type>(SEQUENCE_T);
+ s->addComponent<Speed>(4.5);
+ layers[SEQUENCES_LAYER].emplace_back(s);
- systems.emplace_back(new SpawnSystem);
+ systems.emplace_back(new BloonsSpawnSystem);
+ systems.emplace_back(new ShotsSpawnSystem);
systems.emplace_back(new EventSystem);
systems.emplace_back(new DraggingSystem);
+ systems.emplace_back(new CollisionSystem);
systems.emplace_back(new MovementSystem);
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;
TempPoint startingPoint, finishPoint;
pathFile.read((char *) &startingPoint, 4);
pathFile.read((char *) &length, 4);
gameData.path.resize(length);
pathFile.read(&gameData.path[0], length);
pathFile.read((char *) &finishPoint, 4);
gameData.startingPoint = {float(startingPoint.X), float(startingPoint.Y)};
gameData.finishPoint = {float(finishPoint.X), float(finishPoint.Y)};
}
diff --git a/src/Game.h b/src/Game.h
index 5a9cee5..9f2a5b7 100644
--- a/src/Game.h
+++ b/src/Game.h
@@ -1,47 +1,49 @@
//
// Created by Ido Mozes on 18/06/2019.
//
#ifndef SDL2_GAME_GAME_H
#define SDL2_GAME_GAME_H
#include <iostream>
#include <cmath>
#include <fstream>
#include <memory>
#include <vector>
#include "SDL.h"
#include "SDL_image.h"
#include <comdef.h>
#include "Entity.h"
#include "System.h"
#include "systems/RenderSystem.h"
#include "systems/MovementSystem.h"
#include "systems/EventSystem.h"
-#include "systems/SpawnSystem.h"
+#include "systems/BloonsSpawnSystem.h"
+#include "systems/ShotsSpawnSystem.h"
#include "systems/DraggingSystem.h"
#include "systems/RemoveEntitiesSystem.h"
+#include "systems/CollisionSystem.h"
#include "GameData.h"
#include "boost/filesystem.hpp"
#include <iostream>
struct TempPoint{short X;short Y;};
class Game {
std::vector<std::unique_ptr<System>> systems;
Entities layers[N_LAYERS];
RenderSystem * renderSystem;
GameData gameData;
public:
explicit Game(bool fullscreen, float mapScale=1.5);
~Game();
void update();
bool running() { return gameData.isRunning; }
void loadMap();
};
#endif //SDL2_GAME_GAME_H
diff --git a/src/Settings.h b/src/Settings.h
index 8b683a2..65e3f60 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, SHADOW_LAYER,SHOTS_LAYER, GAME_LAYER, MENU_LAYER,
+ BACKGROUND_LAYER,SEQUENCES_LAYER, SHADOW_LAYER, SHOTS_LAYER, TOWERS_LAYER, BLOONS_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/components/Sequence.h b/src/components/Sequence.h
index 18ed930..4a26ca3 100644
--- a/src/components/Sequence.h
+++ b/src/components/Sequence.h
@@ -1,31 +1,31 @@
//
// Created by Ido Mozes on 07/07/2019.
//
#ifndef SDL_GAME_SEQUENCE_H
#define SDL_GAME_SEQUENCE_H
#include <cmath>
#include "../Component.h"
constexpr int SEQUENCE_FINISHED = -1;
class Sequence : public Component {
int amount;
float interval;
float timeToRecharge;
int amountReady;
public:
static constexpr ComponentType type = ComponentType::SEQUENCE;
- Sequence(int amount, float interval, float delay) : amount(amount), interval(interval),
+ Sequence(int amount, float interval, float delay=0) : amount(amount), interval(interval),
timeToRecharge(delay ? delay : interval),
amountReady(delay == 0) {}
~Sequence() override = default;
int getAmountReady();
};
#endif //SDL_GAME_SEQUENCE_H
diff --git a/src/systems/BloonsSpawnSystem.cpp b/src/systems/BloonsSpawnSystem.cpp
new file mode 100644
index 0000000..47d1131
--- /dev/null
+++ b/src/systems/BloonsSpawnSystem.cpp
@@ -0,0 +1,30 @@
+//
+// Created by Ido Mozes on 07/07/2019.
+//
+
+#include "BloonsSpawnSystem.h"
+
+
+void BloonsSpawnSystem::update(Entities *layers, GameData &gameData) {
+ for (auto &entity: layers[SEQUENCES_LAYER]) {
+ auto[sequence, kind, speed] = entity->getComponents<Sequence, Kind, Speed>().value();
+ int amount = sequence.getAmountReady();
+ for (int j = 0; j < amount; ++j) {
+ auto *bloon = new Entity();
+ bloon->addComponent<Type>(BLOON_T);
+ bloon->addComponent<Kind>(kind);
+ bloon->addComponent<Position>(gameData.startingPoint.X, gameData.startingPoint.Y);
+ bloon->addComponent<PathIndex>(0);
+ bloon->addComponent<Speed>(speed.value);
+
+ SDL_Surface *surface = gameData.assets[kind.value];
+ bloon->addComponent<Visibility>(gameData.renderer, surface,
+ SDL_Rect{int(gameData.startingPoint.X),
+ int(gameData.startingPoint.Y),
+ int(surface->w / 3), int(surface->h / 3)});
+ bloon->addComponent<Range>(std::max(surface->w / 6, surface->h / 6));
+ layers[BLOONS_LAYER].emplace_back(bloon);
+ }
+ }
+
+}
diff --git a/src/systems/SpawnSystem.h b/src/systems/BloonsSpawnSystem.h
similarity index 54%
rename from src/systems/SpawnSystem.h
rename to src/systems/BloonsSpawnSystem.h
index 94efc41..ee9c954 100644
--- a/src/systems/SpawnSystem.h
+++ b/src/systems/BloonsSpawnSystem.h
@@ -1,18 +1,17 @@
//
// Created by Ido Mozes on 07/07/2019.
//
-#ifndef SDL_GAME_SPAWNSYSTEM_H
-#define SDL_GAME_SPAWNSYSTEM_H
+#ifndef SDL_GAME_BLOONSSPAWNSYSTEM_H
+#define SDL_GAME_BLOONSSPAWNSYSTEM_H
#include <vector>
-#include <limits>
#include <iterator>
#include "../System.h"
-class SpawnSystem : public System {
+class BloonsSpawnSystem : public System {
public:
void update(Entities *layers, GameData &gameData) override;
};
-#endif //SDL_GAME_SPAWNSYSTEM_H
+#endif //SDL_GAME_BLOONSSPAWNSYSTEM_H
diff --git a/src/systems/CollisionSystem.cpp b/src/systems/CollisionSystem.cpp
new file mode 100644
index 0000000..4e36b18
--- /dev/null
+++ b/src/systems/CollisionSystem.cpp
@@ -0,0 +1,62 @@
+//
+// Created by Ido Mozes on 11/07/2019.
+//
+#include "CollisionSystem.h"
+
+void insertionSort(Entities &layer) {
+ // can be optimized with binary search instead of comparison to every item
+ for (int i = 1, j = 0; i < layer.size(); j = i++) {
+ auto &entity = layer[i];
+ std::shared_ptr<Entity> entityP(entity);
+ auto &previousEntity = layer[i - 1];
+ auto[position, range] = entity->getComponents<Position, Range>().value();
+ float X = position.value.X - range.value;
+
+ while (j >= 0 and X < layer[j]->getComponent<Position>()->value.X - layer[j]->getComponent<Range>()->value) {
+ layer[j + 1] = layer[j];
+ --j;
+ }
+ if (j != i - 1) {
+ layer[j + 1] = entityP;
+ }
+ }
+}
+
+void CollisionSystem::update(Entities *layers, GameData &gameData) {
+ Entities &bloonsLayer = layers[BLOONS_LAYER];
+ Entities &shotsLayer = layers[SHOTS_LAYER];
+ insertionSort(bloonsLayer);
+ insertionSort(shotsLayer);
+ std::vector<std::tuple<std::shared_ptr<Entity>, std::shared_ptr<Entity>>> collided;
+ int bloonIndex = 0;
+ for (auto &shot : shotsLayer) {
+ auto[shotX, shotY] = shot->getComponent<Position>()->value;
+ auto shotRange = shot->getComponent<Range>()->value;
+ float shotLeft = shotX - shotRange;
+ float shotRight = shotX + shotRange;
+ float shotTop = shotY - shotRange;
+ float shotBottom = shotY + shotRange;
+ for (int i = bloonIndex; i < bloonsLayer.size(); ++i) {
+ auto &bloon = bloonsLayer[i];
+ auto[bloonX, bloonY] = bloon->getComponent<Position>()->value;
+ auto bloonRange = bloon->getComponent<Range>()->value;
+ float bloonLeft = bloonX - bloonRange;
+ float bloonRight = bloonX + bloonRange;
+ float bloonTop = bloonY - bloonRange;
+ float bloonBottom = bloonY + bloonRange;
+ if (bloonRight < shotLeft) {
+ bloonIndex++;
+ continue;
+ }
+ if (shotRight < bloonLeft)
+ break;
+ if (shotBottom >= bloonTop and shotTop <= bloonBottom)
+ collided.emplace_back(shot, bloon);
+ }
+ }
+ for (auto[shot, bloon] :collided) {
+ bloon->addComponent<RemoveEntityEvent>();
+ shot->addComponent<RemoveEntityEvent>();
+ }
+
+}
\ No newline at end of file
diff --git a/src/systems/CollisionSystem.h b/src/systems/CollisionSystem.h
new file mode 100644
index 0000000..ff1ff1a
--- /dev/null
+++ b/src/systems/CollisionSystem.h
@@ -0,0 +1,13 @@
+//
+// Created by Ido Mozes on 11/07/2019.
+//
+
+#ifndef SDL_GAME_COLLISIONSYSTEM_H
+#define SDL_GAME_COLLISIONSYSTEM_H
+#include <tuple>
+#include "../System.h"
+class CollisionSystem : public System {
+public:
+ void update(Entities *layers, GameData &gameData) override;
+};
+#endif //SDL_GAME_COLLISIONSYSTEM_H
diff --git a/src/systems/DraggingSystem.cpp b/src/systems/DraggingSystem.cpp
index 002436e..e667275 100644
--- a/src/systems/DraggingSystem.cpp
+++ b/src/systems/DraggingSystem.cpp
@@ -1,40 +1,40 @@
//
// Created by Ido Mozes on 09/07/2019.
//
#include "DraggingSystem.h"
void DraggingSystem::update(Entities *layers, GameData &gameData) {
-
+ if(!gameData.isDragging)
+ return;
int mouseX, mouseY;
SDL_GetMouseState(&mouseX, &mouseY);
mouseX = int(mouseX / gameData.mapScale);
mouseY = int(mouseY / gameData.mapScale);
for (int i = 0; i < N_LAYERS; ++i) {
for (auto &entity: layers[i]) {
if (auto components = entity->getComponents<Draggable, Visibility>()) {
auto[draggable, visibility] = components.value();
visibility.setPosition(mouseX - int(visibility.getDstRect()->w / 2.0),
mouseY - int(visibility.getDstRect()->h / 2.0));
bool freePosition = true;
if (mouseX > SIDEBAR_WIDTH + MAP_WIDTH or mouseX < SIDEBAR_WIDTH)
- freePosition = false;
-
+ freePosition = true;
else
for (int x = mouseX - SIDEBAR_WIDTH - 4; x < mouseX - SIDEBAR_WIDTH + 5; ++x) {
for (int y = mouseY - 4; y < mouseY + 5; ++y) {
if (gameData.mapData[x][y] == OBSTACLE or gameData.mapData[x][y] == TOWER) {
freePosition = false;
goto setIsPlaceable;
}
}
}
setIsPlaceable:
draggable.isPlaceable = freePosition;
}
}
}
}
\ No newline at end of file
diff --git a/src/systems/EventSystem.cpp b/src/systems/EventSystem.cpp
index 11f6cd3..c9f62c7 100644
--- a/src/systems/EventSystem.cpp
+++ b/src/systems/EventSystem.cpp
@@ -1,129 +1,139 @@
//
// 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.value.X - w / 2.0);
entityY = int(position.value.Y - 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.value];
draggable->addComponent<Visibility>(gameData.renderer, surface, SDL_Rect{
originalMouseX - int(surface->w / 3.0), mouseY - int(surface->h / 3.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);
draggable->addComponent<Strategy>(FIRST);
std::shared_ptr<Entity> ptr(draggable);
gameData.selected = ptr;
auto rangeShadow = new Entity();
rangeShadow->addComponent<RangeShadow>(ptr);
newEntities[SHADOW_LAYER].emplace_back(rangeShadow);
newEntities[MENU_LAYER].emplace_back(ptr);
gameData.isDragging = true;
goto entityClicked;
}
case CLICK: {
-
goto entityClicked;
}
case DROP: {
auto &draggable = *entity->getComponent<Draggable>();
if (draggable.isPlaceable) {
entity->removeComponent<Draggable>();
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 (mouseX > SIDEBAR_WIDTH + MAP_WIDTH or mouseX < SIDEBAR_WIDTH) {
+ entity->addComponent<RemoveEntityEvent>();
+ gameData.selected.reset();
}
- if (i == MENU_LAYER) {
- entity->addComponent<MoveEntityEvent>(GAME_LAYER);
- entity->addComponent<Type>(TOWER_T);
- auto &visibility = *entity->getComponent<Visibility>();
- SDL_Rect *dstRect = entity->getComponent<Visibility>()->getDstRect();
- entity->addComponent<Position>(
- dstRect->x - SIDEBAR_WIDTH + dstRect->w / 2,
- dstRect->y + dstRect->h / 2);
+ else {
+ 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) {
+ entity->addComponent<MoveEntityEvent>(TOWERS_LAYER);
+ entity->addComponent<Type>(TOWER_T);
+ auto &visibility = *entity->getComponent<Visibility>();
+ SDL_Rect *dstRect = entity->getComponent<Visibility>()->getDstRect();
+ entity->addComponent<Position>(
+ dstRect->x - SIDEBAR_WIDTH + dstRect->w / 2,
+ dstRect->y + dstRect->h / 2);
+ }
}
}
goto entityClicked;
}
case SELECT: {
+ if(entity==gameData.selected)
+ goto entityClicked;
gameData.selected = entity;
+ auto rangeShadow = new Entity();
+ rangeShadow->addComponent<RangeShadow>(entity);
+ newEntities[SHADOW_LAYER].emplace_back(rangeShadow);
goto entityClicked;
}
}
}
}
}
}
+ gameData.selected.reset();
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/MovementSystem.cpp b/src/systems/MovementSystem.cpp
index fd7256a..c2111bb 100644
--- a/src/systems/MovementSystem.cpp
+++ b/src/systems/MovementSystem.cpp
@@ -1,68 +1,74 @@
//
// Created by Ido Mozes on 02/07/2019.
//
#include "MovementSystem.h"
void MovementSystem::update(Entities *layers, GameData &gameData) {
for (int i = 0; i < N_LAYERS; ++i) {
for (auto &entity: layers[i]) {
// Move all entities with Visibility and Position
if (auto components = entity->getComponents<Visibility, Position>()) {
auto[visibility, position]=components.value();
float deltaX = 0, deltaY = 0;
if (auto velocityP = entity->getComponent<Velocity>()) {
auto &velocity = *velocityP;
if (auto accelerationP = entity->getComponent<Acceleration>()) {
auto &acceleration = *accelerationP;
velocity.changeVelocity(acceleration.value.X, acceleration.value.Y);
}
deltaX = velocity.value.X;
deltaY = velocity.value.Y;
} else if (auto components2 = entity->getComponents<PathIndex, Speed>()) {
auto[pathIndex, speed] =components2.value();
pathIndex.progress += speed.value;
float deltaIndex = pathIndex.progress - pathIndex.index;
while (deltaIndex >= (gameData.path[pathIndex.index] % 2 == 0 ? 1 : sqrt(2))) {
switch (gameData.path[pathIndex.index]) {
case 0:
deltaX += 1;
break;
case 1:
deltaX += 1;
deltaY += 1;
break;
case 2:
deltaY += 1;
break;
case 3:
deltaX += -1;
deltaY += 1;
break;
case 4:
deltaX += -1;
break;
case 5:
deltaX += -1;
deltaY += -1;
break;
case 6:
deltaY += -1;
break;
case 7:
deltaX += 1;
deltaY += -1;
break;
}
deltaIndex -= (gameData.path[pathIndex.index] % 2 == 0 ? 1 : sqrt(2));
if (pathIndex.index < gameData.path.size() - 1)
pathIndex.index++;
+
+
}
}
position.changePosition(deltaX, deltaY);
+ if (position.value.X > MAP_WIDTH or position.value.X < 0 or position.value.Y > MAP_HEIGHT or
+ position.value.Y < 0) {
+ entity->addComponent<RemoveEntityEvent>();
+ }
}
}
}
}
diff --git a/src/systems/RemoveEntitiesSystem.cpp b/src/systems/RemoveEntitiesSystem.cpp
index 4dbdb6f..cb914c4 100644
--- a/src/systems/RemoveEntitiesSystem.cpp
+++ b/src/systems/RemoveEntitiesSystem.cpp
@@ -1,20 +1,23 @@
//
// Created by Ido Mozes on 10/07/2019.
//
#include "RemoveEntitiesSystem.h"
void RemoveEntitiesSystem::update(Entities *layers, GameData &gameData) {
for (int i = 0; i < N_LAYERS; ++i) {
layers[i].erase(
- std::remove_if(layers[i].begin(), layers[i].end(), [layers](auto &entity) {
- if(auto moveEntityEventP = entity->template getComponent<MoveEntityEvent>()) {
+ std::remove_if(layers[i].begin(), layers[i].end(), [&layers, &gameData](auto &entity) {
+ if (auto moveEntityEventP = entity->template getComponent<MoveEntityEvent>()) {
int newLayer = moveEntityEventP->toLayer;
entity->template removeComponent<MoveEntityEvent>();
layers[newLayer].emplace_back(std::move(entity));
}
+ if (entity and entity->template getComponent<RangeShadow>() and
+ entity->template getComponent<RangeShadow>()->entity != gameData.selected)
+ return true;
return !entity or entity->template getComponent<RemoveEntityEvent>();
}),
layers[i].end());
}
}
\ No newline at end of file
diff --git a/src/systems/RemoveEntitiesSystem.h b/src/systems/RemoveEntitiesSystem.h
index ae3f932..595dbed 100644
--- a/src/systems/RemoveEntitiesSystem.h
+++ b/src/systems/RemoveEntitiesSystem.h
@@ -1,13 +1,14 @@
//
// Created by Ido Mozes on 10/07/2019.
//
#ifndef SDL_GAME_REMOVEENTITIESSYSTEM_H
#define SDL_GAME_REMOVEENTITIESSYSTEM_H
#include <algorithm>
+#include <iostream>
#include "../System.h"
class RemoveEntitiesSystem : public System {
public:
void update(Entities *layers, GameData &gameData) override;
};
#endif //SDL_GAME_REMOVEENTITIESSYSTEM_H
diff --git a/src/systems/RenderSystem.cpp b/src/systems/RenderSystem.cpp
index 9b99ff6..73e7b96 100644
--- a/src/systems/RenderSystem.cpp
+++ b/src/systems/RenderSystem.cpp
@@ -1,71 +1,72 @@
//
// 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)*/
int((MAP_WIDTH + SIDEBAR_WIDTH + MENU_WIDTH) * gameData.mapScale),
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);
SDL_RenderSetScale(gameData.renderer, gameData.mapScale, gameData.mapScale);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");
}
void RenderSystem::update(Entities *layers, GameData &gameData) {
SDL_RenderClear(gameData.renderer);
for (int i = 0; i < N_LAYERS; ++i) {
+ if (i == SEQUENCES_LAYER)
+ continue;
for (auto &entity: layers[i]) {
auto rangeShadowP = entity->getComponent<RangeShadow>();
- auto ¤tEntity = (rangeShadowP and rangeShadowP->entity == gameData.selected) ? rangeShadowP->entity
- : entity;
+ auto ¤tEntity = rangeShadowP ? rangeShadowP->entity : entity;
if (auto visibilityP = currentEntity->getComponent<Visibility>()) {
auto &visibility = *visibilityP;
SDL_Rect *dstRect = visibility.getDstRect();
SDL_Rect newDstRect = {dstRect->x, dstRect->y, dstRect->w, dstRect->h};
SDL_Point entityCenter;
auto positionP = currentEntity->getComponent<Position>();
if (positionP) {
auto &position = *positionP;
entityCenter.x = position.value.X + SIDEBAR_WIDTH;
entityCenter.y = position.value.Y;
newDstRect.x = int(position.value.X + SIDEBAR_WIDTH - newDstRect.w / 2.0);
newDstRect.y = int(position.value.Y - newDstRect.h / 2.0);
} else {
entityCenter.x = int(dstRect->x + dstRect->w / 2.0);
entityCenter.y = int(dstRect->y + dstRect->h / 2.0);
}
- if (gameData.selected == currentEntity and currentEntity != entity) {
+ if (currentEntity != entity) {
auto draggableP = currentEntity->getComponent<Draggable>();
bool isRed = draggableP ? !draggableP->isPlaceable : false;
float range = currentEntity->getComponent<Range>()->value;
filledCircleRGBA(gameData.renderer, entityCenter.x, entityCenter.y, range, isRed ? 255 : 0, 0, 0,
100);
aacircleRGBA(gameData.renderer, entityCenter.x, entityCenter.y, range, isRed ? 255 : 0, 0, 0, 150);
}
if (entity == currentEntity) {
SDL_RenderCopyEx(gameData.renderer, visibility.getTexture(), nullptr, &newDstRect, visibility.angle,
nullptr, SDL_FLIP_NONE);
}
}
}
}
SDL_RenderPresent(gameData.renderer);
}
diff --git a/src/systems/ShotsSpawnSystem.cpp b/src/systems/ShotsSpawnSystem.cpp
new file mode 100644
index 0000000..5089de1
--- /dev/null
+++ b/src/systems/ShotsSpawnSystem.cpp
@@ -0,0 +1,62 @@
+//
+// Created by Ido Mozes on 11/07/2019.
+//
+
+#include "ShotsSpawnSystem.h"
+
+void ShotsSpawnSystem::update(Entities *layers, GameData &gameData) {
+ for (auto &entity: layers[TOWERS_LAYER]) {
+ auto[kind, towerRange, towerPosition, strategy] = entity->getComponents<Kind, Range, Position, Strategy>().value();
+ float minDistance = MAP_HEIGHT + MAP_WIDTH;
+ float minProgress = gameData.path.size();
+ float maxProgress = -1;
+ Entity *closestBloon = nullptr, *firstBloon = nullptr, *lastBloon = nullptr;
+ for (auto &gameEntity: layers[BLOONS_LAYER]) {
+ float distance;
+ if (gameEntity->getComponent<Type>()->value == BLOON_T) {
+ auto[bloonRange, bloonPosition, pathIndex] = gameEntity->getComponents<Range, Position, PathIndex>().value();
+ distance =
+ twoPointsDistance(bloonPosition.value, towerPosition.value) - bloonRange.value;
+ if (distance > towerRange.value)
+ continue;
+ if (distance < minDistance) {
+ minDistance = distance;
+ closestBloon = gameEntity.get();
+ }
+ if (pathIndex.progress < minProgress) {
+ minProgress = pathIndex.progress;
+ lastBloon = gameEntity.get();
+ }
+ if (pathIndex.progress > maxProgress) {
+ maxProgress = pathIndex.progress;
+ firstBloon = gameEntity.get();
+ }
+ }
+ }
+ if (closestBloon or firstBloon or lastBloon) {
+ Entity *target;
+ switch (strategy.value) {
+ case CLOSEST:
+ target = closestBloon;
+ break;
+ case FIRST:
+ target = firstBloon;
+ break;
+ case LAST:
+ target = lastBloon;
+ break;
+ }
+ auto shot = new Entity();
+ shot->addComponent<Position>(towerPosition.value.X, towerPosition.value.Y);
+ float angle = twoPointsAngle(towerPosition.value, target->getComponent<Position>()->value);
+ auto[velocityX, velocityY] = polarToCartesian(angle, 5);
+ shot->addComponent<Velocity>(velocityX, velocityY);
+ shot->addComponent<Type>(SHOT_T);
+ shot->addComponent<Range>(5);
+ SDL_Surface *surface = gameData.assets["Dart"];
+ shot->addComponent<Visibility>(gameData.renderer, surface, SDL_Rect{0, 0, surface->w / 25},
+ radToDeg(angle));
+ layers[SHOTS_LAYER].emplace_back(shot);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/systems/ShotsSpawnSystem.h b/src/systems/ShotsSpawnSystem.h
new file mode 100644
index 0000000..1b5ef7a
--- /dev/null
+++ b/src/systems/ShotsSpawnSystem.h
@@ -0,0 +1,16 @@
+//
+// Created by Ido Mozes on 11/07/2019.
+//
+
+#ifndef SDL_GAME_SHOTSSPAWNSYSTEM_H
+#define SDL_GAME_SHOTSSPAWNSYSTEM_H
+#include <vector>
+#include <iterator>
+#include "../System.h"
+
+class ShotsSpawnSystem : public System {
+public:
+ void update(Entities *layers, GameData &gameData) override;
+};
+
+#endif //SDL_GAME_SHOTSSPAWNSYSTEM_H
diff --git a/src/systems/SpawnSystem.cpp b/src/systems/SpawnSystem.cpp
deleted file mode 100644
index a1037f6..0000000
--- a/src/systems/SpawnSystem.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-//
-// Created by Ido Mozes on 07/07/2019.
-//
-
-#include "SpawnSystem.h"
-
-
-void SpawnSystem::update(Entities *layers, GameData &gameData) {
- Entities newEntities[N_LAYERS];
- for (int i = 0; i < N_LAYERS; ++i) {
- for (auto &entity: layers[i]) {
- if (auto typeP = entity->getComponent<Type>()) {
- switch (typeP->value) {
- case SEQUENCE_T: {
- auto[sequence, kind, speed] = entity->getComponents<Sequence, Kind, Speed>().value();
- int amount = sequence.getAmountReady();
- for (int j = 0; j < amount; ++j) {
- auto *bloon = new Entity();
- bloon->addComponent<Type>(BLOON_T);
- bloon->addComponent<Kind>(kind);
- bloon->addComponent<Position>(gameData.startingPoint.X, gameData.startingPoint.Y);
- bloon->addComponent<PathIndex>(0);
- bloon->addComponent<Speed>(speed.value);
-
- SDL_Surface *surface = gameData.assets[kind.value];
- bloon->addComponent<Visibility>(gameData.renderer, surface,
- SDL_Rect{int(gameData.startingPoint.X),
- int(gameData.startingPoint.Y),
- int(surface->w / 3), int(surface->h / 3)});
- bloon->addComponent<Range>(std::max(surface->w / 6, surface->h / 6));
- newEntities[GAME_LAYER].emplace_back(bloon);
- }
- break;
- }
- case TOWER_T: {
- auto[kind, towerRange, towerPosition, strategy] = entity->getComponents<Kind, Range, Position, Strategy>().value();
- float minDistance = MAP_HEIGHT + MAP_WIDTH;
- float minProgress = gameData.path.size();
- float maxProgress = -1;
- Entity *closestBloon = nullptr, *firstBloon = nullptr, *lastBloon = nullptr;
- for (auto &gameEntity: layers[GAME_LAYER]) {
- float distance;
- if (gameEntity->getComponent<Type>()->value == BLOON_T) {
- auto[bloonRange, bloonPosition, pathIndex] = gameEntity->getComponents<Range, Position, PathIndex>().value();
- distance =
- twoPointsDistance(bloonPosition.value, towerPosition.value) - bloonRange.value;
- if (distance > towerRange.value)
- continue;
- if (distance < minDistance) {
- minDistance = distance;
- closestBloon = gameEntity.get();
- }
- if (pathIndex.progress < minProgress) {
- minProgress = pathIndex.progress;
- lastBloon = gameEntity.get();
- }
- if (pathIndex.progress > maxProgress) {
- maxProgress = pathIndex.progress;
- firstBloon = gameEntity.get();
- }
-
- }
- }
- if (closestBloon or firstBloon or lastBloon) {
- Entity *target;
- switch (strategy.value) {
- case CLOSEST:
- target = closestBloon;
- break;
- case FIRST:
- target = firstBloon;
- break;
- case LAST:
- target = lastBloon;
- break;
- }
- auto shot = new Entity();
- shot->addComponent<Position>(towerPosition.value.X, towerPosition.value.Y);
- float angle = twoPointsAngle(towerPosition.value, target->getComponent<Position>()->value);
- auto[velocityX, velocityY] = polarToCartesian(angle, 10);
- shot->addComponent<Velocity>(velocityX, velocityY);
- shot->addComponent<Type>(SHOT_T);
- SDL_Surface *surface = gameData.assets["Dart"];
- shot->addComponent<Visibility>(gameData.renderer, surface, SDL_Rect{0, 0, surface->w / 25},
- radToDeg(angle));
- newEntities[SHOTS_LAYER].emplace_back(shot);
- }
-
- break;
- }
- }
- }
- }
- }
- for (int i = 0; i < N_LAYERS; ++i) {
- if (!newEntities[i].empty())
- layers[i] += newEntities[i];
- }
-}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Wed, Jun 17, 9:29 PM (1 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
72283
Default Alt Text
(45 KB)
Attached To
Mode
R74 BloonsTD
Attached
Detach File
Event Timeline