决战-Pow!第四集:对象视图

先说一句很抱歉,这几天项目上线,忙得焦头烂额,把这个原本要两天一更的系列暂停了几天。
今天终于迎来一天休息,终于可以安心下来写下技术文章。
上一回,说过了对象系统,那么这回就讲解一下与对象紧密相连的视图(相当于外观)。

1.所有的对象视图均使用Laya.Sprite来存放,所以需要继承一下同时这个基类需要持有EntityObject引用,因为需要根据对象的逻辑进行外观变化,依然采用之前对象池管理。

class ViewObject extends Laya.Sprite implements IPoolObject{
    private _poolType:string;
    constructor(){
        super();
    }

    public createInFactory(entity:EntityObject, poolType:string) {
        this._poolType = poolType;
        this.create(entity);
    }

    protected create(entity:EntityObject) {};

    public releaseInFactory() {
        this.release();
    }

    public release(){}

    public getPoolType(){
        return this.constructor.name;
    }

    public dispose(){
        Logger.log("dispose.");
        // this.removeSelf();
        this.destroy();
    }
}

这些View的创建和管理,通过工厂类处理:

class ViewFactory {
    private static _isInit: boolean = false;
    private static _objectPool: ObjectPool;
    private static _viewRoot: Laya.Node;
    private static _mapObject: Dictionary;
    constructor() {
    }
    public static init(viewRoot: Laya.Node): void {
        if (this._isInit) {
            return;
        }
        this._isInit = true;
        this._viewRoot = viewRoot;
        this._mapObject = new Dictionary();
        this._objectPool = new ObjectPool();
    }
    public static release(): void {
        this._isInit = false;
        for (let pair of this._mapObject) {
            pair.value.releaseInFactory();
            pair.value.dispose();
        }
        this._mapObject.clear();
        this._objectPool.release();
        this._viewRoot = null;
    }
    public static createView(cls:any, entity?: EntityObject, parent:Laya.Sprite = null) {
        let obj: ViewObject = null;
        let useObjectPool: boolean = true;
        obj = this._objectPool.pop(cls.name) as ViewObject;
        if (obj == null) {
            useObjectPool = false;
            obj = this.createByClass(cls);
            // Logger.log('view create');
        }else{
            // Logger.log('view reuse');
        }
        if (obj != null) {
            if(parent != null){
                parent.addChild(obj);
            }else{
                this._viewRoot.addChild(obj);
            }
        }
        obj.createInFactory(entity, cls.name);
        this._mapObject.addKeyValue(entity, obj);
        return obj;
    }
    private static createByClass(cls:any):ViewObject {
        let view:ViewObject = new cls() as ViewObject;
        return view;
    }
    public static releaseView(entity: EntityObject) {
        if (entity != null) {
            let obj: ViewObject = this._mapObject.get(entity);
            if (obj != null) {
                this._mapObject.removeKeyValue(entity);
                obj.releaseInFactory();
                obj.removeSelf();
                // 加入对象池
                this._objectPool.push(obj);
            }
        }
    }
    public static logPool(){
        Logger.log(this._objectPool);
    }
}

通过工厂方法创建,同是与对象实体关联。

然后我们就可以根据我们自己的需要编写不同类的View,可以是骨骼动画,静态图片等等。

class PowView extends ViewObject{
    constructor(){
        super();
        
    }
    public initView(){
        if(this._root == null){
            let skPath:string = 'res/anim/pow.sk';
            let skImgPath:string = 'res/anim/pow.png'
            let factory:Laya.Templet = new Laya.Templet();
            factory.parseData(Loader.getRes(skImgPath), Loader.getRes(skPath));
            this._root = factory.buildArmature()
            this._root.play(0, true);
            this.addChild(this._root);
            // this._root.visible = false;
        }
    }

    private _root:Skeleton = null;
    private _debugView:Laya.Sprite = null;
    private _entity:PowEntity = null;
    
    create(entity:EntityObject){
        this.initView();
        this._entity = entity as PowEntity;
        // if (this._entity) {
        //     if(this._debugView == null) {
        //         this._debugView = new Laya.Sprite();
        //         this.addChild(this._debugView);
        //         this._debugView.graphics.drawCircle(this.x, this.y + this._entity.data.offsetY, this._entity.data.size, '#00ff00');
        //         this._debugView.alpha = 0.5;
        //     }
        // }
        let p:Laya.Point = this._entity.position;
        this.pos(p.x, p.y);
        Laya.timer.frameLoop(1, this, this.update);
        // this._root.visible = true;
    }

    public setType(type:number) {
        switch(type){
            case GameVKey.SCISSORS:
                this._root.play('scissors', true);
                break;
            case GameVKey.ROCK:
                this._root.play('rock', true);
                break;
            case GameVKey.PAPER:
                this._root.play('paper', true);
                break;
            default:
                this._root.play(0, true);
                break;
        }
    }

    public die(dieHandler?:any){
        this._root.play('die', false);
        this._root.playbackRate(4);
        this._root.on(Laya.Event.STOPPED, this, this.onStopped, [dieHandler]);
    }

    private onStopped(dieHandler?:any):void{
        this._root.off(Laya.Event.STOPPED, this, this.onStopped);
        Logger.log("onStopped");
        if(dieHandler){
            dieHandler();
        }
    }

    public setDirection(isMain:boolean){
        // 非自己翻转
        this.rotation = isMain ? 0 : 180;
    }
    public update(){
        if(this._entity != null){
            let p:Laya.Point = this._entity.position;
            if (this.isPosEqual(p)){
                return;
            }
            this.pos(p.x, p.y);
        }
    }

    public isPosEqual(pos:Laya.Point){
        return this.x == pos.x && this.y == pos.y;
    }

    release(){
        this._entity = null;
    }
}

使用方法,对象实体内创建和移除:

// 创建
// Logger.log('PowEntity:create');
this._view = ViewFactory.createView(PowView, this) as PowView;

// 移除(其实这个View还是复用的)
//Logger.log('PowEntity:release');
ViewFactory.releaseView(this);

可以看见这个View的移动是根据entity的position进行位移,而且是死亡的时候会有回调,用于回收~
关于对象视图就只有这些,都是一些很简单的根据状态类型等等,改变动画,改变图片。
如果需要使用到配置的话,就直接通过类型id关联对应的View即可。

开发小游戏的话,只需要有这个基本模子就可以创建出很多类型的小游戏,思路应该很清晰的~
接下来就是主游戏流程的搭建,把这些内容串起来,下集见~

你可能感兴趣的:(决战-Pow!第四集:对象视图)