Posted: 16 Aug 2006, 02:33
How the heck did you script the tail to move like that? @_@!!
WOW!
WOW!
Open Source Realtime Strategy Game Engine
https://springrts.com/phpbb/
KDR_11k wrote:What I see first and foremost is that his approach has less repeating code so if e.g. you wanted each leg to have an additional keyframe you'd add one line instead of however many you have there.
Maybe it was a bad idea to compare a unit with 8 legs totalling 32 degree of liberty with a unit with two legs totalling 4 degrees of liberty. And the macros I used made it easier to amend, but longer to read. Here's how I scripted a 2 legged unit:AF wrote:What you posted was an intimidating mass of text I just didnt want to read it in full and go over it a second time like I did with Arghs.
Code: Select all
#define SIG_BUILD 32
#define WALK_FASTER 300
#define WALK_SLOWER 100
StartMoving()
{
signal SIG_MOVE;
set-signal-mask SIG_MOVE;
while(1)
{
turn jambd to x-axis <8> speed <8>*WALK_FASTER/WALK_SLOWER;
turn tibd to x-axis <34> speed <34>*WALK_FASTER/WALK_SLOWER;
turn jambg to x-axis <0> speed <26>*WALK_FASTER/WALK_SLOWER;
turn tibg to x-axis <0> speed <34>*WALK_FASTER/WALK_SLOWER;
sleep 1000*WALK_SLOWER/WALK_FASTER;
turn jambd to x-axis <-52> speed <60>*WALK_FASTER/WALK_SLOWER;
turn tibd to x-axis <68> speed <34>*WALK_FASTER/WALK_SLOWER;
turn bassin to y-axis <20> speed <20>*WALK_FASTER/WALK_SLOWER;
turn jambd to y-axis <-20> speed <20>*WALK_FASTER/WALK_SLOWER;
turn jambg to y-axis <-20> speed <20>*WALK_FASTER/WALK_SLOWER;
sleep 1000*WALK_SLOWER/WALK_FASTER;
turn jambd to x-axis <0> speed <26>*WALK_FASTER/WALK_SLOWER;
turn tibd to x-axis <0> speed <34>*WALK_FASTER/WALK_SLOWER;
turn jambg to x-axis <8> speed <8>*WALK_FASTER/WALK_SLOWER;
turn tibg to x-axis <34> speed <34>*WALK_FASTER/WALK_SLOWER;
sleep 1000*WALK_SLOWER/WALK_FASTER;
turn jambg to x-axis <-52> speed <60>*WALK_FASTER/WALK_SLOWER;
turn tibg to x-axis <68> speed <34>*WALK_FASTER/WALK_SLOWER;
turn bassin to y-axis <-20> speed <20>*WALK_FASTER/WALK_SLOWER;
turn jambd to y-axis <20> speed <20>*WALK_FASTER/WALK_SLOWER;
turn jambg to y-axis <20> speed <20>*WALK_FASTER/WALK_SLOWER;
sleep 1000*WALK_SLOWER/WALK_FASTER;
}
}
StopMoving()
{
signal SIG_MOVE;
turn jambd to x-axis <0> speed <90>*WALK_FASTER/WALK_SLOWER;
turn tibd to x-axis <0> speed <90>*WALK_FASTER/WALK_SLOWER;
turn jambg to x-axis <0> speed <90>*WALK_FASTER/WALK_SLOWER;
turn tibg to x-axis <0> speed <90>*WALK_FASTER/WALK_SLOWER;
turn bassin to y-axis <0> speed <50>*WALK_FASTER/WALK_SLOWER;
turn jambd to y-axis <0> speed <50>*WALK_FASTER/WALK_SLOWER;
turn jambg to y-axis <0> speed <50>*WALK_FASTER/WALK_SLOWER;
}
I'm not sure what you call stack. But what I see is that with Arg's walkscript, you get eight function running at once just for the walk animation (MotionControl() , Go, MotionControl2() , Go2, MotionControl3() , Go3, MotionControl4() , Go4()), while for mine there is only one (StartMoving()). That means the cob machine has to run eight parrelel threads for each kbot. Well, if we assume that "call-script" is well optimised, the Go function would insert thmselves into each of the MotionControl, so you'll just have 4 threads. But that's still 4 threads to run in parallel for the COB virtual machine, it has to keep in the lines adresses of each, at each tick the COB virtual machine has to decrease 4 timers and check them, and so basically it's 4 times slower than having a single thread do the walk animation. Where's the efficiency gain, in multiplying the workload of the COB machine by 4? That can only bring more lag, what makes you say it could decrease lag? That I really don't get.AF wrote:It decreases the nubmer of items on the stack allowing mroe to be put on, aka faster code, allowing more of the units to appear onscreen for less lag. [...]being a heck of a lot more efficient for the cob virtual machine to execute.
In his method, each time he want one piece to be turned to a certain position, that's still one more line of codes, right? Has for the pause, he seem to have exactly as many as me but spread over more function, (so they are run in parallel instead of one after the other). And then he added all the complex mess of the MotionControl, which add lots of lines for nothing. Oh well, let's just count. My walkscript has four "phase" between four "pose", I'll assume his to since he roughly has the same number of turn. The two leg walkscript I posted has 44 lines. His code, when stripped of everything irrelevant to walkscript, is still 210 lines. For me 44<210. Btw here's what I kept to count his linesWhat I see first and foremost is that his approach has less repeating code so if e.g. you wanted each leg to have an additional keyframe you'd add one line instead of however many you have there.
static-var bMoving;
#define SIG_MOVE 1
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;
}
}
}
start-script MotionControl();// In Create() but I don't count the "Create()" line as it has to be there anyway
start-script MotionControl2();
start-script MotionControl3();
start-script MotionControl4();
bMoving = 0;// In Create() but I don't count the "}" line as it has to be there anyway
StartMoving()
{
bMoving = 1;
return 0;
}
StopMoving()
{
bMoving = 0;
return 0;
}
I don't understand this. Please explain! What do you call stack? In which way you code has less commands being executed? Why is the only alternative something that execute every frame? Which loop?Argh wrote:which takes longer to go through a stack... 100 commands, or 10 commands? Because, short of making loops that execute every frame, that's what it comes down to...
Has a Turn, which is conditional on the results of (z-axis 0 - (LEG__1_DOWN_ANGLE)). This is a major disadvantage from a speed standpoint. Spring has to do several things here:turn leg111 to z-axis 0 - (LEG__1_DOWN_ANGLE) now;
Code: Select all
Go()
{
// normal steps
if (bMoving)
{
// RightSide fronts
wait-for-turn R_THIGH around x-axis;
turn R_THIGH to x-axis <-50> speed <325>;
turn R_KNEE to x-axis <40> speed <325>;
turn R_FOOT to x-axis <15> speed <150>;
wait-for-turn R_THIGH around x-axis;
turn R_THIGH to x-axis <0> speed <325>;
}
if (bMoving)
{
// RightSide backs
wait-for-turn R_THIGH around x-axis;
turn R_THIGH to x-axis <50> speed <325>;
turn R_KNEE to x-axis <0> speed <325>;
turn R_FOOT to x-axis <-50> speed <325>;
wait-for-turn R_THIGH around x-axis;
turn R_THIGH to x-axis <0> speed <325>;
}
}
Go2()
{
// normal steps
if (bMoving)
{
// LeftSide backs
wait-for-turn L_THIGH around x-axis;
turn L_THIGH to x-axis <50> speed <325>;
turn L_KNEE to x-axis <0> speed <325>;
turn L_FOOT to x-axis <-50> speed <325>;
wait-for-turn L_THIGH around x-axis;
turn L_THIGH to x-axis <0> speed <325>;
}
if (bMoving)
{
// LeftSide fronts
wait-for-turn L_THIGH around x-axis;
turn L_THIGH to x-axis <-50> speed <325>;
turn L_KNEE to x-axis <40> speed <325>;
turn L_FOOT to x-axis <15> speed <150>;
wait-for-turn L_THIGH around x-axis;
turn L_THIGH to x-axis <0> speed <325>;
}
}
Stop()
// stop motion
{
sleep 100;
// Legs to start
turn R_THIGH to x-axis <0> now;
turn L_THIGH to x-axis <0> now;
turn R_KNEE to x-axis <0> now;
turn L_KNEE to x-axis <0> now;
turn R_FOOT to x-axis <0> now;
turn L_FOOT to x-axis <0> now;
sleep 100;
}
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;
}
}
}
What do you call "cycle"?, Is the cycle of Spring main loop, that's executed between every image, or cycle of the whatever script function? If it's the cycle of Spring main loop, then yours does 4x times as many mathematical operation as mine.1. Your code has to execute many, many more mathematical operations per cycle than mine does. Each one of your lines:
Erm, where do you see a condition? 0 - (LEG__1_DOWN_ANGLE) is not a condition, it's the angle the piece is turning toward to. Unless you're using the "spin" command, and you're not, there is no way to avoid passing the desired angle in every turn command.turn leg111 to z-axis 0 - (LEG__1_DOWN_ANGLE) now;
Has a Turn, which is conditional on the results of (z-axis 0 - (LEG__1_DOWN_ANGLE)). This is a major disadvantage from a speed standpoint. Spring has to do several things here:
What? On most frames, I run only one line, the "sleep", or the "wait-for", and for a few frames, I run max 4 turn, then a "sleep" or "wait-for". As for the state of bMoving, I don't even check it anywhere in the 2 legs walkscript I posted.A. Run through the BOS's many, many lines every frame, because you don't have MotionControl limiting how many times a second you're checking the state of Moving.
In the Scorpion walkscript, I'm using "now" only once in the lifetime of every scorpion, in the create, so it's not spawn with legs all horizontal like in the 3do. But there's no "now" in the walkscript".3. You're using NOW, which has fundamental limitations in Spring, which I will get into more detail about later.
Hmm, on any give frame, my code run even lines fewer than yours. The MotionControl is avoidable. Unlike what you said, your MotionControl isn't executed every tenth of a second or so, as most of time it's busy waiting for the "go" function to return, but if it were, then it would be really burdensome.2. Yes, my code looks longer than your two-leg example script. However, most of it is not being called on any given frame. In fact, most of it is either in the process of Wait-For-Turn, or is sleeping. The only real bugbear, which is unfortunately unavoidable, is the series of logical checks in MotionControl, which must be executed every tenth of a second or so (which is not too burdensome).
My script execute the minimal number of commands every frame. Most of frames it sleeps, and when it's done sleeping it turn only what must be turned and sleep again. You sound like you believe the COB machine goes throught the whole walk script every time! Well, it does not, "sleep" and "wait-for" are here for a reason.Your script, however, is executing commands every frame, because of the math checks and other things. This is not ideal...
I don't believe that. I'm pretty sure Spring do care how many scripts are running simultaneously within a given COB. As for many things are done each second by the COB interpreter, I already do the minimum. The only way to have less would be to combine the walkscript function with any other function being run continuously, like the SmokeUnit, but then it wouldn't be easy to stop walking and continue smoking (for instance).5. Consider the implications of the following:
Spring doesn't care how many scripts are running simultaneously within a given COB- they're all just points on the same thread. What is the limiting factor... is how many simultaneous things are being asked to execute each second by the COB interpreter, not how many Functions are running simultaneously.
I agree with that. I was just counting the lines because someone said Arg script had less lines, so was easier to read and modify. But Arg's script has both more lines and more instruction effectively being run each frame, so.. And don't worry, I know since long ago that everlooping while without sleep or wait-for are great ways to hang a computer.AF wrote:n# lines dosnt matter. It's number of operations/instructions and calculations that determine speed. Albeit more lines means more chances to add extra instructions.
I'll mount your script, and mine, on the very same T.M.U. kbot, and upload them and stress them, so you won't have that excuse.Argh wrote:Ok... first off, I'm developing some further, concrete proofs. This will take a bit, because of IRL circumstances, so please understand that I'm not being rude by refusing to answer your questions in full at this point.
[...]
I don't suppose anybody tried building 20 of them and then watching CPU load? It's quite instructive! I will be tackling that beast and optimizing it also... but not yet, unfortunately IRL issues are in the way today and tomorrow, so please be patient, I will hit all of this in greater detail Friday.
Please do, as an experiment result can only be truely accepted once it has been repetead by other people:AF wrote:This test should be reran with the units spaced out before told to move.
I still cannot understand what makes you say that, that's why I'm looking and comparing and investigating and asking.LathanStanley wrote:thats the whole point of the way his code is scripted, it SHORTENS the calculations for a VERY heavy legged object >4 legs... vs. your calculation gets huge for a creature with >4 legs....