The Millionth Monkey Gets Its Typewriter.

The Millionth Monkey Gets Its Typewriter.

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
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

The Millionth Monkey Gets Its Typewriter.

Post by Argh »

Ok folks, to win the Ultimate Grand Prize, worth approximately 1 Red Gem...

What about the following code is a radical improvement over current methods?

Code: Select all

piece base, body, platform, box, upperdoor, lowerdoor;
piece rfbodyshaft, rfpiston, rfpistonarm;
piece lfbodyshaft, lfpiston, lfpistonarm;
piece rrbodyshaft, rrpiston, rrpistonarm;
piece lrbodyshaft, lrpiston, lrpistonarm;
piece upperrotator, lowerrotator, shaftnull, platformnull;
piece firepointone;

static-var bMoving;
static-var pitch_01;
static-var heading_01;
#define SIG_RESTORE 2
#define	SIG_AIM1	4
#define	SIG_MOVE	1
#define SMOKEPIECE1 base
#include "smokeunit.h"
#include "exptype.h"
#include "sfxtype.h"


Go()	
	{
	// normal steps	
  	if (bMoving)
	{	
	// RightFront fronts
	wait-for-turn rfbodyshaft around x-axis;
	turn rfbodyshaft to x-axis <-50> speed <325>;
	wait-for-turn rfbodyshaft around x-axis;
	move rfpistonarm to y-axis [-0.3] speed [15];
	turn rfbodyshaft to x-axis <0> speed <325>;
	}
  	if (bMoving)
	{	
	// RightFront backs
	wait-for-turn rfbodyshaft around x-axis;
	turn rfbodyshaft to x-axis <50> speed <325>;
	move rfpistonarm to y-axis [0.4] speed [10];	
	wait-for-turn rfbodyshaft around x-axis;
	turn rfbodyshaft to x-axis <0> speed <325>;
	}
	return 0;
	}
	
Go2()	
	{
	// normal steps	
  	if (bMoving)
	{	
	// RightBack backs
	wait-for-turn rrbodyshaft around x-axis;
	turn rrbodyshaft to x-axis <50> speed <325>;
	move rrpistonarm to y-axis [0.4] speed [10];
	wait-for-turn rrbodyshaft around x-axis;
	turn rrbodyshaft to x-axis <0> speed <325>;
	}
  	if (bMoving)
	{	
	// RightBack fronts
	wait-for-turn rrbodyshaft around x-axis;
	turn rrbodyshaft to x-axis <-50> speed <325>;
	wait-for-turn rrbodyshaft around x-axis;
	move rrpistonarm to y-axis [-0.3] speed [15];
	turn rrbodyshaft to x-axis <0> speed <325>;
	}
	return 0;
	}
	
Go3()	
	{
	// normal steps	
  	if (bMoving)
	{	
	// LeftBack fronts
	wait-for-turn lrbodyshaft around x-axis;
	turn lrbodyshaft to x-axis <-50> speed <325>;
	wait-for-turn lrbodyshaft around x-axis;
	move lrpistonarm to y-axis [-0.3] speed [15];
	turn lrbodyshaft to x-axis <0> speed <325>;
	}
  	if (bMoving)
	{	
	// LeftBack backs
	wait-for-turn lrbodyshaft around x-axis;
	turn lrbodyshaft to x-axis <50> speed <325>;
	move lrpistonarm to y-axis [0.4] speed [10];	
	wait-for-turn lrbodyshaft around x-axis;
	turn lrbodyshaft to x-axis <0> speed <325>;
	}
	return 0;
	}
	
Go4()	
	{
	// normal steps	
  	if (bMoving)
	{	
	// LeftFront backs
	wait-for-turn lfbodyshaft around x-axis;
	turn lfbodyshaft to x-axis <50> speed <325>;
	move lfpistonarm to y-axis [0.4] speed [10];	
	wait-for-turn lfbodyshaft around x-axis;
	turn lfbodyshaft to x-axis <0> speed <325>;
	}
  	if (bMoving)
	{	
	// LeftFront fronts
	wait-for-turn lfbodyshaft around x-axis;
	turn lfbodyshaft to x-axis <-50> speed <325>;
	wait-for-turn lfbodyshaft around x-axis;
	move lfpistonarm to y-axis [-0.3] speed [15];
	turn lfbodyshaft to x-axis <0> speed <325>;
	}
	return 0;
	}


Stop()
	// stop motion
	{
	
	sleep 200;
	
	// RF and LR legs to start
	turn rfbodyshaft to x-axis <0> now;
	move rfpistonarm to y-axis [0] now;
	turn lrbodyshaft to x-axis <10.2> now;
	move lfpistonarm to y-axis [0] now;
	
	sleep 100;
	
	// RR and LF legs to start
	turn rrbodyshaft to x-axis <10.2> now;
	move rrpistonarm to y-axis [0] now;
	turn lfbodyshaft to x-axis <0> now;
	move lfpistonarm to y-axis [0] now;
	
	sleep 100;
	
	return 0;
	}

MotionControl()
 { var moving,just_moved;
   just_moved = 1;
   WHILE ( TRUE )
   {	moving = bMoving ;
     IF (moving)
      	{ 
      	just_moved = 1;
      	call-script Go(bMoving);
       	}
     IF (!moving)
      { IF (just_moved)
         { just_moved = 0;
           call-script Stop();
          }
        SLEEP 50;
       }
    }
 }

MotionControl2()
 { var moving,just_moved;
   just_moved = 1;
   WHILE ( TRUE )
   {	moving = bMoving ;
     IF (moving)
      	{ 
      	just_moved = 1;
      	call-script Go2();
       	}
     IF (!moving)
      { IF (just_moved)
         { 
         just_moved = 0;
         }
        SLEEP 100;
       }
    }
 }
 
MotionControl3()
 { var moving,just_moved;
   just_moved = 1;
   WHILE ( TRUE )
   {	moving = bMoving ;
     IF (moving)
      	{ 
      	just_moved = 1;
      	call-script Go3();
       	}
     IF (!moving)
      { IF (just_moved)
         { 
         just_moved = 0;
         }
        SLEEP 100;
       }
    }
 }
 
MotionControl4()
 { var moving,just_moved;
   just_moved = 1;
   WHILE ( TRUE )
   {	moving = bMoving ;
     IF (moving)
      	{ 
      	just_moved = 1;
      	call-script Go4();
       	}
     IF (!moving)
      { IF (just_moved)
         { 
         just_moved = 0;
         }
        SLEEP 100;
       }
    }
 }

RestoreAfterDelay()
 	{
 	signal SIG_RESTORE;
   	set-signal-mask SIG_RESTORE;
   	sleep 5000;
   	turn platformnull to y-axis <0> speed <100.0>;
	turn shaftnull to x-axis <0> speed <100.0>;
	turn upperrotator to x-axis <-90> now;
	turn lowerrotator to x-axis <90> now;
	sleep 150;
	turn upperrotator to x-axis <-45> now;
	turn lowerrotator to x-axis <45> now;
	sleep 150;
	turn upperrotator to x-axis <0> now;
	turn lowerrotator to x-axis <0> now;
	return 0;
	}


SweetSpot (piecenum)
	{
	piecenum = base;
	}

Create()
	{
	hide base;
	turn rrbodyshaft to x-axis <10.2> now;
	turn lrbodyshaft to x-axis <10.2> now;
	turn rfpiston to z-axis <-15> now;
	turn rrpiston to z-axis <-15> now;
	turn lfpiston to z-axis <15> now;
	turn lrpiston to z-axis <15> now;	
	start-script SmokeUnit();
	start-script MotionControl();
	start-script MotionControl2();
	start-script MotionControl3();
	start-script MotionControl4();
	bMoving = 0;
	}

StartMoving()
 	{
 	bMoving = 1;
   	return 0;
  	}

StopMoving()
 	{
	bMoving = 0;
 	return 0;
  	}
  
AimFromPrimary (piecenum)
	{
	piecenum = shaftnull;
	}

AimPrimary(heading, pitch)
	{
	signal SIG_AIM1;
	set-signal-mask SIG_AIM1;
	wait-for-turn upperrotator around x-axis;
	turn upperrotator to x-axis <225> speed <100>;
	turn lowerrotator to x-axis <135> speed <100>;
	pitch_01 = pitch;
	IF ( pitch_01 <= 32768 )
	{
	turn shaftnull to x-axis 0 - pitch speed <100.0>;
	}
	IF ( pitch_01 > 32768 )
	{
	turn shaftnull to x-axis pitch speed <100.0>;
	}
	heading_01 = heading;
	IF ( heading_01 <= 32768 )
	{
	turn platformnull to y-axis heading speed <100.0>;
	}
	IF ( heading_01 > 32768 )
	{
	turn platformnull to y-axis 0 - heading speed <100.0>;
	}
	wait-for-turn upperrotator around x-axis;
	wait-for-turn platformnull around y-axis;
	wait-for-turn shaftnull around x-axis;
	start-script RestoreAfterDelay();
	return(TRUE);
	}


QueryPrimary(piecenum)
	{
	piecenum = firepointone;
	return 0;
	}

FirePrimary()
	{
	return 0;
	}

Killed(severity, corpsetype)
{
		//explode body type BITMAPONLY | BITMAP1;
		//hide platform;
		//hide box;
		//hide upperdoor;
		//explode lowerdoor type FALL | SMOKE | FIRE | EXPLODE_ON_HIT | BITMAP1;
		//explode rfbodyshaft type FALL | SMOKE | BITMAP1;
		//explode rfpiston type FALL | SMOKE | BITMAP1;
		//explode rfpistonarm type FALL | SMOKE | BITMAP1;
		//hide lfbodyshaft;
		//hide lfpiston;
		//hide lfpistonarm;
		//hide rrbodyshaft;
		//hide rrpiston;
		//hide rrpistonarm;
		//explode lrbodyshaft type FALL | SMOKE | BITMAP1;
		//explode lrpiston type FALL | SMOKE | BITMAP1;
		//explode lrpistonarm type FALL | SMOKE | BITMAP1;
	return (0);
}
I'll give you a hint: it has to do with the number of Go() scripts.
Last edited by Argh on 14 Aug 2006, 19:31, edited 1 time in total.
User avatar
Cabbage
Posts: 1548
Joined: 12 Mar 2006, 22:34

Post by Cabbage »

Green text where some others only have black!? :P
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

<laughs>

Nope, that's not it.

I'll give you another hint: Q: how many lines of code are in a typical walk script? A: the Peewee's is 168 lines long.
User avatar
Aun
Posts: 788
Joined: 31 Aug 2005, 13:00

Post by Aun »

Just tell us what it is instead of waiting for someone who knows what they're doing? :P
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

<shrugs> it's like abstract art; you've gotta know some Theory to understand the work ;)

Another hint: Q: just how hard is it to maintain a fluid sense of motion, with a script where a typical piece (say, the Peewee's leg) has to go through 12 iterations of NOW per walk cycle? A: it's a pain in the @$$.
User avatar
KDR_11k
Game Developer
Posts: 8293
Joined: 25 Jun 2006, 08:44

Post by KDR_11k »

You gave each limb its own "thread"?
User avatar
Dragon45
Posts: 2883
Joined: 16 Aug 2004, 04:36

Post by Dragon45 »

You could further optimize a walk script ( since part of it is just signs) by using a var for the analogous piee that must be moved, and another var to determien which piece it is, and modify the sign accordingly...
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

Hmm... getting warmer...

Yet more hints: What type of motion am I using? What are the advantages of this, in terms of processor throughput? Are there other ways to apply this concept, say to multiple-axis solutions? Scalar representations? Random variations? Muahahaha...

@Dragon: you could, but you'd run into problems with synchronicity, I fear. I think that the script would lock up fairly often because conditions wouldn't get met in a timely manner. The key here is how often and in what way Spring reads through BOS code. Ideally, in a perfect world, we'd be able to explicitly ask nicely for seperate threads dedicated to watch each cycle, and on multiprocessor machines, each thread would be assigned to its own processor for almost perfect synchronization. Luckily for us, Spring's true framerate for even unsync code is 30FPS, so there's a meaningful floor value here, and anything that can fit into the stack during this period can get executed.

BTW, this just occured to me, and may or may not be all that profound... I'll betcha that scripts that call for TURN commands that precisely reach their operating stops on an unsync execution time will operate with perfect results even over long periods, whereas the bane of current scripts is that they frequently become unsynced over time, requiring ugly resets. Haven't tested that, though, just supposing. Maybe the COB rounding functions are "good enough", but it's limited by the number of commands that get put into the stack. I can say, however, that this script operates, with over a hundred of these suckers on the screen... with perfect speed.
User avatar
Weaver
Posts: 644
Joined: 07 Jul 2005, 21:15

Post by Weaver »

Weaver wonders if this script would work for more than 4 legs with a little work. Like maybe 100 legs?
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

Yes! Yes! Yes! MUAHAHAHA!!! Er... sorry... got a bit overexcited there lol...

And with far shorter code than any other possible method (that I know works, anyhow- I'll have to try Dragon's loop idea out, and see if it can't be halved).

And you could even assign slight random variations (say, +/- 3%) so that your millipede would gradually de-sync and look very natural :o

[edit]Although, I must caution... unless Dragon's method actually works, then you're talking about... hmm... about 200 different short sub-scripts operating per cycle, and that's quite a bit of watch-script stuff going on. That might get a wee bit much, if you had too many of these things going at once. However, this bottleneck isn't nearly as bad as many of the other things being done in the sim code...[/edit]

The most important part of all of this is that by being able to use TURN without any lockups... not only can you scale up to a larger number of legs (six or eight would be trivial) ... but, by eliminating TURN NOW, it makes it possible to animate a whole bunch of things that simply weren't really practical before.

For example... imagine a really realistic near-future walker. It's going to have legs, but it's also going to have hydraulic actuators, to serve in place of muscles. Before... the whole idea of animating the hydraulics so that they synchronised with the legs, and turned inverse to the open/close cycle, along with movement of the hydraulics... was hardly practical, except with an absurd number of NOWs. With this... it could be a handful of lines :-)
Last edited by Argh on 14 Aug 2006, 19:20, edited 1 time in total.
User avatar
unpossible
Posts: 871
Joined: 10 May 2005, 19:24

Post by unpossible »

Argh wrote: And you could even assign slight random variations (say, +/- 3%) so that your millipede would gradually de-sync and look very natural :D
eeergh, i don't think they do...they all move with perfect timing not randomness
User avatar
Aun
Posts: 788
Joined: 31 Aug 2005, 13:00

Post by Aun »

Argh wins.
User avatar
hrmph
Posts: 1054
Joined: 12 May 2005, 20:08

Post by hrmph »

Have you tested and compared any of this in game yet? I'm interested in the results.
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Post by AF »

Red gem is redeemble for 200 cookies.

Also wouldnt it be possible to shove Go1/2/3/4 into a single Go function if you wrote a set of functions that took 1/2/3/4 and returned the appropriate pieces? Or is that nto possible in BOS?
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

Have you tested and compared any of this in game yet? I'm interested in the results.
You wouldn't think I'd publish the code unless it was tested and worked as advertised... right? ;) In short, yes, it works. Really!
Also wouldnt it be possible to shove Go1/2/3/4 into a single Go function if you wrote a set of functions that took 1/2/3/4 and returned the appropriate pieces? Or is that nto possible in BOS?
That's what Dragon was saying. I haven't tried it yet, but I think it's going to bork because of failing to return when needed, but I'll just have to write one up and see if it works or not. This is, so far as I know, as close as we've ever gotten to a walk-cycle script that uses only TURN WAIT-FOR-TURNs for control purposes... getting around a lot of previous obstacles.
User avatar
rattle
Damned Developer
Posts: 8278
Joined: 01 Jun 2006, 13:15

Post by rattle »

If BOS supports loops it shouldn't be too difficult to write a function which animates anything on 4+ legs (by distributing them over the two 180° arches, skipping a keyframe each step). Do functions take parameters at all and is return restricted in any way?
Gnomre
Imperial Winter Developer
Posts: 1754
Joined: 06 Feb 2005, 13:42

Post by Gnomre »

I ended up doing something roughly similar with the AT-AA walk script because the 4 legs animated together in one function looked like total ass. It still needs tweaking (to break the sync a little, as well as general tweakage of the movements and timing) but it's still much nicer than one large block. No clue on how efficient it is, though.
User avatar
Forboding Angel
Evolution RTS Developer
Posts: 14673
Joined: 17 Nov 2005, 02:43

Post by Forboding Angel »

Hey argh, could you post this script in the EE forum on the "Other" site?
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

Um, copy... paste? lol...

'sides which, I'm not necessarily done with this yet... it may get better, dunno. Gonna have to try Dragon's loop idea and see if it actually works, or just jams up, like I suspect it will. I'm just excited, because it cuts down on the number of lines per execution cycle by such a huge amount... that, at least in theory, it should lead to very large gains in speed. Heck, since the TURN time is known... it may be quite possible to execute this with a SLEEP and have the script not return to active... but quite frankly, I think that things in SLEEP are still in the stack, honestly.

The main thing about this, is that you can do multiple calls to the same Piece this way, and do one of the Holy Grails... 3-axis rotation in "realtime"...
User avatar
jcnossen
Former Engine Dev
Posts: 2440
Joined: 05 Jun 2005, 19:13

Post by jcnossen »

and do one of the Holy Grails... 3-axis rotation in "realtime"...
wow we really need a new format :/ ;)
Post Reply

Return to “Game Development”