【ChatGPT】实现贪吃蛇游戏

贪吃蛇游戏中。以下是实现赛博朋克风格背景的几种方法:

  1. 使用CSS渐变创建赛博朋克风格背景
  2. 使用赛博朋克风格的背景图像
  3. 集成到现有的游戏代码中

方法1:使用CSS渐变创建赛博朋克风格背景

您可以使用CSS的线性渐变来创建一个赛博朋克风格的背景。以下是一个示例:

css 复制代码
.main {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* 赛博朋克风格的渐变背景 */
  background: linear-gradient(135deg, #ff00cc, #333399, #00ccff);
  background-size: 600% 600%;
  animation: GradientAnimation 15s ease infinite;
  position: relative;
}

@keyframes GradientAnimation {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

方法2:使用赛博朋克风格的背景图像

您还可以选择使用赛博朋克风格的背景图像。以下是一些免费资源网站,您可以在这些网站上找到高质量的赛博朋克风格图像:

一旦您选择了喜欢的图像,可以将其设置为背景。以下是如何在代码中实现:

css 复制代码
.main {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* 使用赛博朋克背景图像 */
  background: url('您选择的背景图像URL') no-repeat center center;
  background-size: cover;
  position: relative;
}

方法3:集成到现有的游戏代码中

以下是将赛博朋克风格背景集成到您之前提供的游戏代码中的完整示例。此示例使用CSS渐变创建赛博朋克风格的背景,并保留了其他您之前添加的功能。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>贪吃蛇游戏 - 赛博朋克风格</title>
  <style>
    body {
      display: flex;
      margin: 0;
      height: 100vh;
      font-family: Arial, sans-serif;
      background-color: #121212;
    }
    .sidebar {
      width: 20%;
      padding: 10px;
      background-color: #1e1e1e;
      color: #fff;
      overflow-y: auto;
    }
    .main {
      flex: 1;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      /* 赛博朋克风格的渐变背景 */
      background: linear-gradient(135deg, #ff00cc, #333399, #00ccff);
      background-size: 600% 600%;
      animation: GradientAnimation 15s ease infinite;
      position: relative;
    }
    @keyframes GradientAnimation {
      0% { background-position: 0% 50%; }
      50% { background-position: 100% 50%; }
      100% { background-position: 0% 50%; }
    }
    .controls {
      margin-top: 10px;
    }
    .controls button, .controls input[type="file"] {
      margin: 5px;
      padding: 10px 15px;
      font-size: 14px;
      cursor: pointer;
      border: none;
      border-radius: 5px;
      background-color: #ff00cc;
      color: #fff;
      transition: background-color 0.3s;
    }
    .controls button:hover, .controls input[type="file"]:hover {
      background-color: #333399;
    }
    canvas {
      border: 2px solid #fff;
      background-size: cover;
    }
    .code-editor {
      width: 30%;
      padding: 10px;
      background-color: #1e1e1e;
      color: #fff;
      overflow-y: auto;
    }
    textarea {
      width: 100%;
      height: 80%;
      background-color: #333;
      color: #fff;
      font-family: monospace;
      font-size: 14px;
      padding: 10px;
      border: none;
      outline: none;
      resize: none;
    }
    .code-editor button {
      width: 100%;
      padding: 10px;
      margin-top: 10px;
      background-color: #00ccff;
      color: #fff;
      border: none;
      border-radius: 5px;
      cursor: pointer;
      transition: background-color 0.3s;
    }
    .code-editor button:hover {
      background-color: #333399;
    }
    h3 {
      margin: 10px 0;
      color: #fff;
    }
    ul {
      list-style: none;
      padding: 0;
    }
    li {
      margin: 5px 0;
      padding: 5px;
      background-color: #333399;
      border-radius: 3px;
      text-align: center;
    }
  </style>
</head>
<body>
  <!-- 左侧排行榜 -->
  <div class="sidebar">
    <h3>Leaderboard</h3>
    <ul id="leaderboard"></ul>
  </div>

  <!-- 主区域 -->
  <div class="main">
    <div id="score" style="color: #fff; font-size: 24px; margin-bottom: 10px;">Score: 0</div>
    <canvas id="gameCanvas" width="400" height="400"></canvas>
    <div class="controls">
      <button id="restartButton">Restart</button>
      <button data-speed="150">Easy</button>
      <button data-speed="100">Medium</button>
      <button data-speed="50">Hard</button>
      <input type="file" id="bgUploader" accept="image/*" title="上传背景图">
    </div>
  </div>

  <!-- 右侧代码编辑器 -->
  <div class="code-editor">
    <h3>Game Code</h3>
    <textarea id="codeEditor">// 您可以在这里修改游戏代码
// 例如,改变蛇的颜色:
ctx.fillStyle = 'lime';
</textarea>
    <button id="applyCode">Apply Code</button>
  </div>

  <script>
    const canvas = document.getElementById('gameCanvas');
    const ctx = canvas.getContext('2d');
    const scoreDisplay = document.getElementById('score');
    const restartButton = document.getElementById('restartButton');
    const leaderboardElement = document.getElementById('leaderboard');
    const difficultyButtons = document.querySelectorAll('[data-speed]');
    const bgUploader = document.getElementById('bgUploader');
    const codeEditor = document.getElementById('codeEditor');
    const applyCodeButton = document.getElementById('applyCode');

    // 游戏设置
    const boxSize = 20;
    const canvasSize = 400;
    let score = 0;
    let gameSpeed = 100;
    let gameInterval;
    let bgImage = null;

    // 初始化蛇和食物
    let snake = [{ x: 200, y: 200 }];
    let direction = { x: 0, y: 0 };
    let food = spawnFood();

    // 历史成绩
    let leaderboard = [];

    // 监听键盘输入
    document.addEventListener('keydown', (e) => {
      const key = e.key;
      if (key === 'ArrowUp' && direction.y === 0) {
        direction = { x: 0, y: -boxSize };
      } else if (key === 'ArrowDown' && direction.y === 0) {
        direction = { x: 0, y: boxSize };
      } else if (key === 'ArrowLeft' && direction.x === 0) {
        direction = { x: -boxSize, y: 0 };
      } else if (key === 'ArrowRight' && direction.x === 0) {
        direction = { x: boxSize, y: 0 };
      }
    });

    // 游戏主循环
    function gameLoop() {
      moveSnake();

      if (checkCollision()) {
        endGame();
        return;
      }

      if (snake[0].x === food.x && snake[0].y === food.y) {
        score++;
        scoreDisplay.textContent = 'Score: ' + score;
        snake.push({});
        food = spawnFood();
      }

      ctx.clearRect(0, 0, canvasSize, canvasSize);
      if (bgImage) {
        ctx.drawImage(bgImage, 0, 0, canvasSize, canvasSize);
      } else {
        // 默认背景色
        ctx.fillStyle = '#121212';
        ctx.fillRect(0, 0, canvasSize, canvasSize);
      }
      drawSnake();
      drawFood();
    }

    // 生成随机食物
    function spawnFood() {
      let newFood;
      // 确保食物不会出现在蛇的身体上
      do {
        newFood = {
          x: Math.floor(Math.random() * (canvasSize / boxSize)) * boxSize,
          y: Math.floor(Math.random() * (canvasSize / boxSize)) * boxSize,
        };
      } while (snake.some(segment => segment.x === newFood.x && segment.y === newFood.y));
      return newFood;
    }

    // 绘制蛇
    function drawSnake() {
      ctx.fillStyle = 'lime';
      snake.forEach((segment) => {
        ctx.fillRect(segment.x, segment.y, boxSize, boxSize);
      });
    }

    // 绘制食物
    function drawFood() {
      ctx.fillStyle = 'red';
      ctx.fillRect(food.x, food.y, boxSize, boxSize);
    }

    // 移动蛇
    function moveSnake() {
      const newHead = {
        x: snake[0].x + direction.x,
        y: snake[0].y + direction.y,
      };

      snake.unshift(newHead);
      snake.pop();
    }

    // 检测碰撞
    function checkCollision() {
      const head = snake[0];

      // 撞墙检测
      if (head.x < 0 || head.y < 0 || head.x >= canvasSize || head.y >= canvasSize) {
        return true;
      }

      // 自咬检测
      for (let i = 1; i < snake.length; i++) {
        if (head.x === snake[i].x && head.y === snake[i].y) {
          return true;
        }
      }

      return false;
    }

    // 游戏结束
    function endGame() {
      clearInterval(gameInterval);
      // 碰撞动效:闪烁背景
      let flashes = 10;
      const flashInterval = setInterval(() => {
        if (flashes <= 0) {
          clearInterval(flashInterval);
          alert('Game Over! Your score: ' + score);
          leaderboard.push(score);
          leaderboard.sort((a, b) => b - a);
          updateLeaderboard();
          resetGame();
          return;
        }
        document.querySelector('.main').style.visibility = document.querySelector('.main').style.visibility === 'hidden' ? 'visible' : 'hidden';
        flashes--;
      }, 100);
    }

    // 更新排行榜
    function updateLeaderboard() {
      leaderboardElement.innerHTML = leaderboard.slice(0, 5).map(score => `<li>${score}</li>`).join('');
    }

    // 重置游戏
    function resetGame() {
      clearInterval(gameInterval);
      snake = [{ x: 200, y: 200 }];
      direction = { x: 0, y: 0 };
      food = spawnFood();
      score = 0;
      scoreDisplay.textContent = 'Score: 0';
      document.querySelector('.main').style.visibility = 'visible';
      startGame();
    }

    // 开始游戏
    function startGame() {
      gameInterval = setInterval(gameLoop, gameSpeed);
    }

    // 重新开始按钮点击事件
    restartButton.addEventListener('click', resetGame);

    // 设置难度按钮
    difficultyButtons.forEach(button => {
      button.addEventListener('click', () => {
        gameSpeed = parseInt(button.getAttribute('data-speed'));
        resetGame();
      });
    });

    // 背景图片上传
    bgUploader.addEventListener('change', (e) => {
      const file = e.target.files[0];
      if (!file) return;
      const reader = new FileReader();
      reader.onload = (e) => {
        const img = new Image();
        img.onload = () => {
          bgImage = img;
        };
        img.src = e.target.result;
      };
      reader.readAsDataURL(file);
    });

    // 代码编辑器应用按钮
    applyCodeButton.addEventListener('click', () => {
      try {
        // 使用Function构造器代替eval以提高安全性
        const userCode = codeEditor.value;
        const userFunction = new Function('ctx', 'boxSize', userFunctionBody(userCode));
        // 重新绘制蛇时应用用户代码
        drawSnake = () => {
          userFunction(ctx, boxSize);
          snake.forEach((segment) => {
            ctx.fillRect(segment.x, segment.y, boxSize, boxSize);
          });
        };
      } catch (err) {
        alert('Invalid code!');
        console.error(err);
      }
    });

    // 辅助函数:提取用户函数体
    function userFunctionBody(code) {
      // 简单地返回用户代码
      return code;
    }

    // 初始化游戏
    startGame();
  </script>
</body>
</html>

新增功能详解

  1. 赛博朋克风格背景

    • CSS渐变:使用线性渐变和动画效果,创建动态的赛博朋克风格背景。
    • 背景图像上传:用户可以上传自己的赛博朋克风格背景图像,图像将覆盖游戏画布背景。
  2. 排行榜位置调整

    • 将排行榜放置在页面的左侧,使用深色背景和霓虹色字体,符合赛博朋克主题。
  3. 代码编辑器位置调整

    • 将代码编辑器放置在页面的右侧,采用暗色主题,增强赛博朋克氛围。
    • 用户可以在代码编辑器中自定义游戏代码,并点击"Apply Code"按钮应用更改。
  4. 碰撞动效

    • 游戏结束时,主区域会闪烁几下,以模拟碰撞效果,然后弹出游戏结束提示并更新排行榜。

使用说明

  1. 赛博朋克背景

    • 默认情况下,主游戏区域有一个动态的赛博朋克风格渐变背景。
    • 用户可以点击"上传背景图"按钮,选择本地的赛博朋克风格图像,图像将应用为游戏背景。
  2. 排行榜

    • 左侧栏显示历史最高分数,最多显示前五名。
  3. 代码编辑器

    • 右侧的代码编辑器允许用户自定义游戏代码,例如更改蛇的颜色或其他绘制属性。
    • 修改代码后,点击"Apply Code"按钮应用更改。
  4. 游戏控制

    • 使用方向键控制蛇的移动方向。
    • 点击"Restart"按钮可以重新开始游戏。
    • 点击"Easy"、"Medium"或"Hard"按钮可以调整游戏速度并重新开始。

自定义建议

  • 增强赛博朋克效果:您可以进一步增强赛博朋克风格,例如添加霓虹灯效果、粒子效果或使用赛博朋克风格的图标和字体。
  • 改进碰撞动效:可以使用更多的动画效果,如闪光、震动或渐变颜色变化,以使碰撞效果更加生动。
  • 代码编辑器功能扩展 :可以集成更强大的代码编辑器库,如 CodeMirrorMonaco Editor,以提供更好的用户体验和代码高亮功能。

示例赛博朋克背景图像

如果您需要一个默认的赛博朋克风格背景图像,可以使用以下免费资源之一:

将下载的图像上传到游戏中,即可应用为背景。

结语

通过上述方法,您可以将贪吃蛇游戏打造成为一个具有赛博朋克风格的视觉体验。希望这些改进能够满足您的需求,并为您的游戏增添更多乐趣和个性化元素!

相关推荐
恩爸编程4 分钟前
纯前端js完成游戏吃豆人
前端·javascript·游戏·游戏程序·开源软件·游戏策划·游戏机
FairGuard手游加固4 小时前
FairGuard游戏加固实机演示
游戏
学习前端的小z11 小时前
【GPTs】Front-end Expert:助力前端开发的智能工具
人工智能·gpt·chatgpt·aigc
傻啦嘿哟12 小时前
代理IP:苹果Siri与ChatGPT Plus融合的关键助力
网络协议·tcp/ip·chatgpt
xianghan收藏册12 小时前
基于lora的llama2二次预训练
人工智能·深度学习·机器学习·chatgpt·transformer
像污秽一样13 小时前
根据气候变化自动制定鲜花存储策略(BabyAGI)
人工智能·chatgpt·langchain
Mac分享吧14 小时前
狂野飙车8+(Asphalt 8+) for Mac 赛车竞速游戏 安装教程
游戏·macos·游戏程序·macbook·玩游戏·苹果电脑·狂野飙车
Roc-xb15 小时前
ChatGPT 桌面版发布了,如何安装?
chatgpt
努力学习的啊张15 小时前
OpenAI 首席产品官:ChatGPT 网页端本周引入高级语音模式
人工智能·gpt·chatgpt·文心一言·ai编程·chatgpt语音