gpt4 book ai didi

基于 Java Tile 的游戏性能

转载 作者:行者123 更新时间:2023-11-30 11:46:00 26 4
gpt4 key购买 nike

我目前正在用 Java 试验基于 2D tile 的横向卷轴游戏,主要基于 David Brackeen 的“Developing Games in Java”中的代码和示例

目前 map 文件的大小为 100x100 block (每个 block 为 64x64 像素)。我已经将系统配置为仅显示玩家可见的图 block 。 Graphics 系统由一个 ScreenManager 类管理,该类返回当前 BufferStrategy 的图形对象,如下所示:

屏幕管理器.java

private GraphicsDevice device;

...

/**
* Gets the graphics context for the display. The
* ScreenManager uses double buffering, so applications must
* call update() to show any graphics drawn.
* <p>
* The application must dispose of the graphics object.
*/
public Graphics2D getGraphics(){
Window window = device.getFullScreenWindow();
if(window != null){
BufferStrategy strategy = window.getBufferStrategy();
return (Graphics2D)strategy.getDrawGraphics();
}
else{
return null;
}
}

来自此 ScreenManager 的图形在游戏循环中传递到 TreeRenderer 的绘制方法之后。

TreeMapRenderer.java

/**
Draws the specified TileMap.
*/
public void draw(Graphics2D g, TileMap map,
int screenWidth, int screenHeight, float fr)
{
Sprite player = map.getPlayer();
int mapWidth = tilesToPixels(map.getWidth());
int mapHeight = tilesToPixels(map.getHeight());

// get the scrolling position of the map
// based on player's position
int offsetX = screenWidth / 2 -
Math.round(player.getX()) - TILE_SIZE;
offsetX = Math.min(offsetX, 0);
offsetX = Math.max(offsetX, screenWidth - mapWidth);

// get the y offset to draw all sprites and tiles
int offsetY = screenHeight /2 -
Math.round(player.getY()) - TILE_SIZE;
offsetY = Math.min(offsetY,0);
offsetY = Math.max(offsetY, screenHeight - mapHeight);

// draw the visible tiles
int firstTileY = pixelsToTiles(-offsetY);
int lastTileY = firstTileY + pixelsToTiles(screenHeight) +1;

int firstTileX = pixelsToTiles(-offsetX);
int lastTileX = firstTileX +
pixelsToTiles(screenWidth) + 1;

//HERE IS WHERE THE SYSTEM BOGS dOWN (checking ~280 tiles per iteration)
for (int y=firstTileY; y<lastTileY; y++) {
for (int x=firstTileX; x <= lastTileX; x++) {
if(map.getTile(x, y) != null){
Image image = map.getTile(x, y).getImage();
if (image != null) {
g.drawImage(image,
tilesToPixels(x) + offsetX,
tilesToPixels(y) + offsetY,
null);
}
}
}
}

// draw player
g.drawImage(player.getImage(),
Math.round(player.getX()) + offsetX,
Math.round(player.getY()) + offsetY,
null);

该算法可以正确地为 X 轴和 Y 轴选择正确的 FROM 和 TO 值,从 10000 到 ~285 之间剔除所需的图 block 。

我的问题是即使这样,游戏在渲染图 block 时也只能以大约 8-10 FPS 的速度运行。如果我关闭 tile 渲染,系统会以 80 FPS 运行(当无事可做时很容易快速运行)

您对如何加快这一过程有什么想法吗?我希望看到至少在 30 FPS 左右的东西才能让它可以玩。

最后,虽然我愿意使用第 3 方库来做到这一点,但我想在承认失败之前尝试自己实现这个逻辑。

编辑:
根据此处的要求,提供了关于如何调用 Image image = map.getTile(x, y).getImage(); 的额外信息。

这里的 map 来自下面的TileMap类

TileMap.java

public class TileMap {

private Tile[][] tiles;
private LinkedList sprites;
private Sprite player;
private GraphicsConfiguration gc;

/**
Creates a new TileMap with the specified width and
height (in number of tiles) of the map.
*/
public TileMap(GraphicsConfiguration gc, int width, int height) {
this.gc = gc;
tiles = new Tile[width][height];
overlayer = new Tile[width][height];
sprites = new LinkedList();
}


/**
Gets the width of this TileMap (number of tiles across).
*/
public int getWidth() {
return tiles.length;
}


/**
Gets the height of this TileMap (number of tiles down).
*/
public int getHeight() {
return tiles[0].length;
}


/**
Gets the tile at the specified location. Returns null if
no tile is at the location or if the location is out of
bounds.
*/
public Tile getTile(int x, int y) {
if (x < 0 || x >= getWidth() ||
y < 0 || y >= getHeight())
{
return null;
}
else {
return tiles[x][y];
}
}


/**
* Helper method to set a tile. If blocking is not defined than it is set to false.
*
* @param x
* @param y
* @param tile
*/
public void setTile(int x, int y,Image tile){
this.setTile(x,y,tile,false);
}

/**
Sets the tile at the specified location.
*/
public void setTile(int x, int y, Image tile, boolean blocking) {
if(tiles[x][y] == null){
Tile t = new Tile(gc, tile, blocking);
tiles[x][y] = t;
}
else{
tiles[x][y].addImage(tile);
tiles[x][y].setBlocking(blocking);
}
}

...

此处的 Tile 是以下代码的实例。本质上,此类仅包含图像,可以通过始终使用 gc.createCompatibleImage(w, h, Transparency.TRANSLUCENT) 添加覆盖层来对其进行更新;和一个 boolean 值来判断它是否会阻止玩家。传入的图像也是以这种方式创建的。

瓷砖.java

public class Tile {
private Image image;
private boolean blocking = false;
private GraphicsConfiguration gc;

/**
* Creates a new Tile to be used with a TileMap
* @param image The base image for this Tile
* @param blocking Will this tile allow the user to walk over/through
*/
public Tile(GraphicsConfiguration gc, Image image, boolean blocking){
this.gc = gc;
this.image = image;
this.blocking = blocking;
}

public Tile(GraphicsConfiguration gc, Image image){
this.gc = gc;
this.image = image;
this.blocking = false;
}

/**
Creates a duplicate of this animation. The list of frames
are shared between the two Animations, but each Animation
can be animated independently.
*/
public Object clone() {

return new Tile(gc, image, blocking);
}

/**
* Used to add an overlay to the existing tile
* @param image2 The image to overlay
*/
public void addImage(Image image2){
BufferedImage base = (BufferedImage)image;
BufferedImage overlay = (BufferedImage)image2;

// create the new image, canvas size is the max. of both image sizes
int w = Math.max(base.getWidth(), overlay.getWidth());
int h = Math.max(base.getHeight(), overlay.getHeight());
//BufferedImage combined = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
BufferedImage combined = gc.createCompatibleImage(w, h, Transparency.TRANSLUCENT);
// paint both images, preserving the alpha channels
Graphics g = combined.getGraphics();
g.drawImage(image, 0, 0, null);
g.drawImage(overlay, 0, 0, null);

this.image = (Image)combined;
}

public boolean isBlocking(){
return this.blocking;
}

public void setBlocking(boolean blocking){
this.blocking = blocking;
}

public Image getImage(){
return this.image;
}

最佳答案

我会使用像素渲染引擎(google it ;D)

基本上你所做的,它有一个巨大的整数数组,对应于你正在绘制的图像。

基本上,每个图 block 都有一个代表其像素的整数数组。当您渲染该图 block 时,您将图 block 数组“复制”(比这稍微复杂一点)到大数组:)

然后,一旦你完成了对主数组的所有渲染,你就可以在屏幕上绘制它。

这样,您每次画东西时都只处理整数而不是整张图片。这使其速度更快。

我使用 MrDeathJockey 的(youtube)教程并将它们与 DesignsbyZephyr 的(也是 youtube)相结合来学习这一点。虽然我不推荐使用他的技术(他只使用 4 种颜色和 8 位图形,与 deathJockey 的教程一样,你可以自定义图像的大小,甚至有多个不同分辨率的 Sprite 表(对字体有用)

但是我确实使用了一些偏移的东西(让屏幕而不是播放器移动)和 Zephyr 的 InputHandler :)

希望对您有所帮助!-Camodude009

关于基于 Java Tile 的游戏性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10046401/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com