Specialeffekter och spelutveckling
i Java(TM) - Rymdpiraterna kommer!
av Anibal Wainstein
5.1.3 Rymdpiraterna kommer!
Nu
kommer du att märka att allt krångel med polisskeppets
rörelser kommer att löna sig. Rymdpiraterna kommer
att röra sig likadant och då kommer de där
rutinerna väl till pass. Animationen för piratskeppen
lagras i Image-arrayen "pirateship" och ser ut som
följande:
pirateship[0] |
pirateship[1] |
pirateship[2] |
pirateship[3] |
pirateship[4] |
 |
 |
 |
 |
 |
Som
du ser så är dom riktade åt andra hållet.
Självklart, vad trodde du? Ditt skepp är inte SÅ
skräckinjagande så att dom flyr för glatta
livet. Vi börjar med att lägga upp deklarationerna:
//I variabeln "pirateship" är animationen
//för piratskeppen lagrade.
Image pirateship[];
//Det behövs fyra int-arrayer för
//rymdpiraternas rörelser.
//"piratev" indikerar den vertikala hastigheten.
//"piratepy" indikerar den vertikala positionen.
//"piratepx" indikerar den horizontella positionen.
//"piratey" indikerar den vertikala positionen
//som piraten skall komma upp till efter en stund,
//dvs destinationen.
int piratev[],piratepy[],piratepx[],piratedy[];
//"maxpirates" indikerar hur många pirater som
// visas i skärmen samtidigt.
int maxpirates=3;
Eftersom
vi har flera pirater i rymden så måste vi ha arrayer
för att lagra rörelseegenskaperna för var och
en. Arrayen "piratev" motsvarar hastigheten "v"
hos polisskeppet. Den vertikala positionen "piratepy"
motsvarar "py" och "piratey" motsvarar
muspekarens position "y0". Nu måste vi också
ha en variabel för att lagra den horizontella positionen
hos piratskeppen, så vi lägger till arrayen "piratepx".
De här skeppen kommer att röra sig genom skärmen
mot polisskeppet. Genom att ändra på maxpirates
skall man kunna bestämma hur många pirater som
kan visas på skärmen samtidigt. I init() metoden
måste vi först lägga in funktionen för
att ladda in animationen. Lägg in följande rader
mellan inladdningen av "ground" och "try"
raden:
//Piratskeppen laddas in. De läggs i position 6
//och framåt på spåraren.
pirateship=new Image[5];
for (int i=0; i<5; i++)
{
pirateship[i]=getImage(getDocumentBase(),"pirateship"+i+".gif");
tracker.addImage(pirateship[i],i+6);
}
Observera
att vi har skrivit in "+6" så att piratskeppen
hamnar efter "ground" bilden i spåraren. Initieringen
av piratskeppen läggs in efter inladdningen av bilderna
och ser ut som följande:
//Max fyra pirater skall finnas på skärmen
//samtidigt.
piratev=new int[maxpirates];
piratepy=new int[maxpirates];
piratepx=new int[maxpirates];
piratedy=new int[maxpirates];
//Piratskeppen initieras.
for (int i=0; i<maxpirates; i++)
initPirateShip(i);
Metoden
initPirateShip() används för att initialisera piratskeppens
position och destination. Kommer du ihåg att när
vi skrev rutinerna för polisskeppets rörelser, så
använde vi oss av variabeln "y0" som vertikal
destination för skeppet? Vi kommer att använda samma
trick här, men nu bestäms den vertikala destinationen
av ett slumpvärde mellan 0 och 300 (300 är
höjden på appleten). Även startpunkten för
piratskeppet får ett slumpvärde. För att räkna
ut slumpvärdet använder vi random() metoden som
vi beskrev i kapitel4.
Metoden initPirateShip() ser ut så här:
public void initPirateShip(int n)
{
piratev[n]=0;
//De vertikala start- och destinationspunkterna
//får vara slumpmässiga.
piratepy[n]=(int) (Math.random()*300.0);
piratedy[n]=(int) (Math.random()*300.0);
//Också skeppets horizontella position är
//slumpmässig, fast vi lägger till ett värde
//så att skeppet startar alltid
//utanför appletskärmen.
piratepx[n]=(int) (Math.random()*300.0+400.0);
}
Det
börjar redan bli svårläst i run() metoden
och innan vi lägger in ännu mer rader får
vi rensa. Vi gör en egen metod av raderna som hanterar
polisskeppets rörelser. Detta kan vi göra utan risk
eftersom polisskeppets variabler är globala:
public void movePoliceShip()
{
//movePoliceShip() metoden hanterar
//polisskeppets rörelser.
if (y0-py>0)
{
v++;
if (y0-py<10) v=3;
if (y0-py<5) v=1;
}
if (y0-py<0)
{
v--;
if (y0-py>-10) v=-3;
if (y0-py>-5) v=-1;
}
if (y0-py==0) v=0;
if (v<-4) v=-4;
if (v>4) v=4;
py+=v;
}
För
att hantera piratskeppens rörelser så skapar vi
nu en liknande metod:
public void movePirateShips()
{
//movePirateShips() metoden hanterar
//piratskeppens rörelser.
for (int i=0; i<maxpirates; i++)
{
//Först tar man hand om de vertikala
//rörelserna. Dessa rutiner är
//identiska med polisskeppets men
//man använder arrayer istället.
if (piratedy[i]-piratepy[i]>0)
{
piratev[i]++;
if (piratedy[i]-piratepy[i]<10) piratev[i]=3;
if (piratedy[i]-piratepy[i]<5) piratev[i]=1;
}
if (piratedy[i]-piratepy[i]<0)
{
piratev[i]--;
if (piratedy[i]-piratepy[i]>-10) piratev[i]=-3;
if (piratedy[i]-piratepy[i]>-5) piratev[i]=-1;
}
if (piratedy[i]-piratepy[i]==0) piratev[i]=0;
if (piratev[i]<-4) piratev[i]=-4;
if (piratev[i]>4) piratev[i]=4;
piratepy[i]+=piratev[i];
//Nu räknar man ut det horizontella rörelserna.
//Om piratskeppet har åkt förbi polisskeppet så
//"skapa" ett nytt skepp.
if (piratepx[i]<-100) initPirateShip(i);
//Piratskeppen rör sig med hastigheten 4.
piratepx[i]-=4;
//Om slumpvärdet är mindre än 0.05 så räkna ut en
//ny vertikal destination.
if (Math.random()<0.05) piratedy[i]=(int) (Math.random()*300.0);
}
}
Som
du ser så är raderna som hanterar piratskeppens
vertikala rörelser nästan identiska med polisskeppets.
Skillnaden är att vi nu har en for-slinga som ser till
att alla piratskeppens variabler uppdateras. I metoden har
vi också lagt in rader för att skeppen ska röra
sig åt vänster med hastigheten 4. När skeppen
kommer utanför skärmen, dvs passerar polisskeppet,
så anropas initPirateShip() så att piratskeppet
får nya värden och placeras på andra sidan
skärmen. Detta ger spelaren intrycket att ett nytt skepp
är på ingång. Den sista raden används
för att räkna ut en ny vertikal destination för
skeppet. I praktiken kommer det att se ut som om en "osynlig
muspekare" klickar så att skeppet rör sig
sidledes. Detta händer bara när slumpvärdet
som räknas ut i if-satsen råkar vara mindre än
0.05 (som vi sa tidigare ger random() flyttalsvärden
mellan 0 och 1). Det betyder att det finns en 5% chans att
piratskeppen svänger i varje bildruta. Till sist tittar
vi också på run() metoden:
public void run()
{
while (true)
{
//Alla rader som hanterar polisskeppets
//metoder har flyttats ut till metoden
//movePoliceShip().
movePoliceShip();
//Metoden movePirateShips() hanterar
//piratskeppens rörelser.
movePirateShips();
groundposition-=2;
if (groundposition<-600) groundposition=0;
bufferg.drawImage(ground,groundposition,0,this);
if (groundposition<-200)
bufferg.drawImage(ground,(groundposition+600),0,this);
//For-slingan ritar ut alla piratskepp.
//Nu använder vi piratepx för att placera
//piratskeppen horizontellt.
for (int i=0; i<maxpirates; i++)
bufferg.drawImage(pirateship[2+piratev[i]/2]
,piratepx[i],-25+piratepy[i],this);
bufferg.drawImage(policeship[2+v/2],0,-55+py,this);
update(getGraphics());
try {Thread.sleep(sleeptime);}
catch(InterruptedException e) {}
}
}
Observera
att vi nu anropar movePoliceShip() och movePirateShips() i
början av run() metoden. Den nya for-slingan används
för att rita ut piratskeppen. Samma trick som i fallet
med polisskeppet används för att rita ut rätt
bild på piratskeppet. Den justeras också med 25
pixlar uppåt så att medelpunkten på piratskeppet
centreras kring "piratepy" positionen. Klicka
här för att se resultatet.
Nästa sida >>
|