Suspension script

Suspension script

Discuss game development here, from a distinct game project to an accessible third-party mutator, down to the interaction and design of individual units if you like.

Moderator: Moderators

User avatar
Zpock
Posts: 1218
Joined: 16 Sep 2004, 23:20

Suspension script

Post by Zpock »

http://www.youtube.com/watch?v=cN1vt01mmcU

Here is a demonstration model + script, you will need to write an fbi and stuff to make it work if you want to test it.

Image

Image

The idea is that every wheel has a spring that pushes against the hull of the vehicle, so it bumps around. The spring force is normally proportional to it's displacement. First off we need these objects and variables:

Code: Select all

#define TA			// This is a TA script

#include "sfxtype.h"
#include "exptype.h"

piece  ground, hull, turret, gun, flare, wheel1, wheel2, wheel3, wheel4, wheel5, wheel6, susp1, susp2, susp3, susp4, susp5, susp6, gs1, gs2, gs3, gs4, gs5, gs6;

static-var  moving, xtilt, xtiltv, xtilta, ztilt, ztilta, ztiltv, ya, yv, yp, s1, s2, s3, s4, s5, s6, damp;

// Signal definitions
#define SIG_AIM				2

#define   ANIM_VARIABLE   Moving 
#undef   ANIM_VARIABLE 
As you can see I have added empty objects in the model, gs1, gs2 etc, those are the "ground sensors" that check the height at the locations of the wheels. This was a quick hack so it's certainly possible to reduce the nunmber of separate objects in different ways. The variables s1, s2, s3 etc is the displacement of each wheel/spring, wich I will show how to compute shortly. xtilt, xtiltv, xtilta etc are the current value, speed, and acceleration of the different axes that the hull can turn, and move. Notice that the body can rotate around both the zaxis, xaxis, and move up/down. Next is the suspension function itself:


Code: Select all

Suspension() 
{
	while(1)
	{
		
		s1 = get GROUND_HEIGHT(get PIECE_XZ(gs1)) - get PIECE_Y(gs1);
		if(s1 < [-2])
		{
			s1 = [-2];
		}

		s2 = get GROUND_HEIGHT(get PIECE_XZ(gs2)) - get PIECE_Y(gs2);
		if(s2 < [-2])
		{
			s2 = [-2];
		}

		s3 = get GROUND_HEIGHT(get PIECE_XZ(gs3)) - get PIECE_Y(gs3);
		if(s3 < [-2])
		{
			s3 = [-2];
		}

		s4 = get GROUND_HEIGHT(get PIECE_XZ(gs4)) - get PIECE_Y(gs4);
		if(s4 < [-2])
		{
			s4 = [-2];
		}

		s5 = get GROUND_HEIGHT(get PIECE_XZ(gs5)) - get PIECE_Y(gs5);
		if(s5 < [-2])
		{
			s5 = [-2];
		}

		s6 = get GROUND_HEIGHT(get PIECE_XZ(gs6)) - get PIECE_Y(gs6);
		if(s6 < [-2])
		{
			s6 = [-2];
		}
Here we compute the different values for s1, s2... etc. Pretty straightforward, but notice that the if:s put a lower bound on how far down the wheels can go, this is important. The result is that sometimes, the wheel is in the air. One thing that can be improved is to add similar code here for the upper bound, this is when the suspension is overloaded and it should make a nasty bump...

Anyway, now we need to take into consideration the different spring displacements. The force from the spring is proportional to this displacement. The force can act in different ways, either giving a linear acceleration, or rotational acceleration on the body, depending on how it's distributed among the wheels/springs. This is just a quick hack to get something that looks like real physics, so I have opted to simply guess some values until i found some that works:

Code: Select all

		xtilta = 0 - (get ATAN(s1, [14]) - get ATAN(s3, [14]) + get ATAN(s4, [14]) - get ATAN(s6, [14]))/300 + xtiltv/7;
		xtiltv = xtiltv + xtilta;
		xtilt = xtilt + xtiltv*4;
The ATANs where mostly to get angles instead of displacement, not much tought went into those. Notice that s1 and s4 are the front wheels, s3 and s6 are the backmost wheels. The force from the front wheels act in the opposite direction as that from the back, hence the difference in signs here. The last term "xtiltv/7" is the dampening. Depending on how much this is, you get different effects, called subcritical, critical and supercritical dampening. In short, subcritical (too weak) will continue to oscillate for a while, critical will quickly return to a balanced state, while supercritical will again slowly return to the balanced state but withouth oscillating at all.

Computing the speed from the acceleration is straightforward, so is the actual tilt. Notice the *4 there, I found that experimenting with different values here will change the amplitude/frequency in a different way then changing the constant in the acceleration formula itself (/300 here). Then we compute the other tilts, and the displacement, in a similar fashion:

Code: Select all

		ztilta = 0 - (get ATAN(s1, [14]) + get ATAN(s2, [14]) + get ATAN(s3, [14]) - get ATAN(s4, [14]) - get ATAN(s5, [14]) - get ATAN(s6, [14]))/300 + ztiltv/7;
		ztiltv = ztiltv + ztilta;
		ztilt = ztilt + ztiltv*4;
		
		ya = (s1 + s2 + s3 + s4 + s5 + s6)/100 - yv/25;
		yv = yv + ya;
		yp = yp + yv/10;
		
		move ground to y-axis yp now;
		turn ground to x-axis xtilt now;
		turn ground to z-axis ztilt now;
Notice that for the displacement we don't need any ATANS or stuff, it's pretty straightforwardly just an average. Different combinations of spring forces could probably be used to get interesting effects, like weighing or such. Then the actual transformations are put into action. The x rotation followed by z rotation is imprecise and can lead to problems with very steep slopes, a more sophisticated way would be to use vector/matrix math to get the rotations done straight, but interestingly, the system is suprisingly good at overcoming these problems and self-correcting itself in a way!

The spring displacements are then recalculated and the wheels repositioned:

Code: Select all

		s1 = get GROUND_HEIGHT(get PIECE_XZ(gs1)) - get PIECE_Y(gs1);
		if(s1 < [-2])
		{
			s1 = [-2];
		}
		s2 = get GROUND_HEIGHT(get PIECE_XZ(gs2)) - get PIECE_Y(gs2);
		if(s2 < [-2])
		{
			s2 = [-2];
		}
		s3 = get GROUND_HEIGHT(get PIECE_XZ(gs3)) - get PIECE_Y(gs3);
		if(s3 < [-2])
		{
			s3 = [-2];
		}
		s4 = get GROUND_HEIGHT(get PIECE_XZ(gs4)) - get PIECE_Y(gs4);
		if(s4 < [-2])
		{
			s4 = [-2];
		}
		s5 = get GROUND_HEIGHT(get PIECE_XZ(gs5)) - get PIECE_Y(gs5);
		if(s5 < [-2])
		{
			s5 = [-2];
		}
		s6 = get GROUND_HEIGHT(get PIECE_XZ(gs6)) - get PIECE_Y(gs6);
		if(s6 < [-2])
		{
			s6 = [-2];
		}
		
		move wheel1 to y-axis s1 now;
		move wheel2 to y-axis s2 now;
		move wheel3 to y-axis s3 now;
		move wheel4 to y-axis s4 now;
		move wheel5 to y-axis s5 now;
		move wheel6 to y-axis s6 now;
		sleep 10;
I'm not sure if the recalculation here is necessary, this is just a quick hack as said, I havn't tried removing it yet. The short sleep ensures that this is computed pretty much every frame. I think this is necessary and that It dosn't really take that much performance, but I havn't done any testing on this. I tries putting in 100 units at the same time or so and noticed no more lag then usual. The rest of the script is the usual stuff, just making sure to start this script on creation. It could probably be stopped from running when idle, but with some time to let any remaining oscillations run for a while.

So there is a lot of improvement that could be made. I'm pretty sure this can be used for a great deal of stuff, including different wheel configuration and even tank tracks. I also think these ideas could be used for a truely awesome walking script for legged things as well, combined with the work on "true walkscripts". Also, the unit recoiling when fireing weapons, when hit, and when starting/stopping movement can surely be added in for great effect.
Last edited by Zpock on 12 Jun 2007, 17:48, edited 1 time in total.
User avatar
SwiftSpear
Classic Community Lead
Posts: 7287
Joined: 12 Aug 2005, 09:29

Post by SwiftSpear »

This looks pretty much liquid cool. Please post a youtube demo!
Lippy
Posts: 327
Joined: 16 Jul 2006, 00:24

Post by Lippy »

Hehe, that is awesome! Going down a hill at insane speed it seems to leave the ground on bumps and grab some air!
User avatar
rattle
Damned Developer
Posts: 8278
Joined: 01 Jun 2006, 13:15

Post by rattle »

Now make the wheels turn accordingly!

This thing reminds me strongly of zwzsg's armduck.
User avatar
Zpock
Posts: 1218
Joined: 16 Sep 2004, 23:20

Post by Zpock »

Youtube video up:

http://www.youtube.com/watch?v=cN1vt01mmcU

Yes, it can even make jumps, shown at the end of the video. I was shocked when I first saw it do that, hadn't thought about that.
pintle
Posts: 1763
Joined: 19 Dec 2005, 16:01

Post by pintle »

that is awesome, very nice work :)
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

Neat :-)

However, the serious designer side of me has to ask:

A. What happens when 100 of these are spawned?

B. Is there a simpler way to fake this, that will look reasonably good most of the time?

Because I suspect that the answer to A is, "you see large CPU usage for scripts, which is inherently bad", and that the answer to B is, "definitely yes".
User avatar
Zoombie
Posts: 6149
Joined: 15 Mar 2005, 07:08

Post by Zoombie »

Holy crap that is one of the coolest things I've ever seen. Can it work with tanks?
User avatar
Zpock
Posts: 1218
Joined: 16 Sep 2004, 23:20

Post by Zpock »

Argh wrote:A. What happens when 100 of these are spawned?

B. Is there a simpler way to fake this, that will look reasonably good most of the time?
I did a quick test, spawning 100 guys running around on victoria crater in the middle (no pathing issues) and scripts shows 15% CPU usage. I definitly think that it can be optimized a lot:

1: the math can probably be cut down a bit without downgrading it, for example get rid of the trigonometry.

2: i recalculated the springs after moving the body before moving the wheels, I think this can be cut without much trouble (I kinda made things up as I went, this was to try and stabilize it when i started, but I'm not sure it even does anything now.

3: the sleep could maybe be extended, to recaluclate fewer times withtout being noticable.

4: stop the script running when it's not needed... this needs a few checks tough.
User avatar
Dragon45
Posts: 2883
Joined: 16 Aug 2004, 04:36

Post by Dragon45 »

Argh-> For point A:
I tries putting in 100 units at the same time or so and noticed no more lag then usual. The rest of the script is the usual stuff, just making sure to start this script on creation. It could probably be stopped from running when idle, but with some time to let any remaining oscillations run for a while.
User avatar
1v0ry_k1ng
Posts: 4656
Joined: 10 Mar 2006, 10:24

Post by 1v0ry_k1ng »

finally wezels can have pro wheelz
User avatar
Neddie
Community Lead
Posts: 9406
Joined: 10 Apr 2006, 05:05

Post by Neddie »

1v0ry_k1ng wrote:finally wezels can have pro wheelz
Fo sho.
User avatar
Dragon45
Posts: 2883
Joined: 16 Aug 2004, 04:36

Post by Dragon45 »

dude - weezels, jeffies, trucks..

OP could really use this
incorporate in all units NOW! :O
User avatar
1v0ry_k1ng
Posts: 4656
Joined: 10 Mar 2006, 10:24

Post by 1v0ry_k1ng »

can someone see what it looks like when applied to tank treads? be sweet for 1944
User avatar
VonGratz
Posts: 471
Joined: 03 May 2005, 05:25

Post by VonGratz »

Congrats!
VERY well done!
VonGratz :wink:
User avatar
SwiftSpear
Classic Community Lead
Posts: 7287
Joined: 12 Aug 2005, 09:29

Post by SwiftSpear »

1v0ry_k1ng wrote:can someone see what it looks like when applied to tank treads? be sweet for 1944
Most tank treads don't animate in spring, and it's gonna take some magic to make the links flow naturally between the wheel components when they vary in height. Not saying it's impossible, but it's not a cut and paste job.
User avatar
Zpock
Posts: 1218
Joined: 16 Sep 2004, 23:20

Post by Zpock »

Yes, what to do with the threads themselves are the big question here. Might try and cut them in segments between the wheels. Might be costly with one ATAN evaluation for each segment, to put it in place, then it can get ugly if you want to do show/hide style animation as well, tough could perhaps just move the segments around a little to create the track animation too. Another option is to simply leave the threads flat and just move the wheels, this can look decent too and they even do it in CoH on the smaller tanks. They seem to be used a bones system for stuff like the tiger tough.

Anyway I can try scripting one of the s44 tanks if you want. Perhaps on the T-34 model? It has a nice simple wheel layout.

Image
imbaczek
Posts: 3629
Joined: 22 Aug 2006, 16:19

Post by imbaczek »

Cool.

BTW, Spring could use some engine-sanctioned IK... ::dreams::
trepan
Former Engine Dev
Posts: 1200
Joined: 17 Nov 2005, 00:52

Post by trepan »

shaders? ;-)
User avatar
Nemo
Spring 1944 Developer
Posts: 1376
Joined: 30 Jan 2005, 19:44

Post by Nemo »

You're welcome to try applying it to a 44 tank, but I don't think we can afford the CPU cost of putting it on all our tanks, so I doubt it'll be used in a release.


The script is unquestionably awesome, however.
Post Reply

Return to “Game Development”