diff --git a/scripts/core/engine.js b/scripts/core/engine.js index 418c5de4..935d14c3 100644 --- a/scripts/core/engine.js +++ b/scripts/core/engine.js @@ -170,22 +170,22 @@ function pprint(msg, lvl = 0) { if (tracy) tracy.message(fmt) } -console.spam = function(msg) { +console.spam = function spam(msg) { pprint(msg, 0) } -console.debug = function(msg) { +console.debug = function debug(msg) { pprint(msg, 1) } -console.info = function(msg) { +console.info = function info(msg) { pprint(msg, 2) } -console.warn = function(msg) { +console.warn = function warn(msg) { pprint(msg, 3) } -console.log = function(msg) { +console.log = function log(msg) { pprint(msg, 2) } -console.error = function(e) { +console.error = function error(e) { if (!e) e = new Error() @@ -195,11 +195,11 @@ ${e.stack}`, 4) else pprint(e,4) } -console.panic = function(e) { +console.panic = function panic(e) { pprint(e, 5) os.quit() } -console.assert = function(op, str = `assertion failed [value '${op}']`) { +console.assert = function assert(op, str = `assertion failed [value '${op}']`) { if (!op) console.panic(str) } diff --git a/scripts/modules/draw2d.js b/scripts/modules/draw2d.js index f0052d0f..2b9208d7 100644 --- a/scripts/modules/draw2d.js +++ b/scripts/modules/draw2d.js @@ -459,18 +459,6 @@ draw.images[prosperon.DOC] = ` :raises Error: If no image is provided. ` -draw.sprites = function(sprites, sort = 0, pipeline) { - var cmds = graphics.make_sprite_queue(sprites, prosperon.camera, pipeline, sort) - for (var i = 0; i < cmds.length; i++) - render.queue(cmds[i]) -} -draw.sprites[prosperon.DOC] = ` -:param sprites: An array of sprite objects to draw. -:param sort: Sorting mode or order, default 0. -:param pipeline: (Optional) A pipeline or rendering state object. -:return: None -` - function software_circle(pos, radius) { if (radius <= 0) return // nothing to draw diff --git a/scripts/modules/ext/transform.js b/scripts/modules/ext/transform.js index 24738f0b..34c7fc8e 100644 --- a/scripts/modules/ext/transform.js +++ b/scripts/modules/ext/transform.js @@ -1,4 +1,4 @@ -var ret = { +return { get pos() { if (!this.transform) return return this.transform.pos; @@ -29,5 +29,3 @@ var ret = { this.scale = this.scale.map((x, i) => x * vec[i]); }, } - -return ret diff --git a/scripts/modules/json.js b/scripts/modules/json.js index f1b2b399..4a02b9e9 100644 --- a/scripts/modules/json.js +++ b/scripts/modules/json.js @@ -1,6 +1,6 @@ var json = {} -json.encode = function(val,replacer,space = 1,whitelist) +json.encode = function encode(val,replacer,space = 1,whitelist) { return JSON.stringify(val, replacer, space) } @@ -11,7 +11,7 @@ If the record does not have a json() method, and if whitelist is a record, then If the space input is true, then line breaks and extra whitespace will be included in the text.` -json.decode = function(text,reviver) +json.decode = function decode(text,reviver) { return JSON.parse(text,reviver) } diff --git a/scripts/modules/lcdsprite.js b/scripts/modules/lcdsprite.js new file mode 100644 index 00000000..f5741058 --- /dev/null +++ b/scripts/modules/lcdsprite.js @@ -0,0 +1,60 @@ +var sprite = {} + +var graphics = use('graphics') +var render = use('render') +var draw2d = use('draw2d') + +var ursprite = {} + +ursprite.move = function move(mv) +{ + this.rect.x += mv.x + this.rect.y += mv.y +} + +ursprite.moveto = function moveto(pos) +{ + this.rect.x = pos.x + this.rect.y = pos.y +} + +ursprite.draw = function draw() +{ + draw2d.image(this.image, this.rect, 0, this.anchor) +} + +var sprites = [] + +sprite.create = function(image, pos, anchor = [0,0], layer = 0, props = {}) +{ + var sp = Object.create(ursprite) + + var image = graphics.texture(image) + sp.image = image + sp.rect = {x:pos.x, y:pos.y, width: image.texture.width, height: image.texture.height} + sp.layer = layer + sp.props = props + sp.anchor = anchor + + sprites.push(sp) + + return sp +} + +sprite.forEach = function(fn) +{ + for (var sp of sprites) + fn(sp) +} + +sprite.values = function() +{ + return sprites.slice() +} + +sprite.geometry = function() +{ + return graphics.make_sprite_mesh(sprites) +} + +return sprite diff --git a/scripts/modules/sdl_render.js b/scripts/modules/sdl_render.js index 3519ed42..2ea619bc 100644 --- a/scripts/modules/sdl_render.js +++ b/scripts/modules/sdl_render.js @@ -28,9 +28,6 @@ render.initialize = function(config) url: "https://prosperon.dev" } -// for (var i in default_conf) -// config[i] ??= default_conf[i] - prosperon.window = prosperon.engine_start({width:500,height:500}) console.log(prosperon.window) context = prosperon.window.make_renderer() diff --git a/scripts/modules/time.js b/scripts/modules/time.js index 4b7c24ff..b17ea865 100644 --- a/scripts/modules/time.js +++ b/scripts/modules/time.js @@ -42,16 +42,16 @@ time.strparse = { s: "second", }; -time.isleap = function(year) { +time.isleap = function isleap(year) { return this.yearsize(year) === 366; }; -time.yearsize = function(y) { +time.yearsize = function yearsize(y) { if (y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0)) return 366; return 365; }; -time.timecode = function(t, fps = 24) { +time.timecode = function timecode(t, fps = 24) { var s = Math.trunc(t); t -= s; return `${s}:${Math.trunc(fps * s)}`; @@ -60,7 +60,7 @@ time.timecode = function(t, fps = 24) { time.monthdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; time.zones = { "-12": "IDLW" }; -time.record = function(num, zone = this.computer_zone()) { +time.record = function record(num, zone = this.computer_zone()) { if (typeof num === "object") { return num; } else if (typeof num === "number") { @@ -113,7 +113,7 @@ time.record = function(num, zone = this.computer_zone()) { } }; -time.number = function(rec) { +time.number = function number(rec) { if (typeof rec === "number") { return rec; } else if (typeof rec === "object") { @@ -153,7 +153,7 @@ time.number = function(rec) { time.fmt = "vB mB d h:nn:ss TZz a y c"; -time.text = function(num, fmt = this.fmt, zone) { +time.text = function text(num, fmt = this.fmt, zone) { var rec = (typeof num === "number") ? time.record(num, zone) : num; zone = rec.zone; if (fmt.match("a")) { diff --git a/source/jsffi.c b/source/jsffi.c index 377ffa5e..90445fbf 100644 --- a/source/jsffi.c +++ b/source/jsffi.c @@ -2883,7 +2883,8 @@ JSC_CCALL(renderer_rects, // Should take a single struct with pos, color, uv, and indices arrays JSC_CCALL(renderer_geometry, - SDL_Renderer *r = js2renderer_ctx(js,self)->sdl; + renderer_ctx *ctx = js2renderer_ctx(js,self); + SDL_Renderer *r = ctx->sdl; JSValue pos = JS_GetPropertyStr(js,argv[1], "pos"); JSValue color = JS_GetPropertyStr(js,argv[1], "color"); JSValue uv = JS_GetPropertyStr(js,argv[1], "uv"); @@ -2902,8 +2903,11 @@ JSC_CCALL(renderer_geometry, HMM_Vec2 *trans_pos = malloc(vertices*sizeof(HMM_Vec2)); memcpy(trans_pos,posdata, sizeof(HMM_Vec2)*vertices); - for (int i = 0; i < vertices; i++) - trans_pos[i] = HMM_MulM3V3(cam_mat, (HMM_Vec3){trans_pos[i].x, trans_pos[i].y, 1}).xy; + for (int i = 0; i < vertices; i++) { + SDL_FPoint p = renderer_world_to_screen(ctx, trans_pos[i]); + trans_pos[i].x = p.x; + trans_pos[i].y = p.y; + } if (!SDL_RenderGeometryRaw(r, tex, trans_pos, pos_stride,colordata,color_stride,uvdata, uv_stride, vertices, idxdata, count, indices_stride)) ret = JS_ThrowReferenceError(js, "Error rendering geometry: %s",SDL_GetError()); @@ -2914,7 +2918,6 @@ JSC_CCALL(renderer_geometry, JS_FreeValue(js,color); JS_FreeValue(js,uv); JS_FreeValue(js,indices); - printf("AMDET\n"); ) JSC_CCALL(renderer_logical_size, @@ -2988,7 +2991,6 @@ JSC_CCALL(renderer_target, // Given an array of sprites, make the necessary geometry // A sprite is expected to have: -// transform: a transform encoding position and rotation. its scale is in pixels - so a scale of 1 means the image will draw only on a single pixel. // image: a standard prosperon image of a surface, rect, and texture // color: the color this sprite should be hued by JSC_CCALL(renderer_make_sprite_mesh, @@ -3003,7 +3005,6 @@ JSC_CCALL(renderer_make_sprite_mesh, for (int i = 0; i < quads; i++) { JSValue sub = JS_GetPropertyUint32(js,sprites,i); - JSValue jstransform = JS_GetProperty(js,sub,transform); JSValue jssrc = JS_GetProperty(js,sub,src); JSValue jscolor = JS_GetProperty(js,sub,color); @@ -3034,7 +3035,6 @@ JSC_CCALL(renderer_make_sprite_mesh, colordata[base+2] = color; colordata[base+3] = color; - JS_FreeValue(js,jstransform); JS_FreeValue(js,sub); JS_FreeValue(js,jscolor); JS_FreeValue(js,jssrc); diff --git a/source/prosperon.c b/source/prosperon.c index d74dc6c9..b7db64f6 100644 --- a/source/prosperon.c +++ b/source/prosperon.c @@ -326,7 +326,7 @@ void actor_turn(prosperon_rt *actor, int greedy) { SDL_LockMutex(actor->turn); #ifdef TRACY_ENABLE - TracyCFiberEnter(actor->id); +// TracyCFiberEnter(actor->id); #endif SDL_LockMutex(actor->msg_mutex); @@ -415,7 +415,7 @@ void actor_turn(prosperon_rt *actor, int greedy) END: #ifdef TRACY_ENABLE - TracyCFiberLeave(actor->id); +// TracyCFiberLeave(actor->id); #endif SDL_UnlockMutex(actor->turn); set_actor_state(actor); @@ -423,7 +423,7 @@ void actor_turn(prosperon_rt *actor, int greedy) KILL: #ifdef TRACY_ENABLE - TracyCFiberLeave(actor->id); +// TracyCFiberLeave(actor->id); #endif SDL_UnlockMutex(actor->turn); actor_free(actor); @@ -529,7 +529,15 @@ JSValue js_actor_delay(JSContext *js, JSValue self, int argc, JSValue *argv) prosperon_rt *actor = JS_GetContextOpaque(js); double seconds; JS_ToFloat64(js, &seconds, argv[1]); + if (seconds <= 0) { + SDL_LockMutex(actor->msg_mutex); + JSValue cb = JS_DupValue(js, argv[0]); + arrput(actor->events, cb); + SDL_UnlockMutex(actor->msg_mutex); + return JS_NewInt32(js, -1); + } Uint64 ns = seconds * SDL_NS_PER_SECOND; + Uint32 id = SDL_AddTimerNS(ns, actor_timer_cb, actor); SDL_LockMutex(actor->msg_mutex); @@ -549,6 +557,8 @@ JSValue js_actor_removetimer(JSContext *js, JSValue self, int argc, JSValue *arg prosperon_rt *actor = JS_GetContextOpaque(js); Uint32 timer_id; JS_ToUint32(js, &timer_id, argv[0]); + if (timer_id == -1) return JS_UNDEFINED; + SDL_RemoveTimer(timer_id); JSValue cb = JS_UNDEFINED; diff --git a/source/sprite.h b/source/sprite.h index f2e9c908..b092e5cf 100644 --- a/source/sprite.h +++ b/source/sprite.h @@ -6,12 +6,14 @@ #include "quickjs.h" struct sprite{ - rect affine; - JSValue image; + HMM_Vec2 pos; // x,y coordinates of the sprite + HMM_Mat2 affine; // defines all deformation + rect affine; // + JSValue image; // the actual texture resource - perhaps SDL_GPUTexture, or SDL_Texture, or something else ... SDL_GPUTexture *tex; - rect uv; - int layer; - HMM_Vec4 color; + rect uv; // pixel coordinates of the sprite on its image + int layer; // layer this sprite draws onto + HMM_Vec4 color; // color in 0-1f }; typedef struct sprite sprite; diff --git a/tests/bunny.png b/tests/bunny.png new file mode 100644 index 00000000..79c31675 Binary files /dev/null and b/tests/bunny.png differ diff --git a/tests/bunnymark.js b/tests/bunnymark.js new file mode 100644 index 00000000..b9dd8e05 --- /dev/null +++ b/tests/bunnymark.js @@ -0,0 +1,64 @@ +// bunnymark +var render = use('render') +var os = use('os') +var dim = [500,500] +render.initialize({ + width:dim.x, + height:dim.y, + resolution_x:dim.x, + resolution_y:dim.y, + mode:"letterboxed", + refresh: 60, +}) + +var camera = { + size: [500,500], + transform: os.make_transform(), + fov:50, + near_z: 0, + far_z: 1000, + surface: undefined, + viewport: {x:0,y:0,width:1,height:1}, + ortho:true, + anchor:[0,0], +} + +var draw = use('draw2d') +var sprite = use('lcdsprite') +var graphics = use('graphics') + +var bunny = graphics.texture('tests/bunny') + +var center = [0.5,0.5] + +var vel = 50 + +for (var i = 0; i < 20000; i++) { + var sp = sprite.create(bunny, [Math.random()*dim.x, Math.random()*dim.y], center) + sp.dir = [Math.random()*vel, Math.random()*vel] +} + +function movendraw(sp) +{ +// sp.move([sp.dir[0]*dt, sp.dir[1]*dt]) + sp.draw() +} + +var dt = 0 +function loop() +{ + var now = os.now() + render.clear([22/255,120/255,194/255,255/255]) + render.camera(camera) + +// sprite.forEach(movendraw) + var mesh = sprite.geometry() + render.geometry(bunny.texture, mesh) + + render.present() + dt = os.now() - now + var delay = (1/60) - dt + $_.delay(loop, delay) +} + +loop() diff --git a/tests/camera.js b/tests/camera.js index 3d126b0f..8ac81749 100644 --- a/tests/camera.js +++ b/tests/camera.js @@ -38,14 +38,24 @@ var hudcam = { var angle = 0 var pos = [0,0,0] +var dt = 0 + +var sprite = use('lcdsprite') +sprite.create("ok", [50,50], [0.5,0]) +sprite.create("nope", [100,100], [0.5,0]) +sprite.create("sad", [150,150], [0.5,0]) + function loop() { - pos.x += 1 + var now = os.now() + pos.x += dt*100 camera.transform.pos = pos - render.clear(Color.red) + render.clear([22/255,120/255,194/255,255/255]) render.camera(camera) - draw.image("button_grey", [0,0]) + for (var sp of sprite.sprites) + draw.image(sp.image, sp.rect) + /* draw.line([[0,0],[100,50]]) draw.point([100,100]) draw.circle([200,200],40) @@ -58,9 +68,14 @@ function loop() draw.rectangle({x:350, y:60, width:200, height:120}, {radius:10,thickness:3}) */ render.camera(hudcam) - draw.slice9("button_grey", {x:0,y:0,width:200,height:250}, 10) + draw.slice9("button_grey", {x:0,y:0,width:100,height:50}, 10) render.present() - $_.delay(loop, 1/60) + dt = os.now()-now + var delay = (1/240) - dt + if (delay <= 0) + loop() + else + $_.delay(loop, delay) } var sound = use('sound')