HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Bouncing off of a Terrain Type

06-01-2008, 03:46 PM#1
Here-b-Trollz
We all know that there are lots of object engines out there that can move stuff around in three dimensions and calculate with decent accuracy approximately how an object would bounce off of a plane drawn in three dimensions. If that was the issue I could go rip out the formulas/calculations from one of those systems and cannibalize them. However, I have a problem which should, in essence, be easier, but I can't figure out.

I'm making a map specific knockback system to help encompass the issue. Essentially, I want units to be able to be knockback'ed in any direction, and, when that unit collides with a terrain type, it is bounced away from the terrain type. The issue I'm running into is finding some sort of angle to bounce the unit off of - I've searched the forums, but come up with unsatisfying results from a couple of years ago: 'if X then flip X speed, if Y then flip Y speed' etc.

A picture is worth a thousand words

Red represents the path of the footman, while blue draws the angle of the wall he is bouncing off of, and its perpendicular (which the red angle is reflected across).

Zoom (requires log in)


Things I have to work with:
  • unit
  • angle (radians)
  • speed
or:
  • unit
  • X speed
  • Y speed
I'm flexible. Any help with deriving the angle of the wall the unit is colliding with would be much appreciated (or if you have a way to get the perpendicular of that angle, since that is the ultimate goal).
Attached Images
File type: jpgExample.jpg (57.6 KB)
06-01-2008, 05:23 PM#2
Ammorth
There is a slight problem. Terrain-types (although look nice and smooth) are actually squares, so you can only bounce of the square, not off the diagonal bit (second bounce).

As for detection, check if points x+n, x-n, y+n, y-n are a certain terrain type. If they are, do your collision in that axis.
06-01-2008, 06:04 PM#3
emjlr3
what I use, which is something that is fairly accurate and easy on the eyes, is as follows:

new_angle = 2*(angle from point heading to current point)+180 - old_angle

where all directions and angles are in degrees

as suggested above, find a point maybe 100-150 distance into the future, check the terrain type, if the unit should bounce, use this to get a rough estimate of the new angle it should be heading after the bounce
06-01-2008, 06:18 PM#4
grim001
I don't think emjlr3's formula has any basis in reality so it might look OK sometimes and look horrible at other times.

Anyway, this is not possible to do the way you are trying to do it because the pathability is determined in square-shaped chunks. You can get approximations but it isn't going to look exact.

The only precise way would be to literally map out every collidable polygon on the map then use GroupEnumUnitsInRect + math to figure out if collisions are occurring. This could work, but depending on the map design it may or may not be too laggy.

An easier way to do this with accuracy would be to use cliffs instead of tiles if you map design allows for that. Cliffs can be detected and bounced off of with perfect accuracy using GetTerrainZ.
06-01-2008, 07:28 PM#5
rulerofiron99
This is genious.

About the cliffs, what would work better is to just have all the black areas one height click lower (not using cliffs), and then simple check if the locZ is 0 or not.

Maybe give this system a try: http://www.wc3campaigns.net/showthread.php?t=96543 (outside/inside polygon detect), and check if the point in the future to see if it's inside or not.
06-01-2008, 07:32 PM#6
grim001
Quote:
Originally Posted by rulerofiron99
About the cliffs, what would work better is to just have all the black areas one height click lower (not using cliffs), and then simple check if the locZ is 0 or not.

I thought about that, but you can't modify height on a per-pixel basis, it is interpolated from the center of the tile. So it's not going to be perfectly accurate either.
06-01-2008, 07:50 PM#7
Anitarf
I find the easiest way to do bouncing like this is with different heights and using vectors, if you get the terrain normal on an area with different heights the normal will not be vertical, but at an angle, so if you then project it onto the XY plane by setting it's Z to 0 then this vector will be perpendicular to your "wall" made of higher ground. Since the terrain normal is determined by comparing the height of some points around the target point, you might get some erratic results depending on how complicated your terrain height map is and how large your sample radius, but on simple walls the effect is fairly straightforward, as is shown by the laser gun in Elimination Tournament.
06-01-2008, 07:58 PM#8
Captain Griffen
Quote:
Originally Posted by Anitarf
I find the easiest way to do bouncing like this is with different heights and using vectors, if you get the terrain normal on an area with different heights the normal will not be vertical, but at an angle, so if you then project it onto the XY plane by setting it's Z to 0 then this vector will be perpendicular to your "wall" made of higher ground. Since the terrain normal is determined by comparing the height of some points around the target point, you might get some erratic results depending on how complicated your terrain height map is and how large your sample radius, but on simple walls the effect is fairly straightforward, as is shown by the laser gun in Elimination Tournament.

It is entirely possible to get the extact terrain height and normal for any point if necessary. If anyone needs it, I made a function to get the exact terrain height of any point; that could be quite simply converted to give the terrain normal.

Basically, just take the three corners of the triangle that the target point is currently on.
06-01-2008, 10:39 PM#9
emjlr3
Quote:
I don't think emjlr3's formula has any basis in reality so it might look OK sometimes and look horrible at other times.

i have yet to see an instance where it works less then believable

I have done this exact thing in the past with great success (of course its not 100%, but cmon this is WC3)

just check the z loc 100 or so in advance, if its greater then 24. or so larger then your current z, use my formula on your current point and future point

since you are using straight tiles it should work even better then the oblong I have
06-02-2008, 12:43 AM#10
Here-b-Trollz
Quote:
Originally Posted by Captain Griffen
It is entirely possible to get the extact terrain height and normal for any point if necessary. If anyone needs it, I made a function to get the exact terrain height of any point; that could be quite simply converted to give the terrain normal.

Basically, just take the three corners of the triangle that the target point is currently on.

If you'd be so kind as to post/send a function which uses three points to get a terrain normal, that'd be pretty awesome, even if only because I'm curious as to how you do it with three points. I understand that a plane only needs three points to be defined, but really all this math is beyond me and I have to get by through trial and error and stealing of code.

Assuming I'm using X speed and Y speed, what do I need to do with the terrain normal to project these speeds across that perpendicular (blue) line? I would assume multiplication, but assuming has gotten me nowhere thus far. For instance, I assumed I'd be able to make this work on my own, but, seeing as how I don't even really know what terrain normal means....
06-02-2008, 07:56 AM#11
Captain Griffen
Well, in this case you're working in 2d, I think? Then you don't need to deal with the Z at all. Hmm...I'll see if I can make what you need.
06-02-2008, 11:42 AM#12
Here-b-Trollz
Quote:
Originally Posted by Captain Griffen
Well, in this case you're working in 2d, I think? Then you don't need to deal with the Z at all.

That is correct.
06-02-2008, 12:50 PM#13
emjlr3
thats right, completely ignore my post, that is tested working, and could be implemented and tested in your map in a matter of minutes

entirely up to you, I'm just saying....

btw, could also just use getterraintype as opposed to loc z
06-03-2008, 01:45 AM#14
Here-b-Trollz
From what I can guess, GetLocZ is likely to be much more accurate, since it's got a slight bend effect around corners. I didn't disregard your post, but you suggested the same thing that I discovered from a couple years back in the 'archives' of back then :p

Hopefully this will achieve a much more reliable effect.
06-22-2008, 03:01 PM#15
Here-b-Trollz
I figured out how to do this. It's simple pathing checks like those used by the laser in ET. I just used UMSWE to change the pathing of my desired bouncy terrain to unpathable, and now my units bounce off of it.

It requires you to store x speed and y speed. Then:

Collapse JASS:
local real x=GetUnitX(u)
local real y=GetUnitY(u)
local real x2=x+velocityx
local real y2=y+velocityy

if(not PathabilityCheck(x2,y))then
    set velocityx=-velocityx
endif
if(not PathabilityCheck(x,y2))then
    set velocityy=-velocityy
endif
if(PathabilityCheck(x2,y2))then
    call SetUnitX(u,x2)
    call SetUnitY(u,y2)
endif

And then of course you need to factor in decay and find out when the unit is no longer moving, but that's the basis of it.