科学教育

搜索
楼主: ZLJ
打印 上一主题 下一主题

王桃桃

[复制链接]

9

主题

19

帖子

273

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
273
61#
发表于 2024-7-16 20:26:20 | 只看该作者
kaia 发表于 2024-7-16 19:56
好的!来,我们一步一步的看一下这个游戏中的函数调用逻辑链。

假设我们有一个游戏,它的代码长这样:

好的,我还想知道,这个游戏的函数调用逻辑链式什么样的?比如代码最后的initgame函数和startgame函数,但是startgame函数里面我没有找到它继续调用了哪些其他函数,你可以为我解释一下吗
回复 支持 反对

使用道具 举报

0

主题

1145

帖子

1715

积分

版主

Rank: 7Rank: 7Rank: 7

积分
1715
62#
发表于 2024-7-16 20:26:36 | 只看该作者
admin 发表于 2024-07-16 20:26
好的,我还想知道,这个游戏的函数调用逻辑链式什么样 ...


当然可以,王桃桃!我明白了你的问题。我们再来详细看看函数调用的具体流程和逻辑链。

假设我们有一个更复杂的游戏代码,也许是这样的:

  1. function initGame() {
  2.     console.log("Initializing game...");
  3.     startGame();
  4. }

  5. function startGame() {
  6.     console.log("Starting game...");
  7.     setupPlayer();
  8.     setupEnemies();
  9.     runGameLoop();
  10. }

  11. function setupPlayer() {
  12.     console.log("Setting up player...");
  13.     // 设置玩家的初始位置、属性等等
  14. }

  15. function setupEnemies() {
  16.     console.log("Setting up enemies...");
  17.     // 设置敌人的初始位置、属性等等
  18. }

  19. function runGameLoop() {
  20.     console.log("Running game loop...");
  21.     updateGame();
  22. }

  23. function updateGame() {
  24.     console.log("Updating game state...");
  25.     // 更新游戏状态,比如玩家和敌人的位置等
  26.     // 再次调用 runGameLoop,形成游戏循环(一般会有某种条件停止循环)
  27.     requestAnimationFrame(runGameLoop); // 用于浏览器每帧刷新时调用
  28. }

  29. // 游戏从initGame函数开始
  30. initGame();
复制代码


### 分析

1. **`initGame` 函数**
   - 这个是游戏启动时第一个被调用的函数。
   - 它打印 "Initializing game..."。
   - 然后,它调用 `startGame` 函数。

2. **`startGame` 函数**
   - 进入 `startGame` 函数后,它先打印 "Starting game..."。
   - 然后开始调用其它三个函数:`setupPlayer()`、`setupEnemies()` 和 `runGameLoop()`。
   - 注意,这里并没有显示的其他函数调用,因为它们都在 `startGame` 函数内部明确列出来了。

3. **`setupPlayer` 函数**
   - 这个函数负责设置玩家的初始状态。
   - 简单地打印 "Setting up player..." 并完成玩家初始化。

4. **`setupEnemies` 函数**
   - 类似于 `setupPlayer`,这个函数负责编写敌人的初始状态。
   - 它也打印 "Setting up enemies..."。

5. **`runGameLoop` 函数**
   - 这个函数负责运行游戏循环。
   - 打印 "Running game loop..."。
   - 调用 `updateGame()` 函数。

6. **`updateGame` 函数**
   - 在 `updateGame` 函数中,你更新游戏的状态,比如玩家和敌人的位置。
   - 打印 "Updating game state..."。
   - 使用 `requestAnimationFrame(runGameLoop)` 再次调用 `runGameLoop`,以确保游戏循环能一直持续下去。这种方法告诉浏览器在下一次重绘时再次执行 `runGameLoop`。

这里,整个流程的链条是:`initGame` -> `startGame` -> `setupPlayer` -> `setupEnemies` -> `runGameLoop` -> `updateGame` -> `runGameLoop` (循环回去)。

这样就形成了一个不断循环的逻辑链,保证游戏不停地运行下去。

如果有更具体的问题或者需要更深入的解释,请告诉我哦,我会很乐意帮你解答!
回复 支持 反对

使用道具 举报

29

主题

107

帖子

348

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
348
63#
 楼主| 发表于 2024-7-16 20:47:27 | 只看该作者
kaia 发表于 2024-7-16 19:48
你好呀!看起来你正在编写一个贪吃蛇游戏呀,真棒!

你问的是哪部分代码与检测蛇吃食物有关。那让我带你 ...

好的,我还想知道,这个游戏的函数调用逻辑链式什么样的?比如代码最后的initgame函数和startgame函数,但是startgame函数里面我没有找到它继续调用了哪些其他函数,你可以为我解释一下吗
回复 支持 反对

使用道具 举报

29

主题

107

帖子

348

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
348
64#
 楼主| 发表于 2024-7-17 15:55:57 | 只看该作者
kaia 发表于 2024-7-16 20:26
当然可以,王桃桃!我明白了你的问题。我们再来详细看看函数调用的具体流程和逻辑链。

假设我们有一个更 ...

好的,我还想知道,这个游戏的函数调用逻辑链式什么样的?
回复 支持 反对

使用道具 举报

0

主题

1145

帖子

1715

积分

版主

Rank: 7Rank: 7Rank: 7

积分
1715
65#
发表于 2024-7-17 15:56:32 | 只看该作者
ZLJ 发表于 2024-07-17 15:55
好的,我还想知道,这个游戏的函数调用逻辑链式什么样 ...


好的,王桃桃,让我们再深入探讨一下函数调用的逻辑链。假设我们有一段简单的游戏代码,它包括初始化和启动游戏的函数。

### 示例代码

  1. function initGame() {
  2.     console.log("Initializing game...");
  3.     loadResources();
  4.     startGame();
  5. }

  6. function loadResources() {
  7.     console.log("Loading resources...");
  8.     // 在这里加载图片、声音等资源
  9. }

  10. function startGame() {
  11.     console.log("Starting game...");
  12.     setupPlayer();
  13.     setupEnemies();
  14.     runGameLoop();
  15. }

  16. function setupPlayer() {
  17.     console.log("Setting up player...");
  18.     // 设置玩家的初始位置、属性等等
  19. }

  20. function setupEnemies() {
  21.     console.log("Setting up enemies...");
  22.     // 设置敌人的初始位置、属性
  23. }

  24. function runGameLoop() {
  25.     console.log("Running game loop...");
  26.     updateGame();
  27. }

  28. function updateGame() {
  29.     console.log("Updating game state...");
  30.     // 更新游戏状态,比如玩家和敌人的位置等
  31.     requestAnimationFrame(runGameLoop); // 用于浏览器每帧刷新时调用
  32. }

  33. // 游戏从initGame函数开始
  34. initGame();
复制代码


### 详细解释

1. **`initGame` 函数**
   - 首先被调用。
   - 打印 "Initializing game..."。
   - 然后它调用 `loadResources()` 和 `startGame()` 函数。

2. **`loadResources` 函数**
   - 被 `initGame` 调用。
   - 打印 "Loading resources..."。
   - 在这部分你可以加载游戏需要的资源,比如图片、声音等。
   
3. **再次回到 `initGame` 函数**
   - 完成资源加载后,继续调用 `startGame`。

4. **`startGame` 函数**
   - 被 `initGame` 调用。
   - 打印 "Starting game..."。
   - 然后依次调用 `setupPlayer()`、`setupEnemies()` 和 `runGameLoop()` 函数。
   
5. **`setupPlayer` 函数**
   - 被 `startGame` 调用。
   - 打印 "Setting up player..."。
   - 设置玩家的初始状态,比如位置和属性。

6. **`setupEnemies` 函数**
   - 被 `startGame` 调用。
   - 打印 "Setting up enemies..."。
   - 设置敌人的初始状态。

7. **`runGameLoop` 函数**
   - 被 `startGame` 调用。
   - 打印 "Running game loop..."。
   - 调用 `updateGame()` 函数。

8. **`updateGame` 函数**
   - 被 `runGameLoop` 调用。
   - 打印 "Updating game state..."。
   - 更新游戏的状态,比如玩家和敌人的位置。
   - 使用 `requestAnimationFrame(runGameLoop)` 再次调用 `runGameLoop`,形成一个循环。

### 调用逻辑链

现在让我们按照顺序理清整个函数调用的链条:

1. `initGame()`
   - 调用 `loadResources()`
   - 回到 `initGame()`,调用 `startGame()`
2. `startGame()`
   - 调用 `setupPlayer()`
   - 调用 `setupEnemies()`
   - 调用 `runGameLoop()`
3. `runGameLoop()`
   - 调用 `updateGame()`
4. `updateGame()`
   - 调用 `runGameLoop()`(通过 `requestAnimationFrame` 形成循环)

通过这些函数的相互调用,游戏从初始化一直进行到持续的游戏循环中,使得游戏能够不断更新和运行。

希望这个解释对你有帮助!如果还有其他问题,请随时问我哦!
回复 支持 反对

使用道具 举报

29

主题

107

帖子

348

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
348
66#
 楼主| 发表于 2024-7-18 14:06:43 | 只看该作者
你好,这是我的贪吃蛇网页游戏三件套代码:
<!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>贪吃蛇游戏</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <h1>欢迎来到贪吃蛇游戏!</h1>
    <!-- 游戏画布 -->
    <canvas id="gameCanvas"></canvas>
   
    <!-- 游戏结束信息 -->
    <div id="gameOver" style="display: none;" >
        <h1>游戏结束</h1>
        <h2>很遗憾!</h2>
        <p>得分: <span id="score">0</span></p>
        <button onclick="startGame()">开始游戏</button>
    </div>

    <!-- 添加音效文件 -->
    <audio id="eatSound" src="eat.mp3"></audio>

    <script src="script.js"></script>
</body>
</html>


css:
/* styles.css */
body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #000;
    flex-direction: column;
}

canvas {
    border: 1px solid #fff;
}

#gameOver {
    position: absolute;
    text-align: center;
    color: white;
}

button{
padding: 10px 20px;
font-size: 16px;
color: balck;
background-color: #9370DB;
border: none;
border-radius: 5px;
cursor: pointer;
}


js:
// script.js
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");

canvas.width = 400;
canvas.height = 400;

const box = 20;
let snake;
let food;
let d;
let score;
let game;

// 获取音频元素
const eatSound = document.getElementById("eatSound");

// 初始化游戏
function initGame() {
    snake = [
        { x: 9 * box, y: 10 * box }
    ];
    food = {
        x: Math.floor(Math.random() * 19 + 1) * box,
        y: Math.floor(Math.random() * 19 + 1) * box
    };
    score = 0;
    d = null;
}

// 启动游戏
function startGame() {
    document.getElementById("gameOver").style.display = "none";
    initGame();
    if (game) clearInterval(game);
    game = setInterval(draw, 200); // 设置游戏速度为500毫秒
}

// 监听键盘事件
document.addEventListener("keydown", direction);
function direction(event) {
    if (event.keyCode == 37 && d != "RIGHT") {
        d = "LEFT";
    } else if (event.keyCode == 38 && d != "DOWN") {
        d = "UP";
    } else if (event.keyCode == 39 && d != "LEFT") {
        d = "RIGHT";
    } else if (event.keyCode == 40 && d != "UP") {
        d = "DOWN";
    }
}

function collision(newHead, array) {
    for (let i = 0; i < array.length; i++) {
        if (newHead.x === array[i].x && newHead.y === array[i].y) {
            return true;
        }
    }
    return false;
}

// 绘制游戏
function draw() {
    ctx.fillStyle = "#000";
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    for (let i = 0; i < snake.length; i++) {
        ctx.fillStyle = (i === 0) ? "green" : "white";
        ctx.fillRect(snake[i].x, snake[i].y, box, box);

        ctx.strokeStyle = "red";
        ctx.strokeRect(snake[i].x, snake[i].y, box, box);
    }

    ctx.fillStyle = "red";
    ctx.fillRect(food.x, food.y, box, box);

    let snakeX = snake[0].x;
    let snakeY = snake[0].y;

    if (d === "LEFT") snakeX -= box;
    if (d === "UP") snakeY -= box;
    if (d === "RIGHT") snakeX += box;
    if (d === "DOWN") snakeY += box;

    if (snakeX === food.x && snakeY === food.y) {
        score += 1; // 每次吃到食物时分数增加1
        // 播放音效
        eatSound.play();

        food = {
            x: Math.floor(Math.random() * 19 + 1) * box,
            y: Math.floor(Math.random() * 19 + 1) * box
        };
    } else {
        snake.pop();
    }

    let newHead = { x: snakeX, y: snakeY };

    if (snakeX < 0 || snakeY < 0 || snakeX >= canvas.width || snakeY >= canvas.height || collision(newHead, snake)) {
        clearInterval(game);
        document.getElementById("score").innerText = score;
        document.getElementById("gameOver").style.display = "block";
        return;
    }

    snake.unshift(newHead);

    ctx.fillStyle = "white";
    ctx.font = "45px Changa one";
    ctx.fillText(score, 2 * box, 1.6 * box);
}

// 开始游戏
initGame();
startGame();
回复 支持 反对

使用道具 举报

29

主题

107

帖子

348

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
348
67#
 楼主| 发表于 2024-7-27 15:38:22 | 只看该作者
kaia 发表于 2024-7-16 12:01
当然可以!你只需要调整敌人生成的概率,就可以减少敌人的生成数量,从而降低游戏难度。在当前的代码中, ...

你好,我还想修改飞机大战小游戏的整个游戏背景,改成一张星空图片,怎么修改?
回复 支持 反对

使用道具 举报

0

主题

1145

帖子

1715

积分

版主

Rank: 7Rank: 7Rank: 7

积分
1715
68#
发表于 2024-7-27 15:38:39 | 只看该作者
ZLJ 发表于 2024-07-27 15:38
你好,我还想修改飞机大战小游戏的整个游戏背景,改成 ...


当然可以!把游戏的背景替换成一张星空图片会让游戏变得更酷。你只需要在画布上绘制这张图片作为背景即可。下面是详细的步骤:

### 第一步:准备星空图片
首先,请确保你有一张星空图片,并将其保存到与你的 `index.html` 文件同一目录下,比如命名为 `background.jpg`。

### 第二步:修改代码
接着,你需要在 JavaScript 中加载并绘制这张图片。这里是完整的修改步骤:

1. **加载星空图片**:在你的脚本文件顶部,添加代码来加载背景图片。
2. **绘制背景图片**:在每一帧更新时绘制背景图片。

### 修改后的 JavaScript(script.js):

  1. const canvas = document.getElementById('gameCanvas');
  2. const ctx = canvas.getContext('2d');

  3. canvas.width = 600; // 设置画布宽度
  4. canvas.height = 600; // 设置画布高度

  5. const playerWidth = 50;
  6. const playerHeight = 50;
  7. let playerX = (canvas.width - playerWidth) / 2;
  8. let playerY = canvas.height - playerHeight - 10;
  9. const playerSpeed = 7;

  10. let bullets = [];
  11. let enemies = [];
  12. let score = 0;

  13. // 加载飞机图片
  14. const playerImage = new Image();
  15. playerImage.src = 'player.png';

  16. // 加载背景图片
  17. const backgroundImage = new Image();
  18. backgroundImage.src = 'background.jpg';

  19. document.addEventListener('keydown', movePlayer);
  20. document.addEventListener('keydown', shootBullet);

  21. function movePlayer(e) {
  22.     if (e.key === 'ArrowLeft' && playerX > 0) {
  23.         playerX -= playerSpeed;
  24.     }
  25.     if (e.key === 'ArrowRight' && playerX < canvas.width - playerWidth) {
  26.         playerX += playerSpeed;
  27.     }
  28. }

  29. function shootBullet(e) {
  30.     if (e.key === ' ') {
  31.         bullets.push({ x: playerX + playerWidth / 2 - 2.5, y: playerY, speed: 10 });
  32.     }
  33. }

  34. function drawPlayer() {
  35.     const degrees = 45; // 旋转角度
  36.     const radians = degrees * (Math.PI / 180); // 将角度转换为弧度

  37.     ctx.save(); // 保存当前画布状态
  38.     ctx.translate(playerX + playerWidth / 2, playerY + playerHeight / 2); // 将原点移动到图像中心
  39.     ctx.rotate(radians); // 旋转画布
  40.     ctx.drawImage(playerImage, -playerWidth / 2, -playerHeight / 2, playerWidth, playerHeight); // 绘制图像
  41.     ctx.restore(); // 恢复画布到之前保存的状态
  42. }

  43. function drawBullets() {
  44.     ctx.fillStyle = '#ff0';
  45.     bullets.forEach((bullet, index) => {
  46.         bullet.y -= bullet.speed;
  47.         ctx.fillRect(bullet.x, bullet.y, 5, 15);
  48.         if (bullet.y < 0) {
  49.             bullets.splice(index, 1);
  50.         }
  51.     });
  52. }

  53. function drawEnemies() {
  54.     ctx.fillStyle = '#f00';
  55.     enemies.forEach((enemy, index) => {
  56.         enemy.y += enemy.speed;
  57.         ctx.fillRect(enemy.x, enemy.y, enemy.width, enemy.height);
  58.         if (enemy.y > canvas.height) {
  59.             enemies.splice(index, 1);
  60.             gameOver();
  61.         }
  62.     });
  63. }

  64. function generateEnemies() {
  65.     // 调整生成敌人的概率
  66.     if (Math.random() < 0.01) { // 将概率从 0.02 降低到 0.01
  67.         const x = Math.random() * (canvas.width - playerWidth);
  68.         enemies.push({ x: x, y: 0, width: 50, height: 50, speed: 3 });
  69.     }
  70. }

  71. function detectCollisions() {
  72.     bullets.forEach((bullet, bIndex) => {
  73.         enemies.forEach((enemy, eIndex) => {
  74.             if (bullet.x > enemy.x && bullet.x < enemy.x + enemy.width &&
  75.                 bullet.y > enemy.y && bullet.y < enemy.y + enemy.height) {
  76.                 score += 10;
  77.                 bullets.splice(bIndex, 1);
  78.                 enemies.splice(eIndex, 1);
  79.             }
  80.         });
  81.     });

  82.     enemies.forEach(enemy => {
  83.         if (playerX < enemy.x + enemy.width &&
  84.             playerX + playerWidth > enemy.x &&
  85.             playerY < enemy.y + enemy.height &&
  86.             playerY + playerHeight > enemy.y) {
  87.             gameOver();
  88.         }
  89.     });
  90. }

  91. function gameOver() {
  92.     alert(`Game Over! Your score is ${score}`);
  93.     document.location.reload();
  94. }

  95. function drawBackground() {
  96.     ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
  97. }

  98. function update() {
  99.     ctx.clearRect(0, 0, canvas.width, canvas.height);
  100.     drawBackground(); // 绘制背景
  101.     drawPlayer();
  102.     drawBullets();
  103.     drawEnemies();
  104.     detectCollisions();
  105.     generateEnemies();
  106.     requestAnimationFrame(update);
  107. }

  108. update();
复制代码


### 解释:
1. **加载背景图片**:
  
  1. const backgroundImage = new Image();
  2.    backgroundImage.src = 'background.jpg';
复制代码


2. **绘制背景图片**:在 `update` 函数中添加 `drawBackground` 函数来绘制背景图片。
  
  1. function drawBackground() {
  2.        ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
  3.    }
复制代码


3. **在每一帧更新时绘制背景图片**:在 `update` 函数中调用 `drawBackground` 函数。
  
  1. function update() {
  2.        ctx.clearRect(0, 0, canvas.width, canvas.height);
  3.        drawBackground(); // 绘制背景
  4.        drawPlayer();
  5.        drawBullets();
  6.        drawEnemies();
  7.        detectCollisions();
  8.        generateEnemies();
  9.        requestAnimationFrame(update);
  10.    }
复制代码


这样,你的游戏就会有一个漂亮的星空背景啦!如果还有其他问题或者需要进一步的帮助,随时告诉我哦!
回复 支持 反对

使用道具 举报

29

主题

107

帖子

348

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
348
69#
 楼主| 发表于 2024-7-27 15:42:15 | 只看该作者
kaia 发表于 2024-7-27 15:38
当然可以!把游戏的背景替换成一张星空图片会让游戏变得更酷。你只需要在画布上绘制这张图片作为背景即可 ...

可不可以在css或者html里面设置呢?
回复 支持 反对

使用道具 举报

29

主题

107

帖子

348

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
348
70#
 楼主| 发表于 2024-7-27 15:45:37 | 只看该作者
kaia 发表于 2024-7-27 15:38
当然可以!把游戏的背景替换成一张星空图片会让游戏变得更酷。你只需要在画布上绘制这张图片作为背景即可 ...

你好,可不可以在css或者html里面设置呢?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表