Jump to content


Photo

Colliding with multiple instances


  • Please log in to reply
12 replies to this topic

#1 Ryef

Ryef

    GMC Member

  • New Member
  • 35 posts
  • Version:GM8

Posted 20 September 2012 - 05:07 AM

The problem arose when I decided to add moving platforms to my game. What I would like the platform to do is check instance_place(x,y-1,parent_objPlayer) then move all those players in contact appropriately.

instance_place() only returns 1 id, thus the problem.

I believe the answer may lie in the with() statement. I've considered doing the approach backwards, and making the platform execute:
with(objPlayer)
     {
     if instance_place(x,y+1,parent_objPlatform)
     x+=whatever;
     }

but this method could be a major memory problem, since there could be hundreds of players in the same room at once. What other method am I not thinking of?

Order here is very important, so I can't simply make objPlayer execute the code. Movement would get out of sync before the Step is over, and the player may end up going through the platform or getting stuck should I add vertical movement as well.

In-depth explanation on order:
Spoiler


P.S. sorry if you viewed this post when it was incomplete, I bumped something on my keyboard that made it post before I was finished typing.

Edited by Ryef, 21 September 2012 - 07:52 PM.

  • 0

#2 DaDiBoM

DaDiBoM

    GMC Member

  • New Member
  • 23 posts

Posted 21 September 2012 - 10:59 AM

with(objPlayer)
     {
     if instance_place(x,y+1,parent_objPlatform)
     x+=whatever;
     }
Your code is fine, just use this

Your other option would be to put all colliding players in a ds_list, then looping through the list and finally removing it, this would be much slower
  • 0

#3 Ryef

Ryef

    GMC Member

  • New Member
  • 35 posts
  • Version:GM8

Posted 21 September 2012 - 07:48 PM

with(objPlayer)
     {
     if instance_place(x,y+1,parent_objPlatform)
     x+=whatever;
     }
Your code is fine, just use this

Your other option would be to put all colliding players in a ds_list, then looping through the list and finally removing it, this would be much slower


I guess it would first check if the player is within view or something to free up some processing, but still, there could be 20 platforms all executing this at the same time for over 100 players (high expectations but still possible). That scenario would execute 2000 times per Step. Maybe now's the time to try only loading objects that are within a certain range of the screen? or does Game Maker already do that? There's got to be another solution that avoids this all together.

Edit: oh, and I think instance_place() should read more like instance_place(x,y+1,other), my mistake.

Edited by Ryef, 21 September 2012 - 07:51 PM.

  • 0

#4 DaDiBoM

DaDiBoM

    GMC Member

  • New Member
  • 23 posts

Posted 23 September 2012 - 11:36 AM


with(objPlayer)
     {
     if instance_place(x,y+1,parent_objPlatform)
     x+=whatever;
     }
Your code is fine, just use this

Your other option would be to put all colliding players in a ds_list, then looping through the list and finally removing it, this would be much slower


I guess it would first check if the player is within view or something to free up some processing, but still, there could be 20 platforms all executing this at the same time for over 100 players (high expectations but still possible). That scenario would execute 2000 times per Step. Maybe now's the time to try only loading objects that are within a certain range of the screen? or does Game Maker already do that? There's got to be another solution that avoids this all together.

Edit: oh, and I think instance_place() should read more like instance_place(x,y+1,other), my mistake.


I think "other" only works in the collision event. I might be wrong though. About the collisions - 2000 isn't that much. You can speed it up a bit by using collision rectangles instead of pixel-perfect collisions but that really shouldn't be needed.
  • 0

#5 Ryef

Ryef

    GMC Member

  • New Member
  • 35 posts
  • Version:GM8

Posted 23 September 2012 - 10:22 PM

I think "other" only works in the collision event. I might be wrong though. About the collisions - 2000 isn't that much. You can speed it up a bit by using collision rectangles instead of pixel-perfect collisions but that really shouldn't be needed.

'other' works in with() statements, it represents the instance calling the with() statement.

I just wish there was a way to clean it up and say "with(objects in collision)" but there is no way in game maker to do that. I feel sloppy saying "with(every player/monster/crate/barrel/drop in the room) then see if they're in collision".
  • 0

#6 TheouAegis

TheouAegis

    GMC Member

  • GMC Member
  • 4714 posts
  • Version:GM8

Posted 23 September 2012 - 11:37 PM

If this is for an online multiplayer game, I think the rule of thumb (I never made a multiplayer game, so I don't know, though) in this situation is to only worry about the actual player and read/write the coordinates of the other players. On the one hand, this will up the bandwidth usage because you'll be sending the x and y for all players across the network, but on each player's side the CPU won't be trying to process 100 objects in such a complex way. But like I said, I never did a multiplayer game and that extra bandwidth usage might be far slower calculating collisions. Unless it's changed over the years, I think any time you have over 50 players on a single screen, it slows down each computer immensely, even when the players aren't moving. Of course in that case you might be best off only transmitting coordinates when they change.

Hopefully someone better oriented with multiplay will overwrite me now.
  • 0

#7 Ryef

Ryef

    GMC Member

  • New Member
  • 35 posts
  • Version:GM8

Posted 24 September 2012 - 08:17 AM

Anyone know a way to run a loop for collision checking, avoiding objects that have already been accounted for?

For example: objects A, B, and C all are using parent P.
Object X checks for a collision with object P.
the expression returns object A and appropriate action is taken.
Object X checks for a collision with object P, but NOT for object A.
the expression returns object B and appropriate action is taken.
Object X checks for a collision with object P, but NOT for object A nor for object B.
the expression returns object C and appropriate action is taken.

There has got to be a way to do this. I'm very comfortable with using loops, but how do I not check an object within a parent?
  • 0

#8 Ryef

Ryef

    GMC Member

  • New Member
  • 35 posts
  • Version:GM8

Posted 24 September 2012 - 08:54 AM

!!!UPDATE!!!

The relation between a Collision Event and the 'other' function is exactly what I'm looking for. How do I do this with instance_place() in a Step Event? (I do as much as possible in Step Events; I do not and will not use a Collision Event, even though it has the solution.)

Example:
I just did some experimenting, and here's how it went...

Object X is a platform. Objects A, B, and C are using parent P.
Objects A and B rest on top of Object X.
Object C is by itself somewhere else in the room.

Object X: [Create Event]: vspeed=-1;
Object X: [Collision with Object P Event]: other.y-=1;

Object A and B moved upward with the platform, while Object C remained in place
This is precisely my solution, but I need to do it in a Step Event, not in a Collision Event.

I'm soooo close, someone please help.

Edited by Ryef, 26 September 2012 - 04:57 AM.

  • 0

#9 Ryef

Ryef

    GMC Member

  • New Member
  • 35 posts
  • Version:GM8

Posted 26 September 2012 - 05:00 AM

I ran the same program again, but this time I monitored the value of 'other' in the collision event. It appears that when using a Collision Event that interacts with more than one object, it runs a loop, once for each instance it encountered (much like a with() loop). Basically, this is exactly what I said in Post #7. Can someone please tell me how this works?

Edited by Ryef, 26 September 2012 - 05:02 AM.

  • 0

#10 Cpt Chuckles

Cpt Chuckles

    GMC Member

  • GMC Member
  • 312 posts
  • Version:GM8.1

Posted 26 September 2012 - 07:30 AM

wait wait wait

i'll admit i didn't really read the whole thread but it sounds like you're trying to make player objects move, from the perspective of the platforms that move them, correct?

why not reverse the thinking? make the player object check if it is colliding with a platform, grab that platform's ID, and then add x and y values stored in the platform object.

for the player:
//Player object: create
{
    myPlatform = noone;
}

//Player object: step
{
    myPlatform = instance_place(x,y+1, parent_Platform);

    ... //stuff

    if(myPlatform > 0) //it will be like -4 if there is no platform there
    {
        x += myPlatform.addx;
        y += myPlatform.addy;
    }
}

now for the platform, each time you place one in the room, you will have to right-click on that instance in the room editor and select creation code, and add:
addx = blah;
addy = blah;
for whatever values you want the affect to be on the player.

would this work?

Edited by Cpt Chuckles, 26 September 2012 - 07:33 AM.

  • 0

#11 Ryef

Ryef

    GMC Member

  • New Member
  • 35 posts
  • Version:GM8

Posted 27 September 2012 - 06:05 AM

wait wait wait

i'll admit i didn't really read the whole thread but it sounds like you're trying to make player objects move, from the perspective of the platforms that move them, correct?

why not reverse the thinking? make the player object check if it is colliding with a platform, grab that platform's ID, and then add x and y values stored in the platform object.

for the player:

//Player object: create
{
    myPlatform = noone;
}

//Player object: step
{
    myPlatform = instance_place(x,y+1, parent_Platform);

    ... //stuff

    if(myPlatform > 0) //it will be like -4 if there is no platform there
    {
        x += myPlatform.addx;
        y += myPlatform.addy;
    }
}

now for the platform, each time you place one in the room, you will have to right-click on that instance in the room editor and select creation code, and add:
addx = blah;
addy = blah;
for whatever values you want the affect to be on the player.

would this work?


The reason I didn't do that to begin with is because I lose control of the order of execution, but now for some reason, I suddenly realize my idea would have problems no matter which object moves first. If the platform had some sort cut-out, and the player was standing in that cut-out, whether the platform moves right or left, by the end of the step something is going to interfere.

A much simpler system is to use my move code, but don't account for the platform that I am standing on. Only account for it when moving based on User-Left-Right input. All of this takes place in the player object, like you said.

So I suppose this topic is solved, and though you didn't say the answer directly, you must have helped my brain get there, so thank you.


P.S.: Merely out of curiosity, I still wish I knew how the Collision Event works for more than one 'other' object.

Edited by Ryef, 27 September 2012 - 06:07 AM.

  • 0

#12 Ryef

Ryef

    GMC Member

  • New Member
  • 35 posts
  • Version:GM8

Posted 03 October 2012 - 09:06 AM

The reason I didn't do that to begin with is because I lose control of the order of execution, but now for some reason, I suddenly realize my idea would have problems no matter which object moves first. If the platform had some sort cut-out, and the player was standing in that cut-out, whether the platform moves right or left, by the end of the step something is going to interfere.

A much simpler system is to use my move code, but don't account for the platform that I am standing on. Only account for it when moving based on User-Left-Right input. All of this takes place in the player object, like you said.


Turns out that this will NOT work, because user-inputted movement may be executed while the platform is out of sync.

EDIT:

Well it kinda works, I'm just not all the way there yet. One solution to this could be the following:
player checks if the platform has executed its movement for the step.
-if it has, move based on the platform, then move based on user-input.
-if it has not, move the platform to where it will be, move based on the platform, then move based on user-input, then move the platform back to where it was.

With this system, I will have to be careful when I check if I'm on the ground (for falling/gravity), but I hope this works.

This topic should called be "Moving Platform issues" instead. Sorry about that. If the original question was answered then I would be able to answer the moving platform issue, but turns out I'm using a roundabout solution.

EDIT:

There are Begin Step and End Step events, but I see these as a 'use if you REALLY REALLY need to', because you only get to do it once. This makes it a kind of last resort for things that are utterly important.

Edited by Ryef, 03 October 2012 - 11:26 AM.

  • 0

#13 Ryef

Ryef

    GMC Member

  • New Member
  • 35 posts
  • Version:GM8

Posted 05 October 2012 - 12:23 PM

I apologize for talking to myself, but no one else seems to be helping.

I tried the "pretend the platform moved, then move appropriately, then move the platform back" method, and it didn't work out so well. Ran into trouble with the platform overlapping the player.

Anyone know a way to run a loop for collision checking, avoiding objects that have already been accounted for?

For example: objects A, B, and C all are using parent P.
Object X checks for a collision with object P.
the expression returns object A and appropriate action is taken.
Object X checks for a collision with object P, but NOT for object A.
the expression returns object B and appropriate action is taken.
Object X checks for a collision with object P, but NOT for object A nor for object B.
the expression returns object C and appropriate action is taken.

There has got to be a way to do this. I'm very comfortable with using loops, but how do I not check an object within a parent?


This method remains the simplest, and gives me the most control over the situation. At the time I did not know how to accomplish it, but I may now.

To NOT check an object, just temporarily change its mask_index to an empty or clear sprite. When the collision loop has finished, put all the mask_index's back to how they were.

Why didn't I think of this before... :biggrin:
  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users