决战-Pow!第四集:对象视图
2018-02-10 本文已影响9人
回忆并快
先说一句很抱歉,这几天项目上线,忙得焦头烂额,把这个原本要两天一更的系列暂停了几天。
今天终于迎来一天休息,终于可以安心下来写下技术文章。
上一回,说过了对象系统,那么这回就讲解一下与对象紧密相连的视图(相当于外观)。
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<EntityObject, ViewObject>;
constructor() {
}
public static init(viewRoot: Laya.Node): void {
if (this._isInit) {
return;
}
this._isInit = true;
this._viewRoot = viewRoot;
this._mapObject = new Dictionary<EntityObject, ViewObject>();
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即可。
开发小游戏的话,只需要有这个基本模子就可以创建出很多类型的小游戏,思路应该很清晰的~
接下来就是主游戏流程的搭建,把这些内容串起来,下集见~