Crash when using arrays of sf::Text - c++

When I load and set font, app crashes and debugger shows me 0xc0000005 at line in MainMenu.cpp (exception is reported by sfml-graphics-d-2.dll):
window.draw(menu.at[i]);
This is line in for loop.
Btw. every time I close my app I have an error "Run-Time Check Failure #2 - Stack around the variable 'window' was corrupted." and debugger show end of main().
MainMenu.h:
#include <SFML/Graphics.hpp>
class MainMenu
{
public:
MainMenu();
void draw(sf::RenderWindow& window);
void MoveUp();
void MoveDown();
private:
std::array<sf::Text,3> menu;
sf::Font arial;
unsigned int cursor{ 0 };
};
MainMenu.cpp:
#include "MainMenu.h"
#include <SFML/Graphics.hpp>
#include <iostream>
constexpr int PLAY{ 1 };
constexpr int SETTINGS{ 2 };
constexpr int EXIT{ 3 };
MainMenu::MainMenu()
{
arial.loadFromFile("ArialUnicodeMS.ttf");
menu[0].setFont(arial);
menu[0].setCharacterSize(40);
menu[0].setFillColor(sf::Color::White);
menu[0].setString("Play!");
menu[0].setPosition(sf::Vector2f(400, PLAY * 40));
menu[1].setFont(arial);
menu[1].setCharacterSize(40);
menu[1].setFillColor(sf::Color::White);
menu[1].setString("Settings");
menu[1].setPosition(sf::Vector2f(400, SETTINGS * 40));
menu[2].setFont(arial);
menu[2].setCharacterSize(40);
menu[2].setFillColor(sf::Color::White);
menu[2].setString("Exit");
menu[2].setPosition(sf::Vector2f(400, EXIT * 40));
}
void MainMenu::draw(sf::RenderWindow& window)
{
for (int i = 0; i < 3; i++)
{
window.draw(menu[i]);
}
}
void MainMenu::MoveUp()
{
if (cursor - 1 >= 0)
{
std::cout << "moved up!";
menu[cursor].setFillColor(sf::Color::White);
cursor--;
menu[cursor].setFillColor(sf::Color::Red);
}
}
void MainMenu::MoveDown()
{
if (cursor + 1 < 3)
{
std::cout << "moved down!";
menu[cursor].setFillColor(sf::Color::White);
cursor++;
menu[cursor].setFillColor(sf::Color::Red);
}
}
main.cpp:
#include "Game.h"
#include "MainMenu.h"
#include "ConstState.h"
#include "Settings.h"
#include <SFML/Graphics.hpp>
#include <iostream>
int main()
{
sf::RenderWindow window(sf::VideoMode(800,600), "test");
Game game;
MainMenu menu;
Settings settings;
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
switch (event.type)
{
case sf::Event::KeyReleased:
switch (event.key.code)
{
case sf::Keyboard::Up:
menu.moveUp();
break;
case sf::Keyboard::Down:
menu.moveDown();
break;
case sf::Keyboard::Return:
switch (menu.getCursor())
{
case 0:
std::cout << "play";
game.run(window);
break;
case 1:
std::cout << "settings";
break;
case 2:
window.close();
break;
}
break;
}
break;
case sf::Event::Closed:
window.close();
break;
}
}
window.clear(sf::Color::Red);
menu.draw(window);
window.display();
}
return 0;
}

In MainMenu::MoveUp() you write: if (cursor - 1 >= 0) ...
First of all, this condition is always true: cursor is an unsigned int, so it has no other options but to be >= 0.
Secondly, in the case when cursor is 0, your cursor - 1 yields the maximum value of unsigned int (as it wraps on overflow). As a result, menu[cursor].setFillColor... causes undefined behaviour because you give your std::array<sf::Text, 3> menu an invalid index.
Try fixing this and check if the error shows up again.

Related

SFML, how to change property of a rectangle when a certain condition is met

So I just started learning SFML. So, I want to take an input x. And when x=1 the color of the rectangle that I created changes. Here is my code:
#include <SFML/Graphics.hpp>
#include <iostream>
using namespace std;
int main()
{
int x;
sf::RenderWindow MW(sf::VideoMode(1200, 650), "Dominus", sf::Style::Close |
sf::Style::Titlebar);
sf::RectangleShape bg(sf::Vector2f(1200.0f, 650.0f)); bg.setFillColor(sf::Color::Green);
while (MW.isOpen()) {
sf::Event evnt;
while (MW.pollEvent(evnt)) {
switch (evnt.type) {
case sf::Event::Closed:
MW.close(); break;
}
}
cin >> x;
if (x == 1) {
bg.setFillColor(sf::Color::Blue);
}
MW.clear();
MW.draw(bg);
MW.display();
}
return 0;
}
Now the problem here that I am facing is that the window does not load properly. And when I move the 'cin' out of the loop, I can't seem to take an input at all.
You can use threads:
#include <SFML/Graphics.hpp>
#include <iostream>
#include <mutex>
#include <thread>
int main() {
std::mutex xmutex;
int x = 0;
std::thread thr([&]() {
std::lock_guard<std::mutex> lock(xmutex);
int x;
std::cin >> x;
});
thr.detach();
sf::RenderWindow MW(sf::VideoMode(1200, 650), "Dominus", sf::Style::Close | sf::Style::Titlebar);
sf::RectangleShape bg(sf::Vector2f(1200.0f, 650.0f)); bg.setFillColor(sf::Color::Green);
while (MW.isOpen()) {
sf::Event evnt;
while (MW.pollEvent(evnt)) {
switch (evnt.type) {
case sf::Event::Closed:
MW.close(); break;
}
}
{
std::lock_guard<std::mutex> lock(xmutex);
if (x == 1) {
bg.setFillColor(sf::Color::Blue);
}
}
MW.clear();
MW.draw(bg);
MW.display();
}
}

sfml - vector[0].getPosition() returns 0

I was making a simple snake game but when I tried moving a part of my snake
it went to 0,0.
I keep all parts of my snake inside a vector.
But when I do something like
vector[0].getPosition()
//(In my code: snakeParts[0].getPosition())
It just returns 0,0.
I also don't get any error whilst compiling.
Here's my code:
#include <SFML/Graphics.hpp>
#include <iostream>
#include <string>
#include <unistd.h>
#include <vector>
using namespace std;
sf::RenderWindow App(sf::VideoMode(854, 480), "Snake");
sf::RectangleShape snake;
sf::RectangleShape snake2;
vector<sf::RectangleShape> snakeParts;
string movingDirection = "Right";
int updatePos() {
snakeParts[1].setPosition(snakeParts[0].getPosition()); //Where my problem lies
if (movingDirection == "Left") {
snake.move(-32,0);
}
else if (movingDirection == "Right") {
snake.move(32,0);
}
else if (movingDirection == "Up") {
snake.move(0,-32);
}
else if (movingDirection == "Down") {
snake.move(0,32);
}
//for (int i=0; i<snakeParts.size(); i++) {
//int target = snakeParts.size()-i;
}
int main()
{
snake.setSize(sf::Vector2f(32, 32));
snake.setFillColor(sf::Color::Green);
snake2.setSize(sf::Vector2f(32, 32));
snake2.setFillColor(sf::Color::Red);
snakeParts.push_back(snake);
snakeParts.push_back(snake2);
while (App.isOpen())
{
sf::Event event;
while (App.pollEvent(event))
{
if (event.type == sf::Event::Closed)
App.close();
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) {
movingDirection = "Left";
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) {
movingDirection = "Right";
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {
movingDirection = "Down";
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
movingDirection = "Up";
}
}
usleep(100000);
//cout << movingDirection << endl;
updatePos();
App.clear();
App.draw(snake);
App.draw(snake2);
App.display();
}
return 0;
}
I think it's something to do with pointers?
But I wouldn't know how I would fix that...
Dump those global snakeN variables! Are you going to declare everything up to snake100 if you want to have 100 cells? Your vector is storing copies (those are left untouched on (0, 0)), on which you should be performing all the logic.
Make all other global variables local to a function or member of a class and use function parameters where needed.
movingDirection should be an enum.
updatePos with its current signature should return something.

RenderWindow Constantly Updating display() Causing Flickering

I am trying to write a program which allows users to draw using the mouse. I have been trying many different ways to appropriately update the display using an object of sf::RenderWindow to call display() without much success. My loop where the drawing is occurring is calling display so fast it's causing massive flickering (confirmed that through testing). If I add a way to slow the call to display(), like using sf::Clock, then the drawing is only updated on the same delay as display() resulting in a stuttering effect. What I need is a way to update the display often enough to show drawing updates while also not causing a screen flicker.
Currently, I've got the display on a delay (at the bottom of the event polling switch statement) so flickering doesn't occur, but adding mainWindow.display(); to the void MainWindow::draw() function causes flickering as it updates too quickly. I had the drawing occurring on sf::Event::MouseMoved, but I tried changing it to see if that would help, and it did not.
Here's where all the drawing and event detection occurs:
MainWindow.h
#pragma once
#include "GraphPaper.h"
#include "stdafx.h"
class MainWindow
{
public:
MainWindow(short, short);
void close();
void start();
void moveCamera(sf::Keyboard::Key);
void draw(sf::Event);
void displayWindow(sf::Vector2i&);
private:
bool leftMousePressed, rightMousePressed, isExiting;
int r, g, b, mouseX, mouseY;
short height, width;
const short DRAWING_CRICLE_RADIUS = 10;
GraphPaper paper;
//DrawingBrush brush;
const sf::Color WHITE = sf::Color(255, 255, 255);
const sf::Color BLACK = sf::Color(0, 0, 0);
sf::CircleShape circle;
sf::Mouse cursor;
sf::Vector2i windowCenter;
sf::RenderWindow mainWindow;
sf::View view;
};
MainWindow.cpp:
#include "MainWindow.h"
#include "GraphPaper.h"
#include "stdafx.h"
MainWindow::MainWindow(short height, short width)
{
this->height = height;
this->width = width;
circle.setRadius(DRAWING_CRICLE_RADIUS);
circle.setFillColor(BLACK);
}
void MainWindow::start()
{
sf::Clock clock;
mainWindow.create(sf::VideoMode(height, width, 32), "Test");
sf::View view(sf::FloatRect(0,0,height,width));
mainWindow.setView(view);
leftMousePressed, rightMousePressed, isExiting = false;
sf::Event currentEvent;
sf::Vector2i windowCenter(mainWindow.getPosition().x + (mainWindow.getSize().x / 2), mainWindow.getPosition().y + (mainWindow.getSize().y / 2));
displayWindow(windowCenter);
while (!isExiting)
{
sf::Clock clock;
while (mainWindow.pollEvent(currentEvent))
{
switch (currentEvent.type)
{
case sf::Event::MouseMoved:
{
if (rightMousePressed == true)
{
std::cout << "Mouse Panned\n";
}
if (leftMousePressed == true)
{
draw(currentEvent);
}
break;
}
case sf::Event::MouseButtonPressed:
{
std::cout << "Mouse Pressed\n";
mouseX = currentEvent.mouseButton.x;
mouseY = currentEvent.mouseButton.y;
if (currentEvent.mouseButton.button == sf::Mouse::Left)
{
while (currentEvent.type != sf::Event::MouseButtonReleased)
{
std::cout << "Mouse is Drawing\n";
draw(currentEvent);
mainWindow.pollEvent(currentEvent);
}
}
else if (currentEvent.mouseButton.button == sf::Mouse::Right)
{
rightMousePressed = true;
}
break;
}
case sf::Event::MouseButtonReleased:
{
std::cout << "Mouse Released\n";
if (currentEvent.mouseButton.button == sf::Mouse::Left)
{
leftMousePressed = false;
}
else if(currentEvent.mouseButton.button == sf::Mouse::Right)
{
rightMousePressed = false;
}
break;
}
case sf::Event::KeyPressed:
{
sf::Keyboard::Key keyPressed = currentEvent.key.code;
if(keyPressed == sf::Keyboard::Escape)
{
close();
}
else if(keyPressed == sf::Keyboard::Left || sf::Keyboard::Right ||
sf::Keyboard::Down || sf::Keyboard::Up ||
sf::Keyboard::A || sf::Keyboard::S ||
sf::Keyboard::D || sf::Keyboard::W)
{
moveCamera(keyPressed);
displayWindow(windowCenter);
}
break;
}
case sf::Event::Closed:
{
close();
break;
}
case sf::Event::Resized:
{
windowCenter = sf::Vector2i(mainWindow.getPosition().x + (mainWindow.getSize().x / 2), mainWindow.getPosition().y + (mainWindow.getSize().y / 2));
displayWindow(windowCenter);
break;
}
}
if (clock.getElapsedTime().asMilliseconds() >= 500)
{
clock.restart();
mainWindow.display();
}
}
}
}
void MainWindow::moveCamera(sf::Keyboard::Key keyPressed)
{
view = mainWindow.getView();
switch (keyPressed)
{
case sf::Keyboard::A:
case sf::Keyboard::Left:
{
view.move(-50, 0);
break;
}
case sf::Keyboard::D:
case sf::Keyboard::Right:
{
view.move(50, 0);
break;
}
case sf::Keyboard::W:
case sf::Keyboard::Up:
{
view.move(0, 50);
break;
}
case sf::Keyboard::S:
case sf::Keyboard::Down:
{
view.move(0, -50);
break;
}
}
mainWindow.setView(view);
}
void MainWindow::draw(sf::Event mouse)
{
circle.setPosition(mainWindow.mapPixelToCoords(sf::Vector2i(mouse.mouseMove.x, mouse.mouseMove.y)));
mainWindow.draw(circle);
}
void MainWindow::close()
{
std::cout << "Closing...\n";
mainWindow.close();
isExiting = true;
}
void MainWindow::displayWindow(sf::Vector2i& windowCenter)
{
mainWindow.clear(WHITE);
mainWindow.draw(paper.getSprite());
mainWindow.display();
cursor.setPosition(windowCenter);
}
You are missing an important part of the rendering loop. You should draw all parts every loop iteration. Right now you are only drawing your circle when it's changed.
Your code should look like this:
change circle position based on input
clear window
draw circle
display

SFML VideoMode breaks application

Using SFML sf::VideoMode breaks my application, saying that "Singularity.exe has stopped working"
Specifically this line :
_mainWindow.create(sf::VideoMode(1024,768,32), "Singularity");
This line is what is causing the problem. When I remove it, the application works fine. Here is the whole code of the main class file:
#include "stdafx.h"
#include "Game.h"
void Game::Start(void)
{
if (_gameState != Uninitialized)
return;
_mainWindow.create(sf::VideoMode(1024,768,32), "Singularity");
_gameState = Game::Playing;
while (!IsExiting())
{
GameLoop();
}
_mainWindow.close();
}
bool Game::IsExiting()
{
if (_gameState == Game::Exiting)
return true;
else
return false;
}
void Game::GameLoop()
{
sf::Event currentEvent;
while (_mainWindow.pollEvent(currentEvent))
{
switch (_gameState)
{
case Game::Playing:
{
_mainWindow.clear(sf::Color(255, 0, 0));
_mainWindow.display();
if (currentEvent.type == sf::Event::Closed)
{
_gameState = Game::Exiting;
}
break;
}
}
}
}
Game::GameState Game::_gameState = Uninitialized;
sf::RenderWindow Game::_mainWindow;
Does anyone have any idea of what might be causing this or how to fix it? I am completely new to SFML, so I'm at a loss for what to do.
Thanks, Zuve

Namespaces acting weird

Ok guys... I'm coding my first game using SFML and I have found the awesomely hateful problem... I'll explain.
main.cpp
#include "include/SFML/include/SFML.hpp"
#include "include/menu.h"
#include <iostream>
#include <fstream>
#include "include/checkfileexistence.h"
#include "include/fonts.h"
#define FPS 20
bool loadFonts();
bool loadMenu();
int main ()
{
if (!loadFonts()) {std::cout << "Could not load fonts!"; return EXIT_FAILURE;}
sf::RenderWindow window (sf::VideoMode(0,0),"Evility", sf::Style::Fullscreen);
window.setFramerateLimit(FPS);
sf::Event event;
window.setKeyRepeatEnabled(false);
while (window.isOpen())
{
window.clear();
if (window.pollEvent(event))
{
switch (event.type)
{
case sf::Event::Closed: {window.close(); break;}
case sf::Event::KeyPressed:
{
switch (event.key.code)
{
case sf::Keyboard::Escape: {window.close(); break;}
case sf::Keyboard::LAlt && sf::Keyboard::F4: {window.close(); break;}
}
}
}
}
if (menu::isBeingUsed)
{
if (!menu::isRunning)
{
if (!loadMenu()) {std::cout << "Could not load menu files!"; return EXIT_FAILURE;}
menu::music.setLoop(true);
menu::music.play();
menu::isRunning = true;
window.setVisible(true);
}
if ((sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) || (sf::Keyboard::isKeyPressed(sf::Keyboard::W)))
{
menu::selectedOption--;
if (menu::selectedOption < 0)
{
menu::selectedOption = 3;
}
}
if ((sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) || (sf::Keyboard::isKeyPressed(sf::Keyboard::S)))
{
menu::selectedOption++;
if (menu::selectedOption > 3)
{
menu::selectedOption = 0;
}
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Return))
{
switch (menu::selectedOption)
{
case 3:
{
window.close();
break;
}
}
}
switch (menu::selectedOption)
{
case 0:
menu::optionSelector.setPosition(sf::Vector2f(60,105));
break;
case 1:
menu::optionSelector.setPosition(sf::Vector2f(60,155));
break;
case 2:
menu::optionSelector.setPosition(sf::Vector2f(60,205));
break;
case 3:
menu::optionSelector.setPosition(sf::Vector2f(60,255));
break;
}
window.draw(menu::spriteBackground);
window.draw(menu::textStartGame);
window.draw(menu::textContinueGame);
window.draw(menu::textOptions);
window.draw(menu::textQuitGame);
window.draw(menu::optionSelector);
}
window.display();
}
}
bool loadFonts()
{
if (!font::ArcadePix.loadFromFile("resources/Fonts/ArcadePix.TTF"))
{
return false;
}
return true;
}
bool loadMenu ()
{
menu::music.openFromFile("resources/Music/Unity.wav");
menu::music.setLoop (true);
menu::textureBackground.loadFromFile("resources/wallpaper.png");
menu::spriteBackground.setTexture(menu::textureBackground, false);
menu::spriteBackground.setPosition(0,0);
menu::spriteBackground.setScale(window.getSize().width / menu::spriteBackground.getLocalBounds().width, window.getSize().height / menu::spriteBackground.getLocalBounds().height);
menu::optionSelector.setSize (sf::Vector2f(25,25));
menu::optionSelector.setFillColor(sf::Color::Yellow);
menu::optionSelector.setPosition(60,105);
menu::textStartGame.setFont(font::ArcadePix);
menu::textStartGame.setColor(sf::Color::Red);
menu::textStartGame.setPosition(sf::Vector2f(100,100));
menu::textStartGame.setString("Start Game");
menu::textContinueGame.setFont (font::ArcadePix);
if (fileExists("resources/Saves/saves.txt"))
{
menu::textContinueGame.setColor(sf::Color::Red);
}
else
{
menu::textContinueGame.setColor(sf::Color(211,211,211,127));
}
menu::textContinueGame.setPosition(100,150);
menu::textContinueGame.setString("Continue Game");
menu::textOptions.setFont(font::ArcadePix);
menu::textOptions.setColor(sf::Color::Red);
menu::textOptions.setPosition(100,200);
menu::textOptions.setString("Options");
menu::textQuitGame.setFont(font::ArcadePix);
menu::textQuitGame.setColor(sf::Color::Red);
menu::textQuitGame.setPosition(100,250);
menu::textQuitGame.setString("Quit Game");
return true;
}
menu.h
#ifndef MENU_H_
#define MENU_H_
#include "SFML/include/SFML.hpp"
namespace menu{
bool isBeingUsed = true;
bool isRunning = false;
sf::RectangleShape rectBackground (sf::Vector2f (1080,720));
sf::Texture textureBackground;
sf::Sprite spriteBackground;
sf::Text textStartGame;
sf::Text textContinueGame;
sf::Text textQuitGame;
sf::Text textOptions;
sf::RectangleShape optionSelector (sf::Vector2f(0,0));
unsigned int selectedOption;
sf::Music music;
}
#endif
So in the awesomely long function call in main.cpp, which I expect to happen, is for the program to look for a class inside the RenderWindow object window, for a class...
But instead, the function call refers to a class function inside a namespace, it also thinks window is in that namespace, because the compilation returns window was not declared in this scope which I presume means window was not declared in menu namespace.
How should I tell my program to look outside the menu namespace?
Peace.
Edit 1: Added all main.cpp code, didn't want to as it is the future code for a game but it is so simple I don't feel like nobody would steal it.
window is a variable that's local to main. Pass it to loadMenu if you need it there.