1 Star 0 Fork 0

张志阳/brainjs-DQN

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
game.js 7.75 KB
一键复制 编辑 原始数据 按行查看 历史
张志阳 提交于 2024-11-16 13:29 +08:00 . 初始化项目
/**
* 游戏核心类,负责游戏逻辑和渲染
*/
class Game {
/**
* 初始化游戏
* 设置画布、玩家、球体和游戏状态
*/
constructor() {
// 获取画布和上下文
this.canvas = document.getElementById('gameCanvas');
this.ctx = this.canvas.getContext('2d', { willReadFrequently: true });
this.canvas.width = 600;
this.canvas.height = 400;
// 初始化玩家
this.player = {
x: this.canvas.width / 2,
y: this.canvas.height / 2,
radius: 10,
speed: 5
};
// 初始化球体数组和游戏状态
this.poisonBalls = []; // 毒药球(蓝色)
this.medicineBalls = []; // 解药球(绿色)
this.score = 0; // 游戏分数
this.isTraining = false; // 训练状态
this.gameSpeed = 1; // 游戏速度
// 创建初始球体
this.initializeBalls();
}
/**
* 初始化毒药球和解药球
* 每种球各创建10个,设置随机位置和速度
*/
initializeBalls() {
// 初始化毒药球,添加速度属性
for (let i = 0; i < 10; i++) {
this.poisonBalls.push({
x: Math.random() * (this.canvas.width - 20) + 10,
y: Math.random() * (this.canvas.height - 20) + 10,
radius: 8,
speedX: (Math.random() - 0.5) * 4, // -2 到 2 之间的随机速度
speedY: (Math.random() - 0.5) * 4
});
}
// 初始化解药球,添加速度属性
for (let i = 0; i < 10; i++) {
this.medicineBalls.push({
x: Math.random() * (this.canvas.width - 20) + 10,
y: Math.random() * (this.canvas.height - 20) + 10,
radius: 8,
speedX: (Math.random() - 0.5) * 4,
speedY: (Math.random() - 0.5) * 4
});
}
}
/**
* 更新所有球的位置
* 处理球体的移动和边界碰撞
*/
updateBalls() {
// 更新毒药球位置
this.poisonBalls.forEach(ball => {
// 根据速度和游戏速度更新位置
ball.x += ball.speedX * this.gameSpeed;
ball.y += ball.speedY * this.gameSpeed;
// 碰到墙壁反弹
if (ball.x - ball.radius <= 0 || ball.x + ball.radius >= this.canvas.width) {
ball.speedX *= -1; // 水平方向速度反转
ball.x = Math.max(ball.radius, Math.min(this.canvas.width - ball.radius, ball.x));
}
if (ball.y - ball.radius <= 0 || ball.y + ball.radius >= this.canvas.height) {
ball.speedY *= -1; // 垂直方向速度反转
ball.y = Math.max(ball.radius, Math.min(this.canvas.height - ball.radius, ball.y));
}
});
// 更新解药球位置(逻辑同上)
this.medicineBalls.forEach(ball => {
ball.x += ball.speedX * this.gameSpeed;
ball.y += ball.speedY * this.gameSpeed;
if (ball.x - ball.radius <= 0 || ball.x + ball.radius >= this.canvas.width) {
ball.speedX *= -1;
ball.x = Math.max(ball.radius, Math.min(this.canvas.width - ball.radius, ball.x));
}
if (ball.y - ball.radius <= 0 || ball.y + ball.radius >= this.canvas.height) {
ball.speedY *= -1;
ball.y = Math.max(ball.radius, Math.min(this.canvas.height - ball.radius, ball.y));
}
});
}
/**
* 绘制游戏画面
* 包括玩家、球体和分数
*/
draw() {
// 清空画布
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
// 更新所有球的位置
this.updateBalls();
// 绘制玩家(红色圆形)
this.ctx.fillStyle = 'red';
this.ctx.beginPath();
this.ctx.arc(this.player.x, this.player.y, this.player.radius, 0, Math.PI * 2);
this.ctx.fill();
// 绘制毒药球(蓝色)
this.ctx.fillStyle = 'blue';
this.poisonBalls.forEach(ball => {
this.ctx.beginPath();
this.ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
this.ctx.fill();
});
// 绘制解药球(绿色)
this.ctx.fillStyle = 'green';
this.medicineBalls.forEach(ball => {
this.ctx.beginPath();
this.ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
this.ctx.fill();
});
// 绘制分数
this.ctx.fillStyle = 'black';
this.ctx.font = '20px Arial';
this.ctx.fillText(`分数: ${this.score}`, 10, 30);
}
/**
* 检查碰撞
* 处理玩家与球体的碰撞
*/
checkCollisions() {
// 检查与毒药球的碰撞
this.poisonBalls.forEach(ball => {
const distance = Math.sqrt(
Math.pow(this.player.x - ball.x, 2) +
Math.pow(this.player.y - ball.y, 2)
);
if (distance < this.player.radius + ball.radius) {
this.score -= 10; // 碰到毒药球扣分
this.resetBall(ball);
}
});
// 检查与解药球的碰撞
this.medicineBalls.forEach(ball => {
const distance = Math.sqrt(
Math.pow(this.player.x - ball.x, 2) +
Math.pow(this.player.y - ball.y, 2)
);
if (distance < this.player.radius + ball.radius) {
this.score += 10; // 碰到解药球加分
this.resetBall(ball);
}
});
}
/**
* 重置球的位置和速度
* @param {Object} ball - 要重置的球体对象
*/
resetBall(ball) {
ball.x = Math.random() * (this.canvas.width - 20) + 10;
ball.y = Math.random() * (this.canvas.height - 20) + 10;
// 重置时也重新随机速度
ball.speedX = (Math.random() - 0.5) * 4;
ball.speedY = (Math.random() - 0.5) * 4;
}
/**
* 获取游戏状态
* @returns {Array} 包含所有游戏对象位置的归一化数组
*/
getState() {
// 返回一个包含所有游戏对象位置的数组
const state = [
this.player.x / this.canvas.width, // 归一化玩家位置
this.player.y / this.canvas.height
];
// 添加毒药球位置
this.poisonBalls.forEach(ball => {
state.push(ball.x / this.canvas.width);
state.push(ball.y / this.canvas.height);
});
// 添加解药球位置
this.medicineBalls.forEach(ball => {
state.push(ball.x / this.canvas.width);
state.push(ball.y / this.canvas.height);
});
return state; // 返回一个长度为42的数组(1个玩家2个坐标 + 20个球各2个坐标)
}
/**
* 移动玩家
* @param {number} action - 动作代码(0:上, 1:下, 2:左, 3:右)
*/
move(action) {
switch(action) {
case 0: // 上
this.player.y = Math.max(this.player.radius, this.player.y - this.player.speed);
break;
case 1: // 下
this.player.y = Math.min(this.canvas.height - this.player.radius, this.player.y + this.player.speed);
break;
case 2: // 左
this.player.x = Math.max(this.player.radius, this.player.x - this.player.speed);
break;
case 3: // 右
this.player.x = Math.min(this.canvas.width - this.player.radius, this.player.x + this.player.speed);
break;
}
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/zhang-zhiyang/brainjs-dqn.git
git@gitee.com:zhang-zhiyang/brainjs-dqn.git
zhang-zhiyang
brainjs-dqn
brainjs-DQN
master

搜索帮助