Generate non-overlapping objects

Game Editor comments and discussion.

Generate non-overlapping objects

Postby lverona » Mon Jan 28, 2013 1:29 pm

Hey fellas!

I am doing a sort of a scrolling shooter. But I am not designing the levels, I am actually generating them off the screen and letting the view come to them. After they exit view, they get destroyed. So all in all, I have very few active objects in the game at any given moment - they get generated, get seen and then get destroyed.

It is a fun concept to work on, however, very quickly you realize that you have to come up with the mechanism of making sure the objects won't overlap when generating, since it doesn't look good. There are several ideas I came up with, namely:
0. Collision events.
A straightforward solution, but very tiresome. The game is in the beginning stages, and I already have about 15 different enemies. About 20 more are planned. Creating collision events for each one of them dealing with collisions with each of the other is unrealistic and maybe even technically impossible - I am not sure gE would handle so much events in a project. Obviously, this is a bad solution.
1. Using CollisionFree
Good solution, but the downside is that it will not differentiate the collider object. With some objects it is ok to overlap. Also, I wonder how CPU intensive is CollisionFree.
2. Using a variable.
It is possible to create a system of flags and somehow mark the used rows. For instance, I have width 480, say an object of 30 by height was generated at 130. So rows 130-160 are now busy and they can be busy, say, until the object collides with view. Or when the view moves the amount which is equal to the width of the object.
This sounds fine, the downside here is that it can be a complex system. I have many objects in the game, many different type of enemies and bases and creating so many variables and various collision events can become a nightmare.
3. Actually make generation along the y axis semi-random, meaning fixed "corridors" for objects. It won't solve the problem fully, but it would at least allow to minimize it. The downside is obviously the feel of the levels might not be as realistic and spontaneous and plus it does not solve the problem fully anyway.
4. Get the x, y of the latest object and somehow work from there. Pretty simple idea, came up with it after I wrote this post and came back to edit. Not yet sure, though, exactly how to use this.

It is always good, however, to get some advice. Maybe I am missing something simple? Any ideas?
lverona
 
Posts: 221
Joined: Tue Apr 24, 2012 11:54 am
Score: 1 Give a positive score

Re: Generate non-overlapping objects

Postby EvanAgain » Mon Jan 28, 2013 5:01 pm

I just want to let you know that I have worked in this area, with this kind of project. There comes a problem with so many calls to create and destroy. It reduces preformance considerably when you have a large amount of Actors. Instead, (especially with level generation), of this kind you should use tiles that switch through their animation position to create the next section of the level.

I have level generation functions that use Actors in this way, and with some modification it can be used to create 2D sidescrolling. I have a GED that already uses the 2D sidescrolling functions. As well you can modify the code to create "platforms" and "boundaries" including 1-way tiles that only stop an Actor from colliding from a single side.

The problem you are facing, "over-lapping objects" is nothing new. All objects "overlap" because the order they are drawn. In 2D, z-Depth is the order in which you draw to the screen. The "further away" the z-depth is from the screen the actor is, those are drawn first, then the other on top.

Parenting Actors to an Actor will allow for you to control the depth of MANY actors based on a single Actor's z-depth. (At least this is what I have come across). Because the Parent Actor will be drawn at it's z-Depth, then the children will be drawn relative to their z-depth. Then the next relative actor and its children drawn to the last Parent Actor drawn.


With my method of solving this is first to figure out the order of drawing you will need to perform the task.

You could create "placeholder" actors that are parented to the view with specified z-Depth with relative names such as:

-Far Background (Can be used to hold a static background or scrolling to represent distance)
-Background (Can be used to hold the Level map, and objects the player will walk infront of)
-Primary Area (Player and Enemy walking space, also holds pickups)
-Foreground (Objects the player will stand behind)
-Near Foreground(GUI- Score, Lives, Time, ect..)




For overlapping Enemies and various random objects:

You can use the (x,y) positions in an array of "active enemies" and then use their "height and width" to be used so they are not drawn on top of each other. Also, if you are using the moveto() function then use the "avoid actors" option, to keep them from getting under each other. Or many, many other ways to solve this problem.


To keep them from getting under each other, you have to make sure they can collide with each other. If they collide, stop them from trying to advance to that already filled space.
EvanAgain
 
Posts: 51
Joined: Thu Jan 10, 2013 5:40 pm
Score: 4 Give a positive score

Re: Generate non-overlapping objects

Postby lverona » Mon Jan 28, 2013 6:06 pm

Well, I have to say that even in Game Editor mode (meaning, without actually compiling the game, which usually optimizes everything and increases performance) my game is robust. In fact, I am very happy with performance, no problems at all. And since I am already generating the amount of actors that will be present on the screen at any time (meaning, the game will not introduce more actors at once at a later stage) I think I should be fine with the amount of actor creation and destruction I have atm.

I have no problem with zdepth at all, the problem with one enemy base being created partially on top (or under, doesn't matter) of another. And I want to avoid that. My goal is to find a method that would not require too much calculation, since the level is being generated in a Draw event which I do not want to overuse.
lverona
 
Posts: 221
Joined: Tue Apr 24, 2012 11:54 am
Score: 1 Give a positive score

Re: Generate non-overlapping objects

Postby skydereign » Mon Jan 28, 2013 6:43 pm

lverona wrote:0. Collision events.
A straightforward solution, but very tiresome. The game is in the beginning stages, and I already have about 15 different enemies. About 20 more are planned. Creating collision events for each one of them dealing with collisions with each of the other is unrealistic and maybe even technically impossible - I am not sure gE would handle so much events in a project. Obviously, this is a bad solution.

Is it possible for you to make only one enemy actor? And just set a variable to differentiate them, that way the major logic would be preserved between enemies?

lverona wrote:1. Using CollisionFree
Good solution, but the downside is that it will not differentiate the collider object. With some objects it is ok to overlap. Also, I wonder how CPU intensive is CollisionFree.

If those objects that are okay to overlap don't need to collide at all, you can use CollisionState to disable collisions, that way CollisionFree will still work properly. As for efficiency, I presume it is the same as any other collision event, gE pretends to place the object, and checks if it would be colliding.

For this kind of idea, I would recommend using CollisionFree. That's ideally what you want. Now if you can't use CollisionState to disable the other actors , then your last idea sounds best. You can use a while loop to generate the random position, making sure the distance between the two points is greater than some value. Depending on speed, you may want to record the last few enemies generated, and check with all of them (problem with this, is it theoretically could enter an infinite loop, so you'd need to limit it in some way).
User avatar
skydereign
 
Posts: 3510
Joined: Mon Jul 28, 2008 8:29 am
Score: 589 Give a positive score

Re: Generate non-overlapping objects

Postby lverona » Mon Jan 28, 2013 6:55 pm

Is it possible for you to make only one enemy actor?


Well, yes and no. I would want to have more than one of the same enemy on the screen, however, it is possible to create several variants, like when you do have several enemies preset to random positions, but you make sure in the code they do not overlap.

If those objects that are okay to overlap don't need to collide at all, you can use CollisionState to disable collisions, that way CollisionFree will still work properly.


Basically, it would be great if gE had groups of some sort, so one Collision event can address a whole group, BUT I do have two daemons running - one is drawing decorations, the other places enemies. Maybe I can use this somehow...

Well, thanks for advice guys, will think this over and try something.
lverona
 
Posts: 221
Joined: Tue Apr 24, 2012 11:54 am
Score: 1 Give a positive score

Re: Generate non-overlapping objects

Postby lverona » Tue Jan 29, 2013 10:43 am

@ skydereign

Man, can CollisionFree be used with an actor that has not yet been created? Like, do a CollisionFree with an actor and then Create it?
Or should I first create it, check and if it collides - destroy?
lverona
 
Posts: 221
Joined: Tue Apr 24, 2012 11:54 am
Score: 1 Give a positive score

Re: Generate non-overlapping objects

Postby skydereign » Tue Jan 29, 2013 6:38 pm

Sadly, if the actor doesn't exist yet, CollisionFree will always be true, because the actor doesn't have an animation within the game. So if there are no clones of the same type in the game, you'll have to create one. Now you can create sentinel actors, that always exist, but don't play in the game, that way CollisionFree will always work, but that is kind of a weak workaround. A better one is to create the actor off screen, and in its create actor event, move it to the proper position (using CollisionFree to check). Also that way you won't have to watch out if your actors have multiple animations, because CollisionFree with "Event Actor" will already know which animation the clone has.
User avatar
skydereign
 
Posts: 3510
Joined: Mon Jul 28, 2008 8:29 am
Score: 589 Give a positive score

Re: Generate non-overlapping objects

Postby lverona » Wed Jan 30, 2013 8:03 pm

Man, the more I am trying to address this issue the more nasty it becomes. I thought I'll figure something out quickly, but no.

Am I right in understanding that the only reliable way to address the actor created is to do something in his Create Actor event? Because if I create an actor from some other object, than I can only address all actors at once, not this particular one, just created?
lverona
 
Posts: 221
Joined: Tue Apr 24, 2012 11:54 am
Score: 1 Give a positive score

Re: Generate non-overlapping objects

Postby skydereign » Wed Jan 30, 2013 8:14 pm

lverona wrote:Am I right in understanding that the only reliable way to address the actor created is to do something in his Create Actor event? Because if I create an actor from some other object, than I can only address all actors at once, not this particular one, just created?

Sometimes. You don't need to use the create actor event, since if you call CreateActor in an event, it updates the default actor reference, allowing you to target that newly created clone specifically. That means you can specify just the newly created one, but you have to do something a little different.
Code: Select all
CreateActor("test", "anim", "(none)", "(none)", 0, 0, false);
if(CollisionFree("test", 10, 10)==1) // this will check if the first test clone is collision free
{
    // which isn't what we want
}

// we want the newly created clone, but it turns out you can do this
if(CollisionFree(test.clonename, 10, 10)==1)
{
    // test.var usually is a reference to the first clone, but since we created a new test actor in this event
    // it has been updated to allow us to access the newly created actor
    // so using that, we can get the new clonename, which is needed for CollisionFree to check the correct clone
}


There are other tricks to being able to being clone specific, but they are kind of weird to explain out of context.
User avatar
skydereign
 
Posts: 3510
Joined: Mon Jul 28, 2008 8:29 am
Score: 589 Give a positive score

Re: Generate non-overlapping objects

Postby lverona » Thu Jan 31, 2013 4:16 pm

Interesting.

I tried it, but so far no effect, in other words the condition never works. Maybe I am doing smth incorrectly?

Say, I have an actor called "ball". I create it. Then I do this?

if (CollisionFree(ball.clonename, x, y+5)) {...}

Because if so, then although I can see there is nothing to collide with, the condition does not fire up.
lverona
 
Posts: 221
Joined: Tue Apr 24, 2012 11:54 am
Score: 1 Give a positive score

Re: Generate non-overlapping objects

Postby lverona » Thu Jan 31, 2013 4:22 pm

Sorry, works, it was my fault elsewhere in the code.

Thanks a million man! This simplified my job greatly!
lverona
 
Posts: 221
Joined: Tue Apr 24, 2012 11:54 am
Score: 1 Give a positive score

Re: Generate non-overlapping objects

Postby lverona » Thu Jan 31, 2013 4:45 pm

Hm. I fixed what didn't work so that now I am sure that I have everything correctly. But the method does not work. CollisionFree using clonename simply gives out 1 every time. In fact, so does using just the name. Even if I use "ball" instead of "ball.clonename" I always get CollisionFree return 1, even when I put objects on top of each other by a script.
lverona
 
Posts: 221
Joined: Tue Apr 24, 2012 11:54 am
Score: 1 Give a positive score

Re: Generate non-overlapping objects

Postby skydereign » Thu Jan 31, 2013 6:37 pm

Are you making sure the position is correct? Perhaps you really mean for it to be relative to the ball actor?
Code: Select all
if(CollisionFree(ball.clonename, ball.x, ball.y+5)

If not, I would either have to see the code or know more about what you are doing as it works for me.
User avatar
skydereign
 
Posts: 3510
Joined: Mon Jul 28, 2008 8:29 am
Score: 589 Give a positive score

Re: Generate non-overlapping objects

Postby lverona » Thu Jan 31, 2013 7:10 pm

Okay, man, when I did it relative to the "ball", it worked.

Next question though - if it does collide - I need to destroy this instance of the "ball". How do I do that?

I will explain what I tried.
I tried doing this in the Key Down event. Here "holder2" is a frame inside which there are enemy bases. It is a visible frame, like a wall around bases. My aim is to create the wall first, see if it collides with anything and if not, then go ahead and fill it with bases. However if it does collide, I need to destroy it.

Code: Select all
int xxx=450;
int yyy=350;

CreateActor("holder2", "holder2", "(none)", "(none)", xxx, yyy, false);

if(CollisionFree("holder2.clonename",holder2.x, holder2.y)){

//do smth

                                            }

else{DestroyActor("holder2.clonename");}


The view in the game is moving. So I would press the key twice, so that on the second key down the created object will overlap the first one (since view did not move far enough). But if I write code like this, what happens is
1. The first instance of holder2 is destroyed, not the newly created one.
2. On next keystrokes Collision Free always returns 1. In other words, this works only once.

Moreover, even if I do not DestroyActor like I do in the code above, but just let the game destroy this first holder2.clonename when it is out of vision and which I do for all objects in the game when they exit vision, and repeat the experiment without restarting the game, it will not work anymore at all. In other words, as soon as the first holder2.clonename is destroyed, something happens.
lverona
 
Posts: 221
Joined: Tue Apr 24, 2012 11:54 am
Score: 1 Give a positive score

Re: Generate non-overlapping objects

Postby skydereign » Thu Jan 31, 2013 7:14 pm

"holder2.clonename" is a literal string. So it will try to do the action on an actor with the name "holder2.clonename". This is not what you want. You want it to be holder2.clonename.

-Edit
Actually, it will see "holder2.clonaneme", and cut off the .clonename because that doesn't make sense. So, it will destroy the first clone.
User avatar
skydereign
 
Posts: 3510
Joined: Mon Jul 28, 2008 8:29 am
Score: 589 Give a positive score

Next

Return to GE - General

Who is online

Users browsing this forum: No registered users and 1 guest