• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

SOLVED give your array items names ?

flyinian

Member
Could you give the individual items in an 2D array a name or can you only use the numbers?

example:

enemyinfo[0,0] = "enemy 1";

Enemy1Name = enemyinfo[0,0];



Thanks.
 

chamaeleon

Member
I hope you realize that the assignment you showed as an example, one, creates an instance variable (because it's not prefixed by var or global.), and two, there's no connection whatsoever between the variable and the array, they will just have the same value stored. If I had a piece of paper with the number 3 written on it, and then I told you to write on a separate piece of paper whatever was written on the first piece of paper, the fact that the number 3 is now written on it doesn't mean there's anything connecting the two pieces paper. You can do whatever you want with either one of them, like burning it, or writing a new number on it, the other would still have the number 3 on it, regardless.
 

flyinian

Member
I hope you realize that the assignment you showed as an example, one, creates an instance variable (because it's not prefixed by var or global.), and two, there's no connection whatsoever between the variable and the array, they will just have the same value stored. If I had a piece of paper with the number 3 written on it, and then I told you to write on a separate piece of paper whatever was written on the first piece of paper, the fact that the number 3 is now written on it doesn't mean there's anything connecting the two pieces paper. You can do whatever you want with either one of them, like burning it, or writing a new number on it, the other would still have the number 3 on it, regardless.
GML:
//Would this work for placing a name to an item in a 2d array?
global.Enemy1Name = enemyinfo[0,0];
 

chamaeleon

Member
is there a way to assign a name(variable) to a array item? Trying to find out if there is an easier way to identify items in an array instead of numbers.
People typically use the arrays and use enums as named indexes as they by default have values starting at zero and increments by one.
 

Nidoking

Member
Again, this is literally what a map does. You can use strings as the keys, or you can use asset IDs, which are numbers, as keys to map to strings. Heck, I even use maps if the keys are an enum, because it's bad practice to assume that enums have any particular numeric value. Nothing like a rewrite of GML that makes enums start at 100000 and turning all of your enum-indexed arrays into memory hogs. I know it won't happen - but it's only poor practice that would cause any problems if it did.
 
Yeah, as @Nidoking said, you're thinking of it in the wrong context. Simply assigning a variable to another variable does literally nothing to make either accessible from the other. What you want is a list or a map that you can reference for each thing, with the values in that list or map representing different things you might want to read or change. An example would be a list of enemies. The naive way of thinking about it is to assign an instance ID to each list position, i.e.:
Code:
// Enemy list creation
enemy_list = ds_list_create();

// Enemy 1 store
enemy_list[| 0] = instance_create_layer(x,y,layer,obj_enemy1);

// Enemy 2 store
enemy_list[| 1] = instance_create_layer(x,y,layer,obj_enemy1);

// Enemy 3 store
enemy_list[| 2] = instance_create_layer(x,y,layer,obj_enemy2);
Here we have a list of enemies, with two instances of obj_enemy1 and one instance of obj_enemy2 being stored. Without setting up specific instance variables for various values you want, literally all you can do is return the instance ID. However, if you do something like this:
Code:
// Enemy list creation
enemy_list = ds_list_create();

// Create enemy 1 map
var enemy_map = ds_map_create();

// Store enemy 1 map values
enemy_map[? "object type"] = obj_enemy1;
enemy_map[? "name"] = "Bob";

// Add enemy 1 map to enemy list
ds_list_add(enemy_list,enemy_map);
ds_list_mark_as_map(ds_list_size(enemy_list)-1);

// Create enemy 2 map
var enemy_map = ds_map_create();

// Store enemy 2 map values
enemy_map[? "object type"] = obj_enemy1;
enemy_map[? "name"] = "Jane";

// Add enemy 2 map to enemy list
ds_list_add(enemy_list,enemy_map);
ds_list_mark_as_map(ds_list_size(enemy_list)-1);

// Create enemy 3 map
var enemy_map = ds_map_create();

// Store enemy 3 map values
enemy_map[? "object type"] = obj_enemy2;
enemy_map[? "name"] = "Tarzan";
enemy_map[? "attack"] = scr_yodel;

// Add enemy 3 map to enemy list
ds_list_add(enemy_list,enemy_map);
ds_list_mark_as_map(ds_list_size(enemy_list)-1);
You can store as much information as you want about each enemy in their enemy_map, and then when you retrieve the list position for that enemy, you will be returned a map that you can then use to grab whatever values you've stored previously. In reality, the same effect can be achieved by using instance variables, but there may be some situation in which you want this kind of behaviour to be linked without having instance variables associated. This way, instead of trying to associate a global or instance variable with a specific name and then referencing that, you can just grab your enemy map and read what is in there, alongside anything else you might want to access:
Code:
//Get the name AND object type of the enemy at list position 0
var enemy_map = enemy_list[| 0];
var name = enemy_map[? "name"];
var obj_type = enemy_map[? "object type"];
You can also check if things have specific variables associated with them with a lesser CPU cost than checking if that variable exists in an instance scope for that instance (as far as I understand it):

Using the first code style I outlined, with instance variables being used instead of map keys (higher CPU cost):
Code:
var enemy_inst = enemy_list[| 0]; // Get the instance ID for the enemy in slot 0 of enemy_list
if (variable_instance_exists(enemy_inst,"attack")) {
   script_execute(attack);
}
Using the second code style I outlined, with map entries being used instead of instance variables (lower CPU cost):
Code:
var enemy_map = enemy_list[| 0];
if (ds_map_exists(enemy_map,"attack")) {
   script_execute(enemy_map[? "attack"]);
}
Taking the time to learn how to use lists, maps, grids, priority lists, etc, is 100% worth your development time, as you will find many varied uses for these data structures that are either harder, or impossible, to replicate using simple arrays.
 

Nidoking

Member
I would go one step farther down that road and make the top-level structure a map instead of a list. That way, the enemy data for obj_goblin is at enemy_data_map[? obj_goblin] instead of using some random index for every enemy type. Any enemy instance can then check its own data using enemy_data_map[? object_index]. (Assuming you don't try to do anything tricky with inheritance that would break that idea. It would be possible to trace your way up parent indices and check whether ds_map_key_exists each time, but I'd just copy the same map index to multiple slots and be careful with how you destroy them afterward.)
 
Yes, very much so. I usually have a global game_state map or buffer or something like that (depending on how often I'm going to be accessing the data and how important security is) which is going to store all the potential data for a save/read state, and there's various methods I might choose depending on what I actually want to read. It's important to understand the data flow before you begin coding or you will inevitably run into problems later. Naive users consider this a flaw within GMS itself ("Why can't I just get the stuff I need") but you should remember that no IDE can provide this type of information (i.e. data YOU consider important, not what generic programmer A might consider important) without certain compromises that you might not want, so having to understand and build it yourself is a sort of blessing in disguise.
 
@RefresherTowel - all those examples have been helpful but I'm stumped on my own issue, If i may hijack this thread for a moment to be educated for what I need to do:

I have a switch and two doors. I can't get the switch to work on both doors (close one and open the other). The code is fine, I just can't get both door instances to work with the switch at the same time
.

I've setup a variable list in the variable options of the switch object and the same for the door object. In both I have door_a and door_b in the lists with multi-select ticked.

In switch instance on the room editor I have everything selected. Door 1 I have door_a selected only, Door 2 - door_b selected only.

The switch object variable is 'name' and the door object variable is 'door_name'

I know I need to declare what door_a and door_b are but not sure what needs to be used - Am i to setup a ds_list? or a ds_map? Is this in the create event of the door/ switch or both objects?

Code:
Switch instance error:
Undefined variable 'door_a' referenced in room level0 in instance inst_6C99B288's variable 'door_name'
Undefined variable 'door_b' referenced in room level0 in instance inst_6C99B288's variable 'door_name'

Door1 instance error:
Undefined variable 'door_a' referenced in room level0 in instance inst_427E5F2E's variable 'name'

Door2 instance error:
Undefined variable 'door_b' referenced in room level0 in instance inst_2C7ADA68's variable 'name'
From what i've read above, would this work? :-

GML:
// Door list creation
door_list = ds_list_create();

// Create door_a map
var door_map = ds_map_create();

// Store door_a map values
door_map[? "object type"] = o_door;
door_map[? "door name"] = door_a;

// Add door_a map to door list
ds_list_add(door_list,door_map);
ds_list_mark_as_map(ds_list_size(door_list),-1);

// Create door_b map
var enemy_map = ds_map_create();

// Store door_b map values
door_map[? "object type"] = o_door;
door_map[? "door name"] = door_b;

// Add door_b map to door list
ds_list_add(door_list,door_map);
ds_list_mark_as_map(ds_list_size(door_list),-1);


//Get the name AND object type of the enemy at list position 0
var door_map = door_list[| 0];
var door_name = door_map[? "name"];
var obj_type = door_map[? "object type"];
If you or anyone could help shed some light on this. I know I'm thinking in the right way I just don't know how to go about it. Having said that though I'll probably figure it out once I wake up tomorrow. Seems to be the case
for most my issues. The next day always brings the solution :)
 
Last edited:

Nidoking

Member
Seems to me like you'd want to put the instance ids of the doors in a list/creation code for the switch. You could do something with a with, but that just seems like more effort than it's worth and won't generalize well.
 
Seems to me like you'd want to put the instance ids of the doors in a list/creation code for the switch. You could do something with a with, but that just seems like more effort than it's worth and won't generalize well.
I have the following in my room start event:

GML:
for (var i = 0; i < instance_number(o_door1); i++){
    var instance = instance_find(o_door1, i)
   
    if (instance != noone) {
        if (string_lower(instance.name)) == string_lower(door_name) {
            target = instance;
        }
    }
}
This looks for the instance ID of the doors in the room if I recall correctly, could I setup a list somewhere amongst this for it to recognise these 'undefined' variables?

I thought putting

Code:
with (inst_2C7ADA68) {
    door_a = o_door1;
    door_b = o_door1;
}

with (inst_427E5F2E) {
    door_a = o_door1;
    door_b = o_door1;
}
in the creation code of the switch object would've solved this but goes to show how little a know about coding :/
 

Nidoking

Member
for (var i = 0; i < instance_number(o_door1); i++){ var instance = instance_find(o_door1, i)
This can seriously just be with (o_door1). If you've got undefined variables, define the variables.

I don't understand the purpose of your door_a and door_b variables to comment on the correctness of what you've done, but I would give each switch either creation code or a variable in the Variable Definitions list with the instance ID of the door(s) it's supposed to affect. I've done more complicated things for this in the past with scripts that I would pair with instance IDs to tell the switch what to do, and another script to tell it how to undo that in the case of pressure switches or timed switches. You can do this with strings like you're trying to do, but then you're setting a string in the door and a string in the switch, and that's twice as much work.
 
This can seriously just be with (o_door1). If you've got undefined variables, define the variables.

I don't understand the purpose of your door_a and door_b variables to comment on the correctness of what you've done, but I would give each switch either creation code or a variable in the Variable Definitions list with the instance ID of the door(s) it's supposed to affect. I've done more complicated things for this in the past with scripts that I would pair with instance IDs to tell the switch what to do, and another script to tell it how to undo that in the case of pressure switches or timed switches. You can do this with strings like you're trying to do, but then you're setting a string in the door and a string in the switch, and that's twice as much work.
I have one switch object. When triggered, I want two instances of the same door object to close / open respectively to each instance. As a string I can't select both door instances with the switch. I've tried the list in the variable options of the switch instance, labelling door_a and door_b - as one would if you had two switch objects and two door objects - switch 1 would have door_a in the string, door 1 would have door_a..... switch 2, door_b; door 2 door_b etc...

So the door_a and door_b variables simply are the door instances i'm trying to get the switch to recognise. therefore door_a and door_b = o_door1;

if I have the one switch connected to one door via strings only, it works fine.

I thought the list option would allow me to connect the single switch object(instance) to the two door instances of the same object. [see below]

visualaid1.jpg
(so in image above, door_a is o_door1 with the image_index = 1; [open], door_b is also o_door1, image_index = 0; [closed]. each o_door1 has its own unique instance ID. If I can capture the ID's maybe I can define door_a and door_b)

Sorry this wasn't so clear and maybe should've started a new thread... :(

I'm going to save my work and attack it tomorrow, thanks for replying @Nidoking and trying your best to help. Noticed you're no.1 helper around here so really appreciate the time taken to help me and others out :)
 

Nidoking

Member
If you want the variables to be instances, don't define them as o_door1, which I presume is the object index. You really want the instance IDs for that.
 
If you want the variables to be instances, don't define them as o_door1, which I presume is the object index. You really want the instance IDs for that.
I finally solved my problem. Ended up deleting my code and writing up something much simpler and after a few frustrating hours I finally got my head around how to code it so if one door opens with the switch another door is coded to do the opposite. Dead obvious now I look at it.

Thanks for trying to help đź‘Ť
 

flyinian

Member
Thanks for the additional information after the post was made solved.

I do appreciate it and i'll be referring to it in the future.
 
Top