How ove the player in SFML with c++ - c++

I'm doing a game in c++ with SFML. I've written a code for move the player, but when the game start the player, moves but when i leave the button the player return at its original position.Can you help me, please?
The main:
#include <iostream>
#include <SFML/Graphics.hpp>
int main() {
sf::RenderWindow window(sf::VideoMode(1320, 840), "Window");
window.setPosition(sf::Vector2i(150, 50));
window.setSize(sf::Vector2u(1320, 840));
window.getPosition();
window.setVerticalSyncEnabled(true);
window.setFramerateLimit(5);
window.getSize();
while (window.isOpen()) {
window.clear(sf::Color::White);
//texture
sf::Texture texture;
if (!texture.loadFromFile("/users/gaetanodonnarumma/desktop/background1.png", sf::IntRect(0, 0, 1320, 840))) {
return -1;
}
sf::Texture playerTexture;
if (!playerTexture.loadFromFile("/users/gaetanodonnarumma/desktop/quadrato-giallo.jpg", sf::IntRect(0, 0, 70, 70))) {
return -1;
}
//sprite
sf::Sprite backgroud;
backgroud.setTexture(texture);
sf::Sprite player;
double pX = 0;
double pY = 770;
player.setTexture(playerTexture);
player.setPosition(sf::Vector2f(pX, pY));
player.getPosition();
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
if (event.type == sf::Event::KeyPressed) {
if (event.key.code == sf::Keyboard::D) {
player.move(10.f, 0.f);
}
}
if (event.type == sf::Event::KeyPressed) {
if (event.key.code == sf::Keyboard::D) {
player.setPosition(pX + 10, 770);
}
}
if (event.type == sf::Event::KeyPressed) {
if (event.key.code == sf::Keyboard::A) {
player.move(-5.f, 0.f);
}
}
}
//draw
window.draw(backgroud);
window.draw(player);
window.display();
}
return 0;
}

All your initialization code is running on every frame. This means that on every frame, you are creating (and destroying) a new player, setting its texture, and setting its position to [0, 770].
Move all the initialization to before the main draw loop begins (before while (window.isOpen())).

Related

Why SFML rectangle textbox is not being formed and how to fix it?

I was making a program in SFML and C++, which like other program have a rectangle shaped box under which text is being filled but it does not even show a rectangle box. My code is:
int main()
{
sf::RenderWindow window({ 640 ,480}, "Window");
std::string input_text;
sf::Font font;
font.loadFromFile("arial.ttf");
sf::Text text("", font);
sf::Clock clock;
sf::RectangleShape rectangle(sf::Vector2f(120, 50));
rectangle.setSize(sf::Vector2f(100, 100));
rectangle.setFillColor(sf::Color(150, 50, 250));
rectangle.setOutlineThickness(10);
rectangle.setOutlineColor(sf::Color(250, 150, 100));
window.draw(rectangle);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
else if (event.type == sf::Event::TextEntered) {
if (std::isprint(event.text.unicode))
input_text += event.text.unicode;
}
else if (event.type == sf::Event::KeyPressed) {
if (event.key.code == sf::Keyboard::BackSpace) {
if (!input_text.empty())
input_text.pop_back();
}
if (event.key.code == sf::Keyboard::Return) {
std::string text1 = text.getString().toAnsiString();
std::cout << text1 << std::endl;
}
}
}
static sf::Time text_effect_time;
static bool show_cursor;
text_effect_time += clock.restart();
if (text_effect_time >= sf::seconds(0.5f))
{
show_cursor = !show_cursor;
text_effect_time = sf::Time::Zero;
}
text.setString(input_text + (show_cursor ? '_' : ' '));
window.clear();
window.draw(text);
window.display();
}
}
I learnt how to make rectangle shape from SFML webpage. I tried to put it under the while (window.isOpen()) and even outside but it doesn't appear to work. What is the issue and how can I fix it? And can text move to next line when it comes out of box?

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

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.

having trouble creating copies of objects using vector push_back code

I'm trying duplicate the RectangleShape rect1 every time I pressed the space button, but instead of doing that, it just seems to delete my rect1 object in the vector Vec as soon as I release the space key. I can't figure out why, anybody help me please?
here is my code:
int main() {
class shape {
public:
RectangleShape rect1;
};
shape getShape;
getShape.rect1.setSize(Vector2f(100, 100));
getShape.rect1.setFillColor(Color(0, 255, 50, 30));
RenderWindow window(sf::VideoMode(800, 600), "SFML Game");
window.setFramerateLimit(60);
window.setKeyRepeatEnabled(false);
bool play = true;
Event event;
while (play == true) {
while (window.pollEvent(event)) {
if (event.type == Event::Closed) {
play = false;
}
}
window.clear();
vector <shape> Vec;
if (Keyboard::isKeyPressed(Keyboard::Space)) {
Vec.push_back(getShape);
}
for (int i = 0; i < Vec.size(); ++i) {
window.draw(Vec[i].rect1);
}
window.display();
}
window.close();
return 0;
}
You need to place the vector outside the loop, otherwise you create a new empty one every time:
int main() {
// If you need to use this class in something other than main,
// you will need to move it outside of main.
class shape {
public:
RectangleShape rect1;
};
// But in this particular case you don't even need a class,
// why not just use RectangleShape?
shape getShape;
getShape.rect1.setSize(Vector2f(100, 100));
getShape.rect1.setFillColor(Color(0, 255, 50, 30));
RenderWindow window(sf::VideoMode(800, 600), "SFML Game");
window.setFramerateLimit(60);
window.setKeyRepeatEnabled(false);
bool play = true;
Event event;
std::vector<shape> Vec; // Put your vector here!
// play is already a bool, so you don't need == true
while (play) {
while (window.pollEvent(event)) {
if (event.type == Event::Closed) {
play = false;
}
}
window.clear();
if (Keyboard::isKeyPressed(Keyboard::Space)) {
Vec.push_back(getShape);
}
for (int i = 0; i < Vec.size(); ++i) {
window.draw(Vec[i].rect1);
}
window.display();
}
window.close();
return 0;
}

I have a Segfault, bad allocation?

This is my code :
t_game_elements *initializeEnvironnement(sf::RenderWindow *window)
{
t_game_elements *gameElements;
playerBat playerBatOne(0, 200);
playerBat playerBatTwo(790, 200);
gameElements = (t_game_elements *)malloc(1000);
gameElements->playerOne = playerBatOne;
gameElements->playerTwo = playerBatTwo;
*gameElements->playerOne.getShape();
window->draw(*playerBatOne.getShape()); // this line don't segfault
window->draw(*gameElements->playerOne.getShape()); // this line segfault
return (gameElements);
}
int main()
{
sf::RenderWindow window(sf::VideoMode(800, 500), "Pong", sf::Style::Default);
t_game_elements *elements;
elements = initializeEnvironnement(&window);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::KeyPressed)
{
if (event.key.code == sf::Keyboard::Escape)
{
window.close();
}
}
if (event.type == sf::Event::Closed)
window.close();
}
// window.clear();
// window.draw(*elements->playerOne.getShape());
// window.draw(*elements.playerTwo->getShape());
window.display();
}
return 0;
}
class playerBat
{
public:
playerBat(int x, int y);
sf::RectangleShape *getShape();
void setShape(sf::RectangleShape *Shape);
int test = 10;
private:
sf::RectangleShape shapeBat;
};
typedef struct s_game_elements
{
playerBat playerOne;
playerBat playerTwo;
} t_game_elements;
playerBat::playerBat(int x, int y)
{
sf::RectangleShape rectangle(sf::Vector2f(120, 50));
rectangle.setSize(sf::Vector2f(10, 100));
rectangle.setPosition(x, y);
rectangle.setFillColor(sf::Color::Green);
shapeBat = rectangle;
}
void playerBat::setShape(sf::RectangleShape *Shape)
{
shapeBat = *Shape;
}
sf::RectangleShape *playerBat::getShape()
{
return &shapeBat;
}
I allocate 1000 bytes just to be sure I allocate enough memory, I will change it when I will fix the segfautlt first.
I tried to display the variable 'test' of my class and it works fine.
Have an idea why I segfault ?
Thanks