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.
Related
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.
I have recently started to learn SFML and I wanted to make a Pong clone because it should be easy but I got into this problem while coding:
The bat movement is very laggy and when I press A or D it moves a bit then stops then moves again and continues.
#include <SFML/Graphics.hpp>
#include "bat.h"
int main()
{
int windowWidth=1024;
int windowHeight=728;
sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight), "SFML window");
bat Bat(windowWidth/2,windowHeight-20);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if(sf::Keyboard::isKeyPressed(sf::Keyboard::A))
Bat.batMoveLeft();
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::D))
Bat.batMoveRight();
else if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
Bat.batUpdate();
window.draw(Bat.getShape());
window.display();
}
return 0;
}
bat.h
#ifndef BAT_H
#define BAT_H
#include <SFML/Graphics.hpp>
class bat
{
private:
sf::Vector2f position;
float batSpeed = .3f;
sf::RectangleShape batShape;
public:
bat(float startX, float startY);
sf::FloatRect getPosition();
sf::RectangleShape getShape();
void batMoveLeft();
void batMoveRight();
void batUpdate();
};
#endif // BAT_H
bat.cpp
#include "bat.h"
using namespace sf;
bat::bat(float startX,float startY)
{
position.x=startX;
position.y=startY;
batShape.setSize(sf::Vector2f(50,5));
batShape.setPosition(position);
}
FloatRect bat::getPosition()
{
return batShape.getGlobalBounds();
}
RectangleShape bat::getShape()
{
return batShape;
}
void bat::batMoveLeft()
{
position.x -= batSpeed;
}
void bat::batMoveRight()
{
position.x += batSpeed;
}
void bat::batUpdate()
{
batShape.setPosition(position);
}
Your problem is you're input handling strategies (polling events vs. checking current state).
In addition, the way you've implemented this right now, means that if there are – just assumption – 5 events in the queue, you'll move the bat 5 times between drawing. If there is only one event (e.g. "key down"), you'll move the bat once.
What you'll typically want to do is check the events while iterating over them:
while (window.pollEvent(event)) {
switch (event.type) {
case sf::Event::Closed:
window.close();
break;
case sf::Event::KeyDown:
switch (event.key.code) {
case sf::Key::Left:
bat.moveLeft();
break;
// other cases here
}
break;
}
}
(Note this is from memory, so untested and might include typos.)
I was taking up the challenge of creating a program to use for graphing simple math equations using C++ and the SFML 2.3.2. graphics library, and I've got the graph paper texture rendering fine. However, the problem I've had is getting it to repeat itself as I scroll around.
I was using sf::View to get it to pan, and it works well, but as soon as it pans outside the pre-defined size of the sprite it's just a blank background.
I thought of trying to determine when I'm outside the bounds of the sprite, and then expanding the size of the sprite or moving it, but then drawings (such as a graph) won't persist if the sprite is changed/reset.
What I need to know is how to create a background of a texture, in this case graphing paper, that will tile/repeat in every direction, and allow drawings to be made on top of it that persist if they move off screen.
Code is below:
GraphPaper.h:
#pragma once
#include "stdafx.h"
class GraphPaper
{
public:
GraphPaper();
~GraphPaper();
bool isObjectLoaded();
sf::Sprite getSprite();
private:
void load(std::string filename);
bool isLoaded;
sf::Texture texture;
sf::Sprite sprite;
const std::string file = "images/Graph-Paper.png";
};
GraphPaper.cpp: This is where I create and load the needed sprite and texture.
I set the texture to repeat inside the "load(string filename)" method, but that only affects it within the bounds set by the sprite's rectangle.
#include "GraphPaper.h"
GraphPaper::GraphPaper() : isLoaded(false)
{
load(file);
assert(isObjectLoaded());
}
GraphPaper::~GraphPaper() {};
void GraphPaper::load(std::string filename)
{
if (texture.loadFromFile(filename) == false)
isLoaded = false;
else
{
texture.setRepeated(true);
sprite.setTexture(texture);
//Huge size to at least make it look like it's infinite,
//but a temporary solution.
sprite.setTextureRect(sf::IntRect(0,0,10000,10000));
isLoaded = true;
}
}
bool GraphPaper::isObjectLoaded()
{
return isLoaded;
}
sf::Sprite GraphPaper::getSprite()
{
return sprite;
}
MainWindow.h:
#pragma once
#include "GraphPaper.h"
#include "stdafx.h"
class MainWindow
{
public:
void close();
void start();
void moveCamera(sf::Event);
private:
bool leftMousePressed, rightMousePressed, isExiting;
int r, g, b, mouseX, mouseY;
GraphPaper paper;
const sf::Color white = sf::Color(255, 255, 255);
sf::RenderWindow mainWindow;
sf::View view;
};
MainWindow.cpp: This is what handles all the drawing, and, at the moment, all input processing. "start()" is simply called from the main method.
#include "MainWindow.h"
#include "GraphPaper.h"
#include "stdafx.h"
void MainWindow::start()
{
sf::RectangleShape rectangle = sf::RectangleShape(sf::Vector2f(120, 50));
rectangle.setFillColor(sf::Color(0,0,0));
mainWindow.create(sf::VideoMode(1024, 768, 32), "Test");
sf::View view(sf::FloatRect(0,0,1000,600));
mainWindow.setView(view);
leftMousePressed, rightMousePressed, isExiting = false;
sf::Event currentEvent;
mainWindow.clear(white);
mainWindow.draw(paper.getSprite());
mainWindow.display();
while (!isExiting)
{
while (mainWindow.pollEvent(currentEvent))
{
switch (currentEvent.type)
{
case sf::Event::MouseMoved:
{
if (rightMousePressed == true)
{
std::cout << "Mouse Panned\n";
}
if (leftMousePressed == true)
{
std::cout << "Mouse is Drawing\n";
}
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)
{
leftMousePressed = true;
}
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:
{
if (currentEvent.key.code == sf::Keyboard::Escape)
{
close();
}
//No right movement yet, was testing.
else if (currentEvent.key.code == sf::Keyboard::Left)
{
moveCamera(currentEvent);
}
break;
}
case sf::Event::Closed:
{
close();
break;
}
}
}
}
}
void MainWindow::moveCamera(sf::Event key)
{
std::cout << "Inside moveCamera\n";
//No right movement yet, was testing.
//Movement is also hardcoded for testing as well.
view.move(100, 0);
mainWindow.setView(view);
mainWindow.clear(white);
mainWindow.draw(paper.getSprite());
mainWindow.display();
std::cout << "Leaving moveCamera\n";
}
void draw()
{
//mainWindow.draw();
}
void MainWindow::close()
{
std::cout << "Closing...\n";
mainWindow.close();
isExiting = true;
}
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
Trying to create a game but i've run into my first hurdle. The game launches into a blank white screen instead of showing the Red screen and i cant proceed into the loading screen and the menu. I've checked that I'm using display for each of my screens but can't figure out where i'm going wrong. I also get no errors. Below is my code
game.cpp
#include "stdafx.h"
#include "Game.h"
#include "LoadScreen.h"
#include "MainMenu.h"
void Game::Start (void)
{
Game game;
if(_gameState != Unlaunched)
return;
game._mainWindow.create(sf::VideoMode(1024,768,32),"Code Matrix");
_gameState = Game::LogoScreen;
while (!Exists())
{
GameLoop();
}
game._mainWindow.close();
}
bool Game::Exists()
{
if(_gameState == Game::Exiting)
return true;
else
return false;
}
void Game::GameLoop()
{
Game game;
sf::Event currentEvent;
while (game._mainWindow.pollEvent(currentEvent))
{
switch (_gameState)
{
case Game::MenuWindow:
{
ShowMenu();
break;
}
case Game::LogoScreen:
{
ShowLogoScreen();
break;
}
case Game::Playing:
{
sf::Event currentEvent;
while (game._mainWindow.pollEvent(currentEvent))
{
game._mainWindow.clear(sf::Color(255,0,0));
game._mainWindow.display();
if(currentEvent.type == sf::Event::Closed)
_gameState = Game::Exiting;
if(currentEvent.type == sf::Event::KeyPressed)
{
if(currentEvent.key.code == sf::Keyboard::Escape) ShowMenu();
}
}
break;
}
}
}
}
void Game::ShowLogoScreen()
{
Game game;
LoadScreen loadScreen;
loadScreen.Show(game._mainWindow);
_gameState = Game::MenuWindow;
}
void Game::ShowMenu()
{
Game game;
MainMenu mainMenu;
MainMenu::MenuOption option = mainMenu.show(game._mainWindow);
switch(option)
{
case MainMenu::Exit:
_gameState = Game::Exiting;
break;
case MainMenu::Play:
_gameState = Game::Playing;
break;
}
}
Game::GameState Game::_gameState = Unlaunched;
LoadScreen.cpp
#include "stdafx.h"
#include "LoadScreen.h"
void LoadScreen::Show(sf::RenderWindow & renderWindow)
{
sf::Texture image;
if (image.loadFromFile("images/LoadingScreen.png") !=true)
{
return;
}
sf::Sprite sprite (image);
renderWindow.draw(sprite);
renderWindow.display();
sf::Event event;
while (true)
{
while (renderWindow.pollEvent(event))
{
if(event.type == sf::Event::EventType::KeyPressed
||event.type == sf::Event::EventType::MouseButtonPressed
|| event.type == sf::Event::EventType::Closed)
{
return;
}
}
}
}
MainMenu.cpp
#include "stdafx.h"
#include "MainMenu.h"
MainMenu::MenuOption MainMenu::show(sf::RenderWindow& window)
{
//Load menu image from file
sf::Texture image;
image.loadFromFile("images/MainMenu.png");
sf::Sprite sprite(image);
//Setup clickable regions
//Play menu item coordinates
MenuItem playButton;
playButton.rect.top= 319;
playButton.rect.height = 626;
playButton.rect.left = 189;
playButton.rect.width = 329;
playButton.action = Play;
//Options menu item coordinates
MenuItem optionButton;
optionButton.rect.left = 356;
optionButton.rect.height = 596;
optionButton.rect.top = 287;
optionButton.rect.width = 483;
optionButton.action = Options;
//Exit menu item coordinates
MenuItem exitButton;
exitButton.rect.left = 554;
exitButton.rect.height = 580;
exitButton.rect.top = 318;
exitButton.rect.width = 687;
exitButton.action = Exit;
_menuItems.push_back(playButton);
_menuItems.push_back(exitButton);
window.draw(sprite);
window.display();
return GetMenuAction(window);
}
MainMenu::MenuOption MainMenu::HandleClick(int x, int y)
{
std::list<MenuItem>::iterator it;
for ( it = _menuItems.begin(); it != _menuItems.end(); it++)
{
sf::Rect<int> menuItemRect = (*it).rect;
if( menuItemRect.height > y
&& menuItemRect.top < y
&& menuItemRect.left < x
&& menuItemRect.width > x)
{
return (*it).action;
}
}
return null;
}
MainMenu::MenuOption MainMenu::GetMenuAction(sf::RenderWindow& window)
{
sf::Event menuEvent;
while(true)
{
while(window.pollEvent(menuEvent))
{
if(menuEvent.type == sf::Event::MouseButtonPressed)
{
return HandleClick(menuEvent.mouseButton.x,menuEvent.mouseButton.y);
}
if(menuEvent.type == sf::Event::Closed)
{
return Exit;
}
}
}
}
void Game::ShowLogoScreen()
{
Game game; // <- this creates a NEW game. You want to use your already created game.
LoadScreen loadScreen;
loadScreen.Show(game._mainWindow);
_gameState = Game::MenuWindow;
}
You create a new game local to the logo screen. That one probably does not even own a window. You should reference your existing game variable.