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>
相关推荐
To_OC3 小时前
LC 51 N 皇后:我以为难的是回溯,结果栽在了对角线下标
javascript·算法·leetcode
腻害兔3 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
不好听6133 小时前
从一行 JSX 到屏幕像素:前端开发者必须懂的浏览器渲染管线
前端
恒拓高科WorkPlus3 小时前
企业级内网即时通讯建设模型:BeeWorks内网IM四层架构
前端
前端小李子4 小时前
前端环境变量裸奔?我用 EnvShield 给它穿了件防弹衣
前端
youtootech4 小时前
HarmonyOS《柚兔学伴》项目实战25-我的页面、Web 嵌入与项目总结
前端·华为·harmonyos
小林ixn4 小时前
从零到一理解 React 父子组件通信:手写一个 Todo 应用带你彻底搞懂单向数据流
前端·javascript·react.js
醇氧6 小时前
CountDownLatch / CyclicBarrier / Semaphore 面试高频问答清单
前端·面试·职场和发展
窝子面7 小时前
手搓最简前后端协作-node
javascript·数据库