mirror of
https://github.com/ifengzp/cocos-awesome.git
synced 2024-12-27 12:08:41 +00:00
121 lines
4.0 KiB
TypeScript
121 lines
4.0 KiB
TypeScript
|
const { ccclass, property } = cc._decorator;
|
||
|
const CALC_RECT_WIDTH = 40;
|
||
|
const CLEAR_LINE_WIDTH = 40;
|
||
|
|
||
|
@ccclass
|
||
|
export default class Scratch_ticket extends cc.Component {
|
||
|
@property(cc.Node)
|
||
|
maskNode: cc.Node = null;
|
||
|
@property(cc.Node)
|
||
|
ticketNode: cc.Node = null;
|
||
|
@property(cc.Label)
|
||
|
progerss: cc.Label = null;
|
||
|
|
||
|
onLoad() {
|
||
|
this.reset();
|
||
|
this.ticketNode.on(cc.Node.EventType.TOUCH_START, this.touchStartEvent, this);
|
||
|
this.ticketNode.on(cc.Node.EventType.TOUCH_MOVE, this.touchMoveEvent, this);
|
||
|
this.ticketNode.on(cc.Node.EventType.TOUCH_END, this.touchEndEvent, this);
|
||
|
this.ticketNode.on(cc.Node.EventType.TOUCH_CANCEL, this.touchEndEvent, this);
|
||
|
}
|
||
|
|
||
|
beforeDestroy() {
|
||
|
this.ticketNode.off(cc.Node.EventType.TOUCH_START, this.touchStartEvent, this);
|
||
|
this.ticketNode.off(cc.Node.EventType.TOUCH_MOVE, this.touchMoveEvent, this);
|
||
|
this.ticketNode.on(cc.Node.EventType.TOUCH_END, this.touchEndEvent, this);
|
||
|
this.ticketNode.on(cc.Node.EventType.TOUCH_CANCEL, this.touchEndEvent, this);
|
||
|
}
|
||
|
|
||
|
touchStartEvent(event) {
|
||
|
let point = this.ticketNode.convertToNodeSpaceAR(event.getLocation());
|
||
|
this.clearMask(point);
|
||
|
}
|
||
|
|
||
|
touchMoveEvent(event) {
|
||
|
let point = this.ticketNode.convertToNodeSpaceAR(event.getLocation());
|
||
|
this.clearMask(point);
|
||
|
}
|
||
|
|
||
|
touchEndEvent() {
|
||
|
this.tempDrawPoints = [];
|
||
|
this.calcProgress();
|
||
|
}
|
||
|
|
||
|
calcDebugger: boolean = false; // 辅助开关,开启则会绘制划开涂层所属的小格子
|
||
|
calcProgress() {
|
||
|
let hitItemCount = 0;
|
||
|
let ctx = this.ticketNode.getComponent(cc.Graphics);
|
||
|
this.polygonPointsList.forEach((item) => {
|
||
|
if (!item.isHit) return;
|
||
|
hitItemCount += 1;
|
||
|
|
||
|
if (!this.calcDebugger) return;
|
||
|
ctx.rect(item.rect.x, item.rect.y, item.rect.width, item.rect.height);
|
||
|
ctx.fillColor = cc.color(216, 18, 18, 255);
|
||
|
ctx.fill();
|
||
|
});
|
||
|
|
||
|
this.progerss.string = `已经刮开了 ${Math.ceil((hitItemCount / this.polygonPointsList.length) * 100)}%`;
|
||
|
}
|
||
|
|
||
|
tempDrawPoints: cc.Vec2[] = [];
|
||
|
clearMask(pos) {
|
||
|
let mask: any = this.maskNode.getComponent(cc.Mask);
|
||
|
let stencil = mask._graphics;
|
||
|
const len = this.tempDrawPoints.length;
|
||
|
this.tempDrawPoints.push(pos);
|
||
|
|
||
|
if (len <= 1) {
|
||
|
// 只有一个点,用圆来清除涂层
|
||
|
stencil.circle(pos.x, pos.y, CLEAR_LINE_WIDTH / 2);
|
||
|
stencil.fill();
|
||
|
|
||
|
// 记录点所在的格子
|
||
|
this.polygonPointsList.forEach((item) => {
|
||
|
if (item.isHit) return;
|
||
|
const xFlag = pos.x > item.rect.x && pos.x < item.rect.x + item.rect.width;
|
||
|
const yFlag = pos.y > item.rect.y && pos.y < item.rect.y + item.rect.height;
|
||
|
if (xFlag && yFlag) item.isHit = true;
|
||
|
});
|
||
|
} else {
|
||
|
// 存在多个点,用线段来清除涂层
|
||
|
let prevPos = this.tempDrawPoints[len - 2];
|
||
|
let curPos = this.tempDrawPoints[len - 1];
|
||
|
|
||
|
stencil.moveTo(prevPos.x, prevPos.y);
|
||
|
stencil.lineTo(curPos.x, curPos.y);
|
||
|
stencil.lineWidth = CLEAR_LINE_WIDTH;
|
||
|
stencil.lineCap = cc.Graphics.LineCap.ROUND;
|
||
|
stencil.lineJoin = cc.Graphics.LineJoin.ROUND;
|
||
|
stencil.strokeColor = cc.color(255, 255, 255, 255);
|
||
|
stencil.stroke();
|
||
|
|
||
|
// 记录线段经过的格子
|
||
|
this.polygonPointsList.forEach((item) => {
|
||
|
item.isHit = item.isHit || cc.Intersection.lineRect(prevPos, curPos, item.rect);
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
polygonPointsList: { rect: cc.Rect; isHit: boolean }[] = [];
|
||
|
reset() {
|
||
|
let mask: any = this.maskNode.getComponent(cc.Mask);
|
||
|
mask._graphics.clear();
|
||
|
|
||
|
this.tempDrawPoints = [];
|
||
|
this.polygonPointsList = [];
|
||
|
this.progerss.string = '已经刮开了 0%';
|
||
|
this.ticketNode.getComponent(cc.Graphics).clear();
|
||
|
|
||
|
// 生成小格子,用来辅助统计涂层的刮开比例
|
||
|
for (let x = 0; x < this.ticketNode.width; x += CALC_RECT_WIDTH) {
|
||
|
for (let y = 0; y < this.ticketNode.height; y += CALC_RECT_WIDTH) {
|
||
|
this.polygonPointsList.push({
|
||
|
rect: cc.rect(x - this.ticketNode.width / 2, y - this.ticketNode.height / 2, CALC_RECT_WIDTH, CALC_RECT_WIDTH),
|
||
|
isHit: false
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|