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

Author Topic: Shooting Lasers  (Read 2080 times)

0 Members and 1 Guest are viewing this topic.

WDR

  • Jr. Member
  • **
  • Posts: 82
    • View Profile
Shooting Lasers
« on: August 24, 2013, 09:41:11 am »
Hi (again)... So, I am making this space based game. So far, I've been able to do player, enemy, backgrounds, click events, game states, movement... everything perfectly (almost). I did a lot of learning on the way. Now, I moved onto creating the lasers. Here's where the problem started. Did a bit of research on the forums and other places... Here's what I did.

if(!greenlasertex.loadFromFile("images/playerlaser.png"))
        return EXIT_FAILURE;

std::list<sf::Sprite> greenlaser(MAX, sf::Sprite(greenlasertex));

for(std::list<sf::Sprite>::iterator greenlaserit = greenlaser.begin(); greenlaserit != greenlaser.end(); greenlaserit++)
{
        greenlaserit->setOrigin(greenlaserit->getGlobalBounds().width/2, greenlaserit->getGlobalBounds().height/2);
        greenlaserit->setScale(0.1f, 0.1f);
        greenlaserit->setPosition(player.getPosition().x, player.getPosition().y);
}

float laserspeed = 800.f;

while(window.isOpen())
{
        float timer = clock.restart().asSeconds();

        window.clear();

        for(std::list<sf::Sprite>::iterator greenlaserit = greenlaser.begin(); greenlaserit != greenlaser.end(); greenlaserit++)
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Space))
                        greenlaserit->setPosition(player.getPosition().x, player.getPosition().y);

        std::list<sf::Sprite>::iterator greenlaserit = greenlaser.begin(), reload;
        while(greenlaserit != greenlaser.end())
        {
                reload = greenlaserit;
                reload++;
                greenlaserit->move(0.f, -laserspeed * timer);
                window.draw(*greenlaserit);
                greenlaserit = reload;
        }

        window.display();
}

Theoretically, I know what this piece of code is doing. It's creating a list of sprites and placing the whole list at the player's position. Then, as soon as the game is started, all the elements in the list of sprites are moving together upwards without any input. When Space key is pressed, the position of all the elements in the list is again reset to player's position. And the whole list moves upward again. Obviously, this is not ideal code and absolutely wrong. Two major problems of this is, 1) All the elements move at a time instead of one at a time. 2) The elements move without any input at the start of the game. What changes must I make in order to place a single element at the player position when input is given and not move until that element is placed? Hope I explained myself clearly. Please point me in the right direction. Thank you.

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Shooting Lasers
« Reply #1 on: August 24, 2013, 07:02:48 pm »
Quote
What changes must I make in order to place a single element at the player position when input is given and not move until that element is placed?

Just start with an empty list, and create a new laser sprite whenever the player fires and add it to the list.

Sprites are very lightweight objects (the texture is the heavy part) so there's no reason not to do it this way.

In theory you should be able to just delete the initialization code at the top (just make the list but put nothing in it) and then replace this:
    for(std::list<sf::Sprite>::iterator greenlaserit = greenlaser.begin(); greenlaserit != greenlaser.end(); greenlaserit++)
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Space))
            greenlaserit->setPosition(player.getPosition().x, player.getPosition().y);
with something like this:
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Space)) {
    sf::Sprite newgreenlaser(greenlasertex);
    newgreenlaser.setOrigin(newgreenlaserit.getGlobalBounds().width/2, newgreenlaser.getGlobalBounds().height/2);
    newgreenlaser.setScale(0.1f, 0.1f);
    newgreenlaser.setPosition(player.getPosition().x, player.getPosition().y);
    greenlaser.push_back(newgreenlaser);
}
Haven't tested it or anything so have fun debugging.

WDR

  • Jr. Member
  • **
  • Posts: 82
    • View Profile
Re: Shooting Lasers
« Reply #2 on: August 24, 2013, 11:20:38 pm »
Awesome! This totally works! Thanks, Ixrec!  :D

It gives the desired output... Creating the element in the list when input is given and then moving it. But, there's just one tiny thing. The lasers are added consecutively to the list as long as the key is being pressed, so it is creating a stream of lasers whenever the key is pressed. Sort of like a lightsaber. The screenshot might give you an idea of what I mean.



I tried putting it inside an event. But, the event checks only once and does not give real-time result. So, the sf::Keyboard is the correct one. But about the lasers... Obviously, there should be a time delay between each laser. When the key is held down, the sprites should generate and move one after the other with a time interval between them, right? At least, that's the theory. How do I set the time interval? I tried Sleep(), but that's not right. It stops the whole program. I'm thinking float elapsed += clock.getElapsedTime() plays a role here. Not sure how to implement it, though. Please help me on this. Thanks!

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Shooting Lasers
« Reply #3 on: August 24, 2013, 11:35:51 pm »
If you want to do this the proper way, read this: http://gafferongames.com/game-physics/fix-your-timestep/  It's not using SFML code, but you should be able to put 2 and 2 together from the SFML documentation and his very generic code in that post.

If you want a very quick and easy solution that doesn't involve precise framerate-independent timing, you can keep an integer like fire_attempts that you reset to 0 whenever space is *not* pressed, increment whenever space is pressed, reset to 0 whenever it passes some arbitrary wraparound point like 20 (this is the part you play with and adjust), and then have a laser get created only when fire_attempts is at 0 (so it happens the first time you see space being pressed, and after that only every 20th time or something).

WDR

  • Jr. Member
  • **
  • Posts: 82
    • View Profile
Re: Shooting Lasers
« Reply #4 on: August 25, 2013, 12:09:12 am »
You, my friend, have pointed me to the right resource. Thank you. I shall go through it and try to implement it. If I have any further queries, I shall post again.  :)