步驟1:主類
首先要做的是被造是一個(gè)主要的階級(jí)。主類將處理向用戶顯示圖像,調(diào)用其他類以重新計(jì)算應(yīng)向播放器顯示的內(nèi)容以及更新相機(jī)的位置。
對(duì)于該類,導(dǎo)入將是:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.util.ArrayList;
import javax.swing.JFrame;
該類及其變量將如下所示:
public class Game extends JFrame implements Runnable{
private static final long serialVersionUID = 1L;
public int mapWidth = 15;
public int mapHeight = 15;
private Thread thread;
private boolean running;
private BufferedImage image;
public int[] pixels;
public static int[][] map =
{
{1,1,1,1,1,1,1,1,2,2,2,2,2,2,2},
{1,0,0,0,0,0,0,0,2,0,0,0,0,0,2},
{1,0,3,3,3,3,3,0,0,0,0,0,0,0,2},
{1,0,3,0,0,0,3,0,2,0,0,0,0,0,2},
{1,0,3,0,0,0,3,0,2,2,2,0,2,2,2},
{1,0,3,0,0,0,3,0,2,0,0,0,0,0,2},
{1,0,3,3,0,3,3,0,2,0,0,0,0,0,2},
{1,0,0,0,0,0,0,0,2,0,0,0,0,0,2},
{1,1,1,1,1,1,1,1,4,4,4,0,4,4,4},
{1,0,0,0,0,0,1,4,0,0,0,0,0,0,4},
{1,0,0,0,0,0,1,4,0,0,0,0,0,0,4},
{1,0,0,2,0,0,1,4,0,3,3,3,3,0,4},
{1,0,0,0,0,0,1,4,0,3,3,3,3,0,4},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,4},
{1,1,1,1,1,1,1,4,4,4,4,4,4,4,4}
};
請注意,可以將地圖重新配置為所需的內(nèi)容,我在這里只是一個(gè)樣品。地圖上的數(shù)字表示該位置的墻壁類型。 0代表空白空間,而其他任何數(shù)字則代表實(shí)心墻和隨之而來的紋理。 BufferedImage是顯示給用戶的,像素是圖像中所有像素的數(shù)組。其他變量實(shí)際上不會(huì)再次出現(xiàn),它們只是用來使圖形和程序正常工作。
構(gòu)造函數(shù)現(xiàn)在看起來像這樣:
public Game() {
thread = new Thread(this);
image = new BufferedImage(640, 480, BufferedImage.TYPE_INT_RGB);
pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
setSize(640, 480);
setResizable(false);
setTitle(“3D Engine”);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBackground(Color.black);
setLocationRelativeTo(null);
setVisible(true);
start();
}
大多數(shù)只是類變量和框架的初始化。 “ pixels =“之后的代碼連接像素和圖像,以便每當(dāng)更改像素中的數(shù)據(jù)值時(shí),向用戶顯示圖像時(shí)就會(huì)在圖像上顯示相應(yīng)的更改。
start和stop方法是簡單并用于確保程序安全地開始和結(jié)束。
private synchronized void start() {
running = true;
thread.start();
}
public synchronized void stop() {
running = false;
try {
thread.join();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
Game類中需要的最后兩個(gè)方法是render和run方法。渲染方法將如下所示:
public void render() {
BufferStrategy bs = getBufferStrategy();
if(bs == null) {
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
bs.show();
}
渲染時(shí)使用緩沖策略,以使屏幕更新更加流暢。總體而言,使用緩沖策略只會(huì)幫助游戲在運(yùn)行時(shí)看起來更好。為了將圖像實(shí)際繪制到屏幕上,需要從緩沖策略中獲取圖形對(duì)象并用于繪制圖像。
run方法非常重要,因?yàn)樗梢蕴幚沓绦虿煌糠值母骂l率。為此,它使用一些代碼來跟蹤何時(shí)經(jīng)過了1/60秒,以及何時(shí)更新了屏幕和攝像機(jī)。這樣可以提高程序運(yùn)行的流暢度。 run方法如下所示:
public void run() {
long lastTime = System.nanoTime();
final double ns = 1000000000.0 / 60.0;//60 times per second
double delta = 0;
requestFocus();
while(running) {
long now = System.nanoTime();
delta = delta + ((now-lastTime) / ns);
lastTime = now;
while (delta 》= 1)//Make sure update is only happening 60 times a second
{
//handles all of the logic restricted time
delta--;
}
render();//displays to the screen unrestricted time
}
}
一旦所有這些方法,構(gòu)造函數(shù)和變量都在其中,那么當(dāng)前在Game類中剩下要做的唯一事情就是添加一個(gè)main方法。主要方法非常簡單,您要做的就是:
public static void main(String [] args) {
Game game = new Game();
}
現(xiàn)在,主類已完成!如果您現(xiàn)在運(yùn)行該程序,則將彈出黑屏。
步驟2:紋理類
在進(jìn)入查找屏幕外觀的計(jì)算之前,我將繞行并設(shè)置Texture類。紋理將應(yīng)用于環(huán)境中的各種墻壁,并將來自保存在項(xiàng)目文件夾中的圖像。在圖像中,我包含了在網(wǎng)上找到的4個(gè)紋理,將在該項(xiàng)目中使用。您可以使用任何想要的紋理。要使用這些紋理,我建議將它們放在項(xiàng)目文件中的文件夾中。為此,請轉(zhuǎn)到項(xiàng)目文件夾(在Eclipse中,它位于工作區(qū)文件夾中)。轉(zhuǎn)到項(xiàng)目文件夾后,創(chuàng)建一個(gè)名為“ res”或其他名稱的新文件夾。將紋理放在此文件夾中。您可以將紋理放置在其他地方,這就是我存儲(chǔ)紋理的地方。完成此操作后,我們就可以開始編寫代碼以使紋理可用。
該類的導(dǎo)入為:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
該類頭及其變量將看起來像這樣:
public class Texture {
public int[] pixels;
private String loc;
public final int SIZE;
數(shù)組像素用于保存紋理圖像中所有像素的數(shù)據(jù)。 Loc用于向計(jì)算機(jī)指示可以找到紋理的圖像文件的位置。 SIZE是一側(cè)的紋理大小(64x64圖像的大小為64),并且所有紋理將完全為正方形。
構(gòu)造函數(shù)將初始化loc和SIZE變量并調(diào)用a方法來將圖像數(shù)據(jù)加載到像素中。看起來像這樣:
public Texture(String location, int size) {
loc = location;
SIZE = size;
pixels = new int[SIZE * SIZE];
load();
}
現(xiàn)在,Texture類剩下的就是添加一個(gè)load方法來從圖像中獲取數(shù)據(jù)并將它們存儲(chǔ)在像素?cái)?shù)據(jù)數(shù)組中。此方法將如下所示:
private void load() {
try {
BufferedImage image = ImageIO.read(new File(loc));
int w = image.getWidth();
int h = image.getHeight();
image.getRGB(0, 0, w, h, pixels, 0, w);
} catch (IOException e) {
e.printStackTrace();
}
}
load方法的工作原理是從loc指向的文件中讀取數(shù)據(jù)并將該數(shù)據(jù)寫入緩沖的圖像。然后,從緩沖的圖像中獲取每個(gè)像素的數(shù)據(jù),并將其存儲(chǔ)在像素中。
此時(shí),Texture類已完成,因此我將繼續(xù)定義一些將要使用的紋理在最終程序中。為此,請將此
public static Texture wood = new Texture(“res/wood.png”, 64);
public static Texture brick = new Texture(“res/redbrick.png”, 64);
public static Texture bluestone = new Texture(“res/bluestone.png”, 64);
public static Texture stone = new Texture(“res/greystone.png”, 64);
放在“公共類Texture”行和“ public int []像素”之間。
使其余部分可以訪問這些紋理該程序讓我們繼續(xù)前進(jìn),并將其交給Game類。為此,我們將需要一個(gè)ArrayList來容納所有紋理,并且需要將紋理添加到此ArrayList中。要?jiǎng)?chuàng)建ArrayList,請將以下代碼行和變量放在類的頂部附近:
public ArrayList textures;
此ArrayList必須在構(gòu)造函數(shù)中初始化,并且還應(yīng)添加紋理在構(gòu)造函數(shù)中。在構(gòu)造函數(shù)中添加以下代碼:
textures = new ArrayList();
textures.add(Texture.wood);
textures.add(Texture.brick);
textures.add(Texture.bluestone);
textures.add(Texture.stone);
現(xiàn)在可以使用紋理了!
第3步:相機(jī)類
現(xiàn)在讓我們繞道而行并設(shè)置Camera類。 Camera類跟蹤玩家在2D地圖中的位置,并負(fù)責(zé)更新玩家的位置。為此,該類將實(shí)現(xiàn)KeyListener,因此將需要導(dǎo)入KeyEvent和KeyListener。
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
需要許多變量來跟蹤攝像機(jī)的位置及其所見。因此,該類的第一個(gè)塊如下所示:
public class Camera implements KeyListener {
public double xPos, yPos, xDir, yDir, xPlane, yPlane;
public boolean left, right, forward, back;
public final double MOVE_SPEED = .08;
public final double ROTATION_SPEED = .045;
xPos和yPos是玩家在Game類中創(chuàng)建的2D地圖上的位置。 xDir和yDir是指向玩家所面對(duì)方向的向量的x和y分量。 xPlane和yPlane也是向量的x和y分量。 xPlane和yPlane定義的向量始終垂直于方向向量,并且在一側(cè)指向相機(jī)視場的最遠(yuǎn)邊緣。另一邊最遠(yuǎn)的邊緣就是負(fù)平面向量。方向矢量和平面矢量的組合定義了相機(jī)視場中的內(nèi)容。布爾值用于跟蹤用戶按下了哪些鍵,以便用戶可以移動(dòng)相機(jī)。 MOVE_SPEED和ROTATION_SPEED指示在用戶按下相應(yīng)鍵時(shí)相機(jī)移動(dòng)和旋轉(zhuǎn)的速度。
接下來是構(gòu)造函數(shù)。構(gòu)造函數(shù)接受告訴類的位置的值,并將相機(jī)分配給相應(yīng)的變量(xPos,yPos 。..)。
public Camera(double x, double y, double xd, double yd, double xp, double yp)
{
xPos = x;
yPos = y;
xDir = xd;
yDir = yd;
xPlane = xp;
yPlane = yp;
}
相機(jī)對(duì)象在最終程序中將需要它,所以讓我們繼續(xù)添加一個(gè)。在具有所有其他變量聲明的Game類中,添加
public Camera camera;
,并在構(gòu)造函數(shù)中添加
camera = new Camera(4.5, 4.5, 1, 0, 0, -.66);
addKeyListener(camera);
,此攝像機(jī)將與地圖一起使用我正在使用,如果您使用的是其他地圖,或者想從其他位置開始,請調(diào)整xPos和yPos的值(在我的示例中為4和6)。使用.66可以提供良好的視野,但是您可以調(diào)整該值以獲得不同的FOV。
現(xiàn)在,Camera類具有構(gòu)造函數(shù),我們可以開始添加方法來跟蹤用戶的輸入并更新相機(jī)的位置/方向。因?yàn)镃amera類實(shí)現(xiàn)了KeyboardListener,所以它必須具有其實(shí)現(xiàn)的所有方法。 Eclipse應(yīng)該自動(dòng)提示您添加這些方法。您可以將keyTyped方法保留為空白,但將使用其他兩種方法。當(dāng)按下相應(yīng)的鍵時(shí),keyPressed會(huì)將布爾值設(shè)置為true,而釋放鍵時(shí),keyReleased會(huì)將其更改為false。方法看起來像這樣:
public void keyPressed(KeyEvent key) {
if((key.getKeyCode() == KeyEvent.VK_LEFT))
left = true;
if((key.getKeyCode() == KeyEvent.VK_RIGHT))
right = true;
if((key.getKeyCode() == KeyEvent.VK_UP))
forward = true;
if((key.getKeyCode() == KeyEvent.VK_DOWN))
back = true;
}
和
public void keyReleased(KeyEvent key) {
if((key.getKeyCode() == KeyEvent.VK_LEFT))
left = false;
if((key.getKeyCode() == KeyEvent.VK_RIGHT))
right = false;
if((key.getKeyCode() == KeyEvent.VK_UP))
forward = false;
if((key.getKeyCode() == KeyEvent.VK_DOWN))
back = false;
}
現(xiàn)在,Camera類正在跟蹤按下了哪些鍵,我們可以開始更新播放器的位置。為此,我們將使用在Game類的run方法中調(diào)用的update方法。在此過程中,我們將繼續(xù)進(jìn)行操作,并通過在Game類中將地圖傳遞給update方法時(shí),將沖突檢測添加到update方法中。更新方法如下所示:
public void update(int[][] map) {
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);
}
}
該方法中控制前進(jìn)和后退運(yùn)動(dòng)的部分通過分別向xPos和yPos添加xDir和yDir來工作。在此動(dòng)作發(fā)生之前,程序會(huì)檢查該動(dòng)作是否會(huì)將相機(jī)放置在墻內(nèi),如果可以,則不進(jìn)行檢查。對(duì)于旋轉(zhuǎn),方向矢量和平面矢量都乘以旋轉(zhuǎn)矩陣,即:
[ cos(ROTATION_SPEED) -sin(ROTATION_SPEED) ]
[ sin(ROTATION_SPEED) cos(ROTATION_SPEED) ]
以獲得其新值。完成update方法后,我們現(xiàn)在可以從Game類中調(diào)用它。在Game類的run方法中,添加以下代碼行,在此處顯示
Add this:
camera.update(map);
in here:
while(running) {
long now = System.nanoTime();
delta = delta + ((now-lastTime) / ns);
lastTime = now;
while (delta 》= 1)//Make sure update is only happening 60 times a second
{
//handles all of the logic restricted time
camera.update(map);
delta--;
}
render();//displays to the screen unrestricted time
}
現(xiàn)在,完成了,我們終于可以進(jìn)入最終類并計(jì)算屏幕了!
第4步:計(jì)算屏幕
在Screen類中,大部分的計(jì)算都是為了使程序正常工作。要工作,該類需要以下導(dǎo)入:
import java.util.ArrayList;
import java.awt.Color;
實(shí)際的類是這樣開始的:
public class Screen {
public int[][] map;
public int mapWidth, mapHeight, width, height;
public ArrayList textures;
該地圖與在游戲類。屏幕使用它來確定墻壁在哪里以及與玩家之間的距離。寬度和高度定義屏幕的大小,并且應(yīng)始終與Game類中創(chuàng)建的框架的寬度和高度相同。紋理是所有紋理的列表,以便屏幕可以訪問紋理的像素。在聲明了這些變量之后,必須像下面這樣在構(gòu)造函數(shù)中對(duì)其進(jìn)行初始化:
public Screen(int[][] m, ArrayList tex, int w, int h) {
map = m;
textures = tex;
width = w;
height = h;
}
現(xiàn)在是時(shí)候編寫類具有的一個(gè)方法了:update方法。更新方法根據(jù)用戶在地圖中的位置重新計(jì)算屏幕的外觀。該方法被不斷調(diào)用,并將更新后的像素?cái)?shù)組返回給Game類。該方法開始于“清除”屏幕。通過將上半部分的所有像素設(shè)置為一種顏色,并將下半部分的所有像素設(shè)置為另一種顏色來實(shí)現(xiàn)此目的。
public int[] update(Camera camera, int[] pixels) {
for(int n=0; n if(pixels[n] != Color.DARK_GRAY.getRGB()) pixels[n] = Color.DARK_GRAY.getRGB();
}
for(int i=pixels.length/2; i if(pixels[i] != Color.gray.getRGB()) pixels[i] = Color.gray.getRGB();
}
讓屏幕的頂部和底部為兩個(gè)不同顏色也使它看起來好像有地板和天花板。清除像素陣列后,該是進(jìn)行主要計(jì)算的時(shí)候了。該程序循環(huán)遍歷屏幕上的每個(gè)垂直條,并投射光線以找出該垂直條上的屏幕上應(yīng)該有什么墻。循環(huán)的開始看起來像這樣:
for(int x=0; xdouble cameraX = 2 * x / (double)(width) -1;
double rayDirX = camera.xDir + camera.xPlane * cameraX;
double rayDirY = camera.yDir + camera.yPlane * cameraX;
//Map position
int mapX = (int)camera.xPos;
int mapY = (int)camera.yPos;
//length of ray from current position to next x or y-side
double sideDistX;
double sideDistY;
//Length of ray from one side to next in map
double deltaDistX = Math.sqrt(1 + (rayDirY*rayDirY) / (rayDirX*rayDirX));
double deltaDistY = Math.sqrt(1 + (rayDirX*rayDirX) / (rayDirY*rayDirY));
double perpWallDist;
//Direction to go in x and y
int stepX, stepY;
boolean hit = false;//was a wall hit
int side=0;//was the wall vertical or horizontal
這里發(fā)生的所有事情都是計(jì)算出循環(huán)其余部分將要使用的一些變量。 CameraX是攝影機(jī)平面上當(dāng)前垂直條紋的x坐標(biāo),并且rayDir變量為射線創(chuàng)建矢量。計(jì)算所有以DistX或DistY結(jié)尾的變量,以便程序僅在可能發(fā)生碰撞的位置檢查碰撞。 perpWallDist是從播放器到射線與之碰撞的第一堵墻的距離。這將在以后計(jì)算。完成此操作后,我們需要根據(jù)已經(jīng)計(jì)算出的變量來找出其他一些變量。
//Figure out the step direction and initial distance to a side
if (rayDirX 《 0)
{
stepX = -1;
sideDistX = (camera.xPos - mapX) * deltaDistX;
}
else
{
stepX = 1;
sideDistX = (mapX + 1.0 - camera.xPos) * deltaDistX;
}
if (rayDirY 《 0)
{
stepY = -1;
sideDistY = (camera.yPos - mapY) * deltaDistY;
}
else
{
stepY = 1;
sideDistY = (mapY + 1.0 - camera.yPos) * deltaDistY;
}
一旦完成,就該找出射線與何處碰撞了。一堵墻。為此,程序要經(jīng)過一個(gè)循環(huán),在該循環(huán)中檢查射線是否與墻壁接觸,如果沒有,則移動(dòng)到下一個(gè)可能的碰撞點(diǎn),然后再次檢查。
//Loop to find where the ray hits a wall
while(!hit) {
//Jump to next square
if (sideDistX 《 sideDistY)
{
sideDistX += deltaDistX;
mapX += stepX;
side = 0;
}
else
{
sideDistY += deltaDistY;
mapY += stepY;
side = 1;
}
//Check if ray has hit a wall
if(map[mapX][mapY] 》 0) hit = true;
}
現(xiàn)在我們知道射線在何處撞擊墻壁,我們可以開始計(jì)算墻壁在我們當(dāng)前所在的垂直條紋中的外觀。為此,我們首先計(jì)算到墻的距離,然后使用該距離來計(jì)算出墻在垂直條中應(yīng)該有多高。然后,我們根據(jù)屏幕上的像素將該高度轉(zhuǎn)換為起點(diǎn)和終點(diǎn)。代碼如下所示:
//Calculate distance to the point of impact
if(side==0)
perpWallDist = Math.abs((mapX - camera.xPos + (1 - stepX) / 2) / rayDirX);
else
perpWallDist = Math.abs((mapY - camera.yPos + (1 - stepY) / 2) / rayDirY);
//Now calculate the height of the wall based on the distance from the camera
int lineHeight;
if(perpWallDist 》 0) lineHeight = Math.abs((int)(height / perpWallDist));
else lineHeight = height;
//calculate lowest and highest pixel to fill in current stripe
int drawStart = -lineHeight/2+ height/2;
if(drawStart 《 0)
drawStart = 0;
int drawEnd = lineHeight/2 + height/2;
if(drawEnd 》= height)
drawEnd = height - 1;
計(jì)算完之后,就該開始從墻的紋理中找出哪些像素會(huì)真正呈現(xiàn)給用戶了。為此,我們首先必須確定與剛擊中的墻關(guān)聯(lián)的紋理,然后確定將向用戶顯示的像素的紋理的x坐標(biāo)。
//add a texture
int texNum = map[mapX][mapY] - 1;
double wallX;//Exact position of where wall was hit
if(side==1) {//If its a y-axis wall
wallX = (camera.xPos + ((mapY - camera.yPos + (1 - stepY) / 2) / rayDirY) * rayDirX);
} else {//X-axis wall
wallX = (camera.yPos + ((mapX - camera.xPos + (1 - stepX) / 2) / rayDirX) * rayDirY);
}
wallX-=Math.floor(wallX);
//x coordinate on the texture
int texX = (int)(wallX * (textures.get(texNum).SIZE));
if(side == 0 && rayDirX 》 0) texX = textures.get(texNum).SIZE - texX - 1;
if(side == 1 && rayDirY 《 0) texX = textures.get(texNum).SIZE - texX - 1;
通過獲取在2D地圖上擊中墻壁的確切位置并減去整數(shù)值(僅保留小數(shù))來計(jì)算x坐標(biāo)。然后將此小數(shù)(wallX)乘以墻的紋理大小即可在我們希望繪制的像素的墻上獲得確切的x坐標(biāo)。一旦我們知道剩下要做的就是計(jì)算紋理上像素的y坐標(biāo)并將其繪制在屏幕上。為此,我們遍歷垂直條帶中屏幕上的所有像素,然后對(duì)其進(jìn)行計(jì)算并計(jì)算紋理上像素的確切y坐標(biāo)。然后,使用該程序,程序?qū)⒓y理中像素的數(shù)據(jù)寫入屏幕上的像素陣列。該程序還使此處的水平墻比垂直墻暗,以提供基本的照明效果。
//calculate y coordinate on texture
for(int y=drawStart; y int texY = (((y*2 - height + lineHeight) 《《 6) / lineHeight) / 2;
int color;
if(side==0) color = textures.get(texNum).pixels[texX + (texY * textures.get(texNum).SIZE)];
else color = (textures.get(texNum).pixels[texX + (texY * textures.get(texNum).SIZE)]》》1) & 8355711;//Make y sides darker
pixels[x + y*(width)] = color;
}
然后,Screen類中剩下的就是返回像素?cái)?shù)組
return pixels;
該類完成。現(xiàn)在,我們要做的就是在Game類中添加幾行代碼以使屏幕正常運(yùn)行。在變量頂部添加以下內(nèi)容:
public Screen screen;
,然后在構(gòu)造函數(shù)中,在初始化紋理之后,將其添加到某處。
screen = new Screen(map, mapWidth, mapHeight, textures, 640, 480);
最后,在在camera.update(map)之前運(yùn)行運(yùn)行方法add
screen.update(camera, pixels);
。程序就完成了!
步驟5:最終代碼
責(zé)任編輯:wv
-
JAVA
+關(guān)注
關(guān)注
19文章
2971瀏覽量
104854 -
3D引擎
+關(guān)注
關(guān)注
0文章
6瀏覽量
8180
發(fā)布評(píng)論請先 登錄
相關(guān)推薦
評(píng)論