所以我正在尝试使用Slick2d制作自上而下的2D游戏。
我有一个世界对象,该对象痛疼一个包含块列表的块列表。这些瓦片是渲染的东西。我将磁贴位置存储在Vector2f中。每个块也都有一个Vector2f位置。这是我当前的工作代码:
主要:
users: {
uid1: {
Clients: {
Johnny Sherman: "Apple",
Tyler Huan: "Microsoft",
//...
}
}
}
渲染器类:
public class Main extends BasicGame {
public static Main instance;
private Renderer renderer;
private long lastFrameTime;
private float delta;
public Main() {
super("Test");
}
public static void main(String[] arguments) {
try {
instance = new Main();
AppGameContainer app = new AppGameContainer(instance);
app.setDisplayMode(1240, 720, false);
app.setShowFPS(true);
app.start();
app.setAlwaysRender(true);
} catch (SlickException e) {
e.printStackTrace();
}
}
@Override
public void init(GameContainer container) throws SlickException {
renderer = new Renderer(new World(), new Player());
for(Chunk chunk : renderer.getWorld().getChunks()) {
System.out.println(chunk.getPosition().x + "," +
chunk.getPosition().y + "," + chunk.getTiles().size());
}
}
@Override
public void update(GameContainer container, int delta)
throws SlickException {
long currentFrameTime = getCurrentTime();
this.delta = (currentFrameTime - lastFrameTime)/1000f;
lastFrameTime = currentFrameTime;
renderer.move();
}
public void render(GameContainer container, Graphics g)
throws SlickException {
renderer.update(g);
}
public float getFrameTimeSeconds() {
return delta;
}
private static long getCurrentTime() {
return Sys.getTime()*1000/Sys.getTimerResolution();
}
public Renderer getRenderer() {
return renderer;
}
}
该代码工作得不错,但问题是帧速率为4-5 fps。 我有一个尝试将纹理缝合在一起并像这样渲染它们的想法,这是我的新渲染器代码:
public class Renderer {
World world;
Player player;
public Renderer(World world, Player player) {
this.world = world;
this.player = player;
}
public World getWorld() {
return world;
}
public void setWorld(World world) {
this.world = world;
}
public Player getPlayer() {
return player;
}
public void setPlayer(Player player) {
this.player = player;
}
public void update(Graphics g) {
for (int i = 0; i < 2; i++) {
for (int i2 = 0; i2 < 2; i2++) {
Vector2f pos = player.getPos();
Chunk chunk = world.getChunk(new Vector2f((int) Math
.floor(pos.x / 16) + i, (int) Math.floor(pos.y / 16)
+ i2));
if (chunk != null) {
for (Tile tile : chunk.getTiles()) {
if (tile.getPos().x < player.getPos().x +
((Display.getWidth() / 2) + 64 + 50) &&
tile.getPos().x > player.getPos().x -
((Display.getWidth() / 2) + 64 + 50) &&
tile.getPos().y < player.getPos().y +
((Display.getHeight() / 2) + 64 + 50) &&
tile.getPos().y > player.getPos().y -
((Display.getHeight() / 2) + 64 + 50))
g.drawImage(tile.getTexture().getScaledCopy(64, 64),
(pos.x - tile.getPos().x)*64+Display.getWidth(),
(pos.y -
tile.getPos().y)*64+Display.getHeight());
}
}
}
}
}
public void move() {
Vector2f pos = player.getPos();
if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
pos.y += 1 * Main.instance.getFrameTimeSeconds();
} else if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
pos.y -= 1 * Main.instance.getFrameTimeSeconds();
}
if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
pos.x += 1 * Main.instance.getFrameTimeSeconds();
} else if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
pos.x -= 1 * Main.instance.getFrameTimeSeconds();
}
int width = Display.getWidth();
int height = Display.getHeight();
Vector2f npos2;
Vector2f constant = new Vector2f((int) Math.floor((width / 2 -
pos.x)/256), (int) Math.floor((height / 2 - pos.y)/256));
Vector2f npos = constant;
if (world.getChunk(npos) == null) {
npos2 = npos;
npos2.x += 1;
//Right
if (world.getChunk(npos2) == null) {
for (int i = 0; i < 2; i++) {
System.out.println("Generating new chunk! (1) " + npos2.x +
", " + npos2.y + ", Player: x: " + player.getPos().x + ", y: " +
player.getPos().y);
npos.x += i;
world.generateChunk(npos);
}
}
npos2.x -= 1;
npos2.y -= 1;
//Down
if (world.getChunk(npos2) == null) {
for (int i = 0; i < 2; i++) {
System.out.println("Generating new chunk! (2) " + npos2.x +
", " + npos2.y + ", Player: x: " + player.getPos().x + ", y: " +
player.getPos().y);
npos.y -= i;
world.generateChunk(npos);
}
}
}
npos = constant;
if (world.getChunk(npos) == null) {
npos2 = npos;
npos2.x -= 1;
//Left
if (world.getChunk(npos2) == null) {
for (int i = 0; i < 2; i++) {
System.out.println("Generating new chunk! (3) " + npos2.x +
", " + npos2.y + ", Player: x: " + player.getPos().x + ", y: " +
player.getPos().y);
npos.x -= i;
world.generateChunk(npos);
}
}
npos2.x += 1;
npos2.y += 1;
//Up
if (world.getChunk(npos2) == null) {
for (int i = 0; i < 2; i++) {
System.out.println("Generating new chunk! (4) " + npos2.x +
", " + npos2.y + ", Player: x: " + player.getPos().x + ", y: " +
player.getPos().y);
npos.y += i;
world.generateChunk(npos);
}
}
}
}
}
问题在于,不仅当我在瓷砖上四处移动太多时,程序都会崩溃,而且我只能得到1 fps,这根本不好。所以我的问题是,以适当的帧速率实现此目标的最佳方法是什么?
使用第二种方法使程序崩溃时出错:
public class Renderer {
World world;
Player player;
public Renderer(World world, Player player) {
this.world = world;
this.player = player;
}
public World getWorld() {
return world;
}
public void setWorld(World world) {
this.world = world;
}
public Player getPlayer() {
return player;
}
public void setPlayer(Player player) {
this.player = player;
}
public void update(Graphics g) {
for (int i = 0; i < 2; i++) {
for (int i2 = 0; i2 < 2; i2++) {
Vector2f pos = player.getPos();
Chunk chunk = world.getChunk(new Vector2f((int) Math
.floor(pos.x / 16) + i, (int) Math.floor(pos.y / 16)
+ i2));
if (chunk != null) {
Image image = null;
try {
image = new Image(4096, 4096);
} catch (SlickException e1) {
e1.printStackTrace();
}
Graphics ig = null;
try {
ig = image.getGraphics();
} catch (SlickException e) {
e.printStackTrace();
}
for (Tile tile : chunk.getTiles()) {
if (tile.getPos().x < player.getPos().x +
((Display.getWidth() / 2) + 64 + 50) &&
tile.getPos().x > player.getPos().x -
((Display.getWidth() / 2) + 64 + 50) &&
tile.getPos().y < player.getPos().y +
((Display.getHeight() / 2) + 64 + 50) &&
tile.getPos().y > player.getPos().y -
((Display.getHeight() / 2) + 64 + 50))
ig.drawImage(tile.getTexture().getScaledCopy(64, 64),
(pos.x - tile.getPos().x)*64+Display.getWidth(),
(pos.y -
tile.getPos().y)*64+Display.getHeight());
}
ig.flush();
g.drawImage(image, chunk.getPosition().x*256 - pos.x,
chunk.getPosition().y*256-pos.y);
}
}
}
}
public void move() {
Vector2f pos = player.getPos();
if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
pos.y += 1 * Main.instance.getFrameTimeSeconds();
} else if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
pos.y -= 1 * Main.instance.getFrameTimeSeconds();
}
if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
pos.x += 1 * Main.instance.getFrameTimeSeconds();
} else if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
pos.x -= 1 * Main.instance.getFrameTimeSeconds();
}
int width = Display.getWidth();
int height = Display.getHeight();
Vector2f npos2;
Vector2f constant = new Vector2f((int) Math.floor((width / 2 -
pos.x)/256), (int) Math.floor((height / 2 - pos.y)/256));
Vector2f npos = constant;
if (world.getChunk(npos) == null) {
npos2 = npos;
npos2.x += 1;
//Right
if (world.getChunk(npos2) == null) {
for (int i = 0; i < 2; i++) {
System.out.println("Generating new chunk! (1) " + npos2.x +
", " + npos2.y + ", Player: x: " + player.getPos().x + ", y: " +
player.getPos().y);
npos.x += i;
world.generateChunk(npos);
}
}
npos2.x -= 1;
npos2.y -= 1;
//Down
if (world.getChunk(npos2) == null) {
for (int i = 0; i < 2; i++) {
System.out.println("Generating new chunk! (2) " + npos2.x +
", " + npos2.y + ", Player: x: " + player.getPos().x + ", y: " +
player.getPos().y);
npos.y -= i;
world.generateChunk(npos);
}
}
}
npos = constant;
if (world.getChunk(npos) == null) {
npos2 = npos;
npos2.x -= 1;
//Left
if (world.getChunk(npos2) == null) {
for (int i = 0; i < 2; i++) {
System.out.println("Generating new chunk! (3) " + npos2.x +
", " + npos2.y + ", Player: x: " + player.getPos().x + ", y: " +
player.getPos().y);
npos.x -= i;
world.generateChunk(npos);
}
}
npos2.x += 1;
npos2.y += 1;
//Up
if (world.getChunk(npos2) == null) {
for (int i = 0; i < 2; i++) {
System.out.println("Generating new chunk! (4) " + npos2.x +
", " + npos2.y + ", Player: x: " + player.getPos().x + ", y: " +
player.getPos().y);
npos.y += i;
world.generateChunk(npos);
}
}
}
}
}
更新: 我没有运气,但是看看其他能够渲染数百张图像而又不丢很多帧的2D游戏,我认为有某种方法可以大大加快我的代码的速度。我不会渲染屏幕图块,而只会尝试渲染所需的数量。
更新#2: 我切换到libgdx,现在它像一个魅力一样运行。对于我的目的,libgdx中包含的批处理渲染效果更好。