OFFICIAL GMS 2.3.0 BETA ANNOUNCEMENT

Status
Not open for further replies.

Canaan

Member
What a timing. :) Yesterday I finished my game and today I was thinking about starting a new game, but I didnt. My plan was to wait for v2.3. Guess what? Today I got my invite. Crazy timing.


but 1st I test if my old stuff works with 2.3
your ticket number?
 

Metroid3D

Member
Woo! Got in this morning. Looking forward to playing around with this.

Edit: #211 for those asking :)
 
Last edited:

Bruchpilot

Member
Please, people. When doing "hooray, I got in!!" postings, always include your ticket number :p (so that the less fortunate can estimate their position in the waiting line)
 

Mool

Member
NVM

What should I report, when I have multiple silent crashes?
Also Android Export has more errors then "Test"

I also get a lot of varialbe not defined, only for android and I cant fix it (variable_instante_exists return true. and variable_instance_get returns the value), but if i want to use that value it crahses -> var not defined. I dont know what I should write into my bug report and I dont want to upload my project to "public beta channel"
 
Last edited:
What should I report, when I have multiple silent crashes?
I had a silent runner crash with my module system library refactoring so I just submitted a report with the whole library code. That is not feasible if there is a not of (private) code, so maybe try to recreate a specific submodule (or approximation thereof) and see if you can reproduce the silent crash. If you can then you could use that to submit the report. But that can be quite a long shot.
 

Mool

Member
I slowly disabled all objects until I found the object with the problem. physics_fixture_bind() isn´t working.
 

zargy

Member
I would just like to point out the very important detail that I own the ticket number 169420. I await my invite with baited breath. This truly is a blessed week.
🙏🙏🙏
 

CursedToast

Member
A year ago I wrote most of the logic for a turn based RPG. Like the engine was basically done, you could clone OG Final Fantasy. It was a mess code-wise (and script-wise) and I kinda wandered off from the project.
All these updates seem like it could be made a *lot* more manageable! Very excited to get my hands on this.

Now allow us to make our own editor tools and I'll have everything I'll ever need for all my various projects! :D
Edit: A system like Unity's UI system would be really great too. Either or. I know both are probably years off, if ever happening but... ya know, either would make me never touch another game engine again. Since I've been using GM for 15 years now and am most comfortable with it!
 
Last edited:

kburkhart84

Firehammer Games
Now allow us to make our own editor tools and I'll have everything I'll ever need for all my various projects! :D
Edit: A system like Unity's UI system would be really great too. Either or. I know both are probably years off, if ever happening but... ya know, either would make me never touch another game engine again. Since I've been using GM for 15 years now and am most comfortable with it!
I remember seeing that they were going to eventually do something like this. And I've been mentioning everywhere it could come up as well, maybe even a couple times in this very topic. I could have my input system's configuration program be part of the IDE...I have both an audio and particle system I'm probably going to do at some point, and both of those could also have components be part of the IDE itself.
 
Ok so I don't have the beta yet but I'm trying to wrap my head around this whole thing...say I'm making a shmup where enemy ships go from waypoint to waypoint, and I'm trying to be organized with parenting/classes, so the idea is:
- the obj_enemy_ship contains an Enemy struct
- and the Enemy struct contains some enemy related vars and an Entity struct and ds_list of Waypoint structs
- and the Entity struct contains a Bbox struct

meaning a bullet could just use the Entity and/or Bbox structs, a non-interactive bird flying by could just use Waypoints etc

...but do I understand this at ALL?? lol I'm sure my syntax is wrong but is this the right general idea of using structs and functions inside them conceptually?

GML:
//scr_bboxes
function Bbox(_x, _y, _width, _height) constructor {
    x:      _x;
    y:      _y;
    width:  _width;
    height: _height;

    update: function(_x, _y) {
        x1 = _x + x;
        y1 = _y + y;
        x2 = _x + x + width;
        y2 = _y + y + width;
    }
}

//scr_entities
function Entity() constructor {
    can_collide: false;
    bbox:        new Bbox(x, y, sprite_width, sprite_height);
}

//scr_waypoints
function Waypoint(_x, _y) constructor {
    x = _x;
    y = _y;

    //so add/delete waypoints can't go here cause that affects the parent's list of these structs
    //but something like update could because it only affects the data in this struct:
    update: function(_x, _y) {
        x += _x;
        y += _y;
    }
}

//scr_enemies
function Enemy() constructor {
    //misc stuff like hp, damage, score, all the stuff that would normally just be a mess of loose instance variables
    hp:     1;
    damage: 1;

    //is this where you'd add this if all Enemies are also Entities?
    entity: new Entity();
    entity.can_collide = true;//so I could set this here to make any obj with the Enemy struct collidable
                              //aka a "new Struct()"'s vars are immediately accessible even inside another struct?

    //waypoint stuff
    static waypoints: ds_list_create();//is this the kind of place you'd use static?

    add_waypoint: function(_x, _y) {
        waypoints[| ds_list_size(waypoints)] = new Waypoint(_x, _y);
    }

    move_waypoint: function(_index, _dist_x, _dist_y) {
        waypoints[| _index].x += _dist_x;//so you can just call the .x from here?
        waypoints[| _index].y += _dist_y;
    }

    update_all_waypoints: function(_dist_x, _dist_y) {
        var _index = 0;
        repeat (ds_list_size(waypoints)) {
            waypoints[| _index++].update(_dist_x, _dist_y);//so this can call .update inside the Waypoint struct?
        }
    }

    draw_all_waypoints: function() {//so you could put draw events in here to use in Draw Events or on surfaces etc?
        var _index = 0;
        repeat (ds_list_size(waypoints)) {
            draw_sprite(spr_waypoint, waypoints[| _index].x, waypoints[| _index].y);
            _index++;
        }
    }

    //these couldn't go in the Waypoint struct because they modifies the parent that the Waypoint structs are in?
    delete_waypoint:      function(_index) {ds_list_remove(waypoints[| _index]);}
    delete_all_waypoints: function(_index) {ds_list_clear(waypoints);}
    cleanup_waypoints:    function()       {ds_destroy(waypoints[_index], ds_list);}
}

//--------------------------------------------------
//obj_enemy_ship
//--------------------------------------------------
//Create Event
enemy        = new Enemy();            //so this "enemy" variable would be where everything below ends up contained and is how to access it?
enemy.hp     = 100;                    //like this is how I would customize the default values the struct inside enemy made, right?
enemy.damage = 1000;
show_message(enemy.entity.can_collide);//this var is in the Entity struct so it would have to be accessed like this right?

//Step Event
if (keyboard_check(vk_space)) {
    enemy.waypoints.add_waypoint(x, y);        //add a waypoint where this obj is
}
enemy.waypoints.update_all_waypoints(100, 100);//add +100/+100 to x/y of all points
enemy.waypoints.move_waypoint(0, 100, 100);    //move waypoint 0 to +100/+100 x/y
enemy.entity.bbox.update(x, y);                //this is how I would reach the bbox's update event right?

//Draw Event
if (DEBUG) {enemy.draw_all_waypoints();}

//--------------------------------------------------

//would doing stuff to obj_enemy_ship from inside some other enemy object be like this where you go through the objs' "enemy" var that was made a "new Enemy()"?
if (scr_collision_check(enemy.entity.bbox, obj_enemy_ship.enemy.entity.bbox)) {
    obj_enemy_ship.hp -= enemy.damage;
}
Because if this is the type of thing we can do now...that's pretty damn epic. I've been using a bunch of enums and functions that are look like "///@arg index, then of course _index = argument0; just to use it in an obnoxious array like Waypoints[_index, waypoint.x] += other.Waypoints[_index + 1, waypoint.x]" and all this cumbersome code...

...but can it really be as simple as this kind of thing? Is there an even easier way to do this kind of thing? Some kind of nesting structs inside structs? Are these the right idea conceptually of where functions inside structs would go and the kind of things you can do with them?

I hope I'm on the right track because the way I've been doing the equivalent of this looks absolutely ridiculous compared to how little code this is and how clean it looks lol if my code could legit look anything like THIS, it would be pretty much impossible to NOT rewrite my game when I get my hands on 3.2!
 
Last edited:

FrostyCat

Member
...but can it really be as simple as this kind of thing? Is there an even easier way to do this kind of thing? Some kind of nesting structs inside structs? Are these the right idea conceptually of where functions inside structs would go and the kind of things you can do with them?
Of course structs are composable, that's one of its main points. Composition over inheritance. What you're doing now is exactly what the new OOP features are meant to facilitate, and there will be many more patterns coming as people get experience using them.
 
Of course structs are composable, that's one of its main points. Composition over inheritance. What you're doing now is exactly what the new OOP features are meant to facilitate, and there will be many more patterns coming as people get experience using them.
This is beyond awesome then! I'm almost stunned in my cpu chair just thinking about how much of my code I could throw out, especially all the workaround stuff I was doing to try to sort of awkwardly do this kind of thing and now it's just like "nah, now you can just do it in the most obvious simple way with minimal code" lol

It took me forever to code the equivalent of the above and now with these new features it's like oh ok I just rewrote the jist of hours of coding in like 10 min. I'm SO pumped for this update now!

On an unrelated note: does anyone know if Sequences basically make Paths obsolete now? I was using paths with point_add etc in code to set up enemy patterns, but if you can add points to a Sequence via code and adjust bezier curves etc then it seems like that's basically the same thing...?
 

FrostyCat

Member
On an unrelated note: does anyone know if Sequences basically make Paths obsolete now? I was using paths with point_add etc in code to set up enemy patterns, but if you can add points to a Sequence via code and adjust bezier curves etc then it seems like that's basically the same thing...?
It replaces a lot of the functionalities on a practical level, but not all of them. For example, motion planning functions still create paths as output.
 
It replaces a lot of the functionalities on a practical level
That's how it seems, I can think of a TON of stuff I would redo completely now. The possibilities seem endless and my example code there probably isn't even the most efficient best practice way to use this stuff.

One thing I wondered while I was typing it out is we can normally do stuff like:

GML:
//argument[1] is optional, the default is 60:
var _delay = (arugment_count > 1 ? argument[1] : 60);

//But with the way these functions have the args instantly assigned, are optional args still possible?  Like:
Struct = {
    whatever: 0;
    draw_sprite: function(_spr_index, _x, _y, [_x_scale], [_y_scale], [_is_flipped]) {
        //draw_sprite();
    }
}

//so that you could leave some args off like:
Struct.draw_sprite(spr_enemy, 100, 100)
And are the vars defined in the function brackets all local to that function? So if you wanted one of them to be made an instance variable you'd want to do like "is_flipped = _is_flipped;" (I assume this is the case, sorry if it's been asked or answered lol just trying to get this straight in my head to think on)
 

FrostyCat

Member
One thing I wondered while I was typing it out is we can normally do stuff like:

GML:
//argument[1] is optional, the default is 60:
var _delay = (arugment_count > 1 ? argument[1] : 60);

//But with the way these functions have the args instantly assigned, are optional args still possible? Like:
Struct = {
whatever: 0;
draw_sprite: function(_spr_index, _x, _y, [_x_scale], [_y_scale], [_is_flipped]) {
//draw_sprite();
}
}

//so that you could leave some args off like:
Struct.draw_sprite(spr_enemy, 100, 100)
And are the vars defined in the function brackets all local to that function? So if you wanted one of them to be made an instance variable you'd want to do like "is_flipped = _is_flipped;" (I assume this is the case, sorry if it's been asked or answered lol just trying to get this straight in my head to think on)
Optional arguments in series are still done the old way, with argument_count and argument[]. The only difference is that we can name the required section.
GML:
static drawSprite = function(_spr_index, _x, _y) {
    var _is_flipped = false,
        _y_scale = 1,
        _x_scale = 1;
    switch (argument_count) {
        case 6: _is_flipped = argument[5];
        case 5: _y_scale = argument[4];
        case 4: _x_scale = argument[3];
        case 3: break;
        default: show_error("Expected 3-6 arguments, got " + string(argument_count) + ".", true);
    }
    draw_sprite_ext(_spr_index, 0, _x, _y, _is_flipped ? -_x_scale : _x_scale, _y_scale, c_white, 0);
}
But the real breakthrough is this new book line for named optional arguments, which any self-respecting JS developer will recognize. It'll involve one helper which JS comes preloaded with (Object.assign()), but needs manual intervention in GML for now:
GML:
///@func struct_merge(@target, source)
///@param @target
///@param source
function struct_merge(target, source) {
    var sourceKeys = variable_struct_get_names(source);
    for (var i = array_length(sourceKeys)-1; i >= 0; --i) {
        var key = sourceKeys[i],
            val = variable_struct_get(source, key);
        variable_struct_set(target, key, val);
    }
}
return target;
And it looks like this:
GML:
static drawSprite = function(_spr_index, _x, _y) {
    var opt = {
        isFlipped: false,
        yScale: 1,
        xScale: 1
    };
    switch (argument_count) {
        case 4:
            struct_merge(opt, argument[3]);
        case 3: break;
        default: show_error("Expected 3-4 arguments, got " + string(argument_count) + ".", true);
    }
    draw_sprite_ext(_spr_index, 0, _x, _y, opt.isFlipped ? -opt.xScale : opt.xScale, opt.yScale, c_white, 0);
}
GML:
drawSprite(sprite_index, x, y, { isFlipped: true })
 
GML:
drawSprite(sprite_index, x, y, { isFlipped: true })
I didn't understand where you were going with that until I got to this line and that immediately cleared it up. So you could just change the relevant optional args and not worry about filling in the ones that don't change from the default. Very interesting stuff, one of my pet peeves is having to fill in all the optional args to get to the one I actually want to change. Thanks for writing up the example! This whole thing is going to be such a paradigm shift for those of us with only GML experience!
 

Lukan

Gay Wizard Freak
For people asking about porting, I ported a copy of Homestead over...
All of the code works, but the game runs poorly because of a lot of convoluted converted scripts, and a single event was deleted from one of my objects causing weird behaviour.
Overall it worked, but I won't be working in 2.3 for HS any time soon until I can manually port my code.
 

Mool

Member
GML:
function Debug(_inst) constructor{
   
    inst = _inst;
   
    static Log = function(log) {
           
    }
   
    static LogError = function (log) {
        Log(log); // ERROR NOT WORKING
    }
   
    static LogWarning = function (log) {
        Log(log); // ERROR NOT WORKING
    }
   
}
This isnt possible?
 

kburkhart84

Firehammer Games
@Moo Why are you making the other functions static, and within the other function's creation? Are you just messing around or is there a reason?
 

FrostyCat

Member
GML:
function Debug(_inst) constructor{
  
    inst = _inst;
  
    static Log = function(log) {
          
    }
  
    static LogError = function (log) {
        Log(log); // ERROR NOT WORKING
    }
  
    static LogWarning = function (log) {
        Log(log); // ERROR NOT WORKING
    }
  
}
This isnt possible?
Not only is it possible, it can also be done better.

Function aliases should not go through an additional function call. The book line is to set them directly to the original.
GML:
function Debug(_inst) constructor {
    inst = _inst;
    
    static Log = function(log) {
        ...
    }
    static LogError = Log;
    static LogWarning = Log;
}
 

FoxyOfJungle

Kazan Games
draw_sprite_ext(_spr_index, 0, _x, _y, _is_flipped ? -_x_scale : _x_scale, _y_scale, c_white, 0);
I always see the character "?", But even looking in the manual, I didn't quite understand what the "?" does. I use it on ds_maps but involuntarily lol
GML:
async_load[? "status"]
Maybe the "?" have different functions in each context, but I was wondering how it works.
 

Mool

Member
OK yes it works, but GMS shows these 2 lines RED. So its a bug.

I just test the new stuff to understand everything.

Soemthing like this was the plan:

GML:
function Debug(_inst) constructor{
 
    inst = _inst;
 
    static Log = function(log) {
         
        var _s = "";
        for (var _i=0; _i<argument_count; _i++) {    
            _s += string (argument[_i]) + ", ";
        }
     
        show_debug_message (_s + " (" +object_get_name(inst.object_index)+ ")");            
    }
 
    static LogError = function (log) {
        Log("ERROR", log); // number of arguments expected 0 got 2
    }
 
    static LogWarning = function (log) {
        Log("WARRNING", log); // number of arguments expected 0 got 2
    }
 
}
@FoxyOfJungle its a accessor: u access the value inside of the map with the key "status"

OR a simple if:

var gg = 1>2 ? "yes" : "no";

same like

var gg;
if (1>2) {
gg = "yes";
}else{
gg = "no";
}
 

FoxyOfJungle

Kazan Games
@FoxyOfJungle its a accessor: u access the value inside of the map with the key "status"

OR a simple if:

var gg = 1>2 ? "yes" : "no";

same like

var gg;
if (1>2) {
gg = "yes";
}else{
gg = "no";
}
Thank you!
Ashamed of myself for not knowing it was that. But, living and learning 😁
I don't think I've ever seen this page: https://docs2.yoyogames.com/source/_build/3_scripting/3_gml_overview/13_accessors.html

Edit:
I was doing some performance tests, and I performed the function 20 times in different ways, I got this:

ds_map_add(_map, "obj", _obj); //(20 times)
Time: 1 ms

_map[? "obj"] = _obj; //(20 times)
Time: 8 ms

So in my case, using accessors is slower than the function name.


EDIT2:

The code i've used:
GML:
var __p_time = current_time;
with (all)
{
    //Search
    switch (object_index)
    {
        case obj_game_controller:
            var _map = ds_map_create();
            ds_list_add(_root_list,_map);
            ds_list_mark_as_map(_root_list,ds_list_size(_root_list)-1);
            var _obj = object_get_name(object_index);
            ds_map_add(_map, "obj", _obj);
            ds_map_add(_map, "AC_nickname", global.AC_nickname);
            ds_map_add(_map, "ST_Volume_Music", global.ST_Volume_Music);
            ds_map_add(_map, "ST_Volume_SFX", global.ST_Volume_SFX);
            ds_map_add(_map, "variable", global.VARIABLE);
            ds_map_add(_map, "DN_hour", global.DN_hour);
            ds_map_add(_map, "DN_minute", global.DN_minute);
            ds_map_add(_map, "DN_second", global.DN_second);
            ds_map_add(_map, "DN_day", global.DN_day);
            ds_map_add(_map, "GC_xp_limite", global.GC_xp_limite);
            ds_map_add(_map, "GC_xp", global.GC_xp);
            ds_map_add(_map, "GC_game_level", global.GC_game_level);
            ds_map_add(_map, "GC_money", global.GC_money);
            ds_map_add(_map, "GC_quantity_booths", global.GC_quantity_booths);
            ds_map_add(_map, "GC_quantity_characters", global.GC_quantity_characters);
            ds_map_add(_map, "GC_quantity_staffs", global.GC_quantity_staffs);
            ds_map_add(_map, "GC_mission_text", global.GC_mission_text);
            ds_map_add(_map, "GC_crystal", global.GC_crystal);
            ds_map_add(_map, "GC_popularity", global.GC_popularity);
          
          
            break;
      
      
        case obj_build_0:
            var _map = ds_map_create();
            ds_list_add(_root_list,_map);
            ds_list_mark_as_map(_root_list,ds_list_size(_root_list)-1);
            var _obj = object_get_name(object_index);
            ds_map_add(_map, "obj", _obj);
            ds_map_add(_map, "x", x);
            ds_map_add(_map, "y", y);
            break;
          
        case obj_character_0:
            var _map = ds_map_create();
            ds_list_add(_root_list,_map);
            ds_list_mark_as_map(_root_list,ds_list_size(_root_list)-1);
            var _obj = object_get_name(object_index);
            ds_map_add(_map, "obj", _obj);
            ds_map_add(_map, "x", x);
            ds_map_add(_map, "y", y);
            break;
      
      
    }
}
show_debug_message("Game Saved,   Time: "+string(current_time-__p_time)+string(" ms"));

I had replaced ds_map_add() with the map[? "key"] = value syntax and then returned the time it took to run in ms.
 
Last edited:

TheMagician

Member
I was doing some performance tests, and I performed the function 20 times in different ways, I got this:

ds_map_add(_map, "obj", _obj); //(20 times)
Time: 1 ms

_map[? "obj"] = _obj; //(20 times)
Time: 8 ms

So in my case, using accessors is slower than the function name.
... That's the first time I've heard that using accessors is slower than using the function calls. Can anybody confirm that?
 
... That's the first time I've heard that using accessors is slower than using the function calls. Can anybody confirm that?
No. Any difference is likely due to flawed testing. My personal testing repeated each 100,000 times and got 33.797ms for the function and 33.755ms for the accessor. That's so far within the margin of error, it's likely the compiler renders both of those down to the exact same machine code.

If you're interested, this is the exact code I used:
GML:
var _map = ds_map_create();
_map[? "key"] = 1;

var _time = get_timer();
repeat(100000) {
  ds_map_add(_map, "key", 1);
}
var _funcTime = get_timer()-_time;
_time = get_timer();
repeat(100000) {
  _map[? "key"] = 1;
}
var _accessorTime = get_timer()-_time;
show_debug_message("Function time: " + string(_funcTime/1000) + "ms");
show_debug_message("Accessor time: " + string(_accessorTime/1000) + "ms");

EDIT: I just realized this was the 2.3 beta page. Sorry! I haven't tested on 2.3, but if it is significantly slower, it's likely a bug and it should be reported.
 

❤️×1

Member
... That's the first time I've heard that using accessors is slower than using the function calls. Can anybody confirm that?
I wanted to benchmark 2.3 struct against map and array anyway, so this worked as my excuse to actually do it.
Of course, struct ain't just another way to stock data and really shines when combined with methods, but I was curious.
The was more of a sanity check, don't really take it into account since the randomization overhead is HUGE.
Code:
Pass 0-----------
    map: 258329
    struct: 206512
    array: 196004
Pass 1-----------
    map: 249861
    struct: 205671
    array: 187195
Pass 2-----------
    map: 246255
    struct: 211015
    array: 187860
Pass 3-----------
    map: 247060
    struct: 206290
    array: 189142
Pass 4-----------
    map: 248114
    struct: 212821
    array: 190221
Pass 5-----------
    map: 247831
    struct: 218212
    array: 193370
Pass 6-----------
    map: 247892
    struct: 217631
    array: 195885
Pass 7-----------
    map: 261897
    struct: 214624
    array: 190072
Pass 8-----------
    map: 259153
    struct: 211199
    array: 201014
Pass 9-----------
    map: 253197
    struct: 229570
    array: 198164
Code:
Pass 0-----------
    map: 316538
    map accessed by function: 328345
    struct: 138899
    with struct: 119677
    array: 54116
Pass 1-----------
    map: 304469
    map accessed by function: 299815
    struct: 135608
    with struct: 123433
    array: 52500
Pass 2-----------
    map: 297015
    map accessed by function: 303408
    struct: 134754
    with struct: 131223
    array: 53490
Pass 3-----------
    map: 299641
    map accessed by function: 304475
    struct: 135153
    with struct: 122584
    array: 52407
Pass 4-----------
    map: 294237
    map accessed by function: 299402
    struct: 159301
    with struct: 119078
    array: 51999
Pass 5-----------
    map: 304547
    map accessed by function: 300286
    struct: 134495
    with struct: 119751
    array: 60163
Pass 6-----------
    map: 302762
    map accessed by function: 297458
    struct: 133994
    with struct: 118688
    array: 51988
Pass 7-----------
    map: 294058
    map accessed by function: 303612
    struct: 148307
    with struct: 118568
    array: 52939
Pass 8-----------
    map: 294002
    map accessed by function: 323402
    struct: 133869
    with struct: 118641
    array: 52587
Pass 9-----------
    map: 296252
    map accessed by function: 299672
    struct: 134955
    with struct: 121007
    array: 52435
Code:
Pass 0-----------
    map: 723849
    map accessed by function: 741074
    struct: 329586
    with struct: 170049
    array: 139744
Pass 1-----------
    map: 722852
    map accessed by function: 737261
    struct: 327872
    with struct: 169855
    array: 121502
Pass 2-----------
    map: 737114
    map accessed by function: 753831
    struct: 327810
    with struct: 168231
    array: 120623
Pass 3-----------
    map: 744915
    map accessed by function: 733853
    struct: 337143
    with struct: 169559
    array: 121175
Pass 4-----------
    map: 742106
    map accessed by function: 727906
    struct: 351464
    with struct: 172806
    array: 131947
Pass 5-----------
    map: 729686
    map accessed by function: 735416
    struct: 330499
    with struct: 169682
    array: 122051
Pass 6-----------
    map: 728468
    map accessed by function: 760713
    struct: 331846
    with struct: 167872
    array: 120164
Pass 7-----------
    map: 722664
    map accessed by function: 732119
    struct: 345438
    with struct: 169081
    array: 122494
Pass 8-----------
    map: 737737
    map accessed by function: 746370
    struct: 350409
    with struct: 172628
    array: 119899
Pass 9-----------
    map: 732860
    map accessed by function: 739210
    struct: 332875
    with struct: 169518
    array: 120428
Code:
Pass 0-----------
    map: 319511
    map accessed by function: 367042
    struct: 134470
    with struct: 112746
    array: 72687
Pass 1-----------
    map: 306319
    map accessed by function: 367906
    struct: 130223
    with struct: 111468
    array: 72913
Pass 2-----------
    map: 316048
    map accessed by function: 385350
    struct: 131108
    with struct: 109193
    array: 72497
Pass 3-----------
    map: 305522
    map accessed by function: 383043
    struct: 131336
    with struct: 113999
    array: 73227
Pass 4-----------
    map: 313381
    map accessed by function: 372457
    struct: 135035
    with struct: 108280
    array: 79624
Pass 5-----------
    map: 317718
    map accessed by function: 368067
    struct: 132107
    with struct: 127816
    array: 70322
Pass 6-----------
    map: 311416
    map accessed by function: 357770
    struct: 129977
    with struct: 108494
    array: 76749
Pass 7-----------
    map: 304051
    map accessed by function: 377042
    struct: 146378
    with struct: 114365
    array: 75639
Pass 8-----------
    map: 299218
    map accessed by function: 366013
    struct: 129278
    with struct: 119734
    array: 84670
Pass 9-----------
    map: 305924
    map accessed by function: 355591
    struct: 132519
    with struct: 112794
    array: 72396
Code:
Pass 0-----------
    map: 756196
    map accessed by function: 1174801
    struct: 318115
    with struct: 156352
    array: 181299
Pass 1-----------
    map: 740334
    map accessed by function: 1170012
    struct: 320246
    with struct: 182190
    array: 179462
Pass 2-----------
    map: 737950
    map accessed by function: 1179407
    struct: 328586
    with struct: 173651
    array: 155087
Pass 3-----------
    map: 739415
    map accessed by function: 1173832
    struct: 321683
    with struct: 163920
    array: 164304
Pass 4-----------
    map: 762839
    map accessed by function: 1180268
    struct: 320585
    with struct: 179227
    array: 179208
Pass 5-----------
    map: 737317
    map accessed by function: 1157529
    struct: 318574
    with struct: 180404
    array: 174690
Pass 6-----------
    map: 745101
    map accessed by function: 1182683
    struct: 319861
    with struct: 154282
    array: 173774
Pass 7-----------
    map: 756132
    map accessed by function: 1165911
    struct: 321718
    with struct: 157397
    array: 172814
Pass 8-----------
    map: 732872
    map accessed by function: 1169237
    struct: 318989
    with struct: 159125
    array: 176293
Pass 9-----------
    map: 739628
    map accessed by function: 1177624
    struct: 326360
    with struct: 167050
    array: 177005
There you go~
Surprisingly, when it comes to read, function and accessor are really close, sometimes function even came first... It's withing margin of error anyway. That said, when writing, accessor are 40 to 50% faster than the function equivalent.
 
Last edited:

Homunculus

Member
@FoxyOfJungle If you really want to compare the accessor to the function, you should use ds_map_set, not add. Add is for adding values when the key is not present, not sure what happens when it’s already there (although I remember in very old versions of gm it essentially “stacked up” the value with the same key multiple times).

I suggest re-running the test with set instead.

@❤×1 did you use add or set for yours?
 
Last edited:

❤️×1

Member
@FoxyOfJungle If you really want to compare the accessor to the function, you should use ds_map_set, not add. Add is for adding values when the key is not present, not sure what happens when it’s already there (although I remember in very old versions of gm it essentially “stacked up” with the same key multiple times).

I suggest re-running the test with set instead.

@❤×1 did you use add or set for yours?
Oh, I used add. Honestly, I never used function so I didn't even knew about set...
Rerun the tests, I'm a bit too lazy to make a whole new post with the new results, but indeed ds_map_set gets within margin of error of the accessor time.
 
Last edited:

Nocturne

Friendly Tyrant
Forum Staff
Admin
Moderator

Zhanghua

Member
I wanted to benchmark 2.3 struct against map and array anyway, so this worked as my excuse to actually do it.
Of course, struct ain't just another way to stock data and really shines when combined with methods, but I was curious.
The was more of a sanity check, don't really take it into account since the randomization overhead is HUGE.
Code:
Pass 0-----------
    map: 258329
    struct: 206512
    array: 196004
Pass 1-----------
    map: 249861
    struct: 205671
    array: 187195
Pass 2-----------
    map: 246255
    struct: 211015
    array: 187860
Pass 3-----------
    map: 247060
    struct: 206290
    array: 189142
Pass 4-----------
    map: 248114
    struct: 212821
    array: 190221
Pass 5-----------
    map: 247831
    struct: 218212
    array: 193370
Pass 6-----------
    map: 247892
    struct: 217631
    array: 195885
Pass 7-----------
    map: 261897
    struct: 214624
    array: 190072
Pass 8-----------
    map: 259153
    struct: 211199
    array: 201014
Pass 9-----------
    map: 253197
    struct: 229570
    array: 198164
Code:
Pass 0-----------
    map: 316538
    map accessed by function: 328345
    struct: 138899
    with struct: 119677
    array: 54116
Pass 1-----------
    map: 304469
    map accessed by function: 299815
    struct: 135608
    with struct: 123433
    array: 52500
Pass 2-----------
    map: 297015
    map accessed by function: 303408
    struct: 134754
    with struct: 131223
    array: 53490
Pass 3-----------
    map: 299641
    map accessed by function: 304475
    struct: 135153
    with struct: 122584
    array: 52407
Pass 4-----------
    map: 294237
    map accessed by function: 299402
    struct: 159301
    with struct: 119078
    array: 51999
Pass 5-----------
    map: 304547
    map accessed by function: 300286
    struct: 134495
    with struct: 119751
    array: 60163
Pass 6-----------
    map: 302762
    map accessed by function: 297458
    struct: 133994
    with struct: 118688
    array: 51988
Pass 7-----------
    map: 294058
    map accessed by function: 303612
    struct: 148307
    with struct: 118568
    array: 52939
Pass 8-----------
    map: 294002
    map accessed by function: 323402
    struct: 133869
    with struct: 118641
    array: 52587
Pass 9-----------
    map: 296252
    map accessed by function: 299672
    struct: 134955
    with struct: 121007
    array: 52435
Code:
Pass 0-----------
    map: 723849
    map accessed by function: 741074
    struct: 329586
    with struct: 170049
    array: 139744
Pass 1-----------
    map: 722852
    map accessed by function: 737261
    struct: 327872
    with struct: 169855
    array: 121502
Pass 2-----------
    map: 737114
    map accessed by function: 753831
    struct: 327810
    with struct: 168231
    array: 120623
Pass 3-----------
    map: 744915
    map accessed by function: 733853
    struct: 337143
    with struct: 169559
    array: 121175
Pass 4-----------
    map: 742106
    map accessed by function: 727906
    struct: 351464
    with struct: 172806
    array: 131947
Pass 5-----------
    map: 729686
    map accessed by function: 735416
    struct: 330499
    with struct: 169682
    array: 122051
Pass 6-----------
    map: 728468
    map accessed by function: 760713
    struct: 331846
    with struct: 167872
    array: 120164
Pass 7-----------
    map: 722664
    map accessed by function: 732119
    struct: 345438
    with struct: 169081
    array: 122494
Pass 8-----------
    map: 737737
    map accessed by function: 746370
    struct: 350409
    with struct: 172628
    array: 119899
Pass 9-----------
    map: 732860
    map accessed by function: 739210
    struct: 332875
    with struct: 169518
    array: 120428
Code:
Pass 0-----------
    map: 319511
    map accessed by function: 367042
    struct: 134470
    with struct: 112746
    array: 72687
Pass 1-----------
    map: 306319
    map accessed by function: 367906
    struct: 130223
    with struct: 111468
    array: 72913
Pass 2-----------
    map: 316048
    map accessed by function: 385350
    struct: 131108
    with struct: 109193
    array: 72497
Pass 3-----------
    map: 305522
    map accessed by function: 383043
    struct: 131336
    with struct: 113999
    array: 73227
Pass 4-----------
    map: 313381
    map accessed by function: 372457
    struct: 135035
    with struct: 108280
    array: 79624
Pass 5-----------
    map: 317718
    map accessed by function: 368067
    struct: 132107
    with struct: 127816
    array: 70322
Pass 6-----------
    map: 311416
    map accessed by function: 357770
    struct: 129977
    with struct: 108494
    array: 76749
Pass 7-----------
    map: 304051
    map accessed by function: 377042
    struct: 146378
    with struct: 114365
    array: 75639
Pass 8-----------
    map: 299218
    map accessed by function: 366013
    struct: 129278
    with struct: 119734
    array: 84670
Pass 9-----------
    map: 305924
    map accessed by function: 355591
    struct: 132519
    with struct: 112794
    array: 72396
Code:
Pass 0-----------
    map: 756196
    map accessed by function: 1174801
    struct: 318115
    with struct: 156352
    array: 181299
Pass 1-----------
    map: 740334
    map accessed by function: 1170012
    struct: 320246
    with struct: 182190
    array: 179462
Pass 2-----------
    map: 737950
    map accessed by function: 1179407
    struct: 328586
    with struct: 173651
    array: 155087
Pass 3-----------
    map: 739415
    map accessed by function: 1173832
    struct: 321683
    with struct: 163920
    array: 164304
Pass 4-----------
    map: 762839
    map accessed by function: 1180268
    struct: 320585
    with struct: 179227
    array: 179208
Pass 5-----------
    map: 737317
    map accessed by function: 1157529
    struct: 318574
    with struct: 180404
    array: 174690
Pass 6-----------
    map: 745101
    map accessed by function: 1182683
    struct: 319861
    with struct: 154282
    array: 173774
Pass 7-----------
    map: 756132
    map accessed by function: 1165911
    struct: 321718
    with struct: 157397
    array: 172814
Pass 8-----------
    map: 732872
    map accessed by function: 1169237
    struct: 318989
    with struct: 159125
    array: 176293
Pass 9-----------
    map: 739628
    map accessed by function: 1177624
    struct: 326360
    with struct: 167050
    array: 177005
There you go~
Surprisingly, when it comes to read, function and accessor are really close, sometimes function even came first... It's withing margin of error anyway. That said, when writing, accessor are 40 to 50% faster than the function equivalent.
So, finnally, the array is the winner, so why do we use the 2.3..........
 

Zhanghua

Member
What a silly statement.
If the access efficiency is so poor, the tiny and regular code implementation is unnecessary to use the struct.

Why we want the struct? Cause we want more OOP or IOP to make the member access ease.

I mean and want that the struct should have the similar efficiency with array as like as the C or CPP's doing.

So that's just a silly moan and slight disappointment of this uneasy ease!
 
Last edited:

chamaeleon

Member
If the access efficiency is so poor, the tiny and regular code implementation is unnecessary to use the struct.

Why we want the struct? Cause we want more OOP or IOP to make the member access ease.

I mean and want that the struct should have the similar efficiency with array as like as the C or CPP's doing.

So that's just a silly moan and slight disappointment of this uneasy ease!
Do you often use hammers for cutting wood?
 

Zhanghua

Member
Do you often use hammers for cutting wood?
I'm so curious about the complexity and efficacy of your implementation of the user inventory in the 2.2.5.

I have made an inventory in the runtime arpg by the ds_map while the RealFps is down to about 500. And then made refraction with the array, the FPS is up to 2000.

So I want to use the advanced data structure, but the REALFPS prevents me to do that...
 
Last edited:

Hyomoto

Member
I'm so curious about the complexity and efficacy of your implementation of the user inventory in the 2.2.5.

I have made an inventory in the runtime arpg by the ds_map while the RealFps is down to about 500. And then made refraction with the array, the FPS is up to 2000.

So I want to use the advanced data structure, but the REALFPS prevents me to do that...
I would invert that, I'm curious about the complexity and efficacy of your implementation of the user inventory. I use a walkable node-based structure that uses maps and lists. It's fairly expensive because it must chop up a string and walk down the path from the source node to find the data requested. However, I'm not doing it 1000x every frame or yeah, it would definitely kill my frame rate. Rather I do it once, and then I don't do it again until something changes and even then I only update the things that changed so not everything has to be looked up from scratch. If I have a particularly expensive lookup, I'll walk to the source node so subsequent lookups don't have to start from the beginning of the database, etc... Hell, my battle system relies on a complex scripting system that also relies on those database lookups and happens in real-time, and it's still not expensive enough to need an alternative even though a single ability might perform dozens of lookups in addition to having to calculate and make comparisons.

It's like pathfinding: your path finder probably needs to be fairly well optimized, but if you are going to call it every frame to recalculate every path on every object and you have hundreds of objects, the solution may be to find a faster data type, but there are much greater results to be had in simply seeking fewer paths less often.
 

Zhanghua

Member
I would invert that, I'm curious about the complexity and efficacy of your implementation of the user inventory. I use a walkable node-based structure that uses maps and lists. It's fairly expensive because it must chop up a string and walk down the path from the source node to find the data requested. However, I'm not doing it 1000x every frame or yeah, it would definitely kill my frame rate. Rather I do it once, and then I don't do it again until something changes and even then I only update the things that changed so not everything has to be looked up from scratch. If I have a particularly expensive lookup, I'll walk to the source node so subsequent lookups don't have to start from the beginning of the database, etc... Hell, my battle system relies on a complex scripting system that also relies on those database lookups and happens in real-time, and it's still not expensive enough to need an alternative even though a single ability might perform dozens of lookups in addition to having to calculate and make comparisons.

It's like pathfinding: your path finder probably needs to be fairly well optimized, but if you are going to call it every frame to recalculate every path on every object and you have hundreds of objects, the solution may be to find a faster data type, but there are much greater results to be had in simply seeking fewer paths less often.
Alright, I can show you some old fashion module of mine about the inventory two years ago using the array stuff without any advanced DS thing.(not the most optimized final version, but the efficiency is reasonable).

Itembag.yyp

Using just one object independent with the room and the main functions are as follows:
1. Add and delete items.
2. Page turning, sorting and use of inventory.
3. Close and open the inventory.
4. Storage and reading of inventory data.
5. Multi-belonged inventories function design.

My intention in this silly argument is hoping to make life easy by using the struct or OOP stuff under none or little decreased fundamental speed.

And my meaning is cleared and I won't argument with anyone about this. Cause everyone has his own design tack and different focused thing.

Meaningless.......Just waiting for testing and refractoring.
 

Attachments

Last edited:

Anuj Raghav

Member
ticket number is: 170195
requested on 28/4/2020
still waiting .....

I still don't get it , why closed beta ...other game engines are offering even the alpha builds to public , here sorry to say but people just wait wait, wait and wait for tiny little features ...and when we have finally something happening ..then we have to wait for our luck to get hands on it even though we are paid customers just like others .
indie developers depend so badly on monetization but we still have no working extensions for major Ads platforms , had to switch to unity for two of my simple 2d projects just because lack of monetization support .

when the whole world is going in one direction …yoyogames always manages to choose the opposite path
 
Last edited:

Zhanghua

Member
ticket number is: 170195
requested on 28/4/2020
still waiting .....
169514, we should waiting for the public beta, YoYo's bug list of 2.3.0 is still opening.

ticket number is: 170195
requested on 28/4/2020
still waiting .....

I still don't get it , why closed beta ...other game engines are offering even the alpha builds to public , here sorry to say but people just wait wait, wait and wait for tiny little features ...and when we have finally something happening ..then we have to wait for our luck to get hands on it even though we are paid customers just like others .
indie developers depend so badly on monetization but we still have no working extensions for major Ads platforms , had to switch to unity for two of my simple 2d projects just because lack of monetization support .

when the whole world is going in one direction …yoyogames always manages to choose the opposite path
I just loved in it.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Moderator
I still don't get it , why closed beta ...other game engines are offering even the alpha builds to public , here sorry to say but people just wait wait, wait and wait for tiny little features ...and when we have finally something happening ..then we have to wait for our luck to get hands on it even though we are paid customers just like others .
Just because others do it, doesn't mean it's right... ;)

Also note that YYG is a SMALL company, and so have to manage their resources carefully and it's a delicate balance between opening the product to people and dealing with issues that come up because of it. Opening it completely means a massive influx of support requests and bug reports, and dealing with them would require a lot of extra man-hours and probably delay the release into stable more than it is being delayed at the moment. I would also say that your comment on "little features" is quite insulting... this is a MASSIVE update with a huge amount of features and changes that will impact users from now onwards. It's no wonder they are being prudent and trying to get it all perfect before the full release. I feel this is a no-win situation for YYG, as I'm pretty sure that if they'd gone full open beta, you'd be in this topic complaining that x/y/z doesn't work or it's broken and why have they released such a buggy beta to paying customers....
 

Anuj Raghav

Member
Just because others do it, doesn't mean it's right... ;)

Also note that YYG is a SMALL company, and so have to manage their resources carefully and it's a delicate balance between opening the product to people and dealing with issues that come up because of it. Opening it completely means a massive influx of support requests and bug reports, and dealing with them would require a lot of extra man-hours and probably delay the release into stable more than it is being delayed at the moment. I would also say that your comment on "little features" is quite insulting... this is a MASSIVE update with a huge amount of features and changes that will impact users from now onwards. It's no wonder they are being prudent and trying to get it all perfect before the full release. I feel this is a no-win situation for YYG, as I'm pretty sure that if they'd gone full open beta, you'd be in this topic complaining that x/y/z doesn't work or it's broken and why have they released such a buggy beta to paying customers....
Please read the full line I no where said this is small or little feature ...I mentioned about all little changes we got so far for which we had to wait for ages …..and for current changes I clearly mentioned " now finally when something is happening" .
as for supporting the company many here have always supported yoyogames even when we get gms1.4 repackaged with eye candy ui . and even less features then previous editor, we did supported it .the features you are adding in 2.3 should have been in gms2 in first place.
in gms we had to click 5 times for something now we have to click around 8-10 times , we are still changing our habbits instead of complaining to yoyogames .
No comment on Ads , monetization ???
see if you want to defend and don't want to accept its your call , you are defending company but don't be surprised when people will start looking for alternatives ..and that too free ones which are more intuitive and full of features.
there must be a reason why after so many years and so many loyal consumer base yoyogames still is a small company . people here try to be diplomatically correct but facts cant change.

as for people saying i am whining because i have no access well … I have always supported the company , despite of publishing most of my work with unity
GameMaker for Windows
GameMaker:HTML5
GameMaker: Studio Professional
HTML5 Export
Android Export
iOS Export
Mac Export
Ubuntu Export
Windows UWP

and I have gms2 with mobile html5 web etc on two of my accounts .but these new members who barely created account few days back wont understand it now .
 

gnysek

Member
I still don't get it , why closed beta ...other game engines are offering even the alpha builds to public
If they are not open-sourced, do they have full bug reporting & support trough helpdesk for all customers then, or only for "premium" accounts? :) That's the difference. In YYG, every customer can ask helpdesk basically about everything.
 

Zhanghua

Member
If they are not open-sourced, do they have full bug reporting & support trough helpdesk for all customers then, or only for "premium" accounts? :) That's the difference. In YYG, every customer can ask helpdesk basically about everything.
Yes, that is a business on some way.
 

Anuj Raghav

Member
If they are not open-sourced, do they have full bug reporting & support trough helpdesk for all customers then, or only for "premium" accounts? :) That's the difference. In YYG, every customer can ask helpdesk basically about everything.
ability to ask and actually things getting fixed are two different things, am still waiting for any comments why none of the extensions got updated regarding monetization
few posts above yours moderator himself is saying that we are small company and not capable of handling bug reports if everyone starts submitting one . that's why we are not going open beta.
now you are suggesting totally opposite view . see, again I am saying politely that covering things up with arguments only can give you momentary satisfaction , but is it doing any good in shaping the future of company or making at least present experience a better experience. you can again cherry pick any point from my statements and answer it to prove your point , that's your right . but I think everything I mentioned , will make things better for everyone of us , and I don't think any of it will harm company either.
Still if anyone has problems with my views , fine i wont drag it further , i leave it to your wisdom .
 

XanthorXIII

Member
YoYo has the right to run the public beta anyway they want, even though a few here feel it's not the absolutely best. However I will mention with names not being said that the one project does Beta's all the time and has their users submit bugs through Github. I honestly think that says a lot about the state of GameMaker vs The other project.
 
Status
Not open for further replies.
Top