策划同学想在游戏内增加投显子弹数量的功能,看了下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;
}
}