世界和摄像机World and Camera
这一节实现的是超过屏幕尺寸的世界地图,这里的世界不是我们的地球,指的是游戏中的虚拟世界。
这里的游戏示例是一个action RPG,即动作角色扮演游戏(action role play game),因此地图尺寸超过了屏幕尺寸。
具体详情可以参考完整代码。
实现过程
Player类修改
- 修改Player类并将player绘制到屏幕的中心位置,player将总是在屏幕中心位置进行绘制
public Player(GamePanel gp, KeyHandler keyH) {
this.gp = gp;
this.keyH = keyH;
screenX = gp.screenWidth / 2 - gp.tileSize / 2;
screenY = gp.screenHeight / 2 - gp.tileSize / 2;
setDefaultValues();
getPlayerImage();
direction = "down";
}
这里的概念容易让人迷糊,需要花时间理解,之前的地图大小很小,任务角色在地图中走来走去,现在要实现超过屏幕尺寸的地图,任务角色不再动,始终位于游戏窗口屏幕中心的位置。
当按下w,a,s,d按键,任务角色一直在窗口屏幕中心位置,不再移动,取而代之的是地图开始移动了,就像魂斗罗、超级玛丽那样横向地图,角色其实没有动,是后面的地图一直在动。
为了表达地图的坐标,增加了世界坐标worldX, worldY;为绘制显示区域的地图,增加了屏幕坐标screenX, screenY。
这节挺难理解的,得花些时间,可以先复制粘贴,后续慢慢理解。
"世界"地图绘制
- 扩展瓷砖贴图绘制循环的边界
int worldCol = 0;
int worldRow = 0;
while (worldCol < gp.maxWorldCol && worldRow < gp.maxWorldRow) {
int tileNum = mapTileNum[worldCol][worldRow];
int worldX = worldCol * gp.tileSize;
int worldY = worldRow * gp.tileSize;
int screenX = worldX - gp.player.worldX + gp.player.screenX;
int screenY = worldY - gp.player.worldY + gp.player.screenY;
//if判断,只绘制位于游戏窗口可见区域的地图,不可见区域没必要绘制
if (worldX + gp.tileSize > gp.player.worldX - gp.player.screenX &&
worldX - gp.tileSize < gp.player.worldX + gp.player.screenX &&
worldY + gp.tileSize > gp.player.worldY - gp.player.screenY &&
worldY - gp.tileSize < gp.player.worldY + gp.player.screenY) {
g2.drawImage(tile[tileNum].image, screenX, screenY, gp.tileSize, gp.tileSize, null);
}
worldCol++;
if (worldCol == gp.maxWorldCol) {
worldCol = 0;
worldRow++;
}
}
增加了3种tile贴图,树,沙,土地,新的地图文件尺寸变为了50 x 50,窗口只有16 x 12。
最终效果
代码
gitee仓库