115 lines
2.8 KiB
TypeScript
115 lines
2.8 KiB
TypeScript
const { ccclass, property } = cc._decorator;
|
|
|
|
const randseed = new Array(4); // Xorshift: [x, y, z, w] 32 bit values
|
|
|
|
function seedrand(seed) {
|
|
for (var i = 0; i < randseed.length; i++) {
|
|
randseed[i] = 0;
|
|
}
|
|
for (var i = 0; i < seed.length; i++) {
|
|
randseed[i % 4] =
|
|
(randseed[i % 4] << 5) - randseed[i % 4] + seed.charCodeAt(i);
|
|
}
|
|
}
|
|
function rand() {
|
|
// based on Java's String.hashCode(), expanded to 4 32bit values
|
|
const t = randseed[0] ^ (randseed[0] << 11);
|
|
|
|
randseed[0] = randseed[1];
|
|
randseed[1] = randseed[2];
|
|
randseed[2] = randseed[3];
|
|
randseed[3] = randseed[3] ^ (randseed[3] >> 19) ^ t ^ (t >> 8);
|
|
|
|
return (randseed[3] >>> 0) / ((1 << 31) >>> 0);
|
|
}
|
|
|
|
function createImageData(size) {
|
|
const width = size; // Only support square icons for now
|
|
const height = size;
|
|
|
|
const dataWidth = Math.ceil(width / 2);
|
|
const mirrorWidth = width - dataWidth;
|
|
|
|
const data = [];
|
|
for (let y = 0; y < height; y++) {
|
|
let row = [];
|
|
for (let x = 0; x < dataWidth; x++) {
|
|
// this makes foreground and background color to have a 43% (1/2.3) probability
|
|
// spot color has 13% chance
|
|
row[x] = Math.floor(rand() * 2.3);
|
|
}
|
|
const r = row.slice(0, mirrorWidth);
|
|
r.reverse();
|
|
row = row.concat(r);
|
|
|
|
for (let i = 0; i < row.length; i++) {
|
|
data.push(row[i]);
|
|
}
|
|
}
|
|
|
|
return data;
|
|
}
|
|
function createColor() {
|
|
const r = Math.floor(rand() * 255);
|
|
const g = Math.floor(rand() * 255);
|
|
const b = Math.floor(rand() * 255);
|
|
|
|
return new cc.Color(r, g, b, 255);
|
|
}
|
|
|
|
function buildOpts(opts) {
|
|
if (!opts.seed) {
|
|
throw new Error("No seed provided");
|
|
}
|
|
|
|
seedrand(opts.seed);
|
|
|
|
return Object.assign(
|
|
{
|
|
size: 8,
|
|
scale: 2,
|
|
color: createColor(),
|
|
bgcolor: createColor(),
|
|
spotcolor: createColor(),
|
|
},
|
|
opts
|
|
);
|
|
}
|
|
|
|
@ccclass
|
|
export default class HashIcon extends cc.Component {
|
|
@property(cc.Graphics)
|
|
ctx: cc.Graphics = null;
|
|
// onLoad () {}
|
|
|
|
start() {}
|
|
|
|
// update (dt) {}
|
|
|
|
init(address: string) {
|
|
const size = 8;
|
|
const scale = this.node.width / size;
|
|
const opts = buildOpts({ seed: address.toLowerCase(), size, scale });
|
|
|
|
const imageData = createImageData(opts.size);
|
|
const width = Math.sqrt(imageData.length);
|
|
this.ctx.clear()
|
|
for (let i = 0; i < imageData.length; i++) {
|
|
const row = Math.floor(i / width);
|
|
const col = i % width;
|
|
// if data is 0, leave the background
|
|
if (imageData[i]) {
|
|
// if data is 2, choose spot color, if 1 choose foreground
|
|
const pngColor = imageData[i] == 1 ? opts.color : opts.spotcolor;
|
|
this.ctx.fillColor = pngColor
|
|
this.ctx.fillRect(
|
|
col * opts.scale,
|
|
row * opts.scale,
|
|
opts.scale,
|
|
opts.scale
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|