shader hotreload; better circle shader; add nogame for setup help; fix io.mod; add joystick input; fix entity hotreload; implement array length in C; add default game.size
This commit is contained in:
parent
a28230a647
commit
515eb65b22
|
@ -976,11 +976,7 @@ swizz.forEach(function(x) {
|
|||
make_swizz();
|
||||
|
||||
Object.defineProperty(Array.prototype, 'normalized', {
|
||||
value: function() {
|
||||
var c = this.slice();
|
||||
var len = Vector.length(c);
|
||||
return c.map(v => v/len);
|
||||
}
|
||||
value: function() { return vector.norm(this); }
|
||||
});
|
||||
|
||||
Object.defineProperty(Array.prototype, 'newfirst', {
|
||||
|
|
|
@ -72,8 +72,8 @@ var entity = {
|
|||
|
||||
delay(fn, seconds) {
|
||||
var timers = this.timers;
|
||||
var stop = function() {
|
||||
delete timers[guid];
|
||||
var stop = function() {
|
||||
timers.remove(stop);
|
||||
execute = undefined;
|
||||
stop = undefined;
|
||||
rm?.();
|
||||
|
@ -98,8 +98,7 @@ var entity = {
|
|||
}
|
||||
|
||||
var rm = Register.update.register(update);
|
||||
var guid = prosperon.guid();
|
||||
timers[guid] = (stop);
|
||||
timers.push(stop);
|
||||
return stop;
|
||||
},
|
||||
|
||||
|
@ -151,7 +150,7 @@ var entity = {
|
|||
ent.guid = prosperon.guid();
|
||||
ent.components = {};
|
||||
ent.objects = {};
|
||||
ent.timers = {};
|
||||
ent.timers = [];
|
||||
ent.ur = {};
|
||||
});
|
||||
/*
|
||||
|
|
|
@ -213,10 +213,26 @@ input.print_pawn_kbm = function(pawn) {
|
|||
return str;
|
||||
};
|
||||
|
||||
var joysticks = {};
|
||||
|
||||
joysticks["wasd"] = {
|
||||
uy: "w",
|
||||
dy: "s",
|
||||
ux: "d",
|
||||
dx: "a"
|
||||
};
|
||||
|
||||
input.procdown = function()
|
||||
{
|
||||
for (var k in downkeys)
|
||||
player[0].raw_input(keyname_extd(k), "down");
|
||||
|
||||
for (var i in joysticks) {
|
||||
var joy = joysticks[i];
|
||||
var x = joy.ux - joy.dx;
|
||||
var y = joy.uy - joy.dy;
|
||||
player[0].joy_input(i, joysticks[i]);
|
||||
}
|
||||
}
|
||||
|
||||
input.print_md_kbm = function(pawn) {
|
||||
|
@ -301,6 +317,23 @@ var Player = {
|
|||
};
|
||||
},
|
||||
|
||||
joy_input(name, joystick) {
|
||||
for (var pawn of this.pawns.reversed()) {
|
||||
if (!pawn.inputs) return;
|
||||
if (!pawn.inputs.joystick) return;
|
||||
if (!pawn.inputs.joystick[name]) return;
|
||||
|
||||
var x = 0;
|
||||
if (input.keyboard.down(joystick.ux)) x++;
|
||||
if (input.keyboard.down(joystick.dx)) x--;
|
||||
var y = 0;
|
||||
if (input.keyboard.down(joystick.uy)) y++;
|
||||
if (input.keyboard.down(joystick.dy)) y--;
|
||||
|
||||
pawn.inputs.joystick[name](x,y);
|
||||
}
|
||||
},
|
||||
|
||||
raw_input(cmd, state, ...args) {
|
||||
for (var pawn of this.pawns.reversed()) {
|
||||
if (!pawn.inputs) {
|
||||
|
|
4
scripts/nogame.js
Normal file
4
scripts/nogame.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
this.hud = function()
|
||||
{
|
||||
mum.label("No game yet! Make game.js to get started!", {pos:game.size.scale(0.5), anchor:[0.5,0.5]});
|
||||
}
|
|
@ -154,49 +154,35 @@ render.set_camera = function(cam)
|
|||
}
|
||||
|
||||
var shader_cache = {};
|
||||
var shader_times = {};
|
||||
|
||||
function strip_shader_inputs(shader)
|
||||
{
|
||||
for (var a of shader.vs.inputs)
|
||||
a.name = a.name.slice(2);
|
||||
}
|
||||
|
||||
function make_shader(shader)
|
||||
|
||||
render.hotreload = function()
|
||||
{
|
||||
if (shader_cache[shader]) return shader_cache[shader];
|
||||
|
||||
var file = shader;
|
||||
shader = io.slurp(shader);
|
||||
if (!shader) {
|
||||
console.info(`not found! slurping shaders/${file}`);
|
||||
shader = io.slurp(`shaders/${file}`);
|
||||
}
|
||||
var writejson = `.prosperon/${file.name()}.shader.json`;
|
||||
|
||||
profile.cache("shader", file);
|
||||
|
||||
breakme: if (io.exists(writejson)) {
|
||||
var data = json.decode(io.slurp(writejson));
|
||||
var filemod = io.mod(writejson);
|
||||
if (!data.files) break breakme;
|
||||
for (var i of data.files) {
|
||||
if (io.mod(i) > filemod) {
|
||||
break breakme;
|
||||
}
|
||||
}
|
||||
|
||||
profile.endcache(" [cached]");
|
||||
var shaderobj = json.decode(io.slurp(writejson));
|
||||
var obj = shaderobj[os.sys()];
|
||||
strip_shader_inputs(obj);
|
||||
for (var i in shader_times) {
|
||||
if (io.mod(i) <= shader_times[i]) continue;
|
||||
say(`HOT RELOADING SHADER ${i}`);
|
||||
shader_times[i] = io.mod(i);
|
||||
var obj = create_shader_obj(i);
|
||||
obj = obj[os.sys()];
|
||||
obj.pipe = render.pipeline(obj);
|
||||
shader_cache[shader] = obj;
|
||||
return obj;
|
||||
var old = shader_cache[i];
|
||||
Object.assign(shader_cache[i], obj);
|
||||
cur.bind = undefined;
|
||||
cur.mesh = undefined;
|
||||
}
|
||||
|
||||
var out = `.prosperon/${file.name()}.shader`;
|
||||
|
||||
}
|
||||
|
||||
function create_shader_obj(file)
|
||||
{
|
||||
var files = [file];
|
||||
var out = ".prosperon/tmp.shader";
|
||||
var shader = io.slurp(file);
|
||||
|
||||
var incs = shader.match(/#include <.*>/g);
|
||||
if (incs)
|
||||
|
@ -223,7 +209,6 @@ function make_shader(shader)
|
|||
|
||||
shader = shader.replace(/uniform\s+(\w+)\s+(\w+);/g, "uniform _$2 { $1 $2; };");
|
||||
shader = shader.replace(/(texture2D|sampler) /g, "uniform $1 ");
|
||||
// shader = shader.replace(/uniform texture2D ?(.*);/g, "uniform _$1_size { vec2 $1_size; };\nuniform texture2D $1;");
|
||||
|
||||
io.slurpwrite(out, shader);
|
||||
|
||||
|
@ -253,11 +238,11 @@ function make_shader(shader)
|
|||
}
|
||||
|
||||
add_code(obj.vs);
|
||||
if (!obj.fs)
|
||||
if (obj.vs.fs) {
|
||||
if (!obj.fs && obj.vs.fs) {
|
||||
obj.fs = obj.vs.fs;
|
||||
delete obj.vs.fs;
|
||||
}
|
||||
}
|
||||
|
||||
add_code(obj.fs);
|
||||
|
||||
obj.blend = blend;
|
||||
|
@ -296,19 +281,58 @@ function make_shader(shader)
|
|||
|
||||
obj.name = file;
|
||||
|
||||
strip_shader_inputs(obj);
|
||||
|
||||
compiled[platform] = obj;
|
||||
}
|
||||
|
||||
compiled.files = files;
|
||||
compiled.source = shader;
|
||||
|
||||
return compiled;
|
||||
}
|
||||
|
||||
function make_shader(shader)
|
||||
{
|
||||
if (shader_cache[shader]) return shader_cache[shader];
|
||||
|
||||
var file = shader;
|
||||
shader = io.slurp(file);
|
||||
if (!shader) {
|
||||
console.info(`not found! slurping shaders/${file}`);
|
||||
shader = io.slurp(`shaders/${file}`);
|
||||
}
|
||||
var writejson = `.prosperon/${file.name()}.shader.json`;
|
||||
|
||||
profile.cache("shader", file);
|
||||
|
||||
breakme: if (io.exists(writejson)) {
|
||||
var data = json.decode(io.slurp(writejson));
|
||||
var filemod = io.mod(writejson);
|
||||
if (!data.files) break breakme;
|
||||
for (var i of data.files) {
|
||||
if (io.mod(i) > filemod) {
|
||||
break breakme;
|
||||
}
|
||||
}
|
||||
|
||||
profile.endcache(" [cached]");
|
||||
var shaderobj = json.decode(io.slurp(writejson));
|
||||
var obj = shaderobj[os.sys()];
|
||||
obj.pipe = render.pipeline(obj);
|
||||
shader_cache[file] = obj;
|
||||
shader_times[file] = io.mod(file);
|
||||
return obj;
|
||||
}
|
||||
|
||||
var compiled = create_shader_obj(file);
|
||||
io.slurpwrite(writejson, json.encode(compiled));
|
||||
profile.endcache();
|
||||
|
||||
var obj = compiled[os.sys()];
|
||||
strip_shader_inputs(obj);
|
||||
obj.pipe = render.pipeline(obj);
|
||||
|
||||
shader_cache[shader] = obj;
|
||||
shader_cache[file] = obj;
|
||||
shader_times[file] = io.mod(file);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -372,7 +396,7 @@ function sg_bind(mesh, ssbo)
|
|||
if (cur.shader.vs.inputs)
|
||||
for (var a of cur.shader.vs.inputs) {
|
||||
if (!(a.name in mesh)) {
|
||||
console.error(`cannot draw shader ${cur.shader.name}; there is no attrib ${a.name} in the given mesh.`);
|
||||
console.error(`cannot draw shader ${cur.shader.name}; there is no attrib ${a.name} in the given mesh. ${json.encode(mesh)}`);
|
||||
return undefined;
|
||||
} else
|
||||
bind.attrib.push(mesh[a.name]);
|
||||
|
@ -540,17 +564,25 @@ render.sprites = function render_sprites(gridsize = 1)
|
|||
profile.endframe();
|
||||
}
|
||||
|
||||
render.circle = function render_circle(pos, radius, color) {
|
||||
render.circle = function render_circle(pos, radius, color, inner_radius = 1) {
|
||||
flush();
|
||||
|
||||
if (inner_radius >= 1)
|
||||
inner_radius = inner_radius/radius;
|
||||
else if (inner_radius < 0)
|
||||
inner_radius = 1.0;
|
||||
|
||||
var mat = {
|
||||
radius: radius,
|
||||
inner_r: inner_radius,
|
||||
coord: pos,
|
||||
shade: color
|
||||
shade: color,
|
||||
};
|
||||
render.use_shader(circleshader);
|
||||
render.use_mat(mat);
|
||||
render.draw(shape.quad);
|
||||
}
|
||||
render.circle.doc = "Draw a circle at pos, with a given radius and color. If inner_radius is between 0 and 1, it acts as a percentage of radius. If it is above 1, is acts as a unit (usually a pixel).";
|
||||
|
||||
render.poly = function render_poly(points, color, transform) {
|
||||
var buffer = render.poly_prim(points);
|
||||
|
@ -799,7 +831,6 @@ render.set_font = function(path, size) {
|
|||
}
|
||||
|
||||
render.doc = "Draw shapes in screen space.";
|
||||
//render.circle.doc = "Draw a circle at pos, with a given radius and color.";
|
||||
render.cross.doc = "Draw a cross centered at pos, with arm length size.";
|
||||
render.arrow.doc = "Draw an arrow from start to end, with wings of length wingspan at angle wingangle.";
|
||||
render.rectangle.doc = "Draw a rectangle, with its corners at lowerleft and upperright.";
|
||||
|
@ -972,13 +1003,17 @@ prosperon.process = function process() {
|
|||
var dt = profile.secs(profile.now()) - frame_t;
|
||||
frame_t = profile.secs(profile.now());
|
||||
|
||||
profile.frame("hotreload");
|
||||
actor.hotreload();
|
||||
render.hotreload();
|
||||
profile.endframe();
|
||||
|
||||
/* debugging: check for gc */
|
||||
profile.print_gc();
|
||||
|
||||
var cycles = os.check_cycles();
|
||||
if (cycles) say(cycles);
|
||||
|
||||
|
||||
profile.frame("app update");
|
||||
prosperon.appupdate(dt);
|
||||
profile.endframe();
|
||||
|
|
|
@ -251,12 +251,18 @@ Cmdline.register_order("play", function(argv) {
|
|||
|
||||
var project = json.decode(io.slurp(projectfile));
|
||||
game.title = project.title;
|
||||
game.size = [1280,720];
|
||||
window.size = game.size;
|
||||
global.mixin("config.js");
|
||||
if (project.title) window.title = project.title;
|
||||
|
||||
game.engine_start(function() {
|
||||
render.set_font("fonts/c64.ttf", 8);
|
||||
global.app = actor.spawn("game.js");
|
||||
if (io.exists("game.js"))
|
||||
global.app = actor.spawn("game.js");
|
||||
else
|
||||
global.app = actor.spawn("scripts/nogame.js");
|
||||
|
||||
if (project.icon) window.set_icon(game.texture(project.icon));
|
||||
game.camera = world.spawn("scripts/camera2d");
|
||||
});
|
||||
|
|
|
@ -27,17 +27,19 @@ void main() {
|
|||
in vec2 coords;
|
||||
in float rad;
|
||||
uniform vec4 shade;
|
||||
uniform float inner_r;
|
||||
out vec4 color;
|
||||
void main() {
|
||||
float px = 1/rad;
|
||||
float blur = 1.0+px;
|
||||
float R = 1;
|
||||
float R2 = 0.90;
|
||||
float dist = sqrt(dot(coords,coords));
|
||||
float sm = 1 - smoothstep(R-px,R,dist);
|
||||
float sm2 = smoothstep(R2-px,R2,dist);
|
||||
float R2 = 1-inner_r;
|
||||
float dist = distance(vec2(0,0),coords);
|
||||
float sm = 1 - smoothstep(R-px,R*blur,dist);
|
||||
float sm2 = smoothstep(R2-px,R2*blur,dist);
|
||||
|
||||
float alpha = sm*sm2;
|
||||
color = vec4(shade.xyz, alpha*alpha);
|
||||
color = vec4(shade.xyz, alpha*shade.a);
|
||||
}
|
||||
@end
|
||||
|
||||
|
|
|
@ -157,6 +157,7 @@ void js_setprop_num(JSValue obj, uint32_t i, JSValue v) { JS_SetPropertyUint32(j
|
|||
|
||||
JSValue js_getpropidx(JSValue v, uint32_t i)
|
||||
{
|
||||
if (!JS_IsArray(js, v)) return JS_UNDEFINED;
|
||||
JSValue p = JS_GetPropertyUint32(js, v, i);
|
||||
JS_FreeValue(js,p);
|
||||
return p;
|
||||
|
@ -401,6 +402,13 @@ HMM_Vec3 js2vec3(JSValue v)
|
|||
return v3;
|
||||
}
|
||||
|
||||
HMM_Vec3 js2vec3f(JSValue v)
|
||||
{
|
||||
HMM_Vec3 vec;
|
||||
vec.x = vec.y = vec.z = js2number(v);
|
||||
return vec;
|
||||
}
|
||||
|
||||
JSValue vec32js(HMM_Vec3 v)
|
||||
{
|
||||
JSValue array = JS_NewArray(js);
|
||||
|
@ -410,6 +418,8 @@ JSValue vec32js(HMM_Vec3 v)
|
|||
return array;
|
||||
}
|
||||
|
||||
JSValue vec3f2js(HMM_Vec3 v) { return vec32js(v); }
|
||||
|
||||
JSValue quat2js(HMM_Quat q)
|
||||
{
|
||||
JSValue arr = JS_NewArray(js);
|
||||
|
@ -428,6 +438,22 @@ HMM_Vec4 js2vec4(JSValue v)
|
|||
return v4;
|
||||
}
|
||||
|
||||
double arr_vec_length(JSValue v)
|
||||
{
|
||||
int len = js_arrlen(v);
|
||||
switch(len) {
|
||||
case 2: return HMM_LenV2(js2vec2(v));
|
||||
case 3: return HMM_LenV3(js2vec3(v));
|
||||
case 4: return HMM_LenV4(js2vec4(v));
|
||||
}
|
||||
|
||||
double sum = 0;
|
||||
for (int i = 0; i < len; i++)
|
||||
sum += pow(js2number(js_getpropidx(v, i)), 2);
|
||||
|
||||
return sqrt(sum);
|
||||
}
|
||||
|
||||
HMM_Quat js2quat(JSValue v)
|
||||
{
|
||||
return js2vec4(v).quat;
|
||||
|
@ -1242,7 +1268,14 @@ JSC_CCALL(vector_norm,
|
|||
case 3: return vec32js(HMM_NormV3(js2vec3(argv[0])));
|
||||
case 4: return vec42js(HMM_NormV4(js2vec4(argv[0])));
|
||||
}
|
||||
return argv[0];
|
||||
|
||||
double length = arr_vec_length(argv[0]);
|
||||
JSValue newarr = JS_NewArray(js);
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
js_setprop_num(newarr, i, number2js(js2number(js_getpropidx(argv[0],i))/length));
|
||||
|
||||
return newarr;
|
||||
)
|
||||
|
||||
JSC_CCALL(vector_angle_between,
|
||||
|
@ -1318,18 +1351,7 @@ JSC_CCALL(vector_angledist,
|
|||
)
|
||||
|
||||
JSC_CCALL(vector_length,
|
||||
int len = js_arrlen(argv[0]);
|
||||
switch(len) {
|
||||
case 2: return number2js(HMM_LenV2(js2vec2(argv[0])));
|
||||
case 3: return number2js(HMM_LenV3(js2vec3(argv[0])));
|
||||
case 4: return number2js(HMM_LenV4(js2vec4(argv[0])));
|
||||
}
|
||||
|
||||
double sum = 0;
|
||||
for (int i = 0; i < len; i++)
|
||||
sum += pow(js2number(js_getpropidx(argv[0], i)), 2);
|
||||
|
||||
return number2js(sqrt(sum));
|
||||
return number2js(arr_vec_length(argv[0]));
|
||||
)
|
||||
|
||||
double r2()
|
||||
|
@ -1853,7 +1875,7 @@ static const JSCFunctionListEntry js_physics_funcs[] = {
|
|||
};
|
||||
|
||||
JSC_GETSET(transform, pos, vec3)
|
||||
JSC_GETSET(transform, scale, vec3)
|
||||
JSC_GETSET(transform, scale, vec3f)
|
||||
JSC_GETSET(transform, rotation, quat)
|
||||
JSC_CCALL(transform_move, transform_move(js2transform(self), js2vec3(argv[0])); )
|
||||
|
||||
|
@ -2617,6 +2639,10 @@ JSC_CCALL(os_dump_mem,
|
|||
ret = tmp2js(tmp);
|
||||
)
|
||||
|
||||
JSC_CCALL(os_value_id,
|
||||
return number2js((intptr_t)JS_VALUE_GET_PTR(argv[0]));
|
||||
)
|
||||
|
||||
static double gc_t = 0;
|
||||
static double gc_mem = 0;
|
||||
static double gc_startmem = 0;
|
||||
|
@ -3106,7 +3132,8 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
|||
MIST_FUNC_DEF(os, calc_mem, 1),
|
||||
MIST_FUNC_DEF(os, check_gc, 0),
|
||||
MIST_FUNC_DEF(os, check_cycles, 0),
|
||||
MIST_FUNC_DEF(os, memstate, 0)
|
||||
MIST_FUNC_DEF(os, memstate, 0),
|
||||
MIST_FUNC_DEF(os, value_id, 1)
|
||||
};
|
||||
|
||||
#include "steam.h"
|
||||
|
|
|
@ -158,8 +158,10 @@ time_t file_mod_secs(const char *file) {
|
|||
struct stat attr;
|
||||
mz_uint index;
|
||||
mz_zip_archive_file_stat pstat;
|
||||
|
||||
if ((index = mz_zip_reader_locate_file(&game_cdb, file, NULL, 0)) != -1) {
|
||||
|
||||
if (!stat(file,&attr))
|
||||
return attr.st_mtime;
|
||||
else if ((index = mz_zip_reader_locate_file(&game_cdb, file, NULL, 0)) != -1) {
|
||||
mz_zip_reader_file_stat(&game_cdb, index,&pstat);
|
||||
return pstat.m_time;
|
||||
}
|
||||
|
@ -170,7 +172,7 @@ time_t file_mod_secs(const char *file) {
|
|||
else
|
||||
stat(file, &attr);
|
||||
|
||||
return attr.st_mtime;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO: Not reentrant
|
||||
|
|
Loading…
Reference in a new issue