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)
else ifeq ($(CC), emcc)
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
LDLIBS += pthread quickjs GL openal c m dl
EXT = .html

View file

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

View file

@ -3,6 +3,10 @@
selectable
*/
global.mixin("config.js");
Window.aspect(Window.mode.full);
Game.loadurs();
var editor = {
toString() { return "editor"; },
grid_size: 100,
@ -371,7 +375,7 @@ var editor = {
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 */
if (this.sel_start) {
@ -393,7 +397,7 @@ var editor = {
gui() {
/* Clean out killed objects */
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("MODE: " + this.edit_mode, [0,500]);

View file

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

View file

@ -105,7 +105,7 @@ GUI.controls.check_submit = function() {
var Mum = {
padding:[0,0], /* Each element inset with this padding on all sides */
offset:[0,0],
font: "fonts/LessPerfectDOSVGA.ttf",
font: "fonts/c64.ttf",
selectable: false,
selected: false,
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));
Game.title = project.title;
Window.aspect(Window.mode.expand);
global.mixin("config.js");
if (project.title) Window.title(project.title);
Game.engine_start(function() {
global.mixin("scripts/sound.js");
global.game = actor.spawn("game.js");
say(`spawned game with ${game.score} points`);
if (project.icon) Window.icon(project.icon);
});
}, "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];
ubo[0] = offset.x;
ubo[1] = offset.y;
ubo[2] = mainwin.rwidth;
ubo[3] = mainwin.rheight;
ubo[2] = mainwin.width;
ubo[3] = mainwin.height;
sg_apply_pipeline(grid_pipe);
sg_apply_bindings(&grid_bind);

View file

@ -84,7 +84,8 @@ void font_init() {
.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.samplers[0] = sg_make_sampler(&(sg_sampler_desc){});
}
@ -100,7 +101,7 @@ void font_set(const char *path)
return;
}
struct sFont *newfont = MakeFont(path, 16);
struct sFont *newfont = MakeFont(path, 8);
if (!newfont) {
YughError("Could not make font from %s.", path);
return;
@ -253,22 +254,19 @@ void sdrawCharacter(struct Character c, HMM_Vec2 cursor, float scale, struct rgb
float lsize = 1.0 / 1024.0;
float oline = 1.0;
vert.pos.x = cursor.X + c.Bearing[0] * scale + oline;
vert.pos.y = cursor.Y - c.Bearing[1] * scale - oline;
vert.wh.x = c.Size[0] * scale + (oline*2);
vert.wh.y = c.Size[1] * scale + (oline*2);
vert.pos.x = cursor.X + c.Bearing[0] * scale;
vert.pos.y = cursor.Y - c.Bearing[1] * scale;
vert.wh.x = c.Size[0] * scale;
vert.wh.y = c.Size[1] * scale;
// 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.v = (c.rect.t0 - oline*lsize)*USHRT_MAX;
vert.st.u = (c.rect.s1-c.rect.s0+oline*lsize*2.0)*USHRT_MAX;
vert.st.v = (c.rect.t1-c.rect.t0+oline*lsize*2.0)*USHRT_MAX;
vert.uv.u = c.rect.s0*USHRT_MAX;
vert.uv.v = c.rect.t0*USHRT_MAX;
vert.st.u = (c.rect.s1-c.rect.s0)*USHRT_MAX;
vert.st.v = (c.rect.t1-c.rect.t0)*USHRT_MAX;
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));
curchar++;
}
@ -401,7 +399,9 @@ int renderText(const char *text, HMM_Vec2 pos, float scale, struct rgba color, f
if (*wordstart == '\e')
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);
cursor.X += font->Characters[*wordstart].Advance * tracking * scale;
wordstart++;
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;
case 48:
ret = JS_NewInt64(js, mainwin.width);
ret = JS_NewInt64(js, mainwin.rwidth);
break;
case 49:
ret = JS_NewInt64(js, mainwin.height);
ret = JS_NewInt64(js, mainwin.rheight);
break;
case 50:
@ -1103,11 +1103,11 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
break;
case 125:
mainwin.width = js2int(argv[1]);
mainwin.rwidth = js2int(argv[1]);
break;
case 126:
mainwin.height = js2int(argv[1]);
mainwin.rheight = js2int(argv[1]);
break;
case 127:
@ -1456,6 +1456,12 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
str = js2str(argv[1]);
font_set(str);
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);

View file

@ -362,10 +362,6 @@ void render_init() {
}
void render_winsize()
{
}
static cpBody *camera = NULL;
void set_cam_body(cpBody *body) { camera = body; }
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_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;
}
HMM_Vec2 screen2world(HMM_Vec2 pos)
{
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_AddV2(pos, HMM_V2(cam_pos().x, cam_pos().y));
return pos;
@ -396,18 +392,63 @@ HMM_Mat4 hudproj = {0.f};
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)
{
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
cpVect pos = cam_pos();
projection = HMM_Orthographic_LH_NO(
pos.x - zoom * window->rwidth / 2,
pos.x + zoom * window->rwidth / 2,
pos.y - zoom * window->rheight / 2,
pos.y + zoom * window->rheight / 2, -10000.f, 10000.f);
pos.x - zoom * usewidth / 2,
pos.x + zoom * usewidth / 2,
pos.y - zoom * useheight / 2,
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();
model_draw_all();
@ -455,6 +496,7 @@ void full_3d_pass(struct window *window)
}
void openglRender(struct window *window) {
sg_swapchain sch = sglue_swapchain();
sg_begin_pass(&(sg_pass){
.action = pass_action,
.swapchain = sglue_swapchain(),

View file

@ -58,7 +58,7 @@ void openglInit3d(struct window *window);
void openglRender3d(struct window *window, camera3d *camera);
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);

View file

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

View file

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

View file

@ -3,11 +3,10 @@
struct window {
int id;
int width;
int height;
float width, height; // The actual width and height of the window
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;
int rwidth;
int rheight;
int render;
int mouseFocus;
int keyboardFocus;

View file

@ -8,7 +8,6 @@ in vec4 vColor;
out vec2 TexCoords;
out vec4 fColor;
out vec2 fst;
uniform vs_params { mat4 projection; };
@ -17,7 +16,6 @@ void main()
gl_Position = projection * vec4(pos + (vert * wh), 0.0, 1.0);
TexCoords = uv + vec2(vert.x*st.x, st.y - vert.y*st.y);
fst = st / wh;
fColor = vColor;
}
@ -26,49 +24,17 @@ void main()
@fs fs
in vec2 TexCoords;
in vec4 fColor;
in vec2 fst;
out vec4 color;
uniform texture2D text;
uniform sampler smp;
float osize = 1.0;
void main()
{
float lettera = texture(sampler2D(text,smp),TexCoords).r;
if (lettera <= 0.1f)
{
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);
if (lettera < 0.1f) discard;
color = fColor;
}
@end