Thanks for the additional code :).
First let's go through your code and clean it up a bit and take care of some bad practices in it. Don't worry everyone does some bad practices when they first start out specially when it comes to game development which is a extremely hard subject.
1. This is only a suggestion and isn't need but I would recommend it.
1 2 3 4 5 6 7 8 9
|
#include <Windows.h>
#include "Game.h"
INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
{
Game game;
game.run();
}
| |
I would recommend you get rid of that very ugly and non cross platform WinMain declaration by linking to sfml-main.lib and sfml-main-d.lib which will allow you to have a simple standard main() like this.
1 2 3 4 5 6 7
|
#include "Game.h"
int main()
{
Game game;
game.run();
}
| |
As stated this looks much cleaner and I don't believe you are using the WINAPI for anything as far as I can see. It also will make your program cross platform which as it sits right now it isn't.
2. This one is a glaring one that you really need to change. In your Game class you are inheiriting from both Ball and Player when there should be absolutly no reason to do so.
class Game : Player, Ball
From just browsing your code it seems like you are inheiriting from those to gain access to
mPlayerRect
from the Player class and
mBallCircle
from the Ball class. So you are basically combining all the functionality of the Player, Ball and Game classes all into the Game class which is not how it should be done.
Instead the game class should not inheirit from the Player and Ball classes and instead it should hold a member of each of those classes to represent the player and the ball in the game (Which you already are doing which is the confusing part).
So lets do some changes to your Game class.
The header should look something like this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
// The game class is just mainly used to hold the main game loop
// and manage things that deal with the game as a whole, like managing the window.
class Game // We don't want to inheirit anything.
{
public:
Game();
void run();
private:
void processEvents();
void update();
void render();
private:
sf::RenderWindow mWindow;
// These don't need to be protected since nothing should inheirit from Game I wouldn't think.
Player mPlayer;
Ball mBall;
};
| |
Now before I go into the Game.cpp file you are going to need to change somethings about the Player and Ball classes since we aren't inheiriting from then anymore.
1 2 3 4 5 6 7 8 9 10 11 12 13
|
class Player
{
public:
Player();
// We need a way to get access the the below sf::RectangleShape
// so that we can do it in your drawing loop. So we need a get function
// for it. There is better ways like inheiriting from sf::Drawable but that
// is more advanced and beyond this post.
sf::RectangleShape& getPlayerRect() const { return mPlayerRect; }
protected:
sf::RectangleShape mPlayerRect;
};
| |
Now the Ball class we need to do the same thing.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
class Ball
{
public:
Ball();
// Same as before we need some getters
sf::CircleShape& getBallCircle() const { return mBallCircle; }
sf::Vector2f& getDirectionV() const { return directionV; }
protected:
sf::CircleShape mBallCircle;
// If you want this to be set to (0.f, 0.f) then I would do it in the constructor
// instead.
sf::Vector2f directionV = sf::Vector2f(0.0f, 0.0f);
private:
void directionF();
};
| |
Now on to your Game.cpp file. It should look like this (Will comment a bit and will go into detail below the code on the changes). I really only changed stuff in the update() and render() methods so that is all I will post.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
void Game::update()
{
// player movement
sf::Vector2f pMovement(0, 0);
// You are not taking into account the delta time but will go into that
// later.
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
pMovement.x -= 5;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
pMovement.x += 5;
// Instead since we are no longer using the inheirited members to
// store the player data we need to retrieve the playerRect from the
// player member in our game class to do the movement.
mPlayer.getPlayerRect().move(pMovement);
// ball movement
sf::Vector2f bMovement(0, 0);
// Same as above we are using the ball member instead so we
// call the getter to get access to the vector in the ball class. And then
// move the ball.
bMovement.x += mBall.getDirectionV().x;
bMovement.y += mBall.getDirectionV().y;
mBall.getBallCircle().move(bMovement);
}
void Game::render()
{
// The main thing here is the same as above we are using out ball and player
// members instead now and need to get their visual component to draw
// instead now.
mWindow.clear();
mWindow.draw(mBall.getBallCircle());
mWindow.draw(mPlayer.getPlayerRect());
mWindow.display();
}
| |
Now that is all basically for the Game class regarding the inheiritence of Ball and Player. Now it should be more manageable and is more like how it is usually done.
3. - You are going to need to deal with a timestep if you are going to be dealing with movement in your game. This post is already quite long as it is so I won't go into detail about this long subject will post a example of how my main game loops usually look with their timesteps and some articles on the subject.
Here is a simple example of how one of my game loops might look.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
sf::Time timePerFrame = sf::seconds(1.0f / 60.0f); // 60 frames per second
sf::Clock deltaClock;
sf::Time timeSinceLastUpdate = sf::Time::Zero;
while (m_Window.isOpen())
{
sf::Time deltaTime = deltaClock.restart();
timeSinceLastUpdate += deltaTime;
while (timeSinceLastUpdate >= timePerFrame)
{
timeSinceLastUpdate -= timePerFrame;
ProcessInput();
Update(timePerFrame);
}
Render();
}
| |
By passing timePerFrame to the update() method I can see how much time has pasted since the last update call (Last frame) and move accordingly by doing
someEntity.move(moveVector.x * timePerFrame, moveVector.y * timePerFrame);
. If I didn't use the timePerFrame and lets say move vector was (5, 0) like in your example the entity would move 5 pixels to the right every frame. So if I was running at 60 FPS I would be moving the entity 300 pixels to the right every second which is really really fast and hard to catch. If the framerate isn't limited to 60FPS you wouldn't even notice it move of screen.
You are actually probably seeing some of this behavior as it is when you press the movement keys in your game. Your player will be moving at a extremely high rate of speed, and so will your Ball like Yanson mentioned.
Anyways here is a nice article on the subject
http://gafferongames.com/game-physics/fix-your-timestep/
But with that I am running out of characters for this long ass post ;p. So I will stop here try making those changes and see what it does and if it helps solve your problem or makes it easier for you to solve it. If you still have questions feel free to keep posting and I would be glad to help with another wall of text (Joking joking ;p).