Gra Snake - logika gry a szata graficzna

0

Witam,

Jestem w trakcie pisanie gry Snake w Javie. Całość jest już zaprojektowana, natomiast natknąłem się na pewien problem.
Otóż Snake porusza się po planszy o wielkości 20x20. Startuje ze środka i idzie np. do góry. (Startuje na pozycji 10x10, wykonuje się metoda odpowiedzialna za ruch, jest na 10x11, wykonuje się metoda, jest na pozycji 10x12 itd. aż uderza w ściane (punkt 10x20), następuje koniec gry). Wszystko jest fajnie jeżeli gram w trybie tekstowym.
Tworząc graficzną implementację mojego snake'a. W oknie o wielkości powiedzmy 250x250. Mój wąż przesuwa się o 1 PIXEL, a chciałbym żeby ruch (czyli przejście z punktu 10x10 do 10x11) odpowiadało przesunięciu się o np. 25pixeli.

Podsumowując, jak przejście z punktu (10,10) do punktu (10,11) w skali zaprojektowanej w logice gry odwzorować w szacie graficznej tak, aby 1 punkt odpowiadał 25 pixelom?

0

Możesz sobie podzielić całą plansze na załóżmy 20x20 kwadratów. Każdy element węża to po prostu jeden kwadrat (wypełniony innym kolorem niż reszta planszy). Ruch węża polega na tym, że ostatni element (ogon) zostaje zamalowany kolorem mapy, po czym "idzie" na początek, stając się głową, i tak w kółko.

0

Miałem wczoraj chyba małe zaćmienie.. Wystarczyło wartość punktu w którym miał pojawić się wąż pomnożyć przez 25;) Ale dzięki za pomoc, na razie męczę się jeszcze z jedną rzeczą, ale póki co powalczę sam ;)

0

przecież przesunięcie w rysowaniu, dajmy na to kolejnych elementów snake możesz sobie robić co pixel ale same elementy przesuwają się o średnice swojego kształtu z którego jest zbudowany, jeżeli twój snake jest reprezentowany przez okręgi o szerokosci 20px to przesuniecie robisz tez co 20px.Tak aby początek kolejnego elementu znajdował się na końcu pierwszego jeden przy drugim.

drawFIGURA(x,y,x+10,y+10);

0

Tak też można, z tym problemem już sobie poradziłem. Gra w sumie zmierza już ku końcowi, ale natknąłem się na kolejny mały problem a mianowicie ogon..
Wkleję tylko odpowiedzialną za ruch metodę:

 
	public void step() {
		int x = (int) Math.round(Math.random()*20-1); //zmienne dla losowego punktu jedzenia
		int y = (int) Math.round(Math.random()*20-1);
		setDirection(direction); // Ustawiam kierunek
		setFood(food); // Ustawiam jedzenie
		int valueX = direction.getDx(); //  Dla każdego z kierunków jest zdefiniowana zmiana pozycji węża w poziomie i pionie po wykonaniu ruchu w danym kierunku 
		int valueY = direction.getDy();
		this.headX+=valueX;
		this.headY+=valueY;
		snakeElement[0] = new SnakeElement(this.headX, this.headY); // snakeElement[0] to głowa węża, zawsze i niezmiennie.

		if(this.getHeadX() == food.getX() && this.getHeadY() == food.getY()) // Sprawdzanie czy wąż zjadł jedzenie
                {
			snakeLength++;
			points++;
			this.food = new SnakeFood(x, y);
			setFood(food);
			gsl.gamePointsChanged();
		}

		for(int i=1;i<snakeLength;i++) // rysowanie ogona
               {

			// algorytm dla ogona ...
			snakeElement[i] = new SnakeElement(snakeElement[i-1].getX()-direction.getDx(),snakeElement[i-1].getY()-direction.getDy());
                        // dla wyjaśnienia, gdyby tego -direction.getDx() nie było, wtedy nowy element powstałby na miejscu głowy

		}

		if(headX<0 || headX>heigth-1 || headY<0 || headY>width-1){
			gsl.gameFinished();
		}

	}

Niestety cały wąż porusza się w pionie bądź w poziomie,( nie można nim narysować zygzaka )

0

Odpowiem i zdradze tajemnice węża :Dnie ruszasz Snakiem jako całością a tylko jego głową reszta to tylko animacje kolejno dziedziczące po sobie pozycje głowy.

0

Całość ma działać właśnie w taki sposób jak to opisałeś. Poruszam głową, a za nią porusza się ogon. Czyli snakeElement[0] "głowa" przesuwa się w jakimś kierunku, snakeElement[1] dziedziczy pozycję po snakeElement[0], a snakeElement[2] dziedziczy pozycję po snakeElement[1]. Taka kombinacja pozwoli mi otrzymać "skręt" ? czyli węża o współrzędnych [(0,2);(0;1);(1,1)] ?

0

Tak :)

0

Całość załatwiają 3 linijki kodu:

 	
	for(int i=snakeLength;i>0;i--) {
			snakeElement[i] = snakeElement[i-1];
		}
		snakeElement[0] =  new SnakeElement(this.headX,this.headY);

albo nawet jedna.. :

 		snakeElement.add(0,new SnakeElement(this.headX,this.headY)); 

dzięki ;)

0

Żeby kontynuować tajemnice węża do Wigilii Świąt Bożego Narodzenia, mam jeszcze jedną małą zagwozdkę, nie mogę wymyślić dlaczego zawracanie węża o długości równej lub większej od 3 wywołuje koniec gry, a węża o długości równej 2 już nie.. Poniżej 2 metody:

 	public void step() {
		int x = (int) Math.round(Math.random() * 20); // zmienne do losowania współrzędnych dla jedzenia
		int y = (int) Math.round(Math.random() * 20);
		setDirection(direction); // ustawiam kierunek
		setFood(food); // ustawiam jedzenie
		this.headX += direction.getDx(); // Dla każdego z kierunków jest zdefiniowana zmiana pozycji węża w poziomie i pionie po wykonaniu ruchu w danym kierunku 
		this.headY += direction.getDy();
		if (this.getHeadX() == food.getX() && this.getHeadY() == food.getY()) // Jeżeli wąż zjadł pożywienie
                {
			snakeLength++; // zwiększam jego długość
			points++; // zwiększam ilość zdobytych punktów
			this.food = new SnakeFood(x, y); // ustawiam jedzenie na nowej pozycji (narazie nie sprawdzam, czy stworzy się "na" wężu
			setFood(food); // ustawiam jedzenie
			gsl.gamePointsChanged(); // informuje słuchacza zdarzeń o zmianie punktów
			snakeElement.add(snakeLength-1, new SnakeElement(this.headX, this.headY)); // Dodaje element na koniec listy
		}
		snakeElement.add(0, new SnakeElement(this.headX, this.headY));// Tworzę głowę (jej nową pozycję) na 0 miejscu listy
		snakeElement.remove(snakeElement.size()-1); // usuwam stary element
		if (gameIsOver()) 
                {
			gsl.gameFinished(); // informuje słuchacza zdarzeń, że skończyłem grę
		}

	}
	public boolean gameIsOver() {
		if (headX < 0 || headX > heigth || headY < 0 || headY > width) // Jeżeli snake wyleciał poza planszę
                {
			return true;
		}
		for (int i = 1; i < snakeLength; i++) 
               {
			if (snakeElement.get(0).getX() == snakeElement.get(i).getX() && snakeElement.get(0).getY() == snakeElement.get(i).getY()) // jeżeli snake ugryzł sam siebie no i... jeżeli zawrócił co niestety nie działa..
                        {
				gsl.gameFinished();
			}
		}

		return false;
	} 
0

Napisałem kiedyś snake'a (takiego płynnego a nie poruszające się co pole) i pamiętam że dla każdego jego elementu ustalałem osobną kolizje i z reguły była ona zrobiona na podstawie Klasy Rectangle(bądź Circle) danej biblioteki, która zaś udostępniała metody kolizji tych figur.

Powiedz w jakiej bibliotece piszesz ? (tylko nie mów AWT/Swing)

Mi się wydaje że po prostu zanim zmienisz pozycje pozostałych elementów węża (czyli tuż po poruszeniu się głowy) musisz wywołać metodę gameIsOver() czyli tą która sprawdzi kolizje.

PS:Znalazłem swój kod i jednak kolizje sprawdzałem ręcznie(nie w moim style):

for(int i=3;i<ogon.size();i++){
            if((int)(x/50)==(int)(ogon.get(i).x/50) && (int)(y/50)==(int)(ogon.get(i).y/50))
                if(timer==0)
                    Snaker.GAMEOVER=true;
            if((int)((x+48)/50)==(int)(ogon.get(i).x/50) && (int)((y+48)/50)==(int)(ogon.get(i).y/50) && (ysp>0 || xsp>0))
                if(timer==0)
                    Snaker.GAMEOVER=true;
        }

1 użytkowników online, w tym zalogowanych: 0, gości: 1