Oooo that's perfect thanks! One more thing, can you leave blank commas on middle arguments that you want to use defaults for, or do you need to use the word "undefined"?:
GML:
entity = new Entity("Monster",,,true);//will this work to only set the last one? lol
entity = new Entity("Monster", undefined, undefined, true);//or would it be this?
//I saw FrostyKat's {"is_hostile: true"} code before which is likely what I'll use and I assume would let you skip a middle optional argument like so:
entity = new Entity("Monster", {strength: 100; is_hostile: true});
//...but I'm just curious about the default syntax lol
Ok I still don't have the beta yet but I tried some more exercises in roughing out how to refactor my game's code when I get the beta. I re-read some of the thread and it sounds like "other" points to the object calling the struct's function, so a quick question first on if this is how it would be used?
GML:
//--------------------------------------------------
//scr_points
//--------------------------------------------------
function Point(_index_, x_offset, _y_offset) constructor {
index = _index;
x_offset = _x_offset;
y_offset = _y_offset;
static draw = function() {
//can I use other.id here instead of having to pass the id to this function?:
draw_circle(other.id.x + x_offset, other.id.y + y_offset, 10, true);
// ^^^^^ ^^^^^
}
}
//--------------------------------------------------
//obj_enemy
//--------------------------------------------------
//Create Event
point = new Point(0, 100, 100);
//Draw Event
point.draw();//would the point be drawn at this object's x + 100, y + 100?
Then I was thinking about how I'd do an object inspector, would the Inspector() function below work to show an instance's Entity struct info in a level editor Properties panel?
GML:
//--------------------------------------------------
//scr_points
//--------------------------------------------------
function default(_value, _default) {//trying to find a cleaner way to do argument defaults lol
return (_value == undefined ? _default : _value);
}
function Entity(_name, _hp, _strength, _is_hostile) constructor {
inspector = new Inspector();
name = _name;
hp = default(_hp, 1);
strength = default(_strength, 1);
is_hostile = default(_is_hostile, false);
}
function Inspector() constructor {//<--------------------------- THIS PART
static debug_show_struct = function(_struct_id) {
var _Names = variable_struct_get_names(_struct_id),
_count = array_length(_Names);
for (var _i = 0; _i < _count; _i++) {
var _name = _Names[_i],
_value = variable_struct_get(_struct_id, _Names[_i];
show_debug_message(_name + ": " + string(_value));
}
}
}
//--------------------------------------------------
//obj_enemy
//--------------------------------------------------
//Create Event
entity = new Entity("Old Man", 100, 10);
entity.inspector.debug_show_struct(entity);
Now this NEXT one was another big revelation moment for me...my save/load code was SO long and complicated looking before, and the code was spread out all over in like an obj_stage object using instance variables and a bunch of scr_stage_save() scr_stage_load() etc scripts, separate ones for the editor and the gameplay, and obj_ed_enemy versions of obj_enemy to add editor features (VS the editor struct I roughed out earlier in this thread that could just be dropped right into the gameplay obj_enemy when the game state is editing)
In my game's current code I had started with Juju Adam's "I love data" code which was fantastic but admittedly juggling an elaborate nesting of ds_maps and ds_lists got pretty frustrating to get working and keep track of when I was adding new stuff to save/load and trying to structure my JSON the way I wanted. Then I kept Juju's structure but used YellowAfterLife's TJSON which made it a lot easier and cleaner looking, but still with some bulk to it esp at the top & bottom of the scripts for the actual opening/saving/loading code.
But NOW...with the new GML features and FrostyCat's JsonStruct, it actually makes me chuckle to myself to look at how little code is needed to save/load with a nice clean organized looking JSON file (theoretically since I can't test it yet). I only expected to try the save stuff but it's so little code that I was like "I wonder how hard loading would be" and then I wanted to try an overall game finite state machine just to kind of think out how it'd go.
GML:
//--------------------------------------------------
//scr_stage
//--------------------------------------------------
function Stage() constructor {
data = {};
static save = function() {
//get stage info
data.info.name = get_string("Stage Name:", "Untitled");
data.info.author = get_string("Stage Author:", "Unknown");
//get enemies
var _i = 0;
with (obj_enemy) {//save each enemy's data
other.data.Enemies[_i++] = {
object_index : object_index;
x : x;
y : y;
Waypoints : Waypoints;//array of Waypoints for AI
};
}
//save using FrostyCat's JsonStruct
jsons_save("STAGE.JSON", jsons_encode(data));
}
static load = function() {
//clear current stage
with (obj_enemy) {instance_destroy();}
//load using FrostyCat's JsonStruct
data = jsons_decode(jsons_load("STAGE.JSON"));
//spawn enemies
for (var _i = 0; _i < array_length(data.Enemies); _i++) {
var _enemy = data.Enemies[_i];
instance_create_layer(_enemy.x, _enemy.y, "enemies", _enemy.object_index);
}
}
static draw_info = function() {
draw_text(0, 0, data.info.name);
draw_text(0, 10, data.info.author);
}
}
function Enemy(_object_index, _x, _y, _Waypoints) constructor {
object_index = _object_index;
x = _x;
y = _y;
Waypoints = _Waypoints;
}
function Waypoint(_x, _y) constructor {
x = _x;
y = _y;
}
function Game(_state) constructor {
state = _state;
}
//--------------------------------------------------
//obj_game
//--------------------------------------------------
//Create Event
game = new Game("GAMEPLAY_INIT");
stage = new Stage();
//Step Event
switch(game.state) {
case "GAMEPLAY_INIT":
stage.load();
game.state = "GAMEPLAY";
case "GAMEPLAY":
//gameplay stuff...
if (keyboard_check_pressed(vk_tab)) {game.state = "EDITOR_INIT";}
break;
case "EDITOR_INIT":
stage.load();
game.state = "EDITOR";
case "EDITOR":
//editor stuff...
if (mouse_check_button_pressed(mb_left)) {
instance_create_layer(mouse_x, mouse_y, "enemies", obj_enemy);
}
if (keyboard_check_pressed(ord("S"))) {stage.save();}
if (keyboard_check_pressed(ord("L"))) {stage.load();}
if (keyboard_check_pressed(vk_tab)) {game.state = "GAMEPLAY_INIT";}
break;
}
//Draw Event
stage.draw_info();
//--------------------------------------------------
//obj_enemy
//--------------------------------------------------
//Create Event
enemy = new Enemy(
obj_enemy, x, y, [
new Waypoint( 0, 0),
new Waypoint(100, 0),
new Waypoint(100, 100),
new Waypoint( 0, 100),
new Waypoint( 0, 0)
]
);
One question I ended up with after all this: is there a way to do "with all objects that contain this struct type"? Something like:
GML:
with (all) {
if (struct_exists("Enemy")) {
//do stuff to these ones...
}
}
Or would the best way of doing this be to keep a ds_list somewhere like in the Stage struct like:
GML:
//--------------------------------------------------
//obj_game
//--------------------------------------------------
//Create Event
stage = new Stage();
stage.Entities = new List();//using FrostyCat's Lightweight Data Structures
//Step Event
for (var _i = 0; _i < stage.Entities.size; _i++) {
with (stage.Entities[_i++]) {
//do stuff to these ones...
}
}
//--------------------------------------------------
//obj_enemy
//--------------------------------------------------
//Create Event
obj_game.stage.Entities.add(id);
//Cleanup
obj_game.stage.Entities.remove(id);
Big thanks to all the advanced guys who've been helping answer everyone's questions and the tutorial makers putting their stuff up on YouTube the last couple weeks!
This is seriously so much fun and I don't even have the beta yet...but every time I'm roughing these things out and I spot something I can use a new feature for and chop out huge chunks of code or entire scripts or bulky arrays of enums it feels like when you bomb a wall in Zelda and find a secret cave lol