Windows now compiles with directx; separated out ur and entity methods

This commit is contained in:
John Alanbrook 2023-09-19 17:35:12 +00:00
parent 45a1b2dfb3
commit a57aaeb5d5
11 changed files with 115 additions and 79 deletions

View file

@ -1,6 +1,6 @@
MAKEFLAGS = --jobs=4
UNAME != uname
nMAKEDIR != pwd
MAKEDIR != pwd
# Options
# DBG --- build with debugging symbols and logging
@ -71,7 +71,7 @@ ARCH = x64
ifeq ($(OS), Windows_NT)
LDFLAGS += -mwin32 -static
CFLAGS += -mwin32
LDLIBS += mingw32 kernel32 opengl32 user32 shell32 dxgi gdi32 ws2_32 ole32 winmm setupapi m
LDLIBS += mingw32 kernel32 d3d11 user32 shell32 dxgi gdi32 ws2_32 ole32 winmm setupapi m
EXT = .exe
PLAT = w64
PKGCMD = cd $(BIN); zip -q -r $(MAKEDIR)/$(DISTDIR)/$(DIST) . -x \*.a ./obj/\*
@ -142,11 +142,12 @@ SHADERS = $(shell ls source/shaders/*.sglsl)
SHADERS := $(patsubst %.sglsl, %.sglsl.h, $(SHADERS))
install: $(BIN)/$(NAME)
cp $(BIN)/$(NAME) $(DESTDIR)
cp -f $(BIN)/$(NAME) $(DESTDIR)
$(BIN)/$(NAME): $(BIN)/libengine.a $(BIN)/libquickjs.a $(BIN)/libcdb.a
@echo Linking $(NAME)
$(LD) $^ $(LDFLAGS) -L$(BIN) $(LDLIBS) -o $@
cp $(BIN)/$(NAME) .
@echo Finished build
$(DISTDIR)/$(DIST): $(BIN)/$(NAME)
@ -207,6 +208,11 @@ jso: tools/jso.c $(BIN)/libquickjs.a
@echo Making $@ from $<
./jso $< > $@
WINCC = x86_64-w64-mingw32-gcc
.PHONY: crosswin
crosswin:
make CC=$(WINCC) OS=Windows_NT
clean:
@echo Cleaning project
@rm -rf bin dist

View file

@ -42,7 +42,7 @@ In edit mode, there are no running scripts; only editing them.
There are two distinct items in the Primum Machina: the Entity, and the Component. Components give qualities to Entities. An Entity is any real, tangible thing in the universe, and so every entity has a position. Components do not necessarily have a position; they can be things like the image that draws where the entity is located, and colliders that allow the entity to respond with the world.
### Components
The most "bare metal" are the components. These are essentially hooks into the engine that tell it how to do particular things. For example, to render a sprite, Javascript does no rendering, but rather tells the engine to create an image and render it in a particular spot.
The most "bare metal" are the components. These are essentially hooks into the engine that tell it how to do particular things. For example, to render a sprite, Javascript does no rendering, but rather tells the engine to create an image and render it in a particular spot. Javascript does the accounting to make or destroy the sprite as needed - but besides that initial startup, no scripting is done.
Components are rendered in an "ECS" style. To work, components must be installed on an entity. They have no meaning outside of a physical object in the world.
@ -62,7 +62,7 @@ All objects follow the prototyping model of inheritence. This makes it trivial t
Components cannot be prototyped. They are fundamentally tied to the entity they are bound to.
Entities can be prototyped out. What this means is that, when you select an object in the game, you can either make a "subtype" of it, where changes to the object trickle down to the created one, or a "sidetype" of it, which is a total duplicate of the object.
Entities can be prototyped out. What this means is that, when you select an object in the game, you can either make a "subtype" of it, where changes to the object trickle down to the created one, or a "sidetype" of it, which is a total duplicate of the object. Javascript handled creating entites with components that have your saved values.
entity.clone(parent) -> create a subtyped version of the entity
entity.dup(parent) -> create a copy of the entity.
@ -79,6 +79,17 @@ Only first Ur-types can have components. Every inherited thing after it can only
Ur-types also remember the list of entities that compose the given Ur.
Visually it looks like this:
Ur-ur, the thing all Ur-types derive from
- Ur-type 1, defined in script, with components
- Variant 1, same component combination but different values
- Variant 2, other different values
- Variant 2A, overwritten values from Variant 2
- Ur-type 2
All ur-types and variants can be created in the world, where they become a true blue ENTITY. Entities can be under entities infinitely.
### Loading traits
Traits are defined by code and a data file. When an Ur-type is extended with a trait, the code is run, and then the data file contains modifications and

View file

@ -24,6 +24,11 @@ Object.defineProperty(Object.prototype, 'getOwnPropertyDescriptors', {
}
});
Object.defHidden = function(obj, prop)
{
Object.defineProperty(obj, prop, {enumerable:false, writable:true});
}
Object.defineProperty(Object.prototype, 'obscure', {
value: function(name) {
Object.defineProperty(this, name, { enumerable: false });

View file

@ -762,7 +762,15 @@ editor.inputs['C-d'] = function() {
};
editor.inputs['C-d'].doc = "Duplicate all selected objects.";
editor.inputs.f3 = function() { editor.selectlist.forEach(x => Log.say(JSON.stringify(x,null,2))); };
editor.inputs.f3 = function() {
Log.say("Selected JSON ...");
editor.selectlist.forEach(x => Log.say(JSON.stringify(x,null,2)));
Log.say("UR JSON ...");
for (var key of Object.keys(editor.selectlist[0].ur.type))
Log.say(key);
editor.selectlist.forEach(x => Log.say(JSON.stringify(x.ur.type,null,2)));
};
editor.inputs['C-m'] = function() {
if (editor.sel_comp) {
@ -1922,3 +1930,4 @@ if (IO.exists("editor.config"))
editor.clear_level();
editor.camera = Game.camera;
Game.stop();
Game.editor_mode(false);

View file

@ -510,7 +510,7 @@ var Game = {
sys_cmd(4);
},
render() { sys_cmd(10); },
editor_mode(m) { sys_cmd(10, m); },
playing() { return sys_cmd(5); },
paused() { return sys_cmd(6); },
@ -554,6 +554,13 @@ gameobject.make_parentable(Primum);
Primum.tag = "PRIMUM";
Primum.selectable = false;
Primum.ur = { tag: "Primum" };
Primum.spawn = function(ur) {
if (typeof ur === 'string')
ur = prototypes.get_ur(ur);
return ur.type.make(this);
};
/* Reparent this object to a new one */
World.reparent = function(parent) { Log.warn("Cannot reparent the Primum."); }
World.unparent = function() { Log.warn("The Primum has no parent, always."); }

View file

@ -15,13 +15,7 @@ var gameobject = {
save: true,
selectable: true,
spawn(ur) {
if (typeof ur === 'string')
ur = prototypes.get_ur(ur);
return ur.type.make(this);
},
/* Make a duplicate of this exact object */
clone(name, ext) {
var obj = Object.create(this);
complete_assign(obj, ext);
@ -113,37 +107,12 @@ var gameobject = {
gizmo: "", /* Path to an image to draw for this gameobject */
/* Bounding box of the object in world dimensions */
/* Bounding box of the ur, if it were to be spawned */
boundingbox() {
var boxes = [];
boxes.push({t:0, r:0,b:0,l:0});
for (var key in this.components) {
if ('boundingbox' in this.components[key])
boxes.push(this.components[key].boundingbox());
}
if (boxes.empty) return cwh2bb([0,0], [0,0]);
var bb = boxes[0];
boxes.forEach(function(x) {
bb = bb_expand(bb, x);
});
var cwh = bb2cwh(bb);
if (!bb) return;
if (this.flipx) cwh.c.x *= -1;
if (this.flipy) cwh.c.y *= -1;
cwh.c = cwh.c.add(this.pos);
bb = cwh2bb(cwh.c, cwh.wh);
return bb ? bb : cwh2bb([0,0], [0,0]);
},
width() {
var bb = this.boundingbox();
return bb.r - bb.l;
@ -204,7 +173,8 @@ var gameobject = {
make(level) {
level ??= Primum;
var obj = Object.create(this);
this.instances.push(obj);
// this.instances.push(obj);
// obj.ur = this;
obj.toString = function() {
if (obj.ur)
return obj.ur.tag;
@ -272,6 +242,45 @@ var gameobject = {
sync() { },
dirty() { return false; },
spawn(ur) {
if (typeof ur === 'string')
ur = prototypes.get_ur(ur);
return ur.type.make(this);
},
/* Bounding box of the object in world dimensions */
boundingbox() {
var boxes = [];
boxes.push({t:0, r:0,b:0,l:0});
for (var key in this.components) {
if ('boundingbox' in this.components[key])
boxes.push(this.components[key].boundingbox());
}
if (boxes.empty) return cwh2bb([0,0], [0,0]);
var bb = boxes[0];
boxes.forEach(function(x) {
bb = bb_expand(bb, x);
});
var cwh = bb2cwh(bb);
if (!bb) return;
if (this.flipx) cwh.c.x *= -1;
if (this.flipy) cwh.c.y *= -1;
cwh.c = cwh.c.add(this.pos);
bb = cwh2bb(cwh.c, cwh.wh);
return bb ? bb : cwh2bb([0,0], [0,0]);
},
dup(diff) {
var dup = Primum.spawn(this.ur);
Object.assign(dup, this);
@ -312,7 +321,9 @@ var gameobject = {
down() { return [0,-1].rotate(Math.deg2rad(this.angle));},
right() { return [1,0].rotate(Math.deg2rad(this.angle));},
left() { return [-1,0].rotate(Math.deg2rad(this.angle));},
/* Given an ur-type, spawn one attached to us */
toJSON() {
var ret = {};
for (var key in this) {
@ -371,6 +382,7 @@ var gameobject = {
gameobject.make_parentable = function(obj) {
var objects = [];
Object.defHidden(obj, 'level');
obj.remove_child = function(child) {
objects.remove(child);
@ -434,19 +446,20 @@ prototypes.from_file = function(file)
return;
}
var newobj = gameobject.clone(file, {});
var newur = gameobject.clone(file, {});
var script = IO.slurp(file);
newobj.$ = {};
Object.defHidden(newur, '$');
newur.$ = {};
var json = {};
if (IO.exists(file.name() + ".json")) {
json = JSON.parse(IO.slurp(file.name() + ".json"));
Object.assign(newobj.$, json.$);
Object.assign(newur.$, json.$);
delete json.$;
}
compile_env(`var self = this; var $ = self.$; ${script}`, newobj, file);
dainty_assign(newobj, json);
compile_env(`var self = this; var $ = self.$; ${script}`, newur, file);
dainty_assign(newur, json);
file = file.replaceAll('/', '.');
var path = file.name().split('.');
@ -457,12 +470,13 @@ prototypes.from_file = function(file)
return base;
};
var a = nested_access(ur, path);
Object.defHidden(a, 'instances');
a.instances = [];
a.tag = file.name();
prototypes.list.push(a.tag);
a.type = newobj;
a.type = newur;
a.instances = [];
newobj.ur = a;
// newur.ur = a;
return a;
}

View file

@ -1249,7 +1249,7 @@ JSValue duk_sys_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *ar
break;
case 10:
render_dirty = 1;
editor_mode = js2bool(argv[1]);
break;
}

View file

@ -430,15 +430,6 @@ void full_2d_pass(struct window *window)
//////////// 2D projection
cpVect pos = cam_pos();
#if defined SOKOL_GLCORE33 || defined SOKOL_GLES3
projection = HMM_Orthographic_RH_ZO(
pos.x - zoom * window->rwidth / 2,
pos.x + zoom * window->rwidth / 2,
pos.y + zoom * window->rheight / 2,
pos.y - zoom * window->rheight / 2, -1.f, 1.f);
hudproj = HMM_Orthographic_RH_ZO(0, window->width, window->height, 0, -1.f, 1.f);
#else
projection = HMM_Orthographic_LH_ZO(
pos.x - zoom * window->rwidth / 2,
pos.x + zoom * window->rwidth / 2,
@ -446,7 +437,6 @@ void full_2d_pass(struct window *window)
pos.y + zoom * window->rheight / 2, -1.f, 1.f);
hudproj = HMM_Orthographic_LH_ZO(0, window->rwidth, 0, window->rheight, -1.f, 1.f);
#endif
sprite_draw_all();
call_draw();

View file

@ -6,7 +6,7 @@
#elif __EMSCRIPTEN__
#define SOKOL_GLES3
#elif __WIN32
#define SOKOL_GLCORE33
#define SOKOL_D3D11
#define SOKOL_WIN32_FORCE_MAIN
#elif __APPLE__
#define SOKOL_METAL

View file

@ -58,7 +58,6 @@ static struct d_prof prof_input;
static struct d_prof prof_physics;
double physlag = 0;
int render_dirty = 0;
double physMS = 1 / 60.f;
@ -74,6 +73,8 @@ static float timescale = 1.f;
static int sim_play = SIM_PLAY;
static int editor_mode = 0;
#ifdef __TINYC__
int backtrace(void **buffer, int size) {
extern uint64_t *__libc_stack_end;
@ -168,25 +169,21 @@ static void process_frame()
prof(&prof_physics);
}
if (sim_play == SIM_STEP) {
if (sim_play == SIM_STEP)
sim_pause();
render_dirty = 1;
}
}
if (sim_play == SIM_PLAY || render_dirty) {
prof_start(&prof_draw);
window_render(&mainwin);
prof(&prof_draw);
render_dirty = 0;
}
prof_start(&prof_draw);
window_render(&mainwin);
prof(&prof_draw);
gameobjects_cleanup();
}
void c_frame()
{
if (sim_play != SIM_PLAY) return;
if (editor_mode) return;
process_frame();
}
@ -196,8 +193,6 @@ void c_clean() {
void c_event(const sapp_event *e)
{
render_dirty = 1;
#ifndef NO_EDITOR
snk_handle_event(e);
#endif
@ -260,7 +255,7 @@ void c_event(const sapp_event *e)
break;
}
if (sim_play != SIM_PLAY)
if (editor_mode)
process_frame();
}

View file

@ -21,6 +21,5 @@ extern double appTime;
extern double renderMS;
extern double physMS;
extern double updateMS;
extern int render_dirty;
extern int editor_mode;
#endif