Separate the ideas of game dimensions and window dimensions

This commit is contained in:
John Alanbrook 2024-03-05 00:11:34 -06:00
parent 7b8be5b4f8
commit 4ba14ddd91
17 changed files with 169 additions and 131 deletions

View file

@ -128,7 +128,7 @@ ifeq ($(OS), Windows_NT)
UNZIP = unzip -o -q $(DISTDIR)/$(DIST) -d $(DESTDIR) UNZIP = unzip -o -q $(DISTDIR)/$(DIST) -d $(DESTDIR)
else ifeq ($(CC), emcc) else ifeq ($(CC), emcc)
OS := Web OS := Web
LDFLAGS += -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2 -pthread -sTOTAL_MEMORY=32MB LDFLAGS += -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2 -pthread -sTOTAL_MEMORY=128MB
CPPFLAGS += -pthread CPPFLAGS += -pthread
LDLIBS += pthread quickjs GL openal c m dl LDLIBS += pthread quickjs GL openal c m dl
EXT = .html EXT = .html

View file

@ -6,24 +6,24 @@ this.realzoom = function() { return cmd(135); };
this.right = function() this.right = function()
{ {
return this.pos.x + (Window.width/2); return this.pos.x + (Game.width/2);
} }
this.left = function() this.left = function()
{ {
return this.pos.x - (Window.width/2); return this.pos.x - (Game.width/2);
} }
this.mixin({ this.mixin({
get zoom() { get zoom() {
var z = Game.native.y / Window.dimensions.y; // var z = Game.native.y / Window.dimensions.y;
return cmd(135)/z; return cmd(135);///z;
}, },
set zoom(x) { set zoom(x) {
x = Math.clamp(x,0.1,10); x = Math.clamp(x,0.1,10);
var z = Game.native.y / Window.dimensions.y; // var z = Game.native.y / Window.dimensions.y;
z *= x; // z *= x;
cmd(62,z); cmd(62,x);
}, },
}); });

View file

@ -3,6 +3,10 @@
selectable selectable
*/ */
global.mixin("config.js");
Window.aspect(Window.mode.full);
Game.loadurs();
var editor = { var editor = {
toString() { return "editor"; }, toString() { return "editor"; },
grid_size: 100, grid_size: 100,
@ -370,8 +374,8 @@ var editor = {
if ('gizmo' in x && typeof x['gizmo'] === 'function' ) if ('gizmo' in x && typeof x['gizmo'] === 'function' )
x.gizmo(); x.gizmo();
}); });
render.line(bbox.topoints(bbox.fromcwh([0,0],[Game.native.x,Game.native.y])).wrapped(1), Color.yellow); render.line(bbox.topoints(bbox.fromcwh([0,0],[Game.width,Game.height])).wrapped(1), Color.green);
/* Draw selection box */ /* Draw selection box */
if (this.sel_start) { if (this.sel_start) {
@ -393,7 +397,7 @@ var editor = {
gui() { gui() {
/* Clean out killed objects */ /* Clean out killed objects */
this.selectlist = this.selectlist.filter(function(x) { return x.alive; }); this.selectlist = this.selectlist.filter(function(x) { return x.alive; });
Debug.coordinate(Window.world2screen([0,0])); GUI.text([0,0], Window.world2screen([0,0]));
GUI.text("WORKING LAYER: " + this.working_layer, [0,520]); GUI.text("WORKING LAYER: " + this.working_layer, [0,520]);
GUI.text("MODE: " + this.edit_mode, [0,500]); GUI.text("MODE: " + this.edit_mode, [0,500]);

View file

@ -91,8 +91,6 @@ global.Game = {
cmd(257, fn); cmd(257, fn);
}, },
native: render.device.pc,
object_count() { object_count() {
return cmd(214); return cmd(214);
}, },
@ -144,6 +142,11 @@ global.Game = {
this.wait_fns = []; this.wait_fns = [];
}, },
set width(w) { cmd(125, w); },
set height(h) { cmd(126, h); },
get width() { return cmd(48); },
get height() { return cmd(49); },
}; };
Game.gc = function() { cmd(259); } Game.gc = function() { cmd(259); }
@ -372,13 +375,22 @@ var Event = {
}, },
}; };
// Window
var Window = { var Window = {
fullscreen(f) { cmd(145, f); }, fullscreen(f) { cmd(145, f); },
set width(w) { cmd(125, w); }, dimensions() { return cmd(265); },
set height(h) { cmd(126, h); }, get width() { return this.dimensions().x; },
get width() { return cmd(48); }, get height() { return this.dimensions().y; },
get height() { return cmd(49); }, mode: {
get dimensions() { return [this.width, this.height]; }, stretch: 0,
keep: 1,
width: 2,
height: 3,
expand: 4,
full: 5
},
aspect(x) { cmd(264, x); },
title(str) { cmd(134, str); }, title(str) { cmd(134, str); },
boundingbox() { boundingbox() {
return { return {
@ -390,12 +402,16 @@ var Window = {
}, },
}; };
Game.width = 1920;
Game.height = 1080;
Window.screen2world = function(screenpos) { Window.screen2world = function(screenpos) {
if (Game.camera) if (Game.camera)
return Game.camera.view2world(screenpos); return Game.camera.view2world(screenpos);
return screenpos; return screenpos;
} }
Window.world2screen = function(worldpos) { Window.world2screen = function(worldpos) {
return Game.camera.world2view(worldpos); return Game.camera.world2view(worldpos);
} }
@ -407,7 +423,6 @@ global.mixin("scripts/debug.js");
global.mixin("scripts/spline.js"); global.mixin("scripts/spline.js");
global.mixin("scripts/components.js"); global.mixin("scripts/components.js");
Window.doc = {}; Window.doc = {};
Window.doc.width = "Width of the game window."; Window.doc.width = "Width of the game window.";
Window.doc.height = "Height of the game window."; Window.doc.height = "Height of the game window.";
@ -452,5 +467,3 @@ Game.view_camera = function(cam)
} }
Window.title(`Prosperon v${prosperon.version}`); Window.title(`Prosperon v${prosperon.version}`);
Window.width = 1280;
Window.height = 720;

View file

@ -105,7 +105,7 @@ GUI.controls.check_submit = function() {
var Mum = { var Mum = {
padding:[0,0], /* Each element inset with this padding on all sides */ padding:[0,0], /* Each element inset with this padding on all sides */
offset:[0,0], offset:[0,0],
font: "fonts/LessPerfectDOSVGA.ttf", font: "fonts/c64.ttf",
selectable: false, selectable: false,
selected: false, selected: false,
font_size: 1, font_size: 1,

View file

@ -1,14 +0,0 @@
function nogamegui()
{
GUI.column({
items: [
GUI.text_fn("NO GAME LOADED", {font_size: 6}),
GUI.text_fn("No game.js available.")
],
anchor: [0.5,0.5],
}).draw(Window.dimensions.scale(0.5));
}
Register.gui.register(nogamegui);

View file

@ -1,6 +0,0 @@
Game.play();
if (!io.exists("game.js"))
load("scripts/nogame.js");
else
load("game.js");

View file

@ -361,13 +361,13 @@ Cmdline.register_order("play", function(argv) {
var project = json.decode(io.slurp(projectfile)); var project = json.decode(io.slurp(projectfile));
Game.title = project.title; Game.title = project.title;
Window.aspect(Window.mode.expand);
global.mixin("config.js"); global.mixin("config.js");
if (project.title) Window.title(project.title); if (project.title) Window.title(project.title);
Game.engine_start(function() { Game.engine_start(function() {
global.mixin("scripts/sound.js"); global.mixin("scripts/sound.js");
global.game = actor.spawn("game.js"); global.game = actor.spawn("game.js");
say(`spawned game with ${game.score} points`);
if (project.icon) Window.icon(project.icon); if (project.icon) Window.icon(project.icon);
}); });
}, "Play the game present in this folder."); }, "Play the game present in this folder.");

View file

@ -553,8 +553,8 @@ void draw_grid(float width, float span, struct rgba color)
float ubo[4]; float ubo[4];
ubo[0] = offset.x; ubo[0] = offset.x;
ubo[1] = offset.y; ubo[1] = offset.y;
ubo[2] = mainwin.rwidth; ubo[2] = mainwin.width;
ubo[3] = mainwin.rheight; ubo[3] = mainwin.height;
sg_apply_pipeline(grid_pipe); sg_apply_pipeline(grid_pipe);
sg_apply_bindings(&grid_bind); sg_apply_bindings(&grid_bind);

View file

@ -84,7 +84,8 @@ void font_init() {
.label = "text buffer" .label = "text buffer"
}); });
font_set("fonts/LessPerfectDOSVGA.ttf"); // font_set("fonts/LessPerfectDOSVGA.ttf");
font_set("fonts/c64.ttf");
bind_text.fs.images[0] = font->texID; bind_text.fs.images[0] = font->texID;
bind_text.fs.samplers[0] = sg_make_sampler(&(sg_sampler_desc){}); bind_text.fs.samplers[0] = sg_make_sampler(&(sg_sampler_desc){});
} }
@ -100,7 +101,7 @@ void font_set(const char *path)
return; return;
} }
struct sFont *newfont = MakeFont(path, 16); struct sFont *newfont = MakeFont(path, 8);
if (!newfont) { if (!newfont) {
YughError("Could not make font from %s.", path); YughError("Could not make font from %s.", path);
return; return;
@ -253,22 +254,19 @@ void sdrawCharacter(struct Character c, HMM_Vec2 cursor, float scale, struct rgb
float lsize = 1.0 / 1024.0; float lsize = 1.0 / 1024.0;
float oline = 1.0; vert.pos.x = cursor.X + c.Bearing[0] * scale;
vert.pos.y = cursor.Y - c.Bearing[1] * scale;
vert.pos.x = cursor.X + c.Bearing[0] * scale + oline; vert.wh.x = c.Size[0] * scale;
vert.pos.y = cursor.Y - c.Bearing[1] * scale - oline; vert.wh.y = c.Size[1] * scale;
vert.wh.x = c.Size[0] * scale + (oline*2);
vert.wh.y = c.Size[1] * scale + (oline*2);
// if (vert.pos.x > frame.l || vert.pos.y > frame.t || (vert.pos.y + vert.wh.y) < frame.b || (vert.pos.x + vert.wh.x) < frame.l) return; // if (vert.pos.x > frame.l || vert.pos.y > frame.t || (vert.pos.y + vert.wh.y) < frame.b || (vert.pos.x + vert.wh.x) < frame.l) return;
vert.uv.u = (c.rect.s0 - oline*lsize)*USHRT_MAX; vert.uv.u = c.rect.s0*USHRT_MAX;
vert.uv.v = (c.rect.t0 - oline*lsize)*USHRT_MAX; vert.uv.v = c.rect.t0*USHRT_MAX;
vert.st.u = (c.rect.s1-c.rect.s0+oline*lsize*2.0)*USHRT_MAX; vert.st.u = (c.rect.s1-c.rect.s0)*USHRT_MAX;
vert.st.v = (c.rect.t1-c.rect.t0+oline*lsize*2.0)*USHRT_MAX; vert.st.v = (c.rect.t1-c.rect.t0)*USHRT_MAX;
vert.color = color; vert.color = color;
// sg_append_buffer(bind_text.vertex_buffers[0], &vert, sizeof(struct text_vert));
memcpy(text_buffer + curchar, &vert, sizeof(struct text_vert)); memcpy(text_buffer + curchar, &vert, sizeof(struct text_vert));
curchar++; curchar++;
} }
@ -400,8 +398,10 @@ int renderText(const char *text, HMM_Vec2 pos, float scale, struct rgba color, f
while (wordstart < line) { while (wordstart < line) {
if (*wordstart == '\e') if (*wordstart == '\e')
wordstart = esc_color(wordstart, &usecolor, color); wordstart = esc_color(wordstart, &usecolor, color);
sdrawCharacter(font->Characters[*wordstart], HMM_AddV2(cursor, HMM_MulV2F((HMM_Vec2){1,-1},scale)), scale, (rgba){0,0,0,255});
sdrawCharacter(font->Characters[*wordstart], cursor, scale, usecolor); sdrawCharacter(font->Characters[*wordstart], cursor, scale, usecolor);
cursor.X += font->Characters[*wordstart].Advance * tracking * scale; cursor.X += font->Characters[*wordstart].Advance * tracking * scale;
wordstart++; wordstart++;
check_caret(caret, wordstart-drawstart, cursor, scale, usecolor); check_caret(caret, wordstart-drawstart, cursor, scale, usecolor);

View file

@ -865,11 +865,11 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
break; break;
case 48: case 48:
ret = JS_NewInt64(js, mainwin.width); ret = JS_NewInt64(js, mainwin.rwidth);
break; break;
case 49: case 49:
ret = JS_NewInt64(js, mainwin.height); ret = JS_NewInt64(js, mainwin.rheight);
break; break;
case 50: case 50:
@ -1103,11 +1103,11 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
break; break;
case 125: case 125:
mainwin.width = js2int(argv[1]); mainwin.rwidth = js2int(argv[1]);
break; break;
case 126: case 126:
mainwin.height = js2int(argv[1]); mainwin.rheight = js2int(argv[1]);
break; break;
case 127: case 127:
@ -1456,6 +1456,12 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
str = js2str(argv[1]); str = js2str(argv[1]);
font_set(str); font_set(str);
break; break;
case 264:
aspect_mode = js2int(argv[1]);
break;
case 265:
ret = vec2js((HMM_Vec2){mainwin.width, mainwin.height});
break;
} }
if (str) JS_FreeCString(js, str); if (str) JS_FreeCString(js, str);

View file

@ -362,10 +362,6 @@ void render_init() {
} }
void render_winsize()
{
}
static cpBody *camera = NULL; static cpBody *camera = NULL;
void set_cam_body(cpBody *body) { camera = body; } void set_cam_body(cpBody *body) { camera = body; }
cpVect cam_pos() { return camera ? cpBodyGetPosition(camera) : cpvzero; } cpVect cam_pos() { return camera ? cpBodyGetPosition(camera) : cpvzero; }
@ -378,14 +374,14 @@ HMM_Vec2 world2screen(HMM_Vec2 pos)
{ {
pos = HMM_SubV2(pos, HMM_V2(cam_pos().x, cam_pos().y)); pos = HMM_SubV2(pos, HMM_V2(cam_pos().x, cam_pos().y));
pos = HMM_ScaleV2(pos, 1.0/zoom); pos = HMM_ScaleV2(pos, 1.0/zoom);
pos = HMM_AddV2(pos, HMM_V2(mainwin.rwidth/2.0, mainwin.rheight/2.0)); pos = HMM_AddV2(pos, HMM_V2(mainwin.width/2.0, mainwin.height/2.0));
return pos; return pos;
} }
HMM_Vec2 screen2world(HMM_Vec2 pos) HMM_Vec2 screen2world(HMM_Vec2 pos)
{ {
pos = HMM_ScaleV2(pos, 1/mainwin.dpi); pos = HMM_ScaleV2(pos, 1/mainwin.dpi);
pos = HMM_SubV2(pos, HMM_V2(mainwin.rwidth/2.0, mainwin.rheight/2.0)); pos = HMM_SubV2(pos, HMM_V2(mainwin.width/2.0, mainwin.height/2.0));
pos = HMM_ScaleV2(pos, zoom); pos = HMM_ScaleV2(pos, zoom);
pos = HMM_AddV2(pos, HMM_V2(cam_pos().x, cam_pos().y)); pos = HMM_AddV2(pos, HMM_V2(cam_pos().x, cam_pos().y));
return pos; return pos;
@ -396,18 +392,63 @@ HMM_Mat4 hudproj = {0.f};
HMM_Vec3 dirl_pos = {4, 100, 20}; HMM_Vec3 dirl_pos = {4, 100, 20};
#define MODE_STRETCH 0
#define MODE_KEEP 1
#define MODE_WIDTH 2
#define MODE_HEIGHT 3
#define MODE_EXPAND 4
#define MODE_FULL 5
int aspect_mode = MODE_FULL;
void full_2d_pass(struct window *window) void full_2d_pass(struct window *window)
{ {
float aspect = mainwin.width/mainwin.height;
float raspect = mainwin.rwidth/mainwin.rheight;
float pwidth = window->width*raspect/aspect;
float left = (window->width-pwidth)/2;
float pheight = window->height*aspect/raspect;
float top = (window->height-pheight)/2;
float usewidth, useheight;
usewidth = window->rwidth;
useheight = window->rheight;
switch(aspect_mode) {
case MODE_STRETCH:
sg_apply_viewportf(0,0,window->width,window->height,1);
break;
case MODE_WIDTH:
sg_apply_viewportf(0, top, window->width, pheight,1); // keep width
break;
case MODE_HEIGHT:
sg_apply_viewportf(left,0,pwidth, window->height,1); // keep height
break;
case MODE_KEEP:
sg_apply_viewportf(0,0,window->rwidth, window->rheight, 1); // no scaling
break;
case MODE_EXPAND:
if (aspect < raspect)
sg_apply_viewportf(0, top, window->width, pheight,1); // keep width
else
sg_apply_viewportf(left,0,pwidth, window->height,1); // keep height
break;
case MODE_FULL:
usewidth = window->width;
useheight = window->height;
break;
}
// 2D projection // 2D projection
cpVect pos = cam_pos(); cpVect pos = cam_pos();
projection = HMM_Orthographic_LH_NO( projection = HMM_Orthographic_LH_NO(
pos.x - zoom * window->rwidth / 2, pos.x - zoom * usewidth / 2,
pos.x + zoom * window->rwidth / 2, pos.x + zoom * usewidth / 2,
pos.y - zoom * window->rheight / 2, pos.y - zoom * useheight / 2,
pos.y + zoom * window->rheight / 2, -10000.f, 10000.f); pos.y + zoom * useheight / 2, -10000.f, 10000.f);
hudproj = HMM_Orthographic_LH_ZO(0, window->rwidth, 0, window->rheight, -1.f, 1.f); hudproj = HMM_Orthographic_LH_ZO(0, usewidth, 0, useheight, -1.f, 1.f);
sprite_draw_all(); sprite_draw_all();
model_draw_all(); model_draw_all();
@ -455,6 +496,7 @@ void full_3d_pass(struct window *window)
} }
void openglRender(struct window *window) { void openglRender(struct window *window) {
sg_swapchain sch = sglue_swapchain();
sg_begin_pass(&(sg_pass){ sg_begin_pass(&(sg_pass){
.action = pass_action, .action = pass_action,
.swapchain = sglue_swapchain(), .swapchain = sglue_swapchain(),

View file

@ -58,7 +58,7 @@ void openglInit3d(struct window *window);
void openglRender3d(struct window *window, camera3d *camera); void openglRender3d(struct window *window, camera3d *camera);
void capture_screen(int x, int y, int w, int h, const char *path); void capture_screen(int x, int y, int w, int h, const char *path);
void render_winsize(); extern int aspect_mode;
void debug_draw_phys(int draw); void debug_draw_phys(int draw);

View file

@ -28,6 +28,11 @@
#include "core.cdb.h" #include "core.cdb.h"
#if defined(_WIN32)
#include <direct.h>
#define mkdir(x,y) _mkdir(x)
#endif
char **prefabs; char **prefabs;
static const char *cur_ext = NULL; static const char *cur_ext = NULL;
@ -251,21 +256,43 @@ int cp(const char *p1, const char *p2)
return 0; return 0;
} }
int mkpath(char *dir, mode_t mode) int mkpath(char *path, mode_t mode)
{ {
if (!dir) { char tmp[256];
errno = EINVAL; char *p = NULL;
return 1; size_t len;
} struct stat sb;
if (strlen(dir) == 1 && dir[0] == '/') strncpy(tmp, path, sizeof(tmp));
return 0; len = strlen(tmp);
if (len > 0 && tmp[len - 1] == '/')
tmp[len - 1] = 0;
#ifdef _WIN32 for (p = tmp + 1; *p; p++) {
return mkdir(dir); if (*p == '/') {
#else *p = 0;
return mkdir(dir,mode); if (stat(tmp, &sb) != 0) {
#endif if (errno != ENOENT || mkdir(tmp, mode) != 0) {
return -1;
}
} else if (!S_ISDIR(sb.st_mode)) {
errno = ENOTDIR;
return -1;
}
*p = '/';
}
}
if (stat(tmp, &sb) != 0) {
if (errno != ENOENT || mkdir(tmp, mode) != 0) {
return -1;
}
} else if (!S_ISDIR(sb.st_mode)) {
errno = ENOTDIR;
return -1;
}
return 0;
} }
int slurp_write(const char *txt, const char *filename, size_t len) { int slurp_write(const char *txt, const char *filename, size_t len) {

View file

@ -26,10 +26,11 @@ void window_resize(int width, int height)
mainwin.dpi = sapp_dpi_scale(); mainwin.dpi = sapp_dpi_scale();
mainwin.width = sapp_width(); mainwin.width = sapp_width();
mainwin.height = sapp_height(); mainwin.height = sapp_height();
mainwin.rwidth = mainwin.width/mainwin.dpi;
mainwin.rheight = mainwin.height/mainwin.dpi; float aspect = mainwin.width/mainwin.height;
float raspect = mainwin.rwidth/mainwin.rheight;
render_winsize(); mainwin.pheight = mainwin.rheight;
mainwin.pwidth = mainwin.rwidth*aspect/raspect;
JSValue vals[2] = { int2js(width), int2js(height) }; JSValue vals[2] = { int2js(width), int2js(height) };
send_signal("window_resize", 2, vals); send_signal("window_resize", 2, vals);

View file

@ -3,11 +3,10 @@
struct window { struct window {
int id; int id;
int width; float width, height; // The actual width and height of the window
int height; float rwidth, rheight; // The desired rendering resolution, what the assets are at
float pwidth, pheight; // The calculated width and height passed to rendering
double dpi; double dpi;
int rwidth;
int rheight;
int render; int render;
int mouseFocus; int mouseFocus;
int keyboardFocus; int keyboardFocus;

View file

@ -8,7 +8,6 @@ in vec4 vColor;
out vec2 TexCoords; out vec2 TexCoords;
out vec4 fColor; out vec4 fColor;
out vec2 fst;
uniform vs_params { mat4 projection; }; uniform vs_params { mat4 projection; };
@ -17,7 +16,6 @@ void main()
gl_Position = projection * vec4(pos + (vert * wh), 0.0, 1.0); gl_Position = projection * vec4(pos + (vert * wh), 0.0, 1.0);
TexCoords = uv + vec2(vert.x*st.x, st.y - vert.y*st.y); TexCoords = uv + vec2(vert.x*st.x, st.y - vert.y*st.y);
fst = st / wh;
fColor = vColor; fColor = vColor;
} }
@ -26,49 +24,17 @@ void main()
@fs fs @fs fs
in vec2 TexCoords; in vec2 TexCoords;
in vec4 fColor; in vec4 fColor;
in vec2 fst;
out vec4 color; out vec4 color;
uniform texture2D text; uniform texture2D text;
uniform sampler smp; uniform sampler smp;
float osize = 1.0;
void main() void main()
{ {
float lettera = texture(sampler2D(text,smp),TexCoords).r; float lettera = texture(sampler2D(text,smp),TexCoords).r;
if (lettera < 0.1f) discard;
if (lettera <= 0.1f) color = fColor;
{
vec2 uvpos = TexCoords - fst;
for (int x = 0; x < 3; x++) {
for (int y = 0; y < 3; y++) {
float pa = texture(sampler2D(text,smp), uvpos + (fst*vec2(x,y))).r;
if (pa > 0.1) {
color = vec4(0.0,0.0,0.0, fColor.a);
return;
}
}
}
discard;
}
// vec2 lsize = fst / textureSize(dtext,0).xy;
/* vec2 uvpos = TexCoords - fst;
for (int x = 0; x < 3; x++) {
for (int y = 0; 0 < 3; y++) {
float pa = texture(sampler2D(text,smp), uvpos + (fst * vec2(x,y))).r;
if (pa <= 0.1) {
color = vec4(0.0,0.0,0.0,fColor.a);
return;
}
}
}
*/
color = vec4(fColor.xyz, fColor.a);
} }
@end @end