Laya中贴图实时合并

策划同学想在游戏内增加投显子弹数量的功能,看了下Laya中并没有提供3d文本相关的组件,所以先去百度下看了下并没有相关的轮子可以直接使用,只能自己写下了

首先分析下需求 子弹数量投显 只需要显示0-9的数字就可以了
那么最简单的一种方式是:
让建模同学每一位搞一个面片 然后把对应的数字贴图贴上去 有几位搞几个面片
显然这种方式是最差解。。。

既然是造轮子,当然不能就这样结束了!

所以,决定用一张贴图一面片来实现这个功能
那么问题点就在于:怎么把0-9这几个数字在运行时实时的将需要的散图合并成一张新的贴图 ,然后放到材质中去渲染
Laya中有可以获取到加载后的图片的像素数据的接口 即 Texture.getTexturePixels
关键代码:

            var ctx = new ILaya.Context();
            ctx.size(width, height);
            ctx.asBitmap = true;
            var uv = null;
            if (x != 0 || y != 0 || width != tex2dw || height != tex2dh) {
                uv = this._uv.slice();
                var stu = uv[0];
                var stv = uv[1];
                var uvw = uv[2] - stu;
                var uvh = uv[7] - stv;
                var uk = uvw / texw;
                var vk = uvh / texh;
                uv = [stu + rePosX * uk, stv + rePosY * vk,
                    stu + (rePosX + draww) * uk, stv + rePosY * vk,
                    stu + (rePosX + draww) * uk, stv + (rePosY + drawh) * vk,
                    stu + rePosX * uk, stv + (rePosY + drawh) * vk];
            }
            ctx._drawTextureM(this, marginL, marginT, draww, drawh, null, 1.0, uv);
            ctx._targets.start();
            ctx.flush();
            ctx._targets.end();
            ctx._targets.restore();
            var dt = ctx._targets.getData(0, 0, width, height);
            ctx.destroy();
            ret = new Uint8Array(width * height * 4);
            st = 0;
            dst = (height - 1) * wstride;
            for (i = height - 1; i >= 0; i--) {
                ret.set(dt.slice(dst, dst + wstride), st);
                st += wstride;
                dst -= wstride;
            }
            return ret;

这段操作就是将图片绘制到上下文中,并拿出像素数据,这时候拿到的数据如果直接使用的话会发现图片是上下颠倒的,需要对像素数据进行重新排列,最后将重排后的数据ret,return出去

理解后就可以对贴图进行合并了

以下为demo测试代码可以稍加修改直接使用

export default class UnlitNumberMaterial extends Laya.UnlitMaterial {
    /**数字资源地址 */
    private _numResTitle: string = "";
    /**加载标志 */
    private _loadedTag: boolean = false;
    /**要渲染的数字 */
    private _renderStr: string = "";
    /**显示几个数字  也就是有几位*/
    private _numberCount: number = 4;
    /**贴图宽度 */
    private _textureW: number = 64;
    /**贴图高度 */
    private _textureH: number = 64;

    constructor() {
        super();
        this.renderMode = Laya.UnlitMaterial.RENDERMODE_TRANSPARENT;
    }

    set fontType(type: string) {
        this._numResTitle = `${type}/num_`;
        Laya.loader.load(`res/atlas/${type}.atlas`, Laya.Handler.create(this, this.loadResComplete));
    }
    private loadResComplete() {
        this._loadedTag = true;
        this.refreshTexture();
    }

    set renderNumber(str: string) {
        this._renderStr = str;
        if (this._loadedTag) {
            this.refreshTexture();
        }
    }

    private refreshTexture() {
        let texW = this._numberCount * this._textureW, texH = this._textureH;
        let texture2d = new Laya.Texture2D(texW, texH, Laya.TextureFormat.R8G8B8A8, false, false);

        let renderTextures = this.getRenderTextures();

        let len = renderTextures.length;
        let totalWidth = len * this._textureW;
        let startX = (texW - totalWidth) / 2;

        for (let i = 0; i < renderTextures.length; i++) {
            let tex = renderTextures[i];
            texture2d.setSubPixels(startX + i * this._textureW, 0, this._textureW, this._textureH, tex.getTexturePixels(0, 0, this._textureW, this._textureH));
        }

        this.albedoTexture = texture2d;
    }

    private getRenderTextures() {
        let renderTextures = [];
        for (let index = 0; index < this._renderStr.length; index++) {
            let numTexture = Laya.loader.getRes(`${this._numResTitle}${this._renderStr[index]}.png`);
            if (numTexture) {
                renderTextures.push(numTexture);
            }
        }
        return renderTextures;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值