vue.js 课程自己编写小游戏

一、太空大战

复制代码
<template>
  <div class="game" @keydown="onKey" tabindex="0">
    <div class="score">分数:{{ score }}</div>

    <!-- 子弹 -->
    <div
      class="bullet"
      v-for="(b, i) in bullets"
      :key="i"
      :style="{ left: b.x + 'px', top: b.y + 'px' }"
    ></div>

    <!-- 怪物 -->
    <div
      class="enemy"
      v-for="(e, i) in enemys"
      :key="i"
      :style="{ left: e.x + 'px', top: e.y + 'px' }"
    >👾</div>

    <!-- 飞机 -->
    <div class="plane" :style="{ left: planeX + 'px' }">✈️</div>

    <!-- 游戏结束 -->
    <div class="game-over" v-if="gameOver">
      <h2>游戏结束</h2>
      <p>最终得分:{{ score }}</p>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const planeX = ref(200)
const bullets = ref([])
const enemys = ref([])
const score = ref(0)
const gameOver = ref(false)

// 左右移动 + 空格发射
const onKey = (e) => {
  if (gameOver.value) return
  if (e.key === 'ArrowLeft') planeX.value -= 15
  if (e.key === 'ArrowRight') planeX.value += 15
  if (e.key === ' ') {
    bullets.value.push({ x: planeX.value + 10, y: 550 })
  }
}

// 子弹飞行
setInterval(() => {
  if (gameOver.value) return
  bullets.value.forEach(b => b.y -= 8)
  bullets.value = bullets.value.filter(b => b.y > 0)
}, 30)

// 自动生成怪物
setInterval(() => {
  if (gameOver.value) return
  enemys.value.push({
    x: Math.random() * 350,
    y: 0
  })
}, 1000)

// 怪物下落
setInterval(() => {
  if (gameOver.value) return
  enemys.value.forEach(e => e.y += 3)

  // 怪物到底部 = 游戏结束
  enemys.value.forEach(e => {
    if (e.y > 570) gameOver.value = true
  })
}, 40)

// 碰撞检测 + 计分
setInterval(() => {
  if (gameOver.value) return
  bullets.value.forEach((b, bi) => {
    enemys.value.forEach((e, ei) => {
      if (Math.abs(b.x - e.x) < 20 && Math.abs(b.y - e.y) < 20) {
        bullets.value.splice(bi, 1)
        enemys.value.splice(ei, 1)
        score.value += 10
      }
    })
  })
}, 50)
</script>

<style>
.game {
  width: 400px;
  height: 600px;
  background: #111;
  margin: 20px auto;
  position: relative;
  outline: none;
  color: white;
  overflow: hidden;
}

.score {
  position: absolute;
  top: 10px;
  left: 10px;
  font-size: 18px;
  z-index: 10;
}

.plane {
  font-size: 30px;
  position: absolute;
  bottom: 20px;
}

.bullet {
  width: 4px;
  height: 12px;
  background: yellow;
  position: absolute;
}

.enemy {
  font-size: 24px;
  position: absolute;
}

.game-over {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
  color: red;
  font-size: 20px;
  background: #000;
  padding: 20px 40px;
  border: 2px solid red;
}
</style>
相关推荐
NiceCloud喜云2 小时前
Opus 4.8 的 Effort Control 怎么选:Low 到 Max 五档策略
android·java·大数据·前端·c++·python·spring
wordbaby3 小时前
React Native + RNOH:跨页面数据回传的最佳实践与避坑指南
前端·react native
GISer_Jing3 小时前
Three.js着色器编译机制深度解析
javascript·webgl·着色器
丷丩3 小时前
MapLibre GL JS第22课:查看本地GeoJSON
前端·javascript·map·mapbox·maplibre gl js
油炸自行车3 小时前
Claude Code 错误:API Error: 400 Failed to deserialize the JSON body into the
开发语言·javascript·json·trae·claude code·api error 400
Front思4 小时前
AI前端工程师需要具备能力+
前端·人工智能·ai
ZC跨境爬虫6 小时前
跟着 MDN 学CSS day_29:(掌握文本与字体样式的核心艺术)
前端·css·ui·html·tensorflow
李子琪。7 小时前
网络空间安全深度实战:CSRF 漏洞原理剖析与基于 Token 的纵深防御体系构建(全栈实验报告)
前端·安全·csrf
冰暮流星7 小时前
javascript之history对象介绍
前端·笔记
IT_陈寒7 小时前
Vite热更新失灵?你可能漏了这个配置
前端·人工智能·后端