Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Why my sf::Text isn't updating every time?  (Read 4601 times)

0 Members and 1 Guest are viewing this topic.

SqrtPapere

  • Newbie
  • *
  • Posts: 3
    • View Profile
Why my sf::Text isn't updating every time?
« on: May 13, 2016, 12:13:06 pm »
Hello,
I'm developing a simple game that should works like a simpler pokemòn and obviously I'm using SFML.
The problem is that I've got the classic label of text that shows hp of the user and  enemy but the updating of it (graphically talking) isn't updating every time, I mean the logic of the game works properly cause if i'm attacking with 60 and the enemy has got 240 hp it took 4 hit to be killed but the sf::Text I'm trying to draw does not update at every "run" of the program.
Here it is the code of the BattleLoop using it:(player and enemy are the pointer to the user and the enemy)
void BattleLoop(std::vector<Character*> *chrt, int ID){
   
    Character *player = chrt->at(0);
    Character *enemy =  chrt->at(ID);
   
    sf::Texture playerTexture, enemyTexture, battleTexture;
    sf::Sprite playerSprite, enemySprite, battleSprite;
     
    sf::Font font;
    if (!font.loadFromFile("Lobster_1.3.otf"))
    {
        std::cout<< "failed to open font"<<std::endl;
    }
   
    sf::Text playerlife, enemylife;  //<---this is the no updating thing!!
 
    playerlife.setColor(sf::Color::Black);
    enemylife.setColor(sf::Color::Black);

    playerlife.setFont(font);
    enemylife.setFont(font);
   
    playerlife.setCharacterSize(20);
    enemylife.setCharacterSize(20);
   
    playerlife.setPosition(402, 200);
    enemylife.setPosition(22, 10);
   
    std::string playerpng = player->getType() + "battle.png";
    if(!playerTexture.loadFromFile(playerpng))
        std::cout<<"Error, could not load "<<playerpng<<std::endl;
    playerSprite.setTexture(playerTexture);
    playerSprite.setTextureRect(sf::IntRect(0,0,110,128));
    playerSprite.setPosition(32,128);
     
    std::string enemypng = std::to_string(enemy->getId()) + ".png";
    if(!enemyTexture.loadFromFile(enemypng))
        std::cout<<"Error, could not load  "<<enemypng<<std::endl;
    enemySprite.setTexture(enemyTexture);
    enemySprite.setPosition(32*11,50);

    bool enemyatk = false;
   
    sf::RenderWindow window2(sf::VideoMode(32*16, 32*8), "Battle!!");
   
    std::ostringstream playerlifeConv;   //I use this to convert the int (life) to string and then in Text
    playerlifeConv << "hp: " << player->getLife();
    playerlife.setString(playerlifeConv.str());
   
    std::ostringstream enemylifeConv;
    enemylifeConv << "hp: " << enemy->getLife();
    enemylife.setString(enemylifeConv.str());
     
    sf::Event events;
   
    while (window2.isOpen()){
       
        updateLife(playerlifeConv, enemylifeConv, player, enemy, &playerlife, &enemylife);
//putting a lot of those method updateLife to prove that's not the problem

        window2.clear();
        window2.draw(playerSprite);
        window2.draw(enemySprite);
        window2.draw(playerlife);
        updateLife(playerlifeConv, enemylifeConv, player, enemy, &playerlife, &enemylife);
        window2.draw(enemylife);
        window2.display();
        updateLife(playerlifeConv, enemylifeConv, player, enemy, &playerlife, &enemylife);

        while (window2.pollEvent(events)){
            updateLife(playerlifeConv, enemylifeConv, player, enemy, &playerlife, &enemylife);
           
            if(events.type == sf::Event::Closed){
                window2.close();
            }
            else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)){
                updateLife(playerlifeConv, enemylifeConv, player, enemy, &playerlife, &enemylife);
                window2.close();
            }
            if (events.type == sf::Event::KeyReleased) {//this is how I attack the enemy
                updateLife(playerlifeConv, enemylifeConv, player, enemy, &playerlife, &enemylife);
                if (events.key.code==sf::Keyboard::Space) {
                    updateLife(playerlifeConv, enemylifeConv, player, enemy, &playerlife, &enemylife);
                    enemy->reduceLife(player->getAttack());  //this is working!!
                    updateLife(playerlifeConv, enemylifeConv, player, enemy, &playerlife, &enemylife);
                    enemyatk=true;

                    if (enemy->getLife()<=0) {
                        updateLife(playerlifeConv, enemylifeConv, player, enemy, &playerlife, &enemylife);

                        chrt->erase(chrt->begin()+ID);
                        enemyatk=false;
                        window2.close();
                    }
                    updateLife(playerlifeConv, enemylifeConv, player, enemy, &playerlife, &enemylife);
             
                    if (enemyatk) {
                        player->reduceLife(enemy->getAttack());
                        enemyatk = false;
                        updateLife(playerlifeConv, enemylifeConv, player, enemy, &playerlife, &enemylife);

                    }
                    if (player->getLife()<=0) {
                        chrt->erase(chrt->begin());
                        window2.close();
                    }
                    updateLife(playerlifeConv, enemylifeConv, player, enemy, &playerlife, &enemylife);              
                }
            }
                 
            updateLife(playerlifeConv, enemylifeConv, player, enemy, &playerlife, &enemylife);

            window2.clear();
            window2.draw(playerSprite);
            updateLife(playerlifeConv, enemylifeConv, player, enemy, &playerlife, &enemylife);
            window2.draw(enemySprite);
            window2.draw(playerlife);
            updateLife(playerlifeConv, enemylifeConv, player, enemy, &playerlife, &enemylife);
            window2.draw(enemylife);
            window2.display();
   
        }//eventloop

    }//gameloop
}

bool collision (sf::Vector2f vp1, sf::Vector2f vp2){  //metodo per collisioni con nemici, se ci troviamo in un raggio di 4px
    float a=fabs(vp1.x-vp2.x);  //fabs fa il valore assoluto
    float b=fabs(vp1.y-vp2.y);
    if (a<4 && b<4) {
        return true;
    }
    return false;
}

void updateLife(std::ostringstream &pl,std::ostringstream &el,  Character *p, Character *e, sf::Text *et, sf::Text *ee){
    pl.clear();
    pl.str("");
    pl << "hp: " << p->getLife();
    et->setString(pl.str());
    el.clear();
    el.str("");
    el << "hp: " << e->getLife();
    ee->setString(el.str());  
}
 

I hope to be clear.
Thankyou(sorry for bad english)

Mr_Blame

  • Full Member
  • ***
  • Posts: 192
    • View Profile
    • Email
Re: Why my sf::Text isn't updating every time?
« Reply #1 on: May 13, 2016, 12:32:34 pm »
Well, why do you update graphics before AND after event polling.

EDIT:

replace std::ostringstream with std::sstringstream 'o' means output, so std::ostringstream doesn't work as excepted. And also you must apply "" value to string stream and THAN "clear" it in order to remove the error state. E.G.:
std::sstream s;
//that how you must clear it
s.str("");
s.clear();
 
« Last Edit: May 13, 2016, 12:41:15 pm by Mr_Blame »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Why my sf::Text isn't updating every time?
« Reply #2 on: May 13, 2016, 12:55:54 pm »
Quote
replace std::ostringstream with std::sstringstream 'o' means output, so std::ostringstream doesn't work as excepted
Seriously?

The right (C++11) way of doing it, is std::to_string. If you still want to use std::ostringstream, then don't reuse instances.

void updateLife(Character *p, sf::Text *t){
    t->setString("hp: " + std::to_string(p->getLife()));
}

// OU...

void updateLife(Character *p, sf::Text *t){
    std::ostringstream oss;
    oss << "hp: " << p->getLife();
    t->setString(pl.str());
}
Laurent Gomila - SFML developer

SqrtPapere

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: Why my sf::Text isn't updating every time?
« Reply #3 on: May 13, 2016, 01:55:21 pm »
Quote
replace std::ostringstream with std::sstringstream 'o' means output, so std::ostringstream doesn't work as excepted
Seriously?

The right (C++11) way of doing it, is std::to_string. If you still want to use std::ostringstream, then don't reuse instances.

void updateLife(Character *p, sf::Text *t){
    t->setString("hp: " + std::to_string(p->getLife()));
}

// OU...

void updateLife(Character *p, sf::Text *t){
    std::ostringstream oss;
    oss << "hp: " << p->getLife();
    t->setString(pl.str());
}

Thankyou, but the problem still remain.. :-[
I'm desperate!

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Why my sf::Text isn't updating every time?
« Reply #4 on: May 13, 2016, 02:11:10 pm »
Then show a complete and minimal code that reproduces the problem. Your original code is so cluttered with these duplicated calls everywhere, that it's hard to know what really happens.
Laurent Gomila - SFML developer

SqrtPapere

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: Why my sf::Text isn't updating every time?
« Reply #5 on: May 13, 2016, 08:55:20 pm »
 
Then show a complete and minimal code that reproduces the problem. Your original code is so cluttered with these duplicated calls everywhere, that it's hard to know what really happens.
Then Laurent here it is a complete code, the problem is that it works in this very simple way. Hope you can understand it now.
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include <unistd.h>
#include <iostream>
#include <stdio.h>

void updateLife(int *p, int *e, sf::Text *et, sf::Text *ee){
    et->setString("hp: " + std::to_string(*p));
    ee->setString("hp: " + std::to_string(*e));
}
void reduceLife( int attack, int &life){
    life-=attack;
}

int main(int, char const**)
{
    int playerhp = 60;
    int playeratk = 60;

    int enemyhp = 240;
    int enemyatk = 10;

        sf::Font font;
        if (!font.loadFromFile("Lobster_1.3.otf"))
        {
            std::cout<< "failed to open font"<<std::endl;
        }
       
        sf::Text playerlife, enemylife;
       
        playerlife.setColor(sf::Color::White);
        enemylife.setColor(sf::Color::White);
        playerlife.setFont(font);
        enemylife.setFont(font);
        playerlife.setCharacterSize(20);
        enemylife.setCharacterSize(20);
        playerlife.setPosition(402, 200);
        enemylife.setPosition(22, 10);
       
        bool attackable = false;
       
        sf::RenderWindow window2(sf::VideoMode(32*16, 32*8), "Battle!!");
       
        sf::Event events;
       
        while (window2.isOpen()){
             
            updateLife(&playerhp, &enemyhp, &playerlife, &enemylife);
                   
            window2.clear();
            window2.draw(playerlife);
            window2.draw(enemylife);
            window2.display();
           
            while (window2.pollEvent(events)){
               
               
                if(events.type == sf::Event::Closed){
                    window2.close();
                }
                else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)){
                    window2.close();
                }
                if (events.type == sf::Event::KeyReleased) {
                   
                    if (events.key.code==sf::Keyboard::Space) {
                       
                        reduceLife(playeratk, enemyhp);
                        updateLife(&playerhp, &enemyhp, &playerlife, &enemylife);

                        enemyatk=true;
                       
                        if (enemyhp<=0) {
                           
                            enemyatk=false;
                            window2.close();
                        }
                                             
                        if (enemyatk) {
                            reduceLife(enemyatk, playerhp);
                            updateLife(&playerhp, &enemyhp, &playerlife, &enemylife);
                            enemyatk = false;
                           
                        }
                        if (playerhp <= 0) {
                            window2.close();
                        }                  
                    }
                }
               
                window2.clear();
                window2.draw(playerlife);
                window2.draw(enemylife);
                window2.display();
               
            }//eventloop
           
        }//gameloop
 


    return EXIT_SUCCESS;
}
 

So I want this logic, and sometimes it works in my original code, but not every time how is supposed to happen..

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Why my sf::Text isn't updating every time?
« Reply #6 on: May 13, 2016, 09:57:15 pm »
Quote
the problem is that it works in this very simple way
There's nothing much we can do if this code works fine. But now you have something to compare your original code with, and usually with this you can spot the difference (= the error) quickly.
Laurent Gomila - SFML developer

SonyUSA

  • Newbie
  • *
  • Posts: 14
    • View Profile
    • Email
Re: Why my sf::Text isn't updating every time?
« Reply #7 on: May 20, 2016, 07:17:40 am »
So I'm really new and totally useless, but I think you may be running into issues because you aren't using ELSE IF. I found in my game that even though I change variables, other nested IFs will "bleed" data because everything is happening sort of... all at once sequentially down your IF tree. Try adding ELSE to all your nested IF's after the first one and see if that fixes it, I -suspect- your enemyatk is bleeding and causing issues but... I dunno >_>
« Last Edit: May 20, 2016, 07:19:29 am by SonyUSA »