phaser3学习笔记

文档内容太多了,也不好找资料,现在个人学习API途径有几种:

  1.百度翻译,靠着个人使用理解来学习

  2.官网API,找有几个网站

  3.官方demo文件夹的使用样例(最好用的)。

  4.补充一个:Notes of Phaser 3(也挺好用的) 【有些标签有特别好用的live demo,可能live为空,但是代码可以自己粘贴下来只用一样有效】

 

核心更新,发现了官方Git账号,里面的插件真香啊,以前不用真吃亏-》here

 

主要是结合here(也就是上面的4)的Usage部分的代码一起参考学习,效率嘎嘎好。

 

所以,为了长久发展和便利,最好还是记录一下(是散装但是可能会整理一下)。

补充一下16进制颜色表:here,便于使用。

1.this.textures.get('xxx').getFrameNames()

  this.指向scene,是获取preload加载的名为'xxx'的json资源中的所有frame名(返回数组)

    用于在player.setFrame或创建动作的时候使用。

 player创建动作,参考:here

 

2.this.anims.create(7也是创建动作)

  this.指向sprite(注意image类型没有anims动作,只能对其创建tweens补间动画),为其创建动作

  1.从json文件,连续

复制代码
示例:

如果你加载了一个名为gems它包含6个称为ruby_0001, ruby_0002,依此类推,然后您可以使用以下方式调用此方法:this.anims.generateFrameNames('gems', { prefix: 'ruby_', end: 6, zeroPad: 4 }).

这end值告诉它寻找6帧,递增编号,都从前缀开始ruby_。这zeroPad值告诉它有多少个零填充数字。要使用此方法创建动画,您可以:
this.anims.create({
  key: 'ruby',
  repeat: -1,
  frames: this.anims.generateFrameNames('gems', {
    prefix: 'ruby_',
    end: 6,
    zeroPad: 4
  })
});
官网API使用demo
复制代码

   简写形式:

复制代码
如果加载了一个名为explosion并且它包含12帧,那么您可以使用:this.anims.generateFrameNumbers('explosion', { start: 0, end: 12 }).

这end值告诉它在12帧后停止。要使用此方法创建动画,您可以:
this.anims.create({
  key: 'boom',
  frames: this.anims.generateFrameNames('explosion', {
    start: 0,
    end: 12
  })
});
Json,连续
复制代码

  2.从json文件,非连续

复制代码
注意到start是可选的,如果动画从第0帧开始,则不需要包含它。

若要反向指定动画,请交换start和end价值观。

如果帧不是连续的,您可以传递一个帧编号数组,例如:

this.anims.generateFrameNumbers('explosion', { frames: [ 0, 1, 2, 1, 2, 3, 4, 0, 1, 2 ] })
Json,非连续
复制代码

 

 3.this.setFrame

  this.指向sprite,为其直接指定绘制的动画帧,用于创建sprite时候的指定站立动作。

  其参数必须是getFrameNames中的name,不能是number序号,在官方文档中有这样解释:

复制代码
你可能习惯于用一个数字来定位一个sprite表中的一个帧。

this.char.setFrame(1);
然而,对于用JSON加载的sprite工作表,帧是由图像名决定的。

this.char.setFrame("Run__006.png");
this.指向scene
复制代码

 

 4.设定图层层级关系,建立阻挡,防止穿模

  关键词是depth,对scene的元素直接指定添加,这一点是phaser3不同于phaser2的很重要的一点(我就是用着phaser2发觉有穿模没啥好的解决办法才推倒重写学习phaser3的。。。)

参考个人demo:

复制代码
    //创建对象
    var map = this.add.tilemap('map');
    console.log(map);
    //文件名字不能随意定义,否则找不到对象
    var tileset1 = map.addTilesetImage('iso-64x64-outside', 'tiles1');
    var tileset2 = map.addTilesetImage('iso-64x64-building', 'tiles2');

    //布置对象,为了后续操作而赋值
    var layer1 = map.createLayer('Tile Layer 1', [tileset1, tileset2]);
    layer1.depth = 0;
    console.log(layer1.depth);

    var layer2 = map.createLayer('Tile Layer 2', [tileset1, tileset2]);
    layer2.depth = 1;
    console.log(layer2.depth);

    var layer3 = map.createLayer('Tile Layer 3', [tileset1, tileset2]);
    layer3.depth = 2;
    console.log(layer3.depth);

    var layer4 = map.createLayer('Tile Layer 4', [tileset1, tileset2]);
    layer4.depth = 3;
    console.log(layer3.depth);

    var layer5 = map.createLayer('Tile Layer 5', [tileset1, tileset2]);
    layer5.depth = 4;
    console.log(layer4.depth);
map是地图,在地图中创建了5个图层,每一个图层都有自己的元素
复制代码

 

5.map.getTileAt

  map.指Tilemap对象,参数为(tileX, tileY, nonNull, layer),返回Tile

 

复制代码
tileX    数字    
从 X 位置获取图块(以图块单位给出,而不是像素)。

tileY    数字    
从中获取图块的 Y 位置(以图块单位给出,而不是像素)。

nonNull    布尔值    
如果为 true,getTile 将不会为空切片返回 null,而是返回索引为 -1 的 Tile 对象。

layer    Phaser . Tilemaps . LayerData    
要操作的 Tilemap 图层。
API解释
复制代码

 

6.如果使用new Phaser.GameObjects.Sprite来在指定scene中创建sprite的话,需要使用scene.add.existing(sprite)添加

  如果不使用,也可以通过 scene.add.sprite(x,y,texture) ->返回Sprite对象,来创建。

 

7.创建动作anims方式:

config配置创建:

复制代码
        // var animConfig = {
        //     key: 'back_right',
        //     frames: this.anims.generateFrameNames(
        //         'char', {
        //             prefix: 'greenhood_walk_back_right_',
        //             start: 1,
        //             end: 8
        //         }),
        //     frameRate: 20,
        //     repeat: -1
        // };
        // this.anims.create(animConfig);
demo
复制代码

直接创建:

复制代码
        this.anims.create({
            key: 'front_right',
            frames: this.anims.generateFrameNames('char', {
                prefix: 'greenhood_walk_front_right_',
                start: 1,
                end: 8,
            }),
            frameRate: 10,
            repeat: -1,
        });
demo
复制代码

记录一份官方代码——create animation from sprite sheet(从sprite sheet的序列帧图创建动作):

复制代码
class Example extends Phaser.Scene
{
    constructor ()
    {
        super();
    }

    preload ()
    {
        this.load.spritesheet('brawler', 'assets/animations/brawler48x48.png', { frameWidth: 48, frameHeight: 48 });
        this.load.image('grid', 'assets/textures/grid-ps2.png');
    }

    create ()
    {
        // Text section
        this.add.tileSprite(400, 300, 800, 600, 'grid');

        this.add.image(0, 0, 'brawler', '__BASE').setOrigin(0, 0);

        this.add.grid(0, 0, 192, 384, 48, 48).setOrigin(0, 0).setOutlineStyle(0x00ff00);

        this.add.text(200, 24, '<- walk', { color: '#00ff00' }).setOrigin(0, 0.5);
        this.add.text(200, 72, '<- idle', { color: '#00ff00' }).setOrigin(0, 0.5);
        this.add.text(200, 120, '<- kick', { color: '#00ff00' }).setOrigin(0, 0.5);
        this.add.text(200, 168, '<- punch', { color: '#00ff00' }).setOrigin(0, 0.5);
        this.add.text(200, 216, '<- jump', { color: '#00ff00' }).setOrigin(0, 0.5);
        this.add.text(200, 264, '<- jump kick', { color: '#00ff00' }).setOrigin(0, 0.5);
        this.add.text(200, 312, '<- win', { color: '#00ff00' }).setOrigin(0, 0.5);
        this.add.text(200, 360, '<- die', { color: '#00ff00' }).setOrigin(0, 0.5);
        this.add.text(48, 440, 'Click to change animation', { color: '#00ff00' });
        const current = this.add.text(48, 460, 'Playing: walk', { color: '#00ff00' });

        // Animation set
        this.anims.create({
            key: 'walk',
            frames: this.anims.generateFrameNumbers('brawler', { frames: [ 0, 1, 2, 3 ] }),
            frameRate: 8,
            repeat: -1
        });

        this.anims.create({
            key: 'idle',
            frames: this.anims.generateFrameNumbers('brawler', { frames: [ 5, 6, 7, 8 ] }),
            frameRate: 8,
            repeat: -1
        });

        this.anims.create({
            key: 'kick',
            frames: this.anims.generateFrameNumbers('brawler', { frames: [ 10, 11, 12, 13, 10 ] }),
            frameRate: 8,
            repeat: -1,
            repeatDelay: 2000
        });

        this.anims.create({
            key: 'punch',
            frames: this.anims.generateFrameNumbers('brawler', { frames: [ 15, 16, 17, 18, 17, 15 ] }),
            frameRate: 8,
            repeat: -1,
            repeatDelay: 2000
        });

        this.anims.create({
            key: 'jump',
            frames: this.anims.generateFrameNumbers('brawler', { frames: [ 20, 21, 22, 23 ] }),
            frameRate: 8,
            repeat: -1
        });

        this.anims.create({
            key: 'jumpkick',
            frames: this.anims.generateFrameNumbers('brawler', { frames: [ 20, 21, 22, 23, 25, 23, 22, 21 ] }),
            frameRate: 8,
            repeat: -1
        });

        this.anims.create({
            key: 'win',
            frames: this.anims.generateFrameNumbers('brawler', { frames: [ 30, 31 ] }),
            frameRate: 8,
            repeat: -1,
            repeatDelay: 2000
        });

        this.anims.create({
            key: 'die',
            frames: this.anims.generateFrameNumbers('brawler', { frames: [ 35, 36, 37 ] }),
            frameRate: 8,
        });

        const keys = [ 'walk', 'idle', 'kick', 'punch', 'jump', 'jumpkick', 'win', 'die' ];

        const cody = this.add.sprite(600, 370);
        cody.setScale(8);
        cody.play('walk');

        let c = 0;
        this.input.on('pointerdown', function () {
            c++;
            if (c === keys.length)
            {
                c = 0;
            }
            cody.play(keys[c]);
            current.setText('Playing: ' + keys[c]);
        });
    }
}

const config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    pixelArt: true,
    scene: [ Example ]
};

const game = new Phaser.Game(config);
全部代码,主要学习是anims.create部分
复制代码

 

8.对于phaser3的游戏场景暂停,启动相关API(学习记录):

调用方式为:this.scene.xxx,this指代当前scene场景

 

    pause:暂停场景,保存数据,仍会渲染
    sleep:休眠场景,保存数据,不会渲染
    stop:停止场景,清除数据,关闭渲染
  switch:sleep当前场景,start指定场景
                   
    restart:重启当前场景,重载数据
    start:关闭当前场景启动指定场景,重载数据
    wake:恢复场景(启动key场景的update和render),无数据处理
  resume:恢复场景(启动key场景的update),无数据处理
  run:运行场景,最通用,可与pause\sleep\stop搭配使用,但是必须指定参数
 
小总结:
  1.使用start与restart具体区别在于:
    参数不同,start(key,data),restart(data),也就是,start能实现scene场景切换,而restart不行。
    当没有指定key值时候,默认为当前场景,是与restart一样的效果。
    两个底层代码都是使用manager.queueOp进行处理
      另外,即便restart效果上是重启场景,但是底层代码是与start一样的结构:
        先stop停止key指定场景,再start启动key指定场景。
  2.wake和resume具体区别:
    是否启动render,翻译成人话就是:
      当白屏时候,resume启动能启动游戏但是不会有画面(白屏)
      也就是——resume不能与sleep搭配
    3.stop不与wake搭配,因为wake不会恢复scene数据
    4.stop可与start,restart搭配,因为会【完全】重新加载数据
    5.pause/sleep+wake可以实现真正保存数据的暂停效果
         pause->渲染暂停界面(界面卡住)
         sleep->不渲染暂停界面(白屏)
 
9.补间动画tween:
先上官网API:here,好评引文:here
额外补上关键常用:
onComplete 相位枪。types . tweens . tweenoncompletecallback <optional>  

补间完成时要调用的函数。

onCompleteParams 排列 <optional>  

要传递给的附加参数onComplete.

onCompleteScope 任何的 <optional>  

的范围onComplete.

onLoop 相位枪。types . tweens . tweenonloopcallback <optional>  

每次补间循环时调用的函数。

onLoopParams 排列 <optional>  

要传递给的附加参数onLoop.

onLoopScope 任何的 <optional>  

的范围onLoop.

onRepeat 相位枪。types . tweens . tweenonrepeatcallback <optional>  

每次补间重复时调用的函数。每个目标的每个属性调用一次。

onRepeatParams 排列 <optional>  

要传递给的附加参数onRepeat.

onRepeatScope 任何的 <optional>  

的范围onRepeat.

onStart 相位枪。types . tweens . tweenonstartcallback <optional>  

补间开始时要调用的函数。

onStartParams 排列 <optional>  

要传递给的附加参数onStart.

onStartScope 任何的 <optional>  

的范围onStart.

onStop 相位枪。types . tweens . tweenonstopcallback <optional>  

补间停止时要调用的函数。

onStopParams 排列 <optional>  

要传递给的附加参数onStop.

onStopScope 任何的 <optional>  

的范围onStop.

onUpdate 相位枪。types . tweens . tweenonupdatecallback <optional>  

每次补间步进时调用的函数。每个目标的每个属性调用一次。

onUpdateParams 排列 <optional>  

要传递给的附加参数onUpdate.

onUpdateScope 任何的 <optional>  

的范围onUpdate.

onYoyo 相位枪。types . tweens . tweenonyoyocallback <optional>  

每次补间溜溜球时调用的函数。每个目标的每个属性调用一次。

onYoyoParams 排列 <optional>  

要传递给的附加参数onYoyo.

onYoyoScope 任何的 <optional>  

的范围onYoyo.

 

补充实际创建方式:

(将create改为add,即实现直接播放该补间动画,而create需要搭配play才能播放)

 

复制代码
                var tween=now_scene.tweens.create({
                    targets: sp,
                    x: (sp.x < u) ? u - 150 : u + 150, // 距离有待修改1
                    y: v,
                    alpha: {
                        from: 0,
                        to: 1
                    },
                    delay: 500, //后期在该延迟区间补充施法特效
                    ease: 'Expo.Out',
                    duration: 500,
                    onComplete: function () {
                        sp.play('atk' + atk_id);
                        check=this;
                        this.remove();//删除当前补间动画
                        console.log(this);
                    }
                });
                console.log("当前创建的补间动画 ->",tween);
                tween.play();
自写demo——create
复制代码

 

这里是官网API的config配置:here(看TweenBuilderConfig)

10.指定FPS帧率,查了大半天资料,并没有找到我所想要的游戏内动态改动FPS达到变速的效果,只能是在GameConfig处配置fps对象的target属性(默认60),且一定需要forceSetTimeout:true,否则不生效【另外,这里的target也只是告诉phaser3理想帧率,实际并不一定能达到,实际帧率在game.loop.actualFps查看】

配置格式可以参考:here

 

11.加载动画

参考这里代码就行了,找帧率控制意外发现的官网样例代码。

 

12.反向动画,补充部分anims事件:here

 对其监听事件模板(动作进行中每一帧都会调用):

sprite.on(Phaser.Animations.Events.ANIMATION_UPDATE, function (anim, frame, gameObject){}

中间的一句话即是,关键词为anims.reverse()

 

13.文本绘制,

API学习:here

这里有一个技巧,将文本转换为图像再进行绘制会提高绘制性能:

 

复制代码
/** 文字精灵
 * @description 把输入的文字转换成纹理后再转成精灵,以提高性能
 * 
 */
export class Character extends Phaser.GameObjects.Sprite {
    constructor(scene:Phaser.Scene,x:number,y:number, character:string) {
        const text = scene.make.text({
            add: false,
            x: 0,
            y: 0,
            text: character,
            style: {
                fontSize: '64px',
                fontFamily: 'gb_kaiti',
                color: '#ffffff',
                align: 'center',
                backgroundColor: '#ff00ff'
            }
        });
        // 用Text的画布生成纹理,加到场景的纹理管理器中
        scene.textures.addCanvas(character, text.canvas);
        // 用字头的纹理生成精灵
        super(scene,x,y,character);
    }
}
复制代码

 

14.graphsic图形绘制

基本添加方式为var pic=scene.add.graphsic();

其相关API:here1here2

需要注意的是,对于一个graphsic绘制的所有图形,对于其graphsic.clear()的作用与其绘制图形的.clear()是一样的,清除该graphsic绘制的所有图形,所以,应该把一个graphsic视为一个绘制图形的整体模块,如果有需要,一个scene最好由多个graphsic构成。

 

15.更改鼠标样式

  1.全局修改:this.input.setDefaultCursor('url(./xxx.cur), pointer');

  2.局部组件修改(按钮之类的效果):(xxx为需要添加按钮交互功能的指向变量)xxx.setInteractive({cursor: 'url(./yyy.cur), pointer'});

 

16.按键绑定

 

 

两个图共同展示AD按键实现相机移动,其他情况的话就去参考官网的input-keyboard看demo样例学习吧。

下面是通过左右按键绑定相机移动的特定方式:

 

 

 

 

 

17.

【Over】

posted @   Renhr  阅读(899)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!
点击右上角即可分享
微信分享提示