You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 00:18:21