贪吃蛇游戏设计-3.添加蛇和食物
3.添加蛇和食物/**贪吃蛇游戏 - 主页面精简版保留蛇和食物的显示功能核心功能绘制游戏画布背景、网格绘制蛇绿色身体 红色头部绘制食物黄色圆形*//**游戏主组件Entry 标记为页面入口组件Component 标记为UI组件*/Entry Component struct ParentComp { // 画布相关变量 /** 画布渲染设置开启抗锯齿使图形边缘更平滑 */ private settings: RenderingContextSettings new RenderingContextSettings(true) /** 画布绘图上下文所有绘图操作都通过此对象执行 */ private context: CanvasRenderingContext2D new CanvasRenderingContext2D(this.settings) /** 画布尺寸正方形根据屏幕宽度动态计算 */ State canvasSize: number 300 /** 每个网格方块的宽度 canvasSize / 20游戏区域是20x20的网格 */ State rectWidth: number 15 // 蛇的属性变量 /** 蛇的长度初始4节 */ State snakeLength: number 4 /** 蛇身每节的X坐标数组网格坐标0-19 */ State snakeX: number[] [0, 1, 2, 3] /** 蛇身每节的Y坐标数组网格坐标0-19 */ State snakeY: number[] [0, 0, 0, 0] // 食物属性变量 /** 食物的X坐标网格坐标 */ State foodX: number 8 /** 食物的Y坐标网格坐标 */ State foodY: number 5 /** 画布是否准备就绪用于确保在Canvas初始化后再绘图 */ State isCanvasReady: boolean false /** * 构建UI界面 */ build() { // Column垂直布局容器子组件从上到下排列 Column() { // ---------- 标题区域 ---------- Text( 贪吃蛇) .fontSize(48) // 字体大小 .fontWeight(FontWeight.Bold) // 粗体 .fontColor(#fff) // 白色字体 .margin({ top: 20, bottom: 10 }) // 外边距 .textAlign(TextAlign.Center) // 居中对齐 // ---------- 游戏画布 ---------- Canvas(this.context) .width(this.canvasSize) // 宽度 .height(this.canvasSize) // 高度正方形 .backgroundColor(#1a1a2e) // 深蓝色背景 .borderRadius(20) // 圆角 .shadow({ // 阴影效果 radius: 20, color: rgba(0, 0, 0, 0.5), offsetX: 0, offsetY: 10 }) // onReady画布准备就绪时的回调在此回调中才能开始绘图 .onReady(() { this.isCanvasReady true // 标记画布已就绪 this.draw() // 绘制初始画面 }) // ---------- 开始游戏按钮 ---------- Button( 开始游戏) .width(40%) .height(40) .fontSize(16) .backgroundColor(#4a90d9) .fontColor(#fff) .borderRadius(20) .margin({ top: 10 }) // ---------- 操作提示 ---------- Text(使用方向键控制蛇的移动) .fontSize(10) .fontColor(#888) .margin({ top: 20, bottom: 20 }) .textAlign(TextAlign.Center) } .width(100%) .height(100%) .backgroundColor(#0f0f23) // 页面背景色深紫色 .justifyContent(FlexAlign.Center) // 垂直居中对齐 } /** * 绘制游戏画面 * 绘图顺序从后到前 * 1. 背景 → 2. 网格线 → 3. 蛇身 → 4. 蛇头 → 5. 食物 */ private draw(): void { // ---------- 1. 绘制背景 ---------- this.context.fillStyle #1a1a2e // 背景颜色 this.context.fillRect(0, 0, this.canvasSize, this.canvasSize) // 填充整个画布 // ---------- 2. 绘制网格线 ---------- this.context.strokeStyle #2d2d44 // 网格线颜色浅灰色 this.context.lineWidth 1 // 线宽 // 绘制21条垂直线分隔20个网格 for (let i 0; i 20; i) { this.context.beginPath() this.context.moveTo(i * this.rectWidth, 0) this.context.lineTo(i * this.rectWidth, this.canvasSize) this.context.stroke() } // 绘制21条水平线 for (let i 0; i 20; i) { this.context.beginPath() this.context.moveTo(0, i * this.rectWidth) this.context.lineTo(this.canvasSize, i * this.rectWidth) this.context.stroke() } // ---------- 3. 绘制蛇身绿色带发光效果 ---------- this.context.fillStyle #00ff88 // 蛇身颜色绿色 this.context.shadowColor #00ff88 // 发光颜色 this.context.shadowBlur 8 // 发光模糊度 // 遍历蛇身不包括蛇头 for (let i 0; i this.snakeLength - 1; i) { this.roundRect( this.snakeX[i] * this.rectWidth 2, // X坐标加2像素内边距 this.snakeY[i] * this.rectWidth 2, // Y坐标 this.rectWidth - 4, // 宽度减4像素内边距 this.rectWidth - 4, // 高度 5 // 圆角半径 ) } // ---------- 4. 绘制蛇头红色带更强的发光效果 ---------- this.context.fillStyle #ff6b6b // 蛇头颜色红色 this.context.shadowColor #ff6b6b // 发光颜色 this.context.shadowBlur 12 // 更强的发光效果 this.roundRect( this.snakeX[this.snakeLength - 1] * this.rectWidth 2, // 蛇头X坐标 this.snakeY[this.snakeLength - 1] * this.rectWidth 2, // 蛇头Y坐标 this.rectWidth - 4, this.rectWidth - 4, 6 // 蛇头圆角更大 ) // ---------- 5. 绘制食物黄色圆形带最强发光效果 ---------- this.context.fillStyle #ffd93d // 食物颜色黄色 this.context.shadowColor #ffd93d // 发光颜色 this.context.shadowBlur 15 // 最强发光效果 this.context.beginPath() // 绘制圆形圆心在食物位置半径为方块宽度的一半 this.context.arc( this.foodX * this.rectWidth this.rectWidth / 2, // 圆心X this.foodY * this.rectWidth this.rectWidth / 2, // 圆心Y this.rectWidth / 2 - 3, // 半径减3像素内边距 0, // 起始角度 Math.PI * 2 // 结束角度360度 ) this.context.fill() // 重置阴影效果避免影响后续绘制 this.context.shadowBlur 0 } /** * 绘制圆角矩形的辅助方法 * Canvas 没有直接的圆角矩形API需要使用路径手动绘制 * * param x 左上角的X坐标 * param y 左上角的Y坐标 * param width 矩形宽度 * param height 矩形高度 * param radius 圆角半径 */ private roundRect(x: number, y: number, width: number, height: number, radius: number): void { this.context.beginPath() this.context.moveTo(x radius, y) // 从左上角右边开始 this.context.lineTo(x width - radius, y) // 上边直线 this.context.quadraticCurveTo(x width, y, x width, y radius) // 右上角圆角 this.context.lineTo(x width, y height - radius) // 右边直线 this.context.quadraticCurveTo(x width, y height, x width - radius, y height) // 右下角圆角 this.context.lineTo(x radius, y height) // 下边直线 this.context.quadraticCurveTo(x, y height, x, y height - radius) // 左下角圆角 this.context.lineTo(x, y radius) // 左边直线 this.context.quadraticCurveTo(x, y, x radius, y) // 左上角圆角 this.context.closePath() // 闭合路径 this.context.fill() // 填充颜色 } }