I have created a class takeDommage for apply a number or dmg and activate a countdown for create the invincibility frame.
And i us my "int pv; in my class so then i check the "int pv;" he didn't move
What's wrong ? pv is initialized before main and it's working then i do pv-=1; manually Oo
main :
//{ Include
#include <SFML/Graphics.hpp>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include<vector>
#include <collision.h>
//}
//{ Constantes
//Constantes ecran
int tailleEcranX = 1280;
int tailleEcranY = 720;
//Constantes perso
int scalePerso = 3;
int tailleSpriteX = 32;
int tailleSpriteY = 48;
int speed(4);
int speedSprinte(10);
int milieuSpriteX = (tailleSpriteX/2)*scalePerso;
int milieuSpriteY = (tailleSpriteY/2)*scalePerso;
int pv = 100;
unsigned int pvMax = 100;
int eSpeed = 1;
//}
//{ Initialisation
//Initiation des dessins
sf::RenderWindow window;
sf::RectangleShape rect;
sf::Texture perso;
sf::Texture ennemis;
sf::Sprite sprite_perso;
sf::Sprite sprite_ennemis;
sf::View view;
sf::RectangleShape rectCol;
sf::RectangleShape pvBar;
sf::RectangleShape pvMaxBar;
enum Dir{Down,Left,Right,Up};
sf::Vector2i anim (1,Down);
#include "gestion_clavier.h"
#include <takeDommage.h>
//}
//{ Main
int main()
{
//{ Positionnement des objets
window.create(sf::VideoMode(tailleEcranX , tailleEcranY), "The Game I");
window.setPosition(sf::Vector2i(500,250));
window.setFramerateLimit(120);
//Fond d'ecran
rect.setFillColor(sf::Color(110,155,255));
rect.setSize(sf::Vector2f(tailleEcranX-10,tailleEcranY-10));
rect.setPosition(5,5);
rect.setOutlineColor(sf::Color(255,255,255));
rect.setOutlineThickness(3);
//rectangle de collision test
rectCol.setFillColor(sf::Color(0,0,200));
rectCol.setSize(sf::Vector2f(50,50));
rectCol.setPosition(400,500);
rectCol.setOutlineColor(sf::Color(255,255,255));
rectCol.setOutlineThickness(1);
//Bar pv
pvBar.setFillColor(sf::Color(20,255,30));
pvBar.setPosition(20,20);
pvMaxBar.setFillColor(sf::Color(0,0,0));
pvMaxBar.setPosition(20,20);
pvMaxBar.setOutlineColor(sf::Color(255,255,255));
pvMaxBar.setOutlineThickness(2);
//Perso
sprite_perso.setTexture(perso);
sprite_perso.setPosition(tailleEcranX/2-milieuSpriteX,tailleEcranY/2-milieuSpriteY);
sprite_perso.setScale(scalePerso,scalePerso);
//Ennemis
sprite_ennemis.setTexture(ennemis);
sprite_ennemis.setPosition(tailleEcranX/2-milieuSpriteX,tailleEcranY/2-milieuSpriteY);
sprite_ennemis.setTextureRect(sf::IntRect(anim.x*tailleSpriteX,anim.y*tailleSpriteY,tailleSpriteX,tailleSpriteY));
sprite_ennemis.setScale(scalePerso,scalePerso);
//Ennemis
sf::RectangleShape enemy;
enemy.setFillColor(sf::Color(200,0,0));
enemy.setSize(sf::Vector2f(50.f, 50.f));
takeDommage obj;
//Clock
sf::Clock time;
//sf::Clock takeDammageClock;
//}
//{Chargement des Sprites
if (!perso.loadFromFile("link/srpite.png",sf::IntRect(0,0,96,192)))
{
std::cout<<"erreur chargement player image"<<std::endl;
}
if (!ennemis.loadFromFile("link/srpite.png",sf::IntRect(288,0,96,192)))
{
std::cout<<"erreur chargement player image"<<std::endl;
}
//}
//{ Game Loop
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
//Stat avec rafrechisement
//Bar pv
pvMaxBar.setSize(sf::Vector2f(4*pvMax,10));
pvBar.setSize(sf::Vector2f(4*pv,10));
//Perso
sprite_perso.setTextureRect(sf::IntRect(anim.x*tailleSpriteX,anim.y*tailleSpriteY,tailleSpriteX,tailleSpriteY));
//Ennemy
std::vector<sf::RectangleShape> enemies;
enemies.push_back(sf::RectangleShape(enemy));
int enemySpawnTimer = 0;
ProcessInput();
//gestion_clavier();
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Z)||sf::Keyboard::isKeyPressed(sf::Keyboard::S)||sf::Keyboard::isKeyPressed(sf::Keyboard::D)||sf::Keyboard::isKeyPressed(sf::Keyboard::Q))
{
if (time.getElapsedTime().asMilliseconds()>= 50)
{
anim.x++;
if(anim.x*tailleSpriteX >= perso.getSize().x)
anim.x=0;
time.restart();
}
}
//Boucle Pv
if(pv>=pvMax)
{
pv=pvMax;
}
if(pv<=0)
{
pv=0;
}
//ENEMIES
if(enemySpawnTimer < 50)
enemySpawnTimer++;
if (enemySpawnTimer >= 50)
{
enemy.setPosition((rand() % int(window.getSize().x - enemy.getSize().x)), 0.f);
enemies.push_back(sf::RectangleShape(enemy));
enemySpawnTimer = 0;
}
for (size_t i = 0; i < enemies.size(); i++)
{
enemies[i].move(0, eSpeed);
if (enemies[i].getPosition().y > window.getSize().y)
enemies.erase(enemies.begin() + i);
}
//Collision
if(Collision::PixelPerfectTest(sprite_perso,sprite_ennemis))
{
//std::cout<<"collision pp"<<std::endl;
obj.prendreDegat(50 ,pv);
//std::cout<<pv<<std::endl;
}
//Dessinage
window.draw(rect);
window.draw(rectCol);
window.draw(sprite_perso);
window.draw(sprite_ennemis);
window.draw(pvMaxBar);
window.draw(pvBar);
//Boucle dessinage
for (size_t i = 0; i < enemies.size(); i++)
{
window.draw(enemies[i]);
}
window.display();
window.clear();
}
//}
return 0;
}
takeDommage.h :
#ifndef TAKEDOMMAGE_H
#define TAKEDOMMAGE_H
#include <SFML/Graphics.hpp>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cmath>
class takeDommage
{
public:
takeDommage();
void prendreDegat(int Dommage, int pv);
//virtual ~takeDommage();
protected:
sf::Clock takeDammageClock;
int Dommage;
private:
};
#endif // TAKEDOMMAGE_H
takeDommage.cpp :
#include "takeDommage.h"
takeDommage::takeDommage()
{
}
void takeDommage::prendreDegat(int Dommage, int pv)
{
if(takeDammageClock.getElapsedTime().asSeconds()>3)
{
std::cout << "bite" << std::endl;
pv -= Dommage;
takeDammageClock.restart();
}
}
if(Collision::PixelPerfectTest(sprite_perso,sprite_ennemis))
{
//std::cout<<"collision pp"<<std::endl;
obj.prendreDegat(50 ,pv);
//std::cout<<pv<<std::endl;
}
you are passing the pv by value.
this causes the void takeDommage::prendreDegat(int Dommage, int pv) to make a local copy of of the pv and decrements the value by Dommage.
what you have to do is pass it by reference. in c++ you do that by Type&
so in your case you change your takeDommage to void takeDommage::prendreDegat(int Dommage, int& pv)
since the pv is now passed by reference, any operation you make in takeDommage::prendreDegat will affect the global pv.
Edit: passing the global variables is not considered a good code practice. But im not going to go into details into that since you just starting c++. Try moving your std::cout<<pv<<std::endl from your main and place it into void takeDommage::prendreDegat(int Dommage, int pv) without making changes and see what happens.
Related
I am checking whether the player has collided with the bullet or not but it gives me an error saying non-const lvalue reference to type 'Sprite' cannot bind to a temporary of type 'Sprite'
here is my main.cpp
#include <SFML/Graphics.hpp>
#include "Player.hpp"
#include "Enemy.hpp"
#include "Game.cpp"
#include"Text.hpp"
#include <vector>
int main()
{
sf::RenderWindow window = sf::RenderWindow(sf::VideoMode(2000, 2000), "Space Outwaders", sf::Style::Close | sf::Style::Titlebar);
window.setFramerateLimit(240);
window.setMouseCursorVisible(false);
// clock
sf::Clock clock;
sf::Clock m_timeElapsed;
// ground
Sprite ground("assets/ground.png");
ground.setPosition(0, 1872);
// player
Player player("assets/player.png");
float gravity = 1.8;
player.setPosition(0, 1590);
//player Text
Text hearts("20","assets/hearts.ttf");
hearts.setSize(60);
hearts.setColor(sf::Color::Red);
// enemy
std::vector<std::pair<Enemy, float>> enemy;
Enemy s("assets/enemy.png");
enemy.push_back(std::pair<Enemy, float>(s, 100));
enemy.push_back(std::pair<Enemy, float>(s, 328));
enemy.push_back(std::pair<Enemy, float>(s, 556));
enemy.push_back(std::pair<Enemy, float>(s, 784));
enemy.push_back(std::pair<Enemy, float>(s, 986));
enemy.push_back(std::pair<Enemy, float>(s, 986 + 228));
int timeElapsedCount = 3;
// time
sf::Time c_time = clock.getElapsedTime();
float m_time = m_timeElapsed.getElapsedTime().asSeconds();
// game loop
sf::Event *ev = new sf::Event;
while (window.isOpen())
{
c_time = clock.getElapsedTime();
m_time = m_timeElapsed.getElapsedTime().asSeconds();
// game loop
ev = new sf::Event;
clock.restart().asSeconds();
if (!player.getCollision(ground))
{
player.move(0, gravity * c_time.asMilliseconds());
}
while (window.pollEvent(*ev))
{
if (ev->type == sf::Event::Closed)
{
window.close();
}
if (player.getSprite().getGlobalBounds().left > -1 && 1941 >= player.getSprite().getGlobalBounds().left)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A) && player.getCollision(ground))
player.left(c_time.asMilliseconds()*2);
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D) && player.getCollision(ground))
player.right(c_time.asMilliseconds()*2);
}
else if (player.getSprite().getGlobalBounds().left <= -1)
player.move(0.1, 0);
else
player.move(-0.1,0);
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S) && player.getCollision(ground))
player.move(0, 10);
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
player.move(0, -10);
}
window.clear(sf::Color(21, 21, 21));
ground.drawSprite(&window);
for (int i = 0; i < std::size(enemy); i++)
{
if (timeElapsedCount <= m_time)
{
timeElapsedCount = m_time+3;
std::cout << timeElapsedCount << std::endl;
}
else if(timeElapsedCount % 2 == 0)
enemy.at(i).second -= 1;
else
enemy.at(i).second += 1;
enemy.at(i).first.setColor(sf::Color(136, 136, 136));
enemy.at(i).first.setPosition(enemy.at(i).second, 0);
enemy.at(i).first.drawSprite(&window);
enemy.at(i).first.moveBullet(1.3*c_time.asMilliseconds(), &ground, &player);
enemy.at(i).first.drawBullet(&window);
if (player.getCollision( enemy.at(i).first.getBullet()))
{
/* code */
}
}
hearts.drawText(&window);
player.drawSprite(&window);
window.display();
delete ev;
}
return 0;
}
here is my sprite class:
#pragma once
#include <SFML/Graphics.hpp>
#include <iostream>
class Sprite
{
protected:
sf::Texture texture;
sf::Sprite sprite;
public:
Sprite(std::string fileName);
sf::Sprite getSprite();
void drawSprite(sf::RenderWindow *window);
void setPosition(int X, int Y);
void move(float X, float Y);
void setColor(sf::Color color);
};
Sprite ::Sprite (std::string fileName)
{
texture.loadFromFile(fileName);
sprite.setTexture(texture);
}
sf::Sprite Sprite ::getSprite()
{
return sprite;
}
void Sprite ::drawSprite(sf::RenderWindow *window)
{
window->draw(sprite);
}
void Sprite ::setPosition(int X, int Y)
{
sprite.setPosition(sf::Vector2f(X, Y));
}
void Sprite :: move(float X , float Y)
{
sprite.move(sf::Vector2f(X,Y));
}
void Sprite :: setColor(sf::Color color)
{
sprite.setColor(color);
}
and my enemy class :
#include "Game.hpp"
class Enemy : public Sprite
{
Sprite * bullet;
public:
void drawBullet(sf::RenderWindow * window);
Enemy(std::string fileName);
void moveBullet(float Y , Sprite * gameObject , Sprite * gameObject2);
void randomLeft(float amount);
auto getBullet();
};
Enemy :: Enemy(std::string fileName) : Sprite(fileName)
{
this->bullet = new Sprite("assets/bullet.png");
this->bullet->setPosition(this->sprite.getPosition().x+120,100);
}
void Enemy :: drawBullet(sf::RenderWindow * window)
{
window->draw(this->bullet->getSprite());
}
void Enemy :: moveBullet(float Y , Sprite * gameObject , Sprite * gameObject2)
{
if (bullet->getSprite().getGlobalBounds().intersects(gameObject->getSprite().getGlobalBounds()) || bullet->getSprite().getGlobalBounds().intersects(gameObject2->getSprite().getGlobalBounds()))
{
// delete bullet; this will give segmentation fault i have to fix this later
this->bullet = new Sprite("assets/bullet.png");
this->bullet->move(this->sprite.getPosition().x+56,100);
}
else
this->bullet->move(0,Y);
}
void Enemy :: randomLeft(float amount)
{
}
// srand((unsigned)time(NULL));
// for (int x = 0; x < 3; x++)
// {
// // Type casting the result to float
// cout << rand() / 10000000 << endl;
// cout << time(0) << std::endl;
// }
auto Enemy :: getBullet()
{
return *bullet;
}
the enemy class has a function that returns a Sprite class object.
and in the main.cpp I check where the player has collided but I keep getting this
error: non-const lvalue reference to type 'Sprite' cannot bind to a temporary of type 'Sprite'
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 writing a simple isometric game - simulator of town development. The main classes are Player class and World class. So, the problem is, that when I launching my game, all seems to be going as planned, but when I want to click "X" to close it, at the moment cursor reach place, in which red arrow points, program is being breaked this error.
It is not happening, when Player object is not created, so I think some problem in it.
Player.hpp:
#ifndef PLAYER_HEADER
#define PLAYER_HEADER
#include "Main.hpp"
#include "ToScreenF.hpp"
#include <iostream>
class Player
{
public:
sf::Vector2i MousePos;
sf::Vector2i inCell;
sf::Vector2i cellOffset;
sf::Vector2i cellSelected;
sf::Vector2f cellSelectedInWorldSpace;
sf::Image selectedTileImage;
sf::Texture selectedTileTexture;
sf::Sprite selectedTileSprite;
sf::Image CheatImage;
sf::Color color;
Player(std::string FILE);
~Player();
void Update(sf::RenderWindow* Window, sf::Vector2f TileSize, sf::Vector2f vOrigin, int WorldWidth, int WorldHeight);
};
#endif PLAYER_HEADER
Player.cpp:
#include "Player.hpp"
Player::Player(std::string FILE)
{
selectedTileImage.loadFromFile(FILE);
selectedTileImage.createMaskFromColor(sf::Color::White);
selectedTileTexture.loadFromImage(selectedTileImage);
selectedTileSprite.setTexture(selectedTileTexture);
CheatImage.loadFromFile("tileCheat.png");
}
void Player::Update(sf::RenderWindow* Window, sf::Vector2f TileSize, sf::Vector2f vOrigin, int WorldWidth, int WorldHeight)
{
MousePos = {sf::Mouse::getPosition((*Window))};
inCell = {(int)(MousePos.x / TileSize.x), (int)(MousePos.y / TileSize.y) };
cellOffset = { MousePos.x % (int)TileSize.x, MousePos.y % (int)TileSize.y };
cellSelected = {
(inCell.y - (int)vOrigin.y) + (inCell.x - (int)vOrigin.x),
(inCell.y - (int)vOrigin.y) - (inCell.x - (int)vOrigin.x)
};
color = CheatImage.getPixel(cellOffset.x, cellOffset.y);
if (color == sf::Color::Red) { cellSelected.x += -1; cellSelected.y += 0; };
if (color == sf::Color::Blue) { cellSelected.x += 0; cellSelected.y += -1; };
if (color == sf::Color::Green) { cellSelected.x += 0; cellSelected.y += 1; };
if (color == sf::Color::Yellow) { cellSelected.x += 1; cellSelected.y += 0; };
if (cellSelected.x < 0) cellSelected.x = 0;
if (cellSelected.x > (WorldWidth - 1)) cellSelected.x = 19;
if (cellSelected.y < 0) cellSelected.y = 0;
if (cellSelected.y > (WorldHeight - 1)) cellSelected.y = 19;
cellSelectedInWorldSpace = ToScreen(cellSelected.x, cellSelected.y, TileSize, vOrigin);
selectedTileSprite.setPosition(cellSelectedInWorldSpace);
Window->draw(selectedTileSprite);
std::cout << cellSelected.x << " " << cellSelected.y << std::endl;
}
ToScreenF.cpp:
#include "ToScreenF.hpp"
sf::Vector2f ToScreen(int x, int y, sf::Vector2f TileSize, sf::Vector2f vOrigin)
{
return sf::Vector2f
{
(vOrigin.x * TileSize.x) + (x - y) * (TileSize.x / 2),
(vOrigin.y * TileSize.y) + (x + y) * (TileSize.y / 2)
};
}
TApplication.hpp:
#ifndef TAPPLICATION_HEADER
#define TAPPLICATION_HEADER
#include "Main.hpp"
#include "World.hpp"
#include "Player.hpp"
namespace Application
{
class TApplication
{
protected:
sf::RenderWindow *Window;
World *GameWorld;
Player* _Player;
public:
TApplication();
~TApplication();
void Init();
void Run();
void End();
};
}
TApplication.cpp:
#include "TApplication.hpp"
namespace Application
{
TApplication::TApplication() : Window(nullptr)
{
}
TApplication:: ~TApplication()
{
}
void TApplication::Init()
{
if (Window == nullptr)
Window = new sf::RenderWindow(sf::VideoMode(1200, 800), "Town Builder Simulator");
GameWorld = new World("BasicTile.png", 100, 100);
_Player = new Player("selectedTile.png");
}
void TApplication::Run()
{
sf::Event event;
while (Window->isOpen())
{
while(Window->pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
Window->close();
}
}
Window->clear();
GameWorld->Draw(Window);
_Player->Update(Window, sf::Vector2f(40, 20), sf::Vector2f(10, 10), GameWorld->WorldWidth, GameWorld->WorldHeight);
Window->display();
}
}
void TApplication::End()
{
if (Window != nullptr)
{
delete Window;
delete GameWorld;
Window = nullptr;
}
}
}
**Main.hpp**
#ifndef MAIN_HEADER
#define MAIN_HEADER
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/Audio.hpp>
#include <SFML/Network.hpp>
#include <SFML/System.hpp>
#endif
Thanks in advance all who helped me, I am very grateful!)
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));
}
}
Hello I add Text Class to my project , where text is fallowing the moving ball
i build is successful, but when i trying debuging i receive
Unhandled exception at 0x0F58155F (sfml-graphics-d-2.dll) in Lotto.exe: 0xC0000005: Access violation reading location 0xCCCCCD24.
My main.cpp
#include <iostream>
#include <SFML/Graphics.hpp>
#include "Ball.h"
#include "Line.h"
#include "TextBall.h"
using namespace std;
using namespace sf;
int main()
{
RenderWindow win(VideoMode(800, 600), L"RozdziaĆ 1");
Clock stoper;
Font font;
font.loadFromFile("arial.ttf");
float ySpeed = -100;
float xSpeed = -100;
Ball CircleOne(win);
Line linia1(win);
linia1.sie(500, 500);
linia1.position(20, 20);
linia1.thiness(2);
TextBall text(win);
text.dFont(font);
text.dString("Hello");
text.dCharacterSize(40);
text.dColor(sf::Color::Black);
text.dPosition(CircleOne.GetPosition().x + 5, CircleOne.GetPosition().y);
CircleOne.SetPozition(100, 100);
// CircleOne.SetOutlineColor(Color::Red);
CircleOne.Fil(Color::Yellow);
CircleOne.Promien(15);
// CircleOne.thinesS();
while (win.isOpen())
{
win.clear(Color::White);
Event e;
while (win.pollEvent(e))
{
if (e.type == Event::Closed)
win.close();
}
auto dt = stoper.restart().asSeconds();
CircleOne.Move(xSpeed *dt , ySpeed * dt);
//text.Move(xSpeed *dt, ySpeed * dt);
linia1.draw();
CircleOne.Draw();
text.Draw();
int positionY = CircleOne.GetPosition().y;
if (positionY <= 0){ ySpeed = -ySpeed; }
if (positionY >= 600.0-2*CircleOne.radius()){ ySpeed = -ySpeed; }
int positionX = CircleOne.GetPosition().x;
if (positionX <= 0){ xSpeed = -xSpeed; }
if (positionX >= 800.0-2*CircleOne.radius()){xSpeed = -xSpeed; }
win.display();
}
}
and TextBall class
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <iostream>
using namespace std;
using namespace sf;
class TextBall{
public:
TextBall(RenderWindow&);
void dString(String);
void dCharacterSize(int);
void dColor(Color);
void dPosition(float, float);
void Move(float, float);
void Draw();
void dFont(Font);
private:
Text text;
RenderWindow& Render;
};
TextBall::TextBall(sf::RenderWindow& app) : Render(app)
{
}
void TextBall::dString(String liczba)
{
text.setString(liczba);
}
void TextBall::dCharacterSize(int size)
{
text.setCharacterSize(size);
}
void TextBall::dColor(Color kolor)
{
text.setColor(kolor);
}
void TextBall::dPosition(float x, float y)
{
text.setPosition(x, y);
}
void TextBall::Move(float a, float b)
{
text.move(a, b);
}
void TextBall::Draw()
{
Render.draw(text);
}
void TextBall::dFont(Font fon)
{
text.setFont(fon);
}
When i add text without a additional class its working fine, i afraid it object sending in TextBall is faulty. Plaese how can i solve this project