0
0
mirror of https://github.com/Nimac0/SDL_Minigame synced 2026-01-12 10:13:42 +00:00

Merge branch 'collision-manager' into powerups

This commit is contained in:
Benedikt Galbavy 2024-01-28 17:12:01 +01:00
commit fce7ded0e3
17 changed files with 334 additions and 79 deletions

View File

@ -0,0 +1,45 @@
#pragma once
#include "Entity.h"
#include "SDL_rect.h"
#include "SpriteComponent.h"
#include "Vector2D.h"
#include <vector>
class ColliderComponent;
class Manager;
class Entity;
constexpr uint8_t DIRECTION_C = 4;
enum class direction
{
LEFT = 0,
RIGHT,
UP,
DOWN
};
using IntersectionBitSet = std::bitset<DIRECTION_C>;
class CollisionHandler
{
private:
Manager& manager;
public:
CollisionHandler(Manager& mManager) :
manager(mManager) { };
~CollisionHandler();
static IntersectionBitSet getIntersection(Entity* entityA, Entity* entityB); // intersections relative to entityA
static IntersectionBitSet getIntersection(Entity* entityA, Entity* entityB, Vector2D posModA, Vector2D posModB);
static IntersectionBitSet getIntersectionWithBounds(Entity* entity);// will fail if speed high enough to switch from no collision to full overlap in one tick
static IntersectionBitSet getIntersectionWithBounds(Entity* entity, Vector2D posMod);
std::vector<ColliderComponent*> getColliders(GroupLabel groupLabel); // temporary function, remove once game.cpp cleaned up
void update();
};

View File

@ -2,17 +2,6 @@
class Entity; class Entity;
enum class GroupLabel
{
MAP,
PLAYERS,
ENEMIES,
COLLIDERS,
PROJECTILE,
HEARTS,
POWERUPS
};
class Component class Component
{ {
public: public:

View File

@ -3,9 +3,11 @@
#include <cstddef> #include <cstddef>
using Group = std::size_t; using Group = std::size_t;
using Team = std::size_t;
constexpr std::size_t MAX_COMPONENTS = 32; constexpr std::size_t MAX_COMPONENTS = 32;
constexpr std::size_t MAX_GROUPS = 32; constexpr std::size_t MAX_GROUPS = 32;
constexpr std::size_t MAX_TEAMS = 8; //
constexpr int SCREEN_SIZE_HEIGHT = 640; constexpr int SCREEN_SIZE_HEIGHT = 640;
constexpr int SCREEN_SIZE_WIDTH = 800; constexpr int SCREEN_SIZE_WIDTH = 800;

View File

@ -15,10 +15,29 @@ using ComponentBitSet = std::bitset<MAX_COMPONENTS>;
using GroupBitSet = std::bitset<MAX_GROUPS>; using GroupBitSet = std::bitset<MAX_GROUPS>;
using ComponentArray = std::array<Component*, MAX_COMPONENTS>; using ComponentArray = std::array<Component*, MAX_COMPONENTS>;
enum class GroupLabel
{
MAPTILES,
PLAYERS,
ENEMIES,
COLLIDERS,
PROJECTILE,
HEARTS,
POWERUPS
};
enum class TeamLabel
{
NONE,
BLUE,
RED
};
class Entity class Entity
{ {
public: public:
explicit Entity(Manager& mManager) : manager(mManager) { } explicit Entity(Manager& mManager) :
manager(mManager) { };
void update() const; void update() const;
void draw() const; void draw() const;
@ -30,6 +49,11 @@ public:
void addGroup(Group mGroup); void addGroup(Group mGroup);
void delGroup(Group mGroup); void delGroup(Group mGroup);
void setTeam(TeamLabel teamLabel);
TeamLabel getTeam();
Manager& getManager() { return manager; };
template <typename T> bool hasComponent() const template <typename T> bool hasComponent() const
{ {
return componentBitSet[getComponentTypeID<T>()]; return componentBitSet[getComponentTypeID<T>()];
@ -63,4 +87,5 @@ private:
ComponentArray componentArray = {}; ComponentArray componentArray = {};
ComponentBitSet componentBitSet; ComponentBitSet componentBitSet;
GroupBitSet groupBitSet; GroupBitSet groupBitSet;
TeamLabel teamLabel;
}; };

View File

@ -5,7 +5,7 @@
#include <vector> #include <vector>
class AssetManager; class AssetManager;
class ColliderComponent; class CollisionHandler;
class Game class Game
{ {
@ -24,7 +24,7 @@ public:
static void addTile(int id, int x, int y); static void addTile(int id, int x, int y);
static SDL_Renderer* renderer; static SDL_Renderer* renderer;
static SDL_Event event; static SDL_Event event;
static std::vector<ColliderComponent*> colliders; static CollisionHandler* collisionHandler;
static AssetManager* assets; static AssetManager* assets;
bool getWinner(); bool getWinner();

View File

@ -5,8 +5,7 @@
#include <vector> #include <vector>
#include "Constants.h" #include "Constants.h"
#include "Entity.h"
class Entity;
class Manager class Manager
{ {
@ -18,9 +17,13 @@ public:
void addToGroup(Entity* mEntity, Group mGroup); void addToGroup(Entity* mEntity, Group mGroup);
std::vector<Entity*>& getGroup(Group mGroup); std::vector<Entity*>& getGroup(Group mGroup);
void addToTeam(Entity* mEntity, Team mTeam);
std::vector<Entity*>& getTeam(Team mTeam);
Entity& addEntity(); Entity& addEntity();
private: private:
std::vector<std::unique_ptr<Entity>> entities; std::vector<std::unique_ptr<Entity>> entities;
std::array<std::vector<Entity*>, MAX_GROUPS> groupedEntities; std::array<std::vector<Entity*>, MAX_GROUPS> entitiesByGroup;
std::array<std::vector<Entity*>, MAX_TEAMS> entitiesByTeam;
}; };

View File

@ -0,0 +1,9 @@
#pragma once
#include "Component.h"
class PlayerComponent : public Component
{
public:
private:
};

View File

@ -13,6 +13,7 @@ public:
friend Vector2D& operator-(Vector2D& vector1, const Vector2D& vector2); friend Vector2D& operator-(Vector2D& vector1, const Vector2D& vector2);
friend Vector2D& operator*(Vector2D& vector1, const Vector2D& vector2); friend Vector2D& operator*(Vector2D& vector1, const Vector2D& vector2);
friend Vector2D& operator/(Vector2D& vector1, const Vector2D& vector2); friend Vector2D& operator/(Vector2D& vector1, const Vector2D& vector2);
friend Vector2D& operator+=(Vector2D& vector1, const Vector2D& vector2);
Vector2D& operator*(const int& i); Vector2D& operator*(const int& i);
Vector2D& zero(); Vector2D& zero();

View File

@ -1,5 +1,6 @@
#include "ColliderComponent.h" #include "ColliderComponent.h"
#include "CollisionHandler.h"
#include "Entity.h" #include "Entity.h"
#include "Game.h" #include "Game.h"
#include "TransformComponent.h" #include "TransformComponent.h"
@ -26,13 +27,13 @@ void ColliderComponent::init()
} }
transform = &entity->getComponent<TransformComponent>(); transform = &entity->getComponent<TransformComponent>();
Game::colliders.push_back(this); //Game::collisionHandler->add(this);
} }
void ColliderComponent::update() void ColliderComponent::update()
{ {
collider.x = transform->position.x; collider.x = transform->position.x - (transform->width - transform->width * transform->scale * this->hitboxScale) / 2;
collider.y = transform->position.y; collider.y = transform->position.y - (transform->width - transform->width * transform->scale * this->hitboxScale) / 2;
collider.w = (transform->width * transform->scale) * this->hitboxScale; collider.w = (transform->width * transform->scale) * this->hitboxScale;

108
src/CollisionHandler.cpp Normal file
View File

@ -0,0 +1,108 @@
#include "CollisionHandler.h"
#include "ColliderComponent.h"
#include "Constants.h"
#include "Entity.h"
#include "Manager.h"
#include "Vector2D.h"
#include <SDL_rect.h>
#include <bitset>
#include <cstdio>
#include <memory>
IntersectionBitSet CollisionHandler::getIntersection(Entity* entityA, Entity* entityB)
{
return getIntersection(entityA, entityB, Vector2D(0,0), Vector2D(0,0));
}
IntersectionBitSet CollisionHandler::getIntersection(Entity* entityA, Entity* entityB, Vector2D posModA, Vector2D posModB)
{
if (!entityA->hasComponent<ColliderComponent>() ||
!entityB->hasComponent<ColliderComponent>())
return std::bitset<DIRECTION_C>();
SDL_Rect colliderA = entityA->getComponent<ColliderComponent>().collider;
SDL_Rect colliderB = entityB->getComponent<ColliderComponent>().collider;
colliderA.x += posModA.x;
colliderA.y += posModA.y;
colliderB.x += posModB.x;
colliderB.y += posModB.y;
if (!SDL_HasIntersection(
&colliderA,
&colliderB))
return std::bitset<DIRECTION_C>();
std::bitset<DIRECTION_C> intersections;
// checks all 4 directions to allow checking full overlap
if (colliderA.x < colliderB.x + colliderB.w &&
colliderA.x > colliderB.x) {
intersections.set((size_t) direction::LEFT);
}
if (colliderA.x + colliderA.w < colliderB.x + colliderB.w &&
colliderA.x + colliderA.w > colliderB.x) {
intersections.set((size_t) direction::RIGHT);
}
if (colliderA.y < colliderB.y + colliderB.h &&
colliderA.y > colliderB.y)
intersections.set((size_t) direction::UP);
if (colliderA.y + colliderA.h < colliderB.y + colliderB.h &&
colliderA.y + colliderA.h > colliderB.y)
intersections.set((size_t) direction::DOWN);
return intersections;
}
IntersectionBitSet CollisionHandler::getIntersectionWithBounds(Entity* entity)
{
return getIntersectionWithBounds(entity, Vector2D(0,0));
}
IntersectionBitSet CollisionHandler::getIntersectionWithBounds(Entity* entity, Vector2D posMod)
{
if (!entity->hasComponent<ColliderComponent>())
return std::bitset<DIRECTION_C>();
SDL_Rect* collider = &entity->getComponent<ColliderComponent>().collider;
std::bitset<DIRECTION_C> intersections;
// all 4 directions and both sides to allow checking for fully out of bounds
if (collider->x + posMod.x < 0 ||
collider->x + posMod.x > SCREEN_SIZE_WIDTH)
intersections.set((size_t) direction::LEFT);
if (collider->x + collider->w + posMod.x < 0 ||
collider->x + collider->w + posMod.x > SCREEN_SIZE_WIDTH)
intersections.set((size_t) direction::RIGHT);
if (collider->y + posMod.y < 0 ||
collider->y + posMod.y > SCREEN_SIZE_HEIGHT)
intersections.set((size_t) direction::UP);
if (collider->y + collider->h + posMod.y < 0 ||
collider->y + collider->h + posMod.y > SCREEN_SIZE_HEIGHT)
intersections.set((size_t) direction::DOWN);
return intersections;
}
std::vector<ColliderComponent*> CollisionHandler::getColliders(GroupLabel groupLabel)
{
std::vector<ColliderComponent*> colliders;
for (auto& entity : manager.getGroup((size_t) groupLabel)) {
if (!entity->hasComponent<ColliderComponent>())
continue;
colliders.emplace_back(&entity->getComponent<ColliderComponent>());
}
return colliders;
}

View File

@ -2,6 +2,7 @@
#include "Manager.h" #include "Manager.h"
#include "Component.h" #include "Component.h"
#include <cstddef>
void Entity::update() const void Entity::update() const
{ {
@ -28,3 +29,14 @@ void Entity::delGroup(Group mGroup)
{ {
groupBitSet[mGroup] = false; groupBitSet[mGroup] = false;
} }
void Entity::setTeam(TeamLabel teamLabel)
{
teamLabel = teamLabel;
manager.addToTeam(this, (size_t) teamLabel);
}
TeamLabel Entity::getTeam()
{
return teamLabel;
}

View File

@ -1,8 +1,10 @@
#include "Game.h" #include "Game.h"
#include "CollisionHandler.h"
#include "Components.h" #include "Components.h"
#include "AssetManager.h" #include "AssetManager.h"
#include "Entity.h"
#include "Map.h" #include "Map.h"
#include "TextureManager.h" #include "TextureManager.h"
#include "Powerup.h" #include "Powerup.h"
@ -12,14 +14,15 @@ Manager manager;
AssetManager* Game::assets = new AssetManager(&manager); AssetManager* Game::assets = new AssetManager(&manager);
CollisionHandler* Game::collisionHandler = new CollisionHandler(manager);
SDL_Renderer* Game::renderer = nullptr; SDL_Renderer* Game::renderer = nullptr;
SDL_Event Game::event; SDL_Event Game::event;
std::vector<ColliderComponent*> Game::colliders; auto& player1(manager.addEntity());
auto& player2(manager.addEntity());
auto& player(manager.addEntity());
auto& enemy(manager.addEntity());
auto& wall(manager.addEntity()); auto& wall(manager.addEntity());
Game::Game() = default; Game::Game() = default;
@ -110,25 +113,27 @@ void Game::init(const char* title, int xpos, int ypos, int width, int height, bo
//ecs implementation //ecs implementation
player.addComponent<TransformComponent>(80,80,2); //posx, posy, scale player1.addComponent<TransformComponent>(80,80,2); //posx, posy, scale
player.addComponent<SpriteComponent>("assets/chicken_knight_spritesheet.png", true); //adds sprite (32x32px), path needed player1.addComponent<SpriteComponent>("assets/chicken_knight_spritesheet.png", true); //adds sprite (32x32px), path needed
player.addComponent<KeyboardController>(SDL_SCANCODE_W, SDL_SCANCODE_S, SDL_SCANCODE_A, SDL_SCANCODE_D, SDL_SCANCODE_E, Vector2D(1, 0));//custom keycontrols can be added player1.addComponent<KeyboardController>(SDL_SCANCODE_W, SDL_SCANCODE_S, SDL_SCANCODE_A, SDL_SCANCODE_D, SDL_SCANCODE_E, Vector2D(1, 0));//custom keycontrols can be added
player.addComponent<ColliderComponent>("player", 0.8f); //adds tag (for further use, reference tag) player1.addComponent<ColliderComponent>("player", 0.8f); //adds tag (for further use, reference tag)
player.addComponent<HealthComponent>(5, &manager, true); player1.addComponent<HealthComponent>(5, &manager, true);
player.addGroup((size_t)GroupLabel::PLAYERS); //tell programm what group it belongs to for rendering order player1.addGroup((size_t) GroupLabel::PLAYERS); //tell programm what group it belongs to for rendering order
player1.setTeam(TeamLabel::BLUE);
enemy.addComponent<TransformComponent>(600, 500, 2); player2.addComponent<TransformComponent>(600, 500, 2);
enemy.addComponent<SpriteComponent>("assets/chicken_spritesheet.png", true); player2.addComponent<SpriteComponent>("assets/chicken_spritesheet.png", true);
enemy.addComponent<KeyboardController>(SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_RCTRL, Vector2D(-1, 0)); player2.addComponent<KeyboardController>(SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_RCTRL, Vector2D(-1, 0));
enemy.addComponent<ColliderComponent>("enemy", 0.8f); player2.addComponent<ColliderComponent>("enemy", 0.8f);
enemy.addComponent<HealthComponent>(5, &manager, false); player2.addComponent<HealthComponent>(5, &manager, false);
enemy.addGroup((size_t)GroupLabel::ENEMIES); player2.addGroup((size_t) GroupLabel::PLAYERS);
player2.setTeam(TeamLabel::RED);
} }
auto& tiles(manager.getGroup((size_t)GroupLabel::MAP)); auto& tiles(manager.getGroup((size_t)GroupLabel::MAPTILES));
auto& players(manager.getGroup((size_t)GroupLabel::PLAYERS)); auto& players(manager.getGroup((size_t)GroupLabel::PLAYERS));
auto& enemies(manager.getGroup((size_t)GroupLabel::ENEMIES)); auto& enemies(manager.getGroup((size_t)GroupLabel::PLAYERS));
auto& projectiles(manager.getGroup((size_t)GroupLabel::PROJECTILE)); auto& projectiles(manager.getGroup((size_t)GroupLabel::PROJECTILE));
auto& hearts(manager.getGroup((size_t)GroupLabel::HEARTS)); auto& hearts(manager.getGroup((size_t)GroupLabel::HEARTS));
auto& powerups(manager.getGroup((size_t)GroupLabel::POWERUPS)); auto& powerups(manager.getGroup((size_t)GroupLabel::POWERUPS));
@ -149,8 +154,8 @@ void Game::handleEvents()
void Game::update() void Game::update()
{ {
Vector2D playerPos = player.getComponent<TransformComponent>().position; Vector2D playerPos = player1.getComponent<TransformComponent>().position;
Vector2D enemyPos = enemy.getComponent<TransformComponent>().position; Vector2D enemyPos = player2.getComponent<TransformComponent>().position;
int powerupSpawn = rand() % 500; int powerupSpawn = rand() % 500;
@ -162,58 +167,46 @@ void Game::update()
assets->createPowerup(Powerup::calculateSpawnPosition(), Powerup::calculateType()); assets->createPowerup(Powerup::calculateSpawnPosition(), Powerup::calculateType());
} }
for (auto cc : colliders)
{
if (SDL_HasIntersection(&player.getComponent<ColliderComponent>().collider, &cc->collider) && strcmp(cc->tag, "player"))
{
player.getComponent<TransformComponent>().position = playerPos;
}
if (SDL_HasIntersection(&enemy.getComponent<ColliderComponent>().collider, &cc->collider) && strcmp(cc->tag, "enemy"))
{
enemy.getComponent<TransformComponent>().position = enemyPos;
}
}
//checking if projectiles hit player1 or player2 //checking if projectiles hit player1 or player2
for (auto& p : projectiles) { for (auto& p : projectiles) {
if(SDL_HasIntersection(&enemy.getComponent<ColliderComponent>().collider, &p->getComponent<ColliderComponent>().collider) if(SDL_HasIntersection(&player2.getComponent<ColliderComponent>().collider, &p->getComponent<ColliderComponent>().collider)
&& (p->getComponent<ColliderComponent>().hasCollision) && !p->getComponent<ProjectileComponent>().getSource()) { && (p->getComponent<ColliderComponent>().hasCollision) && !p->getComponent<ProjectileComponent>().getSource()) {
//std::cout << "Enemy hit!"; //std::cout << "Enemy hit!";
p->getComponent<ColliderComponent>().removeCollision(); p->getComponent<ColliderComponent>().removeCollision();
p->destroy(); p->destroy();
enemy.getComponent<HealthComponent>().getDamage(); player2.getComponent<HealthComponent>().getDamage();
//display updated health | pretty scuffed but works ig //display updated health | pretty scuffed but works ig
for(auto h : hearts) for(auto h : hearts)
h->destroy(); h->destroy();
player.getComponent<HealthComponent>().createAllHearts(); player1.getComponent<HealthComponent>().createAllHearts();
enemy.getComponent<HealthComponent>().createAllHearts(); player2.getComponent<HealthComponent>().createAllHearts();
if(enemy.getComponent<HealthComponent>().getHealth() < 1) { if(player2.getComponent<HealthComponent>().getHealth() < 1) {
std::cout << "Player1 wins!" << std::endl; std::cout << "Player1 wins!" << std::endl;
winner = true; winner = true;
isRunning = false; isRunning = false;
} }
} }
if(SDL_HasIntersection(&player.getComponent<ColliderComponent>().collider, &p->getComponent<ColliderComponent>().collider) if(SDL_HasIntersection(&player1.getComponent<ColliderComponent>().collider, &p->getComponent<ColliderComponent>().collider)
&& (p->getComponent<ColliderComponent>().hasCollision) && p->getComponent<ProjectileComponent>().getSource()) { && (p->getComponent<ColliderComponent>().hasCollision) && p->getComponent<ProjectileComponent>().getSource()) {
//std::cout << "Player hit!"; //std::cout << "Player hit!";
p->getComponent<ColliderComponent>().removeCollision(); p->getComponent<ColliderComponent>().removeCollision();
p->destroy(); p->destroy();
player.getComponent<HealthComponent>().getDamage(); player1.getComponent<HealthComponent>().getDamage();
//display updated health //display updated health
for(auto h : hearts) for(auto h : hearts)
h->destroy(); h->destroy();
player.getComponent<HealthComponent>().createAllHearts(); player1.getComponent<HealthComponent>().createAllHearts();
enemy.getComponent<HealthComponent>().createAllHearts(); player2.getComponent<HealthComponent>().createAllHearts();
if(player.getComponent<HealthComponent>().getHealth() < 1) { if(player1.getComponent<HealthComponent>().getHealth() < 1) {
std::cout << "Player2 wins!" << std::endl; std::cout << "Player2 wins!" << std::endl;
winner = false; winner = false;
isRunning = false; isRunning = false;
@ -259,7 +252,7 @@ void Game::addTile(int id, int x, int y)
auto& tile(manager.addEntity()); auto& tile(manager.addEntity());
tile.addComponent<TileComponent>(x, y, TILE_SIZE, TILE_SIZE, id); tile.addComponent<TileComponent>(x, y, TILE_SIZE, TILE_SIZE, id);
if (id == 1) tile.addComponent<ColliderComponent>("water"); if (id == 1) tile.addComponent<ColliderComponent>("water");
tile.addGroup((size_t)GroupLabel::MAP); tile.addGroup((size_t)GroupLabel::MAPTILES);
} }
bool Game::running() const bool Game::running() const

View File

@ -2,12 +2,7 @@
#include <algorithm> #include <algorithm>
#include "Entity.h" #include "Constants.h"
void Manager::update()
{
for (auto& e : entities) e->update();
}
void Manager::draw() void Manager::draw()
{ {
@ -18,7 +13,7 @@ void Manager::refresh()
{ {
for (auto i(0u); i < MAX_GROUPS; i++) for (auto i(0u); i < MAX_GROUPS; i++)
{ {
auto& v(groupedEntities[i]); auto& v(entitiesByGroup[i]);
v.erase( v.erase(
std::remove_if(std::begin(v), std::end(v), std::remove_if(std::begin(v), std::end(v),
[i](Entity* mEntity) [i](Entity* mEntity)
@ -27,6 +22,17 @@ void Manager::refresh()
}), std::end(v)); }), std::end(v));
} }
for (auto i(0u); i < MAX_TEAMS; i++)
{
auto& v(entitiesByTeam[i]);
v.erase(
std::remove_if(std::begin(v), std::end(v),
[i](Entity* mEntity)
{
return !mEntity->isActive() || (size_t)(mEntity->getTeam()) != i;
}), std::end(v));
}
entities.erase(std::remove_if(std::begin(entities), std::end(entities), entities.erase(std::remove_if(std::begin(entities), std::end(entities),
[](const std::unique_ptr<Entity>& mEntity) [](const std::unique_ptr<Entity>& mEntity)
{ {
@ -35,14 +41,29 @@ void Manager::refresh()
std::end(entities)); std::end(entities));
} }
void Manager::update()
{
for (auto& e : entities) e->update();
}
void Manager::addToGroup(Entity* mEntity, Group mGroup) void Manager::addToGroup(Entity* mEntity, Group mGroup)
{ {
groupedEntities[mGroup].emplace_back(mEntity); entitiesByGroup[mGroup].emplace_back(mEntity);
} }
std::vector<Entity*>& Manager::getGroup(Group mGroup) std::vector<Entity*>& Manager::getGroup(Group mGroup)
{ {
return groupedEntities[mGroup]; return entitiesByGroup[mGroup];
}
void Manager::addToTeam(Entity* mEntity, Team mTeam)
{
entitiesByTeam[mTeam].emplace_back(mEntity);
}
std::vector<Entity*>& Manager::getTeam(Team mTeam)
{
return entitiesByTeam[mTeam];
} }
Entity& Manager::addEntity() Entity& Manager::addEntity()

1
src/PlayerComponent.cpp Normal file
View File

@ -0,0 +1 @@
#include "PlayerComponent.h"

View File

@ -1,5 +1,7 @@
#include "Powerup.h" #include "Powerup.h"
#include "CollisionHandler.h"
#include "Entity.h"
#include "TextureDict.h" #include "TextureDict.h"
#include <SDL.h> #include <SDL.h>
#include "Constants.h" #include "Constants.h"
@ -17,7 +19,7 @@ Vector2D Powerup::calculateSpawnPosition()
spawnRect.x = rand() % (SCREEN_SIZE_WIDTH - spawnRect.w); spawnRect.x = rand() % (SCREEN_SIZE_WIDTH - spawnRect.w);
spawnRect.y = rand() % (SCREEN_SIZE_HEIGHT - spawnRect.h); spawnRect.y = rand() % (SCREEN_SIZE_HEIGHT - spawnRect.h);
conflict = false; conflict = false;
for (auto cc : Game::colliders) for (auto cc : Game::collisionHandler->getColliders(GroupLabel::MAPTILES))
{ {
if (SDL_HasIntersection(&spawnRect, &cc->collider) && strcmp(cc->tag, "projectile")) if (SDL_HasIntersection(&spawnRect, &cc->collider) && strcmp(cc->tag, "projectile"))
{ {

View File

@ -1,5 +1,12 @@
#include "TransformComponent.h" #include "TransformComponent.h"
#include "CollisionHandler.h"
#include "ColliderComponent.h"
#include "Constants.h" #include "Constants.h"
#include "Entity.h"
#include "Game.h"
#include "Vector2D.h"
#include <iostream>
TransformComponent::TransformComponent() TransformComponent::TransformComponent()
{ {
@ -44,12 +51,42 @@ void TransformComponent::update()
// if(velocity.x != 0 && velocity.y != 0) // if(velocity.x != 0 && velocity.y != 0)
float multiplier = velocity.x != 0 && velocity.y != 0 ? 0.707 : 1; //normalizes vector float multiplier = velocity.x != 0 && velocity.y != 0 ? 0.707 : 1; //normalizes vector
Vector2D newPos( Vector2D positionChange(
position.x + velocity.x * speed * multiplier, velocity.x * speed * multiplier,
position.y + velocity.y * speed * multiplier velocity.y * speed * multiplier
); );
if (newPos.x < 0 || newPos.x + (this->width * this->scale) > SCREEN_SIZE_WIDTH || newPos.y < 0 || newPos.y + (this->height * this->scale) > SCREEN_SIZE_HEIGHT)
return;
position = newPos; // TODO: move to separate functions
}
if (this->entity->hasGroup((size_t) GroupLabel::PLAYERS)) {
IntersectionBitSet intersectionsX = CollisionHandler::getIntersectionWithBounds(entity, positionChange);
for (auto& collider : Game::collisionHandler->getColliders(GroupLabel::MAPTILES)) {
intersectionsX |= CollisionHandler::getIntersection(entity, collider->entity, Vector2D(positionChange.x, 0), Vector2D(0, 0));
}
for (auto& collider : Game::collisionHandler->getColliders(GroupLabel::COLLIDERS)) {
intersectionsX |= CollisionHandler::getIntersection(entity, collider->entity, Vector2D(positionChange.x, 0), Vector2D(0, 0));
}
IntersectionBitSet intersectionsY = CollisionHandler::getIntersectionWithBounds(entity, positionChange);
for (auto& collider : Game::collisionHandler->getColliders(GroupLabel::MAPTILES)) {
intersectionsY |= CollisionHandler::getIntersection(entity, collider->entity, Vector2D(0, positionChange.y), Vector2D(0, 0));
}
for (auto& collider : Game::collisionHandler->getColliders(GroupLabel::COLLIDERS)) {
intersectionsY |= CollisionHandler::getIntersection(entity, collider->entity, Vector2D(0, positionChange.y), Vector2D(0, 0));
}
if (intersectionsX.test((size_t) direction::LEFT) && positionChange.x < 0)
positionChange.x = 0;
if (intersectionsX.test((size_t) direction::RIGHT) && positionChange.x > 0)
positionChange.x = 0;
if (intersectionsY.test((size_t) direction::UP) && positionChange.y < 0)
positionChange.y = 0;
if (intersectionsY.test((size_t) direction::DOWN) && positionChange.y > 0)
positionChange.y = 0;
}
position += positionChange;
};

View File

@ -36,6 +36,12 @@ Vector2D& operator/(Vector2D& vector1, const Vector2D& vector2)
vector1.y /= vector2.y; vector1.y /= vector2.y;
return vector1; return vector1;
} }
Vector2D& operator+=(Vector2D& vector1, const Vector2D& vector2)
{
vector1.x += vector2.x;
vector1.y += vector2.y;
return vector1;
}
Vector2D& Vector2D::operator*(const int& i) Vector2D& Vector2D::operator*(const int& i)
{ {
this->x *= i; this->x *= i;