SFML not loading image from file - c++

So I am learning C++ through game development and I recently ran across an error when I was trying to load an image called image1.png.
I tried using directories and that didn't work and then i moved the image to the same directory as the .cpp file and it still doesn't load the texture.
// defining libraries
#include <SFML/Graphics.hpp>
#include<iostream>
//global variables, functions, and classes
int main () {
//SETUPS
sf::RenderWindow window(sf::VideoMode(800, 600),"SFML Game");
window.setFramerateLimit(60);
window.setKeyRepeatEnabled(false);
bool play = true;
sf::Event event;
bool aPressed = false;
bool aReleased = false;
bool leftClick = false;
bool space = false;
bool returnReleased = false;
bool rightClick = false;
int numberOfClicks = 0;
int mouseX, mouseY;
int rectX = 0;
int rectY = 0;
sf::Texture image1;
if (image1.loadFromFile("image1.png") == -1) {
return 1;
}
sf::RectangleShape rect;
rect.setSize(sf::Vector2f(100, 50));
rect.setPosition(0, 0);
rect.setTexture(&image1);
sf::CircleShape circle;
circle.setRadius(50);
circle.setPosition(50,50);
circle.setFillColor(sf::Color::Magenta);
//Game Loop
while (play == true) {
//EVENTS
while (window.pollEvent(event)) {
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::A) {
aPressed = true;
}
if (event.type == sf::Event::KeyReleased && event.key.code == sf::Keyboard::A) {
aReleased = true;
}
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Space) {
space = true;
}
if (event.type == sf::Event::KeyReleased && event.key.code == sf::Keyboard::Space) {
space = false;
}
if (event.type == sf::Event::Closed) {
play = false;
}
if (event.type == sf::Event::KeyReleased && event.key.code == sf::Keyboard::Escape) {
play = false;
}
if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) {
leftClick = true;
}
if (event.type == sf::Event::KeyReleased && event.key.code == sf::Keyboard::Return) {
returnReleased = true;
}
if (event.type == sf::Event::MouseButtonPressed && event.key.code == sf::Mouse::Right){
rightClick = true;
}
}
//LOGIC
if (aPressed == true) {
std::cout << "Key has been pressed\n";
aPressed = false;
}
if (aReleased == true) {
std::cout << "Key has been released\n";
aReleased = false;
}
if (leftClick == true) {
numberOfClicks++;
std::cout << "Number of clicks: " << numberOfClicks << "\n";
leftClick = false;
}
if (event.type == sf::Event::MouseMoved) {
mouseX = event.mouseMove.x;
mouseY = event.mouseMove.y;
//std::cout << "X:" << mouseX << "\n";
//std::cout << "Y:" << mouseY << "\n";
}
if (returnReleased == true) {
std::cout << "Return Released \n";
returnReleased = false;
}
if (rightClick == true) {
numberOfClicks--;
std::cout << "Number of clicks: " << numberOfClicks << "\n";
rightClick = false;
}
rectX += 2;
rectY += 1;
rect.setPosition(rectX, rectY);
rect.setTexture(&image1);
//RENDERING
window.clear();
window.draw(rect);
window.draw(circle);
window.display();
}
//Clean Up
window.close();
return 0;
}

From SFML's page about image loading: http://www.sfml-dev.org/tutorials/2.0/graphics-sprite.php
The loadFromFile function sometimes fails with no obvious reason. First, check the error message printed by SFML in the standard output (check the console). If the message is „unable to open file”, make sure that the working directory (which is the directory any file path will be interpreted relatively to) is what you think it is: when you run the application from the explorer, the working directory is the executable folder, but when you launch your program from your IDE (Visual Studio, Code::Blocks, ...) the working directory is sometimes set to the project directory instead. This can generally be changed easily in the project settings.
Please check the error messages and post the error message.

Related

Game does not launch from Menu

I am new to Game Development. I managed to create a simple game (like Space Invaders) as well as a simple start Menu using C++ and SFML. However, upon pressing "Enter" on the main menu, the game is not being launched. How do I link it properly? I appreciate your help. This is not homework.
main.cpp codes
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include "GameObjectManager.h"
#include "Menu.h"
using namespace std;
int main()
{
sf::Texture galaxyBackgroundTexture;
sf::Sprite galaxyBackground;
if (!galaxyBackgroundTexture.loadFromFile("Textures/galaxybackground.png")) {
cout << "Failed to load Image" << endl;
}
galaxyBackground.setTexture(galaxyBackgroundTexture);
sf::RenderWindow window(sf::VideoMode(1200, 800), "Space Invader Test");
Menu menu(window.getSize().x, window.getSize().y);
window.setFramerateLimit(144);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Key::Return)
{
menu.GetPressedItem();
cout << "Play button has been pressed." << endl;
GameObjectManager* gameObjectManagerManager = new GameObjectManager(&window);
gameObjectManager->update();
gameObjectManager->render(window);
}
else if (event.type == sf::Event::Closed)
{
window.close();
}
else if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape)
{
window.close();
}
}
window.clear();
window.draw(galaxyBackground);
menu.draw(window);
window.display();
}
return 0;
}
Menu.h
#pragma once
#include "SFML/Graphics.hpp"
#define MAX_NUMBER_OF_ITEMS 2
class Menu
{
public:
Menu(float width, float height);
~Menu();
void draw(sf::RenderWindow& window);
int GetPressedItem() { return selectedItemIndex; }
private:
int selectedItemIndex;
sf::Font font;
sf::Text menu[MAX_NUMBER_OF_ITEMS];
};
Menu.cpp
#include "Menu.h"
Menu::Menu(float width, float height)
{
if (!font.loadFromFile("arial.ttf"))
{
cout << "can't load font" << endl;
}
// initialise Menu items
menu[0].setFont(font);
menu[0].setColor(sf::Color::Red);
menu[0].setString("Play");
menu[0].setPosition(sf::Vector2f(width / 2, height / (MAX_NUMBER_OF_ITEMS + 1) * 1));
// EXIT
menu[1].setFont(font);
menu[1].setColor(sf::Color::White);
menu[1].setString("Exit");
menu[1].setPosition(sf::Vector2f(width / 2, height / (MAX_NUMBER_OF_ITEMS + 1) * 2));
}
selectedItemIndex = 0;
Menu::~Menu()
{
}
void Menu::draw(sf::RenderWindow &window)
{
for (int i = 0; i < MAX_NUMBER_OF_ITEMS; i++)
{
window.draw(menu[i]);
}
}
The console window would print:
"Play button has been pressed"
But it does not proceed to the game. Nothing else happens.
"window redefinition" error occurs because both your RenderWindow objects have the same identifiers (i.e. window). You might want to change the name of the second window or better yet use the same window.
The second error, sf::Text::setColor() is deprecated means that it is no longer "useable" or "is not suggested to be used". SFML has two new better functions for this:
sf::Text::setFillColor() : to set the fill of your text.
sf::Text::setOutlineColor() : to give your text an outline (you also need to do change the thickness using setOutlineThickness()).
Moreover, I'd suggest you to use a State Machine for different scenes instead of two separate windows. It really isn't that difficult and will help you learn a few more things. You're somewhat already achieving this with your gameObjectManager. You just need to abstract it and implement it for your menu class as well. And since you have only two scenes you can simply use an integer or boolean to switch between these two.
EDIT: an idea of what you need to do to your main.cpp file
int main()
{
sf::RenderWindow window(sf::VideoMode(1200, 800), "Space Invader Test");
GameObjectManager* gameObjectManagerManager = nullptr;
bool inGame = false; //true = game has started, false = menu screen
while (window.isOpen())//this is the main loop
{
sf::Event event;
while (window.pollEvent(event)) //this is the event loop
{
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Key::Return)
{
if(!inGame)
{
if(menu.GetPressedItem() == PlayButton) //assuming your function returns which button in the menu has been pressed
{
cout << "Play button has been pressed." << endl;
inGame = true;
gameObjectManagerManager = new GameObjectManager(&window);
}
else
{
window.close(); //since the other button is exit
}
}
}
if (event.type == sf::Event::Closed) window.close();
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) window.close();
}
//this is the place where you call your updates
if(inGame) gameObjectManagerManager->update();
window.clear();
window.draw(galaxyBackground);
if(!inGame)menu.draw(window);
if(inGame) gameObjectManagerManager->render();
window.display();
}
return 0;
}

Box2d Player constantly jumping when using enum

I am trying to create a player that jumps and moves left and right.
At the moment, the player jumps infinitely on the spot, or moves infinitely left or right when the corresponding keys are pressed.
What do I need to add to this code to make the character stop jumping or moving once the key is released?
Here is the code so far:
void Character::update()
{
b2Vec2 pos = m_body->GetPosition();
setPosition(pos.x, pos.y);
float angle = m_body->GetAngle()* RAD2DEG;
setRotation(angle);
if (m_movingStates[LEFT])
{
m_body->ApplyLinearImpulseToCenter(b2Vec2(-0.03, 0.0f), true);
}
if (m_movingStates[RIGHT])
{
m_body->ApplyLinearImpulseToCenter(b2Vec2(0.03, 0.0f), true);
}
if (m_movingStates[JUMP] && m_sit)
{
m_body->ApplyLinearImpulseToCenter(b2Vec2(0.f, -0.1f), true);
}
}
void Character::onKeyPress(sf::Event event)
{
if (event.key.code == sf::Keyboard::Left)m_movingStates[LEFT] = true;
if (event.key.code == sf::Keyboard::Right)m_movingStates[RIGHT] = true;
if (event.key.code == sf::Keyboard::Space)m_movingStates[JUMP] = true;
}
void Character::onKeyRelease(sf::Event event)
{
if (event.type == sf::Event::KeyReleased && event.key.code == sf::Keyboard::Left) m_movingStates[LEFT] = false;
if (event.type == sf::Event::KeyReleased && event.key.code == sf::Keyboard::Right) m_movingStates[RIGHT] = false;
if (event.type == sf::Event::KeyReleased && event.key.code == sf::Keyboard::Space) m_movingStates[JUMP] = false;
}

Is there an easier way have keyboard input return a char (SFML)?

I want to use the keyboard input as a parameter for a function. I'm trying to get a keyboard input that returns a char: the key pressed.
Is there a better way to do it than how I'm doing it now?
char getKey() {
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
{
return 'A';
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
{
return 'A';
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::B))
{
return 'B';
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::C))
{
return 'C';
}
//...
return '\0';
}
I know you can get use TextEntered, but I don't want to get other ASCII keys(å, ∫, ç, ...)
Is there an easier way to do this without going through every letter?
You can just handle events in your code
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
window.close();
break;
}
else if(event.type == sf::Event::KeyPressed)
{
const sf::Keyboard::Key keycode = event.key.code;
if (keycode == sf::Keyboard::A)
std::cout << "A is pressed";
}
}
Enum fields for letters are arranged in the same way as in the ASCII. By using this property you can get a char by adding abd subtracting:
#include <SFML/Graphics.hpp>
#include <iostream>
#include <string>
int main() {
sf::RenderWindow window(sf::VideoMode(1200, 650), "");
std::string enteredChars;
enteredChars.reserve(1000);
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed || event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) {
window.close();
} else if (event.type == sf::Event::KeyPressed) {
const sf::Keyboard::Key keycode = event.key.code;
if (keycode >= sf::Keyboard::A && keycode <= sf::Keyboard::Z) {
char chr = static_cast<char>(keycode - sf::Keyboard::A + 'a');
enteredChars.push_back(chr);
}
}
}
window.clear();
window.display();
}
std::cout << enteredChars << "\n";
}

SFML Open multiple windows: Won't let me open more than two windows at a time

Ok so I have a program that has a void that opens a new window then draws a image on that window every time I call the void. It will let me open a second window but won't let me open it again till I close the second window. I think I am thinking about it wrong if I am can someone give me a better way to do it. Here's my code I don't think its 100% necessary but idk.
My goal is to get it to allow me to open multiple windows doing their own thing on the screen. I am trying to open a new window by calling the DrawKey void.
It is opening a window when I press a key the first time but it is limiting me to the main window and one key window. I want to be able to have as many key windows open as I feel the need for.
class MakeKey
{
public:
typedef struct KeySprite {
sf::Image Img;
sf::Texture Tex;
sf::Sprite Sprite;
}Key;
static bool setTransparency(HWND hwnd, unsigned char alpha) { ... }
static bool setShape(HWND hwnd, const sf::Image& image) { ... }
static sf::Vector2i RandSpawn(sf::Image image) { ... }
static void MakeTopWindow(HWND hwnd) { ... }
static void DrawKey(string key)
{
const unsigned char opacity = 1000;
Key Key;
Key.Img.loadFromFile("Assets/Images/A.png");
sf::RenderWindow window(sf::VideoMode(Key.Img.getSize().x, Key.Img.getSize().y, 32), "Key", sf::Style::None);
setTransparency(window.getSystemHandle(), opacity);
if (key == "A")
Key.Img.loadFromFile("Assets/Images/A.png");
else if (key == "D")
Key.Img.loadFromFile("Assets/Images/D.png");
else if (key == "E")
Key.Img.loadFromFile("Assets/Images/E.png");
else if (key == "Q")
Key.Img.loadFromFile("Assets/Images/Q.png");
else if (key == "S")
Key.Img.loadFromFile("Assets/Images/S.png");
else if (key == "W")
Key.Img.loadFromFile("Assets/Images/W.png");
else if (key == "X")
Key.Img.loadFromFile("Assets/Images/X.png");
else if (key == "Z")
Key.Img.loadFromFile("Assets/Images/Z.png");
else if (key == "Esc")
Key.Img.loadFromFile("Assets/Images/esc.png");
setShape(window.getSystemHandle(), Key.Img);
Key.Tex.loadFromImage(Key.Img);
Key.Sprite.setTexture(Key.Tex);
window.setPosition(MakeKey::RandSpawn(Key.Img));
while (window.isOpen())
{
MakeTopWindow(window.getSystemHandle());
window.clear(sf::Color::Transparent);
window.draw(Key.Sprite);
window.display();
}
}
};
Main
int main()
{
sf::RenderWindow window(sf::VideoMode(100, 100, 32), "Main Window", sf::Style::None);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
MakeKey::MakeTopWindow(window.getSystemHandle());
if (event.type == sf::Event::KeyPressed) {
if (event.key.code == sf::Keyboard::A)
MakeKey::DrawKey("A");
else if (event.key.code == sf::Keyboard::D)
MakeKey::DrawKey("D");
else if (event.key.code == sf::Keyboard::E)
MakeKey::DrawKey("E");
else if (event.key.code == sf::Keyboard::Q)
MakeKey::DrawKey("Q");
else if (event.key.code == sf::Keyboard::S)
MakeKey::DrawKey("S");
else if (event.key.code == sf::Keyboard::W)
MakeKey::DrawKey("W");
else if (event.key.code == sf::Keyboard::X)
MakeKey::DrawKey("X");
else if (event.key.code == sf::Keyboard::Z)
MakeKey::DrawKey("Z");
else if (event.key.code == sf::Keyboard::Escape)
MakeKey::DrawKey("Esc");
}
if (event.type == sf::Event::Closed)
window.close();
}
MakeKey::MakeTopWindow(window.getSystemHandle());
window.clear(sf::Color::Transparent);
window.display();
}
return EXIT_SUCCESS;
}
There is no error just no doing quite what I want and I want help figuring out how to make it do what I want.

SFML/C++ Sprite Disappearing After Certain Point

int main() {
sf::RenderWindow window;
sf::Vector2i centerWindow((sf::VideoMode::getDesktopMode().width / 2) - 445, (sf::VideoMode::getDesktopMode().height / 2) - 480);
window.create(sf::VideoMode(900, 900), "SFML Game", sf::Style::Titlebar | sf::Style::Close);
window.setPosition(centerWindow);
window.setKeyRepeatEnabled(true);
sf::Texture wallTxture;
sf::Sprite wall;
if (!wallTxture.loadFromFile("wall.png")) {
std::cerr << "Error\n";
}
wall.setTexture(wallTxture);
//Gravity Vars:
int groundHeight = 750;
bool isJumping = false;
//Movement Vars:
bool goingRight = false;
bool goingLeft = false;
//Set View Mode:
sf::View followPlayer;
followPlayer.reset(sf::FloatRect(0, 0, window.getSize().x, window.getSize().y));
Player player("newPlayer.png");
player.setPos({ 800, 800 });
sf::Vector2f position(window.getSize().x / 2, window.getSize().y / 2);
//Main Loop:
while (window.isOpen()) {
const float moveSpeed = 0.1;
sf::Event Event;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
isJumping = true;
//Handle Movement While Jumping:
if (goingLeft == true) {
player.move({ -moveSpeed, -moveSpeed });
}
else if (goingRight == true) {
player.move({ moveSpeed, -moveSpeed });
}
else {
player.move({ 0, -moveSpeed });
}
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {
player.move({ 0, moveSpeed });
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) {
player.move({ -moveSpeed, 0 });
goingLeft = true;
player.flipX('l');
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) {
player.move({ moveSpeed, 0 });
goingRight = true;
player.flipX('r');
}
//Event Loop:
while (window.pollEvent(Event)) {
switch (Event.type) {
case sf::Event::Closed:
window.close();
case sf::Event::KeyReleased:
if (Event.key.code == sf::Keyboard::Up) {
isJumping = false;
}
else if (Event.key.code == sf::Keyboard::Left) {
goingLeft = false;
}
else if (Event.key.code == sf::Keyboard::Right) {
goingRight = false;
}
}
}
if (player.getX() > window.getSize().x) {
position.x = player.getX();
}
else {
position.x = window.getSize().x;
}
//If player is in air and not jumping:
if (player.getY() < groundHeight && isJumping == false) {
player.move({ 0, moveSpeed });
}
followPlayer.setCenter(position);
window.clear();
window.setView(followPlayer);
window.draw(wall);
player.drawTo(window);
window.display();
}
}
this is my code. What I am trying to do is create a 2D platformer sidescroller. Everything works, except when the sprite goes past a certain point it'll just disappear. This also happens when I jump and move through the air at the same time. I cannot figure out why this is happening, any help would be greatly appreciated :)
I fixed the problem by just getting rid of my flipX function, and instead just creating a new sprite facing a different direction, then changing it everytime the user is facing a new direction