龙华做网站联系电话,常州按天优化代理,电脑建设银行怎样设置网站查询,有没有网址免费的文章目录 引言项目初始化游戏设计和结构游戏程序实现Vue页面嵌入PhaserPreloader 场景加载游戏场景功能实现功能类定义Boom爆炸类Bullet子弹类Enemy敌军类Player玩家类End游戏结束类 总结 更多相关内容可查看 引言
飞机大战#xff08;也被称为射击游戏或空战游戏#xff09… 文章目录 引言项目初始化游戏设计和结构游戏程序实现Vue页面嵌入PhaserPreloader 场景加载游戏场景功能实现功能类定义Boom爆炸类Bullet子弹类Enemy敌军类Player玩家类End游戏结束类 总结 更多相关内容可查看 引言
飞机大战也被称为射击游戏或空战游戏是一种非常受欢迎的休闲游戏类型。在这个博客中我们将探讨如何使用 Vue.js 框架来构建一个简单的飞机大战游戏。我们将从基本的游戏逻辑开始逐步增加游戏元素和交互性代码详解可参考注释最终展示画面在文章底部
项目初始化
git地址https://gitee.com/its-a-little-bad/vue-project—aircraft-battle.git node版本20.8.1
游戏设计和结构
在 Vue.js 中我们通常将游戏的各个部分分解为不同的场景。
主场景 游戏场景
游戏程序实现
Vue页面嵌入Phaser
在 Vue 应用中嵌入一个 Phaser 游戏
template!-- Phaser 游戏的容器 --div idcontainer/div
/template
script setup langts
import { onMounted, onUnmounted } from vue;
import { Game, AUTO, Scale } from phaser;
import { Preloader } from ./game/Preloader;
import { Main } from ./game/Main;
import { End } from ./game/End;// 使用正则表达式检测当前设备是否为移动设备
let isMobile /(iPhone|iPad|Android)/i.test(navigator.userAgent);// 定义了一个 game 变量来存储 Phaser 游戏实例
let game: Game;
onMounted(() {game new Game({parent: container,type: AUTO,width: 375,//游戏的大小根据设备类型进行调整。如果设备是移动设备则高度会根据设备的纵横比计算得出。height: isMobile ? (window.innerHeight / window.innerWidth) * 375 : 667,//游戏的缩放模式也根据设备类型进行设置。移动设备使用 Scale.FIT这意味着游戏将尽可能地适应屏幕大小//而不会保持其原始纵横比。非移动设备则使用 Scale.NONE这意味着游戏将保持其原始大小。scale: {mode: isMobile ? Scale.FIT : Scale.NONE,},physics: {default: arcade,arcade: {debug: false,},},scene: [Preloader, Main, End],});
});onUnmounted(() {game.destroy(true);
});
/scriptstyle
body {margin: 0;
}
#app {height: 100%;
}
/style
Preloader 场景加载
创建一个 Preloader 场景来加载游戏所需的资源和设置一些基本的游戏元素示例如下 程序实现
import { Scene } from phaser;
import backgroundImg from ../assets/images/background.jpg;
import enemyImg from ../assets/images/enemy.png;
import playerImg from ../assets/images/player.png;
import bulletImg from ../assets/images/bullet.png;
import boomImg from ../assets/images/boom.png;
import spritesImg from ../assets/images/sprites.png;
import spritesJson from ../assets/json/sprites.json?url;
import bgmAudio from ../assets/audio/bgm.mp3;
import boomAudio from ../assets/audio/boom.mp3;
import bulletAudio from ../assets/audio/bullet.mp3; export class Preloader extends Scene { // 构造函数定义场景名称为 Preloader constructor() { super(Preloader); } // 预加载资源的方法 preload() { // 加载背景图片 this.load.image(background, backgroundImg); // 加载敌人图片 this.load.image(enemy, enemyImg); // 加载玩家图片 this.load.image(player, playerImg); // 加载子弹图片 this.load.image(bullet, bulletImg); // 加载爆炸动画的精灵表spritesheet this.load.spritesheet(boom, boomImg, { frameWidth: 64, frameHeight: 48, }); // 加载精灵图集atlas this.load.atlas(sprites, spritesImg, spritesJson); // 加载背景音乐 this.load.audio(bgm, bgmAudio); // 加载爆炸音效 this.load.audio(boom, boomAudio); // 加载子弹音效 this.load.audio(bullet, bulletAudio); } // 创建场景的方法 create() { const { width, height } this.cameras.main; // 显示背景通常在Preloader场景中不展示实际游戏内容这里仅为示例 this.add.tileSprite(0, 0, width, height, background).setOrigin(0, 0); // 播放背景音乐在Preloader场景中播放通常是为了给玩家一个等待的反馈 this.sound.play(bgm, { loop: true }); // 循环播放背景音乐 // 添加标题通常也不在Preloader场景中但可以作为加载提示 this.add .text(width / 2, height / 4, 飞机大战, { fontFamily: Arial, fontSize: 60, color: #e3f2ed, stroke: #203c5b, strokeThickness: 6, }) .setOrigin(0.5); // 添加开始按钮通常用于在加载完成后切换到主场景 let button this.add .image(width / 2, (height / 4) * 3, sprites, button) // 假设sprites图集中有名为button的帧 .setScale(3, 2) .setInteractive() .on(pointerdown, () { // 当按钮被点击时切换到主场景这里主场景名为Main this.scene.start(Main); }); // 按钮文案this.add.text(button.x, button.y, 开始游戏, {fontFamily: Arial,fontSize: 20,color: #e3f2ed,}).setOrigin(0.5); } // 创建动画命名为 boom后面使用this.anims.create({key: boom,frames: this.anims.generateFrameNumbers(boom, { start: 0, end: 18 }),repeat: 0,});
}在Phaser 3框架中从一个场景如Preloader切换到另一个场景如Main通常使用this.scene.start(‘Main’)这样的代码来实现。这是Phaser场景管理系统的一部分它允许你动态地加载、创建、运行和销毁游戏的不同部分。
游戏场景功能实现 程序实现
// 定义 Main 场景类继承自 Phaser 的 Scene 类
import { Scene, Physics, GameObjects } from phaser;
import { Player } from ./Player;
import { Bullet } from ./Bullet;
import { Enemy } from ./Enemy;
import { Boom } from ./Boom;// 场景元素
let background: GameObjects.TileSprite;
let player: Player;
let enemys: Physics.Arcade.Group;
let bullets: Physics.Arcade.Group;
let booms: GameObjects.Group;
let scoreText: GameObjects.Text;// 场景数据
let score: number;export class Main extends Scene {constructor() {super(Main);}create() {let { width, height } this.cameras.main;// 创建背景background this.add.tileSprite(0, 0, width, height, background).setOrigin(0, 0);// 创建玩家调用Player类player new Player(this);// 创建敌军组// 注解enemys 是一个 Phaser 的物理组用于存储和管理多个 Enemy 对象// frameQuantity 表示从 enemy 纹理集中加载的帧数key 是纹理集的名称// enable, active, visible 分别是启用物理、激活和可见性标志// classType 指示组中新创建对象的类型enemys this.physics.add.group({frameQuantity: 30,key: enemy,enable: false,// 在此初始状态下不启用物理 active: false,// 在此初始状态下不激活 visible: false,// 在此初始状态下不可见classType: Enemy,// 当组中添加新对象时使用的类});// 创建子弹// 注解与敌军组类似但用于存储和管理多个 Bullet 对象 bullets this.physics.add.group({frameQuantity: 15,key: bullet,enable: false,active: false,visible: false,classType: Bullet,});// 创建爆炸// 注解booms 组用于存储和管理多个 Boom 对象可能是用于显示爆炸动画booms this.add.group({frameQuantity: 30,key: boom,active: false,visible: false,classType: Boom,});// 分数// 注解score 变量用于跟踪玩家的分数scoreText 是显示分数的文本对象 score 0;scoreText this.add.text(10, 10, 0, {fontFamily: Arial,fontSize: 20,});// 注册事件this.addEvent();}// 注册事件addEvent() {// 定时器// 注解此定时器每 400 毫秒触发一次回调生成敌军和发射子弹 this.time.addEvent({delay: 400,callback: () {// 生成2个敌军for (let i 0; i 2; i) {enemys.getFirstDead()?.born();}// 发射1颗子弹bullets.getFirstDead()?.fire(player.x, player.y - 32);},callbackScope: this,repeat: -1,});// 子弹和敌军碰撞会调用 hit 方法this.physics.add.overlap(bullets, enemys, this.hit, null, this);// 玩家和敌军碰撞会调用 gameOver 方法this.physics.add.overlap(player, enemys, this.gameOver, null, this);}// 子弹击中敌军hit(bullet, enemy) {// 子弹和敌军隐藏enemy.disableBody(true, true);bullet.disableBody(true, true);// 显示爆炸booms.getFirstDead()?.show(enemy.x, enemy.y);// 分数增加scoreText.text String(score);}// 游戏结束gameOver() {// 暂停当前场景并没有销毁this.sys.pause();// 保存分数this.registry.set(score, score);// 打开结束场景this.game.scene.start(End);}update() {// 设置背景瓦片不断移动background.tilePositionY - 1;}
}
功能类定义
Boom爆炸类
import { GameObjects, Scene } from phaser;export class Boom extends GameObjects.Sprite {constructor(scene: Scene, x: number, y: number, texture: string) {// 创建对象super(scene, x, y, texture);// 爆炸动画播放结束事件this.on(animationcomplete-boom, this.hide, this);}/*** 显示爆炸* param x 爆炸x坐标* param y 爆炸y坐标*/show(x: number, y: number) {this.x x;this.y y;this.setActive(true);this.setVisible(true);// 爆炸动画this.play(boom);// 爆炸音效this.scene.sound.play(boom);}/*** 隐藏爆炸*/hide() {this.setActive(false);this.setVisible(false);}
}
Bullet子弹类
import { Physics, Scene } from phaser;export class Bullet extends Physics.Arcade.Sprite {constructor(scene: Scene, x: number, y: number, texture: string) {super(scene, x, y, texture);// 设置属性this.setScale(0.25);}/*** 发射子弹* param x 子弹x坐标* param y 子弹y坐标*/fire(x: number, y: number) {this.enableBody(true, x, y, true, true);this.setVelocityY(-300);this.scene.sound.play(bullet);}preUpdate(time: number, delta: number) {super.preUpdate(time, delta);// 子弹走到头销毁if (this.y -14) {this.disableBody(true, true);}}
}
Enemy敌军类
import { Physics, Math, Scene } from phaser;export class Enemy extends Physics.Arcade.Sprite {constructor(scene: Scene, x: number, y: number, texture: string) {// 创建对象super(scene, x, y, texture);scene.add.existing(this);scene.physics.add.existing(this);// 设置属性this.setScale(0.5);this.body.setSize(100, 60);}/*** 生成敌军*/born() {let x Math.Between(30, 345);let y Math.Between(-20, -40);this.enableBody(true, x, y, true, true);this.setVelocityY(Math.Between(150, 300));}preUpdate(time: number, delta: number) {super.preUpdate(time, delta);let { height } this.scene.cameras.main;// 敌军走到头销毁if (this.y height 20) {this.disableBody(true, true)}}
}
Player玩家类
import { Physics, Scene } from phaser;export class Player extends Physics.Arcade.Sprite {isDown: boolean false;downX: number;downY: number;constructor(scene: Scene) {// 创建对象let { width, height } scene.cameras.main;super(scene, width / 2, height - 80, player);scene.add.existing(this);scene.physics.add.existing(this);// 设置属性this.setInteractive();this.setScale(0.5);this.setCollideWorldBounds(true);this.body.setSize(120, 120);// 注册事件this.addEvent();}/*** 注册事件*/addEvent() {// 手指按下我方飞机this.on(pointerdown, () {this.isDown true;this.downX this.x;this.downY this.y;});// 手指抬起this.scene.input.on(pointerup, () {this.isDown false;});// 手指移动this.scene.input.on(pointermove, (pointer) {if (this.isDown) {this.x this.downX pointer.x - pointer.downX;this.y this.downY pointer.y - pointer.downY;}});}
}
End游戏结束类
import { Scene } from phaser;export class End extends Scene {constructor() {super(End);}create() {let { width, height } this.cameras.main;// 结束面板this.add.image(width / 2, height / 2, sprites, result).setScale(2.5);// 标题this.add.text(width / 2, height / 2 - 85, 游戏结束, {fontFamily: Arial,fontSize: 24,}).setOrigin(0.5);// 当前得分let score this.registry.get(score);this.add.text(width / 2, height / 2 - 10, 当前得分${score}, {fontFamily: Arial,fontSize: 20,}).setOrigin(0.5);// 重新开始按钮let button this.add.image(width / 2, height / 2 50, sprites, button).setScale(3, 2).setInteractive().on(pointerdown, () {// 点击事件关闭当前场景打开Main场景this.scene.start(Main);});// 按钮文案this.add.text(button.x, button.y, 重新开始, {fontFamily: Arial,fontSize: 20,}).setOrigin(0.5);}
}
总结
通过使用 Vue.js 框架我们可以轻松地构建出一个简单而有趣的飞机大战游戏。从基本的游戏逻辑开始逐步增加游戏元素和交互性最终得到一个完整且吸引人的游戏作品。希望这个博客能对你有所启发并鼓励你尝试使用 Vue.js 来开发更多有趣的游戏和应用程序 文章转载自: http://www.morning.gqtw.cn.gov.cn.gqtw.cn http://www.morning.fqqlq.cn.gov.cn.fqqlq.cn http://www.morning.hpxxq.cn.gov.cn.hpxxq.cn http://www.morning.ndlww.cn.gov.cn.ndlww.cn http://www.morning.rhlhk.cn.gov.cn.rhlhk.cn http://www.morning.grynb.cn.gov.cn.grynb.cn http://www.morning.plxnn.cn.gov.cn.plxnn.cn http://www.morning.rbrhj.cn.gov.cn.rbrhj.cn http://www.morning.jlxqx.cn.gov.cn.jlxqx.cn http://www.morning.fycjx.cn.gov.cn.fycjx.cn http://www.morning.xfwnk.cn.gov.cn.xfwnk.cn http://www.morning.gnbfj.cn.gov.cn.gnbfj.cn http://www.morning.ydxx123.cn.gov.cn.ydxx123.cn http://www.morning.bqpg.cn.gov.cn.bqpg.cn http://www.morning.rtkgc.cn.gov.cn.rtkgc.cn http://www.morning.pbksb.cn.gov.cn.pbksb.cn http://www.morning.mfct.cn.gov.cn.mfct.cn http://www.morning.mzrqj.cn.gov.cn.mzrqj.cn http://www.morning.jfcbs.cn.gov.cn.jfcbs.cn http://www.morning.zrlwl.cn.gov.cn.zrlwl.cn http://www.morning.dmjhp.cn.gov.cn.dmjhp.cn http://www.morning.lwbhw.cn.gov.cn.lwbhw.cn http://www.morning.dhqyh.cn.gov.cn.dhqyh.cn http://www.morning.dwhnb.cn.gov.cn.dwhnb.cn http://www.morning.ckxd.cn.gov.cn.ckxd.cn http://www.morning.mmclj.cn.gov.cn.mmclj.cn http://www.morning.jpzcq.cn.gov.cn.jpzcq.cn http://www.morning.zlgr.cn.gov.cn.zlgr.cn http://www.morning.rgtp.cn.gov.cn.rgtp.cn http://www.morning.lmrjn.cn.gov.cn.lmrjn.cn http://www.morning.uqrphxm.cn.gov.cn.uqrphxm.cn http://www.morning.nthyjf.com.gov.cn.nthyjf.com http://www.morning.kxqfz.cn.gov.cn.kxqfz.cn http://www.morning.wjmb.cn.gov.cn.wjmb.cn http://www.morning.lqws.cn.gov.cn.lqws.cn http://www.morning.crkmm.cn.gov.cn.crkmm.cn http://www.morning.cbtn.cn.gov.cn.cbtn.cn http://www.morning.xwlhc.cn.gov.cn.xwlhc.cn http://www.morning.kxwsn.cn.gov.cn.kxwsn.cn http://www.morning.yjqkk.cn.gov.cn.yjqkk.cn http://www.morning.errnull.com.gov.cn.errnull.com http://www.morning.yrbqy.cn.gov.cn.yrbqy.cn http://www.morning.zhffz.cn.gov.cn.zhffz.cn http://www.morning.yxplz.cn.gov.cn.yxplz.cn http://www.morning.plzgt.cn.gov.cn.plzgt.cn http://www.morning.fndfn.cn.gov.cn.fndfn.cn http://www.morning.btwlp.cn.gov.cn.btwlp.cn http://www.morning.fmry.cn.gov.cn.fmry.cn http://www.morning.rbjp.cn.gov.cn.rbjp.cn http://www.morning.jzlfq.cn.gov.cn.jzlfq.cn http://www.morning.aowuu.com.gov.cn.aowuu.com http://www.morning.wsxxq.cn.gov.cn.wsxxq.cn http://www.morning.lnwdh.cn.gov.cn.lnwdh.cn http://www.morning.yzxhk.cn.gov.cn.yzxhk.cn http://www.morning.kksjr.cn.gov.cn.kksjr.cn http://www.morning.qkkmd.cn.gov.cn.qkkmd.cn http://www.morning.bklhx.cn.gov.cn.bklhx.cn http://www.morning.lmpfk.cn.gov.cn.lmpfk.cn http://www.morning.fwzjs.cn.gov.cn.fwzjs.cn http://www.morning.nytqy.cn.gov.cn.nytqy.cn http://www.morning.bcdqf.cn.gov.cn.bcdqf.cn http://www.morning.rnmmh.cn.gov.cn.rnmmh.cn http://www.morning.thzwj.cn.gov.cn.thzwj.cn http://www.morning.zwtp.cn.gov.cn.zwtp.cn http://www.morning.ckhry.cn.gov.cn.ckhry.cn http://www.morning.ltffk.cn.gov.cn.ltffk.cn http://www.morning.pctql.cn.gov.cn.pctql.cn http://www.morning.rjnm.cn.gov.cn.rjnm.cn http://www.morning.hwbf.cn.gov.cn.hwbf.cn http://www.morning.zfhwm.cn.gov.cn.zfhwm.cn http://www.morning.sypby.cn.gov.cn.sypby.cn http://www.morning.ltdrz.cn.gov.cn.ltdrz.cn http://www.morning.bkfdf.cn.gov.cn.bkfdf.cn http://www.morning.xzkgp.cn.gov.cn.xzkgp.cn http://www.morning.jgnjl.cn.gov.cn.jgnjl.cn http://www.morning.dyght.cn.gov.cn.dyght.cn http://www.morning.znrlg.cn.gov.cn.znrlg.cn http://www.morning.zqkr.cn.gov.cn.zqkr.cn http://www.morning.rjljb.cn.gov.cn.rjljb.cn http://www.morning.gmysq.cn.gov.cn.gmysq.cn