I'm trying to create a game. I have a class GameObjects that many classes will inherit from. The class GameObject has a draw method that takes the window address to the display. Why does the sprite show up without the texture when displayed like this?
This is the texture, more of a placeholder. I was able to load it in other files directly creating the sprite and drawing it.
Here is my main.cpp
#include <iostream>
#include "Game.h"
int main()
{
//window setup
Game game;
//Initialize game
game.start();
return 0;
}
Here is my Game.h
#pragma once
#include "GameObject.h"
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/Audio.hpp>
#include <iostream>
class Game
{
private:
//window variables
int w_width;
int w_height;
sf::RenderWindow window;
sf::Event ev;
bool isRunning;
std::vector<GameObject> o_vector;
void initVariables();
void initWindow();
void initObjects();
void drawObjects();
public:
void start();
void run();
void input();
void update();
void render();
};
And Game.cpp
#include "Game.h"
#include "GameObject.h"
void Game::start()
{
this->initVariables();
this->initWindow();
this->initObjects();
this->run();
}
//Initializations
void Game::initVariables()
{
isRunning = true;
//window variables
w_width = 1280;
w_height = 720;
}
void Game::drawObjects()
{
for (int o_count = 0; o_count < o_vector.size(); o_count++)
{
o_vector.at(o_count).draw(window);
}
}
void Game::initWindow()
{
//window creation
window.create(sf::VideoMode(w_width, w_height), "The Dungeon Crawler", sf::Style::Titlebar | sf::Style::Close | sf::Style::Resize);
}
void Game::initObjects()
{
GameObject baseObject;
o_vector.push_back(baseObject);
}
void Game::run()
{
while (isRunning)
{
input();
update();
render();
}
}
void Game::input()
{
while (window.pollEvent(ev))
{
switch (ev.type)
{
case sf::Event::Closed:
window.close();
break;
case sf::Event::KeyPressed:
switch (ev.key.code)
{
case sf::Keyboard::Escape:
window.close();
break;
case sf::Keyboard::A:
break;
}
}
}
}
void Game::update()
{
}
void Game::render()
{
window.clear(sf::Color(0, 0, 128));
drawObjects();
window.display();
}
Here is GameObject.h
#pragma once
#include <vector>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <iostream>
class GameObject
{
private:
std::string name;
std::vector<int> o_position;
std::vector<int> o_size;
std::string t_path;
sf::Sprite o_sprite;
sf::Texture o_texture;
void initVariables();
public:
//Constructors & Destructors
GameObject();
~GameObject();
//Getters
std::vector<int> getPos();
std::vector<int> getSize();
sf::Sprite getSprite();
//Setters
void setPos(std::vector<int>pos_in);
void setSize(std::vector<int> size_in);
//Graphics
void draw(sf::RenderWindow &displayWindow);
};
And GameObject.cpp
#include "GameObject.h"
GameObject::GameObject()
{
initVariables();
}
GameObject::~GameObject()
{
}
void GameObject::initVariables()
{
o_position = { 0,0 };
o_size = { 64,64 };
t_path = "Resources/EmptySquare.png";
if (!o_texture.loadFromFile(t_path))
{
std::cout << "Failed to load" << std::endl;
return;
}
o_sprite.setTexture(o_texture);
}
std::vector<int> GameObject::getPos()
{
return o_position;
}
std::vector<int> GameObject::getSize()
{
return o_size;
}
sf::Sprite GameObject::getSprite()
{
return o_sprite;
}
void GameObject::setPos(std::vector<int> pos_in)
{
o_position = pos_in;
}
void GameObject::setSize(std::vector<int> size_in)
{
o_size = size_in;
}
void GameObject::draw(sf::RenderWindow &displayWindow)
{
displayWindow.draw(o_sprite);
}
Thank you for any help!
the problem is this line in Game::initObjects()
GameObject baseObject;
o_vector.push_back(baseObject);
you creata a copy of GameObject.
so it will make a copy of o_sprite.
the o_sprite copies the texture pointer.
after this function ends, the texture pointer is no longer valid.
sf::Sprite has the member const Texture* m_texture; and when calling sf::Sprite::setTexture(const Texture& texture) this member m_texture will in fact point to the texture. That texture will be destructed after initObjects() ends, and your element at position 0 will have a o_sprite.m_texture that points to this destructed object. SFML/Sprite.hpp
you could define the correct operator=(GameObject) that implements the correct sprite copy - or in this case simply say:
void Game::initObjects()
{
o_vector.resize(1);
}
resize will call the constructor of GameObject and you will have no copies and therefore dangling pointers.
Another way would be for you to allocate game object on the heap and store a pointer to it in the vector. This way you will avoid the cost of copying.
To make these changes, declare baseObject as private member of Game class and in initObjects method allocate it on the heap.
class Game
{
private:
GameObject *baseObject;
std::vector<GameObject *> o_vector;
};
void Game::initObjects()
{
baseObject = new GameObject;
o_vector.push_back(baseObject);
}
void Game::drawObjects()
{
for (int o_count = 0; o_count < o_vector.size(); o_count++)
{
o_vector.at(o_count)->draw(window); // use -> operator to call draw
}
}
PS: Instead of raw pointer, you can also use C++11 smart pointer.
Related
New to C++, I'm trying to make "platforms" spawn every 2 seconds and go upwards. However, the platform disappears when a new Platform is pushed onto the platforms vector.
Platform.h:
#pragma once
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <vector>
class Platform
{
private:
sf::RectangleShape shape;
public:
Platform() = default;
Platform(const Platform& platform);
void updatePos();
sf::RectangleShape getShape() { return shape; }
};
Platform.cpp:
#include "Platform.h"
Platform::Platform(const Platform& platform)
{
shape.setSize(sf::Vector2f(300.f, 40.f));
shape.setPosition(1920.f / 2.f - shape.getSize().x / 2.f, 1080.f);
}
void Platform::updatePos()
{
shape.move(sf::Vector2f(0.f, -5.f));
}
Game.h:
#pragma once
#include "Platform.h"
#include <iostream>
class Game
{
private:
sf::RenderWindow window{ sf::VideoMode(1920, 1080), "Dodge the Spikes", sf::Style::Fullscreen };
std::vector<Platform> platforms;
bool gameOver{};
unsigned int platformTimer{};
public:
Game() = default;
void update();
void draw();
void run();
};
Game.cpp:
#include "Game.h"
void Game::update()
{
if (!gameOver)
{
//spawn platforms
platformTimer++;
if (platformTimer >= 120)
{
platforms.push_back(Platform{});
platformTimer = 0;
}
//update platforms
for (auto i{platforms.begin()}; i < platforms.end();)
{
i->updatePos();
i++;
}
}
}
void Game::draw()
{
for (auto i{ platforms.begin() }; i < platforms.end();)
{
window.draw(i->getShape());
i++;
}
}
void Game::run()
{
while (window.isOpen())
{
sf::Event evnt;
while (window.pollEvent(evnt))
{
if (evnt.type == sf::Event::Closed)
{
window.close();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
{
window.close();
}
}
this->update();
window.clear();
this->draw();
window.display();
}
}
I am trying to storesf::RectangleShape's into thestd::vectorand then draw each of them into thesf::RenderWindow.
Single rectangle shape is representing 1x1 tetromino and i would like to store it into the vector each time it reaches the bottom of the window. Then I would like to reset the position of the current tetromino to the default position.
I think I'm not even to able store it correctly. Each time the tetromino reaches the bottom it gives me this error message:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Bellow please find my current code. I just started working on it and already got stuck.
Definitions.h
#pragma once
// Point structure
struct Point
{
int dim_x;
int dim_y;
};
// Field Dimensions
const int fieldRows = 10;
const int fieldColumns = 9;
const int pointSize = 50.f;
// For checkingEdges funntion within the Tetrnomino.h
enum Edge
{
leftEdge,
rightEdge,
noneEdge
};
Game.h
#pragma once
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include "Definitions.h"
#include "Tetromino.h"
class Game
{
public:
Game();
~Game();
// Game starter
void run();
// Accessors
bool running();
private:
// Updating and rendering the game window
void update();
void render();
// Initialization
void initVariables();
void initWindow();
void initBacgroundMusic();
// Polling
void pollEvents();
// Window logic stuff
sf::RenderWindow* _window;
sf::Event _event;
void drawStack();
// Bacground Music
sf::Music _ost;
// Tetromino + Its logic
Tetromino _T;
sf::Time delayTime = sf::milliseconds(300);
sf::Clock clock;
};
Tetromino.h
#pragma once
#include <SFML/Graphics.hpp>
#include <vector>
#include "Definitions.h"
class Tetromino
{
public:
Tetromino();
~Tetromino();
// Initialization
void initTetromino();
// Tetromonino logic
void moveTetromino();
Edge checkEdges();
// Getters & Setters
sf::RectangleShape getTetromino();
sf::RectangleShape getStackPart(int part);
int getStackSize();
void setTetromino(sf::RectangleShape &t);
private:
// The current tetromino
sf::RectangleShape _tetromino;
std::vector<sf::RectangleShape> _stack;
};
Game.cpp
#include "Game.h"
//-----Consturcotrs and Destructors-----//
Game::Game()
{
//Basic Initialization
_T.initTetromino();
initVariables();
}
Game::~Game()
{
delete _window;
}
//-----Private Functions-----//
void Game::run()
{
update();
render();
}
bool Game::running()
{
return _window->isOpen();
}
void Game::update()
{
sf::Time elapsed = clock.getElapsedTime();
pollEvents();
if (elapsed >= delayTime)
{
_T.moveTetromino();
clock.restart();
}
}
void Game::render()
{
_window->clear(sf::Color::White);
_window->draw(_T.getTetromino());
drawStack();
_window->display();
}
void Game::initVariables()
{
_window = nullptr;
initWindow();
initBacgroundMusic();
}
void Game::initWindow()
{
_window = new sf::RenderWindow(sf::VideoMode(fieldColumns * pointSize, fieldRows * pointSize), "Tetris v0.2", sf::Style::Default);
_window->setVerticalSyncEnabled(true);
_window->setFramerateLimit(60);
}
void Game::initBacgroundMusic()
{
_ost.openFromFile("../QT_SFML_Tetris/Music.ogg");
_ost.play();
_ost.setLoop(true);
_ost.setVolume(50.f);
}
void Game::pollEvents()
{
while (_window->pollEvent(_event))
{
if (_event.type == sf::Event::Closed) {_window->close();}
if (_event.type == sf::Event::KeyPressed)
{
if (_event.key.code == sf::Keyboard::Escape){_window->close();}
if (_event.key.code == sf::Keyboard::Left && _T.checkEdges() != leftEdge)
{
sf::RectangleShape t = _T.getTetromino();
t.setPosition(t.getPosition().x - pointSize, t.getPosition().y);
_T.setTetromino(t);
render();
}
if (_event.key.code == sf::Keyboard::Right && _T.checkEdges() != rightEdge)
{
sf::RectangleShape t = _T.getTetromino();
t.setPosition(t.getPosition().x + pointSize, t.getPosition().y);
_T.setTetromino(t);
render();
}
if (_event.key.code == sf::Keyboard::Down)
{
sf::RectangleShape t = _T.getTetromino();
t.setPosition(t.getPosition().x, t.getPosition().y+ pointSize);
_T.setTetromino(t);
render();
}
}
}
}
**void Game::drawStack()**
{
for (unsigned int i = _T.getStackSize(); i > 0; --i)
{
_window->draw(_T.getStackPart(i));
}
}
main.cpp
#include <Game.h>
int main()
{
Game game;
while (game.running())
{
game.run();
}
return 0;
}
Tetromino.cpp
#include "Tetromino.h"
//-----Consturcotrs and Destructors-----//
Tetromino::Tetromino()
{
}
Tetromino::~Tetromino()
{
}
//-----Public Functions-----//
void Tetromino::initTetromino()
{
_tetromino.setPosition(sf::Vector2f((fieldColumns * pointSize - pointSize) / 2, 0.f));
_tetromino.setSize(sf::Vector2f(pointSize, pointSize));
_tetromino.setFillColor(sf::Color::Red);
}
void Tetromino::moveTetromino()
{
_tetromino.move(0.f, pointSize);
if (_tetromino.getPosition().y > fieldRows * pointSize - pointSize)
{
_stack.push_back(_tetromino);
_tetromino.setPosition(sf::Vector2f((fieldColumns * pointSize - pointSize) / 2, 0.f));
}
}
Edge Tetromino::checkEdges()
{
if (_tetromino.getPosition().x == 0)
{
return leftEdge;
}
else if (_tetromino.getPosition().x == (fieldColumns * pointSize) - pointSize)
{
return rightEdge;
}
else return noneEdge;
}
sf::RectangleShape Tetromino::getTetromino()
{
return _tetromino;
}
sf::RectangleShape Tetromino::getStackPart(int part)
{
return _stack[part];
}
int Tetromino::getStackSize()
{
return _stack.size();
}
void Tetromino::setTetromino(sf::RectangleShape &t)
{
_tetromino = t;
}
I think the main issue could be within this line:
_stack.push_back(_tetromino);
In the drawStack() method you try to iterate backwards.
There is a reverse iterator doing this for you.
you have an off-by one error in your index calculation, which works only with an empty vector (exactly to prevent these errors you should use the iterator!)
You may want to read about iterators in C++ here is a small example.
According to your code it will look like (note that you need also a getStack()-method in Tetromino.hpp, returning the reference of the vector):
void Game::drawStack()
{
for (auto it = _T.getStack().rbegin(); it != _T.getStack().rend(); it++)
{
_window->draw(*it);
}
}
If you want to keep the index, I this is a fix:
void Game::drawStack()
{
for (int i = _T.getStackSize()-1; i >= 0; --i)
{
_window->draw(_T.getStackPart(i));
}
}
I'm just playing around with C++ SFML stuff and I kinda don't understand why my code isn't working. The thing I want to do is to draw like let's say 5, squares in Window randomly placed around the screen using vector, but I don't understand why it's not working. And it doesn't give any error as well, I can open game like normal, but it's just not rendering.
This is the main game class:
#include "main_game.h"
#include "main_menu.h"
void main_game::Initialize(sf::RenderWindow* window)
{
this->Player = new player();
this->Player->setOrigin(this->Player->getGlobalBounds().width / 2, this->Player->getGlobalBounds().height / 2);
this->TestObject = new testObject();
this->TestObject->Initialize();
this->TestObject->setOrigin(this->TestObject->getGlobalBounds().width / 2, this->TestObject->getGlobalBounds().height / 2);
}
void main_game::Update(sf::RenderWindow* window)
{
this->Player->setPosition(sf::Mouse::getPosition(*window).x, sf::Mouse::getPosition(*window).y);
this->Player->Update();
if (this->Player->CheckCollision(TestObject))
{
this->TestObject->setColor(sf::Color::Red);
}
else
{
this->TestObject->setColor(sf::Color::Cyan);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Escape))
{
coreState.SetState(new main_menu());
}
}
void main_game::Render(sf::RenderWindow* window, std::vector<sf::Sprite> sprites)
{
this->TestObject->Render(*window, sprites);
window->draw(*this->Player);
}
void main_game::Destroy(sf::RenderWindow* window)
{
delete this->Player;
delete this->TestObject;
}
This is the testObject.h class
#pragma once
#include "entity.h"
class testObject : public Entity
{
public:
testObject();
void Initialize();
void Render(sf::RenderWindow &window, std::vector<sf::Sprite> sprites);
void Update();
private:
sf::RenderWindow window;
};
And this is testObject.cpp class
#include "testObject.h"
testObject::testObject()
{
this->Load("testObject.png");
}
void testObject::Initialize()
{
sf::Texture testObjectTexture;
sf::Sprite testObjectSprite;
testObjectTexture.loadFromFile("testObject.png");
testObjectSprite.setTexture(testObjectTexture);
std::vector<sf::Sprite> sprites(5, sf::Sprite(testObjectSprite));
srand(time(0));
for (unsigned int i = 0; i < sprites.size(); i++)
{
sprites[i].setPosition(1 + (rand() % 1024 - 32), rand() % 640 - 32);
}
}
void testObject::Render(sf::RenderWindow &window, std::vector<sf::Sprite> sprites)
{
for (unsigned int i = 0; i < sprites.size(); i++)
{
window.draw(sprites[i]);
}
}
void testObject::Update()
{
Entity::Update();
}
main_game.h:
#pragma once
#include "game_state.h"
#include "player.h"
#include "testObject.h"
class main_game : public tiny_state
{
public:
void Initialize(sf::RenderWindow* window);
void Update(sf::RenderWindow* window);
void Render(sf::RenderWindow* window, std::vector<sf::Sprite> sprites);
void Destroy(sf::RenderWindow* window);
private:
player* Player;
testObject* TestObject;
};
An easy fix to this is simply use an array, or any other data structure that can store by copy rather than store by reference instead of a vector, which stores by reference, to hold the sprites.
The problem is two fold, its not just a scope issue, if you moved the render function into the initialize scope, you will draw your sprite 5 times in the same place, because every element in your vector is pointing to testObjectSprite's memory location (the same place).
I am working on a little project where I am trying to get a player in my 2D view (actually a circle) and let him move left to right, up and down flawless, also I want to be able to press 2 keys at ones so he moves sideways or something like that.
Also i want to be able to shoot with the player in a certain direction in a later state of the project (it could be important as of now)
I am doing this project because I want to learn how C++ OOP works.
The structure im having in my mind is simple :
Main > (Creates) > GameWindow
Main > (creates) > EntityManager > (creates) > Player
Player > (creates via) > EnitityManager > Gun
Gun > (Creates via) > EntityManager > Bullet
Player can :
Walk up/down/left/right
Shoot.
So to get to the code, This is what I have in my FirstGame.cpp
#include "stdafx.h"
#include "GameWindow.h"
#include "EntityManager.h"
int main()
{
// Create an entity manager
EntityManager::Instance();
// Display the window
GameWindow::Instance().Run();
}
in my GameWindow.h I have :
#pragma once
#include <SFML/Graphics.hpp>
using namespace sf;
class GameWindow
{
public:
static GameWindow& Instance()
{
static GameWindow instance;
return instance;
}
RenderWindow& GetRenderWindow();
void Run();
private:
static const int DEF_WIDTH = 1366;
static const int DEF_HEIGHT = 720;
GameWindow();
GameWindow(const GameWindow&);
GameWindow& operator=(const GameWindow&);
~GameWindow();
string windowTitle;
int windowWidth;
int windowHeight;
void Initialize();
void DisplayWindow();
void CheckWindowEvent();
};
and in my GameWindow.cpp
#include "StdAfx.h"
#include "GameWindow.h"
#include "Player.h"
#include "SFML\Graphics.hpp"
RenderWindow renderWindow;
Event eventSF;
GameWindow::GameWindow()
{
Initialize();
}
GameWindow::~GameWindow()
{
}
void GameWindow::Initialize()
{
// Set width & height to default settings
windowWidth = DEF_WIDTH;
windowHeight = DEF_HEIGHT;
// Create the render window
renderWindow.create(VideoMode(windowWidth, windowHeight), windowTitle, Style::Titlebar | Style::Close | Style::Resize);
Cmd::WriteLine("GameWindow Initialized!");
}
RenderWindow& GameWindow::GetRenderWindow()
{
return renderWindow;
}
void GameWindow::Run()
{
// Loop until window has closed
while (renderWindow.isOpen())
{
// Check current window events
CheckWindowEvent();
// Display window
DisplayWindow();
}
}
void GameWindow::DisplayWindow()
{
// Display the render window
renderWindow.clear();
renderWindow.display();
}
void GameWindow::CheckWindowEvent()
{
Event _event;
while (renderWindow.pollEvent(_event))
{
// Request for closing the window
if (_event.type == Event::Closed)
renderWindow.close();
}
}
and in my EntityManager.h I got :
#pragma once
#include "Entity.h"
#include "Player.h"
class EntityManager
{
public:
static EntityManager& Instance()
{
static EntityManager instance = EntityManager();
return instance;
}
private:
EntityManager();
~EntityManager();
void Initialize();
};
and my EntityManager.cpp
#include "StdAfx.h"
#include "EntityManager.h"
#include "GameWindow.h"
#include "Player.h"
EntityManager::EntityManager()
{
Initialize();
}
EntityManager::~EntityManager()
{
}
void EntityManager::Initialize()
{
Player::Create();
}
and now the Player.h
#pragma once
#include <SFML/Graphics.hpp>
#include "Entity.h"
using namespace sf;
class Player: Entity
{
public:
Player();
~Player();
void GotDamage(int damage);
static void Create();
void Draw();
void Shoot();
void Move(float x, float y);
void Controls(Event _eventSF);
private:
string name;
int health;
Event eventSF;
CircleShape playerVisual;
protected:
void Initialize() override;
};
and last the Player.cpp
#include "StdAfx.h"
#include "Player.h"
#include "GameWindow.h"
#include <SFML/Graphics.hpp>
Player::Player()
{
}
Player::~Player()
{
}
void Player::Create()
{
Player player;
player.Initialize();
player.Draw();
player.Controls(player.eventSF);
}
void Player::Initialize()
{
CircleShape playerVisual(50);
playerVisual.setPosition(800, 450);
playerVisual.setFillColor(sf::Color(100, 250, 50));
Entity::Initialize();
}
void Player::Controls(sf::Event _eventSF)
{
while(GameWindow::Instance().GetRenderWindow().isOpen())
{
while(GameWindow::Instance().GetRenderWindow().pollEvent(_eventSF))
{
switch(_eventSF.type)
{
case sf::Event::KeyPressed:
if (_eventSF.key.code == sf::Keyboard::Up)
{
Move(0,-1);
}
if (_eventSF.key.code == sf::Keyboard::Down)
{
Move(0,1);
}
if (_eventSF.key.code == sf::Keyboard::Left)
{
Move(-1,0);
}
if (_eventSF.key.code == sf::Keyboard::Right)
{
Move(1,0);
}
if (_eventSF.key.code == sf::Keyboard::BackSpace)
{
GotDamage(20);
}
break;
}
}
}
cout << " Checking Controls " << endl;
}
void Player::Move(float _x, float _y)
{
cout << "Move Player " << endl;
playerVisual.move(_x, _y);
Draw();
}
void Player::GotDamage(int _damage)
{
//for some reason health is -858993460
cout << "Your current health is " << Player::health << " you received " << _damage << " damage now you have " << Player::health - _damage << " health left. " << endl;
health -= _damage;
}
void Player::Draw()
{
cout << "Draw Player" << endl;
CircleShape visual(50);
playerVisual.setPosition(800, 450);
playerVisual.setFillColor(sf::Color(100, 250, 50));
GameWindow::Instance().GetRenderWindow().draw(visual);
}
I know it is a lot but I hope someone can help me.
To repeat my goal :
I am trying to get my player to be drawn on the screen and let him move sideways and if possible diagonal.
Thanks in advance!
To add onto KeyHeart's answer.
I hacked up your code a bit and managed to get it working.
Keep in mind the scope of your variables. There's CircleShape playerVisual(50) in Player::Initialize() which is a local variable, but you already have a CircleShape playerVisual inside Player.h! So the former is unnecessary. Likewise in Player::Create() you create a local player object.
I don't have a full copy of your code, so I assume what you plan on doing is having EntityManager handle all existing entities, such as the player. Therefore you should have Player player declared in the EntityManager's header file. Thus calling the constructor, which I have taken everything from Player::Create() and placed it into Player::Player(). And this player will exist for lifespan of EntityManager.
The order in which you should be updating the buffer is:
renderWindow.clear()
renderWindow.draw()
renderWindow.display()
As you have it now, you draw() then clear() effectively displaying nothing.
There are many approaches, but the simplest would be adding a call to Player::Draw() in GameWindow::DisplayWindow(). Though GameWindow will need a player object to call Draw().
Regarding moving the player. Player::Controls contains what may be an infinite loop in a sense. The line while (GameWindow::Instance().GetRenderWindow().isOpen()) will continue to loop as long as the window is open thus can block anything else from updating, such as drawing.
Shouldn't you be drawing playerVisual rather than visual which exists locally inside the Player::Draw() function?
Also shouldn't you call Player::Draw() in GameWindow::Run(), since you call GameWindow::DisplayWindow() which will update the screen. Calling Player::Draw() in Player::Move() limits drawing of the sprite only to when it moves. The results of this would be the sprite existing only in frames in which it moves otherwise an empty canvas.
I am trying to make my first pong game in c++ with sfml but I have some problems
when I try to call the window.draw() function I think my code will explain the most.
This is my Game.h
#pragma once
#include <SFML/Graphics.hpp>
class Game
{
public:
Game();
void run();
private:
void processEvents();
void update();
void render();
sf::RenderWindow mWindow;
};
My game.cpp
#pragma once
#include "Game.h"
#include "Paddle.h"
Game::Game()
: mWindow(sf::VideoMode(640,480), "Pong")
{
}
void Game::run()
{
while (mWindow.isOpen())
{
processEvents();
update();
render();
}
}
void Game::processEvents()
{
sf::Event event;
while(mWindow.pollEvent(event))
{
if(event.type == sf::Event::Closed)
mWindow.close();
}
}
void Game::render()
{
mWindow.clear();
mWindow.draw(Paddle::player1);
mWindow.display();
}
void Game::update()
{
}
my Paddle.h and paddle.cpp
#pragma once
#include <SFML/Graphics.hpp>
class Paddle
{
public:
Paddle(int width, int height);
sf::RectangleShape player1(sf::Vector2f(int width,int height));
sf::RectangleShape player2(sf::Vector2f(int width,int height));
private:
};
My paddle.h
#include "Paddle.h"
Paddle::Paddle(int width,int height)
{
}
My main.cpp
#include "Game.h"
#include "Paddle.h"
int main()
{
Game game;
Paddle player1(10,60);
Paddle player2(10,60);
game.run();
}
That was all my code.
The problem is that I don't know how to draw the paddles in my Game.cpp
I think I should use some sort of pointers or reference-argument.
When I do it like this:
void Game::render()
{
mWindow.clear();
mWindow.draw(Paddle::player1);
mWindow.display();
}
I get an error. How do I solve this?
You need something like
class Game
{
public:
Game(Paddle & p1, Paddle & p2);
...
private:
...
Paddle & mP1;
Paddle & mP2;
};
Game::Game(Paddle & p1, Paddle & p2)
: mWindow(sf::VideoMode(640,480), "Pong"),
mP1(p1), mP2(p2)
{
}
void Game::render()
{
mWindow.clear();
mWindow.draw(mP1);
mWindow.display();
}
int main()
{
Paddle player1(10,60);
Paddle player2(10,60);
Game game(player1, player1);
game.run();
}