C++ Game AI only works in main - c++

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
}

Related

How to handle collisions in a 2d console game

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 ?

C++ (Arduino wrapper): variable or field declared void arduino

C++ (Arduino wrapper) question: This is related to this thread on double pointer member access regarding a shoot em up game.
I have a base class (Sprite), and from this other classes are derived - Alien and Player. For collision detection I want to pass pointers to Alien and Player, then access coordinates as in:
void Collision( Alien *pAlien, Player *pPlayer )
{
// obtain alien and player's (x,y) and do collision check here
pAlien->getX();
pPlayer->getX();
}
But after declaring the above function after the class I get this:
error: variable or field 'Collision' declared void
My question is: How can I resolve this? streamlined code and a screen shot are shown below.
/*****************************************************************************************/
// Bass class - has a form/shape, x and y position also has a method of moving
class Sprite
{
public:
Sprite(unsigned char * const spacePtrIn, unsigned int xInit, unsigned int yInit);
protected:
};
/*****************************************************************************************/
// Derived class "Alien" - has a specific form/shape, and specific (x,y) position
class Alien : public Sprite
{
public:
Alien();
virtual void Move();
};
/*****************************************************************************************/
// Derived class "Player" - has a specific form/shape, and specific (x,y) position
class Player : public Sprite
{
public:
Player(): Sprite(&spaceShip[0], xPlayer(), yPlayer()) {}
virtual void Move();
};
/*****************************************************************************************/
/*****************************************************************************************/
void Collision( Alien *pAlien, Player *pPlayer )
{
// obtain alien and player's (x,y) and do collision check here
pAlien->getX();
pPlayer->getX();
}
/*****************************************************************************************/
/*****************************************************************************************/

Embedded C++ Class interaction

I'm continuing with a game for an embedded microcontroller (Arduino), and I have a question on class interaction -- this question continues from my previous question here and I have based my code on the suggestion of sheddenizen (see response to the given link in 'here'):
I have three classes that inherit from a base class-
(i) class Sprite - (bass class) has a bitmap shape and (x,y) position on an LCD
(ii) class Missile : public Sprite - has a specific shape, (x,y) and also takes a obj
(iii) class Alien : public Sprite - has specific shape and (x,y)
(iv) class Player : public Sprite - ""
They all have different (virtual) method of moving and are shown on the LCD:
My streamlined code is below - specifically, I only want the missile to fire under certain conditions: when missile is created it takes an objects (x,y) value, how can I access a passed objects value within an inherited class?
// Bass class - has a form/shape, x and y position
// also has a method of moving, though its not defined what this is
class Sprite
{
public:
Sprite(unsigned char * const spacePtrIn, unsigned int xInit, unsigned int yInit);
virtual void Move() = 0;
void Render() { display.drawBitmap(x,y, spacePtr, 5, 6, BLACK); }
unsigned int X() const { return x; }
unsigned int Y() const { return y; }
protected:
unsigned char *spacePtr;
unsigned int x, y;
};
// Sprite constructor
Sprite::Sprite(unsigned char * const spacePtrIn, unsigned int xInit, unsigned int yInit)
{
x = xInit;
y = yInit;
spacePtr = spacePtrIn;
}
/*****************************************************************************************/
// Derived class "Missile", also a sprite and has a specific form/shape, and specific (x,y) derived from input sprite
// also has a simple way of moving
class Missile : public Sprite
{
public:
Missile(Sprite const &launchPoint): Sprite(&spaceMissile[0], launchPoint.X(), launchPoint.Y()) {}
virtual void Move();
};
void Missile::Move()
{
// Here - how to access launchPoint.X() and launchPoint.Y() to check for
// "fire conditions"
y++;
Render();
}
// create objects
Player HERO;
Alien MONSTER;
Missile FIRE(MONSTER);
// moving objects
HERO.Move();
MONSTER.Move();
FIRE.Move();
Since Missile is a subclass of Sprite you can access Sprite::x and Sprite::y as if they were members of Missile. That is by simply writing x (or this->x if you insist).
The launchpoint reference that you got in the constructor is gone by now, so your Missile::Move memfunction cannot access it any more.
If in the meantime the members x and y changed, but you want the original value, you can either save a reference to launchpoint (which might be dangerous, it is destroyed) or you have to keep a copy of the original coordinates.

Inheriting from Transformable and Drawable in SFML

I'm trying to inherit from Transformable and Drawable in SFML in order to make my objects... well, transformable and drawable. I'm making a simple breakout game, but perhaps I'm going about this the wrong way. Here's my code:
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
class Player : public sf::Transformable, public sf::Drawable {
public:
Player(int x, int y);
~Player() {};
sf::RectangleShape p_rect;
void doMovement(const sf::RenderWindow& window);
sf::FloatRect getGlobalBounds() const;
private:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const {
states.transform *= getTransform();
target.draw(p_rect, states);
}
};
class Ball : public sf::Transformable, public sf::Drawable {
public:
Ball(int r, int x, int y);
~Ball() {};
sf::CircleShape b_circle;
void doXMovement();
void doYMovement();
bool doXCollisions(const Player& player);
bool doYCollisions(const Player& player);
sf::FloatRect getGlobalBounds() const;
private:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const {
states.transform *= getTransform();
target.draw(b_circle, states);
}
bool right;
bool up;
};
Player::Player(int x, int y) {
p_rect = sf::RectangleShape(sf::Vector2f(x, y));
}
void Player::doMovement(const sf::RenderWindow& window) {
setPosition(sf::Mouse::getPosition(window).x, 500);
if (getPosition().x < 0)
setPosition(0, 500);
else if (getPosition().x > 720)
setPosition(720, 500);
}
sf::FloatRect Player::getGlobalBounds() const {
return getTransform().transformRect(p_rect.getGlobalBounds());
}
Ball::Ball(int r, int x, int y) {
b_circle = sf::CircleShape(r);
b_circle.setPosition(x, y);
right = true;
up = false;
}
void Ball::doXMovement() {
if (right)
move(1, 0);
else
move(-1, 0);
}
void Ball::doYMovement() {
if (up)
move(0, -1);
else
move(0, 1);
}
bool Ball::doXCollisions(const Player& player) {
bool coll;
if (getGlobalBounds().intersects(player.getGlobalBounds())) {
right = !right;
coll = true;
} else
coll = false;
if (getPosition().x >= 800 - b_circle.getRadius())
right = false;
else if (getPosition().x <= 0)
right = true;
return coll;
}
bool Ball::doYCollisions(const Player& player) {
bool coll;
if (getGlobalBounds().intersects(player.getGlobalBounds())) {
up = !up;
coll = true;
} else
coll = false;
if (getPosition().x <= 0)
up = false;
return coll;
}
sf::FloatRect Ball::getGlobalBounds() const {
return getTransform().transformRect(b_circle.getGlobalBounds());
}
int main() {
sf::RenderWindow window(sf::VideoMode(800, 600), "Breakout");
window.setMouseCursorVisible(false);
Player player(80, 10);
Ball ball(3, 100, 100);
sf::Clock clock;
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed)
window.close();
}
player.doMovement(window);
if (clock.getElapsedTime().asMilliseconds() >= 3) {
clock.restart();
if (!ball.doYCollisions(player))
ball.doXCollisions(player);
ball.doYMovement();
ball.doXMovement();
}
window.clear(sf::Color::Black);
window.draw(player);
window.draw(ball);
window.display();
}
return 0;
}
Now moving and drawing work (nearly) as expected, however collisions are a bit wonky. First my collisions problems:
Do I need to implement the getGlobalBounds function the way I did? Or is there a better way to do it with things included in Transformable and Drawable?
Should I be performing transformations on the shapes directly, or should I pass the transformations to the draw function like I currently am?
Something strange is also happening with the drawing which is probably a quick fix. Right now the getPosition method returns incorrect values for my ball object. The area it returns seems to be shifted down and to the right a bit. Any reason that might be?
Thanks for any help you are able to give!
EDIT: Also any general C++ tips are welcome, I'm still a beginner.
If I were you I would define a new class, called TransformableAndDrawable like this:
class TransformableAndDrawable : public sf::Transformable, public sf::Drawable {
// Your code here
}
In this class you should define all the members which are generally needed by your transformable and drawable classes. Also, in this class you should define all the methods which can be generally implemented in your transformable and drawable classes. Then, your classes should be inherited from TransformableAndDrawable, like this:
class Player : TransformableAndDrawable {
// Your code here
}
Now, the answer to the first question is: I would implement in the TransformableAndDrawable class the given method if it is a general method, so all the classes inherited from TransformableAndDrawable will have this method.
Instead of giving different names, like p_rect and p_circle, name these members with the same name, like p_shape, so you will have no naming issues. Also, I believe that you can declare your p_shape to be of an ancestor class or interface (I do not know what classes are defined in the library you are working with) and only when needed specify the nature of the shape (whether it is a circle or a rectangle or something else).
As for the second questions: I like the way you have implemented things, but you have made two mistakes:
it is not scalable: we want a general solution, a class which can be used for any shape you are working with now and in the future, don't we?
it is not general enough: When I want to know the global bounds of a shape, then I am not interested of the nature of the shape, I would prefer your code to handle the nature of the shape without me knowing it
In short, you should do the following:
Create a wrapper class which will be inherited from Transformable and Drawable
In your wrapper class, be agnostic to the nature of the shape, be as general as possible, hopefully there is some class or interface which is ancestor to both RectangleShape and CircleShape.
Inherit all your drawable and transformable classes from your wrapper class, so you will have a shared functionality among your classes
If something in your wrapper class is not good for a class which was inherited from it, overwrite the method in that class.
EDIT:
I have looked into the library you are using in more detail and found out that there is a class called Shape, which is the ancestor to both CircleShape and RectangleShape. So, instead of these classes use Shape and your code will be more general and reusable.

C++ Referencing an objects current state within another object

I've searched high and low for an answer to this question and have attempted many solutions including forward declaration, pointers, and references. I'm sure I'm just using incorrect syntax somewhere. After many wasted hours, I've decided to turn to stack overflow.
I am attempting to code one of my first CPP applications as a learning experience. Right now I have a Player and a Ball object. My Ball object must be able to access some of the member variables and methods in my player object. I have been unable to figure out how to do this. Below is an extremely simplified version of my code. I've commented the code that is particularly important.
PlayState.hpp
#ifndef PLAYSTATE_HPP
#define PLAYSTATE_HPP
#include "Player.hpp"
#include "Ball.hpp"
class Player;
class Ball;
class PlayState
{
public:
PlayState();
Player player;
Ball ball;
};
#endif
PlayState.cpp
#include "PlayState.hpp"
PlayState::PlayState() {
}
void PlayState::update() {
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
{
ball.checkCollision();
player.move(1);
}
ball.update();
}
void PlayState::draw()
{
m_game.screen.clear();
m_game.screen.draw( player.getSprite() );
m_game.screen.draw( ball.getSprite() );
m_game.screen.display();
}
Player.hpp
#ifndef PLAYER_HPP
#define PLAYER_HPP
class Player
{
public:
Player();
~Player();
void create();
void setRotation(float);
void setPosition(float, float);
};
#endif
Player.cpp shouldn't really be all that important to see.
Ball.hpp
#ifndef BALL_HPP
#define BALL_HPP
class Player; // I don't think forward declaration is what I need???
class Ball
{
public:
bool picked_up;
bool throwing;
Player *player; // this isn't working
Ball();
~Ball();
bool checkCollision();
};
#endif
Ball.cpp
#include "Ball.hpp"
Ball::Ball() {
Ball::picked_up = false;
Ball::throwing = false;
}
Ball::~Ball() {
}
bool Ball::checkCollision()
{
float ball_position_x = Ball::getPosition().x;
float ball_position_y = Ball::getPosition().y;
// I need to access the player object here.
float x_distance = abs(player.getPosition().x - ball_position_x);
float y_distance = abs(player.getPosition().y - ball_position_y);
bool is_colliding = (x_distance * 2 < (player.IMG_WIDTH + Ball::width)) && (y_distance * 2 < (player.IMG_HEIGHT + Ball::height));
return is_colliding;
}
When you say player, do you mean the exact same player that is in the same playstate object as the current ball object? If so you want to first set up that link, it cannot be done automatically.
PlayState::PlayState() :ball(&player){ //pass pointer to ball of its player?
}
class Ball
...
Ball(Player *myPlayer);
...
}
Ball::Ball(Player *myPlayer):player(myPlayer) {
...
// I need to access the player object here.
float x_distance = abs(player->getPosition().x - ball_position_x);
You also need to use a pointer to use the player since it is a pointer to a player object.
You do need the forward declaration to Player above the Ball class. The one above Playstate is unnecessary.
Also your player doesnt seem to have a GetPosition function, I am assuming it is a public member function you forgot to include above.