Fix rotate, scale, move

This commit is contained in:
John Alanbrook 2023-12-12 14:46:27 +00:00
parent d9f6dd5e56
commit 2083fb6e9e
14 changed files with 85 additions and 215 deletions

View file

@ -551,13 +551,9 @@ polygon2d.inputs['C-b'].doc = "Freeze mirroring in place.";
component.edge2d = Object.copy(collider2d, {
dimensions:2,
thickness:0,
/* open: 0
clamped: 1
beziers: 2
looped: 3
*/
type: Spline.type.clamped,
type: Spline.type.catmull,
looped: false,
angle: 5,
flipx: false,
flipy: false,
@ -609,32 +605,12 @@ component.edge2d = Object.copy(collider2d, {
sample(n) {
var spoints = this.spoints();
// n = this.samples * this.sample_calc();
var degrees = 2;
if (n < spoints.length) n = spoints.length;
if (spoints.length === 2)
return spoints;
if (spoints.length < 2)
return [];
if (this.samples === 1) {
if (this.looped) return spoints.wrapped(1);
return spoints;
}
/*
order = degrees+1
knots = spoints.length + order
assert knots%order != 0
*/
n = this.samples * this.sample_calc();
if (this.looped)
return Spline.sample(degrees, this.dimensions, Spline.type.open, spoints.wrapped(this.degrees), n);
/* if (this.looped)
return Spline.sample(degrees, this.dimensions, Spline.type.open, spoints.wrapped(this.degrees), n);*/
return Spline.sample(degrees, this.dimensions, this.type, spoints, n);
return Spline.sample_angle(this.type, spoints, this.angle);
},
samples: 1,

View file

@ -27,13 +27,9 @@ var editor = {
},
edit_mode: "basic",
get_this() {
return this.edit_level;
},
get_this() { return this.edit_level; },
get_that() {
return this.selectlist.length === 1 ? this.selectlist[0] : this.get_this();
},
get_that() { return this.selectlist.length === 1 ? this.selectlist[0] : this.get_this(); },
try_select() { /* nullify true if it should set selected to null if it doesn't find an object */
var go = physics.pos_query(Mouse.worldpos);
@ -78,7 +74,7 @@ var editor = {
var objs = x.slice();
var duped = [];
objs.forEach(function(x) { duped.push(x.dup()); } );
objs.forEach(x => duped.push(x.dup()));
return duped;
},
@ -404,7 +400,7 @@ var editor = {
}
GUI.text("0,0", world2screen([0,0]));
GUI.text(editor.edit_level.worldpos().map(function(x) { return Math.round(x); }), world2screen(editor.edit_level.worldpos()), 1, Color.red);
GUI.text(editor.edit_level.worldpos().map(x => Math.round(x)), world2screen(editor.edit_level.worldpos()), 1, Color.red);
GUI.text("+", world2screen(editor.edit_level.worldpos()), 1, Color.blue);
var thiso = editor.get_this();
@ -771,21 +767,12 @@ editor.inputs.r = function() {
});
};
editor.inputs.r.doc = "Rotate selected using the mouse while held down.";
editor.inputs.r.released = function() { editor.rotlist = []; }
editor.inputs.f5 = function()
{
editor.start_play_ed();
}
editor.inputs.f5 = function() { editor.start_play_ed(); }
editor.inputs.f5.doc = "Start game from 'debug' if it exists; otherwise, from 'game'.";
editor.inputs.f6 = function()
{
editor.start_play();
}
editor.inputs.f6 = function() { editor.start_play(); }
editor.inputs.f6.doc = "Start game as if the player started it.";
editor.inputs['M-p'] = function() {
@ -1137,7 +1124,6 @@ editor.inputs.mouse.move = function(pos, dpos)
editor.rotlist?.forEach(function(x) {
var anglediff = Math.atan2(relpos.y, relpos.x) - x.rotoffset;
x.obj.angle = x.angle + Math.rad2deg(anglediff);
if (x.pos)
x.obj.pos = x.pos.sub(x.offset).add(x.offset.rotate(anglediff));

View file

@ -334,15 +334,21 @@ function Color(from) {
*/
var Spline = {};
Spline.sample_angle = function(type, points, angle) {
var s = spline_cmd(0, type, 2, points, angle);
return s;
}
Spline.sample = function(degrees, dimensions, type, ctrl_points, nsamples)
{
var s = spline_cmd(0, degrees,dimensions,type,ctrl_points,nsamples);
console.warn(s);
return s;
}
Spline.type = {
open: 0,
clamped: 1,
beziers: 2
catmull: 0,
beziers: 1,
bspline: 2,
cubichermite: 3
};
load("scripts/components.js");

View file

@ -55,7 +55,6 @@ actor.remaster = function(to){
to.padawans.push(this);
};
var gameobject = {
full_path() {
return this.path_from(Primum);
@ -237,8 +236,6 @@ var gameobject = {
this.level?.remove_obj(this);
this.level = parent;
cmd(208,parent.body,this.body);
function unique_name(list, obj) {
var str = obj.toString().replaceAll('.', '_');

View file

@ -1,13 +1,11 @@
/* On collisions, entities are sent a 'hit' object, which looks like this: */
var HIT = {
normal: "The normal of the collision point.",
hit: "The gameobject ID of the object that collided.",
hit: "The gameobject of the object that collided.",
sensor: "Boolean for if the colliding object was a sensor.",
velocity: "Velocity of the contact.",
pos: "Position in world space of the contact.",
depth: "Depth of the contact.",
id: "Gameobject ID of the colliding object.",
obj: "Entity that collided."
};
var Physics = {
@ -21,14 +19,10 @@ var physics = {
get gravity() { return cmd(72); },
set damping(x) { cmd(73,Math.clamp(x,0,1)); },
get damping() { return cmd(74); },
pos_query(pos) {
return cmd(44, pos);
},
pos_query(pos) { return cmd(44, pos); },
/* Returns a list of body ids that a box collides with */
box_query(box) {
return cmd(52, box.pos, box.wh);
},
box_query(box) { return cmd(52, box.pos, box.wh); },
box_point_query(box, points) {
if (!box || !points)
@ -37,20 +31,11 @@ var physics = {
return cmd(86, box.pos, box.wh, points, points.length);
},
shape_query(shape) {
return cmd(80,shape);
},
shape_query(shape) { return cmd(80,shape); },
com(pos) {
if (!Array.isArray(pos)) return;
var com = [];
for (var i = 0; i < pos[0].length; i++) {
com[i] = pos.reduce(function(acc,val) {
return acc + val[i];
});
com[i] /= pos.length;
}
return com;
if (!Array.isArray(pos)) return [0,0];
return pos.reduce((a,i) => a.add(i)).map(g => g/pos.length);
},
};

View file

@ -57,8 +57,16 @@ cpShape *phys2d_query_pos(cpVect pos) {
return find;
}
int p_compare(void *a, void *b)
{
if (a > b) return 1;
if (a < b) return -1;
if (a == b) return 0;
}
gameobject **clean_ids(gameobject **ids)
{
qsort(ids, arrlen(ids), sizeof(*ids), p_compare);
gameobject *curid = NULL;
for (int i = arrlen(ids)-1; i >= 0; i--)
if (ids[i] == curid)
@ -107,21 +115,20 @@ gameobject *phys2d_query_box(HMM_Vec2 pos, HMM_Vec2 wh) {
cpBB bbox = cpShapeGetBB(box);
int *ids = NULL;
querybox qb;
qb.bb = bbox;
qb.ids = ids;
qb.ids = NULL;
cpSpaceShapeQuery(space, box, querylist, ids);
cpSpaceShapeQuery(space, box, querylist, qb.ids);
cpSpaceEachBody(space, querylistbodies, &qb);
cpShapeFree(box);
return clean_ids(ids);
return clean_ids(qb.ids);
}
gameobject *phys2d_query_shape(struct phys2d_shape *shape) {
gameobject *phys2d_query_shape(struct phys2d_shape *shape)
{
gameobject **ids = NULL;
cpSpaceShapeQuery(space, shape->shape, querylist, ids);
return clean_ids(ids);
@ -565,7 +572,6 @@ void duk_call_phys_cb(HMM_Vec2 norm, struct callee c, gameobject *hit, cpArbiter
// srfv.cp = cpArbiterGetPointA(arb,0);
// JS_SetPropertyStr(js, obj, "pos", vec2js(srfv));
// JS_SetPropertyStr(js,obj,"depth", num2js(cpArbiterGetDepth(arb,0)));
JS_SetPropertyStr(js,obj,"obj", JS_DupValue(js,hit->ref));
struct postphys_cb cb;
cb.c = c;

View file

@ -8,6 +8,8 @@
#include "stb_ds.h"
static gameobject **gameobjects;
gameobject *body2go(cpBody *body) { return cpBodyGetUserData(body); }
gameobject *shape2go(cpShape *shape)
{
@ -59,16 +61,14 @@ gameobject *pos2gameobject(HMM_Vec2 pos) {
if (hit)
return shape2go(hit);
return NULL;
/*
for (int i = 0; i < arrlen(gameobjects); i++) {
if (!gameobjects[i].body) continue;
cpVect gpos = cpBodyGetPosition(gameobjects[i].body);
float dist = cpvlength(cpvsub(gpos, pos.cp));
if (!gameobjects[i]->body) continue;
HMM_Vec2 gpos = go_pos(gameobjects[i]);
float dist = HMM_DistV2(gpos,pos);
if (dist <= 25) return i;
if (dist <= 25) return gameobjects[i];
}
*/
return NULL;
}
@ -166,14 +166,11 @@ gameobject *MakeGameobject() {
.next = -1,
.drawlayer = 0,
.shape_cbs = NULL,
.children = NULL,
.gravity = 1,
.cgravity = (HMM_Vec2){0,0},
.damping = NAN,
.timescale = 1.0,
.ref = JS_UNDEFINED,
.parent = NULL,
.children = NULL
};
go.cbs.begin.obj = JS_UNDEFINED;
@ -185,18 +182,10 @@ gameobject *MakeGameobject() {
*ngo = go;
cpBodySetUserData(go.body, ngo);
phys2d_setup_handlers(ngo);
arrpush(gameobjects, ngo);
return ngo;
}
void gameobject_traverse(gameobject *go, HMM_Mat4 p)
{
HMM_Mat4 local = transform3d2mat(go2t3(go));
go->world = HMM_MulM4(local, p);
for (int i = 0; i < arrlen(go->children); i++)
gameobject_traverse(go->children[i], go->world);
}
void rm_body_shapes(cpBody *body, cpShape *shape, void *data) {
struct phys2d_shape *s = cpShapeGetUserData(shape);
if (s->data) {
@ -225,7 +214,12 @@ void gameobject_free(gameobject *go) {
if (!go) return;
YughWarn("FREEING A GAMEOBJECT");
JS_FreeValue(js, go->ref);
dag_clip(go);
for (int i = arrlen(gameobjects)-1; i >= 0; i--)
if (gameobjects[i] == go) {
arrdelswap(gameobjects, i);
break;
}
if (cpSpaceIsLocked(space))
arrpush(go_toclean, go);

View file

@ -45,12 +45,9 @@ struct gameobject {
struct phys_cbs cbs;
struct shape_cb *shape_cbs;
JSValue ref;
struct gameobject *master;
HMM_Mat4 world;
transform2d t; /* The local transformation of this object */
float drawlayer;
struct gameobject *parent;
struct gameobject **children;
};
typedef struct gameobject gameobject;
@ -60,8 +57,6 @@ void gameobject_apply(gameobject *go);
void gameobject_free(gameobject *go);
void gameobjects_cleanup();
void gameobject_traverse(gameobject *start, HMM_Mat4 p);
transform2d go2t(gameobject *go);
transform3d go2t3(gameobject *go);

View file

@ -296,8 +296,8 @@ void vec2float(HMM_Vec2 v, float *f) {
JSValue vec2js(HMM_Vec2 v) {
JSValue array = JS_NewArray(js);
js_setprop_num(array,0,JS_NewFloat64(js,v.x));
js_setprop_num(array,1,JS_NewFloat64(js,v.y));
js_setprop_num(array,0,num2js(v.x));
js_setprop_num(array,1,num2js(v.y));
return array;
}
@ -386,23 +386,29 @@ JSValue bb2js(struct boundingbox bb)
}
JSValue duk_spline_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
int degrees = js2int(argv[1]); /* not used */
int d = js2int(argv[2]); /* dimensions: 1d, 2d, 3d ...*/
int cmd = js2int(argv[0]);
/*
0: hermite-cubic
1: catmull-rom
2: b-spline
3: bezier
*/
int type = js2int(argv[3]);
HMM_Vec2 *points = js2cpvec2arr(argv[4]);
size_t nsamples = js2int(argv[5]);
int type = js2int(argv[1]);
int d = js2int(argv[2]); /* dimensions: 1d, 2d, 3d ...*/
HMM_Vec2 *points = js2cpvec2arr(argv[3]);
float param = js2number(argv[4]);
HMM_Vec2 *samples = catmull_rom_ma_v2(points, param);
HMM_Vec2 *samples = catmull_rom_ma_v2(points, nsamples);
JSValue arr = vecarr2js(samples, nsamples);
free(samples);
if (!samples)
return JS_UNDEFINED;
return JS_UNDEFINED;
// for (int i = 0; i < arrlen(samples); i++)
// YughWarn("%g,%g", samples[i].x, samples[i].y);
JSValue arr = vecarr2js(samples, arrlen(samples));
// arrfree(samples);
return arr;
}
JSValue ints2js(int *ints) {
@ -491,7 +497,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
const char *str2 = NULL;
const void *d1 = NULL;
const void *d2 = NULL;
int *ids = NULL;
gameobject *ids = NULL;
gameobject *go = NULL;
JSValue ret = JS_UNDEFINED;
@ -691,7 +697,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
case 44:
go = pos2gameobject(js2vec2(argv[1]));
ret = go ? go->ref : JS_UNDEFINED;
ret = go ? JS_DupValue(js,go->ref) : JS_UNDEFINED;
break;
case 45:
@ -1324,7 +1330,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
ret = dsp_node2js(dsp_fwd_delay(js2number(argv[1]), js2number(argv[2])));
break;
case 208:
dag_set(js2gameobject(argv[1]), js2gameobject(argv[2]));
// dag_set(js2gameobject(argv[1]), js2gameobject(argv[2]));
break;
case 209:
break;

View file

@ -17,7 +17,6 @@ struct phys_cbs {
struct callee separate;
};
extern struct callee stacktrace_callee;
extern JSValue num_cache[100];

View file

@ -122,7 +122,7 @@ void sprite_draw_all() {
if (layers) arrfree(layers);
for (int i = 0; i < freelist_len(sprites); i++)
if (sprites[i].next == -1 && sprites[i].go >= 0 && sprites[i].enabled)
if (sprites[i].next == -1 && sprites[i].go != NULL && sprites[i].enabled)
arrpush(layers, i);
if (!layers || arrlen(layers) == 0) return;
@ -240,14 +240,12 @@ void tex_draw(struct Texture *tex, HMM_Mat3 m, struct glrect r, struct rgba colo
}
void sprite_draw(struct sprite *sprite) {
gameobject *go = sprite->go;
if (!sprite->tex) return;
HMM_Mat3 m = t_go2world(sprite->go);
HMM_Mat3 sm = transform2d2mat(sprite->t);
tex_draw(sprite->tex, HMM_MulM3(m, sm), sprite->frame, sprite->color, 0, (HMM_Vec2){0,0}, 0, sprite->emissive);
if (sprite->tex) {
HMM_Mat3 m = t_go2world(go);
HMM_Mat3 sm = transform2d2mat(sprite->t);
tex_draw(sprite->tex, HMM_MulM3(m, sm), sprite->frame, sprite->color, 0, (HMM_Vec2){0,0}, 0, sprite->emissive);
}
}
void sprite_setanim(struct sprite *sprite, struct TexAnim *anim, int frame) {

View file

@ -13,7 +13,7 @@ struct sprite {
transform2d t;
struct rgba color;
struct rgba emissive;
gameobject *go; /* id of gameobject */
gameobject *go;
struct Texture *tex;
struct glrect frame;
int enabled;

View file

@ -14,7 +14,7 @@ HMM_Vec3 trans_down(const transform3d *trans) { return HMM_QVRot(vDOWN, trans->r
HMM_Vec3 trans_right(const transform3d *trans) { return HMM_QVRot(vRIGHT, trans->rotation); }
HMM_Vec3 trans_left(const transform3d *trans) { return HMM_QVRot(vLEFT, trans->rotation); }
HMM_Vec2 mat_t_pos(HMM_Mat3 m, HMM_Vec2 pos) { return HMM_MulM3V3(m, (HMM_Vec3){pos.x, pos.y, 0}).xy; }
HMM_Vec2 mat_t_pos(HMM_Mat3 m, HMM_Vec2 pos) { return HMM_MulM3V3(m, (HMM_Vec3){pos.x, pos.y, 1}).xy; }
HMM_Vec2 mat_t_dir(HMM_Mat3 m, HMM_Vec2 dir)
{
@ -36,9 +36,7 @@ HMM_Vec3 mat3_t_dir(HMM_Mat4 m, HMM_Vec3 dir)
return mat3_t_pos(m, dir);
}
HMM_Mat3 transform2d2mat(transform2d trn) {
return HMM_MulM3(HMM_Translate2D(trn.pos), HMM_MulM3(HMM_RotateM3(trn.angle), HMM_ScaleM3(trn.scale)));
}
HMM_Mat3 transform2d2mat(transform2d trn) { return HMM_MulM3(HMM_Translate2D(trn.pos), HMM_MulM3(HMM_RotateM3(trn.angle), HMM_ScaleM3(trn.scale))); }
transform2d mat2transform2d(HMM_Mat3 m)
{

View file

@ -25,10 +25,6 @@
#include "2dphysics.h"
#ifdef __GLIBC__
#include <execinfo.h>
#endif
#include <signal.h>
#include <time.h>
@ -83,55 +79,6 @@ static int sim_play = SIM_PLAY;
int editor_mode = 0;
#ifdef __TINYC__
int backtrace(void **buffer, int size) {
extern uint64_t *__libc_stack_end;
uint64_t **p, *bp, *frame;
asm ("mov %%rbp, %0;" : "=r" (bp));
p = (uint64_t**) bp;
int i = 0;
while (i < size) {
frame = p[0];
if (frame < bp || frame > __libc_stack_end) {
return i;
}
buffer[i++] = p[1];
p = (uint64_t**) frame;
}
return i;
}
#endif
void print_stacktrace() {
#ifdef __GLIBC__
void *ents[512];
size_t size = backtrace(ents, 512);
YughCritical("====================BACKTRACE====================");
char **stackstr = backtrace_symbols(ents, size);
YughCritical("Stack size is %d.", size);
for (int i = 0; i < size; i++)
YughCritical(stackstr[i]);
js_stacktrace();
#endif
}
void seghandle(int sig) {
//#ifdef __GLIBC__
// if (strsignal(sig))
YughCritical("CRASH! Signal: %d.", sig);
js_stacktrace();
exit(1);
//#endif
// js_stacktrace();
// exit(1);
}
const char *engine_info()
{
static char str[100];
@ -153,19 +100,15 @@ void c_init() {
window_set_icon("icons/moon.gif");
window_resize(sapp_width(), sapp_height());
script_evalf("Game.init();");
// bjork = ds_openvideo("bjork.mpg");
}
int frame_fps() {
return 1.0/sapp_frame_duration();
}
int frame_fps() { return 1.0/sapp_frame_duration(); }
static void process_frame()
{
double elapsed = stm_sec(stm_laptime(&frame_t));
script_evalf("Register.appupdate.broadcast(%g);", elapsed);
call_stack();
// ds_advance(bjork, elapsed);
input_poll(0);
/* Timers all update every frame - once per monitor refresh */
timer_update(elapsed, timescale);
@ -318,7 +261,6 @@ void app_name(char *name) { start_desc.window_title = strdup(name); }
int main(int argc, char **argv) {
#ifndef NDEBUG
log_init();
// #ifdef __linux__
int logout = 0;
if (logout) {
time_t now = time(NULL);
@ -326,21 +268,6 @@ int main(int argc, char **argv) {
snprintf(fname, 100, "yugine-%d.log", now);
log_setfile(fname);
}
FILE *sysinfo = NULL;
/* sysinfo = popen("uname -a", "r");
if (!sysinfo) {
YughWarn("Failed to get sys info.");
} else {
log_cat(sysinfo);
pclose(sysinfo);
}*/
// #endif
signal(SIGSEGV, seghandle);
signal(SIGABRT, seghandle);
signal(SIGFPE, seghandle);
// signal(SIGBUS, seghandle);
#endif
#ifdef STEAM
@ -395,7 +322,4 @@ dam->update_activity(dam, &da, NULL, NULL);
return 0;
}
double apptime()
{
return stm_sec(stm_diff(stm_now(), start_t));
}
double apptime() { return stm_sec(stm_diff(stm_now(), start_t)); }