OFFICIAL GMS 2.3.0 BETA ANNOUNCEMENT

Status
Not open for further replies.
GML:
function Enemy(_sprite_index) constructor {
    _duration = 0;
    _state = 0;
    init = function(_sprite_index) {
        sprite_index = _sprite_index;
        idle(60);
    }

    idle = function(_duration) {
        _duration = _duration;
        _state = 0;
    }
  
    step = function(){//call enemy.step() in step event
        switch( _state ){
            case 0:
                if (!_duration--) {
                    show_debug_message("duration over")
                }
            break;
        }
    }
  
    init(_sprite_index);// you can call it inner function just in one event step.
}
BPOutlaws_Jeff
Something like this.
Interesting...so the bottom init(_sprite_index); would cause it to run itself when an "enemy = new Enemy(spr_enemy);" is called? But it would have to be below the function's definition inside the struct? This'll be super handy for spawning things in code!
Now that the Assets Browser has been re-designed to allow us to structure it anyway that we want, I'm trying to figure out how I want to go about this. I thought about doing something like
Code:
Player
    Sprites
    Functions
    Objects
   
Enemies
    Sprites
    Functions
    Objects
That's something I've been kicking around. Anyone else thought of how they may redo their stuff?
I hear people in Unity do something like this so maybe some Unity tutorials would give you ideas on best practices. I'm used to the GMS setup but I'm definitely leaning toward trying something like this out although when you get to functions or audio etc that can be shared that might get a little messy...
I'm struggling with all this. Every time someone posts some code the layout is different. I'm still trying though.
I am struggling to figure out how to glue everything together.
lol I hear ya. I'm redoing parts of my game or common tasks with rough ideas of how to approach it using this new stuff to figure out where I can clean things up and do them more efficiently but it's all running blind on what any best practices are for this. Plus I was looking up tutorials in general and there's a ton of "OOP is bad, use procedural/functional programming" stuff on YouTube which is like, wait are we getting features that we shouldn't be using? lol I'm sure those vids are just talking about people abusing OOP and classes to the point where it's counter-productive which gives the feeling that we're being handed a double-edged sword and approach it carefully.

I see the point the anti-OOP vids make that there's a lure to do a ton of extra coding and set up overly-elaborate solutions for things that could probably be done a lot simpler just doing them more straightforward especially for solo gameDev if you're not making an MMORPG or something but just have like 12 different enemies in your game, you probably don't need an entity that can be a mammal that's a person with 2 legs and getters and setters etc etc but probably just some basic sharing is enough for small projects.

For any of the more experienced devs:
1) Are there any resources you recommend (YouTube vids or articles) for newbies to this that focus on properly using structs & classes & all this new (to us) function constructor etc stuff? Whether it's actual code from another language or just general philosophy behind it?

and 2) Similarly is there any recommended reading or watching (or games with source code) for best practices regarding overall game structure etc in relation to this stuff? A lot of OOP related examples seem to be for websites and boring data management stuff instead of gameDev and it feels like there's a lot of different stuff to consider when you're making an actual game instead of a website with an employee payroll system.

Like I'm thinking the most logical thing to do would be to replace a bunch of stuff like input handler objects with just structs inside the main game obj like:
GML:
//--------------------------------------------------
//obj_game
//--------------------------------------------------
//Create Event
settings = {
    enum diff {easy, medium, hard}//can I put these in here so the relevant ones are in one place?
    enum gfx  {high, medium, low}

    difficulty:   diff.easy;
    gfx_detail:   gfx.high;
    music_volume: 10;
    sfx_volume:   10;

    keyboard: {//I have no idea what kind of best practice doing controller supports would be lol
        right:  vk_right;
        attack: vk_space;
        //etc...
    }

    gamepad: {
        right:  gp_padr;
        attack: gp_face1;
        //etc...
    }
}

input = {//only gonna create one of these inside the obj_game object...no more need for an obj_input handler?
    enum key {up, down, left, right, attack, check, pressed, released}

    #macro INPUT           obj_game.input//can I throw macros in here so the related ones are all in one place? lol

    #macro RIGHT_CHECK     INPUT.get_input(INPUT.binds.right,  INPUT.binds.check   )
    #macro RIGHT_PRESSED   INPUT.get_input(INPUT.binds.right,  INPUT.binds.pressed )
    #macro RIGHT_RELEASED  INPUT.get_input(INPUT.binds.right,  INPUT.binds.released)

    #macro ATTACK_CHECK    INPUT.get_input(INPUT.binds.attack, INPUT.binds.check   )
    #macro ATTACK_PRESSED  INPUT.get_input(INPUT.binds.attack, INPUT.binds.pressed )
    #macro ATTACK_RELEASED INPUT.get_input(INPUT.binds.attack, INPUT.binds.released)
    //etc..

    binds = {
        right:  [settings.keyboard.right,  settings.gamepad.right ]
        attack: [settings.keyboard.attack, settings.gamepad.attack]
        //etc..
    }

    get_input = function(_bind, _type) {
        switch (_type) {                            //excuse my OCD lol
            case key.check:    return keyboard_check(         _bind[0]) + gamepad_check_button(         0, _bind[1]); break;
            case key.pressed:  return keyboard_check_pressed( _bind[0]) + gamepad_check_button_pressed( 0, _bind[1]); break;
            case key.released: return keyboard_check_released(_bind[0]) + gamepad_check_button_released(0, _bind[1]); break;
        }
    }
}



//--------------------------------------------------
//scr_components
//--------------------------------------------------
Anim = function() constructor {
    play    = function(_anim_name) {skeleton_animation_set(_anim_name);}
    is_done = function()           {return image_index + image_speed == image_number - 1;}
    current = function(_anim_name) {return skeleton_animation_get()  == _anim_name;}
}



//--------------------------------------------------
//obj_player
//--------------------------------------------------
//Create Event
anim = new Anim();
anim.play("idle");

//Step Event
if (RIGHT_CHECK && ATTACK_PRESSED)               {anim.play("shoryuken");}
if (anim.current("shoryuken") && anim.is_done()) {anim.play("idle");}
But it's hard to guage whether I'm just doing kickflips and 360s for the sake of doing them lol it seems like I could end up with something like:
GML:
//inside obj_game:
input.pressed(dir.right);
audio.play(bgm_song);
replay.start_recording("recording.txt");
menus.create("Main Menu");
enemies.update_all();
Like with pretty much all the major stuff contained in just one obj_game object...but that seems kind of crazy compared to what was going on before lol using parenting alone kind of forced you to spread your objects out (obj_button is a child of obj_menu which is a child of obj_gui etc). It's hard to tell if this is trying to cram too much into one spot or if an ideal game would really look something like an obj_main and then just player & enemy & powerup etc objects instead of a bunch of separate handler objects.

I guess I (and probably a lot of other newbies) just kind of wonder what sort of best practices & guidelines there are for this specifically in terms of gameDev. Like Amon said: trying to figure out how to glue it all together. I know there was a lot of "everyone is learning bad coding practices" stuff in the early GML days and this is a huge shift so I'm probably not alone in wanting to make sure I'm learning the best approaches and rules from day one instead of making whatever mistakes have been made with OOP over the last however many years its been popular lol
It's not that difficult...
1) When you new MyFunctionMarkedAsConstructor() you are creating an "instance" and returning it.
2) This "instance" is different from the instances made from objects.. it's called struct (AKA lightweight object instance)
3) As you might imagine inside that struct you can have variables and those are independent from the instance ones.


############### LETS LOOK AT THE IMAGE BELOW #############
View attachment 30996
GML:
 //0) you create an instance of objBase
//1) in the create event you set the x and y (of the instance to 10 and 22)
//2) you create a struct of type MyStruct
//3) this is an individual entity that as nothing to do with the instance
//4) you set variables inside the struct 'a'
//5) the x and y inside the struct are not the same from the instance.
### LETS LOOK AT ANOTHER EXAMPLE WITH CONSTRUCTOR PARAMS ###
View attachment 30998
GML:
//0) you create an instance of objBase
//1) in the create event you set the x and y (of the instance to 10 and 22)
//2) you create a struct of type MyStruct and pass (100 and 200 as params)
//3) the struct is created and the 'struct variables' are set
[CONCLUSION] the x and y inside the struct is not the x and y inside the instance :)

[EXTRA]
If you want to change the instance position you need to either:
1) remove the constructor keyword from the function.
OR
2) use other keyword before the x/y variables.

Either way:
  • If the function is marked as a constructor you should NOT call it as a function.
  • If it is NOT a constructor you shoudn't be calling it with new.
This was super useful, thanks! The diagrams really cleared things up!
Not fancy, but just spent a short time learning the ropes and building this. Time invested in total was about an hour learning and implementing, so pretty short all things considered.
This is great! As someone who uses a ton of Spine stuff in my games I'm really curious to see what the sequencer can do and how it plays with Spine and what kind of tasks seem better to do in the sequencer than in Spine and how to combine the two and see what they can do together.
 

Amon

Member
There definitely needs to be a tutorial on how to integrate structs/constructors etc with the rest of GMS2. i.e. Where we used 'with' we now can use blah and this is how: we moved objects like this before but now you can do it with structs etc and this is how; etc etc etc...

:)
 

Dogarooski

Member
There definitely needs to be a tutorial on how to integrate structs/constructors etc with the rest of GMS2. i.e. Where we used 'with' we now can use blah and this is how: we moved objects like this before but now you can do it with structs etc and this is how; etc etc etc...

:)
'with' in 2.2:
GML:
with (object)
{
    // ...
}
'with' in 2.3:
GML:
with (object)
{
    // ...
}
 

atmobeat

Member
I've really been enjoying reading all the code here using the new GML functions. Constructors and how to use the new static keyword are things I'm still working out. Overall I'm thrilled with all the new additions packed within 2.3. I have some simple questions for now while I chew on the more nuanced uses of the new gml features.

Since the IDE now allows us to rearrange everything, how does that work with the resource ids? GMS2.2 assigns object ids to the objects based on the order they appear in the tree from top to bottom (I assume the same goes for other resources as well). What is 2.3 doing? Are the assets, as they're now called, assigned numbers according to their current position or is there a fixed arrangement “behind the scenes” while the rearranging we do is merely superficial? I actually use this quirk of GMS2.2 so I'm curious how I may or may not have to change things.

Second set of questions: structs are all instances correct? If I create a struct with whatever way of doing so, the thing I've created is a lightweight instance, even though people here have been calling them lightweight objects. Is this correct? From what I've seen of the dot notation used to access the variables inside a struct, and the lack of functions to get the equivalent of instance ids for structs, this is the only thing that makes sense. Also, if I create a struct inside obj_whatever, I don't access the struct by using obj_whatever.struct.x; rather, I just use struct.x no matter what the scope is, right? Do I therefore get an error if I try to make two structs with the same name from within different objects?
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Since the IDE now allows us to rearrange everything, how does that work with the resource ids? GMS2.2 assigns object ids to the objects based on the order they appear in the tree from top to bottom (I assume the same goes for other resources as well). What is 2.3 doing? Are the assets, as they're now called, assigned numbers according to their current position or is there a fixed arrangement “behind the scenes” while the rearranging we do is merely superficial? I actually use this quirk of GMS2.2 so I'm curious how I may or may not have to change things.
The old way was undocumented behaviour, and subject to change at any time, so you should never be using it in your projects. The new way is also undocumented behaviour and will remain so as it could change at any time. ;)

Second set of questions: structs are all instances correct? If I create a struct with whatever way of doing so, the thing I've created is a lightweight instance, even though people here have been calling them lightweight objects. Is this correct? From what I've seen of the dot notation used to access the variables inside a struct, and the lack of functions to get the equivalent of instance ids for structs, this is the only thing that makes sense.
No. A struct is essentially a new data-type and has nothing to do with instances and objects... which is why the name "lightweight object" was dropped, as they aren't really.

Also, if I create a struct inside obj_whatever, I don't access the struct by using obj_whatever.struct.x; rather, I just use struct.x no matter what the scope is, right? Do I therefore get an error if I try to make two structs with the same name from within different objects?
No, this is not correct. While the struct is a separate entity, it's still bound to the instance that created it by the variable the struct reference was assigned to.
 

Nathan

Member
I understand adding new programming to the game and handling scripts differently, but can't the current script system also coexist with the newer system so we don't have to relearn how to do all the scripts in our game?

Super super excited for the sequences (as a video editor I'm sure I'll have lots of feedback for that), and I also want to get the jump on things we will need to update in our game to make everything function on the new version. Applying now! Thanks!
 
Last edited:

drandula

Member
I understand adding new programming to the game and handling scripts differently, but can't the current script system also coexist with the newer system so we don't have to relearn how to do all the scripts in our game?

Also how do I apply to test it out? Super super excited for the sequences (as a video editor I'm sure I'll have lots of feedback for that), and I also want to get the jump on things we will need to update in our game to make everything function on the new version. Thanks!
You can basically use scripts as before, they just need add bit extra line which is easy to learn. Also GMS automatically creates these lines for you when you import 2.2 project to 2.3. Scripts can have many functions though, which is useful for organizing.
Look for first post and apply for beta, though queue might be long. It is currently in semi-open beta.
 

Cameron

Member
I'm loving all the new features! There is so much new goodness in 2.3 that YoYo probably could have gotten away with calling this 3.0. In a lot of ways this feels like more of an update than when we went to 2.0.

I just want to thank all the guys over at YoYo for listening to our requests and putting in the hard work overhauling everything to make this update a reality. I'm sure at times it's been stressful and I hope you guys know how much it's appreciated and that it's all been worth it.

Despite some of us complaining here this is a great update! From the ability to completely manipulate the asset tree to functions and structs this is huge in the ability for us to manage our projects, especially as they grow into behemoths. And I haven't even scratched the surface of sequences and animation curves. Great stuff guys, give yourself a pat on the back, you deserve it :)
 

Cameron

Member
What's the newest ticket id?
It's the weekend. There are no new ticket id's. If you would have taken the time to look at the thread you would have seen that the highest ticket number, so far reported, was mine at 169427.

Edit: Unless someone I've "ignored" posted on here with a higher number lol. But I've only "ignored" 6 people so that's unlikely.
 
Last edited:

Zhanghua

Member
It's the weekend. There are no new ticket id's. If you would have taken the time to look at the thread you would have seen that the highest ticket number, so far reported, was mine at 169427.

Edit: Unless someone I've "ignored" posted on here with a higher number lol. But I've only "ignored" 6 people so that's unlikely.
I should be waiting for the end of the month.
 

Zhanghua

Member
Is this an existed bug for static when overwriting the parent static method variable.
Or just syntax error?

@FrostyCat
@xDGameStudios



GML:
/////////////////////////
//////Public Script
function test_parent() constructor{
    static say = function(){ show_debug_message("say something...."); }
}

function test_child():test_parent() constructor{
  
    old_say = say;// If the old_say isn't static the project will be crashed when create two or more instance
    static say= function(){
        old_say();
        show_debug_message("say anything....");
    }
}

//BUG happened when creating two or more instances
///////////////////////
//////Object Create Event
temp = new test_child();

///////////////////////
//////Object Step Event
temp.say();
 
Last edited:

FrostyCat

Member
Is this an existed bug for static when overwriting the parent static method variable.
Or just syntax error?

@FrostyCat
@xDGameStudios



GML:
/////////////////////////
//////Public Script
function test_parent() constructor{
    static say = function(){ show_debug_message("say something...."); }
}

function test_child():test_parent() constructor{

    old_say = say;// If the old_say isn't static the project will be crashed when create two or more instance
    static say= function(){
        old_say();
        show_debug_message("say anything....");
    }
}

//BUG happened when creating two or more instances
///////////////////////
//////Object Create Event
temp = new test_child();

///////////////////////
//////Object Step Event
temp.say();
I'm able to reproduce this in runtimes 23.1.1.123 and 23.1.1.118, and this definitely looks like a contradiction against YoYo's previous advice. I will ask for an explanation in the closed beta forum. It could be a permanent change behind the scenes or an untested bug.
 

Zhanghua

Member
I'm able to reproduce this in runtimes 23.1.1.123 and 23.1.1.118, and this definitely looks like a contradiction against YoYo's previous advice. I will ask for an explanation in the closed beta forum. It could be a permanent change behind the scenes or an untested bug.
Thank you very much!
 
I can't believe what a difference these new GML features make! It's almost ridiculous...I don't even have the demo yet but I'm doing all these little tests in this thread refactoring parts of my game's code to get an idea of how to do things the new way and every single time I start coding, what feels like almost no time at all goes by and I'm like "ok, what's next...oh wait. I'm done. Huh...that's everything my old code did. And actually I bet I can throw this complete other part of my code in here if I just......"

I used to use an array of points like Points[0, point.x_off] for an enemy to follow for AI and it was this huge clunky thing. Then I also had an obj_ed_point for in my level editor, and that had a bunch of stuff in it that worked with an obj_ed_move that was a tool to select and drag points around with the mouse and had all this insane code in it to handle dragging things around, and all of this was just a huge bulky mess spread out all over different areas in my project.

I pretty much redid the entire point list thing in 10 minutes of just messing around, and then was like "I wonder if I can just throw mouse dragging stuff in there?" and 20 minutes later it's all there, looking super organized, elegant, and so minimalist compared to the bulky blocks of code I had spread out all over before.

And then as I was typing this post I was like "wait I bet I can also split out the mouse dragging stuff so that any object can become editable by just adding an edit component on" and did it in 2 minutes! (and then realized I could use an update_points and draw_points to avoid needing a loop in the obj_enemy and edited this post lol):
GML:
//--------------------------------------------------
//scr_points
//--------------------------------------------------
function Points() constructor {
    list_points = ds_list_create();

    add = function(x_off, _y_off) {
        var _index            = ds_list_size(list_points);
        list_points[| _index] = new Point(_index, _x_off, _y_off);
    }

    delete = function(_index) {
        ds_list_delete(list_points[| _index]);
    }
 
    cleanup = function() {
        ds_destroy(list_points, ds_type_list);
    }
 
    update_points = function(_id) {
        if (EDIT_MODE) {
            var _i = 0;
            repeat (ds_list_size(list_points)) {
                list_points[| _i++].update(_id);
            }
        }
    }

    draw_points = function(_id) {
        if (EDIT_MODE) {
            var _i = 0;
            repeat (ds_list_size(list_points)) {
                list_points[| _i++].draw(_id);
            }
        }
    }
}

function Point(_index_, x_off, _y_off) constructor {
    edit  = new Edit();
    index = _index;
    x_off = _x_off;
    y_off = _y_off;
 
    update = function(_id) {
        edit.check_mouse_drag(_id);
        edit.check_delete(_id);
    }
 
    draw = function(_id) {
        draw_circle(_id.x + x_off, _id.y + y_off, 10, true);
    }
}

function Edit() constructor {
    mouse_over = function(_id) {
        return point_distance(mouse_x, mouse_y, _id.x + x_off, _id.y + y_off) <= 5;
    }
 
    mouse_drag = function(_id) {
        if (mouse_over(_id)) && mouse_check_button(mb_left)) {
            if (mouse_check_button_pressed(mb_left)) {
                x_origin = x_off;
                y_origin = y_off;
            }
         
            x_off = x_origin + (mouse_x - x_off);
            y_off = y_origin + (mouse_y - y_off);
        }
    }
 
    check_delete = function(_id) {
        if (mouse_over(_id) && keyboard_check_pressed(vk_delete)) {
            _id.points.delete(index);
        }
    }
}

//--------------------------------------------------
//obj_enemy
//--------------------------------------------------
//Create Event
points = new Points();
points.add(  0,   0);
points.add(100,   0);
points.add(100, 100);
points.add(  0, 100);

//Step Event
points.update_points(_id);

//Draw Event
points.draw_points(_id);

//Cleanup Event
points.cleanup();
This honestly feels like cheating...the equivalent of this took me SO ****ing long before, you have no idea lol It's actually embarrassing to think about. And that code is so much more disorganized and hard to come back to & modify compared to this. I probably sound like a n00b gushing so much but these new features literally make coding FUN again instead of feeling like a grind on a large project. Like is THIS what devs using other languages have gotten to do all this time?? I now understand why the advanced guys have been bugging YoYo to add this stuff for so many years lol

Also I realize I could put the Point constructor directly inside the Points one's add function like so:
GML:
function Points() constructor {
    list_points = ds_list_create();

    add = function(x_off, _y_off) {
        var _index            = ds_list_size(list_points);
        list_points[| _index] = {
            edit  = new Edit();
            index = _index;
            x_off = _x_off;
            y_off = _y_off;

            update = function(_id) {
                edit.check_mouse_drag(_id);
                edit.check_delete(_id);
            }

            draw = function(_id) {
                draw_circle(_id.x + x_off, _id.y + y_off, 10, true);
            }
        }
    }
}
...but that feels like getting fancy for the sake of getting fancy which I swore off when I tried to come back to "super optimized minimalist" code that I thought was SO clever when I wrote it but had to spend an hour trying to figure out wtf it did when I came back to it months later lol and it feels like separating structs out will be easier for me to understand at a glance instead of cramming them in like this.

Three new questions after this experiment:

1) variable_struct_get_names() will return an array/list of the variables in the struct, right? Like with the above code it would return ["edit", "index", "x_off", "y_off"] to do stuff with? I'm assuming it's a slow operation you wouldn't want to do every frame, so if you knew you were going to need those you'd probably want to have a "var_names = variable_struct_get_names();" in there to use instead? But then you'd probably have to use variable_struct_set() to do anything with them, which I'm guessing is ALSO slow to do every frame...so I guess if you had to go through a bunch of options then an array with enums would probably be the faster option...do I understand this correctly?

2) @FrostyCat answered this earlier but just to clarify a detail of it, can I do this:
GML:
function point(_necessary_var, _optional_var) constructor {
    var1 = _necessary_var;
    var2 = (argument_count > 1 ? _optional_var : 100);//default value
                       //is this ^^^^^^^^^^^^^ allowed or does it HAVE to use ugly ol' argument[1] :( lol
                       //and if so then can this be a feature request to be able to do this? :) PLEASE!! :D
}
3) Is there a way to indicate a variable is optional? Like:
GML:
function point(_necessary_var, [_optional_var]) constructor {
 
Last edited:

Cpaz

Member
2) @FrostyCat answered this earlier but just to clarify a detail of it, can I do this:
GML:
function point(_necessary_var, _optional_var) constructor {
    var1 = _necessary_var;
    var2 = (argument_count > 1 ? _optional_var : 100);//default value
                       //is this ^^^^^^^^^^^^^ allowed or does it HAVE to use ugly ol' argument[1] :( lol
                       //and if so then can this be a feature request to be able to do this? :) PLEASE!! :D
}
This is absolutely possible and should work as you've written it IIRC.

To add to that:

3) Is there a way to indicate a variable is optional? Like:
GML:
function point(_necessary_var, [_optional_var]) constructor {
Every argument is technically optional. You will get no syntax error if you don't use an argument, nor will the compiler or runtime throw an error for not using an argument.

All that you need is to toss in an undefined check, and you should be good to go there. Now, whether or not that's performant, that's another story entirely.
 

NightFrost

Member
A question about 2.3 that is not about functions and structs for a change: has there been any significant feature additions to the room editor? I've noticed a few things I've missed to speed up work have been the ability to offset the grid, and having assets snap to grid by their sprite and bounding box edges, optimally as toggleable features.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
A question about 2.3 that is not about functions and structs for a change: has there been any significant feature additions to the room editor? I've noticed a few things I've missed to speed up work have been the ability to offset the grid, and having assets snap to grid by their sprite and bounding box edges, optimally as toggleable features.
IIRC, the room editor now has rulers, and things should be able to snap to them. Other than that though, no updates... However I believe the room editor will be getting a re-vamp sometime in the near-ish future.
 

NightFrost

Member
IIRC, the room editor now has rulers, and things should be able to snap to them. Other than that though, no updates... However I believe the room editor will be getting a re-vamp sometime in the near-ish future.
Yes, that doesn't sound like a solution I'm looking for. The use case I'm talking about: I might have sprites sized 32x32 - and their multiples - and I can quickly align them to a grid of same size, either as objects to object layers or as sprites to sprite layers. However not all sprites have their origin at bottom left because of 2.5D depth ordering system. When they snap by origin they are misaligned with the rest. Snapping by sprite edge would solve this.

I have a code solution to that in the meantime. All sprites have origins at bottom left, but I have a list of sprites that require custom origins and contains their values. When game starts, the origins get updated according to that list, and every ingame room's Room Start event calls a script that rifles through layers and repositions these sprites and objects with those sprites, as moving the origin has now repositioned them incorrectly. Only after that the 2.5D depth ordering system will run. It works, but one shouldn't have to jump through kludgy hoops like that.
 

FrostyCat

Member
The lightweight data structures library that I have been working on since the beginning of the month is finally complete: https://github.com/dicksonlaw583/LightweightDataStructures

There are a couple of regressions from the last runtime to the current one that prevents the library from showing its full potential. But at the very least it's ready for an open beta showing what the new OOP features can offer.
 

Bingdom

Googledom
I've been playing around with the beta lately, and I'm quite intrigued by some of the additions!

First of all, sequences have been well integrated! With the flexibility of animation curves to the modularity of sequences, it opens to great heights with componentized objects!
I can definitely see myself taking extensive use of these new features.

The improvement with asset management was a long-awaited change (at least on my part). It's good to finally see this get updated.

I haven't yet delved into the new GML improvements.

However, with all its glory, it does have a few downsides.

Animation curves
  • I would like to see a snapping feature through the editor.
  • The ability to import/export points, and to copy the points to the clipboard
Sequence Editor
  • Track panel: "Right click -> Add new track" is missing
Room Editor
  • The room editor tools appear to be behind the sequence editor. I would normally expect that the original editor would be modular internally to prevent such a thing from occurring.
 
The lightweight data structures library that I have been working on since the beginning of the month is finally complete: https://github.com/dicksonlaw583/LightweightDataStructures

There are a couple of regressions from the last runtime to the current one that prevents the library from showing its full potential. But at the very least it's ready for an open beta showing what the new OOP features can offer.
Awesome! List sort with callback is what I missed so much in GMS. Did you compare performance against built-in functions?
 

FrostyCat

Member
Awesome! List sort with callback is what I missed so much in GMS. Did you compare performance against built-in functions?
Not yet, I want to be more certain about its correctness before looking into its performance. Due to several regressions in runtime 23.1.1.123, I have been unable to run the test suite on YYC and HTML5 where I would like to know the most about performance impacts. I have a gut feeling it will be slower because it is on GML speed instead of native speed, but hopefully the possibilities it opens will be worth the expense.
 
1589908683558.png
1589908704117.png
Same game, much larger overhead for running the same code. I get that there is still a lot of work to be done because it is in the beta.... but 30% more memory and 100 fps hit is a little unnerving.
 

Dogarooski

Member
Same game, much larger overhead for running the same code. I get that there is still a lot of work to be done because it is in the beta.... but 30% more memory and 100 fps hit is a little unnerving.
I wouldn't worry too much about the memory since it's still relatively low and the extra memory is probably just from the garbage collector implementation. Also I wouldn't bother comparing VM performance, since the VM was never meant to be fast in the first place (that's why they maintain the YYC). In theory, the average steady-state framerate of the game should be higher when compared to the old reference counting method since, when a garbage collection isn't occurring, there isn't any reference counting code, which itself costs some time to execute but also has an instruction cache footprint that may be non-trivial. Also, memory allocations on a proper managed heap should be faster than before (virtually instantaneous) and array lookups have also been made faster. I think that if everything was implemented correctly, the average runtime performance of projects using 2.3 should be better.

The only thing, I think, that would make it worse is people abusing structs for superficial reasons like "namespacing". Also structs are slower than arrays, so while the old (albeit less readable) method of using arrays like structs should be even faster than before, structs would be even slower in both cases since it's a hash map lookup, and arrays are linear access without the chance of hash collisions. Structs would also use more memory than arrays.

Oh and I really hope that YoYo didn't implement function calls in the way that I think they did. I hope they just work the same as legacy script calls. I can't help but assume by the way that they've been described, that all function calls now also require a global variable lookup, which because of the way that global variables are implemented in the YYC (at least pre-2.3, unless it's been changed) would require a hash map lookup at the beginning of the calling function/event. These already sucked when you had some small helper scripts that you just wanted to be fast, because if they include some global variable lookups and now (possibly) function calls, they're not so small or fast anymore.

ok, i'm rambling. too much theory and now i'm banned.
 
Last edited:
Status
Not open for further replies.
Top