记录Laya2.0 实现刮刮乐效果

实现刮刮乐的效果,直接上效果图

第一种思路:

两张图片,一张底板显示,一张遮罩显示。利用获取遮罩的像素,记录鼠标在遮罩上的位置,获取该位置一定范围内的像素点集合,更改像素点的颜色。(理论上,因为涉及到像素级操作,未做实践。)

第二种思路:

两张图片,一张底板img_full显示,一张遮罩img_bg显示。如图摆放滑动鼠标给底板图片动态绘制mask就可以实现效果了。

private r: number = 3;
private $bgMask: Laya.Sprite = new Laya.Sprite();
private isTouched: boolean = false;
test(): void{
this.$bgImage.mask = this.$bgMask;
this.$bgImage.on(Laya.Event.MOUSE_DOWN, this, (event: Laya.Event)=>{
this.isTouched = true;
});
this.$bgImage.on(Laya.Event.MOUSE_MOVE, this, (event: Laya.Event)=>{
if(this.isTouched)
this.drawCircle(event.stageX, event.stageY);
});
this.$bgImage.on(Laya.Event.MOUSE_UP, this, (event: Laya.Event)=>{
this.isTouched = false;
});
}

drawCircle(x: number, y: number): void{
this.$bgMask.graphics.drawCircle(x, y, this.r, "red");
}

第三种思路:

参考官方新手引导示例,利用叠加模式来实现。实现代码如下,以下代码包含两种方式去实现绘制路线的平滑,一种是两点之间绘制直线;一种是绘制圆或者矩形等,再分解过程形成片段,利用自定义形成贝塞尔平滑点集合,再利用这些形成的点进行绘制(注意:该种方法在绘制区域面大的时候回导致掉帧严重!!!)。

	/**
     * 刮刮乐效果
     */
    private ScratchImage(): void{
        const Sprite = Laya.Sprite;
        // 绘制底图
        this.image = GameUtils.findObj("showDi", this.owner);
        // 引导所在容器
        this.guideContainer = new Sprite();
        this.owner.addChild(this.guideContainer);
        this.guideContainer.cacheAs = "bitmap";
        // 绘制遮罩区,含透明度,可见游戏背景
        var maskArea = new Sprite();
        this.guideContainer.addChild(maskArea);
        maskArea.width = this.image.width;
        maskArea.height = this.image.height;
        // 遮罩的位置
        var maskPos = new Laya.Vector2((1280 -maskArea.width)*0.5, (720-maskArea.height)*0.5);
        maskArea.pos(maskPos.x, maskPos.y);
        maskArea.loadImage("achievement/top_bg_full@2x.png");
        maskArea.alpha = 1;
        // 用来绘制的对象,利用叠加模式,从遮罩区域抠出可交互区
        this.interactionArea = new Sprite();
        this.guideContainer.addChild(this.interactionArea);
        this.interactionArea.blendMode = "destination-out";
        Laya.stage.on(Laya.Event.MOUSE_DOWN, this, function (e){
            this.isTouched = true;
            // this.penultPos = new Laya.Vector2(e.stageX, e.stageY);
            this.prevX = e.stageX;
            this.prevY = e.stageY
        });
        // 鼠标是否不在目标图片范围内
        var isOut = false;
        Laya.stage.on(Laya.Event.MOUSE_MOVE, this, function (e){
            if(this.isTouched == true){
                // this.scratchSmopthPath(e.stageX, e.stageY);
                // 世界坐标转换为this.image的局部坐标
                var pos = this.image.globalToLocal(new Laya.Point(e.stageX, e.stageY));
                // 当鼠标不在图片显示范围内,重新设置划线的起点坐标
                if(pos.x < 0 || pos.x > this.image.width || pos.y >this.image.width || pos.y < 0){
                    isOut = true;
                }else{
                    if(isOut){
                        isOut = false;
                        this.prevX = e.stageX;
                        this.prevY = e.stageY
                    }
                    this.nextStep(e.stageX, e.stageY);
                }
            }
        });
        Laya.stage.on(Laya.Event.MOUSE_UP, this, function (e){
            this.isTouched = false;
            // this.twoPoint = false;
            this.prevX = 0;
            this.prevY = 0;
        });
    }

    /**
     * 刮奖操作  注意:在刮奖结束后要把画的线清理,false掉跟遮罩相关的容器对象!避免卡顿掉帧!
     * (当玩家手指滑到刮奖区外边, 首先要判断玩家操作区域是否在底图范围内。
     * 若不存在,则更新this.prevX,this.prevY 的信息为重新进入矩形的交点坐标)
     */
    nextStep(x, y) {
        this.interactionArea.graphics.drawLine(this.prevX, this.prevY, x, y, "#000000", 20);
        this.prevX = x
        this.prevY = y;
    }
	/*private twoPoint: boolean = false;
    privatelastPos: Laya.Vector2;//最后一个点
    private penultPos: Laya.Vector2;//倒数第二个点
    
    // 另一种方式(平滑滑动绘图的区域)绘图实现刮刮乐
    private scratchSmopthPath(nowX:number, nowY:number): void{
        var posMouse = new Laya.Vector2(nowX, nowY);
        if(this.twoPoint && this..calcDistance(posMouse, this.lastPos) > 10){
            var distancePoint = this.calcDistance(posMouse, this.lastPos);
            var segments = Math.ceil(distancePoint / 3);//计算出平滑的段数
            segments = segments < 1 ? 1 : segments;
            var pointList: Array<Laya.Vector2> = this.Beizier(this.penultPos, this.lastPos, posMouse, segments);//进行贝塞尔平滑
            this.lastPos = posMouse;
            this.penultPos = pointList[pointList.length-2]
            for (var i = 0; i < pointList.length; i++)
            {
                this.interactionArea.graphics.drawCircle(pointList[i].x, pointList[i].y, 10, "#000000");
            }
        }else{
            this.twoPoint = true;
            this.lastPos = posMouse;
        }
    }*/
    
	/**
     * 获取形成贝塞尔平滑的点坐标数组集集合
     * @param start 起点
     * @param mid 中点
     * @param end 终点
     * @param segments 需要平滑的段数
     */
    Beizier( start: Laya.Vector2, mid:Laya.Vector2, end:Laya.Vector2, segments: number): Array<Laya.Vector2>
    {
        var posList = new Array<Laya.Vector2>();
        var d:number = 1 / segments;
        posList.push(mid);
        for (var i = 0; i < segments-1; i++)
        {
            var t: number = d * (i + 1);
            var points: Laya.Vector2 = new Laya.Vector2((1 - t)*(1 - t)*mid.x+2*t*(1 - t)*start.x+t*t*end.x, (1 - t)*(1 - t)*mid.y+2*t*(1 - t)*start.y+t*t*end.y);
            posList.push(points);
        }
        posList.push(end);
        return posList;
    }
    
    /**
     * 计算两个点之间的距离
     * @param a 第一个点的2d坐标
     * @param b 第二个点的2d坐标
     */
    calcDistance(a: Laya.Vector2, b: Laya.Vector2): number{
        return Math.sqrt(Math.pow(a.x-b.x,2)+Math.pow(a.y-b.y,2));
    }

优化方向:

目前实现是在底板图片范围内均可以绘制,没有考虑相应区域是否已经绘制过,所以后续可以朝着是否可以记录已经绘制过的区域进行剔除,不进行绘制新的图案?目前未想到相应的实现方法。另一方面未实现,玩家在刮了一定范围后让mask直接清除,完全显示底板?

TUDO:玩家已经绘制的区域进行剔除,不让进行绘制。玩家在刮了限定范围内区域后,直接显示底板,刮刮乐结束。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Laya3D是一款基于HTML5技术的3D游戏引擎,它可以运行在多个平台上,包括PC、移动设备和Web。实现战争迷雾效果需要以下步骤: 1. 创建一个地图模型,包括战场和障碍物。 2. 创建一个相机,并设置其位置和朝向,以便能够正确地观察地图。 3. 创建一个光源,可以使用点光源、方向光源或者环境光源。 4. 创建一些材质,用于给地图和障碍物上色。 5. 创建一个迷雾层,用于遮挡地图和障碍物。 6. 在场景中添加一个渲染器,用于将场景渲染到屏幕上。 7. 在每帧更新时,根据相机的位置和迷雾层的范围,计算出需要显示的部分,并将其渲染到屏幕上。 以下是一个简单的示例代码: ```javascript Laya3D.init(0, 0, true); // 创建场景和相机 var scene = Laya.stage.addChild(new Laya.Scene()); var camera = scene.addChild(new Laya.Camera(0, 0.1, 100)); camera.transform.translate(new Laya.Vector3(0, 10, -20)); camera.transform.rotate(new Laya.Vector3(-30, 0, 0), true, false); // 创建光源 var light = scene.addChild(new Laya.DirectionLight()); light.color = new Laya.Vector3(1, 1, 1); light.direction = new Laya.Vector3(0.3, -1, 0); // 创建地图模型和材质 var map = scene.addChild(new Laya.MeshSprite3D(Laya.PrimitiveMesh.createPlane(50, 50))); var mapMat = new Laya.BlinnPhongMaterial(); mapMat.albedoColor = new Laya.Vector4(0.5, 0.5, 0.5, 1); mapMat.renderMode = Laya.BlinnPhongMaterial.RENDERMODE_OPAQUE; map.meshRenderer.material = mapMat; // 创建障碍物模型和材质 var obstacle = scene.addChild(new Laya.MeshSprite3D(Laya.PrimitiveMesh.createBox(1, 2, 1))); var obstacleMat = new Laya.BlinnPhongMaterial(); obstacleMat.albedoColor = new Laya.Vector4(0, 0.5, 0, 1); obstacleMat.renderMode = Laya.BlinnPhongMaterial.RENDERMODE_OPAQUE; obstacle.meshRenderer.material = obstacleMat; obstacle.transform.translate(new Laya.Vector3(-5, 0, 0)); // 创建迷雾层和材质 var fogLayer = scene.addChild(new Laya.MeshSprite3D(Laya.PrimitiveMesh.createPlane(50, 50))); var fogMat = new Laya.UnlitMaterial(); fogMat.albedoColor = new Laya.Vector4(0, 0, 0, 1); fogMat.renderMode = Laya.UnlitMaterial.RENDERMODE_TRANSPARENT; fogMat.renderQueue = Laya.Material.RENDERQUEUE_TRANSPARENT; fogLayer.meshRenderer.material = fogMat; fogLayer.transform.translate(new Laya.Vector3(0, 10, 0)); fogLayer.transform.rotate(new Laya.Vector3(90, 0, 0), true, false); // 创建渲染器 var renderer = Laya.stage.addChild(new Laya.Renderer()); renderer.render(scene, camera); // 更新迷雾层 Laya.timer.frameLoop(1, this, function() { var range = 5; // 迷雾范围 var pos = camera.transform.position; var fogPos = fogLayer.transform.position; fogPos.x = pos.x; fogPos.z = pos.z; fogMat.tilingOffset = new Laya.Vector4(range, range, -pos.x / range, -pos.z / range); }); ``` 在这个示例中,我们创建了一个简单的地图和障碍物,并使用BlinnPhongMaterial和UnlitMaterial给它们上色。然后创建了一个迷雾层,使用UnlitMaterial和透明渲染模式来遮挡地图和障碍物。在每帧更新时,根据相机的位置和迷雾范围,更新迷雾层的位置和纹理坐标,以实现迷雾效果

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值