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:
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?
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());
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.
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.
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.