Specialeffekter och spelutveckling
i Java(TM) - Dubbelbuffring
av Anibal Wainstein
4.2 Dubbelbuffring
Dubbelbuffring är en teknik som har använts
i nästan alla programmeringsspråk av spelutvecklare
och specialeffektsprogrammerare. När man ritar linjer,
rektanglar, texter och bilder direkt på skärmen
så kan man i princip se när varje objekt ritas
ut. Detta är inte önskvärt om man bara vill
att åskådaren ska se slutresultatet, och som vi
har sett med textscroller
och slideshow exemplen så kan
detta leda till flimmer. För att undvika detta så
ritar man först i en buffert (därav namnet "dubbelbuffring").
Bufferten kan vara en bild som man ritar på i minnet
och visar inte upp den för åskådaren förrän
den är färdig. I Java gör man detta genom att
skapa en bild som är lika stor som appleten och sedan
hämtar man ett Graphics-objekt som är kopplad till
denna. När man har ritat klart så anropar man paint()
metoden som ritar ut buffertbilden på skärmen.
4.2.1 SlideShow
II, nu utan flimmer
För att dubbelbuffra slideshow appleten
i förra avsnittet så måste vi först
deklarera en global Image variabel och en Graphics variabel
som vi initierar i init() metoden. Lägg till följande
variabler till de globala appletvariablerna (lägg in
dem under deklarationen för variabeln "nextimagepositiony"):
Image bufferimage;
Graphics bufferg;
//"delay" får användas istället för sleeptime för att
//fördröja varje animering. "sleeptime kommer att användas
//för att lägga en konfigurerbar fördröjning mellan varje
//bild istället.
int delay=0;
När vi ändå är på
gång att ändra i appleten så kan vi passa
på att lägga till en ny parameter "delay".
Denna kommer att användas i stället för "sleeptime"
som fördröjning i animationen. Variabeln "sleeptime"
kommer att användas som fördröjning mellan
varje bild i stället. Nu kommer änvändaren
av denna applet att kunna lägga in en fördröjning
innan nästa bild rullar in. För att skapa bufferten
så skriver vi följande rader och lägger in
dem sist i init() metoden:
//Hämta storleken för appleten
Dimension d=size();
//createImage() skapar en tom bild
//som är lika stor som appletskärmen
bufferimage=createImage(d.width,d.height);
//bufferg kopplas nu till bufferbilden
bufferg=bufferimage.getGraphics();
delay=getIntegerParameter("delay",10);
Det enda vi behöver göra nu är
att se till att de två bilderna ritas ut i bufferten
först och inte direkt på skärmen. Detta görs
i paint() metoden:
public synchronized void paint(Graphics g)
{
//först kontrollerar vi att bufferg
//är initierat, det är inte alltid säkert
//att den är det.
if (bufferg!=null)
{
//vi ritar de två bilderna i bufferten först
bufferg.drawImage(images[currentimage],0,0,this);
bufferg.drawImage(images[nextimage]
,nextimagexposition,nextimageyposition,this);
//nu ritar vi ut bufferten i appletskärmen
g.drawImage(bufferimage,0,0,this);
}
}
Det finns lite ändringar att göra
i run() metoden också, nu när vi har ändrat
på parametrarna:
public void run()
{
Dimension d=size();
int displacementx=0;
int displacementy=0;
int pathsize=0;
currentimage=0;
nextimage=1;
while (true)
{
int directionx=(int) (Math.random()*3.0)-1;
int directiony=(int) (Math.random()*3.0)-1;
if (directionx==0 && directiony==0) directiony=1;
if (d.width<d.height) pathsize=d.width;
else pathsize=d.height;
displacementx=directionx*d.width;
displacementy=directiony*d.height;
if (nextimage>maxitems-1) nextimage=0;
for (int i=0; i<=pathsize; i++)
{
nextimagexposition=displacementx
-directionx*(i*d.width)/pathsize;
nextimageyposition=displacementy
-directiony*(i*d.height)/pathsize;
update(getGraphics());
//nu är det "delay" som är fördröjningen
//i for-slingan.
try {Thread.sleep(delay);}
catch(InterruptedException e) {}
}
//"sleeptime" används utanför slingan
try {Thread.sleep(sleeptime);}
catch(InterruptedException e) {}
currentimage=nextimage;
nextimage++;
if (nextimage>maxitems-1) nextimage=0;
}
}
Vi lägger upp en ny fördröjning
utanför for-slingan och använder "sleeptime"
variabeln där istället. Nu kan appletanvändaren
specifiera en fördröjning innan nästa bild
börjar rulla in. Nu borde appleten vara helt färdig.
Glöm nu inte att lägga in parametern "delay"
och sätta denna till 20. Ändra om sleeptime till
1000 millisekunder eller mer. Klicka
här för att titta på den. Visst är
den vacker?
Nästa sida >>
|