How to handle collisions in a 2d console game - c++

I'm making a simple console game using windows.h library. Class Game has a map, which is an array of type CHAR_INFO (structure of unicode symbol and its color). This class also has an array of Enemy and Projectile objects. Every iteration game updates the position of each object in the game using Entity's method called move(), which calculates the next position of an entity and checks if there is a symbol which represents an enemy or a projectile. If there is, method move() calls one of these functions:
virtual bool onProjectileCollision() = 0; //collision methods return 0 if the entity is dead
virtual bool onEnemyCollision() = 0;
these functions are overriden by Enemy and Projectile classes like this:
bool onProjectileCollision() override {
return 1;
};
bool onEnemyCollision() override {
return 1;
};
The problem is that I don't know which object the entity collides with (I know only its class), therefore i can't call any method of this object:
class Enemy : public Entity {
int hp;
public:
void die() {
hp = 0;
}
bool onProjectileCollision() override {
die(); //I can do this
return 1;
};
}
class Projectile : public Entity {
public:
bool onEnemyCollision() override {
enemy.die(); // but I can't do this
return 0;
};
}
How should i build a connection between these objects ?

Related

How can I create an instance of a variable in an abstract class

I handed in a remake of an old game in C++ using SDL2 for a programming course that I took, I passed but the professor left me some feedback and there is one part that I couldn't understand. It made sense when he said it and when I tried implementing it I got stuck.
I have an Enemy class which is an abstract class and then many different enemies that inherit from that class. The issue is that when I am creating an enemy I have to pass in its constructor my ProjectileManager* instance that I have created in my main controlling file called Game.cpp. He said that since all enemies need the ProjectileManager it would be smarter to just add it in the Enemies class as protected and have the other children inherit it.
The issue is that the instance is created in the Game.cpp and I have to pass that specific instance since that is the one that I am Drawing and Updating for. Is there a way to do that?
Edit: Here is some of the code
Game.cpp:
void Game::Initialize()
{
m_pProjectileManager = new ProjectileManager();
}
The projectile manager is what Updates and Draws all the projectiles as well as their hit logic etc.
It has an array that manages all the projectiles.
Every time an enemy wants to shoot it would access the projectile manager (that I passed in its constructor) and trigger the shoot function of the specific enemy:
void Plant::Shoot(const Point2f& target)
{
if (m_CanShoot)
{
m_CurrentState = Plant::PlantState::shooting;
m_pProjectileManager->AddProjectile((new PlantProjectile(Point2f{ m_Shape.left, m_Shape.bottom }, target)));
m_CanShoot = false;
m_TimeSinceLastShot = 0;
}
}
Finally this is the Enemy class that I have right now:
class Enemies
{
public:
virtual ~Enemies() = 0;
virtual void Update(float elapsedSec, const Point2f& playerPos, Level& level) = 0;
virtual void Draw() const = 0;
virtual Rectf GetShape() const = 0;
virtual float GetHealth() const = 0;
virtual void Damage(float damage) = 0;
protected:
ProjectileManager* m_pProjectileManager;
};
If there is only ever one ProjectileManager object in the entire game, there are two "easy" ways to accomplish this, and both have some drawbacks.
First, you could make it a singleton:
class ProjectileManager
{
// stuff....
static ProjectileManager* instance()
{
static ProjectileManager one;
return &one;
}
};
// Game.cpp
void Game::Initialize()
{
// m_pProjectileManager = new ProjectileManager();
m_pProjectileManager = ProjectileManager::instance();
}
// Enemy impl
void Plant::Shoot(const Point2f& target)
{
if (m_CanShoot)
{
m_CurrentState = Plant::PlantState::shooting;
ProjectileManager::instaince()->AddProjectile((new PlantProjectile(Point2f{ m_Shape.left, m_Shape.bottom }, target)));
m_CanShoot = false;
m_TimeSinceLastShot = 0;
}
}
Or you could make it static in Enemy, and provide a function to set it:
class Enemy
{
public:
static SetProjectileManager(ProjectileManager* projectile_manager)
{
m_pProjectileManager = projectile_manager;
}
protected:
static ProjectileManager* m_pProjectileManager;
};
// Game.cpp
void Game::Initialize()
{
m_pProjectileManager = new ProjectileManager();
Enemy::SetProjectileManager(m_pProjectileManager);
}
Without seeing the entire codebase it's hard to know which is the better (of these two) recommendations. Neither is perfect by any means. Singletons have a lot of drawbacks and I hesitate to recommend them much anymore. Static class members are perhaps less of a code smell.
In any case, the best path forward is likely a refactor to pass to the Enemy constructor.
Some further reading:
What are drawbacks or disadvantages of singleton pattern?
Why using static namespace/class member variables is a bad idea in C++?

How do I create multiple objects of a (game character) class dynamically in c++

I have to modify my program and create a new (Gamefigures) class from which my current classes(Rabbit and Hedg) inherit. The code is a small game where two animals race until they reach the goal, but in the second task I have to make sure that it is possible that multiple iterations of these animals can race. (5 vs 5 or X vs X for instance). I am allowed to move some variables or methods to the Gamefigures class. Both of the animals use different rules to walk. How do I make a new class which creates multiple objects dynamically of the same class from which my current classes inherit?
I have tried to use the new expression to create a new object but I don't know if it is the right thing to do.
I tried:
Hedg* nHedg = new Hedg[numFigures];
Here is the rest of my code:
class Hedg: public Gamefigures
{
private:
int salat = 1;
protected:
int position1 = 0;
public:
bool turn(int fields)
{
int counter = 10;
if (fields < 11)//Less than 10 fields
{
while ((counter > 0))
{
if (counter < fields)//max 10 fields
{
fields = counter;
}
position1 += fields;//walk
counter -= fields;
if (counter <= 0)
{
salat = 0;
}
}
getSalat();
return true;
}
else
return false;
}
Hedg()
{
}
int getPosition1()
{
return position1;
}
int getSalat()
{
return salat = 1;
}
int getStock1()
{
return salat;
}
~Hedg()
{
}
};
class Game :public Hedg, public Rabbit
{
private:
int goal = 0;
int numFields = 0;
protected:
Rabbit theRabbit;
Hedg theHedg;
public:
Game();
Game(int numFields);
int getGoal();
int dice();
void doyourturn();
bool getStand();
~Game();
};
Here is the error message:
Error code C4430 missing typespecifier
I think that the polymorphism is what you need for your use case and will solve your problems.
Let's suppose you have a base class for your animals:
class Animal
{
// ...
// Create all the (pure) virtual methods to be redefined by a derived class
virtual void walk() = 0; // For example
};
Then you defines your two specific animals, the rabbit and the hedgehog:
class Rabbit : public Animal
{
// ...
// Redefine here the (pure) virtual methods of Animal for a Rabbit
void walk() override;
};
class HedgeHog : public Animal
{
// ...
// Redefine here the (pure) virtual methods of Animal for a HedgeHog
void walk override;
};
And you can use polymorphism to handle your list of animals:
std::vector<Animal*> race_competitors;
race_competitors.push_back(new Rabbit);
race_competitors.push_back(new HedgeHog);
And this way, when you will call the walk() method over a competitor, it will automatically execute the proper walking rule of the corresponding animal.
Of course, at the end of the race, don't forget to delete the content of the vector because the animals was created with new ("manually" allocated memory, on the heap).
Just for information, the Game class doesn't have to inherit from Rabbit and HedgeHog, it just has to know them as class members, or even better, store a std::vector<Animal*> as a list of competitors.
I hope it will help you to improve your design and solve your problems.

C++ calling method of subclass in superclass?

I have an EnemyBullet subclass of superclass Bullet.
Now I'm calling the Bullet method Process() using an EnemyBullet object.
What I want is to determine whether the current object is an EnemyBullet to distinguish from Bullet action.
My code is like this,
void Bullet::Process(float deltaTime)
{
// Generic position update, based upon velocity (and time).
m_y = m_y + this->GetVerticalVelocity()*deltaTime;
m_pSprite->SetY(static_cast<int>(m_y));
m_pSprite->SetX(static_cast<int>(m_x));
if (m_y < 0)
{
SetDead(true);
}
//Here I want to detect current object is an EnemyBullet, then define a different action
//I tried the following code, but it didn't work
if (EnemyBullet* v = static_cast<EnemyBullet*>(Bullet)) {
if (m_y >800)
{
SetDead(true);
}
}
}
Here's an example of calling a method on an instance of a subclass from a method in the superclass:
class Bullet {
public:
void process() {
// update m_y...
// update sprite position...
if (this->isDead()) {
// handle dead bullet...
}
}
virtual bool isDead() {
return (m_y < 0);
}
protected:
int m_y;
};
class EnemyBullet : public Bullet {
public:
bool isDead() override {
return (m_y > 800);
}
};
Note how each bullet type has custom isDead logic.

Event-based Game engine based on polymorphism of Entities

I would like to create a simple framework for throwing and catching events in a game. Events could be things like a Collision which (according to the type) can take several arguments (note that every Event type may take another amount of arguments, not just two as in the example).
I would then like to implement functions/classes/... to deal with a Collision, based on polymorphism. This example should illustrate the problem:
#include <iostream>
#include <vector>
class Entity {};
class Player: public Entity {};
class Bomb: public Entity {
public:
bool exploded;
};
class MineSweeper: public Entity {};
// For now, I only included Collisions, but I eventually want to extend it to
// more types of Events too (base class Event, Collision is derived class)
void onCollision(Player* p, Bomb* b) {
if (! b->exploded) {
std::cout << "BOOM";
b->exploded = true;
}
}
void onCollision(Entity* e, Entity* f) {
std::cout << "Unhandled collision\n";
}
// Possibility for Collision between Minesweeper and Bomb later
class Game {
public:
std::vector<Entity*> board; // some kind of linear board
Game() {
board = {new Player, new Bomb, new MineSweeper};
}
void main_loop() {
onCollision(board[0], board[1]); // player and bomb!
onCollision(board[1], board[2]);
}
};
int main() {
Game g;
g.main_loop();
}
Note that I understand perfectly well why the above code doesn't work as intended, I included this example solely to illustrate my problem better.
The above example uses functions for the events, but I'm perfectly fine with classes or any other solution that is maintainable.
I hope it is clear that I would like C++ to decide which event handler to use based on the types of the arguments (presumably at runtime).
My question: How can I do this in C++? An example would be appreciated.
(not my question: fix my code please)
user2864740 provided enough clues for me to find a solution myself. Multiple dispatch was indeed the missing piece.
The following code works as intended, making use of dynamic_cast to dispatch correctly.
#include <iostream>
#include <vector>
class Entity {
virtual void please_make_this_polymorphic() {}
// although this function does nothing, it is needed to tell C++ that it
// needs to make Entity polymorphic (and thus needs to know about the type
// of derived classes at runtime).
};
class Player: public Entity {};
class Bomb: public Entity {
public:
bool exploded;
};
class MineSweeper: public Entity {};
// For now, I only included Collisions, but I eventually want to extend it to
// more types of Events too (base class Event, Collision is derived class)
void onCollision(Player* p, Bomb* b) {
if (!b->exploded) {
std::cout << "BOOM\n";
b->exploded = true;
}
}
void onCollision(Entity* e, Entity* f) {
std::cout << "Unhandled collision\n";
}
void dispatchCollision(Entity* e, Entity* f) {
Player* p = dynamic_cast<Player*>(e);
Bomb* b = dynamic_cast<Bomb*>(f);
if (p != nullptr && b != nullptr) {
onCollision(p, b); // player and bomb
} else {
onCollision(e, f); // default
}
}
class Game {
public:
std::vector<Entity*> board; // some kind of linear board
Game() {
board = {new Player, new Bomb, new MineSweeper};
}
void main_loop() {
dispatchCollision(board[0], board[1]); // player and bomb
dispatchCollision(board[1], board[2]);
}
};
int main() {
Game g;
g.main_loop();
}
Although it works, I'd like to point out some problems with this code:
Manual editing of dispatchCollision needed when adding new Collisions.
Currently, the dispatcher using a simple kind of rule-based system. (Does it fit rule 1? What about rule 2? ...) When adding loads of different functions it needs to dispatch, that may have an impact on the performance.
A collision between A and B should be the same as a collision between B and A, but that isn't properly handled yet.
Solving these problems is not necessarily in the scope of this question IMHO.
Also, the example given should work just as well for more than 2 arguments. (Multiple dispatch, not just double dispatch.)
You should decide first what event subscription model you need.
It could be signal/slot mechanism and you can find plenty of libraries:
https://code.google.com/p/cpp-events/ , http://sigslot.sourceforge.net/ and the like.
Or it could be bubbling/sinking events like in HTML DOM when event gets propagated on parent/child chain ( from event source element to its containers).
Or even other schema.
It is quite easy to create whatever you need with std::function holders in modern C++.
Maybe a good structure for your case could be something like this:
class Entity{
public:
virtual int getType() = 0;
};
enum EntityTypes {
ACTOR,
BOMB,
MINESWEEPER,
};
class Actor : public Entity{
public:
virtual int getType() {return int(ACTOR);}
void applyDamage() {
std::cout << "OUCH";
}
};
class Bomb : public Entity{
public:
Bomb() : exploded(false) {}
virtual int getType() {return int(BOMB);}
void explode() {
this->exploded = true;
}
bool isExploded() {
return this->exploded;
}
protected:
bool exploded;
};
class MineSweeper : public Entity{
public:
virtual int getType() {return int(MINESWEEPER);}
};
class CollisionSolver {
public:
virtual solve(Entity* entity0, Entity* entity1) = 0;
};
class ActorBombCollisionSolver : public CollisionSolver {
public:
virtual solve(Entity* entity0, Entity* entity1) {
Actor* actor;
Bomb* bomb;
if (entity0->getType() == ACTOR && entity1->getType() == BOMB) {
actor = static_cast<Actor*>(entity0);
bomb = static_cast<Bomb*>(entity1);
}else if (entity1->getType() == ACTOR && entity0->getType() == BOMB) {
actor = static_cast<Actor*>(entity1);
bomb = static_cast<Bomb*>(entity0);
}else {
//throw error;
}
if (!bomb->isExploded()) {
bomb->explode();
actor->applyDamage();
}
}
};
class CollisionDispatcher {
public:
CollisionDispatcher() {
CollisionSolver* actorBombCollisionSolver = new ActorBombCollisionSolver;
this->solvers[ACTOR][BOMB] = actorBombCollisionSolver;
this->solvers[BOMB][ACTOR] = actorBombCollisionSolver;
// this part wouldn't be necessary if you used smart pointers instead of raw... :)
this->solvers[BOMB][MINESWEEPER] = 0;
this->solvers[MINESWEEPER][BOMB] = 0;
this->solvers[ACTOR][MINESWEEPER] = 0;
this->solvers[MINESWEEPER][ACTOR] = 0;
}
void dispatchCollision(Entity* entity0, Entity* entity1) {
CollisionSolver* solver = this->solvers[entity0->getType()][entity1->getType()];
if (!solver) {
return;
}
solver->solve(entity0, entity1);
}
protected:
unordered_map<int, unordered_map<int, CollisionSolver*> > solvers;
};
class Game {
public:
std::vector<Entity*> board; // some kind of linear board
Game() : dispatcher(new CollisionDispatcher)
{
board = {new Player, new Bomb, new MineSweeper};
}
void main_loop() {
dispatcher->dispatchCollision(board[0], board[1]);
dispatcher->dispatchCollision(board[0], board[2]);
dispatcher->dispatchCollision(board[1], board[2]);
}
protected:
CollisionDispatcher* dispatcher;
};
int main() {
Game g;
g.main_loop();
}
This way you can easily add new collision solvers, just define the class, and register t in the CollisionDispatcher constructor.
If you use smart pointers you won't need to set zeroes in the map entries not registered, but if you use raw pointers you have to set them to zero OR use unordered_map::find method instead of just grabbing the solver using operator []
Hope it helps!

C++ Game AI only works in main

I have a problem getting the AI to work if I do it in a subclass.
Here is my main loop in which I access the player and enemy classes for their move, logic, and show functions.
//Logic
myPlayer.player_move();
myEnemy.enemy_logic();
//Rendering
myPlayer.player_show();
myEnemy.enemy_show();
So I access the Player class's function that moves the player then I access the logic(AI) function of the Enemy Class.
void Enemy::enemy_move(){
eX -= 2;
}
void Enemy::enemy_logic(){
Player myPlayer;
if(myPlayer.x > SCREEN_WIDTH / 2){
enemy_move();
}
}
So if the Players x value is greater than half the screen, I want the enemy to start moving left
I can compile the program but when I move the player past the halfway point of the screen, the enemy does nothing. If I were to put this if statement in the main.cpp then it works fine. Any advice?
It's because you're re-initializing your instance of the class Player. Instead, pass it as a parameter:
void Enemy::enemy_logic(Player myPlayer){
if(myPlayer.x > SCREEN_WIDTH / 2){
enemy_move();
}
}
That way the function uses your instance, and not a new instance in a different scope.
Because you are initializing an instance of Player as myPlayer that is not connected to anything.
You should define a private variable for myPlayer inside your Enemy Class or pass a pointer to the Player class instance as an argument, in this way you will be able to maintain the state.
If your enemies depend on a single player you can "bind" each enmy to a player like this:
class Player
{
Position m_x, m_y, m_z;
public:
Position const & x (void) { return m_x; }
};
class Enemy
{
public:
Enemy (Player &p) : m_player(p) { }
Player & m_player;
void logic (void)
{
if (m_player.x() > SCREEN_WIDTH/2)
{
move_x();
}
}
void move_x (void) { /*...*/ }
};
int main (void)
{
Player the_player;
Enemy the_enemy(the_player);
// move the player
the_enemy.logic(); // the_enemy knows the_player and acts accordingly
}