画出蛇头

This commit is contained in:
flykhan 2023-02-12 21:36:52 +08:00
parent a92bb2d136
commit 622fe376fc
No known key found for this signature in database
3 changed files with 79 additions and 4 deletions

View File

@ -0,0 +1,11 @@
// 定义一个格子
export class Cell {
// 参数是格子的行数和列数
constructor(r,c){
this.r = r;
this.c = c;
// 坐标转换,用于确定蛇的每节身体所在格子中心点的坐标
this.x = c + 0.5;
this.y = r + 0.5;
}
}

View File

@ -1,5 +1,6 @@
// 在 AcGameObject.js 里使用的是 export class ,因此这里需要使用 {} 括起来引用;如果是 export default 则不需要用括号括起来 // 在 AcGameObject.js 里使用的是 export class ,因此这里需要使用 {} 括起来引用;如果是 export default 则不需要用括号括起来
import { AcGameObject } from "./AcGameObject"; import { AcGameObject } from "./AcGameObject";
import { Snake } from "./Snake";
// 导入墙组件 // 导入墙组件
import { Wall } from "./Wall"; import { Wall } from "./Wall";
@ -18,8 +19,9 @@ export class GameMap extends AcGameObject{
this.L = 0; this.L = 0;
// 定义棋盘格的行数和列数 // 定义棋盘格的行数和列数
// 行数和列数不同时设置为偶数或者不同时设置为奇数,可以避免AB两蛇同时进入同一个格子,避免因此对优势者不公平
this.rows = 13; this.rows = 13;
this.cols = 13; this.cols = 14;
// 绘制棋盘内部区域的障碍物(墙)的数量 // 绘制棋盘内部区域的障碍物(墙)的数量
this.inner_walls_count = 50; this.inner_walls_count = 50;
@ -27,6 +29,13 @@ export class GameMap extends AcGameObject{
// 存储所有的墙 // 存储所有的墙
// 上面的 super() 会先将 AcGameObject 先绘制, walls 的绘制在后面执行,因此墙最后会覆盖原棋盘格进行绘制 // 上面的 super() 会先将 AcGameObject 先绘制, walls 的绘制在后面执行,因此墙最后会覆盖原棋盘格进行绘制
this.walls = []; this.walls = [];
// 创建蛇对象数组
this.snakes = [
// 注意这里的对象生成方式和传参方式
new Snake({id: 0, color: "#4876ec", r: this.rows-2, c: 1}, this),
new Snake({id: 1, color: "#f94848", r: 1, c: this.cols-2}, this),
];
} }
// 判断函数:判断角色路径是否联通。传入参数:g数组,起点和终点的横纵坐标 // 判断函数:判断角色路径是否联通。传入参数:g数组,起点和终点的横纵坐标
@ -83,13 +92,17 @@ export class GameMap extends AcGameObject{
// 主对角线对称 g[r][c] 和 g[c][r] 完成两种联合判断 // 主对角线对称 g[r][c] 和 g[c][r] 完成两种联合判断
// 当此位置已经有障碍物了,则重新计算下一个位置 // 当此位置已经有障碍物了,则重新计算下一个位置
if(g[r][c] || g[c][r]) continue; // if(g[r][c] || g[c][r]) continue;
// 解决中心对称问题,需要将注释代码修改为下一行
if(g[r][c] || g[this.rows-1-r][this.cols-1-c]) continue;
// 将计算求得的随机障碍物的位置置为 true ,以对该位置进行绘制 // 将计算求得的随机障碍物的位置置为 true ,以对该位置进行绘制
// g[r][c] 和 g[c][r] 的坐标在对角线位置会重合,会被绘制为一个障碍物 // g[r][c] 和 g[c][r] 的坐标在对角线位置会重合,会被绘制为一个障碍物
g[r][c] = g[c][r] = true; // g[r][c] || g[c][r] = true;
// 解决中心对称问题,需要将注释代码修改为下一行
g[r][c] = g[this.rows-1-r][this.cols-1-c] = true;
// 1000 次中,规定数量的内部障碍物已经够了之后就 break 掉 // 1000 次中,规定数量的内部障碍物已经够了之后就 break 掉
break; break;
} }
} }

View File

@ -0,0 +1,51 @@
// 每条蛇定义成一个对象
import { AcGameObject } from "./AcGameObject";
import { Cell } from "./Cell";
// 需要继承自绘制基础类 AcGameObject ,用于蛇的绘制刷新
export class Snake extends AcGameObject {
// 参数:蛇的信息 info ,当前游戏地图 gamemap
constructor(info, gamemap) {
super();
// 每条蛇的 id 用于区分每条蛇, color 用于定义蛇的颜色
this.id = info.id;
this.color = info.color;
// 调用地图的引用获取一些地图参数,例如:每个格子的边长
this.gamemap = gamemap;
// 蛇初始只有一个点(蛇头),初始时只需要定义出蛇头即可。初始坐标为每条蛇的起始位置
// cells[] 存放蛇的身体, cells[0] 存放蛇头
this.cells = [new Cell(info.r, info.c)]
}
start() {
}
update() {
// 每次更新蛇类对象都重新调用一次渲染
this.render();
}
// render 不来自基类,需要本类自己实现
render() {
// 取出单元格长度引用和画布
const L = this.gamemap.L;
const ctx = this.gamemap.ctx;
// 画圆(蛇的身体结点)
ctx.fillStyle = this.color;
// 蛇的身体不止一节,需要枚举画出所有的肢结。of 遍历 cells 值
for(const cell of this.cells){
// 画成正方形
// ctx.fillRect(cell.c * L, cell.r * L, L, L);
// 画成圆形
ctx.beginPath();
ctx.arc(cell.x * L, cell.y * L, L * 0.5, 0, 2*Math.PI);
// 填充颜色
ctx.fill();
}
}
}