我正在研究一些在线示例,并试图了解HTML5游戏如何组合在一起。
我已经掌握了基础知识,例如游戏循环,并将更新和渲染逻辑分开。
我正处于可以从tileset生成地图的阶段,并渲染一个可以四处走动的角色,并在其移动时让精灵有动画。
我一直在努力的是视口在移动时跟随角色的方式。它主要是工作,相机会跟随 - 然而,它对生成的地图有一个非常奇怪的影响。
到目前为止,代码很长,但我已经创建了一个当前工作方式的JSFiddle,它说明了我遇到的问题。可以使用箭头键移动角色。
顺便说一下,我注意到角色是否走进左上角,似乎没问题。
生成地图的代码是:
tileSize = game.currentMap.tileset.tileWidth;
if (player.x >= (game.viewport.x / 2)) r = Math.floor(player.x - ((map.width * map.tileset.tileWidth) / 2))
for (r = Math.floor(game.viewport.x / map.tileset.tileWidth); r < Math.floor(game.viewport.x / map.tileset.tileWidth) + canvas.width / map.tileset.tileWidth + 1; r++) {
for (c = Math.floor(game.viewport.y / map.tileset.tileHeight); c < Math.floor(game.viewport.y / map.tileset.tileHeight) + canvas.height / map.tileset.tileHeight + 1; c++) {
var tile = ground[r][c];
var tileRow = (tile / game.currentMap.tileset.tilesInImgRow) | 0; // Bitwise OR operation
var tileCol = (tile % game.currentMap.tileset.tilesInImgRow) | 0;
ctx.drawImage(
game.currentMap.tileset.image, (tileCol * tileSize), (tileRow * tileSize),
tileSize,
tileSize, (c * tileSize) - game.viewport.x, (r * tileSize) - game.viewport.y,
tileSize,
tileSize);
tile = layer1[r][c];
tileRow = (tile / game.currentMap.tileset.tilesInImgRow) | 0;
tileCol = (tile % game.currentMap.tileset.tilesInImgRow) | 0;
ctx.drawImage(
game.currentMap.tileset.image, (tileCol * tileSize), (tileRow * tileSize),
tileSize,
tileSize, (c * tileSize) - game.viewport.x, (r * tileSize) - game.viewport.y,
tileSize,
tileSize);
}
}
但是,当我正在研究来自其他资源的代码时 - 我有点担心这个问题是由这个函数还是由生成和更新视口的函数引起的。
有什么建议吗?
更新
调整视口的代码,以便在角色靠近地图边缘时,它不再保留在视口的中心:
if (game.viewport.x <= 0) dX = player.x;
else if (game.viewport.x >= game.currentMap.tileset.tileWidth * game.currentMap.width - canvas.width) dX = player.x - game.viewport.x;
else dX = Math.round(canvas.width / 2 - player.width / 2);
if (game.viewport.y <= 0) dY = player.y;
else if (game.viewport.y >= game.currentMap.tileset.tileHeight * game.currentMap.height - canvas.height) dY = player.y - game.viewport.y;
else dY = Math.round(canvas.height / 2 - player.height / 2);
移动角色时更新视口的代码:
if (player.x + player.width / 2 < canvas.width / 2) {
game.viewport.x = 0;
} else if (player.x + canvas.width / 2 + player.width / 2 >= map.tileset.tileWidth * map.width) {
game.viewport.x = map.tileset.tileWidth * map.width - canvas.width;
} else {
game.viewport.x = Math.floor(player.x - (canvas.width / 2 - player.width / 2));
}
if (player.y + player.height / 2 < canvas.height / 2) {
game.viewport.y = 0;
} else if (player.y + canvas.height / 2 + player.height / 2 >= map.tileset.tileHeight * map.height) {
game.viewport.y = map.tileset.tileHeight * map.height - canvas.height;
} else {
game.viewport.y = Math.floor(player.y - (canvas.height / 2 - player.height / 2));
}
最初使用以下方法设置视口:
var game = {
images: 0,
imagesLoaded: 0,
backgroundColor: '#000',
viewport: {
x: Math.floor(player.x - (canvas.width / 2 - playerSpriteSize / 2)),
y: Math.floor(player.y - (canvas.height / 2 - playerSpriteSize / 2))
},
currentMap: map,
fps: 0,
lastfps: 0,
fpsTimer: 0
}
答案 0 :(得分:1)
好吧,在玩了几天的代码和几杯咖啡之后,我已经设法解决了我自己的问题,我认为我会分享给其他有类似问题的人。
更新视口的代码很好,问题是分配给视口的初始值以及迭代地图x和y图块的方式。
在游戏变量中,我将视口更改为:
viewport: {
x: Math.floor(player.x - (canvas.width / 2)),
y: Math.floor(player.y - (canvas.height / 2))
},
然后在drawMap函数中:
for (r = 0; r < map.rowTileCount; r++) {
for (c = 0; c < map.colTileCount; c++) {
这样,我们总是生成完整的地图(这可能会不必要地使用额外的资源,但我们总是可以回来再看一遍)然后我们只将一个剪裁的部分绘制到画布上,这是正是我想要的。