js实现人物行走
实现基础动画循环
使用requestAnimationFrame创建平滑动画循环,通过时间差计算确保帧率稳定。定义一个游戏循环函数,在每次屏幕刷新时更新角色位置和渲染状态。
let lastTime = 0;
function gameLoop(timestamp) {
const deltaTime = timestamp - lastTime;
lastTime = timestamp;
updatePosition(deltaTime);
renderCharacter();
requestAnimationFrame(gameLoop);
}
requestAnimationFrame(gameLoop);
处理键盘输入
通过addEventListener监听键盘事件,使用对象存储按键状态。创建包含方向键映射的对象,实时跟踪WASD或方向键的按下/释放状态。
const keys = {};
document.addEventListener('keydown', (e) => {
keys[e.key] = true;
});
document.addEventListener('keyup', (e) => {
keys[e.key] = false;
});
// 方向键映射示例
const directionMap = {
'ArrowUp': 'up',
'ArrowDown': 'down',
'ArrowLeft': 'left',
'ArrowRight': 'right'
};
角色移动逻辑
根据按键状态计算移动向量,考虑对角线移动的归一化处理。定义移动速度和加速度参数,实现更自然的运动效果。

const character = {
x: 0,
y: 0,
speed: 100, // 像素/秒
moving: false
};
function updatePosition(deltaTime) {
let moveX = 0;
let moveY = 0;
if (keys['ArrowUp']) moveY -= 1;
if (keys['ArrowDown']) moveY += 1;
if (keys['ArrowLeft']) moveX -= 1;
if (keys['ArrowRight']) moveX += 1;
// 对角线移动归一化
if (moveX !== 0 && moveY !== 0) {
moveX *= 0.7071;
moveY *= 0.7071;
}
character.x += moveX * character.speed * (deltaTime / 1000);
character.y += moveY * character.speed * (deltaTime / 1000);
character.moving = (moveX !== 0 || moveY !== 0);
}
精灵动画控制
使用精灵表实现行走动画,通过计算帧索引实现动画播放。定义动画帧率和当前帧索引,根据移动状态切换不同动画序列。
const sprite = {
frameWidth: 32,
frameHeight: 48,
currentFrame: 0,
frameCount: 4,
frameDuration: 100, // 毫秒
lastFrameTime: 0,
row: 0 // 精灵表行号(0:下,1:左,2:右,3:上)
};
function updateAnimation(deltaTime) {
if (!character.moving) {
sprite.currentFrame = 0;
return;
}
sprite.lastFrameTime += deltaTime;
if (sprite.lastFrameTime >= sprite.frameDuration) {
sprite.currentFrame = (sprite.currentFrame + 1) % sprite.frameCount;
sprite.lastFrameTime = 0;
}
// 根据移动方向设置精灵行
if (keys['ArrowUp']) sprite.row = 3;
else if (keys['ArrowDown']) sprite.row = 0;
else if (keys['ArrowLeft']) sprite.row = 1;
else if (keys['ArrowRight']) sprite.row = 2;
}
渲染角色
使用Canvas API绘制精灵动画,计算正确的精灵图裁剪区域。实现双缓冲技术避免画面闪烁,处理不同方向的镜像翻转。

const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const spriteSheet = new Image();
spriteSheet.src = 'character.png';
function renderCharacter() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (!spriteSheet.complete) return;
const sx = sprite.currentFrame * sprite.frameWidth;
const sy = sprite.row * sprite.frameHeight;
ctx.save();
ctx.translate(character.x, character.y);
if (sprite.row === 1) { // 向左移动时水平翻转
ctx.scale(-1, 1);
ctx.drawImage(spriteSheet, sx, sy, sprite.frameWidth, sprite.frameHeight,
-sprite.frameWidth, 0, sprite.frameWidth, sprite.frameHeight);
} else {
ctx.drawImage(spriteSheet, sx, sy, sprite.frameWidth, sprite.frameHeight,
0, 0, sprite.frameWidth, sprite.frameHeight);
}
ctx.restore();
}
边界检测
添加场景边界限制,防止角色移出可视区域。计算碰撞体积,实现简单的碰撞检测系统。
function checkBoundaries() {
character.x = Math.max(0, Math.min(canvas.width - sprite.frameWidth, character.x));
character.y = Math.max(0, Math.min(canvas.height - sprite.frameHeight, character.y));
}
// 在updatePosition函数末尾调用
checkBoundaries();
性能优化
使用对象池管理游戏对象,减少内存分配。实现视口裁剪,只渲染可见区域的元素。
function optimizeRendering() {
// 计算可见区域
const viewportLeft = Math.max(0, character.x - canvas.width/2);
const viewportTop = Math.max(0, character.y - canvas.height/2);
// 只渲染位于视口内的对象
// ...
}
移动端支持
添加触摸控制支持,创建虚拟摇杆界面。实现手势识别处理滑动操作。
const touchArea = document.getElementById('touchArea');
let touchStartX = 0;
let touchStartY = 0;
touchArea.addEventListener('touchstart', (e) => {
touchStartX = e.touches[0].clientX;
touchStartY = e.touches[0].clientY;
});
touchArea.addEventListener('touchmove', (e) => {
const touchX = e.touches[0].clientX;
const touchY = e.touches[0].clientY;
// 根据滑动距离和方向设置移动状态
// ...
});






