Egret社区

[Egret Engine] webgl下遮罩做拖拽卡成狗

2017-2-28 18:58
518111
产品 Egret Engine 版本 4.0.2
复现概率 100% 平台 Android 6.0
复现步骤 做一个遮罩,拖拽
问题描述 在部分安卓手机上,比较大的遮罩做拖拽非常非常卡
错误代码 module views.commons {

/**
* 搓牌
*/
export class RubCard extends eui.Group {

private static DURATION: number = 500;

private maskBack: egret.Shape;

private maskFront: egret.Shape;

private back: egret.Bitmap;

private front: egret.Sprite;

private meta: egret.Point;

private tween: TweenMax;

private frontTop: egret.Shape;
private frontBottom: egret.Shape;

constructor(back: egret.DisplayObject, front: egret.DisplayObject, isT: Boolean) {
super();

var rtb: egret.RenderTexture = new egret.RenderTexture();
rtb.drawToTexture(back);

var rtf: egret.RenderTexture = new egret.RenderTexture();
rtf.drawToTexture(front);

this.back = new egret.Bitmap(rtb);
this.addChild(this.back);

this.front = new egret.Sprite();
var bmp = new egret.Bitmap(rtf);
this.front.addChild(bmp);

this.frontTop = new egret.Shape();
this.frontTop.graphics.beginFill(0XFFFFFF, 1);
this.frontTop.graphics.drawRect(0, 0, (isT) ? 128 : 130, (isT) ? 122 : 105);
this.frontTop.graphics.endFill();
this.frontTop.x = (isT) ? 720 : 718;
this.frontTop.y = (isT) ? 9 : 10;
this.front.addChild(this.frontTop);
this.addChild(this.front);

this.frontBottom = new egret.Shape();
this.frontBottom.graphics.beginFill(0XFFFFFF, 1);
this.frontBottom.graphics.drawRect(0, 0, (isT) ? 128 : 130, (isT) ? 122 : 105);
this.frontBottom.graphics.endFill();
this.frontBottom.x = 20;
this.frontBottom.y = (isT) ? 448 : 460;
this.front.addChild(this.frontBottom);

this.maskBack = new egret.Shape();
this.maskBack.graphics.beginFill(0XFF0000);
this.maskBack.graphics.drawRect(0, 0, Math.max(this.back.width, this.back.height) * 2, Math.max(this.back.width, this.back.height) * 2);
this.maskBack.graphics.endFill();
this.addChild(this.maskBack);

this.maskFront = new egret.Shape();
this.maskFront.graphics.beginFill(0XFF0000);
this.maskFront.graphics.drawRect(0, 0, Math.max(this.back.width, this.back.height) * 2, Math.max(this.back.width, this.back.height) * 2);
this.maskFront.graphics.endFill();
this.addChild(this.maskFront);

this.back.mask = this.maskBack;
this.front.mask = this.maskFront;

this.width = this.back.width;
this.height = this.back.height;

this.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onTouchEventHandler, this);

// this.maskBack.cacheAsBitmap = true;
// this.maskFront.cacheAsBitmap = true;
// this.back.cacheAsBitmap = true;
// this.front.cacheAsBitmap = true;

this.init();
}

public init(): void {
this.maskBack.x = this.back.width / 2;
this.maskBack.y = this.back.height - this.maskBack.height;
this.maskBack.anchorOffsetX = this.maskBack.width / 2;
this.maskBack.anchorOffsetY = 0;
this.maskBack.rotation = 0;

this.maskFront.x = this.maskBack.x
this.maskFront.y = this.maskBack.y;
this.maskFront.anchorOffsetX = this.maskBack.anchorOffsetX;
this.maskFront.anchorOffsetY = this.maskBack.anchorOffsetY;
this.maskFront.rotation = this.maskBack.rotation;

this.back.x = 0;
this.back.y = 0;
this.back.rotation = 0;

this.front.x = 0;
this.front.y = this.back.height;
this.front.rotation = 0;

this.tween = null;
}

private onTouchEventHandler(event: egret.TouchEvent): void {
if (this.tween) {
return;
}

if (event.type == egret.TouchEvent.TOUCH_BEGIN) {
this.init();
this.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE, this.onTouchEventHandler, this);
this.stage.addEventListener(egret.TouchEvent.TOUCH_CANCEL, this.onTouchEventHandler, this);
this.stage.addEventListener(egret.TouchEvent.TOUCH_END, this.onTouchEventHandler, this);
this.stage.addEventListener(egret.TouchEvent.TOUCH_RELEASE_OUTSIDE, this.onTouchEventHandler, this);

this.meta = this.globalToLocal(event.stageX, event.stageY);
this.onUpdate(this.globalToLocal(event.stageX, event.stageY));
}
else if (event.type == egret.TouchEvent.TOUCH_MOVE) {
this.onUpdate(this.globalToLocal(event.stageX, event.stageY));
this.checkPosition(this.globalToLocal(event.stageX, event.stageY));
}
else {
if (this.stage) {
this.stage.removeEventListener(egret.TouchEvent.TOUCH_MOVE, this.onTouchEventHandler, this);
this.stage.removeEventListener(egret.TouchEvent.TOUCH_CANCEL, this.onTouchEventHandler, this);
this.stage.removeEventListener(egret.TouchEvent.TOUCH_END, this.onTouchEventHandler, this);
this.stage.removeEventListener(egret.TouchEvent.TOUCH_RELEASE_OUTSIDE, this.onTouchEventHandler, this);
}

this.onDrop(this.globalToLocal(event.stageX, event.stageY));
}

event.updateAfterEvent();
}

private onUpdate(point: egret.Point): void {
// 计算遮罩角度
var angle = Math.atan2((this.meta.x - point.x), (this.meta.y - point.y));
var rotation = Math.min(90, Math.max(-90, (-180 * angle / Math.PI) % 180));

this.maskBack.rotation = rotation;
this.maskFront.rotation = this.maskBack.rotation;
this.front.rotation = rotation * 2;

// 计算遮罩位置
var a = point.x - this.meta.x;
var b = this.meta.y - point.y;
var c = Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
var x = a * this.maskBack.height / c;
var y = b * this.maskBack.height / c;

if (point.y > this.meta.y) {
this.maskBack.x = (point.x > this.meta.x) ? (point.x - this.meta.x) / 2 + this.maskBack.height : (point.x < this.meta.x) ? (point.x - this.meta.x) / 2 + this.back.width - this.maskBack.height : point.x;
this.maskBack.y = (point.x == this.meta.x) ? this.back.height - this.maskBack.height : (this.back.height - this.meta.y) + point.y + (this.meta.y - point.y) / 2;
} else {
this.maskBack.x = isNaN(x) ? this.back.width / 2 : (point.x > this.meta.x) ? (point.x - this.meta.x) / 2 + x : (point.x - this.meta.x) / 2 + x + this.back.width;
this.maskBack.y = isNaN(y) ? this.back.height - this.maskBack.height : (this.back.height - this.meta.y) + point.y + (this.meta.y - point.y) / 2 - y;
}

this.maskFront.x = this.maskBack.x = this.back.x + this.maskBack.x;
this.maskFront.y = this.maskBack.y = this.back.y + Math.min(this.back.height, this.maskBack.y);

// 计算牌面位置
this.front.anchorOffsetX = (point.x > this.meta.x) ? 0 : (point.x < this.meta.x) ? this.front.width : this.front.width / 2;
this.front.anchorOffsetY = 0;

this.front.x = (point.x > this.meta.x) ? a : (point.x < this.meta.x) ? this.back.width + a : this.front.width / 2;
this.front.y = this.back.height - b;

this.front.x = this.back.x + this.front.x;
this.front.y = this.back.y + Math.min(this.back.height, this.front.y);
}

private checkPosition(point: egret.Point): void {
var tweenUpdate: Function = () => {
this.onUpdate(point);
}
var tweenComplete: Function = () => {
TweenMax.delayedCall(0.5, () => { this.dispatchEvent(new egret.Event(egret.Event.COMPLETE)); })
}

if (this.front.rotation > 90 && this.front.x > this.back.width * 2 / 3) {
TweenMax.to(this.back, RubCard.DURATION / 1000, { x: -this.back.width });
this.tween = TweenMax.to(point, RubCard.DURATION / 1000, { x: this.meta.x + this.back.width * 2, y: this.meta.y, onUpdate: tweenUpdate, onComplete: tweenComplete });

TweenMax.to(this.frontTop, RubCard.DURATION / 1000, { alpha: 0 });
TweenMax.to(this.frontBottom, RubCard.DURATION / 1000, { alpha: 0 });

sound_play_voice(SOUND_rub_over);
return;
} else if (this.front.rotation < -90 && this.front.x < this.back.width * 1 / 3) {
TweenMax.to(this.back, RubCard.DURATION / 1000, { x: this.back.width });
this.tween = TweenMax.to(point, RubCard.DURATION / 1000, { x: this.meta.x - this.back.width * 2, y: this.meta.y, onUpdate: tweenUpdate, onComplete: tweenComplete });

TweenMax.to(this.frontTop, RubCard.DURATION / 1000, { alpha: 0 });
TweenMax.to(this.frontBottom, RubCard.DURATION / 1000, { alpha: 0 });

sound_play_voice(SOUND_rub_over);
return;
} else if (this.front.y < this.back.height * 1 / 3) {
TweenMax.to(this.back, RubCard.DURATION / 1000, { y: this.back.height });
this.tween = TweenMax.to(point, RubCard.DURATION / 1000, { x: this.meta.x, y: this.meta.y - this.back.height * 2, onUpdate: tweenUpdate, onComplete: tweenComplete });

TweenMax.to(this.frontTop, RubCard.DURATION / 1000, { alpha: 0 });
TweenMax.to(this.frontBottom, RubCard.DURATION / 1000, { alpha: 0 });

sound_play_voice(SOUND_rub_over);
return;
}
}

private onDrop(point: egret.Point): void {
var tweenUpdate: Function = () => {
this.onUpdate(point);
}

var tweenReset: Function = () => {
this.init();
this.dispatchEvent(new egret.Event(egret.Event.ENDED));
}

if (this.tween) {
return;
}

this.tween = TweenMax.to(point, RubCard.DURATION / 1000, { x: this.meta.x, y: this.meta.y, onUpdate: tweenUpdate, onComplete: tweenReset });
}

}
}
BUG截图
在安卓部分手机上,webgl模式,做一个搓牌效果。

大的遮罩一个大图,然后做触摸拖拽。特别特别卡,非常卡。
分享到 :
0 人收藏

11 个回复

倒序浏览
wyb815  圆转纯熟 | 2017-2-28 19:53:54
非矩形遮罩性能消耗都很大,不知道是引擎问题还是webgl问题。我们项目经验是不用非矩形遮罩。
yjtx  官方团队 | 2017-3-1 09:45:53
wyb815 发表于 2017-2-28 19:53
非矩形遮罩性能消耗都很大,不知道是引擎问题还是webgl问题。我们项目经验是不用非矩形遮罩。 ...

不要用显示对象做遮罩来做有动态效果的,这个性能消耗就是大。
metinyt  圆转纯熟 | 2017-3-1 10:37:57
yjtx 发表于 2017-3-1 09:45
不要用显示对象做遮罩来做有动态效果的,这个性能消耗就是大。

用什么做遮罩最好呢?
归零  登堂入室 | 2017-3-1 10:42:03
metinyt 发表于 2017-3-1 10:37
用什么做遮罩最好呢?

egret.Rectangle
airsiao  登堂入室 | 2017-3-1 13:01:22
wyb815 发表于 2017-2-28 19:53
非矩形遮罩性能消耗都很大,不知道是引擎问题还是webgl问题。我们项目经验是不用非矩形遮罩。 ...

是矩形的遮罩,绝对矩形,draw出来的
airsiao  登堂入室 | 2017-3-1 13:01:58
yjtx 发表于 2017-3-1 09:45
不要用显示对象做遮罩来做有动态效果的,这个性能消耗就是大。

呃,不用显示对象做遮罩....还有别的可以做遮罩么....?@.@
airsiao  登堂入室 | 2017-3-1 13:02:14

我试试这个,哈哈,多谢
airsiao  登堂入室 | 2017-3-1 13:15:57

呃....可是rectangle的话.....没办法设置anchorOffset和rotation.....
airsiao  登堂入室 | 2017-3-1 13:18:55

用rectangle似乎实现不了我代码里这个效果啊...
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|京网文[2014]0791-191号|京ICP证150115号|Egret社区 ( 京ICP备14025619号 )

Powered by Discuz! X3.4 © 2001-2019 Comsenz Inc.

返回顶部