这是一个功能丰富的双人乒乓球游戏,支持玩家对战和AI自动对战,包含多种高级特性如多球模式、智能AI追踪等。
代码结构分析
1. 常量定义和初始化
javascript
- const BALL_IMAGE = img`...`; // 球的像素图像
-
- const PADDLE_SPEED = 150; // 球拍移动速度
-
- const PADDING_FROM_WALL = 3; // 球拍离墙的距离
-
- const TIMEOUT = 5000; // AI接管超时时间(5秒)
复制代码
2. 玩家交互检测系统
javascript
- let playerOneLastMove = -TIMEOUT;
-
- let playerTwoLastMove = -TIMEOUT;
-
-
-
- // 设置按键重复延迟
-
- controller.setRepeatDefault(0, 1000);
-
-
-
- // 监听玩家操作时间戳
-
- controller.up.onEvent(ControllerButtonEvent.Repeated, () => playerOneLastMove = game.runtime());
-
- controller.down.onEvent(ControllerButtonEvent.Repeated, () => playerOneLastMove = game.runtime());
复制代码
智能特性:如果玩家5秒内没有操作,AI会自动接管控制。
3. 游戏对象创建
创建玩家球拍
javascript
- function createPlayer(player: info.PlayerInfo) {
-
- const output = sprites.create(image.create(3, 18), SpriteKind.Player);
-
- output.image.fill(player.bg); // 使用玩家主题色
-
- output.setStayInScreen(true); // 限制在屏幕内
-
- return output;
-
- }
复制代码
创建乒乓球
javascript
- function createBall() {
-
- let ball = sprites.create(BALL_IMAGE.clone(), SpriteKind.Enemy);
-
- ball.vy = randint(-20, 20); // 随机垂直速度
-
- ball.vx = 60 * (Math.percentChance(50) ? 1 : -1); // 随机水平方向
-
- }
复制代码
4. 核心游戏逻辑
球的状态更新
javascript
- game.onUpdate(function () {
-
- sprites.allOfKind(SpriteKind.Enemy).forEach(b => {
-
- // 检测得分
-
- const scoreRight = b.x < 0;
-
- const scoreLeft = b.x >= screen.width;
-
-
-
- if (scoreRight) info.player2.changeScoreBy(1);
-
- else if (scoreLeft) info.player1.changeScoreBy(1);
-
-
-
- // 上下边界反弹
-
- if (b.top < 0) b.vy = Math.abs(b.vy);
-
- else if (b.bottom > screen.height) b.vy = -Math.abs(b.vy);
-
-
-
- // 得分后重新生成球
-
- if (scoreLeft || scoreRight) {
-
- b.destroy(effects.disintegrate, 500);
-
- control.runInParallel(() => {
-
- pause(250);
-
- createBall();
-
- });
-
- }
-
- });
-
- });
复制代码
碰撞检测与物理响应
javascript
- sprites.onOverlap(SpriteKind.Player, SpriteKind.Enemy, (sprite, otherSprite) => {
-
- const fromCenter = otherSprite.y - sprite.y; // 计算击中点偏移
-
-
-
- // 物理反弹效果
-
- otherSprite.vx = otherSprite.vx * -1.05; // 反向并加速5%
-
- otherSprite.vy += (sprite.vy >> 1) + (fromCenter * 3); // 加入旋转效果
-
-
-
- // 视觉效果
-
- otherSprite.startEffect(effects.ashes, 150);
-
- sprite.startEffect(effects.ashes, 100);
-
-
-
- // 球的颜色变化(击中时染色)
-
- otherSprite.image.setPixel(
-
- randint(1, otherSprite.image.width - 2),
-
- randint(1, otherSprite.image.height - 2),
-
- sprite.image.getPixel(0, 0) // 使用球拍颜色
-
- );
-
-
-
- pingMessage = !pingMessage; // 切换"ping"/"pong"显示
-
- pause(500); // 防重复触发
-
- });
复制代码
5. 高级AI追踪系统
这是游戏最复杂和智能的部分:
javascript
- function trackBall(player: Sprite) {
-
- const next = nextBall(player);
-
- if (!next) return;
-
-
-
- if (ballFacingPlayer(player, next)) {
-
- intersectBall(player, next); // 追踪球的预计落点
-
- } else {
-
- player.vy = 0; // 球朝反方向,放松等待
-
- }
-
- }
复制代码
智能球选择算法
javascript
- function nextBall(player: Sprite) {
-
- return sprites.allOfKind(SpriteKind.Enemy).sort((a, b) => {
-
- const aFacingPlayer = ballFacingPlayer(player, a);
-
- const bFacingPlayer = ballFacingPlayer(player, b);
-
-
-
- // 优先选择面向玩家的球
-
- if (aFacingPlayer && !bFacingPlayer) return -1;
-
- else if (!aFacingPlayer && bFacingPlayer) return 1;
-
-
-
- // 其次选择最先到达的球
-
- const aDiff = Math.abs((a.x - player.x) / a.vx);
-
- const bDiff = Math.abs((b.x - player.x) / b.vx);
-
- return aDiff - bDiff;
-
- })[0];
-
- }
复制代码
物理轨迹预测算法
javascript
- function intersectBall(player: Sprite, target: Sprite) {
-
- // 计算球的预计落点:使用相似三角形原理
-
- const projectedDY = (target.x - player.x) * target.vy / target.vx;
-
- let intersectionPoint = target.y - projectedDY;
-
-
-
- // 处理边界反弹的估算
-
- if (intersectionPoint < 0) {
-
- intersectionPoint = Math.abs(intersectionPoint % screen.height)
-
- } else if (intersectionPoint > screen.height) {
-
- intersectionPoint -= intersectionPoint % screen.height;
-
- }
-
-
-
- // 移动到预计落点
-
- if (intersectionPoint > player.y + (player.height >> 2)) {
-
- player.vy = PADDLE_SPEED; // 向下移动
-
- } else if (intersectionPoint < player.y - (player.height >> 2)) {
-
- player.vy = -PADDLE_SPEED; // 向上移动
-
- } else {
-
- player.vy = 0; // 已在正确位置
-
- }
-
- }
复制代码
6. 特殊功能系统
多球模式控制
javascript
- // 添加球(消耗2分)
-
- controller.A.onEvent(ControllerButtonEvent.Pressed, () => addBall(info.player1));
-
- function addBall(player: info.PlayerInfo) {
-
- player.changeScoreBy(-2);
-
- createBall();
-
- }
-
-
-
- // 移除球(消耗2分,至少保留1个)
-
- controller.B.onEvent(ControllerButtonEvent.Pressed, () => removeBall(info.player1));
-
- function removeBall(player: info.PlayerInfo) {
-
- const balls = sprites.allOfKind(SpriteKind.Enemy);
-
- if (balls.length > 1) {
-
- Math.pickRandom(balls).destroy();
-
- player.changeScoreBy(-2);
-
- }
-
- }
-
- 视觉反馈系统
-
- javascript
-
- game.onShade(function () {
-
- if (pingMessage) {
-
- screen.printCenter("ping", 5);
-
- } else {
-
- screen.printCenter("pong", 5);
-
- }
-
- })
复制代码
|