Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
35 KB
Referenced Files
None
Subscribers
None
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 &currentEntity = (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

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)

Event Timeline