Code Snippet #1
April 15th, 2008 Michael Schwarz and categorized as 3DGS
Hereby I introduce the new code snippets section. Today serving you a Half-Life like movement script.
This script works different than most movement scripts, as it uses vec_accelerate instead directly passing the speed to the c_move parameters, thus creating a move natural movement.
More after the click:
First off we want to set a few constants, aswell as a few dynamic variables which we will later use in the script. Using defined constants makes it easier to read the script as it does make it easier to later modify a specific value without having to crawl through the whole script to find a specific value.
1: define true, 1;
2: define false, 0;
3:
4: define relSpeed_x,skill7;
5: define relSpeed_y,skill8;
6: define relSpeed_z,skill9;
7: define absSpeed_x,skill10;
8: define absSpeed_y,skill11;
9: define absSpeed_z,skill12;
10: define P_Speed,skill13;
11: define P_AngSpeed,skill14;
12: define P_Weight,skill15;
13: define P_Friction,skill16;
14:
15: var GLOB_BkgColor[3];
16: var PHY_Gravity[3];
17: var MOV_Playerspeed = 25;
18: var MOV_Turnspeed = 10;
19: var MOV_MaxUpAngle = 90;
20: var MOV_MaxDownAngle = -90;
21: var MOV_ShiftFactor = 1.35;
So, I use the opportunity to set up my standard defines for true and false, which I prefer to use over 1/0 or on/off respectively.
We store the player input in an imaginary vector called “relSpeed” in the skills of the entity, for the sake of being able to have a better accessibility for external events.
Global acceleration, like gravity, is passed by the absSpeed vector.
Then we have the values P_Speed, P_AngSpeed, P_Weight and P_Friction. P_Speed indicating the current speed the player is moving and P_AngSpeed indicating the speed the player is turning around.
Now we have some dynamic variables that are part of the movement system:
- GLOB_BkgColor[3] : Actually just for defining the sky color.
- PHY_Gravity[3] : We will define the values for this at game start. It’s as the name says the gravity.
- MOV_Playerspeed : You will have to play with this value, as it defines how fast your player will move.
- MOV_Turnspeed : You have to play with this value too. Defines the speed you will turn/look around.
- MOV_MaxUpAngle : The maximal angle you can look upwards.
- MOV_MaxDownAngle : The maximal angle you can look downwards.
- MOV_ShiftFactor : The factor the MOV_Playerspeed gets multiplied by when holding the shift key. Use a value over 1.00 to accelerate the movement when pressing this key, or a value below 1.00 if you want the player to slow down when you press the shift key.
Now comes the main function for the whole thing, it is actually this function that does most of the difference to other movement codes:
1: function FNC_ApplyPhysics(ent, enablePoly)
2: {
3: me = ent;
4: vec_set(me.absSpeed_x, PHY_Gravity.x);
5:
6: while(me)
7: {
8: c_move(me, nullvector, me.absSpeed_x, IGNORE_SPRITES);
9: c_move(me, me.relSpeed_x, nullvector, IGNORE_SPRITES|GLIDE);
10: wait(1);
11: }
12: }
As the commentary says, we use c_move twice here. One time for the absolute speed and one time for the relative speed. This is necessary as for the normal “movement” we need the GLIDE flag, or else we would become stuck in edges; and honestly you would actually not even move without it. Then we need the second c_move without the GLIDE flag because else you wouldn’t be able to walk up stairs or ledges.
And finally, the main movement code:
1: function FNC_MoveWASD(ent)
2: {
3: // :: Assign ME pointer to entity.
4: me = ent;
5:
6: // :: Main loop
7: while(me)
8: {
9: // :: Rotate camera
10: camera.pan += -((mouse_force.x * MOV_Turnspeed) * time_step);
11:
12: // :: Assign camera pan to entity pan
13: me.pan = camera.pan;
14:
15: // :: Camera Tilting
16: // : If Camera tilt is over or under maximal tilt angles
17: if(camera.tilt > MOV_MaxUpAngle || camera.tilt < MOV_MaxDownAngle)
18: {
19: if(camera.tilt > MOV_MaxUpAngle)
20: {
21: // :: If it is over the maximal upper limit
22: camera.tilt = int(camera.tilt - 2*time_step);
23: // : Limit mouse movement
24: if(mouse_force.y < 0){camera.tilt += ((mouse_force.y * MOV_Turnspeed) * time_step);}
25: }
26: else
27: {
28: // :: If it is over the maximal lower limit
29: camera.tilt = int(camera.tilt + 2*time_step);
30: // : Limit mouse movement
31: if(mouse_force.y > 0){camera.tilt += ((mouse_force.y * MOV_Turnspeed) * time_step);}
32: }
33: }
34: else
35: {
36: // :: Else
37: // : Free tilting
38: camera.tilt += ((mouse_force.y * MOV_Turnspeed) * time_step);
39: }
40:
41: // :: If camera roll is not equal to 0°
42: if(camera.roll != 0)
43: {
44: // :: And if camera roll is higher or equal to 180°
45: if(camera.roll >= 180)
46: {
47: // : Roll clockwise
48: camera.roll = int(camera.roll + 2*time_step);
49: }
50: else
51: {
52: // :: else
53: // : roll counter-clockwise
54: camera.roll = int(camera.roll - 2*time_step);
55: }
56: }
57:
58: vec_accelerate(my.relSpeed_x, my.P_Speed, vector(((key_w-key_s)*MOV_Playerspeed*(1+key_shift*MOV_ShiftFactor))*time_step, ((key_a-key_d)*MOV_Playerspeed*(1+key_shift*MOV_ShiftFactor))*time_step, me.relSpeed_z), 0.5);
59: wait(1);
60: }
61: }
62:
63: function FNC_AttachCam(ent, z_offset)
64: {
65: me = ent;
66: vec_set(camera.x, vector(me.x, me.y, me.z));
67: if(!key_ctrl){ camera.z += z_offset; }
68: }
69:
70: action ACT_Player
71: {
72: player = me;
73: FNC_ApplyPhysics(player, false);
74: FNC_MoveWASD(player);
75:
76: camera.genius = player;
77:
78: while(1)
79: {
80: FNC_AttachCam(player, 35);
81: wait(1);
82: }
83: }
In the action ACT_Player you might want to change the second parameter of the FNC_AttachCam inside the while-loop, it defines the height of the camera from the origin of the player, so depending of the size of your player model this value can vary.
Inside your main function, you will also need to include the following BEFORE loading any level:
1: PHY_Gravity[0] = 0;
2: PHY_Gravity[1] = 0;
3: PHY_Gravity[2] = (-9.8);
4:
5: camera.arc = 75;
6: fps_max = 60;
7: fps_min = 35;
8: fps_lock = on;
This defines the Gravity. The value of (-9.8) should be adequate to the real earth gravity when using the Warlock/Cbabe/Guard model as reference. The FOV is set to 75, as it gives the whole thing a more natural feeling overall and we set an FPS lock so the movement doesn’t get jumpy or jerky whenever your FPS should rise or fall unexpectedly.
Now just attach the ACT_Player action to your player model in WED and have some Half-Life-Movement-Fun !
Stay tuned for the upcoming issue #2 of Code Snippets!
This article has been read 1233 times
Does this all go into one file? Is this saved as ACT_Player.wdl?
I guess I need to be more advanced to understand exactly what to do but getting to that point seems almost impossible with all the old tutorials that do not work.
It might be helpful if you had links to the files that were already finished as you cannot copy and paste this code into the script editor.
I do think this is awesome and I hope to figure it out so I can use it and learn a little finally.
Thanks,
Kevin
Hi!
Yes everything comes in one file with exception for the last snippet box, which comes into your main function (as the comment says)
Well, I made it “un-copiable” exactly for the reason that you learn better if you copy something by typing it, instead of copy+paste.
But if you really insist, I can upload you the file.
Anyway, I would suggest you to copy it. It’s the better way to learn. As you type, you realize what has to do with what. You recognize the conjunctions faster and better as if you would just copy and paste and run it ;)
I do see your point about typing but when you have a 30 day trial and your on day 12 and you still can’t figure out how to make something work, then you want to copy and paste.
I did copy it and then got rid of the numbers (1:, etc.)
Now to give it a try. Thanks!
Ah sorry, I didn’t know you only had a trial.
Anyway, If you still need the complete script or any help with it, dont hesitate to ask!
Thank you so much it works!
You’re welcome anytime!
This script is great, but is there a place to download it from as a working .c file because i meet difficulty with the defining. There are some syntax errors I can’t fix.