Cześć. Piszę Space Invaders i mam problem z ujęciem w c++ automatycznego poruszania obiektami. Zamiar jest następujący: co sekundę, każdy ze stworków (na potrzeby testów pracuje przy jednym) porusza się w prawo np. 10 razy, potem 1 raz w dół, potem 10 razy w lewo, raz w dół i sekwencja rozpoczyna się od nowa, zupełnie jak w grze (pomijam fakt, że przyśpieszają po jakimś czasie).
if (zegar.getElapsedTime().asSeconds() > 1.0f)
{
inv.move(10, 0);
if (przemieszczenia > 5)
{
przemieszczenia = 0;
inv.move(0, 10);
break;
}
//tutaj nie mam pojecia jak calkowicie wyjsc z pierwszego ifa, bo gdy dam break pierwszy if gdy minie sekunda po prostu sie zerwie za pierwszym razem, a ja chcialbym dopiero gdy drugi if sie spelni
}
Próbowałem tego, nie mam pojęcia jak to rozwiązać.
for (int przemieszczenia = 0; przemieszczenia > 5; przemieszczenia++)
{
if (zegar.getElapsedTime().asSeconds() > 1.0f)
{
inv.move(10, 0);
zegar.restart();
}
}
Kombinowałem dalej, pętla w ogóle się nie wykonuje, najbliżej byłem gdy:
float x=10, y;
if (zegar.getElapsedTime().asSeconds() > 1.0f)
{
inv.move(x, 0);
przemieszczenia++;
zegar.restart();
if (przemieszczenia > 5)
{
y = 10;
inv.move(0, y);
przemieszczenia = 0;
x = -10;
}
}
Masa jeszcze innych dziwactw przedarła się przez kod źródłowy, ale były jeszcze gorsze niż powyższe. Nie chcę gotowego rozwiązania na tacy, proszę tylko o wskazówkę, bo czuję, że tkwię w dużym błędzie myślowym. Istota tej animacji obiektów opiera się właśnie o czas, a gdy czas jest warunkiem poruszanie się w jedną stronę będzie wiecznie. Podsumowując, nie mam jakiegokolwiek pomysłu na warunek tej animacji, dlatego liczę na małą wskazówkę, a czekając kombinuję dalej :D :)
//edit: Wow! Dziękuję wszystkim za tak szybki i pozytywny odzew :D Na dniach pogłębię swoją wiedzę o pętlach i wrzucę posta w jaki sposób akurat ja to rozwiązałem. ;)
//edit2: Myślę, że zrozumiałem już sens pętli stałokrokowej i zrobiłem animacje poruszania się stworka :)
Kod:
#include <SFML/Graphics.hpp>
#include <iostream>
using namespace std;
int main()
{
sf::RenderWindow okno(sf::VideoMode(800, 600), "sfml");
sf::Texture invtxd;
invtxd.loadFromFile("inv1ab.png");
sf::Sprite inv(invtxd);
inv.setTextureRect(sf::IntRect(0, 0, 256, 256));
sf::Clock stoper;
sf::Clock zegar; //tworzymy zegar, który będzie odliczał nam czas od jego utworzenia
sf::Time CzasOdAktualizacji = sf::Time::Zero; //tworzymy obiekt, który będzie zapamiętywał czas, który upłynał od ostatniej aktualizacji i zerujemy go.
const sf::Time KrokCzasowy = sf::seconds(1.f / 60.f); //nasz krok czasowy i czas klatki, tutaj około 60 klatek na sekunde
int przemieszczenia = 0;
const int jakDalekoPrzeniesc = 20;
while (okno.isOpen())
{
sf::Time Czas = zegar.restart(); //tworzymy obiekt, który będzie przetrzymywał czas jaki zajął obieg pętli
CzasOdAktualizacji += Czas; // zwiększamy czas od ostatniej aktualizacji(skrót: COOA) o czas obiegu pętli
while (CzasOdAktualizacji > KrokCzasowy) //jeśli COOA większe od kroku czasowego
{
sf::Event event;
while (okno.pollEvent(event))
{
if (event.type == sf::Event::Closed)
okno.close();
}
//tutaj aktualizacja gry
if (stoper.getElapsedTime().asSeconds() > 1.f)
{
int x = inv.getPosition().x;
int y = inv.getPosition().y;
inv.setPosition(x + 10, y);
if (przemieszczenia < 22)
{
if (przemieszczenia < 10)
{
przemieszczenia++;
inv.setPosition(x + jakDalekoPrzeniesc, y); //prawo
}
else if (przemieszczenia < 11)
{
przemieszczenia++;
inv.setPosition(x, y + jakDalekoPrzeniesc); //dol
}
else if (przemieszczenia < 21)
{
przemieszczenia++;
inv.setPosition(x - jakDalekoPrzeniesc, y); //lewo
}
else if (przemieszczenia < 22) //dol
{
przemieszczenia++;
inv.setPosition(x, y + jakDalekoPrzeniesc);
}
stoper.restart();
}
CzasOdAktualizacji -= KrokCzasowy; // odejmujemy czas trwania klatki
}
okno.clear(sf::Color::Black);
okno.draw(inv);
okno.display();
}
}
return 0;
}
Muszę nałożyć ostatnie szlify, bo gdy daję przemieszczenia = (przemieszczenia + 1) % 22; aby zapewnić powtarzalność tej sekwencji (prawo, dół, lewo i tak w kółko) to nie schodzi w dół, ale generalnie jest ok. :)