随笔 - 283  文章 - 0 评论 - 110 阅读 - 117万
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

版本:2.4.10

参考:Cocos论坛-刮刮卡实现

 

一 显示效果

二 实现原理

三 刮刮卡实现

 

一 显示效果

 

二 实现原理

实现是利用一张纯灰色cover图片盖在谢谢惠顾图片上方,将图片cover放在cc.Mask节点下进行遮罩。

将cc.Mask设置为反向遮罩,并设置高宽为0,并使用Mask的cc.Graphcis进行线段绘制,这样有线段的地方灰色图片cover就会透明,露出下方的"谢谢惠顾"。

 

                              无遮罩                                                                       正常遮罩                                                                           反向遮罩

                                    

 

 

三 刮刮卡实现

创建空节点cc.Node,命名为mask,从右边属性面板选择添加组件-渲染组件-Mask。(直接在cc.Node上右键创建节点-渲染组件-是没有Mask的

 

设置mask高宽为0,勾选反向遮罩Inverted,遮罩方式Type选择RECT

 

 找一张纯灰色图片

 

将图片放在mask节点下

 

因为反向遮罩是遮挡的地方才会变透明,当mask高宽为0时啥也没遮挡,这时cover图片是可以全部看见的。

 

尝试把mask高宽修改成50x50,可以看到会透明了一个50x50的矩形。(实际运行时记得把mask高宽改回成0)

 

把谢谢惠顾图片放在cover图片下

 

 

代码中获取mask的属性_graphics(转换成any才能获取,因为这个属性没有暴露出来

根据触摸的移动,使用moveTo()和lineTo进行绘制线段,有线段的部分就会露出下方的"谢谢惠顾"。

1
2
3
4
5
6
7
8
let graphics: cc.Graphics = (this.mask as any)._graphics;
graphics.lineWidth = 20;
graphics.lineCap = cc.Graphics.LineCap.ROUND;
graphics.lineJoin = cc.Graphics.LineJoin.ROUND;
graphics.strokeColor = cc.color(255, 255, 255, 255);
graphics.moveTo(pos.x, pos.y);
graphics.lineTo(pos.x, pos.y);
graphics.stroke();

 

完整代码:

封装的刮刮卡类, GuaGuaKa.ts:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
const { ccclass, property } = cc._decorator;
 
/**
 * 刮刮卡
 * @author chenkai 2022.9.27
 */
@ccclass
export default class GuaGuaKa {
 
    /**遮罩 */
    private mask: cc.Mask = null;
    /**覆盖图片 */
    private cover: cc.Node = null;
 
    /**
     * 初始化
     * @param mask   遮罩
     * @param cover  覆盖图片
     */
    public init(mask: cc.Mask, cover: cc.Node) {
        this.mask = mask;
        this.cover = cover;
        this.reset();
    }
 
    /**开始 */
    public begin() {
        //设置线段
        let graphics: cc.Graphics = (this.mask as any)._graphics;
        graphics.lineWidth = 20;
        graphics.lineCap = cc.Graphics.LineCap.ROUND;
        graphics.lineJoin = cc.Graphics.LineJoin.ROUND;
        graphics.strokeColor = cc.color(255, 255, 255, 255);
 
        //触摸事件
        this.cover.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.cover.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
    }
 
    /**停止 */
    public stop() {
        this.cover.off(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.cover.off(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
    }
 
    /**重置 */
    public reset() {
        let graphics: cc.Graphics = (this.mask as any)._graphics;
        graphics.clear();
    }
 
    /**触摸开始 */
    private onTouchStart(e: cc.Event.EventTouch) {
        //记录触摸起始点,将触摸点世界坐标转成cover本地坐标
        let pos = this.cover.convertToNodeSpaceAR(e.getLocation());
        //将画线起点移动到触摸起始点
        let graphics: cc.Graphics = (this.mask as any)._graphics;
        graphics.moveTo(pos.x, pos.y);
    }
 
    /**触摸移动 */
    private onTouchMove(e: cc.Event.EventTouch) {
        //将触摸点世界坐标转成cover本地坐标
        let pos = this.cover.convertToNodeSpaceAR(e.getLocation());
        //画线
        let graphics: cc.Graphics = (this.mask as any)._graphics;
        graphics.lineTo(pos.x, pos.y);
        graphics.stroke();
    }
 
    /**销毁 */
    public dispose() {
        this.stop();
        this.mask = null;
        this.cover = null;
    }
}

 

主场景 Main.ts:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import GuaGuaKa from "./GuaGuaKa";
 
 
const { ccclass, property } = cc._decorator;
 
/**
 * 刮刮卡
 * @author chenkai 2022.9.27
 */
@ccclass
export default class MainScene extends cc.Component {
 
    @property({ type: cc.Mask, tooltip: "遮罩" })
    mask: cc.Mask = null;
    @property({ type: cc.Node, tooltip: "纯灰色图片" })
    cover: cc.Node = null;
 
    /**刮刮卡 */
    private guaguaKa: GuaGuaKa;
 
    public onLoad() {
        this.guaguaKa = new GuaGuaKa();
        this.guaguaKa.init(this.mask, this.cover);
        this.guaguaKa.begin();
    }
}

  

 

posted on   gamedaybyday  阅读(229)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示