Att göra en grundläggande 3D-motor i Java (3 / 5 steg)
Steg 3: Klassen Camera
Nu låt oss ta en omväg och ställa in klassen Camera. Klassen Camera håller reda på var spelaren ligger i 2D-kartan, och tar också hand om uppdatering av spelarens position. För att göra detta i klassen kommer att genomföra KeyListener, så det kommer att behöva importera KeyEvent och KeyListener.
importera java.awt.event.KeyEvent; < br > import java.awt.event.KeyListener;
Många variabler för att hålla reda på kamerans position och vad det kan se. På grund av detta första bit av klassen ser ut så här:
allmän klass kamera implementerar KeyListener {
offentliga dubbel xPos, yPos, xDir, yDir, xPlane, yPlane;
offentliga boolean vänster, höger, fram, tillbaka;
offentliga slutliga dubbel MOVE_SPEED =. 08;
offentliga slutliga dubbel ROTATION_SPEED =. 045;
xPos och yPos är platsen för spelaren på 2D-kartan som har skapats i klassen spel. xDir och yDir är x och y komponenter i en vektor som pekar i riktningen spelaren står inför. xPlane och yPlane är också x och y komponenter i en vektor. Vektorn definieras av xPlane och yPlane är alltid vinkelrät riktning vektorn och den pekar på den yttersta kanten av kamerans synfält på ena sidan. Längst kanten på andra sidan är bara negativa plan vektorn. Kombinationen av vektorn riktning och planet vektorn definierar vad som är i kamerans synfält. De booleska värden används för att hålla reda på vilka tangenter som trycks av användaren så att användaren kan flytta kameran. MOVE_SPEED och ROTATION_SPEED diktera hur snabbt kameran rör sig och vänder medan användaren är att trycka på motsvarande knapp.
Nästa är konstruktören. Konstruktören tar i värden som berättar för klassen där kameran ligger och vad det kan se och tilldelar dem till den motsvarande variabeln (xPos, yPos...).
offentliga kamera (double x, dubbla y, dubbel xd, dubbel yd, dubbel xp, dubbel yp)
{
xPos = x;
yPos = y;
xDir = xd;
yDir = yd;
xPlane = xp;
yPlane = yp;
}
En kamera objekt kommer att behövas i sista programmet, så låt oss gå vidare och Lägg till ett. I spelet klass med alla de andra variabeldeklarationer lägga till i
offentliga kamera kamera;
och i konstruktören lägger till i
kamera = ny kamera (4,5 4,5, 1, 0, 0,-. 66);
addKeyListener(camera);
Denna kamera kommer att arbeta med kartan jag använder, om du använder en annan karta eller justera värdena xPos och yPos (4 och 6 i mitt exempel) om du vill börja på en annan plats. Med hjälp av.66 ger vad jag känner är ett bra synfält, men du kan justera värdet för att få en olika FOV.
Nu när klassen Camera har en konstruktör kan vi börja lägga till metoder att spåra användaren ingångar och att uppdatera kamerans position/orientering. Eftersom klassen Camera implementerar KeyboardListener måste alla metoder från det genomförs. Eclipse bör automatiskt uppmana dig att lägga till dessa metoder. Du kan lämna den keyTyped metoden tomt, men de andra två metoderna ska användas. keyPressed ställer booleans till true när deras motsvarande tangenter trycks, och keyReleased kommer att ändra dem tillbaka till false när knapparna kommer. Metoderna som ser ut så här:
public void keyPressed (KeyEvent key) {
IF((Key.getKeyCode() == KeyEvent.VK_LEFT))
vänster = sant;
IF((Key.getKeyCode() == KeyEvent.VK_RIGHT))
höger = sant;
IF((Key.getKeyCode() == KeyEvent.VK_UP))
framåt = sant;
IF((Key.getKeyCode() == KeyEvent.VK_DOWN))
tillbaka = sant;
}
och
public void keyReleased (KeyEvent key) {
IF((Key.getKeyCode() == KeyEvent.VK_LEFT))
vänster = false;
IF((Key.getKeyCode() == KeyEvent.VK_RIGHT))
höger = false;
IF((Key.getKeyCode() == KeyEvent.VK_UP))
framåt = false;
IF((Key.getKeyCode() == KeyEvent.VK_DOWN))
tillbaka = false;
}
Nu när klassen Camera är att hålla spår som tangenter trycks ned kan vi börja uppdatera spelarens position. Att göra detta kommer vi att använda en uppdateringsmetod som kallas i metoden kör i klassen spel. Medan vi är på det vi ska gå vidare och lägga till kollision upptäckt metoden update genom att skicka kartan till den när den anropas i klassen spel. Metoden update ser ut så här:
public void uppdatera (int [] [] karta) {
IF(forward) {
IF(Map[(int) (xPos + xDir * MOVE_SPEED)] [(int) yPos] == 0) {
xPos += xDir * MOVE_SPEED;
}
IF(Map[(int)xPos][(int) (yPos + yDir * MOVE_SPEED)] == 0)
yPos += yDir * MOVE_SPEED;
}
IF(back) {
IF(Map[(int) (xPos - xDir * MOVE_SPEED)] [(int) yPos] == 0)
xPos-= xDir * MOVE_SPEED;
IF(Map[(int)xPos][(int) (yPos - yDir * MOVE_SPEED)] == 0)
yPos-= yDir * MOVE_SPEED;
}
IF(Right) {
Double oldxDir = xDir;
xDir=xDir*Math.cos(-ROTATION_SPEED) - yDir*Math.sin(-ROTATION_SPEED);
yDir=oldxDir*Math.sin(-ROTATION_SPEED) + yDir*Math.cos(-ROTATION_SPEED);
Double oldxPlane = xPlane;
xPlane=xPlane*Math.cos(-ROTATION_SPEED) - yPlane*Math.sin(-ROTATION_SPEED);
yPlane=oldxPlane*Math.sin(-ROTATION_SPEED) + yPlane*Math.cos(-ROTATION_SPEED);
}
IF(Left) {
Double oldxDir = xDir;
xDir=xDir*Math.cos(ROTATION_SPEED) - yDir*Math.sin(ROTATION_SPEED);
yDir=oldxDir*Math.sin(ROTATION_SPEED) + yDir*Math.cos(ROTATION_SPEED);
Double oldxPlane = xPlane;
xPlane=xPlane*Math.cos(ROTATION_SPEED) - yPlane*Math.sin(ROTATION_SPEED);
yPlane=oldxPlane*Math.sin(ROTATION_SPEED) + yPlane*Math.cos(ROTATION_SPEED);
}
}
De delar av metoden som kontroll framåt och bakåt rörelse arbete genom att lägga xDir och yDir till xPos och yPos, respektive. Innan denna rörelse händer kontrolleras om rörelsen kommer att sätta kameran inuti en vägg, och inte gå igenom med rörelse om det kommer. För rotation både riktning vektorn och planet vektor multipliceras med rotation matrix, som är:
[cos(ROTATION_SPEED)-sin(ROTATION_SPEED)]
[sin(ROTATION_SPEED) cos(ROTATION_SPEED)]
för att få deras nya värden. Med metoden update avslutade kan vi nu kalla det från klassen spel. I spelet klassens kör metoden tillägga den följande lina av koden där det visas här
Lägg till detta:
Camera.Update(Map);
i här:
While(Running) {
länge nu = System.nanoTime();
delta = delta + ((now-lastTime) / ns);
lastTime = nu;
medan (delta > = 1) //Make säker uppdatering sker endast 60 gånger per sekund
{
hanterar all logik begränsad tid
Camera.Update(Map);
delta--;
}
Render (), //displays till dess att skärmen obegränsad
}
Nu när det är gjort kan vi äntligen gå vidare till den sista klassen och beräkna skärmen!