„Strzelaj” – powiedział dowódca

Dziś zajmiemy się długo już zapowiadanymi strzałami. Na początek możliwość strzelania będzie posiadał tylko nasz bohater. Początkowe założenia mówią, że strzał reprezentowany przez czerwony prostokąt będzie wystrzeliwany w cztery strony świat co określony czas. Najprościej takie coś rozwiązać za pomocą kolekcji dostępnych w Javie. Zatem zacznijmy od stworzenia nowej klasy Shoot.java

public class Shoot extends Rectangle {
    private int strong;
    private int direction;
    private Texture texture;
    private Pixmap pixmap;

    public Shoot(float x, float y, int strong, int direction){
        this.x = x;
        this.y = y;
        this.strong = strong;
        this.direction = direction;
        pixmap = new Pixmap(10, 20, Pixmap.Format.RGBA8888);
        pixmap.setColor(Color.RED);
        pixmap.fillRectangle(0,0,10,20);
        texture = new Texture(pixmap);
        pixmap.dispose();
    }

    public int getStrong() {
        return strong;
    }

    public void setStrong(int strong) {
        this.strong = strong;
    }

    public Texture getTexture() {
        return texture;
    }

    public void setTexture(Texture texture) {
        this.texture = texture;
    }

    public Pixmap getPixmap() {
        return pixmap;
    }

    public void setPixmap(Pixmap pixmap) {
        this.pixmap = pixmap;
    }

    public int getDirection() {
        return direction;
    }

    public void setDirection(int direction) {
        this.direction = direction;
    }
}

Jak już wcześniej wspomniałem, strzał będzie prostokątem, dlatego nowo utworzona klasa Shoot dziedziczy po klasie Rectangle. Zmienna strong odpowiedzialna będzie za siłę strzału, czyli ilość pkt życia ma odebrać strzał trafiony w przeciwnika. Następna linijka to zmienna odpowiedzialna za określenie kierunku strzału, wykorzystamy ją do aktualizacji ruchu strzału w kolejnych klatkach sceny. Kolejne zmienne to powtarzający się kod odpowiedzialny, w dalszej części, za rysowanie na ekranie czerwonego prostokąta (ten wpis jednak nie jest o tym, zatem zapraszam do zapoznania się z wcześniejszymi). Najważniejszą częścią tej klasy jest konstruktor, który tworzy obiekt, przypisując mu pozycję startową, siłę uderzenia, kierunek lotu oraz nadając m wygląd. Kolejne linijki to gettery oraz settery.

Następnie do klasy Player.java dodajemy nową zmienną, będącą ostatnim kierunkiem w jakim poruszał się nasz bohater.

private int direction;

Teraz przechodzimy do naszego głównego kodu UWar.java

Na samym początku dokonamy małej refaktoryzacji kodu (teraz coraz częściej będziemy modyfikować już istniejący kod).

if(Gdx.input.isKeyPressed(Input.Keys.W) && player.y < 5000-2*player.radius){
			player.y += 250 * Gdx.graphics.getDeltaTime();
			player.setDirection(1);
		}

		if(Gdx.input.isKeyPressed(Input.Keys.S) && player.y > 0){
			player.y -= 250 * Gdx.graphics.getDeltaTime();
			player.setDirection(3);
		}

		if(Gdx.input.isKeyPressed(Input.Keys.A) && player.x > 0){
			player.x -= 250 * Gdx.graphics.getDeltaTime();
			player.setDirection(0);
		}

		if(Gdx.input.isKeyPressed(Input.Keys.D) && player.x < 5000-2*player.radius) {
			player.x += 250 * Gdx.graphics.getDeltaTime();
			player.setDirection(2);
		}

Dla każdego przycisku dokonujemy zmiany wartości poruszania, tak abyśmy uwzględniali czas między ostatnią i obecną klatką sceny oraz nadajemy kierunek w którym poruszył się bohater.

0 – lewo

1 – góra

2 – prawo

3 – dół

Teraz możemy przejść do dodawania nowej funkcjonalności w naszej grze.

private LinkedList<Shoot>;
private float timeShoot;

Dodajemy nową zmienną, która jest listą dwukierunkową, przyjmującą obiekty klasy Shoot oraz tworzymy zmienną typu float, odpowiedzialną za obliczanie czasu miedzy strzałami.

strzaly = new LinkedList<Shoot>();
timeShoot = 1;

Listę, jak każdą inną zmienną, należy zinicjalizować, tak też robimy na kodzie powyżej. timeShoot przypisujemy wartość 1.0, zezwalającą na wykonanie strzału.

Abyśmy zobaczyli jakikolwiek efekt należy jeszcze zrobić jeszcze dwie rzeczy. Pierwsza z nich to dodanie obiektów do listy po naciśnięciu klawisza SPACE.

timeShoot += Gdx.graphics.getDeltaTime();
		if(Gdx.input.isKeyPressed(Input.Keys.SPACE)){
			if(timeShoot > 0.2){
				strzaly.add(new Shoot(player.x + player.getTexture().getWidth() / 2 - 5, player.y + player.getTexture().getHeight() / 2 - 5, 1, player.getDirection()));
				timeShoot = 0;
			}
		}

Pierwsza linijka powyższego kodu odpowiada za dodanie czasu do naszej zmiennej obliczającej czas miedzy strzałami. Metoda ta zwraca nam różnicę między poprzednią a obecną klatką. Następnie mamy warunek wykrywający przyciśnięcie klawisza SPACE. Jeśli warunek jest spełniony, wtedy sprawdzamy kolejny warunek. W chwili gdy czas zmiennej timeShoot jest większy od 0.2, wtedy dodaj strzał do listy strzaly z obecnymi pozycjami bohatera w chwili zajścia zdarzenia z obliczonym środkiem tekstury, siłą strzału równą 1 oraz kierunkiem będącym ostatnim kierunkiem w którym poruszał się bohater.

Teraz pozostaje nam zrealizować kolejny punkt, wyświetlanie nowych elementów listy na ekranie.

for (Shoot s : strzaly) {
   batch.draw(s.getTexture(), s.x, s.y);
}

Tworzymy iterator za pomocą fora, którego zadaniem jest przejście przez całą listę i narysowanie na ekranie każdego obiektu tekstury wczytując z niego współrzędne x i y.

Już naszym oczom ukazuję się efekt naszej pracy, jednak w chwili obecnej są to nic nie robiące punkty statyczne. Zatem teraz, aby coś się zaczęło dziać, po włączeniu naszej gry należy dodać w metodzie update() kod odpowiedzialny za zmianę pozycji naszych strzałów.

for (Shoot s : strzaly) {
			if(s.getDirection() == 0){
				s.x -= 300 * Gdx.graphics.getDeltaTime();
			}
			if(s.getDirection() == 1){
				s.y += 300 * Gdx.graphics.getDeltaTime();
			}
			if(s.getDirection() == 2){
				s.x += 300 * Gdx.graphics.getDeltaTime();
			}
			if(s.getDirection() == 3){
				s.y -= 300 * Gdx.graphics.getDeltaTime();

Kolejny raz stosujemy iterator (po listach operuję się za pomocą iteratora). Dla każdego strzału sprawdzamy kierunek i wykonujemy odpowiedni ruch.

Teraz efektem dzisiejszej pracy będzie taki widok

 

 Podsumowanie

Dziś udało się nam zrobić strzały o których wspominałem już od kilku wpisów. Teraz bohater poza poruszaniem się po naszej mapie może również strzelać czerwonymi prostokątami. W kolejnym wpisie zajmiemy się modyfikacją dziś utworzonego kodu. Jak na dziś zrobiliśmy kawał dobrej roboty.

Pozdrawiam,

sirmarbug

Podziel się ze znajomymi