Adventure Game Studio

AGS Support => Beginners' Technical Questions => Topic started by: Snake on Tue 19/05/2009 02:20:37

Title: Checking Multiple Objects with IsColliding
Post by: Snake on Tue 19/05/2009 02:20:37
Sorry for posting again on the same day - hell, I hate posting at all.

But there's just GOT to be an easier way to check whether an object is colliding with ten others - other than writing them all out in one big-arse "if and OR" statement... like I've been sitting here doing for the past ten minutes.

I'm hoping there's something like this;

if (object[1].IsCollidingWithObject(object[1,2,3,4,5,6,7,8,9,10])==1){
  //do stuff here
}


I also have to do this code for the ten other objects.

What I'm doing is seeing if any of the ten random objects are touching eachother. If they are, then push them over a bit.

The code I've got works, but it's just so damn tedious and time consuming, not to mention hideous. I'm not even through testing the first object and have 19 more to go (in all).

Any insight is much appreciated,

--Snake
Title: Re: Checking Multiple Objects with IsColliding
Post by: GarageGothic on Tue 19/05/2009 02:26:22
If all the objects are numbered sequentially, you can use a "while" loop (or rather, two of them):


int objectcount = 1; //because 1 is the first object in your example, but maybe you meant 0?
while (objectcount < 10) { //doesn't include object 10 since that will be the final second object we check against
  int secondobjectcount = objectcount+1;
  while (secondobjectcount <= 10) {
     if (object[objectcount].IsCollidingWithObject(object[secondobjectcount]) == true) {
       //DO STUFF
       }
     secondobjectcount++;
     }
  objectcount++;
  }


Of course this doesn't take into account that pushing an object away could make it collide with an already checked object, so they may overlap until next game loop (I take it this code is in your repeatedly_execute?). There's really no way around that without the code getting very complicated.
Title: Re: Checking Multiple Objects with IsColliding
Post by: Snake on Tue 19/05/2009 03:04:24
So far, that has seemed to work quite well. I honestly don't have a clue what you have done, but with further inspection I'm sure I'll understand it enough ;)

Thank you
Title: Re: Checking Multiple Objects with IsColliding
Post by: GarageGothic on Tue 19/05/2009 03:21:57
Glad it works. I realize it looks a bit confusing at first, but it's actually quite simple once you understand the concept of "while" loops. Take your time to look it over and let me know if you have any questions. I can also explain it step-by-step to you if you want.
Title: Re: Checking Multiple Objects with IsColliding
Post by: Trent R on Tue 19/05/2009 04:57:15
Not quite sure if it would work, but another option (though possibly too laggy for your use) may be to use SSH's Pixel Perfect Collision Detection (http://www.adventuregamestudio.co.uk/yabb/index.php?topic=26307.0).

[Edit]:I believe it has a IsCollidingWithAnything.
Quote
//  PPColliding.OWithAnything(Object *a);
//    Check if a is colliding with any object or character. Returns
//    the value of GetLocationType for the first collision found, but there
//    may be more than one collision.

~Trent
Title: Re: Checking Multiple Objects with IsColliding
Post by: GarageGothic on Tue 19/05/2009 05:39:59
Unless you truly need pixel perfect detection I wouldn't really recommend it. I wrote the original code that the PixelPerfect module is based on, and while it does work fine, it is a bit of a hack and can be quite slow depending on the size of the objects and how many of them are likely to collide at the same time.
Also, since you would have to run it once for each individual object, you would miss out on the "secondobjectcount = objectcount+1" optimization that I included in the script above (i.e. object 0 will check for collisions with objects 1-10, so object 1 doesn't need to check collisions with object 0 and so on, until object 9 only checks for collisions with object 10 since everything else has been taken care of earlier).

Edit: I just realized you could probably optimize it a bit further by only allowing one collision per game loop for each object (so once it has collided and gets pushed away it will not move again until the next loop). I'm not sure if this is desirable, but as it currently doesn't recheck collisions after being pushed away* it shouldn't make much of a difference. At the moment I'm too tired to figure out how best to implement this though.

* The reason it doesn't do this is that it would require quite a bit of extra code to avoid endless loop situations where an object gets stuck between two or more other objects, freezing and eventually crashing the game.
Title: Re: Checking Multiple Objects with IsColliding
Post by: Trent R on Tue 19/05/2009 06:07:41
Ahah. I wasn't even thinking of what was going on internally.... But I already knew that a while loop is the best and tried (and failed) to suggest an alternative. Oh well ;D

~Trent
Title: Re: Checking Multiple Objects with IsColliding
Post by: Snake on Tue 19/05/2009 14:35:22
I was going to use that module anyway for the actual gameplay, since, IsColliding checks the entire rectangle, ignoring the transparency. That is, of course, if this has been updated since then (I remember making the suggestion for a Pixel Perfect collision module years ago ('04/'05 maybe)... heh, for this very same game too).

I'll further explain what is happening so you have a better understanding on the effects of code or modules. Sorry for the lack of further explaination earlier on:

The resolution is 800x600 (I know I've religiously bashed this resolution in the past, but I feel it is well needed for this project).  In the beginning of each "stage" (before fade in), ten objects are randomly placed on the "field". The check to see whether these objects are too close to each other will only happen once, which is, in the very start of the room.
I see what you are saying now, GG, since the code you have created is in the repeatedly execute section, the module would slow it down being continuously checked throughout, even when it doesn't need to be.

Hmm... couldn't I make a variable to see whether they are all done? If so, I could stop the code from running. If any slow-down, this should end rather quickly, in theory.

//--EDIT--//
Come to think of it, the module would be used for something else entirely anyway. For the initial check of the objects being too close, I'd much rather it be checking the rectangle.
But anyway, terminating the code when it doesn't need to be run any more, since the objects won't be moving, would be the way to go anyway, wouldn't it?
Title: Re: Checking Multiple Objects with IsColliding
Post by: GarageGothic on Tue 19/05/2009 14:44:56
QuoteThe check to see whether these objects are too close to each other will only happen once, which is, in the very start of the room.

Oh, this is a different matter entirely. I thought this was some sort of physics thing where objects could bump into eachother. I wish you had mentioned it from the start since this is a much easier thing to do. You can still reuse part of the code, just move it to the EnterRoomBeforeFadeIn event and instead of bumping the object a few pixels away just keep randomizing its position until it no longer overlaps anything else.


//first a couple of utility functions

bool checkprevcollision(int objectid) {
  int secondobjectcount;
  while (secondobjectcount < objectid) {
    if (object[objectid].IsCollidingWithObject(object[secondobjectcount]) == true) return true;
    secondobjectcount++;
    }
  }

function randomizeposition(int objectid, int x, int y, int width, int height) {
  object[objectid].X = x + Random(width);
  object[objectid].Y = y + Random(height);
  }

function PositionObjects(int range) {
  int objectcount = 0;
  while (objectcount <= range) {
    randomizeposition(objectcount, 20, 20, 760, 560); //Just some random numbers for the bounding box
    while (checkprevcollision(objectcount) == true) {
      randomizeposition(objectcount, 20, 20, 760, 560);
      }
    objectcount++;
    }
  }


And just call PositionObjects(10) from the EntersRoomBeforeFadein event.

Edit: Doh, you posted while I was writing. Well, as long as what you've got is working, everything is fine  :).

Edit 2: Fixed some stupid mistakes in the code in case anybody wants to use it.
Title: Re: Checking Multiple Objects with IsColliding
Post by: Snake on Tue 19/05/2009 15:09:28
Sorry, GG, I have this aweful habit and "fear" of letting in on too much of what I'm working on. It's just as silly as someone watermarking their screenshots in the GiP forum.

That is what I've been doing lately, I've just been randomizing their placement again if they are touching (instead of just pushing them over by 20 or so pixels), except from within the REP_EXEC.

I didn't realize that from within the BEFORE_FADEIN it would keep checking if they were touching or not before actually loading the room. Thanks, I've moved the code and it still works perfectly.

//--EDIT--//
While we're on the subject of randomizing objects on screen;
How can I randomize the other ten objects on the BOTTOM HALF of the screen?
Random(XX) allows only one number, and that is the maximum. How do I tell AGS I want them to be randomized within 350 and 550?
Title: Re: Checking Multiple Objects with IsColliding
Post by: NsMn on Tue 19/05/2009 15:18:36
The second part is easy. Just write

Random(200)+350;
Title: Re: Checking Multiple Objects with IsColliding
Post by: GarageGothic on Tue 19/05/2009 15:18:49
See the randomizeposition utility function in the above code, it uses a bounding box that the coordinates are randomized within.
Title: Re: Checking Multiple Objects with IsColliding
Post by: Snake on Tue 19/05/2009 16:08:45
My God, this is almost histerical. That's what I've been trying to do, but foolishly been writing it like this:

object[11].Y=Random((200)+350);


Thanks, guys, once again.
Title: Re: Checking Multiple Objects with IsColliding
Post by: Snake on Tue 19/05/2009 18:29:19
Sorry for the double post.

I'm just now realizing and remembering that IsColliding only checks the baselines.

GG, I've been messing with your code to add in AreThingsOverlapping, but nothing seems to be working.
Here's what I tried last:

     if (AreThingsOverlapping(objectcount, secondobjectcount) == true) {


It says: AreThingsOverlapping: Invalid parameter. I'm not sure I understand what I should be doing...
Title: Re: Checking Multiple Objects with IsColliding
Post by: Matti on Tue 19/05/2009 18:33:55
I think you have to add 1000 to the object number (for whatever reason). This is what the manual says:

"THING1 and THING2 can either be a CHARID, or can be an object number PLUS 1000. So for example, passing EGO as THING1, and 1004 as THING2, will compare the character EGO with Object 4 in the current room."

Title: Re: Checking Multiple Objects with IsColliding
Post by: Snake on Tue 19/05/2009 18:44:39
That's strange. I just double checked the manual with IsColliding and it says it ONLY checks in rectangular form, which is what I want. But if that's the case, why are some objects still overlapping?
Title: Re: Checking Multiple Objects with IsColliding
Post by: GarageGothic on Tue 19/05/2009 18:59:16
I think the baseline issue is only with characters, in the AreThingsOverlapping section in the help file it even says:

QuoteCalling this function with both the parameters as objects is the same as calling Object.IsCollidingWithObject.

Which one of my scripts are you using, still the first one? If so the optimization* may be causing problems (as it checks for collision with items that haven't yet been positioned - depending of course on where you've put your randomization code), take a look at the new script that I posted and see how it only does collision checks with items already in place. But it would be even easier to troubleshoot if you posted your own code.

*The optimization is still there in the new code, so it's the same number of iterations, but it works backwards instead of forwards. I should really have done it like this from the start.
Title: Re: Checking Multiple Objects with IsColliding
Post by: Snake on Wed 20/05/2009 16:21:10
GG:
Yes, I was still using your first code. It seemed to be working fine but I sat down this morning and restarted the room a bundle of times and there were certainly times where the objects would over lap. I tried messing around with it but to no avail.

So what I've done now is deleted your code entirely (copied and pasted into notepad for backup of course) and am trying to use the new code that you had substituted.

I'm having a bit of a problem. Now, I'm using the new AGS so I'm still trying to get used to it - used 2.72 for too long.

For some reason I'm finding it very hard, frustratingly hard, to implement it into the game.

I'm assuming your entire code goes into the global script. I pasted everything at the bottom just like I would have with 2.72, but nothing is being recognized.

What in the hell am I doing wrong here?
Title: Re: Checking Multiple Objects with IsColliding
Post by: GarageGothic on Wed 20/05/2009 16:38:56
What exactly do you mean that "nothing is being recognized"?

The code doesn't need to be in the global script. If you only use it in a single room you can put it in the room script and call it from the room's EnterRoomBeforeFadein event (which needs to be below my code to be able to call the functions). If you use it in multiple rooms, put it in the global script and remember to add:

import function PositionObjects(int range);

to the global header. Again, call it from the EnterRoomBeforeFadein event in the room script.
Title: Re: Checking Multiple Objects with IsColliding
Post by: Snake on Wed 20/05/2009 17:15:28
Sorry - what I mean by "nothing's being recognized" is that secondobjectcount is an undefined token.

I tried again and remembered this time to include the import aspect of it (heh) and got the same thing.
Title: Re: Checking Multiple Objects with IsColliding
Post by: GarageGothic on Wed 20/05/2009 17:20:25
Oh yeah, there's a spelling mistake. "secondbjectcount++;" should be "secondobjectcount++;" of course. I fixed the above code.
Title: Re: Checking Multiple Objects with IsColliding
Post by: Snake on Wed 20/05/2009 18:52:59
Quote from: GarageGothic on Wed 20/05/2009 17:20:25
Oh yeah, there's a spelling mistake. "secondbjectcount++;" should be "secondobjectcount++;" of course. I fixed the above code.
Heh - We both have to pay a little more attention me thinks. You had misspelled RandomizePosition everytime too ;)

But anyway, man, I got it working and I think I've finally cracked the case with the over-lapping issue (since it ignored your new code too).

Besides your original code I had put in a check to see if any objects were out of bounds. No matter where I put any of the code, some objects were still overlapping.

Like you had brought up in one of your earlier posts, it didn't check to see whether any of the objects that were moved got placed on top of another one or not.

I noticed that in your new code, the boundries for the objects was already uncluded.
This finally sunk in my head and so I removed my code for checking the boundries, adjusted the boundries within your code and wa-la. So far after a bunch of testing I haven't seen any overlapping.
Title: Re: Checking Multiple Objects with IsColliding
Post by: GarageGothic on Wed 20/05/2009 19:06:46
Yeah, that's what happens when you write code directly on the forums instead of using the script editor. Next time I should probably test it before posting :)

Anyway, great to hear that it works now. Are you experiencing any slowdown when changing rooms? I was a bit worried about how many iterations it would take for the objects to find a non-overlapping position.
Title: Re: Checking Multiple Objects with IsColliding
Post by: Snake on Wed 20/05/2009 19:23:17
lol

I'm experiencing 0 slowdown so far and I expect that it'll stay that way.

I'm excited that it is working as well. Thank you, GG.

Here's one more conundrum for you:

I need to do the same thing for the bottom half of the screen (366-750) with ten more objects.
With your old code all I did was copy and paste it and change all the INTs slightly to make it work.

But with your new code it seems to be a bit more complicated than that. I'm finding it hard to understand how you conected you integers to those ten objects...

The bottom objects are objects11-20.
Title: Re: Checking Multiple Objects with IsColliding
Post by: Khris on Wed 20/05/2009 19:33:35
If I may, all you need to do is adjust the function a bit:

function PositionObjects(int first, int last, int x, int y, int w, int h) {
  int objectcount = first;
  while (objectcount <= last) {
    randomizeposition(objectcount, x, y, w, h); //Just some random numbers for the bounding box
    while (checkprevcollision(objectcount) == true) {
      randomizeposition(objectcount, x, y, w, h);
      }
    objectcount++;
    }
  }


Then call PositionObjects(0, 10, x, y, w, h); to position objects 0-10 in a bounding box @ x,y with width w and height h.
For the bottom objects, use PositionObjects(11, 20, x, y, w, h);
Title: Re: Checking Multiple Objects with IsColliding
Post by: GarageGothic on Wed 20/05/2009 19:53:55
If the two screen areas don't intersect, you could optimize a bit (not that it's going to make much of a difference as the objects will never overlap) by adding a parameter for the first object to check against in checkprevcollision:

bool checkprevcollision(int objectid, int first) {
  int secondobjectcount = first;
  while (secondobjectcount < objectid) {
    if (object[objectid].IsCollidingWithObject(object[secondobjectcount]) == true) return true;
    secondobjectcount++;
    }
  }


and update KhrisMUC's PositonObjects to:

function PositionObjects(int first, int last, int x, int y, int w, int h) {
  int objectcount = first;
  while (objectcount <= last) {
    randomizeposition(objectcount, x, y, w, h); //Just some random numbers for the bounding box
    while (checkprevcollision(objectcount, first) == true) {
      randomizeposition(objectcount, x, y, w, h);
      }
    objectcount++;
    }
  }
Title: Re: Checking Multiple Objects with IsColliding
Post by: Snake on Wed 20/05/2009 20:27:26
This is what it gave me:

GlobalScript.asc(536): Error (line 536): Function declaration has wrong number of arguments to prototype
Which is this line:
function PositionObjects(int first, int last, int x, int y, int w, int h) {


\edit/
Should I be replacing the code I have with this, or should I be making this one seperate?

Title: Re: Checking Multiple Objects with IsColliding
Post by: GarageGothic on Wed 20/05/2009 20:39:01
Did you remember to change the import in the header to the updated function? And yeah, just replace your code (and put in the first and last values into the function calls in your room script).
Title: Re: Checking Multiple Objects with IsColliding
Post by: Snake on Wed 20/05/2009 20:46:30
No, I didn't, which I figured out a few minutes ago. It worked.


Right now I'm adjusting the boundries... the top objects seem to be clustering together, though not toughing, and the bottom objects are more spread out but some are off screen. I'll get back in a few minutes...

//--EDIT--//
I got the top half adjusted perfectly, couldn't get any better, but I can't seem to get the numbers right for the bottom half.
Title: Re: Checking Multiple Objects with IsColliding
Post by: GarageGothic on Wed 20/05/2009 21:05:12
Object coordinates are defined as the lower left corner of the object, so you should make sure to have at least an object's width of margin on the right hand side of the screen.
Title: Re: Checking Multiple Objects with IsColliding
Post by: Snake on Wed 20/05/2009 21:15:39
I don't know, I can't get right.

PositionObjects(11, 20, 50, 350, 690, 590); is what I came up with and either nothing shows up or there's only 3 or 4 objects on. I don't understand where I 'm going wrong.

Should I be doing fancy-dancy stuff like this, (200)+350?
Title: Re: Checking Multiple Objects with IsColliding
Post by: GarageGothic on Wed 20/05/2009 21:22:15
I think you're mistaking the height/width values for coordinates. Looking at the numbers I assume the game is 800x600 resolution, but if your y-coordinate starts at 350 and the box is 590 pixels tall, that would mean 340 of those pixels are offscreen. If you want the box to end at y coordinate 590 it should only have a height value of 240.
Title: Re: Checking Multiple Objects with IsColliding
Post by: Snake on Wed 20/05/2009 21:41:11
Finally got it:
12, 366, 690, 230

Thanks for all your help and putting up with my lack of scripting ability. You have no idea how much I appreciate it.