C++ SFML 2.2 graphics not rendering - c++

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).

Related

Why is my SFML sprite not showing texture?

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.

Can't draw sf::RectangleShape s stored in vector (Tetris clone)

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));
}
}

Qt Creator Platformer Game - Can't make it work (Beginner with QGraphics)

i'm making a little game just for pratice. I basically want to make my character (a red triangle) move left and right, jump, etc.
The program is still very small at this state, And I wanna know 'how' I should do such things.
I've created a Player Class(QObject, QGraphicsPolygonItem) and a Game Class(QGraphicsView). It worked at first when I gave the Player Class a method for KeyPressEvent, but I had a problem with the jump loop : I wanted to do a scene->update() inside my jump loop, But I couldn't because the scene is an attribute of my Game Class.
Then, I tried giving the Game Class the PressKeyEvent method, so it would move the Player * player attribute.
So basically, what I want is to be able to see the position of my rect update every iteration of my for loop. Can I do that ?
Hope this makes sense, and as always, thanks a lot guys !!
Player.h & Player.cpp
#pragma once
#include <QGraphicsPolygonItem>
#include <QBrush>
class Player :
public QObject, public QGraphicsPolygonItem
{
Q_OBJECT
public:
Player();
// Setters
void setIsJumping(bool);
// Getters
bool getIsJumping();
public slots:
private:
bool isJumping;
};
#include "Player.h"
Player::Player()
{
// ***************
// Draw the player
// ***************
QVector<QPointF> gemPoints;
gemPoints << QPointF(0, 2) << QPointF(1, 0) << QPointF(2, 2);
// Size
int SCALE_BY = 8;
for (size_t i = 0; i < gemPoints.size(); i++)
{
gemPoints[i] *= SCALE_BY;
}
// Create the polygon
QPolygonF gemModel(gemPoints);
setPolygon(gemModel);
setPos(400, 500);
// Color
QBrush brush;
brush.setStyle(Qt::SolidPattern);
brush.setColor(Qt::red);
setBrush(brush);
// Make player focusable
this->setFlag(QGraphicsItem::ItemIsFocusable);
this->setFocus();
}
void Player::setIsJumping(bool jump)
{
if (jump == true)
{
isJumping = true;
}
else
{
isJumping = false;
}
}
bool Player::getIsJumping()
{
return isJumping;
}
Game.h & Game.cpp
#pragma once
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QKeyEvent>
#include "Player.h"
class Game :
public QGraphicsView
{
Q_OBJECT
public:
// Constructors
Game(QWidget* parent = NULL);
// Methods
void start();
void jump();
void keyPressEvent(QKeyEvent *event);
// Attributes
QGraphicsScene* scene;
Player* player;
};
#include "Game.h"
Game::Game(QWidget* parent)
{
// Set up the screen
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setFixedSize(1024, 768);
// Set up the scene
scene = new QGraphicsScene();
scene->setSceneRect(0, 0, 1024, 768);
setScene(scene);
}
void Game::start()
{
scene->clear();
player = new Player();
scene->addItem(player);
}
void Game::keyPressEvent(QKeyEvent * event)
{
if (event->key() == Qt::Key_Left)
{
player->setPos(x() - 3, y());
}
else if (event->key() == Qt::Key_Right)
{
player->setPos(x() + 3, y());
}
else if (event->key() == Qt::Key_Space)
{
for (size_t i = 0; i < 10; i++)
{
player->setIsJumping(true);
this->jump();
}
}
}
void Game::jump()
{
if (player->getIsJumping() == true)
{
for (size_t i = 0; i < 100; i++)
{
this->player->setPos(x(), y() - 0.1);
this->update();
}
player->setIsJumping(false);
}
}
Main.cpp
#include "plateforme.h"
#include <QtWidgets/QApplication>
#include "Game.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Game game;
game.show();
game.start();
return a.exec();
}
The problem is that I can't move the player correctly now, It moves only once and in a weird way. Any help is appreciated.
The problem is that when you set the position for player, you should modify the coordinates of player and not of this. Therefore, whenever you want to move the player, use:
player->setPos(player->x() - 3, player->y());
^ ^
and the same for jumping in your loop:
player->setPos(player->x(), player->y() - 0.1);
^ ^
When you use setPos(x()-3, y()), it sets the player position to position of your QGraphicsView, that is why it disappears from the view. Good luck with your game!

Trying to draw my player and move him

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.

Class field resets to zero

im trying to make a simple game engine, it consists of 2 classes, Game
class Game
{
protected:
SDL_Event event;
vector<Sprite> render_queue;
void render();
public:
int SCREEN_WIDTH,
SCREEN_HEIGHT,
SCREEN_BPP,
FPS;
SDL_Surface *screen;
Game(int width, int height, int fps);
void reset_screen();
void set_caption(string caption);
bool update();
void quit();
void add_sprite(Sprite spt);
};
and Sprite
class Sprite
{
public:
float x,y;
SDL_Surface* graphics;
Sprite();
void draw(SDL_Surface *target);
void loadGraphics(string path);
};
when im trying to change x or y of sprite it resets to 0 on next frame!
main.cpp
int main(int argc, char* args[])
{
Game testing(640, 480, 50);
testing.set_caption("Test");
Sprite s1;
Sprite s2;
s1.loadGraphics("img1.png");
s2.loadGraphics("img1.jpg");
testing.add_sprite(s1);
testing.add_sprite(s2);
while(!testing.update())
{
s1.x = 100;
s2.y = 200;
}
return 0;
}
You make copies of the sprites when adding them to the Game:
class Game
{
/* ... */
void add_sprite(Sprite spt);
};
That's why the lines s1.x = 100; and s2.y = 200; (operating on a different copy in the main()) have no effect.
I think the method should be instead defined like that:
class Game
{
/* ... */
void add_sprite(Sprite &spt);
};
That way Game would be using the Sprite objects from the main().
testing.add_sprite(s2); makes a copy of sprite, so changing the value of s1,s2 in the main code has no effect on the copy in testing.
You need to pass by reference or pointer to to add_sprite()