Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
45 KB
Referenced Files
None
Subscribers
None
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 &currentEntity = (rangeShadowP and rangeShadowP->entity == gameData.selected) ? rangeShadowP->entity
- : entity;
+ auto &currentEntity = 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

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)

Event Timeline