Game Development Community

creating specific collision responses

by rennie moffat · in Torque Game Builder · 06/07/2010 (7:21 am) · 20 replies

HI there, I have created a system where by my player, onUpdate, castCollision. My enemies, have specific set collisionPoly's. I have gone in on a test level and recorded each enemy normal when colliding with the player from any of the four sides. What I achieved is a reaction, specific, this means my player will "bounce right, left, up down depending on what side he is hit from... but here comes my question.


In the test level, I was able to move my player up to the correct position, ease him in so he is touching the enemy, from any side, then open up the console, and record the info (normal, contact points). However, in a game situation, my enemies, temporarily lose collision send when collided with by the player. Also in game play, my specific, bouncing reactions only happen on, if I am lucky, 10% of the collisions. I am wondering, is by turning off collisions the instant of impact not recording the same normals as I had recorded in the test level where by I "sat" my player, right up next to the enemy and did not turn off collisions? I was very meticulous in recording all possible normals and I think it would work, I am just wondering what you guys think.

Thanks,
Ren



PS. here is my process, just in case you want to skip the reading.



player onUpdate()
{
%this.owner.castCollision()


if object collided with == enemyX
if normalX == "specificNormalX to EnemyX" && normalY == "specificNormalY to enemyX"
Then player "bounce right animation"
}



Thats it in a nut shell. I know I am getting collisions as I have a whole other system for scoring which works. Any professional thoughts would be appreciated.


About the author

My thanks to Garage Games and the Garage Games Community combined with owned determination I got one game up, Temple Racer and I am looking to build more interesting, fun games for the mass market of the iOS app store.


#1
06/08/2010 (8:27 am)
Hi I am just wanting to get this going. If I could create this to work, pretty much all the time, 70% would be good, it would be the icing on the cake for my first app. The trouble is, my game is time based. When I/player collides with an enemy, time is added. A specific amount is added depending on the enemy class. Some are more, some are less but all, need to have collisions temporarily turned off upon collision. This is the only way to insure 1 hit count is recorded, otherwise 30 hits could be counted in one collision due to the time the player and enemy are actually in contact.

This brings me to my problem. I have discovered, if I delay the turning off or turn off collisions turning off and allow the collision to be longer than one split instant that my "bounce effect works". So I must find a way to allow for the bounce to occur (a delayed schedule works) however, this does not work for time as the collisions length, the amount of time the two are officially colliding, each nanosecond adds or counts a hit.

My time is counted as an int. Each second is 1 int.


If anyone has any thoughts on this, and how to solve it, please let me know.

Thanks
Ren

#2
06/08/2010 (8:34 am)
ps. I thought of making my collision cast time, into the future longer. but that did not work.
#3
06/08/2010 (9:27 am)
I don't think you necessarily have to turn the collisions off upon collision to ensure that only 1 hit count is recorded.

You could just have a variable for your objects that keeps track if it has collided. For example Object.hasCollided would initially be set to false. When you collide you could check to see if object.hasCollided is false. If it is false then set it to true and then do whatever you want with it. The next time the onCollision callback gets called Object.hasCollided will be true and it will be ignored. You can set a schedule up to reset it back to false in a few seconds or so.
#4
06/08/2010 (9:35 am)
well ok, but i think that you may be missing something. a collision of object A onto B, while visually may appear as one single collision, that collision takes place over time and as long as collisions are true a collision occurs, repeatedly. So if I don;t turn off collisions at impact, repeated collisions occur, thus repeated scores are altered.
#5
06/08/2010 (9:59 am)
I think I now what you are saying, but I am trying to think, how could I set one collision to one collision instant with out turning off collisions for sake of scoring?

I am thinking something like this, but I can't see it working. Anyone have insight on this?



function onCollision()
{
%this.collided();
}

function collided(%this)
{
%this.collided = true;
if(%this.collided == true)
%this.dothis();
}


I can't seem to figure out how, beyond setting collisions to false immediately, to do this. but I need collisions to last, slight longer than at impact to insure my bounce effect, however that cripples my scoring accuracy. Any ideas, please send em along.




#6
06/08/2010 (11:32 am)
I had something like this in mind:

function onCollision()
{
%this.collided();
}

function collided(%this)
{
//This is where you would have your collision effect such as bouncing.
%this.collisionEffect();

//This is where you effect the score
if(%this.hasCollided != true)
{
%this.hasCollided = true;
%this.EffectScore();
%this.schedule("ResethasCollided",1000)
}
}

That way when you have collisions, your bouncing will not be effected but the score will only count once.
#7
06/08/2010 (11:57 am)
oh i see thanks! I will try that.






#8
06/08/2010 (1:20 pm)
sweet, that works perfectly, thanks Kenneth. I just never thought of putting a condition (if X is true inside the function itself). Good tip.





#9
06/23/2010 (3:04 pm)
Hi there, this is just a continuation of the main question.


I have my player, castCollision, if the normals returned == particualr numbers then the player has a particualr animation to correspond with the normals play. This creates the illusion that he bounces, left right up down.


My question is, this only happens sometimes on collision. I want it to happen all the time.


My question is, is this as efficient, as effective as I could hope for?


function onUpdate(%this)
{
	
////I have tried, but am unsure if placing...
////%this.owner.castCollision(0.005); first makes a difference
////tests showed no significance
////however if you think that should please let me know
////the basic code is as follows

	%collision = %this.owner.castCollision(0.005);
	
	%normalY = getWord(%collision, 5);
	%normalX = getWord(%collision, 4);
	%contactY = getWord(%collision, 3);
	%contactX = getWord(%collision, 2);
	%time = getWord(%collision, 1); 
	%object = getWord(%collision, 0);

		
	if(%object.class $= "enemy1Class")
	{
		///account for 1
		if(%normalX == 0.391091 && %normalY == 0.920352)
		{
			///do this....
		}
			
		///account for 2
		if(%normalX == -0.497046 && %normalY == 0.867724)
		{
			///do this....
		}
		
		///account for 3
		if(%normalX == -0.375095 && %normalY == -0.926986)
		{
			///do this....
		}
		
		///account for 4
		if(%normalX == 0.455631 && %normalY == -0.890169)
		{
			///do this....
		}
	}

The normals were found by placing the player in contact on each of it's four sides against each of the four sides of the enemy and recording the echo returns.


Of note: each object, enemy and player are 4 sided collisionPoly's
#10
06/23/2010 (5:34 pm)
Without knowing what you mean by bounce (bounce a little, bounce a little and return, bounce with the full force of movement, etc.) it's hard to answer this question.

The short answer is that a normal is a vector. You are comparing vectors. Therefore, use t2dVectorCompare.
#11
06/23/2010 (6:06 pm)
well, the bounce would be taken care of in each if statement, so if the normalXY == X && Y as given then i tell it to do something. What I am concerned about is that collision do happen as noted in the scoring of my game, but the reaction I would tell it to do here (separate from scoring) does not always occur. So I think that although a collision takes place between the player owner and the enemy1Class the reaction I want does not happen.


Is there a reason? A better way to insure the criteria are met?
#12
06/23/2010 (6:16 pm)
So wait,
are you saying as opposed to just comparing a set of numbers compare the vectors as vectors?!


of course!!


#13
06/25/2010 (12:59 am)
When you use numbers like that in code they're typically referred to as "magic numbers" (unnamed numerical constants) and they're considered bad programming practice for many reasons.

Why not use the standard bounce collision? Why not just use vector math instead? Could you imagine a physics library that had to encode all the (infinite) potential collision normals? ;)

Typing "vector bounce" in Google returns hundreds of results on how to do this. Try this one. You Google right?

If you have specific animations that need to take place depending on the direction then that's easy too ... you can calculate from the collision normal the direction of the bounce and split that up into (say) quadrants (or whatever) for your animation.

It's basic stuff.
#14
06/25/2010 (8:16 am)
Well perhaps my description of "bounce" was inappropriate considering the "bounce" that already exists with collisions.



Quote:
Why not just use vector math instead?
but I would still need my player to understand upon which side he has been hit. I am unsure how, beyond the way I have already done (normal comparison on collision). And by the way, in my needs I only have 4 possible collision normals per enemy, I have 5 enemies. Not much. However, is it the speed of the collision (as it may be over in an instant, it may change, as in, it may hit something, have that collision normal, but by the time it is recognized/calculated by the computer the normals, due to the objects constantly moving, have changed, thus the reaction is ignored?



Yes, I think the process is pretty basic, I am just trying to insure that the program sees it, when it happens as much as possible.




Still not sure how I am going to end up going about this, but I hope doing a t2dVectorComparision vs just comparing numbers will increase it's effectiveness.






#15
06/25/2010 (9:47 am)
There's also the layman's version of this problem:

DONT turn off collision. It's complicated and unnecessary.

When a collision occurs, set a flag on the player (if you don't want him to hit multiple enemies in a row) or the enemy (if you want them to be able to swarm the player) that represents invincibility.

For examlpe, some pseudocode:

if(collision && !%this.isInvincible)
{

apply damage and impulse;
%this.isInvincible = true;
schedule(1000,"%this.isInvincible=false");

}


After 1 second, the player can be hit again. You'll still have a bunch of collisions, but the code to apply damage and impulses is wrapped in a conditional that prevents it from happening more than once a second.

Also, this method doesn't call collisions every update (expensive). It only reacts when a collision is encountered.

As for finding out the angle to bounce, you shouldn't have to. The contact normal is a vector and you use that vector to apply an impulse. If you get the normal from the enemies perspective, it's facing the correct way.

If you get the normal from the player, then you just have to invert the x and y values (multiply by -1).
#16
06/25/2010 (11:15 am)
Being completely honest Rennie ... you'll do it your way if you don't want to read/understand basic vector math. I'm sure you'll reply and say you do know it in which case you wouldn't be doing what you're doing.

Had to say it, not trying to be mean.

Programming involves mathematics ... you know, that stuff you learned at school but never thought you'd need. ;)

Follow the links I sent, they explain it real well.
#17
06/25/2010 (12:06 pm)
ok will do.

#18
06/25/2010 (6:35 pm)
@Melv,
I read up and actually do understand vector math from High School Algebra but What I don't get is, in theory, I think I could flip the velocities on collision, so if traveling 3x 4y on collision make 4x 3y, but in may case I could have near infinite directions. So in that case, I am not sure what to make of the vector math. If you want to laugh me off or what have you, please do so, but I am just saying what I am thinking trying to work this little bit out. I still have not added in a t2dVectorCompare and I have not had a chance to yet, so hopefully that will remedy the problem but we will see I guess.
#19
06/28/2010 (1:19 pm)
If you want a bounce to always be on one of the (say) 4 cardinal directions then isn't it esaier to calculate the bounce vector then see which cardinal direction it's closest to and use that? Surely the largest component of the bounce direction (either X or Y) gives you that.

... and I'm not laughing at all, just saying how easy the math behind it is and that you should use an algebraic solution not some rigid rules-based one trying to compare values you've echoed. Short of you being given the exact solution in code, I'm not sure how else to help you.
#20
06/28/2010 (4:59 pm)
well the trick is, with mine (maybe I should have been clearer about my programming) but the "bounce" is an animation. The player actually remains in the same position or on the same path, unaffected, however, the player is moved to layer 31 and in it's place is an animation, giving the bounce effect. So I really have no reason or need to calculate the bounce vector.


See I have 4 animations, for each possible direction. If the class and normals on collision match, the player "bounces", problem is, the "bounce" does not occur as often as I would like.


One thing of note, perhaps this will give you insight is that it usually always occurs when colliding with a certain enemy class. This particular class is quite large, so if "traveling thru the enemy on collision, onUpdate(where the cast collision occurs) has more time to calculate numbers. If this is something that should be considered please let me know. If it is, is there a way to "elongate" the time my player is in contact with a "smaller enemy"?