Added JS engine.

This commit is contained in:
2021-09-18 00:39:00 -07:00
parent 9dd9ce7cbd
commit ef9137fabb
52 changed files with 547 additions and 35712 deletions

View File

@ -1,56 +0,0 @@
const path = require('path');
const { imageCreate, imageWrite, imageLoad, imageCopy } = require('./../../utils/image');
const fs =require('fs');
// Where to crop
const FACE_AREA = { x: 367, y: 256, width: 280, height: 280 };
// Where the images are stored
const IMAGES_ROOT = path.join(...[
'.',
'assets',
'characters',
'penny',
'sprites'
]);
// Which image directories to crop
const IMAGES_DIRECTORIES = [ 'eyebrows', 'eyes', 'mouths' ];
(async () => {
// Load the base
const base = await imageLoad(path.join(IMAGES_ROOT, 'dealer.png'));
let columnsMax = 0;
for(let row = 0; row < IMAGES_DIRECTORIES.length; row++) {
const dir = path.join(IMAGES_ROOT, IMAGES_DIRECTORIES[row]);
const scan = fs.readdirSync(dir);
columnsMax = Math.max(scan.length, columnsMax);
}
// Create the output buffer
const out = imageCreate(base.width+(columnsMax*FACE_AREA.width), base.height);
// Copy the base
imageCopy(out, base, 0, 0);
// Now begin copying the children, row is defined by the directory
for(let row = 0; row < IMAGES_DIRECTORIES.length; row++) {
const dir = path.join(IMAGES_ROOT, IMAGES_DIRECTORIES[row]);
const scan = fs.readdirSync(dir);
// Column defined by the file index
for(let col = 0; col < scan.length; col++) {
const img = await imageLoad(path.join(dir, scan[col]));
console.log('Copying', scan[col]);
imageCopy(out, img,
base.width+(col*FACE_AREA.width), FACE_AREA.height*row,
FACE_AREA
);
}
}
await imageWrite(out, path.join(IMAGES_ROOT, 'sheet.png'));
})().catch(console.error);

View File

@ -1,56 +0,0 @@
const fs = require('fs');
const path = require('path');
// Constants
const WORLD_LOAD_TOKEN = ";";
const TILE_FLAG_DYNAMIC = 1;
// Method.
const saveWorld = (world) => {
const pathWorld = path.join(__dirname, '..', '..', 'assets', world.name);
if(!fs.existsSync(pathWorld)) fs.mkdirSync(pathWorld);
// World string buffer (file data).
let strBuffer = "";
// Header
strBuffer += [
world.version,
world.tileset,
""// Seal
].join(WORLD_LOAD_TOKEN);
// Tilemap Definition
let buffer = [];
for(let i = 0; i < world.tilemap.length; i++) {
let tileDef = world.tilemap[i];
buffer.push(tileDef.verticeCount+'');
buffer.push(tileDef.indiceCount+'');
buffer.push(tileDef.flags+'');
}
strBuffer += buffer.join(WORLD_LOAD_TOKEN);
fs.writeFileSync(path.join(pathWorld, 'world.txt'), strBuffer);
}
// Worlds.
const TILEMAP_WIDTH = 8;
const TILEMAP_HEIGHT = 298;
let world = {
version: '1.00',
tileset: 'tileset.png',
name: 'testworld',
tilemap: [ ]
};
for(let i = 0; i < TILEMAP_WIDTH * TILEMAP_HEIGHT; i++) {
world.tilemap[i] = {
indiceCount: 6,
verticeCount: 4,
flags: 0
};
}
console.log('bruh', world);
saveWorld(world);

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include <dawn/dawn.h>
#include "../primitive.h"
#define POKER_CHIP_NAME "Poker Chip"
#define POKER_CHIP_VERTICE_COUNT 5249
#define POKER_CHIP_INDICE_COUNT 29874
#define POKER_CHIP_TRIANGLE_COUNT 9958
/**
* Generated Model Poker Chip
* Generated at Sun, 30 May 2021 01:23:51 GMT
* @returns Poker Chip as a primitive.
*/
primitive_t * pokerChipCreate();

View File

@ -1,143 +0,0 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
const fs = require('fs');
const path = require('path');
const MODEL_NAME = 'Poker Chip';
const FLIP_TEXTURE_Y = true;
let rawVertices = [];
let faces = [];
let coordinates = [];
const filePath = path.join(__dirname, '..', '..', 'assets', 'models', 'poker table_del', 'poker_table.obj');
const data = fs.readFileSync(filePath, 'utf-8');
const scale = 0.1;
data.split('\n').forEach(line => {
const bits = line.trim().split(' ');
if(!bits.length || bits.every(n => !n || !bits.length)) return;
const lineType = bits.shift();
if(lineType === 'v') {
const [ x, y, z ] = bits.map(n => {
const val = parseFloat(n) * scale;
return val;
});
rawVertices.push({ x, y, z });
} else if(lineType === 'vt') {
let [ u, v ] = bits.map(n => parseFloat(n));
if(FLIP_TEXTURE_Y) v = 1 - v;
coordinates.push({ u, v });
} else if(lineType === 'f') {
faces.push(bits.map(n => {
const [ vertice, coordinate ] = n.split('/').map(n => parseInt(n));
return { vertice, coordinate };
}));
}
});
const verticeCompare = (vl, vr) => (
vl.x === vr.x &&
vl.y === vr.y &&
vl.z === vr.z &&
vl.u === vr.u &&
vl.v === vr.v
);
const indices = [];
const vertices = [];
faces.forEach(face => {
face.forEach(faceIndice => {
const rawVert = rawVertices[faceIndice.vertice-1];
const rawCoord = coordinates[faceIndice.coordinate-1];
const vertice = { ...rawVert, ...rawCoord };
const indice = vertices.findIndex(vert => {
return verticeCompare(vert, vertice);
});
if(indice === -1) {
indices.push(vertices.length);
vertices.push(vertice);
} else {
indices.push(indice);
}
})
})
const MODEL_NAME_CAPS = MODEL_NAME.replace(/\s/g, '_').toUpperCase();
const MODEL_NAME_CAMEL = [
MODEL_NAME[0].toLowerCase(),
MODEL_NAME.split(' ').join('').substr(1)
].join('')
// const fn = MODEL_NAME.toLowerCase().split(' ').join('');
const fn = 'model';
const license = `/**
* Copyright (c) ${new Date().getFullYear()} Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
`;
// Write header file
const header = `${license}
#pragma once
#include <dawn/dawn.h>
#include "../primitive.h"
#define ${MODEL_NAME_CAPS}_NAME "${MODEL_NAME}"
#define ${MODEL_NAME_CAPS}_VERTICE_COUNT ${vertices.length}
#define ${MODEL_NAME_CAPS}_INDICE_COUNT ${indices.length}
#define ${MODEL_NAME_CAPS}_TRIANGLE_COUNT ${indices.length/3}
/**
* Generated Model ${MODEL_NAME}
* Generated at ${new Date().toUTCString()}
* @returns ${MODEL_NAME} as a primitive.
*/
void ${MODEL_NAME_CAMEL}Init(primitive_t *primitive);
`;
// Write Source file
const strVertices = vertices.map((v,i) => {
return `{ .x = ${v.x}, .y = ${v.y}, .z = ${v.z}, .u = ${v.u}, .v = ${v.v} }`;
}).join(',\n ');
const strIndices = indices.map(i => {
return `${i}`;
}).join(',\n ');
const source = `${license}
#include "${fn}.h"
primitive_t * ${MODEL_NAME_CAMEL}Create(primitive_t *primitive) {
vertice_t vertices[${MODEL_NAME_CAPS}_VERTICE_COUNT] = {
${strVertices}
};
indice_t indices[${MODEL_NAME_CAPS}_INDICE_COUNT] = {
${strIndices}
};
primitiveInit(
${MODEL_NAME_CAPS}_VERTICE_COUNT,
${MODEL_NAME_CAPS}_INDICE_COUNT
);
primitiveBufferVertices(primitive, 0, ${MODEL_NAME_CAPS}_VERTICE_COUNT, vertices);
primitiveBufferIndices(primitive, 0, ${MODEL_NAME_CAPS}_INDICE_COUNT, indices);
return primitive;
}
`;
fs.writeFileSync(path.join(__dirname, fn+'.h'), header);
fs.writeFileSync(path.join(__dirname, fn+'.c'), source);

View File

@ -1,96 +0,0 @@
const fs = require("fs");
const path = require('path');
const { PNG } = require("pngjs");
// Constants
const IMAGES_ROOT = path.join(...[
'.',
'assets',
'characters',
'penny',
'Sample sets',
'Mouth'
]);
const FILE_OUT = path.join(...[
'.',
'assets',
'characters',
'penny',
'textures',
'mouth.png'
])
// Code
const imageLoad = (image) => new Promise(resolve => {
fs.createReadStream(image)
.pipe(new PNG({ filterType: 4 }))
.on("parsed", function () {
// Normalize
const pixels = [];
for(let y = 0; y < this.height; y++) {
for(let x = 0; x < this.width; x++) {
const idx = (this.width * y + x) << 2;
const r = this.data[idx];
const g = this.data[idx + 1];
const b = this.data[idx + 2];
const a = this.data[idx + 3];
pixels.push({ r, g, b, a });
}
}
resolve({ pixels, width: this.width, height: this.height });
})
;
});
const imageWrite = (image, file) => new Promise(resolve => {
const png = new PNG({ width: image.width, height: image.height });
png.width = image.width;
png.height = image.height;
for(let y = 0; y < image.height; y++) {
for(let x = 0; x < image.width; x++) {
const i = (image.width * y + x);
const idx = i << 2;
const pixel = image.pixels[i];
png.data[idx] = pixel.r;
png.data[idx + 1] = pixel.g;
png.data[idx + 2] = pixel.b;
png.data[idx + 3] = pixel.a;
}
}
png.pack().pipe(fs.createWriteStream(file))
.on('close', () => resolve(true))
;
});
(async () => {
const files = fs.readdirSync(IMAGES_ROOT);
let stitched = null;
let k = 0;
for(let i = 0; i < files.length; i++) {
const filePath = path.join(IMAGES_ROOT, files[i]);
const image = await imageLoad(filePath);
if(!stitched) {
stitched = {
width: image.width,
height: image.height * files.length,
pixels: Array(image.width*image.height*files.length)
}
}
for(let j = 0; j < image.pixels.length; j++) {
stitched.pixels[j + (i * image.width * image.height)] = { ...image.pixels[j] };
}
};
console.log('Writing');
await imageWrite(stitched, FILE_OUT);
})().catch(console.error);

View File

@ -1,103 +0,0 @@
const { PNG } = require("pngjs");
const path = require('path');
const fs = require('fs');
/**
* Loads an image into memory.
* @param image Image to load
* @returns A promise that resolves to the loaded image.
*/
const imageLoad = (image) => new Promise(resolve => {
fs.createReadStream(image)
.pipe(new PNG({ filterType: 4 }))
.on("parsed", function () {
// Normalize
const pixels = [];
for(let y = 0; y < this.height; y++) {
for(let x = 0; x < this.width; x++) {
const idx = (this.width * y + x) << 2;
const r = this.data[idx];
const g = this.data[idx + 1];
const b = this.data[idx + 2];
const a = this.data[idx + 3];
pixels.push({ r, g, b, a });
}
}
resolve({ pixels, width: this.width, height: this.height });
})
;
});
/**
* Writes an image to an output file.
* @param image Image to write.
* @param file File to write to.
* @returns A promise that, when resolved, has saved the image.
*/
const imageWrite = (image, file) => new Promise(resolve => {
const png = new PNG({ width: image.width, height: image.height });
png.width = image.width;
png.height = image.height;
for(let y = 0; y < image.height; y++) {
for(let x = 0; x < image.width; x++) {
const i = (image.width * y + x);
const idx = i << 2;
const pixel = image.pixels[i];
png.data[idx] = pixel.r;
png.data[idx + 1] = pixel.g;
png.data[idx + 2] = pixel.b;
png.data[idx + 3] = pixel.a;
}
}
png.pack().pipe(fs.createWriteStream(file))
.on('close', () => resolve(true))
;
});
/**
* Creates a blank image
* @param width Width of the image.
* @param height Height of the image.
* @param fill Optional pixel to fill with, defaults to 0,0,0,0
* @returns The newly created image.
*/
const imageCreate = (width, height, pixel) => {
if(!pixel || !pixel.r) pixel = { r:0, g:0, b:0, a:0 };
const pixels = [];
for(let i = 0; i < width * height; i++) pixels.push({ ...pixel });
return { pixels, width, height };
}
/**
* Copies an area of a source image into a target image.
* @param target Target image to copy into.
* @param source Source image to copy from.
* @param tx Target X position to copy into
* @param ty Target Y position to copy into
* @param sub Optional source area to use, defined as { x, y, width, height }.
*/
const imageCopy = (target, source, tx, ty, sub) => {
if(!sub) sub = { x: 0, y: 0, width: source.width, height: source.height };
for(let x = sub.x; x < sub.x+sub.width; x++) {
for(let y = sub.y; y < sub.y+sub.height; y++) {
let absX = x - sub.x + tx;
let absY = y - sub.y + ty;
if(absX > target.width || absY > target.height) continue;
let ti = absY * target.width + absX;
let si = y * source.width + x;
target.pixels[ti] = { ...source.pixels[si] };
}
}
}
module.exports = {
imageWrite,
imageCreate,
imageLoad,
imageCopy
}