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

Author Topic: how to remove a sf::Sprite and use a timer  (Read 6839 times)

0 Members and 1 Guest are viewing this topic.

Engineer

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
how to remove a sf::Sprite and use a timer
« on: August 18, 2013, 02:52:33 am »
Hello,
in my snake game I try to make pick ups which grant abilities to the player controlling the snake.
However I experience some problems : the pick up spawns all the time even if I programmed it to spawn every 3 seconds :/
Also I do not know how to remove a sprite from the screen. Thought about not drawing it but then if the player still go on it the snake would still grow :/
And last problem, my function isKeyPickedUp() always return true, even if I programmed it to return true ONLY if the key sprite coordinate match with the snake coordinate, and if it does, spawn the key elsewhere directly. So I end up with a snake that grows bigger and bigger... :(
I will also explain other problems of my snake after those have been resolved (those are minor other problems).
Thanks for your help, here is the code of my pick up for the snake
/*void Key::SpawnKey() // spawn a key every 5 seconds
{
    timeKey = clockKey.getElapsedTime();
    if(timeKey.asSeconds() > 5)
    {
        keysprite.setPosition(rand() % BORDERX - 70, rand() % BORDERY - 70);
        clockKey.restart();
        timeKey = clockKey.getElapsedTime();
    }
    timeKey = clockKey.getElapsedTime();
}
bool Key::isKeyPickedUp()
{
    if(keysprite.getGlobalBounds().contains(snake.getX(),snake.getY()));
    {
        return true;
    }
    return false;
}

sf::Sprite Key::getKeySprite()
{
    return keysprite;
}

void Key::growOrDespawn()
{
    if(isKeyPickedUp())
    {
        keysprite.setPosition(1000,1000);
        snake.grow();// if key has been picked up, move the key out of the map (I do not know how to destroy it :p
        SpawnKey();                       // and spawn a new key after 5 seconds.
    }
}*/

 

and the code in my main, in the window.isOpen() loop :

//key.growOrDespawn();
//window.draw(key.keysprite);
 
and the code in the main BEFORE the window.isOpen() loop :

    /*Key key;
    sf::Texture keyTexture;
    keyTexture.loadFromFile("key.png");
    key.keysprite.setTexture(keyTexture);*/

I think the problem comes that I put spawnKey() inside the loop, so it spawns keys all the time, but it's strange because I put a timer of 10 seconds before it actually set the position of the sprite :(
Some help?
Thanks a lot in advance. :)

Oh, and of course, I declared sf::Clock clockKey at debut of file, as well as timeKey. :)
« Last Edit: August 18, 2013, 03:01:20 am by Engineer »

Geheim

  • Full Member
  • ***
  • Posts: 201
    • View Profile
    • Email
Re: how to remove a sf::Sprite and use a timer
« Reply #1 on: August 18, 2013, 04:39:35 am »
the pick up spawns all the time even if I programmed it to spawn every 3 seconds :/
Use the clockKey instead of your timeKey ;)

Also I do not know how to remove a sprite from the screen. Thought about not drawing it but then if the player still go on it the snake would still grow :/
Do you store them in a container? (vector, list) Then you can delete the element if you don't need it anymore. If not, moving it outside the window should be ok too.
However if you just don't draw it, it is still there, thats why your snake grows ;)

And last problem, my function isKeyPickedUp() always return true, even if I programmed it to return true ONLY if the key sprite coordinate match with the snake coordinate
How big is your keySprite? If it fills the entire screen, it will probably contain your snake all the time. Maybe the values of snake.getX() and snake.getY() are not correct? How should we know...

You have to give us some more code / explanation in order to help you, otherwise we can just guess ;)
Failing to succeed does not mean failing to progress!

Engineer

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
Re: how to remove a sf::Sprite and use a timer
« Reply #2 on: August 18, 2013, 01:32:17 pm »
Okay thanks a lot for your advice already. Right now my snake grows when he eats one pickup. :)
But only the first one, I do not know why. :(
Here are my modified piece of code (only work once, after that the snake don't grow if he eats one pick up :


Alright, I had only given a piece of the code because my program is all made in one file. :/

No, there is only one key object because I only want them to respawn one at a time, so I didn't made a list/vector/deque for the pick up.

I will give you the functions of snake so you can understand:
Block::Block(int x, int y)
{
    ax = x;
    ay = y;
}

float Block::getX()
{
    return ax;
}

float Block::getY()
{
    return ay;
}

void Block::setX(float ZX)
{
    ax = ZX;
}

void Block::setY(float ZY)
{
    ay = ZY;
}

void Snake::Move(int NewDirection)
{
    shrink();
    if(NewDirection == Up)
    {

        if(adirection != Down)
        {
            asnake.push_front(Block(asnake.front().getX(), asnake.front().getY() - 15));
            adirection = Up;
        }
        else
        {
            asnake.push_front(Block(asnake.front().getX(), asnake.front().getY() + 15));
        }
    }
    else if(NewDirection == Right)
    {
        if(adirection != Left)
        {
            asnake.push_front(Block(asnake.front().getX() + 15, asnake.front().getY()));
            adirection = Right;
        }
        else
        {
            asnake.push_front(Block(asnake.front().getX() - 15, asnake.front().getY()));
        }
    }
    else if(NewDirection == Down)
    {
            if(adirection != Up)
            {
                asnake.push_front(Block(asnake.front().getX(), asnake.front().getY() + 15));
                adirection = Down;
            }
            else
            {
                asnake.push_front(Block(asnake.front().getX(), asnake.front().getY() - 15));
            }

    }
    else if(NewDirection == Left)
    {
        if(adirection != Right)
        {
            asnake.push_front(Block(asnake.front().getX() - 15, asnake.front().getY()));
            adirection = Left;
        }
        else
        {
            asnake.push_front(Block(asnake.front().getX() + 15, asnake.front().getY()));
        }
    }

}

void Snake::grow()
{
    asnake.push_back(Block(asnake.back().getX(), asnake.back().getY()));
}
void Snake::shrink()
{
    asnake.pop_back();
}

std::deque<Block> Snake::getBlocks()
{
    return asnake;
}
int Snake::getX()
{
    return asnake.front().getX();
}

int Snake::getY()
{
    return asnake.front().getY();
}

Snake::Snake()
{
    asnake.push_front(Block(BORDERX/2,BORDERY/2));
    asnake.push_front(Block(BORDERX/2+15,BORDERY/2+15));
    asnake.push_front(Block(BORDERX/2+15,BORDERY/2+15));
}

void Snake::setdirection()
{
    adirection = Left;
}

bool Snake::checkForCollisionBorder()
{
    for(unsigned int i = 0; i < getBlocks().size(); i++)
    {
        int cx = (getBlocks())[i].getX();
        int cy = (getBlocks())[i].getY();
        if((cx > BORDERX - 50) || (cx < 50) || (cy > BORDERY - 50) || (cy < 50))
        {
            return true;
        }
    }
    return false;
}

bool Snake::checkForBite()
{
    for(unsigned int s = 1; s < getBlocks().size(); s++)
    {
        if((getBlocks())[s].getX() == snake.getX() && (getBlocks())[s].getY() == snake.getY())
        {
            return true;
        }
    }
    return false;
}

void Key::SpawnKey() // spawn a key every 5 seconds
{
    if(clockKey.getElapsedTime().asSeconds() > 3)
    {
        spawn = true;
        keysprite.setPosition(350, 200);
        clockKey.restart();
    }
}
bool Key::isKeyPickedUp()
{
    if((keysprite.getPosition().x == snake.getX() && keysprite.getPosition().y == snake.getY()) && spawn)
    {
        spawn = false;
        return true;
    }
    return false;
}

sf::Sprite Key::getKeySprite()
{
    return keysprite;
}

void Key::growOrDespawn()
{
    if(isKeyPickedUp())
    {
        maximalSize++;
        snake.grow();// if key has been picked up, move the key out of the map (I do not know how to destroy it :p
        SpawnKey();                       // and spawn a new key after 5 seconds.
    }
}
 

My snake is made of a deque of Blocks (which contains 2 coordinates), and in my main function in the window.isOpen() loop, I put this to draw each segment of the snake based on the deque of Blocks:

                window.draw(backgroundsprite);
                for(unsigned int i = 1; i < (snake.getBlocks()).size(); i++)
                {
                    float xb = (snake.getBlocks())[i].getX();
                    float yb = (snake.getBlocks())[i].getY();

                    sf::RectangleShape block(sf::Vector2f(15,15));
                    block.setFillColor(sf::Color::Green);
                    block.setOutlineThickness(2);
                    block.setOutlineColor(sf::Color::Yellow);
                    block.setPosition(xb, yb);

                    window.draw(block);
                }

So you can understand now how my code works. :)
Right now the only issue is that it only work once (once the snake takes the pick up, he will grow once, but if he takes again the pick up (which is put elsewhere on the screen), he doesn't grow. :(
Thanks for your help.

Geheim

  • Full Member
  • ***
  • Posts: 201
    • View Profile
    • Email
Re: how to remove a sf::Sprite and use a timer
« Reply #3 on: August 18, 2013, 02:04:43 pm »
if((keysprite.getPosition().x == snake.getX() && keysprite.getPosition().y == snake.getY()) && spawn)
This only triggers, if the positions are exactly the same! As far as I can see, the size of one bodypart of your snake is 15x15 pixel?
I guess you set the position of your keySprite once at 0, 0 or something divisible by 15.
However if you pick it up once and set the position then to: "keysprite.setPosition(350, 200);"  you end up with this: 350 / 15 = 23.3333 and 200 / 15 = 13.3333, so this can't work, right?

Either you make sure to use positions divisible by 15, or you use the contains function, but the first one would be better ;) If you would have an array of the field, it would be easier to handle ;)

Two things I noticed:
(snake.getBlocks())
You don't need the outer brackets, just "snake.getBlocks()" works too.

In the constructor of the Block, you pass two int's, but in setX and setY you pass two floats... :D
Failing to succeed does not mean failing to progress!

Engineer

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
Re: how to remove a sf::Sprite and use a timer
« Reply #4 on: August 18, 2013, 02:29:50 pm »
Damn dude you are an angel, I never thought about that.
But I set up the positions at 300 and 255 after that and it still doesn't work.
So I don't know. :(
in fact, I'd like to put rand() in the set position of my function spawnkey but it always spawn at the same place X_X

Geheim

  • Full Member
  • ***
  • Posts: 201
    • View Profile
    • Email
Re: how to remove a sf::Sprite and use a timer
« Reply #5 on: August 18, 2013, 02:37:34 pm »
in fact, I'd like to put rand() in the set position of my function spawnkey but it always spawn at the same place X_X
You have to call srand once: srand((unsigned int)(time(NULL)));

I have to go now, I will check the issue with the growing then, maybe you could provide the rest of the code which is missing? ;)
Failing to succeed does not mean failing to progress!

 

anything