Changing Timeline's dynamically (Collision Handling)

2 views
Skip to first unread message

jere_uy

unread,
Apr 27, 2011, 12:29:03 AM4/27/11
to PulpCore
I'm having some trouble when handling collisions on a little tile-
based game i'm building.
On my update() method i run a checkCollisions() method which does the
following:

for (int i = 0; i < characterList.size(); i++) {
//i grab one player an the timeline he's moving on
Player thisPlayer = characterList.get(i);
Timeline thisPlayerTline = characterTimelines.get(i);

for (int x = 0; x < characterList.size(); x++) {
//with that player i go through the character's list
Player otherPlayer = characterList.get(x);

//we dont want to check for collisions against ourselves
if (otherPlayer == thisPlayer) {
continue;
}

//here's where my problem is, in actually HANDLING the
collision, not detecting it
if (thisPlayer.collidesWith(otherPlayer)) {
//this finds a new path (Player has a "path"
attribute)
findNewPath(thisPlayer);

//and here's where i think im doing something wrong
Timeline newTline = new Timeline();
newTline.move(thisPlayer, thisPlayer.getPath(), 0, 1,
someDuration);
//replace the player's old timeline
removeTimeline(thisPlayerTline, false);
//the index is "i", for the first player
characterTimelines.set(i, newTline);
addTimeline(newTline);
}
}
}

i need help badly with this, because it works on some occasions. on
others the characters handle the collision well, they find a new path
and they keep walking, but they suddenly jump to a random location on
the map and keep moving... like they "jumped to their previous
timeline"... i have no idea what i'm doing wrong... also... i dont
think this method works when the player gets boxed in, i.e: he's on a
tile, and all the other tiles around him are occupied by other
players... really need some help with this... thanks!

ScottyDont

unread,
Apr 28, 2011, 2:50:28 PM4/28/11
to PulpCore
Hey,

I saw that nobody's replied to this topic yet. I wanted to let you
know that I looked it over a few times, and I can't see anything wrong
with it... then again i'm not that good at debugging code from sight
without compiling/running.

Sorry I couldn't be of more help,



-Scott

jere_uy

unread,
May 2, 2011, 12:23:38 AM5/2/11
to PulpCore
thanks man! i haven't figured this out yet, and i have tried a bunch
of things, not removing the timeline, using map as implementation to
store timelines, but still dont know where's the problem... i dont
need someone to tell me "what to do" just to point out where you think
there might be something wrong in the code... this is killing me!!

Seth Hetu

unread,
May 2, 2011, 3:45:13 AM5/2/11
to pulp...@googlegroups.com
Since you're looking for ideas, have you tried setting "gracefully" to
"true" when you call removeTimeline()?

I know this isn't the desired behavior (you want to interrupt the
timeline) but if this performs gracefully then your hypothesis that
the old timeline is somehow being restored might be correct.

Personally, I'd make a log file which dumps out the object ID of each
sprite's timeline at each time tick. Then you can see if old timelines
are somehow being restored.

Or possibly call getNumTimelines() every time tick and make sure that
the the number is what you'd expect (e.g., old one's aren't being
re-added, or new ones added twice).

Sorry, but I'm afraid I don't have any really insightful ideas on
this. Just throwing out ideas.

-->Seth

> --
> You received this message because you are subscribed to the Google Groups "PulpCore" group.
> To post to this group, send email to pulp...@googlegroups.com.
> To unsubscribe from this group, send email to pulpcore+u...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/pulpcore?hl=en.
>
>

Troy Cox

unread,
May 2, 2011, 7:46:38 PM5/2/11
to PulpCore
I'd reorder things.
Stop/remove the old timeline FIRST -- even set it to null (whatever)
-- kill it dead.
Then, get the new path.
Then create the new time line . . .

You're currently adding the player to the new timeline while the old
timeline is still around. It may be a bug, so just verify there isn't
any possibility of artifacts. Totally clean house.

jere_uy

unread,
May 3, 2011, 2:01:56 AM5/3/11
to PulpCore
ok guys, first of all thanks for your replies... followed both of your
tips and i think there's some strange behavior with timelines in
particular cases... following Troy's advise, i now reordered things so
i:

1 - remove old timeline (from both scene and list, couldnt set it to
null as it gave some errors on runtime)
2 - find new path
3 - create new timeline and call "move()"
4 - add new timeline (to both scene and list)

i now believe the "jumps to previous timeline" is gone... i'll let you
know with further testing... also, following seth's advise, i used the
getNumTimelines() method to see how many were active and i was
surprised to see, that in 2 out of 10 test runs with 10 active
characters, the number of timelines went up to almost 400! in this
particular cases two characters were colliding and were kinda
"stuck" (they kept colliding head on for a while).. kinda strange...

off topic, has anyone developed this sort of tile based games with
characters moving on their own before? collision handling is driving
me nuts!

ScottyDont

unread,
May 3, 2011, 9:52:17 AM5/3/11
to PulpCore
I'm doing a 2D side scroller made up of 200px wide tiles with varying
slopes.

Here's some simple pseudo code to help you out.

Tile[10] tile;
Player player;

// first find out which tile you're on
//second find the slope of the current tile, which is rise over run...
or y over x

for(i=0;i < 10; i++){
if(Math.floor(player.x / 200) == i){

double m = (tile[i].y2 - tile[i].y1) / (tile[i].x2 -
tile[i].x1);

//y = mx + b.... y - mx = b

double b = tile[i].y2 - (m*tile[i].x2)
double tileYAtPlayerPointX = m*player.x2 + b;

if((player.y2 < tileYAtPlayerPointX) && (player.y1 >
tileYAtPlayerPointX)){

// your character is on the line... stop falling

} else if ((player.y2 < tileYAtPlayerPointX) && (player.y1 <
tileYAtPlayerPointX)){

// your character is above the line... fall

} else {

// your character is below the line

} // close else
} // close outside if
} // close forloop

ScottyDont

unread,
May 3, 2011, 9:53:44 AM5/3/11
to PulpCore
You can also negate the forloop if all your tiles are the same size
simply by saying:

i = Math.floor(player.x / 200);
> > me nuts!- Hide quoted text -
>
> - Show quoted text -

Troy Cox

unread,
May 5, 2011, 12:18:02 AM5/5/11
to PulpCore
First, it sounds like you are continuing to check for collisions after
a collision has already been detected. You need to stop calling the
handler until after there is no longer a collision, or you will be
creating a new path and timeline in every loop. I'm a bit surprised
the two sprites ever separated. They must have luckily gotten paths in
opposite directions at the same time.

Basically, you need two handlers, one you're calling on collision,
which sets a property so it isn't called any more. Another handler
that is called when there is no longer a collision, which will reset
to the first handler. At least a switch or if inside the handler to
quit creating new paths and timelines until the collision condition is
false.

Once that is fixed, next, you need to see why you can't clean up a
time line. If you can't, you're app will eventually crash (I bet
you're leaking if you run a profiler) . Note: consider reusing the
same timeline (stop, new path, start).

Finally, based on those results:

1) create a new test scene, or project
2) create your player, path
3) don't worry about collisions, simply set up a timed loop that calls
your handler over and over at a reasonable rate

In other words, get rid of the complexity and work it out there, until
you get it fixed. At the very least, if you can duplicate your problem
in a small test case, you can post a link here and get better help.

Regards.

jere_uy

unread,
May 6, 2011, 3:12:42 PM5/6/11
to PulpCore
I think i get what you mean troy... i was able to verify that when two
characters collide and "bounce back", the if clause with the
"thisPlayer.collidesWith(otherPlayer)" condition is actually entered
THREE times... meaning in one collision i am probably, like you said,
"creating a new path and timeline in every loop" that's probably
what's causing my characters to jump randomly to other locations
later... so.. let me get this straight... i should add an attribute to
the Character class (something like a boolean "collides"), and in the
moment of collision i would set "collides = true" so it doesn't enter
the loop again... and instead of asking this:

if (thisPlayer.collidesWith(otherPlayer))

i would ask this:

if (thisPlayer.collidesWith(otherPlayer) && thisPlayer.collides ==
false)

and i could add an else clause here and set "collides" attribute to
false if the current character doesn't collide.
reusing timelines is not an option, since if i want all the characters
to move at the same speed always, the duration varies depending on the
path they have...

i'm going to give it a go now and reply as soon as possible, a million
thanks for your help man, your insight has been really helpful!

Troy Cox

unread,
May 7, 2011, 12:40:10 PM5/7/11
to PulpCore
You're getting it.

By the way, just a thought to help you code faster loops: '&&' is what
we call a Short-Circuit Logical Operator.

This means that any code after it is ignored if the first condition is
false. So, place the fasted conditions to check in the first position
of any expression that uses '&&' to combine booleans. This can make a
huge difference in tight loops.

if (a && b){} -- If a is false, then b will not be evaluated. This is
generally true of languages derived from C (C++, Java C#).

So, you gave this example:
if (thisPlayer.collidesWith(otherPlayer) && thisPlayer.collides ==
false)

Now, which is faster to check: thisPlayer.collides or
thisPlayer.collidesWith(otherPlayer)??

You know your code, but I'd wager checking the new boolean property is
much quicker. So, if you place it as the first in the expression and
then place the actual collision check last, it will only ever run the
slower code when the faster code results in true.

This may not result in a noticeable difference in the particular case.
But if you use this convention throughout a program, it will make a
difference--notably in inner loops.

Also, this is true with '||'. If the first expression evaluates to
'true', the second is not checked.

-Regards

jere_uy

unread,
May 10, 2011, 3:21:01 PM5/10/11
to PulpCore
Solved! the random "jumps" have stopped now... evidently the problem
was entering the collission loop more than once on each collission...
got a few other problems now but glad i got this out of the way... im
definitely loving game developing... i've never had a taste of this
before, but let me say it tastes quite good! thanks everyone for your
help!
Reply all
Reply to author
Forward
0 new messages