mirror of
https://github.com/Nimac0/SDL_Minigame
synced 2026-01-12 10:13:42 +00:00
Merge branch 'origin/Projectiles' into 'main'
This commit is contained in:
commit
7bc17eb8b9
27
include/AssetManager.h
Normal file
27
include/AssetManager.h
Normal file
@ -0,0 +1,27 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "TextureManager.h"
|
||||
#include "Vector2D.h"
|
||||
#include "Components.h"
|
||||
#include "ECS.h"
|
||||
|
||||
class AssetManager {
|
||||
|
||||
public:
|
||||
|
||||
AssetManager(Manager* manager);
|
||||
~AssetManager();
|
||||
|
||||
void createProjectile(Vector2D pos, Vector2D velocity, bool source, int scale, int range, int speed, const char* texturePath);
|
||||
|
||||
//texture management
|
||||
void addTexture(std::string id, const char* path);
|
||||
|
||||
SDL_Texture* getTexture(std::string id);
|
||||
|
||||
private:
|
||||
|
||||
Manager* man;
|
||||
std::map<std::string, SDL_Texture*> textures;
|
||||
};
|
||||
@ -10,9 +10,11 @@ public:
|
||||
SDL_Rect collider;
|
||||
const char* tag;
|
||||
TransformComponent* transform;
|
||||
bool hasCollision; //added for removing collision of destroyed projectiles
|
||||
|
||||
ColliderComponent(const char* tag);
|
||||
|
||||
void init() override;
|
||||
void update() override;
|
||||
void removeCollision();
|
||||
};
|
||||
@ -2,6 +2,16 @@
|
||||
|
||||
class Entity;
|
||||
|
||||
enum class GroupLabel
|
||||
{
|
||||
MAP,
|
||||
PLAYERS,
|
||||
ENEMIES,
|
||||
COLLIDERS,
|
||||
PROJECTILE,
|
||||
HEARTS
|
||||
};
|
||||
|
||||
class Component
|
||||
{
|
||||
public:
|
||||
|
||||
@ -8,4 +8,5 @@
|
||||
#include "KeyboardController.h"
|
||||
#include "ColliderComponent.h"
|
||||
#include "TileComponent.h"
|
||||
|
||||
#include "ProjectileComponent.h"
|
||||
#include "HealthComponent.h"
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include <array>
|
||||
#include "Constants.h"
|
||||
|
||||
|
||||
class Component;
|
||||
class Entity;
|
||||
class Manager;
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
class AssetManager;
|
||||
class ColliderComponent;
|
||||
|
||||
class Game
|
||||
@ -26,9 +28,15 @@ class Game
|
||||
static SDL_Renderer* renderer;
|
||||
static SDL_Event event;
|
||||
static std::vector<ColliderComponent*> colliders;
|
||||
static AssetManager* assets;
|
||||
|
||||
bool getWinner();
|
||||
|
||||
private:
|
||||
int counter = 0;
|
||||
bool isRunning = false;
|
||||
SDL_Window* window;
|
||||
|
||||
//true for player1 win / false for player2 win;
|
||||
bool winner;
|
||||
};
|
||||
|
||||
65
include/HealthComponent.h
Normal file
65
include/HealthComponent.h
Normal file
@ -0,0 +1,65 @@
|
||||
#include "Components.h"
|
||||
|
||||
class HealthComponent : public Component {
|
||||
|
||||
public:
|
||||
|
||||
HealthComponent(int health, Manager* manager, bool player) : health(health), manager(manager), player(player) {}
|
||||
|
||||
~HealthComponent() {}
|
||||
|
||||
void getDamage() {
|
||||
this->health--;
|
||||
}
|
||||
|
||||
int getHealth() {
|
||||
return this->health;
|
||||
}
|
||||
|
||||
void init() override
|
||||
{
|
||||
createAllHearts();
|
||||
}
|
||||
|
||||
void createAllHearts() {
|
||||
|
||||
int x; //starting position for first health icon
|
||||
|
||||
if(player) {
|
||||
x = 10;
|
||||
} else {
|
||||
x = 750;
|
||||
}
|
||||
|
||||
for(int i = 0; i < health; i++) {
|
||||
|
||||
//checks for player side
|
||||
if(player) {
|
||||
createHeartComponents(x);
|
||||
x += 50;
|
||||
continue;
|
||||
}
|
||||
|
||||
createHeartComponents(x);
|
||||
x -= 50;
|
||||
}
|
||||
}
|
||||
|
||||
void createHeartComponents(int x) {
|
||||
|
||||
auto& heart(manager->addEntity());
|
||||
heart.addComponent<TransformComponent>(x,5,1);
|
||||
heart.addComponent<SpriteComponent>("assets/chicken_neutral_knight.png");
|
||||
heart.addGroup((size_t)GroupLabel::HEARTS);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
int health;
|
||||
|
||||
Manager* manager;
|
||||
|
||||
bool player; //true if player1 / false if player2
|
||||
|
||||
};
|
||||
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "SDL.h"
|
||||
#include "Component.h"
|
||||
#include "Vector2D.h"
|
||||
|
||||
class TransformComponent;
|
||||
|
||||
@ -13,12 +14,21 @@ public:
|
||||
SDL_Scancode down;
|
||||
SDL_Scancode left;
|
||||
SDL_Scancode right;
|
||||
//SDL_Scancode action;
|
||||
SDL_Scancode fire;
|
||||
|
||||
//for attack cooldown in between shots
|
||||
Uint32 lastFireTime;
|
||||
Uint32 fireCooldown = 1000; //in ms can be adjusted to change possible attack-speed
|
||||
|
||||
KeyboardController() = default;
|
||||
KeyboardController(SDL_Scancode up, SDL_Scancode down, SDL_Scancode left, SDL_Scancode right/*, SDL_Scancode action*/);
|
||||
KeyboardController(SDL_Scancode up, SDL_Scancode down, SDL_Scancode left, SDL_Scancode right, SDL_Scancode fire, Vector2D fireVelocity);
|
||||
~KeyboardController() = default;
|
||||
|
||||
void init() override;
|
||||
void update() override;
|
||||
|
||||
private:
|
||||
//for creation of projectiles
|
||||
TransformComponent* player; //for starting position of projectile
|
||||
Vector2D fireVelocity; //decide source of projectile and flying direction
|
||||
};
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "Constants.h"
|
||||
|
||||
|
||||
53
include/ProjectileComponent.h
Normal file
53
include/ProjectileComponent.h
Normal file
@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
#include "ECS.h"
|
||||
#include "Components.h"
|
||||
#include "Vector2D.h"
|
||||
|
||||
class ProjectileComponent : public Component {
|
||||
|
||||
//can maybe be split in separate .cpp file
|
||||
|
||||
public:
|
||||
|
||||
ProjectileComponent(int range, int speed, Vector2D velocity, bool source) : range(range), speed(speed), velocity(velocity), source(source) {
|
||||
|
||||
}
|
||||
|
||||
~ProjectileComponent() {}
|
||||
|
||||
void init() override {
|
||||
transformComponent = &entity->getComponent<TransformComponent>();
|
||||
}
|
||||
|
||||
void update() override {
|
||||
|
||||
transformComponent->velocity = velocity;
|
||||
|
||||
distance += speed;
|
||||
|
||||
if (distance > range) {
|
||||
entity->destroy();
|
||||
entity->getComponent<ColliderComponent>().removeCollision();
|
||||
//std::cout << "out of range" << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool getSource() {
|
||||
return this->source;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
TransformComponent* transformComponent;
|
||||
|
||||
int range = 0;
|
||||
int speed = 0;
|
||||
int distance = 0;
|
||||
|
||||
const bool source; //true if from player1 / false if from player2
|
||||
|
||||
Vector2D velocity;
|
||||
};
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "SDL.h"
|
||||
#include "Component.h"
|
||||
#include "Game.h"
|
||||
|
||||
class TransformComponent;
|
||||
|
||||
|
||||
28
src/AssetManager.cpp
Normal file
28
src/AssetManager.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "AssetManager.h"
|
||||
#include "Component.h"
|
||||
#include "Components.h"
|
||||
#include <cstddef>
|
||||
|
||||
AssetManager::AssetManager(Manager* manager) : man(manager) {
|
||||
|
||||
}
|
||||
|
||||
AssetManager::~AssetManager() {}
|
||||
|
||||
void AssetManager::addTexture(std::string id, const char* path) {
|
||||
textures.emplace(id, TextureManager::get().loadTexture(path));
|
||||
}
|
||||
|
||||
SDL_Texture* AssetManager::getTexture(std::string id) {
|
||||
return textures.at(id);
|
||||
}
|
||||
|
||||
void AssetManager::createProjectile(Vector2D pos, Vector2D velocity, bool source, int scale, int range, int speed, const char* texturePath) {
|
||||
|
||||
auto& projectile(man->addEntity());
|
||||
projectile.addComponent<TransformComponent>(pos.x, pos.y, 32, 32, scale); //32x32 is standard size for objects
|
||||
projectile.addComponent<SpriteComponent>(texturePath);
|
||||
projectile.addComponent<ProjectileComponent>(range, speed, velocity, source);
|
||||
projectile.addComponent<ColliderComponent>("projectile");
|
||||
projectile.addGroup((size_t)GroupLabel::PROJECTILE);
|
||||
}
|
||||
@ -6,6 +6,7 @@
|
||||
ColliderComponent::ColliderComponent(const char* tag)
|
||||
{
|
||||
this->tag = tag;
|
||||
this->hasCollision = true;
|
||||
}
|
||||
|
||||
void ColliderComponent::init()
|
||||
@ -26,3 +27,8 @@ void ColliderComponent::update()
|
||||
collider.w = transform->width * transform->scale;
|
||||
collider.h = transform->height * transform->scale;
|
||||
}
|
||||
|
||||
void ColliderComponent::removeCollision()
|
||||
{
|
||||
this->hasCollision = false;
|
||||
}
|
||||
103
src/Game.cpp
103
src/Game.cpp
@ -9,10 +9,13 @@
|
||||
#include "ColliderComponent.h"
|
||||
#include "SpriteComponent.h"
|
||||
#include "KeyboardController.h"
|
||||
#include "AssetManager.h"
|
||||
|
||||
Map* map;
|
||||
Manager manager;
|
||||
|
||||
AssetManager* Game::assets = new AssetManager(&manager);
|
||||
|
||||
SDL_Renderer* Game::renderer = nullptr;
|
||||
|
||||
SDL_Event Game::event;
|
||||
@ -22,14 +25,7 @@ std::vector<ColliderComponent*> Game::colliders;
|
||||
auto& player(manager.addEntity());
|
||||
auto& enemy(manager.addEntity());
|
||||
auto& wall(manager.addEntity());
|
||||
|
||||
enum class GroupLabel
|
||||
{
|
||||
MAP,
|
||||
PLAYERS,
|
||||
ENEMIES,
|
||||
COLLIDERS
|
||||
};
|
||||
//auto& projectile (manager.addEntity());
|
||||
|
||||
Game::Game() = default;
|
||||
|
||||
@ -68,22 +64,37 @@ void Game::init(const char* title, int xpos, int ypos, int width, int height, bo
|
||||
map = new Map();
|
||||
map->loadMap("assets/SDL_map_test.txt", 25, 20);
|
||||
|
||||
//adding textures to the library in AssetManager
|
||||
|
||||
assets->addTexture("player1", "assets/chicken_neutral_knight.png");
|
||||
assets->addTexture("player2", "assets/chicken_neutral.png");
|
||||
assets->addTexture("bigEgg", "assets/bigger_egg.png");
|
||||
|
||||
|
||||
//ecs implementation
|
||||
|
||||
player.addComponent<TransformComponent>(0,0,2); //posx, posy, scale
|
||||
player.addComponent<TransformComponent>(80,80,2); //posx, posy, scale
|
||||
player.addComponent<SpriteComponent>("assets/chicken_neutral_knight.png"); //adds sprite (32x32px), path needed
|
||||
player.addComponent<KeyboardController>(SDL_SCANCODE_W, SDL_SCANCODE_S, SDL_SCANCODE_A, SDL_SCANCODE_D);//custom keycontrols can be added
|
||||
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
|
||||
player.addComponent<ColliderComponent>("player"); //adds tag (for further use, reference tag)
|
||||
player.addComponent<HealthComponent>(5, &manager, true);
|
||||
player.addGroup((size_t)GroupLabel::PLAYERS); //tell programm what group it belongs to for rendering order
|
||||
|
||||
enemy.addComponent<TransformComponent>(600, 500, 2);
|
||||
enemy.addComponent<SpriteComponent>("assets/chicken_neutral.png");
|
||||
enemy.addComponent<KeyboardController>(SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT);
|
||||
enemy.addComponent<KeyboardController>(SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_RCTRL, Vector2D(-1, 0));
|
||||
enemy.addComponent<ColliderComponent>("enemy");
|
||||
enemy.addComponent<HealthComponent>(5, &manager, false);
|
||||
enemy.addGroup((size_t)GroupLabel::ENEMIES);
|
||||
|
||||
}
|
||||
|
||||
auto& tiles(manager.getGroup((size_t)GroupLabel::MAP));
|
||||
auto& players(manager.getGroup((size_t)GroupLabel::PLAYERS));
|
||||
auto& enemies(manager.getGroup((size_t)GroupLabel::ENEMIES));
|
||||
auto& projectiles(manager.getGroup((size_t)GroupLabel::PROJECTILE));
|
||||
auto& hearts(manager.getGroup((size_t)GroupLabel::HEARTS));
|
||||
|
||||
void Game::handleEvents()
|
||||
{
|
||||
SDL_PollEvent(&event);
|
||||
@ -108,20 +119,63 @@ void Game::update()
|
||||
|
||||
for (auto cc : colliders)
|
||||
{
|
||||
if (SDL_HasIntersection(&player.getComponent<ColliderComponent>().collider, &cc->collider) && strcmp(cc->tag, "player"))
|
||||
if (SDL_HasIntersection(&player.getComponent<ColliderComponent>().collider, &cc->collider) && strcmp(cc->tag, "player") && cc->hasCollision)
|
||||
{
|
||||
player.getComponent<TransformComponent>().position = playerPos;
|
||||
}
|
||||
if (SDL_HasIntersection(&enemy.getComponent<ColliderComponent>().collider, &cc->collider) && strcmp(cc->tag, "enemy"))
|
||||
if (SDL_HasIntersection(&enemy.getComponent<ColliderComponent>().collider, &cc->collider) && strcmp(cc->tag, "enemy") && cc->hasCollision)
|
||||
{
|
||||
enemy.getComponent<TransformComponent>().position = enemyPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto& tiles(manager.getGroup((size_t)GroupLabel::MAP));
|
||||
auto& players(manager.getGroup((size_t)GroupLabel::PLAYERS));
|
||||
auto& enemies(manager.getGroup((size_t)GroupLabel::ENEMIES));
|
||||
//checking if projectiles hit player1 or player2
|
||||
for (auto& p : projectiles) {
|
||||
if(SDL_HasIntersection(&enemy.getComponent<ColliderComponent>().collider, &p->getComponent<ColliderComponent>().collider)
|
||||
&& (p->getComponent<ColliderComponent>().hasCollision) && !p->getComponent<ProjectileComponent>().getSource()) {
|
||||
//std::cout << "Enemy hit!";
|
||||
p->getComponent<ColliderComponent>().removeCollision();
|
||||
p->destroy();
|
||||
|
||||
enemy.getComponent<HealthComponent>().getDamage();
|
||||
|
||||
//display updated health | pretty scuffed but works ig
|
||||
for(auto h : hearts)
|
||||
h->destroy();
|
||||
|
||||
player.getComponent<HealthComponent>().createAllHearts();
|
||||
enemy.getComponent<HealthComponent>().createAllHearts();
|
||||
|
||||
if(enemy.getComponent<HealthComponent>().getHealth() < 1) {
|
||||
std::cout << "Player1 wins!" << std::endl;
|
||||
winner = true;
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(SDL_HasIntersection(&player.getComponent<ColliderComponent>().collider, &p->getComponent<ColliderComponent>().collider)
|
||||
&& (p->getComponent<ColliderComponent>().hasCollision) && p->getComponent<ProjectileComponent>().getSource()) {
|
||||
//std::cout << "Player hit!";
|
||||
p->getComponent<ColliderComponent>().removeCollision();
|
||||
p->destroy();
|
||||
|
||||
player.getComponent<HealthComponent>().getDamage();
|
||||
|
||||
//display updated health
|
||||
for(auto h : hearts)
|
||||
h->destroy();
|
||||
|
||||
player.getComponent<HealthComponent>().createAllHearts();
|
||||
enemy.getComponent<HealthComponent>().createAllHearts();
|
||||
|
||||
if(player.getComponent<HealthComponent>().getHealth() < 1) {
|
||||
std::cout << "Player2 wins!" << std::endl;
|
||||
winner = false;
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::render()
|
||||
{
|
||||
@ -138,6 +192,12 @@ void Game::render()
|
||||
{
|
||||
e->draw();
|
||||
}
|
||||
for (auto& p : projectiles)
|
||||
p->draw();
|
||||
|
||||
for (auto& h : hearts)
|
||||
h->draw();
|
||||
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
@ -153,10 +213,7 @@ void Game::addTile(int id, int x, int y)
|
||||
{
|
||||
auto& tile(manager.addEntity());
|
||||
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);
|
||||
}
|
||||
|
||||
@ -164,3 +221,7 @@ bool Game::running() const
|
||||
{
|
||||
return isRunning;
|
||||
}
|
||||
|
||||
bool Game::getWinner() {
|
||||
return this->winner;
|
||||
}
|
||||
@ -1,13 +1,16 @@
|
||||
#include "KeyboardController.h"
|
||||
#include "TransformComponent.h"
|
||||
#include "Entity.h"
|
||||
#include "AssetManager.h"
|
||||
|
||||
KeyboardController::KeyboardController(SDL_Scancode up, SDL_Scancode down, SDL_Scancode left, SDL_Scancode right)
|
||||
KeyboardController::KeyboardController(SDL_Scancode up, SDL_Scancode down, SDL_Scancode left, SDL_Scancode right, SDL_Scancode fire, Vector2D fireVelocity)
|
||||
{
|
||||
this->up = up;
|
||||
this->down = down;
|
||||
this->left = left;
|
||||
this->right = right;
|
||||
this->fire = fire;
|
||||
this->fireVelocity = fireVelocity;
|
||||
}
|
||||
|
||||
void KeyboardController::init()
|
||||
@ -32,4 +35,28 @@ void KeyboardController::update()
|
||||
if (keystates[this->right]) {
|
||||
transform->velocity.x = 1;
|
||||
}
|
||||
|
||||
if (keystates[this->fire]) {
|
||||
|
||||
Uint32 currentTicks = SDL_GetTicks();
|
||||
|
||||
if (currentTicks - lastFireTime >= fireCooldown) {
|
||||
|
||||
player = &entity->getComponent<TransformComponent>();
|
||||
|
||||
//checks player source via the firing velocity
|
||||
//TODO: adding actual projectile textures
|
||||
if(fireVelocity.x > 0) {
|
||||
Game::assets->createProjectile(Vector2D(player->position.x, player->position.y), fireVelocity,
|
||||
false,1, 180, 1, "assets/chicken_neutral_knight.png");
|
||||
}
|
||||
else {
|
||||
Game::assets->createProjectile(Vector2D(player->position.x, player->position.y), fireVelocity,
|
||||
true,1, 180, 1, "assets/chicken_neutral_knight.png");
|
||||
}
|
||||
|
||||
lastFireTime = currentTicks;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -10,7 +10,7 @@ SpriteComponent::SpriteComponent(const char* path)
|
||||
|
||||
SpriteComponent::~SpriteComponent()
|
||||
{
|
||||
SDL_DestroyTexture(this->texture);
|
||||
// SDL_DestroyTexture(this->texture);
|
||||
}
|
||||
|
||||
void SpriteComponent::setTexture(const char* path)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user