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

Implemented powerups

This commit is contained in:
Nimac0 2024-01-30 05:05:42 +01:00
parent a9f9931101
commit c49ce18ed0
17 changed files with 246 additions and 81 deletions

View File

@ -1,5 +1,5 @@
#pragma once
#include <stdint.h>
#include <cstdint>
struct Animation
{
uint8_t index;

View File

@ -1,14 +1,20 @@
#include "Entity.h"
#pragma once
#include <SDL_render.h>
#include <map>
#include <string>
#include "Powerup.h"
#include "Entity.h"
class Vector2D;
class Manager;
enum class PowerupType
{
HEART,
WALKINGSPEED,
SHOOTINGSPEED
};
class AssetManager
{
public:
@ -19,6 +25,9 @@ public:
void createProjectile(Vector2D pos, Vector2D velocity, bool source, int scale, int range, int speed, const char* texturePath, TeamLabel teamLabel);
void createPowerup(Vector2D pos, PowerupType type);
Vector2D calculateSpawnPosition();
PowerupType calculateType();
//texture management
void addTexture(std::string id, const char* path);

View File

@ -7,6 +7,7 @@ using Team = std::size_t;
constexpr std::size_t MAX_COMPONENTS = 32;
constexpr std::size_t MAX_GROUPS = 32;
constexpr std::size_t MAX_STATS = 32;
constexpr std::size_t MAX_TEAMS = 8; //
constexpr int SCREEN_SIZE_HEIGHT = 640;
@ -21,3 +22,7 @@ constexpr int MAP_SIZE_Y = 20;
constexpr int SPAWN_ATTEMPTS = 30;
constexpr int BUFF_DURATION = 5000;
constexpr int BUFF_VALUE = 1;

View File

@ -3,6 +3,7 @@
#include "Component.h"
#include "Vector2D.h"
#include "Constants.h"
class TransformComponent;
class SpriteComponent;
@ -31,6 +32,8 @@ public:
void init() override;
void update() override;
void modifyAtkSpeed(int8_t modifier);
private:
//for creation of projectiles
TransformComponent* player; //for starting position of projectile

View File

@ -1,26 +0,0 @@
#pragma once
#include "Component.h"
#include "Manager.h"
#include "Vector2D.h"
#include <map>
enum class PowerupType
{
HEART,
WALKINGSPEED,
SHOOTINGSPEED
};
class Powerup
{
public:
Powerup(){}
~Powerup(){}
static Vector2D calculateSpawnPosition();
static PowerupType calculateType();
private:
Manager* manager;
};

View File

@ -0,0 +1,19 @@
#pragma once
#include "Component.h"
#include "AssetManager.h"
class PowerupComponent : public Component
{
public:
PowerupComponent(PowerupType type);
~PowerupComponent() {};
void update() override;
void heartEffect(Entity* player);
void movementSpeedEffect(Entity* player);
void atkSpeedEffect(Entity* player);
private:
void (PowerupComponent::*pickupFunc)(Entity* player);
};

View File

@ -2,6 +2,7 @@
#include "Component.h"
#include "Vector2D.h"
#include "Constants.h"
class TransformComponent;

View File

@ -0,0 +1,27 @@
#pragma once
#include "Component.h"
#include "Constants.h"
#include <cstdint>
#include <array>
enum class Stats
{
MOVEMENT_SPEED,
ATTACK_SPEED
};
class StatEffectsComponent : public Component{
public:
StatEffectsComponent() {};
~StatEffectsComponent() {};
void init() override;
void update() override;
void modifyStatDur(Stats stat, uint8_t duration);
void modifyStatValue(Stats stat, int modifier);
private:
std::array<int8_t, MAX_STATS> buffs = { 0 };
};

View File

@ -2,7 +2,7 @@
#include <map>
#include <string>
#include "Powerup.h"
#include "AssetManager.h"
class TextureDict
{

View File

@ -2,6 +2,7 @@
#include "Component.h"
#include "Vector2D.h"
#include "Constants.h"
class TransformComponent : public Component
{
@ -23,4 +24,5 @@ public:
void init() override;
void update() override;
void modifySpeed(int8_t modifier);
};

View File

@ -1,9 +1,19 @@
#include "AssetManager.h"
#include "Entity.h"
#include "TextureManager.h"
#include "Components.h"
#include "TransformComponent.h"
#include "CollisionHandler.h"
#include "ColliderComponent.h"
#include "Constants.h"
#include "Entity.h"
#include "Game.h"
#include "Vector2D.h"
#include "PowerupComponent.h"
#include <iostream>
AssetManager::AssetManager(Manager* manager) : man(manager) {}
AssetManager::~AssetManager() {}
@ -45,5 +55,37 @@ void AssetManager::createPowerup(Vector2D pos, PowerupType type) {
}
powerups.addComponent<ColliderComponent>("powerup", 0.6f);
powerups.addComponent<PowerupComponent>(type);
powerups.addGroup((size_t)GroupLabel::POWERUPS);
}
Vector2D AssetManager::calculateSpawnPosition()
{
Vector2D spawnPos = Vector2D(-1, -1);
bool conflict = false;
for (int i = 0; i <= SPAWN_ATTEMPTS; i++)
{
SDL_Rect spawnRect;
spawnRect.h = spawnRect.w = 32;
spawnRect.x = rand() % (SCREEN_SIZE_WIDTH - spawnRect.w);
spawnRect.y = rand() % (SCREEN_SIZE_HEIGHT - spawnRect.h);
conflict = false;
for (auto cc : Game::collisionHandler->getColliders({ GroupLabel::MAPTILES }))
{
if (SDL_HasIntersection(&spawnRect, &cc->collider) && strcmp(cc->tag, "projectile"))
{
conflict = true;
break;
}
}
if (conflict) continue;
spawnPos = Vector2D(spawnRect.x, spawnRect.y);
}
return spawnPos;
}
PowerupType AssetManager::calculateType()
{
PowerupType type = PowerupType(rand() % 3);
return type;
}

View File

@ -9,7 +9,7 @@
#include "HealthComponent.h"
#include "Map.h"
#include "TextureManager.h"
#include "Powerup.h"
#include "StatEffectsComponent.h"
Map* map;
Manager manager;
@ -122,6 +122,7 @@ void Game::init(const char* title, int xpos, int ypos, int width, int height, bo
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
player1.addComponent<ColliderComponent>("player", 0.8f); //adds tag (for further use, reference tag)
player1.addComponent<HealthComponent>(5, Direction::LEFT);
player1.addComponent<StatEffectsComponent>();
player1.addGroup((size_t) GroupLabel::PLAYERS); //tell programm what group it belongs to for rendering order
@ -131,6 +132,7 @@ void Game::init(const char* title, int xpos, int ypos, int width, int height, bo
player2.addComponent<KeyboardController>(SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_RCTRL, Vector2D(-1, 0));
player2.addComponent<ColliderComponent>("enemy", 0.8f);
player2.addComponent<HealthComponent>(5, Direction::RIGHT);
player2.addComponent<StatEffectsComponent>();
player2.addGroup((size_t) GroupLabel::PLAYERS);
}
@ -167,7 +169,7 @@ void Game::update()
if (powerupSpawn == 0)
{
assets->createPowerup(Powerup::calculateSpawnPosition(), Powerup::calculateType());
assets->createPowerup(assets->calculateSpawnPosition(), assets->calculateType());
}
// needs to be in game.cpp to have access to internal functions

View File

@ -71,4 +71,10 @@ void KeyboardController::update()
}
}
}
void KeyboardController::modifyAtkSpeed(int8_t modifier)
{
this->fireCooldown -= modifier * 500;
std::cout << "curr fire cooldown: " << this->fireCooldown << std::endl;
}

View File

@ -1,40 +0,0 @@
#include "Powerup.h"
#include "CollisionHandler.h"
#include "Entity.h"
#include "TextureDict.h"
#include <SDL.h>
#include "Constants.h"
#include "Game.h"
#include "ColliderComponent.h"
Vector2D Powerup::calculateSpawnPosition()
{
Vector2D spawnPos = Vector2D(-1,-1);
bool conflict = false;
for (int i = 0; i <= SPAWN_ATTEMPTS; i++)
{
SDL_Rect spawnRect;
spawnRect.h = spawnRect.w = 32;
spawnRect.x = rand() % (SCREEN_SIZE_WIDTH - spawnRect.w);
spawnRect.y = rand() % (SCREEN_SIZE_HEIGHT - spawnRect.h);
conflict = false;
for (auto cc : Game::collisionHandler->getColliders(GroupLabel::MAPTILES))
{
if (SDL_HasIntersection(&spawnRect, &cc->collider) && strcmp(cc->tag, "projectile"))
{
conflict = true;
break;
}
}
if (conflict) continue;
spawnPos = Vector2D(spawnRect.x, spawnRect.y);
}
return spawnPos;
}
PowerupType Powerup::calculateType()
{
PowerupType type = PowerupType(rand() % 3);
return type;
}

56
src/PowerupComponent.cpp Normal file
View File

@ -0,0 +1,56 @@
#include "PowerupComponent.h"
#include "Game.h"
#include "CollisionHandler.h"
#include "Entity.h"
#include "HealthComponent.h"
#include "StatEffectsComponent.h"
#include "Constants.h"
PowerupComponent::PowerupComponent(PowerupType type)
{
switch (type)
{
case PowerupType::HEART:
this->pickupFunc = (&PowerupComponent::heartEffect);
break;
case PowerupType::WALKINGSPEED:
this->pickupFunc = (&PowerupComponent::movementSpeedEffect);
break;
case PowerupType::SHOOTINGSPEED:
this->pickupFunc = (&PowerupComponent::atkSpeedEffect);
break;
default:
break;
}
}
void PowerupComponent::update()
{
Entity* player;
if ((player = Game::collisionHandler->getAnyIntersection<Entity*>(
entity,
Vector2D(0, 0),
{ GroupLabel::PLAYERS },
{},
true)) != nullptr)
{
std::cout << "collided with powerup" << std::endl;
(this->*pickupFunc)(player);
this->entity->destroy();
}
}
void PowerupComponent::heartEffect(Entity* player)
{
player->getComponent<HealthComponent>().modifyHealth(1);
}
void PowerupComponent::movementSpeedEffect(Entity* player)
{
player->getComponent<StatEffectsComponent>().modifyStatDur(Stats::MOVEMENT_SPEED, BUFF_DURATION);
}
void PowerupComponent::atkSpeedEffect(Entity* player)
{
player->getComponent<StatEffectsComponent>().modifyStatDur(Stats::ATTACK_SPEED, BUFF_DURATION);
}

View File

@ -0,0 +1,54 @@
#include "StatEffectsComponent.h"
#include "Entity.h"
#include "TransformComponent.h"
#include "KeyboardController.h"
#include <algorithm>
#include <iostream>
void StatEffectsComponent::init()
{}
void StatEffectsComponent::update()
{
/*int i = 0;
std::transform(this->buffs.begin(), this->buffs.end(), this->buffs.begin(),
[this, &i](uint8_t statDuration) {
i++;
uint8_t newDur = statDuration - 1;
if (statDuration > 0 && newDur == 0) {
if (statDuration > 1)
std::cout << (int) statDuration << (int) newDur << std::endl;
this->modifyStatValue((Stats)i, BUFF_VALUE * -1);
}
return newDur;
});*/
for (int i = 0; i < MAX_STATS; i++)
{
if (this->buffs.at(i) == 0) continue;
if (this->buffs.at(i) - 1 == 0)
{
this->modifyStatValue((Stats)i, BUFF_VALUE * -1);
}
this->buffs.at(i) -= 1;
}
}
void StatEffectsComponent::modifyStatDur(Stats stat, uint8_t duration)
{
if(this->buffs.at((uint8_t)stat) == 0) this->modifyStatValue(stat, BUFF_VALUE);
this->buffs.at((uint8_t)stat) += duration;
}
void StatEffectsComponent::modifyStatValue(Stats stat, int modifier)
{
switch (stat)
{
case Stats::MOVEMENT_SPEED:
this->entity->getComponent<TransformComponent>().modifySpeed(modifier);
break;
case Stats::ATTACK_SPEED:
this->entity->getComponent<KeyboardController>().modifyAtkSpeed(modifier);
break;
default: break;
}
}

View File

@ -60,21 +60,26 @@ void TransformComponent::update()
// TODO: move to separate functions
if (this->entity->hasGroup((size_t) GroupLabel::PLAYERS)) {
if (this->entity->hasGroup((size_t)GroupLabel::PLAYERS)) {
IntersectionBitSet intersections =
(CollisionHandler::getIntersectionWithBounds(entity, Vector2D(positionChange.x, 0)) |
(Game::collisionHandler->getAnyIntersection<IntersectionBitSet>(entity, Vector2D(positionChange.x, 0), {GroupLabel::MAPTILES, GroupLabel::COLLIDERS})) &
(Game::collisionHandler->getAnyIntersection<IntersectionBitSet>(entity, Vector2D(positionChange.x, 0), { GroupLabel::MAPTILES, GroupLabel::COLLIDERS })) &
IntersectionBitSet("0011")) |
(CollisionHandler::getIntersectionWithBounds(entity, Vector2D(0, positionChange.y)) |
(Game::collisionHandler->getAnyIntersection<IntersectionBitSet>(entity, Vector2D(0, positionChange.y), {GroupLabel::MAPTILES, GroupLabel::COLLIDERS})) &
(Game::collisionHandler->getAnyIntersection<IntersectionBitSet>(entity, Vector2D(0, positionChange.y), { GroupLabel::MAPTILES, GroupLabel::COLLIDERS })) &
IntersectionBitSet("1100"));
if (intersections.test((size_t) direction::LEFT) || intersections.test((size_t) direction::RIGHT))
positionChange.x = 0;
if (intersections.test((size_t)direction::LEFT) || intersections.test((size_t)direction::RIGHT))
positionChange.x = 0;
if (intersections.test((size_t) direction::UP) || intersections.test((size_t) direction::DOWN))
if (intersections.test((size_t)direction::UP) || intersections.test((size_t)direction::DOWN))
positionChange.y = 0;
}
position += positionChange;
};
}
void TransformComponent::modifySpeed(int8_t modifier)
{
this->speed += modifier * 2;
}