[java] czyszczenie ekranu gry

Witam. Mam pewien problem. Otóż mam taki kod:

import javax.swing.JApplet;

import java.awt.*;

import java.awt.event.*;

/**

 *

 * @author piotrek

 */

public class NewJApplet extends JApplet implements KeyListener {

    int przycisk;

    String pokazprzycisk;

    int mapkaX = 0;

    int mapkaY = 0;

    /**

     * Initialization method that will be called after the applet is loaded

     * into the browser.

     */

    public void init() {

        addKeyListener(this);

        setBackground( Color.black );

        // TODO start asynchronous download of heavy resources

    }

    public void przyciski() {

        if(przycisk == 38){ mapkaY += 1;}

        if(przycisk == 40){ mapkaY -= 1;}

        if(przycisk == 37){ mapkaX += 1;}

        if(przycisk == 39){ mapkaX -= 1;}

    }

    public void paint (Graphics gDC2){

        Graphics2D gDC = (Graphics2D)gDC2;

        przyciski();

        gDC.setColor(new Color(0,0,0));


	Image img;

	img = getImage(getDocumentBase(), "pustynia.png");

	gDC.drawImage(img, mapkaX, mapkaY, this);



        //gDC.drawString(pokazprzycisk, 100, 100);

        gDC.drawString(przycisk+"", 120, 100);

        try

                {

                        Thread.sleep(10); // metoda powoduje że program "śpi" przez sekundę (1000milisekund)

                } catch (InterruptedException e) {}

        repaint();

    }


    public void keyPressed(KeyEvent e) { przycisk = e.getKeyCode(); repaint();}

    public void keyReleased(KeyEvent e) {przycisk = e.getKeyCode(); repaint();}

    public void keyTyped(KeyEvent e) {przycisk = e.getKeyCode(); repaint();}

}

On ma za zadanie poruszać obrazkiem w zależności który przycisk wciśniemy… Niestety pojawił się problem z tym, że jak obrazek zmienia pozycję (wciskam strzałkę np. w dol) to pojawia się coś takiego:

95c4e7486edd84a4m.jpg

beztytuuhfj.png

Jak widać na tym zdjęciu nie wygląda to ładnie. Więc jak zrobić żeby obraz ciągle się odświeżał i żeby nie było ileś tam kopii tych obrazków tylko jedna?

Image img;

   img = getImage(getDocumentBase(), "pustynia.png");

Miej litość dla HDD i weź to wrzuć do jakiejś metody inicjującej, bo wczytywanie jednego obrazka w pętli rysującej to grzech.

czyścić możesz np. zamalowując stary render czarnym (gDC.setColor(Color.BLACK); gDC.fillRect(0,0,getWidth(),getHeight());), albo metodą czyszczącą: gDC.clearRect(0,0,getWidth(),getHeight());

Hmmm. Dodałem to gDC.clearRect(0,0,getWidth(),getHeight()); oraz usunąłem thread.sleep i jest dobrze ale strasznie miga. Aż oczy bolą.

Musisz jeszcze się zaopatrzyć w podwójne buforowanie.

Spróbuj w konstruktorze, albo gdzieś tam przed rysowaniem jeszcze dodać: setDoubleBuffered(true);

Jeśli nie pomoże, to musisz ręcznie to zrobić: przy rysowaniu utworzyć Image takiego samego rozmiaru jak okno i na nim wszystko rysować, a potem narysować sam ten obrazek w oknie.

polecam:

http://www.realapplets.com/tutorial/Dou … ering.html

http://java.sun.com/products/java-media … index.html

Mam kolejny problem tym razem już nie z obrazkami (bynajmniej nie do końca)

Otóż… Zrobiłem sobie kod w którym jeden obiekt będzie się powoli przesuwał w miejsce przeze mnie wskazane. Tzn. obiekt “ludzik” jest na pozycji X:1,Y:1 a ja wskażę mu inną pozycję to on idzie w to miejsce. Niestety problem pojawił się z tym że… obiekt przesuwa się tylko kiedy wciskam jakiś przycisk na klawiaturze. No i utknąłem. Szukam już od 30 min co zrobić żeby obiekt przesuwał się sam bez jakby “mojego wkładu”, próbowałem już z 10 sposobów jak to minąć i nic… :o

Liczę że wy coś wymyślicie bo ja nie daję rady:

import javax.swing.JApplet;

import java.awt.*;

import java.awt.event.*;

/**

 *

 * @author piotrek

 */

public class NewJApplet extends JApplet implements KeyListener, Runnable {

    int przycisk;

    String pokazprzycisk;

    int mapkaX = -1;

    int mapkaY = -1;

    String ods = "tak";

    Image img = null;

    Image warstwa1 = null;

    Image warstwa2 = null;

    Image warstwa3 = null;

    Image warstwa4 = null;

    Image ludekB = null;

    Graphics bufferGraphics;

    Image offscreen;

    int WojskaB[][] = new int[100][100];

    Dimension dim;

    int XScreen;

    int YScreen;

    int WTH;

    int HIT;

    boolean wojskaBol = false;

    public Graphics gDC;

    /**

     * Initialization method that will be called after the applet is loaded

     * into the browser.

     */

    public void init() {

        addKeyListener(this);

        setBackground( Color.black );

        dim = getSize();

        offscreen = createImage(677,370);

        XScreen = 677;

        YScreen = 370;

        bufferGraphics = offscreen.getGraphics();

        // TODO start asynchronous download of heavy resources

    }




    public void przyciski() {

       // [...]Obsługa klawiszy


    }


    public void ManageWojska() {

        //przemieszczanie wojsk

        for(int ii = 0; ii < WojskaB.length; ii++){

            if(WojskaB[ii][3] > WojskaB[ii][1]){ WojskaB[ii][3] -= 1; }

            if(WojskaB[ii][3] < WojskaB[ii][1]){ WojskaB[ii][3] += 1; }

            if(WojskaB[ii][4] > WojskaB[ii][2]){ WojskaB[ii][4] -= 1; }

            if(WojskaB[ii][4] < WojskaB[ii][2]){ WojskaB[ii][4] += 1; }

        }


}


    public void RysWojska (Graphics gDC){

        /* LEGENDA

         * 0 - ilosc wojsk (max 12)

         * 1 - cel (pozycja X)

         * 2 - cel (pozycja Y)

         * 3 - aktualna pozycja X

         * 4 - aktualna pozycja Y

         * 5 - zadanie

         * 6 - czy wyswietlone

         */

        //jeżeli nie ma wojsk tworzę pierwsze

        if(wojskaBol == false){

            WojskaB[0][0] = 16;

            WojskaB[0][1] = 50;

            WojskaB[0][2] = 50;

            WojskaB[0][3] = 1;

            WojskaB[0][4] = 1;

            WojskaB[0][5] = 1;

            WojskaB[0][6] = 0;

            wojskaBol = true;

        }

        //obsługuję wszystkie wojska

        [...] rysowanie wojsk w odpowienim miejscu

        }

        //return gDC;

    }


    public void paint (Graphics gDC2){


        gDC = bufferGraphics;


        gDC.setColor(Color.BLACK); gDC.fillRect(0,0,getWidth(),getHeight());


        gDC.setColor(new Color(0,0,0));


	if(warstwa1 == null){

            //img = getImage(getDocumentBase(), "tapeta.png");

            warstwa1 = getImage(getDocumentBase(), "warstwa1.png");

            warstwa2 = getImage(getDocumentBase(), "warstwa2.png");

            warstwa3 = getImage(getDocumentBase(), "warstwa3.png");

            warstwa4 = getImage(getDocumentBase(), "warstwa4.png");

            ludekB = getImage(getDocumentBase(), "ludekB.png");

        }


        WTH = warstwa1.getWidth(rootPane);

        HIT = warstwa1.getHeight(rootPane);

        [...]rysowanie mapki

        przyciski();

        //gDC.drawString(pokazprzycisk, 100, 100);

        gDC.drawString(przycisk+"", 120, 100);

        RysWojska(gDC);

        ManageWojska();

        gDC2.drawImage(offscreen,0,0,this);

    }


    public void update(Graphics g)

    {

          paint(g);

    }


    public void run(){



    }


    public void keyPressed(KeyEvent e) { przycisk = e.getKeyCode(); repaint();}

    public void keyReleased(KeyEvent e) {przycisk = e.getKeyCode(); repaint();}

    public void keyTyped(KeyEvent e) {przycisk = e.getKeyCode(); repaint();}

}

wyciąłem z kodu zbędne linijki (bo trochę jednak już napisałem) żeby było krócej.

Będę wdzięczny za pomoc!

A jakie to sposoby próbowałeś? W tych 10 nie było timera?

Aktualnie logikę masz uzależnioną od grafiki - oblicza logikę bezpośrednio przed rysowaniem. Musisz zrobić timera, który będzie wywoływał metodę obliczającą logikę co np. 10ms (da ci wtedy 100 FPS dla logiki) i na końcu żądającą przerysowania (repaint()).

Dobrze by też było wziąć pod uwagę zmienność czasu - timer o zegarze 10ms nie będzie się wykonywał zawsze co 10ms. Musisz pobierać milisekundy, obliczać różnicę między klatkami i użyć ich jako mnożnika przemieszczenia.

A co do obsługi klawiatury: Tworzysz tablicę booleanów (albo jednego inta, jak się umiesz bitami posługiwać) przechowującą stan kluczowych klawiszy (tych do poruszania się). W metodzie keyPressed ustawiasz wartość konkretnej komórki na true, a w keyReleased na false.

Przykład timera:

http://javaprogramming.awardspace.com/i … okaz=kurs9

Java nie jest dobrym początkiem do animacji, zwłaszcza jak się nie zna mechanizmów działania wysokopoziomowych GUI.