GameMaker: Studio

GameMaker: Studio

View Stats:
OL3 Aug 4, 2018 @ 11:44am
Find X from a object with multiple instances
So i am making a multiplayer game splitscreen and i need to give a code to a spesific object which has multiple instances.

so lets say i would try to find the inventory from the obj_player number 3, in this case there is 4 instances of the obj_player. Here comes the problem:

obj_player.inventory = ...

^ this code will always refear to the first object placed, how do i choose it to take the code from a object that are not made first but lets say the 3 instance created.?



sorry for bad grammar, english and sentences buildup and thanks for any answer in advance
Last edited by OL3; Aug 4, 2018 @ 6:37pm
Originally posted by Zappy:
(TL;DR at the bottom.)

Actually, I'm pretty sure that obj_player.inventory = ... refers to every obj_player instance. (After all, the documentation says that since obj_stuff.var += 4 is just short for obj_stuff.var = obj_stuff.var + 4, it makes "var" of every "obj_stuff" end up with the same value as each other.)

Now, without having to make separate objects for each player (such as obj_player1, obj_player2, et cetera), there are some ways that you can do what you want to do.


First of all, you may want to get to learn the instance_number(obj) and instance_find(obj,n) functions. You can find in-depth explanations of them in GameMaker: Studio's documentation, but here's a very basic explanation of them:
instance_number(obj) lets you find out how many instances of the object "obj" exist in the room. For example, in a room with 4 players, each of them having their own objects called obj_player, instance_number(obj_player) should return a value of 4.
instance_find(obj,n) returns the id of the "n"-minus-one-th instance of the object "obj" in the room. (That means that if you call that function with an "n" of 0, it'll return the first instance, and an "n" of 1 is the second instance, and so on.) However, there is no reliable way to be sure of the order of "n", so if you spawn player 1, player 2, player 3, and player 4 in that order, instance_find(obj_player,2) might return the id of player 3, but it's equally likely to return the id of player 1, 2, or 4.


Taking that last bit into account, I now regret even mentioning those two functions, as using them, even when used properly, will either be unreliable or still more wasteful (performance-wise) than just storing the id of the players upon instance creation in a different object and reading from that to do stuff. Therefore, I've "spoilered" them, so they will still be in this comment, but clutter the comment much less.


What I would instead suggest is to have obj_player instances be created by another object (like obj_system or obj_server or obj_network or such), and then store the result of instance_create(x,y,obj) in a variable in that object for each player. (instance_create(x,y,obj) returns the id of the created instance.)

For example, obj_system could do something like player1 = instance_create(100,200,obj_player); to save the id of the created instance in a variable called "player1".
Then obj_system can do stuff like player1.x+=100 to move player 1, but no other players, 100 pixels to the right, and other objects can do stuff like obj_system.player1.x+=100 for the same result.

Of course, coding it this way will get pretty messy pretty quickly as you add more players (having to manually type player1.x, player2.x, et cetera at least one time if you do it right, and likely many more times in any case). Therefore, you may want to use an array or such instead.
For example, obj_system could do something like players[numplayers] = instance_create(100,200,obj_player); numplayers += 1; to have an array called "players" have a new index added at the position of "numplayers" with the id of the created instance, and then increase "numplayers" by 1.
With this approach, you should of course do players[0]=noone; numplayers=0; in the Create event of obj_system to avoid errors resulting in crashes.
Then you should make sure to never ever access an index of "players" that's less than 0 or more than "numplayers" minus one.

Just to clarify, with the array-based second approach, this is how things should work with 4 players:
obj_system.players[0].x += 100; will move player 1, but not 2/3/4, 100 pixels to the right.
obj_system.players[1].x += 100; will move player 2, but not 1/3/4, 100 pixels to the right.
obj_system.players[2].x += 100; will move player 3, but not 1/2/4, 100 pixels to the right.
obj_system.players[3].x += 100; will move player 4, but not 1/2/3, 100 pixels to the right.
obj_system.players[-1].x += 100; will always cause the game to crash!
obj_system.players[4].x += 100; will always/usually cause the game to crash, the only exception possibly being if a 5th player joined and then left and set obj_system.players[4] to noone in the process.
object_system.numplayers will be 4, as there are 4 players.

And this is how things should work with 0 players:
obj_system.players[0].x += 100; will always/usually cause the game to crash, exactly like with obj_system.players[4].x += 100; when there are 4 players.
obj_system.players[-1].x += 100; will still always cause the game to crash!
obj_system.numplayers will be 0, as there are 0 players.

In other words, with obj_system.players[n], "n" should never be less than 0, and "n" should also never be more than obj_system.numplayers - 1. (Yes, this means that if there are 0 players, the array should never be accessed at all.)

Of course, if you have 4 players and player 2 leaves, it would be best to make sure to "trickle down" player 3's and 4's variables in the array to leave no gaps. In other words, if player 2 leaves, obj_system.players[0] should remain as the id of the player 1, obj_system.players[1] (new player 2) should be set to the current value of obj_system.players[2] (old player 3), obj_system.players[2] (new player 3) should be set to the current value of obj_system.players[3] (old player 4), and obj_system.players[3] (now-empty player slot) should preferably be set to noone. The order of these operations here is important. Setting the new player 2 to the old player 3 should be done before the new player 3 is set to the old player 4, for hopefully-obvious reasons.
(A for loop will be helpful for this.)


Do note that a lot of this above stuff is specifically for if players are supposed to be able to join/leave the game at will, rather than the entire game being designed for specifically 4 players at a time.



TL;DR:
Have a "system" or "server" or "game engine" object handle the creation of player object instances, and store the result of the creations in a variable in an array in that object, while also storing the number of current players in that object.
Then instead of doing something like obj_player.x += 100;, do something like obj_system.players[2].x += 100; to move player 3 100 pixels to the right.
< >
Showing 1-3 of 3 comments
maras Aug 4, 2018 @ 12:25pm 
You can use variables to store players ids
player1 = instance_create(10, 10, obj_player); player2 = instance_create(20, 20, obj_player); // player1.inventory = ... with player2 instance_destroy(); etc
Last edited by maras; Aug 4, 2018 @ 12:26pm
The author of this thread has indicated that this post answers the original topic.
Zappy Aug 4, 2018 @ 1:06pm 
(TL;DR at the bottom.)

Actually, I'm pretty sure that obj_player.inventory = ... refers to every obj_player instance. (After all, the documentation says that since obj_stuff.var += 4 is just short for obj_stuff.var = obj_stuff.var + 4, it makes "var" of every "obj_stuff" end up with the same value as each other.)

Now, without having to make separate objects for each player (such as obj_player1, obj_player2, et cetera), there are some ways that you can do what you want to do.


First of all, you may want to get to learn the instance_number(obj) and instance_find(obj,n) functions. You can find in-depth explanations of them in GameMaker: Studio's documentation, but here's a very basic explanation of them:
instance_number(obj) lets you find out how many instances of the object "obj" exist in the room. For example, in a room with 4 players, each of them having their own objects called obj_player, instance_number(obj_player) should return a value of 4.
instance_find(obj,n) returns the id of the "n"-minus-one-th instance of the object "obj" in the room. (That means that if you call that function with an "n" of 0, it'll return the first instance, and an "n" of 1 is the second instance, and so on.) However, there is no reliable way to be sure of the order of "n", so if you spawn player 1, player 2, player 3, and player 4 in that order, instance_find(obj_player,2) might return the id of player 3, but it's equally likely to return the id of player 1, 2, or 4.


Taking that last bit into account, I now regret even mentioning those two functions, as using them, even when used properly, will either be unreliable or still more wasteful (performance-wise) than just storing the id of the players upon instance creation in a different object and reading from that to do stuff. Therefore, I've "spoilered" them, so they will still be in this comment, but clutter the comment much less.


What I would instead suggest is to have obj_player instances be created by another object (like obj_system or obj_server or obj_network or such), and then store the result of instance_create(x,y,obj) in a variable in that object for each player. (instance_create(x,y,obj) returns the id of the created instance.)

For example, obj_system could do something like player1 = instance_create(100,200,obj_player); to save the id of the created instance in a variable called "player1".
Then obj_system can do stuff like player1.x+=100 to move player 1, but no other players, 100 pixels to the right, and other objects can do stuff like obj_system.player1.x+=100 for the same result.

Of course, coding it this way will get pretty messy pretty quickly as you add more players (having to manually type player1.x, player2.x, et cetera at least one time if you do it right, and likely many more times in any case). Therefore, you may want to use an array or such instead.
For example, obj_system could do something like players[numplayers] = instance_create(100,200,obj_player); numplayers += 1; to have an array called "players" have a new index added at the position of "numplayers" with the id of the created instance, and then increase "numplayers" by 1.
With this approach, you should of course do players[0]=noone; numplayers=0; in the Create event of obj_system to avoid errors resulting in crashes.
Then you should make sure to never ever access an index of "players" that's less than 0 or more than "numplayers" minus one.

Just to clarify, with the array-based second approach, this is how things should work with 4 players:
obj_system.players[0].x += 100; will move player 1, but not 2/3/4, 100 pixels to the right.
obj_system.players[1].x += 100; will move player 2, but not 1/3/4, 100 pixels to the right.
obj_system.players[2].x += 100; will move player 3, but not 1/2/4, 100 pixels to the right.
obj_system.players[3].x += 100; will move player 4, but not 1/2/3, 100 pixels to the right.
obj_system.players[-1].x += 100; will always cause the game to crash!
obj_system.players[4].x += 100; will always/usually cause the game to crash, the only exception possibly being if a 5th player joined and then left and set obj_system.players[4] to noone in the process.
object_system.numplayers will be 4, as there are 4 players.

And this is how things should work with 0 players:
obj_system.players[0].x += 100; will always/usually cause the game to crash, exactly like with obj_system.players[4].x += 100; when there are 4 players.
obj_system.players[-1].x += 100; will still always cause the game to crash!
obj_system.numplayers will be 0, as there are 0 players.

In other words, with obj_system.players[n], "n" should never be less than 0, and "n" should also never be more than obj_system.numplayers - 1. (Yes, this means that if there are 0 players, the array should never be accessed at all.)

Of course, if you have 4 players and player 2 leaves, it would be best to make sure to "trickle down" player 3's and 4's variables in the array to leave no gaps. In other words, if player 2 leaves, obj_system.players[0] should remain as the id of the player 1, obj_system.players[1] (new player 2) should be set to the current value of obj_system.players[2] (old player 3), obj_system.players[2] (new player 3) should be set to the current value of obj_system.players[3] (old player 4), and obj_system.players[3] (now-empty player slot) should preferably be set to noone. The order of these operations here is important. Setting the new player 2 to the old player 3 should be done before the new player 3 is set to the old player 4, for hopefully-obvious reasons.
(A for loop will be helpful for this.)


Do note that a lot of this above stuff is specifically for if players are supposed to be able to join/leave the game at will, rather than the entire game being designed for specifically 4 players at a time.



TL;DR:
Have a "system" or "server" or "game engine" object handle the creation of player object instances, and store the result of the creations in a variable in an array in that object, while also storing the number of current players in that object.
Then instead of doing something like obj_player.x += 100;, do something like obj_system.players[2].x += 100; to move player 3 100 pixels to the right.
RandomDude Aug 4, 2018 @ 11:00pm 
obj_player.imventory would just return the first instance of that object.

with obj_player{ if player_number == 3{ //access the players inventory break; //stop the loop after finding the right player } }

I made up a variable called player_number and you could either edit the instance create code in the room to assign this or use another loop like this:

count = 1; with obj_player{ player_number = other.count; other.count ++( }
Last edited by RandomDude; Aug 4, 2018 @ 11:02pm
< >
Showing 1-3 of 3 comments
Per page: 1530 50

Date Posted: Aug 4, 2018 @ 11:44am
Posts: 3