zoukankan      html  css  js  c++  java
  • Phaser学习之路——飞机星战

    一直想尝试html5游戏的制作,闲来无事,发现了phaser这个html5的游戏开发框架,尝试完成一个小游戏,此博文就作为自己的开发和学习的记录。

    1 什么是Phaser

      Phaser是一个开源的桌面和移动HTML5 2D游戏开发框架,官网地址: http://www.phaser.io/

    2  环境搭建

      没什么说的,官网下载phaser的js文件,html页面进行引入

    3  创建项目

      创建一个项目文件StarCrash,文件层级如下:

     

      assets: 存放项目需要用到的图片,声音,字体等资源

      js :  存放项目需要用到的js文件,下载的phaser.min.js 可以放在此文件夹下

      index.html : 游戏页面html

    4  开始搬砖

    phaser代码的基本结构

    var game = new Phaser.Game(320, 568, Phaser.AUTO, 'StarCrash', { preload: preload, create: create, update: update});
    
    //加载资源
    function preload() {
    }
    
    //创建场景
    function create(){
    }
    
    //更新场景
    function update(){
    }

    加载游戏资源

    function preload() {
        //加载资源
      game.load.image('bullet', 'assets/bullet.png');
      game.load.image('e_bullet', 'assets/enemy-bullet.png');
      game.load.spritesheet('s_explode', 'assets/smallexplode.png',64,64);
      game.load.spritesheet('explode', 'assets/explode.png',128,128);
      game.load.image('invader', 'assets/invader.png');
      game.load.image('m_invader', 'assets/invader32x32x4.png');
      game.load.image('player', 'assets/player.png');
      game.load.image('background', 'assets/starfield.png');
     }

    使用的游戏资源都为phaser demo内的图片,声音暂未添加。 

    创建游戏场景

      使用之前加载的游戏资源对游戏对象飞机子弹,敌人子弹,爆炸动画,敌人都是以组(池)的方式进行创建,减少内存的创建和回收。监控键盘输入对飞机对象进行操作。

      

    function create(){
                //创建背景
                background = game.add.tileSprite(0, 0, 320,568, 'background');
                game.physics.enable(background,Phaser.Physics.ARCADE);
                //创建飞机
                player = game.add.sprite(160, 520, 'player');
                player.anchor.setTo(0.5, 0.5);
                game.physics.enable(player, Phaser.Physics.ARCADE);
                //防止飞机飞出边界
                player.body.collideWorldBounds = true;
    
                //创建飞机子弹
                bullets = game.add.group();
                bullets.enableBody = true;
                bullets.physicsBodyType = Phaser.Physics.ARCADE;
                bullets.createMultiple(50, 'bullet');
                bullets.setAll('anchor.x', 0.5);
                bullets.setAll('anchor.y', 1);
                bullets.setAll('outOfBoundsKill', true);
                bullets.setAll('checkWorldBounds', true);
    
    
                //创建敌人子弹组
                ebullets = game.add.group();
                ebullets.enableBody = true  ;
                ebullets.physicsBodyType = Phaser.Physics.ARCADE;
                ebullets.createMultiple(30,'e_bullet');
                ebullets.setAll('anchor.x',0.5);
                ebullets.setAll('anchor.y',1);
                ebullets.setAll('outOfBoundsKill', true);
                ebullets.setAll('checkWorldBounds', true);
    
                enemy = new Enemy();
                enemy.init();
    
                //创建爆炸动画
                explosions = game.add.group();
                explosions.createMultiple(30, 's_explode');
                explosions.forEach(enemyExplosion, this);
    
                //得分
                scoreStr = "分数:"
                scoreText = game.add.text(game.world.centerX,16,scoreStr + score, { font: '16px Arial', fill: '#fff' });
                scoreText.anchor.setTo(0.5,0.5);
    
    
                //提示信息
                infoText = game.add.text(game.world.centerX,game.world.centerY,' ', { font: '24px Arial', fill: '#fff' });
                infoText.anchor.setTo(0.5, 0.5);
                infoText.visible = false;
    
    
                //控制
                cursors = game.input.keyboard.createCursorKeys();
                fireButton = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);
            }

    创建敌人

      创建敌人方法

    //敌人
            function Enemy(){
                this.init = function () {
                    //初始化创建创建敌人池
                    this.enemies = game.add.group();
                    this.enemies.enableBody = true;
                    this.enemies.physicsBodyType = Phaser.Physics.ARCADE;
                    this.enemies.createMultiple(50, 'invader');
                    this.enemies.setAll('anchor.x', 0.5);
                    this.enemies.setAll('anchor.y', 0.5);
                    this.enemies.setAll('outOfBoundsKill', true);
                    this.enemies.setAll('checkWorldBounds', true);
    
                    this.maxWidth = game.width - game.cache.getImage('invader').width;
                    // 产生敌人的定时器
                    game.time.events.loop(Phaser.Timer.SECOND * 2, this.create, this);
                }
                //创建敌人
                this.create =function(){
                    enemyobj = this.enemies.getFirstExists(false);
                    if(enemyobj){
                        enemyobj.reset(game.rnd.integerInRange(0, this.maxWidth), game.cache.getImage('invader').height);
                        enemyobj.body.velocity.y = 50;
                    }
                }
                //
                this.crashPlayer = function(player,enemy){
                    enemy.kill();
                    playerDead();
                }
                this.shootPlayer = function (player,ebullet) {
                    ebullet.kill();
                    playerDead();
                }
                this.fire = function () {
                    liveEnemies.length = 0;
                    //存活的敌人
                    this.enemies.forEachAlive(function (obj) {
                        liveEnemies.push(obj);
                    });
                    //获取敌人子弹
                    ebullet = ebullets.getFirstExists(false);
    
                    if(ebullet && liveEnemies.length > 0){
                        //随机敌人的索引
                        var random=game.rnd.integerInRange(0,liveEnemies.length-1);
                        //获取随机敌人
                        var ranEnemy = liveEnemies[random];
                        //子弹从敌人位置射出
                        ebullet.reset(ranEnemy.body.x + 8,ranEnemy.body.y + 16);
                        //子弹射向飞机
                        game.physics.arcade.moveToObject(ebullet,player,120);
                        EFireTimer = game.time.now  + 2000;
                    }
                }
            }

    更新场景

      实现背景页面的滚动,玩家的操作反馈

    function update(){
                //  Scroll the background
                background.tilePosition.y += 3;
                player.body.velocity.setTo(0, 0);
    
                //
                if(cursors.left.isDown){
                    player.body.velocity.x = -200;
                }
                //
                else if (cursors.right.isDown) {
                    player.body.velocity.x = 200;
                }
                //
                else if(cursors.up.isDown){
                    player.body.velocity.y = -200;
                }
                //
                else if(cursors.down.isDown){
                    player.body.velocity.y = 200;
                }
                // 发射子弹
                if (fireButton.isDown)
                {
                    fireBullet();
                }
                //敌人发射子弹
                if (game.time.now > EFireTimer)
                {
                    enemy.fire();
                }
    
                //飞机碰撞敌人
                game.physics.arcade.overlap(enemy.enemies ,player, enemy.crashPlayer, null, this);
                //子弹碰撞敌人
                game.physics.arcade.overlap(bullets,enemy.enemies , hitEnemy, null, this);
                //敌人子弹碰撞飞机
                game.physics.arcade.overlap(ebullets,player,enemy.shootPlayer,null,this);
            }

    玩家发射子弹

    function fireBullet(){
                if(game.time.now > bullettime){
                    // 获取子弹组里的第一颗子弹
                    bullet = bullets.getFirstExists(false);
                    if(bullet){
                        bullet.reset(player.x, player.y - 8);
                        bullet.body.velocity.y = -300;
                        bullettime = game.time.now + 500;
                    }
                }
            }

    击中敌人

      //击中敌人
            function hitEnemy(bullet,enemy){
                bullet.kill();
    
                //播放爆炸动画
                var explosion = explosions.getFirstExists(false);
                explosion.reset(enemy.body.x,enemy.body.y);
                explosion.play('s_explode', 10, false, true);
    
                //刷新得分
                score += 1;
                scoreText.text = scoreStr + score;
    
                enemy.kill();
            }

    敌人爆炸

     //敌人爆炸
            function enemyExplosion(obj) {
                obj.anchor.x = 0.5;
                obj.anchor.y = 0.5;
                obj.animations.add('s_explode');
            }

    飞机爆炸

    //飞机爆炸
            function playerDead(){
                player.kill();
    
                //播放爆炸动画
                var explosion = explosions.getFirstExists(false);
                explosion.reset(player.body.x,player.body.y);
                explosion.play('s_explode', 30, false, true);
    
                //显示游戏结束文字
                infoText.text = " GAME OVER 
     Click to restart";
                infoText.visible = true;
    
                //点击重新开始
                game.input.onTap.addOnce(restartGame,this);
            }

    重新开始

    //重新开始
            function restartGame(){
                //清除敌人
                enemy.enemies.callAll('kill');
                //清除敌人子弹
                ebullets.callAll('kill');
                //隐藏gameover
                infoText.visible = false;
    
                //刷新分数
                score = 0;
                scoreText.text = scoreStr + score;
    
                //复活玩家
                player.revive().reset(160,520);
            }

    至此,简单的飞机游戏就完成了,有几点不足之处:

    (1)没有加载声音资源

    (2)未实现不同类型敌人,后续可以扩展敌人方法,增加不同敌人类型

    代码比较丑陋,也是抱着学习phaser的态度,未对代码进行优化,也算是phaser的基本入门吧,游戏比较简单,后期扩展的点还是挺多的,有时间可以继续优化。

  • 相关阅读:
    常用正则、正则表达式
    移动端虚拟手机键盘
    如何隐藏滚动条还能实现滚动的功能
    醉盏的第一篇博客-关于title的换行处理
    Mybatis-Generator自动生成Dao、Model、Mapping等相关映射文件(懒人版)
    java学习笔记----@Override的作用
    web项目生成web.xml的两种方式
    angular分页插件tm.pagination二次触发问题解决歪方案
    Ubuntu Server17.10配置静态IP
    cors 的深入细节
  • 原文地址:https://www.cnblogs.com/dpwow/p/6150369.html
Copyright © 2011-2022 走看看