Raised This Month: $19 Target: $400
 4% 

Half-Life Position, Velocity, and Angles (for n00bs)


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
stupok
Veteran Member
Join Date: Feb 2006
Old 05-01-2009 , 15:32   Half-Life Position, Velocity, and Angles (for n00bs)
Reply With Quote #1

Half-Life Position, Velocity, and Angles

This guide is intended for newbies with a desire to learn about position, velocity, and angles. The goal is for you to be comfortable manipulating these variables in Pawn in AMXx in Half-Life.


Dimensions

dimension - a property of space; extension in a given direction

  • 0th dimension


There really is no dimension here--it's the 0th dimension, after all. You can think of it as an infinitely small point. It does not extend in any direction.

We cannot specify a location in this dimension.


  • 1st dimension


Now we have a line in one direction. You can only change the length of the line. Many problems in physics are idealized to one-dimensional problems for simplicity. For example, falling bodies are often idealized to fall straight down with no deviation.

We can specify a location in this dimension with one number.

For example, a straight line starting from your floor going up to your ceiling. Let's say the floor is 0, the ceiling might be 2.5 (in meters, let's say). Any point in between would be between 0 and 2.5.

In code, you can hold the position with a variable like this:

Code:
new Float:fHeight

I'm only talking about the first dimension, so, strictly speaking, there is no explicit direction. You can only go back and forth.

However, you can say the variable from my example exists in the Y-direction because our world is in three dimensions and saying "Y-direction" implies that we are talking about going up and down, in general.

Depending on the context, you might say that a one-dimensional variable is in the X-direction or Z-direction. Typically, you only say that it is in the X or Y directions.


  • 2nd dimension


Finally! Now we can move up, down, left, and right (and any combination of these directions). More complicated physics problems are idealized in two dimensions. For example, a projectile's motion is idealized in two dimensions.

We can specify a location in two dimensions with a pair of numbers. We call this pair of numbers coordinates. In writing, you usually see coordinates written like this (X, Y). The X-direction means left and right. The Y-direction means up and down.

In code, you can hold the position with a variable like this:

Code:
new Float:fPosition[2]

The variable is called an array and it holds two values. The first value, fPosition[0], should hold the position in the X-direction. The second value, fPosition[1], should hold the position in the Y-direction. (You can also use [1] for the X-direction and [0] for the Y-direction, but it's nice to do things in a standard way so others can understand your code quickly.)

Code:
public MakeHudMessage( id ) {     // X values range from 0 to 1, 0 is left edge of the screen, 1 is right edge of the screen     // Y values range from 0 to 1, 0 is top edge of the screen, 1 is bottom edge of the screen         new Float:fPosition[2]         fPosition[0] = 0.2 // x position     fPosition[1] = 0.5 // y position         set_hudmessage( 200, 100, 0, fPosition[0], fPosition[1], 0, 6.0, 12.0, 0.1, 0.2, 4 )         // red = 200, green = 100, blue = 0     // x position = 0.2, y position = 0.5     // effects = 0     // fxtime = 6.0     // holdtime = 12.0     // fadeintime = 0.1, fadeouttime = 0.2     // channel = 4         show_hudmessage( id, "Hi this is a hudmessage!" ) }

set_hudmessage prepares a hud message with position, color, effects, and time
show_hudmessage shows text in the way specified by set_hudmessage


  • 3rd dimension


OH BOY! Now we can move up, down, left, right, forwards, backwards AND any combination of these directions.

We can specify a location in three dimensions with a group of three numbers. In writing, you usually see coordinates written like this (X, Y, Z). The Z-direction means forwards and backwards.
BUT WAIT! The Z-direction means forwards and backwards in the picture above, but it actually means up and down in Half-Life. Why? The programmers of Half-Life decided to make the Z-direction up/down. So, forward/back/left/right are handled with the X and Y directions.
In code, you can hold the position in three dimensions with a variable like this:

Code:
new Float:fPosition[3]

fPosition[0] holds the position in the X-direction, fPosition[1] holds the position in the Y-direction, and fPosition[2] holds the position in the Z-direction.

Code:
public PlayWithOrigins( id ) {     new iOrigin[3]     get_user_origin( id, iOrigin )         // move the player 20 units in the Z-direction (upwards)     iOrigin[2] += 20         set_user_origin( id, iOrigin ) }

Vectors

So far, I've covered the 0th, 1st, 2nd, and 3rd dimensions. The code examples have dealt with coordinates representing positions, but I have hinted at a different use for three-dimensional arrays with my physics examples.

You need to learn two new words: vector and scalar

vector - a quantity possessing both magnitude and direction, represented by an arrow the direction of which indicates the direction of the quantity and the length of which is proportional to the magnitude

scalar - representable by position on a scale or line; having only magnitude

When we are dealing with positions, like the position of a player in a map or the position of text on the screen, we are dealing with scalar quantities. Scalar values have no direction, only magnitude (size). When you say a player is located at (X, Y, Z), you know nothing about whether or not he is moving. If he is moving, you don't know where.

Velocity is a vector quantity. Let's jump into an example:

Code:
new Float:fVelocity[3] pev( id, pev_velocity, fVelocity )

pev is a FakeMeta function used to retrieve values from entities
pev_velocity tells pev() which value we are retrieving
fVelocity holds the value we are retrieving, it must be a 3-dimensional array

After executing this code, let's say that our velocity is now (100, 200, 0). This means we have a velocity in the X-direction of 100 units per second, a Y-velocity of 200 units per second, and a Z-velocity of 0 units per second. The numbers directly indicate the magnitude of the velocity. How can we find the direction? (Vector values have both magnitude AND direction.)

Here is the situation, in picture form:



Notice that the vectors both start at the origin (0, 0, 0) and extend away from it.

To get the direction, you must combine all three component vectors (X, Y and Z) into one. (Components are pieces.)



So, now we can see that fVelocity holds a vector value. That means you can discover the magnitude AND direction of the velocity by interpreting the values it holds.
  • Speed versus Velocity

They are not the same. Speed is a scalar quantity and velocity is a vector quantity. You can store speed in a variable like this:

Code:
new Float:fSpeed

To store velocity, you must have a variable like this:

Code:
new Float:fVelocity[3]

Speed means distance/time, like miles per hour (mph) or meters per second (m/s). It does not tell you where you are going.

Velocity, when you're NOT dealing with code, is written in two parts. First, you say the speed like 40 mph (yes, speed is one part of velocity). Next, you must say the direction. For example, North. When we're dealing with code, you don't have two parts. Instead, you have to interpret the 3 values to figure out speed and direction.
  • Extracting Speed from Velocity

Remember Pythagoras? He has this nifty theorem:

Code:
c * c = a * a + b * b
In English: C squared equals a squared plus b squared

If you glance at the above image with the red, green, and pink arrows, you can see how this works. C is the length of the pink arrow, a is the length of the green arrow, and b is the length of the red arrow.

In three dimensions, it's like this:

Code:
hypotenuse * hypotenuse = x * x + y * y + z * z
(Hypotenuse is a fancy word for the sloped part of a right triangle. A right triangle is a triangle with a 90 degree angle.)

Here's what we were looking for:

Code:
speed * speed = x vel * x vel + y vel * y vel + z vel * z vel
Or, in real code:

Code:
new Float:fVelocity[3] // store some velocity into fVelocity // slow, inefficient way (but you get to see what it looks like) New Float:fSpeed = floatsqroot( fVelocity[0] * fVelocity[0] + fVelocity[1] * fVelocity[1] + fVelocity[2] * fVelocity[2] ) // fast, efficient way New Float:fSpeed = vector_length( fVelocity )
  • Extracting Direction from Velocity

We don't have North, South, East, and West in Half-Life. We just have angles, so that's how we'll represent the direction of our velocity.

The math is more complicated, so let's leave it at this:

Code:
new Float:fVelocity[3] new Float:fAngle[3] // store some velocity vector_to_angle( fVelocity, fAngle )
  • Example

So, let's do something useful useless with our new knowledge. We are going to save the player's position, launch him in a random direction, and finally move him back to his original position.

Code:
public UselessFunction( id ) {     new Float:fOrigin[3]     new Float:fVelocity[3]         // save his origin     pev( id, pev_origin, fOrigin )         // create a random velocity     fVelocity[0] = random_float( 100.0, 500.0 ) * ( random_num(0,1) ? 1.0 : -1.0 )     fVelocity[1] = random_float( 100.0, 500.0 ) * ( random_num(0,1) ? 1.0 : -1.0 )     fVelocity[2] = random_float( 100.0, 500.0 ) * ( random_num(0,1) ? 1.0 : -1.0 )         // set his velocity, WOOSH     set_pev( id, pev_velocity, fVelocity )         // put him back to his original position in 2.0 seconds     set_task( 2.0, "PutMeBackPLZ", id, _:fOrigin, 3 ) } public PutMeBackPLZ( iOrigin[3], id ) {     // set his origin, YAWN     set_pev( id, pev_origin, iOrigin ) }

set_pev is a FakeMeta function used to set various values for entities
random_float generates a random number between two numbers
random_num does the same thing, but returns an int rather than a float
set_task is used to call a function after a few seconds


Angles

There is another use for three-dimensional arrays (variables like fVelocity[3]). They are used to store an entity's angles.
  • Pitch, Yaw, and Roll

I'm going to use your imagination to make this easy to understand. Imagine a hotdog and place it on the desk in front of you with one end pointing at the monitor.

pitch - lift one end of the hotdog while the other end stays on the desk
PUT IT BACK DOWN!
yaw - now, spin the hotdog on the desk
POINT IT AT THE MONITOR AGAIN!
roll - now, roll the hotdog along the desk

Now do the same actions you did to the hotdog, but move your head instead of the hotdog. (Tilt your head up/down, rotate left/right, and then roll it.) You should begin to feel a sort of satisfaction now that you understand the meaning of pitch, yaw, and roll. If not, yell at me.

Here's a nice image that explains pitch, yaw, and roll. Thanks arkshine! (And thanks to the creator, whoever it is.)


In Half-Life, the angles are stored thusly:

Code:
new Float:fAngle[3] fAngle[0] // pitch fAngle[1] // yaw fAngle[2] // roll

You can use pev() to retrieve the angles, just like we did with velocity or origin, but there are several different angles in Half-Life. You'll have to experiment with them to get a good idea of the purpose they serve.

pev_angles - orientation of the entity
pev_v_angle - orientation of the camera, (player's view), v_angle = view angle
pev_punchangle - deviation from the view angle (POW! I punched you in the kisser and now your face rotated over there but you will slowly return back to your v_angle)

You can get/set these just like the others, with FakeMeta or Engine:

Code:
// FakeMeta new Float:fAngles[3] pev( id, pev_angles, fAngles ) set_pev( id, pev_angles, fAngles ) // Engine entity_get_vector( id, EV_VEC_angles, fAngles ) entity_set_vector( id, EV_VEC_angles, fAngles )
  • Normal

What's a normal? Is it the opposite of a weird? Wow, I'm tired.

More vocabulary for your hungry, hungry mind:

plane - a flat or level surface

normal - the dictionary definition is confusing, so here's mine: a line that is perpendicular to the plane

Why is this useful? Well, it get's complicated.
  • Example

My Wall Text plugin makes use of positions, vectors, angles, and normals.

The goal of the plugin is to aim at a wall and paint text on it.

Here's the step-by-step process:

1. Get the position on the wall where the user is aiming.
2. Get the normal of the wall. (The wall is a plane and the normal points out of the wall into the world where the player exists.)
3. Make a vector pointing the to left (from the perspective of the wall's normal).
4. PAINT!
5. Move over to the left, using the vector we calculated.
6. Repeat steps 4-5 until finished.

If you're observant, you'll notice that I've neglected to do this calculation for sloped surfaces like ramps. The plugin will work for perfectly vertical walls at any angle, but it will fail if you want to do a multi-line message on a sloped wall like a ramp, because I was too lazy to write the extra code.

Here's the code:

Code:
CreateNewMessage( id, szMessage[MESSAGE_LEN] ) {     new Float:fAimOrigin[3]     new Float:fPlayerOrigin[3]         new Float:fAimVector[3]     new Float:fNormalVector[3]     new Float:fTextVector[3]         // user's view angle     pev( id, pev_v_angle, fAimVector )         // vector pointing in that direction     angle_vector( fAimVector, ANGLEVECTOR_FORWARD, fAimVector )         // user's origin     pev( id, pev_origin, fPlayerOrigin )         // lengthen vector and move it to user's origin     fAimVector[0] = fAimVector[0] * 9999.0 + fPlayerOrigin[0]     fAimVector[1] = fAimVector[1] * 9999.0 + fPlayerOrigin[1]     fAimVector[2] = fAimVector[2] * 9999.0 + fPlayerOrigin[2]         // execute traceline, grab normal vector and end position     new iTr = create_tr2()     engfunc( EngFunc_TraceLine, fPlayerOrigin, fAimVector, IGNORE_MONSTERS, id, iTr )     get_tr2( iTr, TR_vecEndPos, fAimOrigin )     get_tr2( iTr, TR_vecPlaneNormal, fNormalVector )     free_tr2( iTr )         // convert normal vector to angles     vector_to_angle( fNormalVector, fTextVector )         // get vector pointing to the right, from the perspective of the normal vector     angle_vector( fTextVector, ANGLEVECTOR_RIGHT, fTextVector )         // lengthen by width of one character, and point towards the left (from the perspective of the normal vector)     fTextVector[0] *= -1.0 * CHAR_WIDTH     fTextVector[1] *= -1.0 * CHAR_WIDTH     fTextVector[2] *= -1.0 * CHAR_WIDTH         // ... }
__________________

Last edited by Arkshine; 03-01-2016 at 07:36.
stupok is offline
TitANious
Veteran Member
Join Date: Feb 2009
Location: Denmark
Old 05-01-2009 , 15:33   Re: Half-Life Position, Velocity, and Angles (for n00bs)
Reply With Quote #2

Would help others GJ
__________________
I dislike this.

"A sneeze never comes alone!" <-- Important to remember.
TitANious is offline
Send a message via MSN to TitANious
joaquimandrade
Veteran Member
Join Date: Dec 2008
Location: Portugal
Old 05-01-2009 , 15:34   Re: Half-Life Position, Velocity, and Angles (for n00bs)
Reply With Quote #3

First. I will read it now.

Edit: fuck
__________________
joaquimandrade is offline
stupok
Veteran Member
Join Date: Feb 2006
Old 05-01-2009 , 15:34   Re: Half-Life Position, Velocity, and Angles (for n00bs)
Reply With Quote #4

Quote:
Originally Posted by joaquimandrade View Post
First. I will read it now.
lol, you have bad luck trying to be the first to post on my threads.
__________________
stupok is offline
joaquimandrade
Veteran Member
Join Date: Dec 2008
Location: Portugal
Old 05-01-2009 , 15:36   Re: Half-Life Position, Velocity, and Angles (for n00bs)
Reply With Quote #5

Quote:
Originally Posted by stupok View Post
lol, you have bad luck trying to be the first to post on my threads.
lol. so true.
__________________
joaquimandrade is offline
TitANious
Veteran Member
Join Date: Feb 2009
Location: Denmark
Old 05-01-2009 , 15:37   Re: Half-Life Position, Velocity, and Angles (for n00bs)
Reply With Quote #6

Quote:
Originally Posted by joaquimandrade View Post
First. I will read it now.

Edit: fuck
YES!
__________________
I dislike this.

"A sneeze never comes alone!" <-- Important to remember.
TitANious is offline
Send a message via MSN to TitANious
xPaw
Retired AMX Mod X Moderator
Join Date: Jul 2008
Old 05-01-2009 , 15:44   Re: Half-Life Position, Velocity, and Angles (for n00bs)
Reply With Quote #7

PutMeBackDammit!
__________________
xPaw is offline
Arkshine
AMX Mod X Plugin Approver
Join Date: Oct 2005
Old 05-01-2009 , 15:49   Re: Half-Life Position, Velocity, and Angles (for n00bs)
Reply With Quote #8

Woo.~~
Arkshine is offline
Emp`
AMX Mod X Plugin Approver
Join Date: Aug 2005
Location: Decapod 10
Old 05-01-2009 , 16:16   Re: Half-Life Position, Velocity, and Angles (for n00bs)
Reply With Quote #9

Code:
    set_task( 2.0, "PutMeBackDammit", id, fOrigin, 2 )
}

public PutMeBackDammit( fOrigin[3], id )
You are passing fOrigin into set_task (will give you warning tag mismatch). Either use _: or convert it to an int vector first.
Secondly, you are only passing the first 2 dimensions through the set_task.
Also, in PutMeBackDammit fOrigin[3] should be iOrigin[3] since it isn't really declared a float.

I would suggest adding mins/maxs in the angles section.

And lastly, clean up your language, it's a little annoying with all the "dammit"s.

Anyway, cheers for the tut.
Emp` is offline
Send a message via AIM to Emp` Send a message via MSN to Emp` Send a message via Yahoo to Emp` Send a message via Skype™ to Emp`
stupok
Veteran Member
Join Date: Feb 2006
Old 05-01-2009 , 16:36   Re: Half-Life Position, Velocity, and Angles (for n00bs)
Reply With Quote #10

Thanks for catching the mistakes. I used "dammit" with the intention of adding some humor to an otherwise boring read. Maybe you're right that it's inappropriate, so I've removed all of the occurrences.

I'll cover mins/maxs shortly.

Thanks!
__________________
stupok is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 04:09.


Powered by vBulletin®
Copyright ©2000 - 2021, vBulletin Solutions, Inc.
Theme made by Freecode