如何在CSS Grid上创建可按键控制的可移动角色
问题
我为一款小型2D游戏创建了一个8行3列的CSS Grid,想要创建一个小型“chicken”角色,通过按键利用left、top等CSS属性进行控制,但不确定如何将其添加到现有HTML中。
起初我尝试移除chicken类的grid属性,并添加position: absolute来覆盖角色的网格定位,但发现这会导致角色不占用空间,不知道还有什么其他方法可以尝试。
原CSS代码:
body{ margin:0; } .game_frame{ position: absolute; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background: #00162b; } .game_screen{ display: grid; grid-template-rows: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr; position: absolute; width: 90%; height: 90%; background: black; } .scoreboard{ grid-row-start: 1; grid-column-start: 1; color: white; font-family: verdana; font-size: 30px; padding-left: 10px; padding-top: 10px; text-shadow: 1px 1px 10px #ccc; } .timer{ grid-row-start: 1; grid-column-start: 2; padding-left: 45%; color: white; font-family: verdana; font-size: 25px; padding-top: 30px; text-shadow: 1px 1px 20px #fff, 1px 1px 20px #ccc; } .solid_line{ height: 3%; width: 100%; background-color: white; } .dotted_line{ background-image: linear-gradient(to right, white 0%, white 90%, transparent 40%); background-size: 36px 2px; background-repeat: repeat-x; height: 3%; width: 100%; } .chicken{ grid-row-start: 8; grid-column-start: 2; background-image: url("chicken_texture.png"); background-repeat: no-repeat; width: 20%; justify-self: center; }
原HTML代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title> Traffic Evasion </title> <link rel="stylesheet" href="styles.css"> </head> <body> <div class="game_frame"> <div class="game_screen"> <div class="scoreboard"> Score: 0 </div> <div class="timer"> 90 </div> <div class="solid_line" style="grid-row-start:2; grid-column-start:1; grid-column-end:4"> </div> <div class="dotted_line" style="grid-row-start:3; grid-column-start:1; grid-column-end:4"> </div> <div class="dotted_line" style="grid-row-start:4; grid-column-start:1; grid-column-end:4"> </div> <div class="dotted_line" style="grid-row-start:5; grid-column-start:1; grid-column-end:4"> </div> <div class="dotted_line" style="grid-row-start:6; grid-column-start:1; grid-column-end:4"> </div> <div class="dotted_line" style="grid-row-start:7; grid-column-start:1; grid-column-end:4"> </div> <div class="solid_line" style="grid-row-start:8; grid-column-start:1; grid-column-end:4"> </div> <div class="chicken"> </div> </div> </div> <script src="/socket.io/socket.io.js"></script> <script src="client.js"></script> </body> </html>
解决方案
可移动角色不需要占用Grid布局空间,应该脱离Grid文档流独立控制,具体实现步骤如下:
1. 调整容器与角色的定位规则
- 给
.game_screen添加position: relative,让它成为chicken绝对定位的参考容器(保留原有的absolute属性不影响)。 - 给
.chicken设置position: absolute,移除原有的grid定位属性,用top和left定义初始位置,同时通过transform: translateX(-50%)保持水平居中,和之前的justify-self: center效果一致。
2. 修改后的CSS代码
body{ margin:0; } .game_frame{ position: absolute; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background: #00162b; } .game_screen{ display: grid; grid-template-rows: repeat(8, 1fr); /* 简化重复行写法 */ grid-template-columns: repeat(3, 1fr); /* 简化重复列写法 */ position: relative; /* 添加作为绝对定位的参考容器 */ width: 90%; height: 90%; background: black; } .scoreboard{ grid-row: 1 / 2; /* 简化grid行定位写法 */ grid-column: 1 / 2; /* 简化grid列定位写法 */ color: white; font-family: verdana; font-size: 30px; padding-left: 10px; padding-top: 10px; text-shadow: 1px 1px 10px #ccc; } .timer{ grid-row: 1 / 2; /* 简化grid行定位写法 */ grid-column: 2 / 3; /* 简化grid列定位写法 */ padding-left: 45%; color: white; font-family: verdana; font-size: 25px; padding-top: 30px; text-shadow: 1px 1px 20px #fff, 1px 1px 20px #ccc; } .solid_line{ height: 3%; width: 100%; background-color: white; } .dotted_line{ background-image: linear-gradient(to right, white 0%, white 90%, transparent 40%); background-size: 36px 2px; background-repeat: repeat-x; height: 3%; width: 100%; } .chicken{ position: absolute; background-image: url("chicken_texture.png"); background-repeat: no-repeat; width: 20%; height: 10%; /* 添加高度保证角色正常显示 */ top: calc(100% - 10% - 1.5%); /* 对应原第8行位置,减去自身高度和solid_line高度 */ left: 33.33%; /* 对应原第2列位置,3列每列占比约33.33% */ transform: translateX(-50%); /* 保持水平居中 */ }
3. 添加按键控制逻辑
在client.js中监听键盘事件,通过修改chicken的top和left属性实现移动,同时设置边界限制避免角色移出游戏屏幕:
const chicken = document.querySelector('.chicken'); const gameScreen = document.querySelector('.game_screen'); const moveStep = 5; // 每次移动的像素距离 // 获取游戏屏幕和角色的尺寸信息 let screenRect = gameScreen.getBoundingClientRect(); let chickenRect = chicken.getBoundingClientRect(); // 窗口大小变化时重新获取尺寸 window.addEventListener('resize', () => { screenRect = gameScreen.getBoundingClientRect(); chickenRect = chicken.getBoundingClientRect(); }); document.addEventListener('keydown', (e) => { const currentTop = parseInt(window.getComputedStyle(chicken).top); const currentLeft = parseInt(window.getComputedStyle(chicken).left); switch(e.key) { case 'ArrowUp': if (currentTop > 0) { chicken.style.top = `${currentTop - moveStep}px`; } break; case 'ArrowDown': if (currentTop < screenRect.height - chickenRect.height) { chicken.style.top = `${currentTop + moveStep}px`; } break; case 'ArrowLeft': if (currentLeft > 0) { chicken.style.left = `${currentLeft - moveStep}px`; } break; case 'ArrowRight': if (currentLeft < screenRect.width - chickenRect.width) { chicken.style.left = `${currentLeft + moveStep}px`; } break; } });
说明
- 角色采用绝对定位后,不会影响Grid布局的其他元素,完全独立可控。
- 初始位置通过计算和原Grid布局的第8行第2列对齐,保证视觉一致性。
- 按键控制逻辑添加了边界检测,防止角色移出游戏屏幕,同时支持窗口大小变化时更新边界。
内容的提问来源于stack exchange,提问作者Tszhim Chan
相关产品推荐
相关产品推荐

