• 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!

Referring to different instances of the same object [SOLVED]

Good morning,

If anyone can help me with this it would be appreciated.

obj_inv_box is created and when my player obj_pl_um_states meets with it in the step event a button prompt appears to press so he can go to the next level. This works fine when I only have one obj_inv_box. But at a certain point I have two obj_inv_box and the collision event only works with the second created box. How do I get it to work with both of them? To be clear, the thing which doesn't work is the button isn't created when he meets global.invboxfire, but is when he meets global.invboxice.

//create obj inv box (2)
global.invboxfire=instance_create_layer(global.toiletTop.x-32,global.toiletTop.y-96,"instances",obj_inv_box)
global.invboxice=instance_create_layer(global.toiletBottom.x-32,global.toiletBottom.y-96,"instances",obj_inv_box)

//step
if place_meeting(x,y,obj_pl_um_states){
instance_create_layer(512,96,"text",obj_button)
}
else{
instance_destroy(obj_button)
}
 
Last edited:

TheouAegis

Member
Because your first box creates a button, but then the second box runs its code and destroys all the buttons in the room.

Instead of destroying the button, why not create it in the Create event and then (de)activate it when the player gets close or far enough.
 
Because your first box creates a button, but then the second box runs its code and destroys all the buttons in the room.

Instead of destroying the button, why not create it in the Create event and then (de)activate it when the player gets close or far enough.
I thought by putting the boxes in global variables it would differentiate them. Putting the button in the create event won't work as I only want it to appear when the player touches the boxes and then disappear when he is not touching them. This works perfectly with one box in the room, but not with two. I was trying to avoid creating a second box_instance. Maybe I should use the with command?
 

Kyrieru

Member
There are a few ways you can do it.
If the problem is differentiating between objects,

When the door creates the textbox, do something like this (just before creating the object)
global.my_creator = id

//create event of textbox object
my_creator = global.my_creator

Then the textbox does..

with player_group
if place_meeting(x,y,my_creator)

Basically the door passes it's ID onto the textbox so it knows which object created it.
Then the textbox checks collisions for that door only.
 
There are a few ways you can do it.
If the problem is differentiating between objects,

When the door creates the textbox, do something like this (just before creating the object)
global.my_creator = id

//create event of textbox object
my_creator = global.my_creator

Then the textbox does..

with player_group
if place_meeting(x,y,my_creator)

Basically the door passes it's ID onto the textbox so it knows which object created it.
Then the textbox checks collisions for that door only.
Ok thanks, but I'm confused. So you mean just before the box creates the button, I store global.my_creator = id where? In the box object or the button object?

Then in the create event of the button I store my_creator = global.my_creator?

Then in the step even of the box I put
with player_group
if place_meeting(x,y,my_creator)? What is player_group?
 

Kyrieru

Member
The door creates the global variable right before it creates the button. So put it just before instance_create()
The textbox sets my_creator to global.my_creator in it's create event.
player_group would be whatever player object you're using, so replace it with yours.
 
The door creates the global variable right before it creates the button. So put it just before instance_create()
The textbox sets my_creator to global.my_creator in it's create event.
player_group would be whatever player object you're using, so replace it with yours.
I tried this but it doesn't seem to work as the button is only created when the obj_player contacts the inv_box, so it never meets my_creator which, if I'm following your suggestion is now assigned to the obj_button? I think I need to assign the boxes different ids.
 
Last edited:

Kyrieru

Member
I tried this but it doesn't seem to work as the button is only created when the obj_player contacts the inv_box, so it never meets my_creator which, if I'm following your suggestion is now assigned to the obj_button?
Whatever object the player touches to create the button is what should set
global.my_creator = id

All you're doing is storing the id of the object the player touched in the newly created object/button etc.

Then that new object knows what object created it/which object the player touched.

The created object then uses "with player_ob" to make the player check for collisions. It should be like this, though. (I forgot to add "other")

with player_ob
if place_meeting(x,y,other.my_creator)
 
Whatever object the player touches to create the button is what should set
global.my_creator = id

All you're doing is storing the id of the object the player touched in the newly created object/button etc.

Then that new object knows what object created it/which object the player touched.

The created object then uses "with player_ob" to make the player check for collisions. It should be like this, though. (I forgot to add "other")

with player_ob
if place_meeting(x,y,other.my_creator)
Ok so my player touches one of the already created boxes to create the button (in the step event of obj_inv_box)
Code:
if place_meeting(x,y,obj_pl_um_states){
    global.creator=id
    instance_create_layer(512,96,"text",obj_button)
}
Then in the obj_button create event
Code:
my_creator=global.creator
Then in the obj_ button step event
Code:
if place_meeting(x,y,other.my_creator){
    instance_create_layer(512,96,"text",obj_button)
}
else{
    instance_destroy(obj_button)
}
This caused an inf loop.
 
Last edited:

Kyrieru

Member
I think I misunderstood what you're trying to do, and I'm still not really sure.

You can check if the button was created by a certain object by doing this;
if obj_button.my_creator = id

If you could post a visual example I would probably be able to help a bit more.
 
I think I misunderstood what you're trying to do, and I'm still not really sure.

You can check if the button was created by a certain object by doing this;
if obj_button.my_creator = id

If you could post a visual example I would probably be able to help a bit more.
Okay well I did try make it clear in op, and whilst I haven't solved it, I need to crack on so have just created duplicate objects to make it work (which it does). Maybe I will look at it again later but right now, it remains unsolved for me.
 

FrostyCat

Redemption Seeker
Learn the difference between objects and instances.

NEVER access a single instance by object ID if multiple instances of the object exist. This includes attempts to reference or set object.variable (which is inconsistent across exports) and using with (object) to apply actions to it (this encompasses all instances of the object instead of just the one you want). Verbally, "Dog's colour" makes sense with one dog, but not with multiple dogs.
Created or copied instance. instance_create() (GMS 1.x and legacy) / instance_create_layer() (GMS 2.x) and instance_copy() return the ID of the created or copied instance. NEVER use instance_nearest() to establish this relationship --- something else could be closer by.
Create:
Code:
my_button = noone;
Step:
Code:
if (place_meeting(x, y, obj_pl_um_states)) {
  if (my_button == noone) {
    my_button = instance_create_layer(512, 96, "text", obj_button);
  }
} else if (my_button != noone) {
  instance_destroy(my_button);
  my_button = noone;
}
 
Last edited:
I made a mistake, check the post again. The old code keeps creating new buttons while the collision holds, and then only destroys the latest one.
Thank you, this works. I had an additional problem related to this, how would I then go to one level if one box is activated and a different level if another instance of the same box is activated?

So the buttons are created and in the collision event of inv_box (the top box) when obj_pl_um_states touches it I have
Code:
if keyboard_check_pressed(ord("A")){
    alarm[0]=200
    instance_destroy(obj_button)
    instance_destroy(obj_pl_um_states)
    global.toiletTop.sprite_index=spr_toilet_UM
    audio_play_sound(sou_flush,1,0)
}
//Then the alarm changes the room which works fine.
if room==room_ckboss{
    room_goto(room_fire)
    instance_create_layer(128,544,"instances",obj_pl_um_states)
    obj_pl_um_states.state=states.original
}

//But how would I make it so if obj_pl_um_states touches the second instance of obj_inv_box (the bottom one)  it would go to a different room (room_ice)?
I tried storing the two instances of inv_box in global variables to differentiate them in the collision event but it didn't work.
 
Last edited:

FrostyCat

Redemption Seeker
If you already have the two instance IDs stored in global variables, just use them to detect collisions instead of object IDs.
Code:
if (place_meeting(x, y, global.invboxfire)) {
  room_goto(rm_fire);
} else if (place_meeting(x, y, global.invboxice)) {
  room_goto(rm_ice);
}
None of this is difficult, the big problem here is that you aren't recognizing places where instance IDs can be used instead of object IDs. Go over all the things you currently believe accept only object IDs, look them up in the Manual and see if they also accept instance IDs. In particular, the variable reference dot (subject.variable) also accepts instance IDs on its left side. As a general rule, the only place in GML that accepts object IDs but not instance IDs is the obj parameter in built-in functions starting with instance_create_*() or object_*().
 
If you already have the two instance IDs stored in global variables, just use them to detect collisions instead of object IDs.
Code:
if (place_meeting(x, y, global.invboxfire)) {
  room_goto(rm_fire);
} else if (place_meeting(x, y, global.invboxice)) {
  room_goto(rm_ice);
}
None of this is difficult, the big problem here is that you aren't recognizing places where instance IDs can be used instead of object IDs. Go over all the things you currently believe accept only object IDs, look them up in the Manual and see if they also accept instance IDs. In particular, the variable reference dot (subject.variable) also accepts instance IDs on its left side. As a general rule, the only place in GML that accepts object IDs but not instance IDs is the obj parameter in built-in functions starting with instance_create_*() or object_*().
Okay thanks for the advice.

Although your suggestion is more elegant, I used the position of my player to also change the room to the correct one (which is okay as the inv_box(es) are static).
Code:
if instance_exists(obj_pl_um_states){
if obj_pl_um_states.y<250{
if keyboard_check_pressed(ord("A")){
    alarm[0]=200
    instance_destroy(obj_button)
    instance_destroy(obj_pl_um_states)
    global.toiletTop.sprite_index=spr_toilet_UM
    audio_play_sound(sou_flush,1,0)
}
}
}
if instance_exists(obj_pl_um_states){
if obj_pl_um_states.y>250{
if keyboard_check_pressed(ord("A")){
    alarm[1]=200
    instance_destroy(obj_button)
    instance_destroy(obj_pl_um_states)
    global.toiletBottom.sprite_index=spr_toilet_UM
    audio_play_sound(sou_flush,1,0)
}
}
}
 
Top