Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F132440
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
35 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c9b83e8..e46f7c2 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)
+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)
target_link_libraries(SDL_Game ${Boost_LIBRARIES})
\ No newline at end of file
diff --git a/src/Component.h b/src/Component.h
index 85391f2..3b58b8d 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 {
float X;
float Y;
};
class Entity;
enum ComponentType {
- VISIBILITY, POSITION, VELOCITY, SPEED, ACCELERATION, PATH_INDEX, HEALTH, KIND, TYPE,RANGE, DAMAGE, PIERCE, SPREAD, SEQUENCE, ACTION, DRAGGABLE,RANGE_SHADOW,
+ VISIBILITY, POSITION, VELOCITY, SPEED, ACCELERATION, PATH_INDEX, HEALTH, KIND, TYPE,RANGE, DAMAGE, PIERCE, SPREAD, SEQUENCE, ACTION, DRAGGABLE,RANGE_SHADOW,STRATEGY,
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 1aa1517..83179f9 100644
--- a/src/Game.cpp
+++ b/src/Game.cpp
@@ -1,133 +1,134 @@
//
// 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>(1);
+ 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<Type>(SEQUENCE_T);
- s->addComponent<Speed>(1);
+ 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 EventSystem);
systems.emplace_back(new DraggingSystem);
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/GameData.h b/src/GameData.h
index 3013f1a..0d55ec8 100644
--- a/src/GameData.h
+++ b/src/GameData.h
@@ -1,39 +1,39 @@
//
// 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;
+ float mapScale;
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;
~GameData();
};
#endif //SDL_GAME_GAMEDATA_H
diff --git a/src/Physics.h b/src/Physics.h
index 1f9dea7..ee4633a 100644
--- a/src/Physics.h
+++ b/src/Physics.h
@@ -1,29 +1,35 @@
//
// Created by Ido Mozes on 11/07/2019.
//
#ifndef SDL_GAME_PHYSICS_H
#define SDL_GAME_PHYSICS_H
#include <tuple>
#include <cmath>
#include "Component.h"
inline std::tuple<float, float> cartesianToPolar(float X, float Y) {
float alpha = atan2f(Y, X);
float R = X / sinf(alpha);
return std::make_tuple(alpha, R);
}
inline std::tuple<float, float> polarToCartesian(float alpha, float R) {
return std::make_tuple(R * cosf(alpha), R * sinf(alpha));
}
-inline float twoPointsDistance(Point point1, Point point2){
+inline float twoPointsDistance(Point point1, Point point2) {
return sqrtf(powf(point1.X - point2.X, 2) +
powf(point1.Y - point2.Y, 2));
}
-inline float twoPointsAngle(Point point1, Point point2){
- return atan2f(point2.Y - point1.Y,point2.X - point1.X);
+
+inline float twoPointsAngle(Point point1, Point point2) {
+ return atan2f(point2.Y - point1.Y, point2.X - point1.X);
+}
+
+inline float radToDeg(float radians) {
+ return radians * (180.0 / 3.141592653589793238463);
}
+
#endif //SDL_GAME_PHYSICS_H
diff --git a/src/Settings.h b/src/Settings.h
index 4fecf71..8b683a2 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, GAME_LAYER, MENU_LAYER,
+ BACKGROUND_LAYER, SHADOW_LAYER,SHOTS_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 8aa941f..b85f8c1 100644
--- a/src/System.h
+++ b/src/System.h
@@ -1,41 +1,42 @@
//
// 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/Type.h"
+#include "components/Strategy.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/Strategy.h b/src/components/Strategy.h
new file mode 100644
index 0000000..12b6052
--- /dev/null
+++ b/src/components/Strategy.h
@@ -0,0 +1,23 @@
+//
+// Created by Ido Mozes on 11/07/2019.
+//
+
+#ifndef SDL_GAME_STRATEGY_H
+#define SDL_GAME_STRATEGY_H
+#include "../Component.h"
+
+enum Strateies {
+ FIRST, LAST, CLOSEST, STRONGEST
+};
+
+class Strategy : public Component {
+public:
+ Strateies value;
+ static constexpr ComponentType type = ComponentType::STRATEGY;
+
+ Strategy(Strateies value) : value(value) {}
+
+ ~Strategy() override = default;
+};
+
+#endif //SDL_GAME_STRATEGY_H
diff --git a/src/components/Visibility.cpp b/src/components/Visibility.cpp
index 3640ebf..8f61c06 100644
--- a/src/components/Visibility.cpp
+++ b/src/components/Visibility.cpp
@@ -1,38 +1,38 @@
//
// Created by Ido Mozes on 23/06/2019.
//
#include "Visibility.h"
-Visibility::Visibility(SDL_Renderer *renderer, SDL_Surface *newSurface, std::optional<SDL_Rect> dstR) : dstRect(dstR){
+Visibility::Visibility(SDL_Renderer *renderer, SDL_Surface *newSurface, std::optional<SDL_Rect> dstR, float angle) : dstRect(dstR), angle(angle){
loadTexture(renderer, newSurface);
}
Visibility::~Visibility() {
SDL_DestroyTexture(texture);
}
void Visibility::loadTexture(SDL_Renderer *renderer, SDL_Surface *newSurface) {
surface = newSurface;
reloadTexture(renderer);
if (dstRect) {
if (dstRect->w == 0)
dstRect->w = int((float(surface->w) / surface->h) * dstRect->h);
else if (dstRect->h == 0)
dstRect->h = int((float(surface->h) / surface->w) * dstRect->w);
}
}
void Visibility::reloadTexture(SDL_Renderer *renderer) {
texture = SDL_CreateTextureFromSurface(renderer, surface);
}
void Visibility::setPosition(int x, int y) {
if (dstRect) {
dstRect->x = x;
dstRect->y = y;
}
}
diff --git a/src/components/Visibility.h b/src/components/Visibility.h
index af6924c..e1bac3e 100644
--- a/src/components/Visibility.h
+++ b/src/components/Visibility.h
@@ -1,43 +1,44 @@
//
// Created by Ido Mozes on 23/06/2019.
//
#ifndef SDL2_GAME_VISIBILITY_H
#define SDL2_GAME_VISIBILITY_H
#include <fstream>
#include <optional>
#include "SDL.h"
#include "SDL_image.h"
#include "../Component.h"
SDL_Texture *loadTexture(SDL_Renderer *renderer, const char *path);
class Visibility : public Component {
SDL_Surface *surface = nullptr;
SDL_Texture *texture = nullptr;
std::optional<SDL_Rect> dstRect;
public:
+ float angle=0;
static constexpr ComponentType type = ComponentType::VISIBILITY;
- Visibility(SDL_Renderer *renderer, SDL_Surface *newSurface, std::optional<SDL_Rect> dstR = std::nullopt);
+ Visibility(SDL_Renderer *renderer, SDL_Surface *newSurface, std::optional<SDL_Rect> dstR = std::nullopt,float angle = 0);
~Visibility() override;
SDL_Texture *getTexture() { return texture; }
SDL_Rect *getDstRect() { return dstRect ? &dstRect.value() : nullptr; }
void setPosition(int x, int y);
void loadTexture(SDL_Renderer *renderer, SDL_Surface *newSurface);
void reloadTexture(SDL_Renderer *renderer);
};
#endif //SDL2_GAME_VISIBILITY_H
diff --git a/src/systems/EventSystem.cpp b/src/systems/EventSystem.cpp
index 4d506d3..11f6cd3 100644
--- a/src/systems/EventSystem.cpp
+++ b/src/systems/EventSystem.cpp
@@ -1,129 +1,129 @@
//
// 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 / 4.0), mouseY - int(surface->h / 4.0),
+ 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 (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);
}
}
goto entityClicked;
}
case SELECT: {
gameData.selected = entity;
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 4f85066..9b99ff6 100644
--- a/src/systems/RenderSystem.cpp
+++ b/src/systems/RenderSystem.cpp
@@ -1,70 +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)
+ 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) {
for (auto &entity: layers[i]) {
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 = 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)};
+ SDL_Rect newDstRect = {dstRect->x, dstRect->y, dstRect->w, dstRect->h};
+ SDL_Point entityCenter;
+
+ auto positionP = currentEntity->getComponent<Position>();
if (positionP) {
auto &position = *positionP;
- r.x = int((position.value.X + SIDEBAR_WIDTH) * gameData.mapScale - r.w / 2.0);
- r.y = int(position.value.Y * gameData.mapScale - r.h / 2.0);
+ 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) {
- int currentEntityX, currentEntityY;
- if (positionP) {
- auto &position = *positionP;
- currentEntityX = int((position.value.X + SIDEBAR_WIDTH) * gameData.mapScale);
- currentEntityY = int(position.value.Y * gameData.mapScale);
- } else {
- currentEntityX = int((dstRect->x + dstRect->w / 2.0) * gameData.mapScale);
- currentEntityY = int((dstRect->y + dstRect->h / 2.0) * gameData.mapScale);
- }
auto draggableP = currentEntity->getComponent<Draggable>();
bool isRed = draggableP ? !draggableP->isPlaceable : false;
- float range = currentEntity->getComponent<Range>()->value *gameData.mapScale;
- filledCircleRGBA(gameData.renderer, currentEntityX, currentEntityY, range, isRed ? 255 : 0, 0, 0,
+ float range = currentEntity->getComponent<Range>()->value;
+ filledCircleRGBA(gameData.renderer, entityCenter.x, entityCenter.y, range, isRed ? 255 : 0, 0, 0,
100);
- aacircleRGBA(gameData.renderer, currentEntityX, currentEntityY, range, isRed ? 255 : 0, 0, 0, 150);
+ 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);
+
}
- if (entity == currentEntity)
- SDL_RenderCopy(gameData.renderer, visibility.getTexture(), nullptr, &r);
}
}
}
SDL_RenderPresent(gameData.renderer);
}
diff --git a/src/systems/SpawnSystem.cpp b/src/systems/SpawnSystem.cpp
index 3f4c944..a1037f6 100644
--- a/src/systems/SpawnSystem.cpp
+++ b/src/systems/SpawnSystem.cpp
@@ -1,74 +1,99 @@
//
// 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) {
- Entities newEntities;
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),
- surface->w / 3, surface->h / 3});
+ int(surface->w / 3), int(surface->h / 3)});
bloon->addComponent<Range>(std::max(surface->w / 6, surface->h / 6));
- newEntities.emplace_back(bloon);
+ newEntities[GAME_LAYER].emplace_back(bloon);
}
break;
}
case TOWER_T: {
- auto[kind, towerRange, towerPosition] = entity->getComponents<Kind, Range, Position>().value();
+ auto[kind, towerRange, towerPosition, strategy] = entity->getComponents<Kind, Range, Position, Strategy>().value();
float minDistance = MAP_HEIGHT + MAP_WIDTH;
- Point closestPosition = {-1, -1};
- Entity * b;
+ 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] = gameEntity->getComponents<Range, Position>().value();
+ 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;
- closestPosition = {bloonPosition.value.X, bloonPosition.value.Y};
- b=gameEntity.get();
+ closestBloon = gameEntity.get();
}
+ if (pathIndex.progress < minProgress) {
+ minProgress = pathIndex.progress;
+ lastBloon = gameEntity.get();
+ }
+ if (pathIndex.progress > maxProgress) {
+ maxProgress = pathIndex.progress;
+ firstBloon = gameEntity.get();
+ }
+
}
}
- if (closestPosition.X != -1 and minDistance <= towerRange.value) {
+ 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, closestPosition);
+ 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, gameData.assets["Dart"],
- SDL_Rect{0, 0, gameData.assets["Dart"]->w / 2});
- newEntities.emplace_back(shot);
+ 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;
}
}
}
}
- if (!newEntities.empty())
- layers[i] += newEntities;
+ }
+ 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
Tue, Jun 16, 12:46 AM (2 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
72498
Default Alt Text
(35 KB)
Attached To
Mode
R74 BloonsTD
Attached
Detach File
Event Timeline