{"id":"d48826a3-b625-452d-a276-6b4fc39a2257","name":"AI-坦克像素大战","type":"window","description":"长按方向键移动，空格发射子弹","matches":["*://*/*"],"code":"// 创建游戏容器\nconst gameContainer = document.createElement('div');\ngameContainer.style.width = '400px';\ngameContainer.style.height = '400px';\ngameContainer.style.backgroundColor = '#000';\ngameContainer.style.position = 'relative';\ngameContainer.style.margin = '0 auto';\ngameContainer.style.overflow = 'hidden';\ndocument.body.appendChild(gameContainer);\n\n// 游戏常量\nconst GRID_SIZE = 20;\nconst GAME_WIDTH = 400;\nconst GAME_HEIGHT = 400;\nconst TANK_SPEED = 2;\nconst BULLET_SPEED = 5;\nconst AI_UPDATE_INTERVAL = 1000;\n\n// 游戏对象\nconst game = {\n  player: null,\n  enemies: [],\n  bullets: [],\n  walls: [],\n  gameOver: false,\n  score: 0,\n  lastAITime: 0\n};\n\n// 坦克类\nclass Tank {\n  constructor(x, y, color, isPlayer = false) {\n    this.x = x;\n    this.y = y;\n    this.width = GRID_SIZE;\n    this.height = GRID_SIZE;\n    this.color = color;\n    this.direction = isPlayer ? 'up' : 'down'; // 玩家默认向上，敌人默认向下\n    this.isPlayer = isPlayer;\n    this.speed = TANK_SPEED;\n    this.cooldown = 0;\n    this.element = document.createElement('div');\n    this.updateElement();\n    gameContainer.appendChild(this.element);\n  }\n\n  updateElement() {\n    this.element.style.position = 'absolute';\n    this.element.style.left = `${this.x}px`;\n    this.element.style.top = `${this.y}px`;\n    this.element.style.width = `${this.width}px`;\n    this.element.style.height = `${this.height}px`;\n    this.element.style.backgroundColor = this.color;\n  }\n\n  move(direction) {\n    if (this.direction !== direction) {\n      this.direction = direction;\n      return;\n    }\n\n    let newX = this.x;\n    let newY = this.y;\n\n    switch (direction) {\n      case 'up':\n        newY = Math.max(0, this.y - this.speed);\n        break;\n      case 'down':\n        newY = Math.min(GAME_HEIGHT - this.height, this.y + this.speed);\n        break;\n      case 'left':\n        newX = Math.max(0, this.x - this.speed);\n        break;\n      case 'right':\n        newX = Math.min(GAME_WIDTH - this.width, this.x + this.speed);\n        break;\n    }\n\n    if (!this.checkCollision(newX, newY)) {\n      this.x = newX;\n      this.y = newY;\n      this.updateElement();\n    }\n  }\n\n  checkCollision(x, y) {\n    // 边界检查\n    if (x < 0 || x + this.width > GAME_WIDTH || y < 0 || y + this.height > GAME_HEIGHT) {\n      return true;\n    }\n\n    // 墙壁碰撞检查\n    for (const wall of game.walls) {\n      if (\n        x < wall.x + wall.width &&\n        x + this.width > wall.x &&\n        y < wall.y + wall.height &&\n        y + this.height > wall.y\n      ) {\n        return true;\n      }\n    }\n\n    // 坦克碰撞检查\n    const tanks = this.isPlayer ? game.enemies : [game.player];\n    for (const tank of tanks) {\n      if (tank && \n          x < tank.x + tank.width &&\n          x + this.width > tank.x &&\n          y < tank.y + tank.height &&\n          y + this.height > tank.y\n      ) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n\n  fire() {\n    if (this.cooldown > 0) return;\n\n    let bulletX, bulletY;\n    switch (this.direction) {\n      case 'up':\n        bulletX = this.x + this.width / 2 - 2;\n        bulletY = this.y - 4;\n        break;\n      case 'down':\n        bulletX = this.x + this.width / 2 - 2;\n        bulletY = this.y + this.height;\n        break;\n      case 'left':\n        bulletX = this.x - 4;\n        bulletY = this.y + this.height / 2 - 2;\n        break;\n      case 'right':\n        bulletX = this.x + this.width;\n        bulletY = this.y + this.height / 2 - 2;\n        break;\n    }\n\n    game.bullets.push(new Bullet(bulletX, bulletY, this.direction, this.isPlayer));\n    this.cooldown = 20;\n  }\n\n  update() {\n    if (this.cooldown > 0) {\n      this.cooldown--;\n    }\n  }\n\n  destroy() {\n    gameContainer.removeChild(this.element);\n    if (this.isPlayer) {\n      game.player = null;\n      game.gameOver = true;\n    } else {\n      game.enemies = game.enemies.filter(enemy => enemy !== this);\n      game.score += 100;\n    }\n  }\n}\n\n// 子弹类\nclass Bullet {\n  constructor(x, y, direction, isPlayer) {\n    this.x = x;\n    this.y = y;\n    this.width = 4;\n    this.height = 4;\n    this.direction = direction;\n    this.speed = BULLET_SPEED;\n    this.isPlayer = isPlayer;\n    this.element = document.createElement('div');\n    this.updateElement();\n    gameContainer.appendChild(this.element);\n  }\n\n  updateElement() {\n    this.element.style.position = 'absolute';\n    this.element.style.left = `${this.x}px`;\n    this.element.style.top = `${this.y}px`;\n    this.element.style.width = `${this.width}px`;\n    this.element.style.height = `${this.height}px`;\n    this.element.style.backgroundColor = this.isPlayer ? '#0f0' : '#f00';\n  }\n\n  update() {\n    switch (this.direction) {\n      case 'up':\n        this.y -= this.speed;\n        break;\n      case 'down':\n        this.y += this.speed;\n        break;\n      case 'left':\n        this.x -= this.speed;\n        break;\n      case 'right':\n        this.x += this.speed;\n        break;\n    }\n\n    this.updateElement();\n\n    // 检查是否超出边界\n    if (\n      this.x < 0 ||\n      this.x > GAME_WIDTH ||\n      this.y < 0 ||\n      this.y > GAME_HEIGHT\n    ) {\n      this.destroy();\n      return;\n    }\n\n    // 检查碰撞\n    this.checkCollision();\n  }\n\n  checkCollision() {\n    // 检查墙壁碰撞\n    for (const wall of game.walls) {\n      if (\n        this.x < wall.x + wall.width &&\n        this.x + this.width > wall.x &&\n        this.y < wall.y + wall.height &&\n        this.y + this.height > wall.y\n      ) {\n        this.destroy();\n        return;\n      }\n    }\n\n    // 检查坦克碰撞\n    const tanks = this.isPlayer ? game.enemies : [game.player];\n    for (const tank of tanks) {\n      if (tank && \n          this.x < tank.x + tank.width &&\n          this.x + this.width > tank.x &&\n          this.y < tank.y + tank.height &&\n          this.y + this.height > tank.y\n      ) {\n        tank.destroy();\n        this.destroy();\n        return;\n      }\n    }\n\n    // 检查子弹碰撞\n    for (const bullet of game.bullets) {\n      if (bullet !== this && \n          bullet.isPlayer !== this.isPlayer &&\n          this.x < bullet.x + bullet.width &&\n          this.x + this.width > bullet.x &&\n          this.y < bullet.y + bullet.height &&\n          this.y + this.height > bullet.y\n      ) {\n        bullet.destroy();\n        this.destroy();\n        return;\n      }\n    }\n  }\n\n  destroy() {\n    gameContainer.removeChild(this.element);\n    game.bullets = game.bullets.filter(bullet => bullet !== this);\n  }\n}\n\n// 墙壁类\nclass Wall {\n  constructor(x, y) {\n    this.x = x;\n    this.y = y;\n    this.width = GRID_SIZE;\n    this.height = GRID_SIZE;\n    this.element = document.createElement('div');\n    this.element.style.position = 'absolute';\n    this.element.style.left = `${x}px`;\n    this.element.style.top = `${y}px`;\n    this.element.style.width = `${this.width}px`;\n    this.element.style.height = `${this.height}px`;\n    this.element.style.backgroundColor = '#888';\n    gameContainer.appendChild(this.element);\n  }\n}\n\n// 初始化游戏\nfunction initGame() {\n  // 清除所有元素\n  while (gameContainer.firstChild) {\n    gameContainer.removeChild(gameContainer.firstChild);\n  }\n\n  // 重置游戏状态\n  game.player = null;\n  game.enemies = [];\n  game.bullets = [];\n  game.walls = [];\n  game.gameOver = false;\n  game.score = 0;\n  game.lastAITime = 0;\n\n  // 创建玩家坦克\n  game.player = new Tank(\n    GAME_WIDTH / 2 - GRID_SIZE / 2,\n    GAME_HEIGHT - GRID_SIZE * 2,\n    '#0f0',\n    true\n  );\n\n  // 创建敌人坦克\n  for (let i = 0; i < 3; i++) {\n    game.enemies.push(\n      new Tank(\n        GRID_SIZE * 2 + i * GRID_SIZE * 4,\n        GRID_SIZE,\n        '#f00'\n      )\n    );\n  }\n\n  // 创建墙壁\n  for (let i = 0; i < 10; i++) {\n    const x = Math.floor(Math.random() * (GAME_WIDTH / GRID_SIZE)) * GRID_SIZE;\n    const y = Math.floor(Math.random() * (GAME_HEIGHT / GRID_SIZE)) * GRID_SIZE;\n    \n    // 确保墙壁不会生成在玩家或敌人初始位置\n    if (\n      !(x === game.player.x && y === game.player.y) &&\n      !game.enemies.some(enemy => enemy.x === x && enemy.y === y)\n    ) {\n      game.walls.push(new Wall(x, y));\n    }\n  }\n\n  // 创建分数显示\n  const scoreElement = document.createElement('div');\n  scoreElement.style.position = 'absolute';\n  scoreElement.style.top = '10px';\n  scoreElement.style.left = '10px';\n  scoreElement.style.color = '#fff';\n  scoreElement.style.fontFamily = 'Arial';\n  scoreElement.style.fontSize = '16px';\n  scoreElement.id = 'score';\n  gameContainer.appendChild(scoreElement);\n  updateScore();\n\n  // 添加键盘监听\n  document.addEventListener('keydown', handleKeyDown);\n}\n\n// 更新分数显示\nfunction updateScore() {\n  const scoreElement = document.getElementById('score');\n  if (scoreElement) {\n    scoreElement.textContent = `Score: ${game.score}`;\n  }\n}\n\n// 键盘控制\nfunction handleKeyDown(e) {\n  if (game.gameOver || !game.player) return;\n\n  switch (e.key) {\n    case 'ArrowUp':\n      game.player.move('up');\n      break;\n    case 'ArrowDown':\n      game.player.move('down');\n      break;\n    case 'ArrowLeft':\n      game.player.move('left');\n      break;\n    case 'ArrowRight':\n      game.player.move('right');\n      break;\n    case ' ':\n      game.player.fire();\n      break;\n  }\n}\n\n// AI控制\nfunction updateAI() {\n  const now = Date.now();\n  if (now - game.lastAITime < AI_UPDATE_INTERVAL) return;\n  game.lastAITime = now;\n\n  for (const enemy of game.enemies) {\n    // 随机移动或开火\n    const action = Math.floor(Math.random() * 5);\n    switch (action) {\n      case 0:\n        enemy.move('up');\n        break;\n      case 1:\n        enemy.move('down');\n        break;\n      case 2:\n        enemy.move('left');\n        break;\n      case 3:\n        enemy.move('right');\n        break;\n      case 4:\n        enemy.fire();\n        break;\n    }\n  }\n}\n\n// 游戏循环\nfunction gameLoop() {\n  if (game.gameOver) {\n    // 游戏结束显示\n    const gameOverElement = document.createElement('div');\n    gameOverElement.style.position = 'absolute';\n    gameOverElement.style.top = '50%';\n    gameOverElement.style.left = '50%';\n    gameOverElement.style.transform = 'translate(-50%, -50%)';\n    gameOverElement.style.color = '#fff';\n    gameOverElement.style.fontFamily = 'Arial';\n    gameOverElement.style.fontSize = '24px';\n    gameOverElement.textContent = `Game Over! Score: ${game.score}`;\n    gameContainer.appendChild(gameOverElement);\n\n    const restartButton = document.createElement('button');\n    restartButton.textContent = 'Restart';\n    restartButton.style.marginTop = '20px';\n    restartButton.style.padding = '10px 20px';\n    restartButton.addEventListener('click', initGame);\n    gameOverElement.appendChild(restartButton);\n\n    return;\n  }\n\n  // 更新AI\n  updateAI();\n\n  // 更新所有坦克\n  if (game.player) game.player.update();\n  for (const enemy of game.enemies) {\n    enemy.update();\n  }\n\n  // 更新所有子弹\n  for (const bullet of game.bullets) {\n    bullet.update();\n  }\n\n  // 检查游戏状态\n  if (game.enemies.length === 0) {\n    // 所有敌人都被消灭，生成新的敌人\n    for (let i = 0; i < 3; i++) {\n      game.enemies.push(\n        new Tank(\n          GRID_SIZE * 2 + i * GRID_SIZE * 4,\n          GRID_SIZE,\n          '#f00'\n        )\n      );\n    }\n  }\n\n  // 更新分数\n  updateScore();\n\n  // 继续游戏循环\n  requestAnimationFrame(gameLoop);\n}\n\n// 开始游戏\ninitGame();\ngameLoop();","installTime":1735710700240,"author":"script dog","version":"1.0.0","enabled":true,"source":"{\"blocks\":{\"languageVersion\":0,\"blocks\":[{\"type\":\"test_demo_one\",\"id\":\"O+pzkj7xL5P~hE=72r7J\",\"x\":374,\"y\":154},{\"type\":\"test_demo_two\",\"id\":\"iPC;7.H(:ug$OS4GmmIA\",\"x\":367,\"y\":235}]},\"variables\":[{\"name\":\"i\",\"id\":\"B*8^FllO$)scycG3qU1v\"},{\"name\":\"j\",\"id\":\"XRM+jysw9|)xV=Ot{i`5\"},{\"name\":\"var1\",\"id\":\"si}k.E3)6Bb9PC8{GB6K\"}]}","runAt":"document_idle","showRunLogo":false,"useGM":false,"useDog":true,"templates":{},"updateTime":1791619148085,"size":11750,"window":{"icon":"","title":"","left":0,"top":0,"width":"445","height":"440"},"programmingType":"text","loading":false}