Share variables between classes C++? - c++

Yet another question about classes as Im new to OOP. I am creating a game just for fun. Its a top down shooter, space shooter.
I have a few different classes:
Bullet (a list of bullet coordinates),
Player (player sprite, position etc),
Enemy (enemy sprite, position etc),
Collision (taking coordinates Ax, Ay, and Bx, By to see if they have collided)
How can I send the coordinates from Bullet, Enemy to the Collision class to see if they have collided?
Collision col
col.collision(ax, ay, bx, by) //how can I get the Player and Bullet pos?

Probably what you want to do is to have a common class "SceneObject" that has a position. Then Player, Enemy and Bullet all inherit from that class.
Your Collision then does not need knowledge about Players, Enemies etc. but only SceneObjects which have a position. You can write a Getter method in your base class that returns the position.

I would create a base class for Bullet, Enemy (and maybe Player). Let's call it Object and the Object would own the Coordinates and would have a function determining if a Collision happened.
In code it would look like to following:
class Object
{
private:
Coord position;
public:
bool Collide(const Object& otherObject) const;
};

You typically have to go through every enemy and check the coordinates of that enemy against your player coordinates.
I'm sure you stored those enemies somewhere, preferably in a container like std::vector. Now let me just assume you did exactly that:
// somewhere in a 'Game' class
std::vector<Enemy> myEnemies;
Player myPlayer;
Collision col;
for(int i=0; i < myEnemies.size(); ++i){
col.collision(myPlayer.getX(), myPlayer.getY(), myEnemies[i].getX(), myEnemies[i].getY())
}
And that's it. :) You do the same for bullets and similar objects. Save them all in a container, iterate over that container, and check the positions of the objects.
Now, for another tip, if a class only contains methods and no variables, you may aswell make that free functions. Just because you use OOP in some parts of your project doesn't require you to use it everywhere. Make that collision a free function and be done with it. :)

Related

Drawing "higher-level" object

So I'm using SFML for a Computer Science project - making a chess game. I have a class Square which is a single square of the chessboard - currently, it contains four vertices (four sf::Vertex objects in a member variable sf::VertexArray) and is colored either white or black. A class ChessBoard encapsulates a std::vector of Squares.
Using the tutorial given by SFML, I'm able to draw a single square. However, the draw() function works based on vertices, and since the ChessBoard class doesn't not actually contain vertices, but rather objects that themselves contain vertices, I'm not able to draw the chess board (i.e. its internal draw() function does not work).
Does anyone know how to work around this?
(I can provide more info/clarification/code if necessary/helpful.)
That's not really how "higher level drawing" is supposed to work.
Your parent class(es) shouldn't have to bother how to draw children. You're mixing responsibilities.
Instead, subclass sf::Drawable (and sf::Transformable, if required).
All this does is forcing you to implement a draw() member, which does all the drawing.
Here's a simple example for your ChessBoard class:
class ChessBoard : public sf::Drawable {
void draw (RenderTarget &target, RenderStates states) const {
for (auto &tile : mTiles) // Iterate over all board pieces
target.draw(tile, states); // Draw them
}
}
As you can see, this is trivial to setup. In a similar way, you can overload your Square class. (Isn't that name too generic? Why not simply reusing sf::RectangleShape?)
class ChessBoard : public sf::Drawable {
void draw (RenderTarget &target, RenderStates states) const {
target.draw(mVertices, states);
}
}
So, back to your main game loop. How to draw the ChessBoard? Again, trivial:
while (window.isOpen()) {
// All the other things happening
window.draw(mChessBoard);
}
While the advantages of this approach might not be as obvious at first, it's pretty easy to see that you're capable of passing responsibilities down the line. For example, the ChessBoard doesn't have to know how to properly draw a Square. In a trivial example – using unicolored polygons only – it's not that easy to notice, but your code will be a lot cleaner once you start adding shaders, textures, etc. Suddenly you'd no longer just have to return a sf::VertexArray, but you'll also need pointers or references to the other ressources. So the ChessBoard would have to know, which components to request from Square to draw it properly (Does it have a shader? Do I need a texture?).
Nevermind. Silly me. Implemented a getter inside class Square that returned the vertex array, & inside Chessboard looped through the vector of squares, calling the getter on each iteration.

Arguments to Update Method in Game Pattern

I have been working to create a game in C++. A World class contains all game-state related objects and the main game loop function.
class World {
Clock clock;
Map map;
std::vector<Entity*> entities;
...
All entities in my game inherit from the abstract class Entity. For example:
class Player: public Entity {...};
class Enemy: public Entity {...};
class Bullet: public Entity {...};
Entities are updated each frame by iterating through a list of all entities and calling the update() method on each one.
To account for varying frame rates, I pass the elapsed time in each frame as a float delta to the update method (like most other game engines). The problem I run into is all the different things an entity might need to reference in update().
The Entity class defines the virtual update method as follows:
virtual void update(float delta) = 0;
Calling this function from the game loop looks like this:
for(int i = 0; i < entities.size(); i++) {
entities[i]->update(clock.get_delta());
}
This works great. But now, let's say for example that we want to add a feature where Player can move faster on different surfaces. To know what surface the player is on would require access to the Map object belonging to the World class.
We could add that to the virtual update method:
virtual void update(float delta, Map *map) = 0;
But now Enemy and Bullet's update functions have to take the new map parameter even though they don't use it.
The same would go for any other object or variable an entity needs in its update method. Before long, there would be dozens of parameters (game map, list of other entities, game state information) cluttering the method definition.
My question is: How can I prevent this? I tried passing a reference to World as the only argument, but it resulted in circular dependencies.
I solved this in my game by storing a Map* in the Player class. Works great if you never have to change it.

SFML Drawing a Moving Sprite in Another Class

I am fairly new to SFML and am trying to make a scrolling plane game that shoots out a bullet whenever I press the spacebar. I've gotten all of the movement working, but I'm trying to figure out how to put the bullets into another class file so that I can have a whole set of them later on (I.E. create.bullet(), create.missle(), etc.). Here is the code that I have now.
void create::bullet(int xPos, int yPos)
{
sf::Texture bulletTexture;
if(!bulletTexture.loadFromFile("bullet.png"))
cout << "There was an error loading the bullet texture file." << endl;
sf::Sprite bulletSprite;
bulletSprite.setTexture(bulletTexture);
bulletSprite.setPosition(xPos, yPos);
window.draw(bulletSprite);
}
I have the sf::RenderWindow instance called window in the main class, but I apparently can't reference it directly from another class. I haven't been able to implement velocity yet either, but I should be able to do that. Another thing that I need help with however, is getting it so that there is no limit on the number of bullets that can be fired. It seems like if I just have this function run whenever spacebar is pressed, it will just reset the sprite to the new position and get rid of the old one. Thanks for the help!
First of all, loading textures from files is slow. You should do it once when the program or level starts, and store the texture somewhere.
Instead of a Create class, make a Bullet class. Then, you can have a vector of bullets (or pointers/smart pointers to them). Each time you want a new bullet, you just push_back() it to the vector. If a bullet needs to be destroyed you erase() it. Then, for the game itself, you need to call Move() for every bullet and then Draw() for every bullet in the vector. Once you have that done, you can add the collision detection and so on.
You also have a choice - each bullet can have its own sf::sprite and modify it, or you can have one sf::sprite for each game sprite and reposition it for every bullet.
Personally, I'm using the second approach. My Bullet class looks like this:
Bullet::Bullet(std::string ntype, double nx, double ny, double nvx, double nvy):
type(ntype), x(nx), y(ny), vx(nvx), vy(nvy)
{
angle=atan2(vy, vx)*(180/M_PI);
}
void Bullet::Move()
{
x+=vx;
y+=vy;
};
void Bullet::Draw()
{
DrawSprite(type, x, y, angle+90);
};
In the separate .cpp file, I have a string ordered map of sf::sprites. My draw function looks like this:
void DrawSprite(std::string type, float x, float y, float angle)
{
sf::Sprite temp=sprites[type];
temp.setRotation(angle);
temp.setPosition(x, y);
window.draw(temp);
}

Is it possible to initialise two classes, that require pointers to each other, at the same time?

I am making a snake game. I have two classes, snake and food. When I call snake->move() it needs to check that there are no collisions and for this purpose it needs to know what food's position is and therefore requires a pointer to food. food has a function that moves it to a new random position, move->setNewPosition(), which needs to know the position of snake so that it doesn't collide with the snake when it moves. For this purpose, it requires a pointer to snake.
Therefore, for both classes, I would need to supply a pointer to the other class which must be initialised. But to initialise the other class I need to initialise the other class and so on. Is there any way to initialise two classes, that require pointers to each other, at the same time?
If not, what would be a better way of structuring my program that would allow me to check the coordinates of the other class?
If i don't misunderstand you, create init function that call before game loop starts:
void initSnake()
{
auto snake = new Snake();
auto food = new Food();
snake->setFood(food);
food->setSnake(snake);
}
They just need the facility to find the location of other snakes and food items when their movement functions are invoked. There's no need to know of their existence at initialisation time!
You can therefore have a collection of snakes and a collection of food items, and pass a reference to those collections to any newly created snakes and food items. Just create those collections first.
You could do this via another class, perhaps, which could also act as a factory.
class GameManager;
class Snake
{
friend class GameManager;
public:
int getX() { return _x; }
int getY() { return _y; }
void setPosition(int x, y) { /* ... */ }
private:
Snake(GameManager* manager, int x, int y) : _manager(manager), _x(x), _y(y) {}
GameManager* _manager;
int _x, _y;
};
class GameManager
{
public:
const std::vector<Snake*>& Snakes() { return _snakes; }
Snake* SpawnSnake(int x, int y)
{
Snake* newSnake = new Snake(this, x, y);
snakes.push_back(newSnake);
return snake;
}
private:
std::vector<Snake*> _snakes;
};
(Just an example. Code not tested to see if it actually compiles. E&OE)
The GameManager ensures that all created snakes are found in the snakes vector because the Snake constructor is private. Each snake can call _manager.Snakes() to get a vector containing all the other snakes in the game which it can then query individually for their positions. This is easily generalised to support food items as well.
This has the small advantage over the "construct-initialise" pattern suggested in other answers in that it ensures that when you get a new Snake object it is actually ready for use... this example isn't quite RAII, but it would require a minimum of effort to make it reasonably exception-safe.
You can define one base class for them, which has these methods:
virtual void setPosition(const int x, const int y)
virtual void getPosition(int &x, int &y) const
Snake should use them too, just override them if you need to. Now both classes can call each other's setPosition and getPosition directly if you give the other object as a parameter with type Base.
An other way would be; In your main()-function, or wherever you define your snake:
int main()
{
Snake* s = new Snake;
Food* f = new Food;
Snake->setLocation(0,0); // Wherever you want the snake to start from
}
And whenever you create a new food, give it snake's location: f->setRandomLocation(snake->getLocation()) where the parameter would be coordinates where NOT to place it.
One alternative would be to have a Manager class which both of them send their requests to, which would make more sense (but doesn't solve your particular problem).
Nevertheless, if you have class A and class B, and each one needs the other, you can do the following:
A *a = new A;
B *b = new B;
// check a and b to make sure they are not NULL
a->set_b(b);
b->set_a(a);
Mmn, not sure how your game works but I assume there would be a lot of food objects?
Maybe an idea would be to create a Collision class that accepts a Snake player and stores all the Food players in the game.
So the Collision constructor might look like this
Collison(Snake &snake, Vector<Food*> &foods)
{
}
The Collision class would also have an collision update to loop that you call somewhere in your code.. This loop would check if the snake object collides with a food object.. and you can do whatever you want.. remove the food from the foods vector change the food position, whatever.
collison.UpdateCollisions() ;
I would suggest breaking the cyclic dependency, instead of hammering it in: make both moving functions take the environment (i.e. a list of things it can collide with) as a parameter.

Making an object move independently in SDL(like a gun shot)

I have been following lazyfoos tutorials on SDL, and I have heavily modified his code to make sort of a ship game, that moves around. I'm trying to make the ship shoot, but i have absolutely no idea how to go about doing this. I have the ship and it's movements and the actual application of the image in a class, and I as wondering if anyone had any techniques or certain ways that are efficient in making the ship shoot, making the shot move independently and then disappearing when it goes off screen. I know that I am giving a vague explanation sort of, but I don't want to be given all of the answers, just a little sample code and a point in the right direction.
Create a class to hold a projectile, with all the information you need in it, such as this:
struct Projectile
{
Vector2 position;
Vector2 velocity;
shared_ptr<Image> graphic;
Time time_until_my_destruction;
bool dead;
void update(Time time_delta) {
if(!dead) {
position += velocity * time_delta;
time_until_my_destruction -= time_delta;
if(time_until_my_destruction < 0.0) dead = true;
}
}
void draw(DrawDest & dest) const {
graphic->draw(dest, position);
}
bool checkCollision(const GameObject & object) const {
return object.area().contains(position);
}
};
This class is not complete obviously, you'll probably want to make adjustments to access levels, and write some constructors and other things, but it should give you the basic idea.
Make a container of those. When the ship fires, put one into the container. Each frame, call update, draw, check if the projectile is dead and check for collisions against the game objects. If a collision occurs, apply damage or whatever. If the object is dead, remove it from the container.
I can only absolutely recommend Aaron's Game Programming Tutorials, it uses C++ and SDL.