NASZE SERWISY:    ANDROID   LINUX   MAEMO   SYMBIAN   WEBOS




Hosting sponsoruje:



GRIN3 - polskie fonty

Profesjonalne czcionki z polskimi znakami - czcionki.com

OpenMobile on Facebook


 

[Java] - prosty Arkanoid

Odpowiednie forum do zadawania pytań dotyczących rozpoczęcia programowania.

[Java] - prosty Arkanoid

Postprzez issa » 28 maja 2009, o 15:40

Jeśli Moderator uważa , że ten temat nie powinien być osobnym wątkiem na Forum , proszę o przeniesienie go według własnego uznania.

Wydaje mi się jednak , że zasługuje na osobny wątek , gdyby ktoś szuka sposobu realizacji podobnego pomysłu.
Jest to prosty zarys kodu do Arkanoida w podstawowej wersji. Nie chodziło oczywiście o jakąś wysublimowaną grafikę ani o stworzenie gry która mogłaby konkurować z projektami zawodowców , co raczej o pokazanie co można osiągnąć naprawdę prostym i krótkim kodem. W projekcie założyłem , że jak w każdym Arkanoidzie będzie ruchoma platforma która umożliwi nam wystrzeleni kulki z odpowiedniej pozycji oraz bloki które rzecz jasna po zderzeniu z kulką mają zniknąć. Prostym rozszerzeniem poniższego kodu byłoby np. dodanie ruchomych poziomych bądź pionowych bloków których trafienie dawałoby dodatkowe punkty , powodowało rysowanie linii blokującej "przepadnięcie" kulki , dawało możliwość strzelenia z platformy itp. Aplikacja i video znajduje się pod adresem:

http://www.zshare.net/download/606306987efe4f44/

To co nie za bardzo mi się podoba , to jednak wolne działanie aplikacji napisanych w Javie. Nie wyobrażam sobie iPhonowego Blixa napisanego w Javie. Być może jest to wina jakość mojego kodu , jednak z testów jakie zrobiłem i tak wynika , że na e63 działa o wiele szybciej niż na rozłożonym ekranie Nokii e90. Fajnie by było zmierzyć się z androidową wersją Javy , z tego co czytałem Android ma sprzętową akcelerację Javy , podobnie jest o ile się nie mylę z Samsungiem Omnia HD.
Ale do rzeczy:
Klasa Prosty_Android nie wymaga oczywiście żadnych objaśnień bo to oczywista oczywistość , skupmy się od razu na klasie Plotno rozszerzającej klasę GameCanvas z pakietu javax.microedition.lcdui.game.* i konstruktorze:

public Plotno ()
{ super (false);
pozycjaX = 140;
setFullScreenMode (true);
try
{
obrazekPrzeszkody = Image.createImage ("/blok.png");
obrazekKulki = Image.createImage ("/kulka.png");
obrazekTla = Image.createImage ("/tlo.png");
obrazekPlatformy = Image.createImage ("/platforma.png");
}
catch (Exception e) {}
g = getGraphics();
menadzer_warstw = new LayerManager();
blok = new Sprite[3];
for (int i = 0 ; i<3 ;i++)
{
blok[i] = new Sprite (obrazekPrzeszkody , 40,20);
blok[i].setPosition (100+50*i,0);
menadzer_warstw.append (blok[i]);
}
platforma = new Sprite (obrazekPlatformy , 60,15);
platforma.setPosition (120,225);
kulka = new Sprite ( obrazekKulki , 15 ,15);
kulka.setPosition (140,210);
tlo = new Sprite ( obrazekTla , 320 , 240);
tlo.setPosition (0,0);
menadzer_warstw.append (platforma);
menadzer_warstw.append(kulka);
menadzer_warstw.append (tlo);
mozna_strzelic = true;
}
Kod konstruktora zaczyna się od wywołania konstruktora klasy bazowej , którego parametrem jest false , a która powoduje , że w klasie (Plotno) dziedziczącej po klasie GameCanvas (i Canvas , bo po niej dziedziczy ta pierwsza klasa) będziemy mogli używać klasycznej obsługi klawiatury , czyli metod keyPressed i keyRepeated. Dlaczego tych dwóch metod? Bo tylko obie w połaczeniu dają możliwość wygodnego sterowania platformą. Ustawiamy współrzędną pozycjaX kulki na taką samą jaka jest podana w wywołaniu kulka.setPosition (140,210);
Ustawiamy tryb ekranu na full i wczytujemy z zasobów (res) niezbędne obrazki. Pobieramy obiekt "wykreślacza" , tworzymy menadżera warstw oraz tworzymy tablicę trzech elementów typu Sprite a następnie w pętli dodajemy do tablicy te obiekty do których będziemy się później odwoływać przez blok[0] , blok[1] oraz blok[2] , ustawiamy ich pozycję na ekranie metodą setPosition , czynimy je widzialnymi setVisible (true) , choć w sumie domyśłnie każdy Sprite jest widzialny , oraz dodajemy do menadżera warstw. Należy pamiętać , że obiekt o najniższym identyfikatorze , czyli dodany najpierw jest odrysowany na końcu a o najwyższym , czyli dodany na końcu , jest odrysowywany pierwszy. Dlatego też ostatnim dodanym elementem / warstwą w konstruktorze będzie obiekt tła. To samo czynimy z platformą , kulką oraz tłem. Później wyjaśnię do czego służy zmienna mozna_strzelic typu boolean.
W metodzie paint:

public void paint (Graphics g)
{

menadzer_warstw.paint (g,0,0);
flushGraphics();
}


którą będziemy wywoływać po każdym ruchu kulki odmalowywany jest menadzer_warstw i wszystko jest "spłukiwane"/flush na ekran , dopiero wtedy wszystko co zostało narysowane w buforze pojawi się na ekranie.

W obsłudze klawiatury najpierw obsługujemy przyciśnięcie (pressed) klawisza , a następnie w drugiej funkcji długotrwałe/powtarzane przyciśnięcie (repeated).
public void keyPressed (int klawisz)
{
int akcja = getGameAction (klawisz);
switch (akcja)
{
case FIRE:
{
if (mozna_strzelic)
{
mozna_strzelic = false;
ruszaj = true;
Runnable watek = new Watek (kulka ,0 , pozycjaX , 210 , 1 ,-1 );
new Thread (watek).start();
break;
}
}
case LEFT:

{ pozycjaX = pozycjaX-10;
if (mozna_strzelic == true)
{
kulka.move (-10,0);
}
platforma.move (-10,0);
paint (g);
break;
}

case RIGHT:

{ pozycjaX = pozycjaX+10;
if (mozna_strzelic == true)
{
kulka.move (10,0);
}
platforma.move (10,0);
paint (g);
break;
}
}
}
W klasie Canvas (z której dziedziczy GameCanvas) zdefiniowane są stałe używane do gier , między innymi FIRE , LEFT , UP itp. W ciele metody keyPressed która przyjmuje jako argument kod klawisza , za pomocą metody int akcja = getGameAction (klawisz); , będziemy mogli skorzystać z w/w stałych , co robimy za pomocą instrukcji switch. Jeśłi wystąpił przypadek (case) FIRE , LEFT bądź RIGHT obsługujemy je.
Przyciśnięcie FIRE powoduje uruchomienie nowego wątku , w któym będzie obsługiwany ruch kulki i jej zderzenia z blokami i końcem ekranu. Zmienna mozna_strzelic która w konstruktorze ustawiona był na true , zostaje ustawiona na false , żeby oczywiście do zakończenia animacji nie można było wystrzelić kulki drugi raz. ruszaj ustawiona jest na true i do momentu kiedy kulka będzie się odbijać od platformy będzie miała wartość true , w przeciwnym wypadku następuje oczywiście koniec wątku , czyli ruszaj = false;
Przypadek LEFT i RIGHT obsługuje jednocześnie ruch kulki i platformy. Jeśli mozna_strzelic==true , kulka będzie się przesuwała razem z platformą. Po wystrzeleniu i ustawieniu zmiennej mozna_strzelic na false oczywiście ruch lewo-prawo nie będzie zaburzał ruchu kulki , to bardzo ważne i jednocześnie proste rozwiązanie separujące te dwa elementy gry. Każde ruch powoduje oczywiście odmalowanie paint (g) całego buforu.
Ciało metody keyRepeated to praktycznie prawie powtórzenie metody keyPressed. Jak pisałem dopiero te dwie metody dają pełną wygodę przy obsłudze platformy.
Po uruchomieniu wątku czyli wystrzeleniu kulki sprawdzane są zdarzenia zetknięcia kulki z ekranem , kolizji z blokami i odbiciem od platformy, te drugie obsługiwane w warunkach:

if (kuleczka.collidesWith (blok[0],false))
{
blok[0].setVisible (false);
opoznienie = 0;
}
if (kuleczka.collidesWith (blok[1],false))
{
blok[1].setVisible (false);
opoznienie = 0;
}
if (kuleczka.collidesWith (blok[2],false)) {blok[2].setVisible (false);}
if (kuleczka.collidesWith (platforma , false))
{if (dx==1 && dy==1)
{
dx=1;
dy=-1;
}
if (dx==-1 && dy==1)
{
dx=-1;
dy=-1;
}
}
przy użyciu metody klasy Sprite: sprite_A.collidesWith (sprite_B). Jak widać w łatwy sposób można spowodować by uderzenie w dany blok powodowało np. przyspieszenie bądź spowolnienie.
I to praktycznie na tyle. Mam sporo koncepcji na pisanie programów w Java2me , wzorem do naśladowania jest kopalnia zwana AppStore.


Kod: Zaznacz cały
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.game.*;

public class Prosty_Arkanoid extends MIDlet implements CommandListener
{

private Plotno plotno;
private Display ekran;
public Prosty_Arkanoid()
   {
    Plotno plotno = new Plotno ();
    Command koniec = new Command ("Koniec" , Command.EXIT , 0);
 
    plotno.addCommand (koniec);
    plotno.setCommandListener (this);
    ekran = Display.getDisplay(this);
    ekran.setCurrent (plotno);

  }

public void startApp() {}
   
public void pauseApp() {}

public void destroyApp (boolean bezwarunkowo) {}

public void commandAction (Command polecenie , Displayable ekran)
      {
       if (polecenie.getCommandType () == Command.EXIT)
          {       
            notifyDestroyed();
          }


       }
}
   
class Plotno extends GameCanvas

{
   public Plotno ()
     { super (false);
       pozycjaX = 145;
       setFullScreenMode (true);
       try
        {
         obrazekPrzeszkody = Image.createImage ("/blok.png");
         obrazekKulki     = Image.createImage ("/kulka.png");
         obrazekTla        = Image.createImage ("/tlo.png");
         obrazekPlatformy  = Image.createImage ("/platforma.png");
        }
       catch (Exception e) {}
       g = getGraphics();
       menadzer_warstw = new LayerManager();
       blok = new Sprite[3];
       for (int i = 0 ; i<3 ;i++)
        {
         blok[i] = new Sprite (obrazekPrzeszkody , 40,20);
         blok[i].setPosition (100+50*i,0);
         blok[i].setVisible (true);
         menadzer_warstw.append (blok[i]);
         }
       platforma = new Sprite (obrazekPlatformy , 60,15);
       platforma.setPosition (120,225);
       kulka = new Sprite ( obrazekKulki , 15 ,15);
       kulka.setPosition (140,210);
       tlo =   new Sprite ( obrazekTla , 320 , 240);
       tlo.setPosition (0,0);
       menadzer_warstw.append (platforma);
       menadzer_warstw.append(kulka);
       menadzer_warstw.append (tlo);
       mozna_strzelic = true;
     }
     


   public void paint (Graphics g)
     {
       
       menadzer_warstw.paint (g,0,0);
       flushGraphics();
     }
   
   
   public void keyPressed (int klawisz) 
     {
       int akcja = getGameAction (klawisz);
       switch (akcja)
        {
         case FIRE:
           {
             if (mozna_strzelic)
              { kulka.setVisible (true);
                mozna_strzelic = false;
                ruszaj = true;
                Runnable watek = new Watek (kulka ,0 , pozycjaX , 210  , 1 ,-1 );
                new Thread (watek).start();
                break;
              }
           }
          case LEFT:
         
             { pozycjaX = pozycjaX-10;
               if (mozna_strzelic == true)
                {
                  kulka.move (-10,0);
                }
               platforma.move (-10,0);
               paint (g);
               break;
             }
         
         case RIGHT:
         
             { pozycjaX = pozycjaX+10;
               if (mozna_strzelic == true)
                {
                  kulka.move (10,0);
                }
               platforma.move (10,0);
               paint (g);
               break;
             }
        }
     }
    public void keyRepeated (int klawisz) 
     { int akcja = getGameAction (klawisz);
       switch (akcja)
         {
          case LEFT:
         
             { pozycjaX = pozycjaX-10;
               if (mozna_strzelic == true)
                {
                  kulka.move (-10,0);
                }
               platforma.move (-10,0);
               paint (g);
               break;
             }
         
         case RIGHT:
         
             { pozycjaX = pozycjaX+10;
               if (mozna_strzelic == true)
                {
                  kulka.move (10,0);
                }
               platforma.move (10,0);
               paint (g);
               break;
             }
        }
    }
class Watek implements Runnable
    {
     public Watek (Sprite kuleczka , int opoznienie , int x , int y ,int dx,int dy)
      {
       this.kuleczka = kuleczka;
       this.opoznienie = opoznienie;
       this.dx = dx;
       this.dy = dy;
       this.pozycjaX = x;
       this.pozycjaY = y;
       kuleczka.setPosition (x , y);
      }
      public void run()
         
           {
             while (ruszaj)

              { 

                if (pozycjaY<1)              {dy = +1;}
                if (pozycjaY>getHeight()-15) {ruszaj=false;}
                if (pozycjaX<1)              {dx = +1;}
                if (pozycjaX>getWidth()-10)  {dx = -1;}   
                if (kuleczka.collidesWith (blok[0],false))
                   {
                     blok[0].setVisible (false);
                     opoznienie = 0;
                     }
                if (kuleczka.collidesWith (blok[1],false))
                   {
                    blok[1].setVisible (false);
                    opoznienie = 0;
                   }
                if (kuleczka.collidesWith (blok[2],false)) {blok[2].setVisible (false);}
                if (kuleczka.collidesWith (platforma , false))
                  {if (dx==1 && dy==1)
                   {
                     dx=1;
                     dy=-1;
                    }
                   if (dx==-1 && dy==1)
                    {
                     dx=-1;
                     dy=-1;
                    }
                   }
       
                 pozycjaY=pozycjaY+dy;
                 pozycjaX=pozycjaX+dx;

                 kuleczka.move (dx , dy);
                 paint(g);
                 
                 try
                  {
                   Thread.sleep (opoznienie);
                  }
                  catch (Exception e)
                  {
                  }
               
              }
           }
     private Sprite kuleczka;
     private int dx;
     private int dy;
     private int opoznienie;
     private int pozycjaX;
     private int pozycjaY;
     }
private Sprite blok[];
private Sprite platforma;
private Sprite kulka;
private Sprite tlo;
private LayerManager menadzer_warstw;
private Image obrazekKulki;
private Image obrazekTla;
private Image obrazekPrzeszkody;
private Image obrazekPlatformy;
private Graphics g;
private boolean ruszaj;
private boolean mozna_strzelic;
private int pozycjaX;
private int pozycjaY;
}
issa
10%
10%
 
Posty: 49
Dołączył(a): 11 sierpnia 2006, o 20:13
    WindowsXPFirefox

Powrót do Od czego zacząć?

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 1 gość

cron