Huh! Well that’s unusual - a window acting like it has a frame (that explains the offset when dragging) when there’s no frame in sight. Not sure who I would have to thank for this one
YellowAfterlife
Creator of
Recent community posts
Around half of my extensions do not work on 2024.13 due to this bug
https://github.com/YoYoGames/GameMaker-Bugs/issues/10141
You can fix it by hand by moving every macro out of every extension, but I recommend rolling back to 2024.11 until it gets patched.
Without knowing your project specifics, I’m willing to guess that it’s not screen capture that’s slow, but rather writing a large PNG file - you can test this by loading the file back as a sprite, drawing it on a surface, and calling surface_save
.
GML has a buffer_compress
function that you can use to make your own PNG encoder, but it does not expose the underlying zlib functions for compressing a portion of data at the time, so whatever you make won’t be any better than existing surface_save
- has to be a native extension doing either this or saving on a separate thread in general.
Or maybe you can write 32-bit BMP files instead - these have a basic header followed by RGBA bytes that are stored upside-down (bottom row first).
For ascent/descent quick reference, check out to the tooltip that displays when you hold your mouse over “Highlight glyphs under the mouse”. Then check how it goes for the example font.
For 6x12 you could likely use default ascent/descent with pixel size of 64. Then the optimal size will usually be either 12 or 16, depending on how software counts font sizes.
And some libraries just like to aggressively apply anti-aliasing when rasterizing glyphs for rendering so you may not always get what you want with a TTF/OTF font.
Surfaces are usually destroyed when renderer state changes - like switching between exclusive fullscreen and windowed mode on multi-monitor systems, minimizing the window, or if the display/GPU get unplugged.
Using borderless/non-exclusive fullscreen with or without Gameframe helps avoid some of these scenarios, but ultimately you should use surface_exists
and re-create the surfaces before using them if they’re gone.
More or less!
You can check the shuffle in HTML5 runtime source as a point of reference - it’s not unlike yours, but swaps elements instead of using array_push+delete and traverses back to front so that it can’t swap the same thing multiple times.
Good question!
I tried quickly adding it as that’s largely the same code as the 64-bit one, and turns out that it’s hardly faster:
And for some reason it is slower if you put the whole PRNG in a macro:
I was expecting it to be slightly faster since you don’t have to do the ordeal with manually shifting the sign bit, but I didn’t notice that you have to do & $FFFFFFFF
after both <<
operations to simulate a 32-bit register.
If you are using Julian’s implementation of 32-bit Xorshift specifically, you’ll want to update to the latest commit because Julian didn’t previously notice this either.
Either way, I included it in the test project, but I see little reason to use the 32-bit version over the 64-bit one.
Another thing to consider with PRNGs (or other relatively small functions) is the way you implement them.
Putting the whole thing in a macro that you use instead of a function call is the fastest and global scripts with global variables are faster than method calls on constructors, but having methods call other methods also costs! So
function Xorshift32(_state) constructor {
state = _state;
static value = function() {
state ^= (state << 13) & $FFFFFFFF;
state ^= (state >> 17);
state ^= (state << 5) & $FFFFFFFF;
return state / 4294967296.0;
}
static float = function(_max) {
return value() * _max;
}
}
will be slower than
function Xorshift32(_state) constructor {
state = _state;
...
static float = function(_max) {
state ^= (state << 13) & $FFFFFFFF;
state ^= (state >> 17);
state ^= (state << 5) & $FFFFFFFF;
return state / 4294967296.0 * _max;
}
}
In my code I deal with this by auto-generating the scripts from Haxe source code (and have the Haxe compiler inline everything so that no function goes more than one call deep)
If I understood you correctly, I think that only happens if you have set your game to start in exclusive full screen mode.
Implementing borderless fullscreen through window_set_showborder helps.
This extension can also be used for that, but you don’t have to unless you’re using the LTS version of GM.
Gameframe calls display_set_gui_size
to switch GUI size when it draws its stuff. It’s supposed to switch it back afterwards, but there’s no display_get_gui_size
so it might be setting it to something other than what GM usually sets the GUI size too.
Call display_set_gui_size
yourself and that should be fine.
Upon a brief review I think I would prefer one of those smaller projects that you’ve tried adding GMLive to (with GMLive still in there so that I can see if this pops up or not) because GM:S took quite a while to build the project, then I pressed Alt+Enter to exit full-screen and it crashed with this:
___________________________________________
############################################################################################
FATAL ERROR in
action number 1
of Key Press Event for <Enter> Key
for object objDevolver:
global variable name 'mvol' index (100221) not set before reading it.
at gml_Script_sxeasy_play (line 10) - audio_sound_gain(global.currentsong,global.mvol,0)
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_sxeasy_play (line 10)
called from - gml_Object_objDevolver_KeyPressed_ENTER_1 (line 2) - sxeasy_play(working_directory+"\Edge of a Frozen Stream.ogg")
I then disabled fullscreen in Global Game Settings, ran the project again, GM:S hanged on “checking resources” for good 15 minutes, and upon starting it crashed with this:
ERROR!!! :: ############################################################################################
FATAL ERROR in
action number 1
of Alarm Event for alarm 0
for object objMusicPlay:
global variable name 'mvol' index (100221) not set before reading it.
at gml_Script_sxeasy_play (line 10) - audio_sound_gain(global.currentsong,global.mvol,0) ############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_sxeasy_play (line 10)
called from - gml_Object_objMusicPlay_ObjAlarm0_1 (line 2) - sxeasy_play(working_directory+"\Edge of a Frozen Stream.ogg");
I don’t have Unity installed right now, but that probably means that they decided to re-set the icon on their own.
You would need to add a window message hook that intercepts the attempts to change icon and passes your saved icons instead.
In the GameMaker/C++ version that looks like the following:
LRESULT window_command_proc_hook(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
if (msg == WM_SETICON && window_icon_hook.enable) {
HICON icon;
switch (wp) {
case ICON_SMALL:
icon = window_icon_hook.icons[0];
break;
case ICON_BIG:
icon = window_icon_hook.icons[1];
break;
default: icon = NULL;
}
if (icon != NULL) lp = (LPARAM)icon;
}
return CallWindowProc(window_icon_hook.base, hwnd, msg, wp, lp);
}
void window_icon_hook_ensure(HWND hwnd) {
if (window_icon_hook.base == nullptr) {
window_icon_hook.base = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)window_command_proc_hook);
}
}
As ever, all function signatures and typedefs can be taken from pinvoke.net
You can find the previous release on Wayback Machine but this isn’t very good at all - I guess the font library that I use either introduced a bug in the version I updated to (while the git version breaks kerning for some reason) or changed what you’re supposed to give it to get a color font.
The current version should be working on everything starting from GM2022/LTS and to the latest 2024.11.
Beta versions of GM are at your own risk - these tend to break (and then unbreak) random GML functions and it’s not always possible to make a workaround even if you figure out what did happen this time around.
For the most part I only have to update GMLive when there are breaking changes to project format or GML functions - for example, I’ll have to release a patch for whatever that’s going on for some people here soon.
And if you open the previous version on Wayback Machine, does that work?
https://web.archive.org/web/20250126224026/https://yal.cc/r/20/pixelfont/
Ascent and Descent are in em units, not in pixels. There’s an overlay when you move your mouse over the input image showing ascent/descent.
I can’t tell what this glyph of yours is supposed to be, but you can try ascent=896, descent=128, linegap=0 (and adjust your Baseline Y to be, well, at the baseline).