部署DeepSeek模型,进群交流最in玩法!
立即加群
发布
社区首页 >专栏 >从零到一:腾讯云 AI 代码助手 + DeepSeek 写一个浏览器插件

从零到一:腾讯云 AI 代码助手 + DeepSeek 写一个浏览器插件

作者头像
全栈若城
发布2025-02-28 09:02:28
发布2025-02-28 09:02:28
7900
代码可运行
举报
文章被收录于专栏:若城技术专栏若城技术专栏
运行总次数:0
代码可运行
腾讯云 AI 代码助手 + DeepSeek 写一个浏览器插件

需求如下:

代码语言:javascript
代码运行次数:0
复制
 我现在要做一个Google 的浏览器插件, 该浏览器插件的核心功能是一款贪吃蛇的游戏, 此外我不希望这款游戏中存在任何图片素材, 关于该游戏的具体开发思路我没有相关规划, 请你先帮我生成一份具体的规划,然后根据这个规划开始生成前端的相关代码,
 技术栈要求:vite/ts/vue3/支持 vue3 的 UI 框架等,我拥有相关的开发环境,需要你从创建项目到代码编写一步一步的实现功能

下面是腾讯云AI代码助手给我的全部回复:

项目规划
一、项目结构规划
代码语言:javascript
代码运行次数:0
复制
chrome-snake-extension/
├── public/                 # 静态资源
│   └── manifest.json       # Chrome扩展配置文件
├── src/
│   ├── assets/             # 样式文件
│   │   └── game.css        
│   ├── components/         # Vue组件
│   │   └── GameBoard.vue   # 游戏核心组件
│   ├── utils/
│   │   └── gameLogic.ts    # 游戏核心逻辑
│   ├── background.ts       # 后台服务脚本
│   └── main.ts             # 入口文件
├── index.html
├── vite.config.ts          # Vite配置
└── package.json
二、开发步骤分解
  1. 创建项目 & 初始化
  2. Chrome扩展配置
  3. 游戏画布基础搭建
  4. 核心游戏逻辑实现
  5. 用户交互与UI美化
  6. 浏览器扩展功能集成
  7. 测试与打包
代码实现(分步骤指导)
步骤1:创建项目
代码语言:javascript
代码运行次数:0
复制
npm create vite@latest chrome-snake-extension -- --template vue-ts
cd chrome-snake-extension
npm install
步骤2:配置Chrome扩展

public/manifest.json

代码语言:javascript
代码运行次数:0
复制
{
  "manifest_version": 3,
  "name": "Vue Snake",
  "version": "1.0",
  "description": "A modern Snake game extension",
  "action": {
    "default_popup": "index.html",
    "default_icon": {
      "16": "icon16.png",
      "48": "icon48.png",
      "128": "icon128.png"
    }
  },
  "permissions": ["storage"],
  "background": {
    "service_worker": "background.js"
  },
  "icons": {
    "16": "icon16.png",
    "48": "icon48.png",
    "128": "icon128.png"
  }
}
步骤3:基础游戏组件

src/components/GameBoard.vue

代码语言:javascript
代码运行次数:0
复制
<template>
  <div class="game-container">
    <canvas ref="gameCanvas"></canvas>
    <div class="control-panel">
      <div class="score-board">
        Score: {{ score }} | High Score: {{ highScore }}
      </div>
      <button @click="toggleGame">
        {{ isPlaying ? 'Pause' : 'Start' }}
      </button>
      <button @click="resetGame">Reset</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { GameEngine } from '../utils/gameLogic';

const gameCanvas = ref<HTMLCanvasElement>();
const score = ref(0);
const highScore = ref(0);
const isPlaying = ref(false);
let gameEngine: GameEngine;

// 初始化游戏引擎
onMounted(() => {
  if (gameCanvas.value) {
    gameEngine = new GameEngine({
      canvas: gameCanvas.value,
      onScoreUpdate: (newScore) => {
        score.value = newScore;
        if (newScore > highScore.value) {
          highScore.value = newScore;
        }
      },
      onGameOver: () => {
        isPlaying.value = false;
      }
    });
  }
});

// 游戏控制
const toggleGame = () => {
  isPlaying.value ? gameEngine.pause() : gameEngine.start();
  isPlaying.value = !isPlaying.value;
};

const resetGame = () => {
  gameEngine.reset();
  score.value = 0;
  isPlaying.value = false;
};

// 键盘事件监听
const handleKeyPress = (e: KeyboardEvent) => {
  if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {
    e.preventDefault();
    gameEngine.changeDirection(e.key.replace('Arrow', '').toLowerCase() as Direction);
  }
};

onMounted(() => window.addEventListener('keydown', handleKeyPress));
onUnmounted(() => window.removeEventListener('keydown', handleKeyPress));
</script>
步骤4:核心游戏逻辑

src/utils/gameLogic.ts

代码语言:javascript
代码运行次数:0
复制
type Direction = 'up' | 'down' | 'left' | 'right';
type Position = { x: number; y: number };

interface GameConfig {
  canvas: HTMLCanvasElement;
  gridSize?: number;
  onScoreUpdate?: (score: number) => void;
  onGameOver?: () => void;
}

export class GameEngine {
  private ctx: CanvasRenderingContext2D;
  private gridSize: number;
  private snake: Position[] = [];
  private food: Position = { x: 0, y: 0 };
  private direction: Direction = 'right';
  private nextDirection: Direction = 'right';
  private gameLoopId: number | null = null;
  private score = 0;

  constructor(private config: GameConfig) {
    this.ctx = config.canvas.getContext('2d')!;
    this.gridSize = config.gridSize || 20;
    
    // 初始化画布尺寸
    config.canvas.width = 400;
    config.canvas.height = 400;
    
    this.reset();
  }

  private generateFood() {
    do {
      this.food = {
        x: Math.floor(Math.random() * (this.ctx.canvas.width / this.gridSize)),
        y: Math.floor(Math.random() * (this.ctx.canvas.height / this.gridSize))
      };
    } while (this.snake.some(segment => 
      segment.x === this.food.x && segment.y === this.food.y
    ));
  }

  private draw() {
    // 清空画布
    this.ctx.fillStyle = '#2c3e50';
    this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);

    // 绘制食物
    this.ctx.fillStyle = '#e74c3c';
    this.ctx.fillRect(
      this.food.x * this.gridSize,
      this.food.y * this.gridSize,
      this.gridSize - 2,
      this.gridSize - 2
    );

    // 绘制蛇
    this.snake.forEach((segment, index) => {
      this.ctx.fillStyle = index === 0 ? '#3498db' : '#2980b9';
      this.ctx.fillRect(
        segment.x * this.gridSize,
        segment.y * this.gridSize,
        this.gridSize - 2,
        this.gridSize - 2
      );
    });
  }

  private move() {
    const head = { ...this.snake[0] };
    
    this.direction = this.nextDirection;
    
    switch (this.direction) {
      case 'up': head.y--; break;
      case 'down': head.y++; break;
      case 'left': head.x--; break;
      case 'right': head.x++; break;
    }

    // 碰撞检测
    if (
      head.x < 0 || head.x >= this.ctx.canvas.width / this.gridSize ||
      head.y < 0 || head.y >= this.ctx.canvas.height / this.gridSize ||
      this.snake.some(segment => segment.x === head.x && segment.y === head.y)
    ) {
      this.config.onGameOver?.();
      return;
    }

    this.snake.unshift(head);

    // 吃到食物
    if (head.x === this.food.x && head.y === this.food.y) {
      this.score++;
      this.config.onScoreUpdate?.(this.score);
      this.generateFood();
    } else {
      this.snake.pop();
    }
  }

  start() {
    if (!this.gameLoopId) {
      const gameStep = () => {
        this.move();
        this.draw();
        this.gameLoopId = requestAnimationFrame(gameStep);
      };
      gameStep();
    }
  }

  pause() {
    if (this.gameLoopId) {
      cancelAnimationFrame(this.gameLoopId);
      this.gameLoopId = null;
    }
  }

  reset() {
    this.pause();
    this.snake = [{ x: 5, y: 5 }];
    this.direction = 'right';
    this.nextDirection = 'right';
    this.score = 0;
    this.generateFood();
    this.draw();
  }

  changeDirection(newDirection: Direction) {
    const oppositeDirections: Record<Direction, Direction> = {
      up: 'down',
      down: 'up',
      left: 'right',
      right: 'left'
    };
    
    if (newDirection !== oppositeDirections[this.direction]) {
      this.nextDirection = newDirection;
    }
  }
}
步骤5:样式设计

src/assets/game.css

代码语言:javascript
代码运行次数:0
复制
.game-container {
  width: 400px;
  padding: 20px;
  background: #34495e;
  border-radius: 10px;
  color: white;
}

canvas {
  border: 2px solid #2c3e50;
  border-radius: 5px;
}

.control-panel {
  margin-top: 15px;
  display: flex;
  gap: 10px;
  align-items: center;
}

button {
  padding: 8px 15px;
  background: #3498db;
  border: none;
  border-radius: 4px;
  color: white;
  cursor: pointer;
  transition: background 0.3s;
}

button:hover {
  background: #2980b9;
}

.score-board {
  flex-grow: 1;
  font-family: monospace;
}
步骤6:入口文件调整

src/main.ts

代码语言:javascript
代码运行次数:0
复制
import { createApp } from 'vue'
import './assets/game.css'
import GameBoard from './components/GameBoard.vue'

createApp(GameBoard).mount('#app')
步骤7:测试与打包
  1. 在Chrome浏览器访问 chrome://extensions
  2. 开启"开发者模式"
  3. 点击"加载已解压的扩展程序",选择项目目录
  4. 测试游戏功能
  5. 打包:
代码语言:javascript
代码运行次数:0
复制
npm run build
功能扩展建议
  1. 添加难度选择(调整游戏速度)
  2. 实现主题切换功能
  3. 增加音效(使用Web Audio API)
  4. 添加在线排行榜功能
  5. 支持触摸操作(移动端适配)

这个实现方案完全使用矢量图形绘制,不依赖任何图片素材,核心游戏逻辑与UI组件分离,便于维护和扩展。游戏控制逻辑完整包含开始/暂停/重置功能,并实现了经典贪吃蛇的所有核心机制。

跟从腾讯ai代码助手的建议进行开发

npm run build 时报错,如下图所示

此时我们将报错内容复制给腾讯AI 代码助手,给出的建议如下图所示:

此时可以build 成功了

将dist 文件加载到扩展

我们安装 步骤7:测试与打包 的流程 将dist 文件加载到扩展程序, 报错如下, 我们依旧将报错信息复制给腾讯ai 代码助手

腾讯AI 代码给出的解决方案如下

第一部分:修复 TypeScript 的 Direction 类型错误
  1. GameBoard.vue 顶部添加类型定义
代码语言:javascript
代码运行次数:0
复制
<script setup lang="ts">
// 新增类型定义 -------------------
type Direction = 'up' | 'down' | 'left' | 'right';
// ------------------------------

// 原有代码
const handleKeyPress = (e: KeyboardEvent) => {
  if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.key)) {
    e.preventDefault();
    gameEngine.changeDirection(
      e.key.replace("Arrow", "").toLowerCase() as Direction
    );
  }
};
// ...其他代码
</script>

第二部分:解决 Chrome 扩展加载失败问题
  1. 确保项目结构正确
代码语言:javascript
代码运行次数:0
复制
chrome-snake-extension/
├── public/
│   ├── manifest.json
│   └── icons/ (如果有图标)
├── src/
│   └── ...其他源码
└── vite.config.ts
  1. 配置 vite.config.ts
代码语言:javascript
代码运行次数:0
复制
import { defineConfig } from 'vite'
import { resolve } from 'path'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  build: {
    rollupOptions: {
      input: {
        main: resolve(__dirname, 'index.html')
      },
      output: {
        // 确保静态资源在 assets 目录
        assetFileNames: 'assets/[name].[ext]'
      }
    },
    // 输出到 dist 目录
    outDir: 'dist'
  }
})
  1. 示例 manifest.json
代码语言:javascript
代码运行次数:0
复制
{
  "manifest_version": 3,
  "name": "Snake Game",
  "version": "1.0",
  "action": {
    "default_popup": "index.html"
  },
  "background": {
    "service_worker": "background.js"
  },
  "permissions": ["storage"]
}
  1. 创建背景脚本文件: 在 public 目录下创建 background.js(可以是空文件,暂时用于测试)

第三部分:验证修复
  1. 重新构建项目:
代码语言:javascript
代码运行次数:0
复制
npm run build
  1. 检查 dist 目录结构:
代码语言:javascript
代码运行次数:0
复制
dist/
├── assets/
│   ├── index.[hash].js
│   └── ...
├── index.html
├── manifest.json
└── background.js
  1. 在 Chrome 中加载扩展:
  • 打开 chrome://extensions
  • 开启 “Developer mode”
  • 点击 “Load unpacked”
  • 选择整个 dist 目录

常见问题排查:
  1. 如果出现 background.js 404 错误:
  • vite.config.ts 中添加复制插件:
代码语言:javascript
代码运行次数:0
复制
npm install rollup-plugin-copy --save-dev
代码语言:javascript
代码运行次数:0
复制
// vite.config.ts
import copy from 'rollup-plugin-copy'

export default defineConfig({
  plugins: [
    vue(),
    copy({
      targets: [
        { src: 'public/*', dest: 'dist' }
      ],
      hook: 'writeBundle'
    })
  ]
})
  1. 如果使用 Manifest V3:
  • 确保所有脚本使用 ES modules:
代码语言:javascript
代码运行次数:0
复制
{
  "background": {
    "service_worker": "background.js",
    "type": "module"
  }
}

效果展示

按照腾讯云ai 代码给出的建议, 我们修改后重新运行 效果如下图所示

问题

体验过程中发现 运行速度过快等问题, 此时依旧可以通过 代码助手来逐步优化, 这里就不过多讲解啦。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-02-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 腾讯云 AI 代码助手 + DeepSeek 写一个浏览器插件
  • 项目规划
  • 代码实现(分步骤指导)
  • 功能扩展建议
  • 跟从腾讯ai代码助手的建议进行开发
  • 将dist 文件加载到扩展
  • 腾讯AI 代码给出的解决方案如下
    • 第一部分:修复 TypeScript 的 Direction 类型错误
    • 第二部分:解决 Chrome 扩展加载失败问题
    • 第三部分:验证修复
    • 常见问题排查:
    • 效果展示
    • 问题
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档