I think that statement is full of bs and crap, sure maybe hes wrong, but I'd like not to be an basher, which most people are on this forum zwzsg. Opps, i just bashed somebody didnt i, but yeah, harsh words. Zwzsg is right the other 100 percent.Because it already proves me that yes, you are full of crap, and behind your "I'll share my discoveries, I'll give you a lot more of my source" posture, behind your impressive sounding wording, there's nothing valuable.
Cyclic Animation for Newbies
Moderator: Moderators
I'm convinced that Argh has a sincere desire to help. He went out of his way to make the Nanoblobs code easily understandable, and many of my forum searches ended with one of his posts on how something works. I don't think he needs to be treated harshly.
Even should he make a mistake, it may start a discussion from which valuable insight could be gained.
Even should he make a mistake, it may start a discussion from which valuable insight could be gained.
He's trying but he doesn't understand everything and has a tendency to hold mistaken beliefs while proclaiming they are great truths. IIRC he didn't learn what precompiler statements are until some time after I joined the board here which wasn't that long ago.
One of the ancient philosophers (Socrate or Aristotle, can't tell their philosophies apart) said "I know that I don't know" which means that he knows about the limits of his knowledge. If you know where your limits are you know where to improve. Nothing is more dangerous than falsely believing you know something (popular in tech-support stories).
Just for the heck of it, here's the walkscript.h from the Lolimod:
Feel free to take what you like. If left unchanged you need a hierarchy starting with a pelvis object that has legs (r/l thigh, shin, foot) and a chest which again has a head and arms (r/l uarm, farm, hand). Aiming tells the script whether you need the arms for an aiming animation (set it during AimWeapon and unset during your reset aim function), moving tells it whether you're still moving. In StartMoving you should set moving to 1 and start-script Walk(), in StopMoving you just put moving back to 0. Due to the semaphore the Walk() function will only be executed by one thread at a time. IdleAim() is the function that poses the unit's upper body int he idle stance.
One of the ancient philosophers (Socrate or Aristotle, can't tell their philosophies apart) said "I know that I don't know" which means that he knows about the limits of his knowledge. If you know where your limits are you know where to improve. Nothing is more dangerous than falsely believing you know something (popular in tech-support stories).
Just for the heck of it, here's the walkscript.h from the Lolimod:
Code: Select all
static-var moving, walking, aiming;
#define THIGH_F <-30>
#define THIGH_B <20>
#define THIGHSPEED_F <100>
#define THIGHSPEED_B <100>
#define SHIN_F <0>
#define SHIN_B <40>
#define SHINSPEED_F <160>
#define SHINSPEED_B <160>
#define PELVIS <-10>
#define PELVISSPEED <80>
#define CHEST <15>
#define CHESTSPEED <100>
#define HEAD <-5>
#define HEADSPEED <30>
#define WALKBOB [2]
#define BOBSPEED [8]
#define ARM_F <-30>
#define ARM_B <30>
#define ARMSPEED_F <120>
#define ARMSPEED_B <120>
Walk() {
if(walking) return 0; //semaphore
walking=1;
turn lthigh to x-axis 0 now;
turn lshin to x-axis 0 now;
turn rthigh to x-axis <-10> now;
turn rshin to x-axis <20> now;
turn pelvis to z-axis PELVIS now;
turn chest to z-axis CHEST now;
turn lthigh to z-axis 0 - PELVIS now;
turn rthigh to z-axis 0 - PELVIS now;
while(moving) {
if (moving) {
#ifdef USE_ARMS
if (!aiming) turn ruarm to x-axis ARM_B speed ARMSPEED_B;
#endif
turn rthigh to x-axis THIGH_F speed THIGHSPEED_F;
turn rshin to x-axis SHIN_B speed SHINSPEED_B;
move pelvis to y-axis WALKBOB speed BOBSPEED;
wait-for-turn lthigh around x-axis;
}
if (moving) {
#ifdef USE_ARMS
if (!aiming) turn luarm to x-axis ARM_F speed ARMSPEED_F;
#endif
turn lthigh to x-axis THIGH_B speed THIGHSPEED_B;
turn pelvis to z-axis 0 - PELVIS speed PELVISSPEED;
turn chest to z-axis 0 - CHEST speed CHESTSPEED;
turn head to z-axis 0 - HEAD speed HEADSPEED;
turn lthigh to z-axis PELVIS speed PELVISSPEED;
turn rthigh to z-axis PELVIS speed PELVISSPEED;
wait-for-turn rshin around x-axis;
}
if (moving) {
turn rshin to x-axis SHIN_F speed SHINSPEED_F;
move pelvis to y-axis 0 speed BOBSPEED;
wait-for-turn rthigh around x-axis;
}
if (moving) {
#ifdef USE_ARMS
if (!aiming) turn luarm to x-axis ARM_B speed ARMSPEED_B;
#endif
turn rthigh to x-axis THIGH_B speed THIGHSPEED_B;
turn pelvis to z-axis PELVIS speed PELVISSPEED;
turn chest to z-axis CHEST speed CHESTSPEED;
turn head to z-axis HEAD speed HEADSPEED;
turn lthigh to z-axis 0 - PELVIS speed PELVISSPEED;
turn rthigh to z-axis 0 - PELVIS speed PELVISSPEED;
wait-for-turn lthigh around x-axis;
}
if (moving) {
#ifdef USE_ARMS
if (!aiming) turn ruarm to x-axis ARM_F speed ARMSPEED_F;
#endif
turn lthigh to x-axis THIGH_F speed THIGHSPEED_F;
turn lshin to x-axis SHIN_B speed SHINSPEED_B;
move pelvis to y-axis WALKBOB speed BOBSPEED;
wait-for-turn lshin around x-axis;
}
if (moving) {
turn lshin to x-axis SHIN_F speed SHINSPEED_F;
move pelvis to y-axis 0 speed BOBSPEED;
wait-for-turn rthigh around x-axis;
}
}
walking=0;
turn rthigh to x-axis 0 speed THIGHSPEED_F;
turn lthigh to x-axis 0 speed THIGHSPEED_F;
turn rshin to x-axis 0 speed SHINSPEED_F;
turn lshin to x-axis 0 speed SHINSPEED_F;
turn pelvis to z-axis 0 speed PELVISSPEED;
turn chest to z-axis 0 speed CHESTSPEED;
turn lthigh to z-axis 0 speed PELVISSPEED;
turn rthigh to z-axis 0 speed PELVISSPEED;
move pelvis to y-axis 0 speed BOBSPEED;
turn head to z-axis 0 speed HEADSPEED;
#ifdef USE_ARMS
if (!aiming) call-script IdleAim();
#endif
}
All I have to say is, my Internet access went down for the past two days, and I came back to this 
First off, I whole-heartedly retract my scripting tutorial. Nevermind that I'm working on a large project, and finding ways to Get Things Done is usually more important than How. Nevermind that saving 20-30 minutes, per scripting operation, is more important than the final efficiency. Because gosh, coding quickly and functionally just can't be more important to me than pure efficiency
You wanted efficiency... well, here ya go.
Here is the most efficient turn / wait-for-turn walk script with a rest state possible, so far as I can determine, after looking at the .BASM code made with Mafia's COB assembler. If you wish to disprove it, I expect to see sourcecode. GPL'd or not, but this is GPL.
Note the single static-var. It's really important. Static-vars and #defines are identical in actual function within the stack. There is no difference at the machine-language level. Whereas vars, on the other hand, only require movement within the stack. Go study the resulting code, using Mafia's tools, and you will start to understand what I'm saying here. Or not. But this code is GPL, and I have a feeling that if you guys actually test it, you will find that I'm right.
Lastly, the fact that I do not understand everything does not mean I'm stupid, or that I should be treated like this. Gloat all ya want, guys, but every time you do this, the amount of helpful stuff I do for the community goes down again. It'd be one thing if you said, "Hey Argh, I like your ideas, but here's some even better SOURCECODE", but this kind of e-peen stuff is actually pretty lame, and I'm ashamed for you- your mothers would be appalled

First off, I whole-heartedly retract my scripting tutorial. Nevermind that I'm working on a large project, and finding ways to Get Things Done is usually more important than How. Nevermind that saving 20-30 minutes, per scripting operation, is more important than the final efficiency. Because gosh, coding quickly and functionally just can't be more important to me than pure efficiency

You wanted efficiency... well, here ya go.
Here is the most efficient turn / wait-for-turn walk script with a rest state possible, so far as I can determine, after looking at the .BASM code made with Mafia's COB assembler. If you wish to disprove it, I expect to see sourcecode. GPL'd or not, but this is GPL.
Code: Select all
//Arghs's Maximum-Efficiency Turn / Wait-for-Turn Walkscript
//Released under the terms of the GPL, v 2.0 or later.
piece body, gun, flare, pelvis, lthigh, lleg, lcalf, lfoot, rthigh, rleg, rcalf, rfoot;
static-var bMoving;
StartMoving()
{
bMoving = TRUE;
}
StopMoving()
{
bMoving = FALSE;
}
Run(RandomSeed, StillMoving)
{
RandomSeed = rand (200, 350);
while(TRUE)
{
///////////////////////////////////////////////////// HALT ANIMATION
if(!bMoving)
{
wait-for-turn rfoot around x-axis;
wait-for-turn rthigh around x-axis;
wait-for-turn lfoot around x-axis;
wait-for-turn lthigh around x-axis;
move body to y-axis [0] speed [3000];
turn pelvis to y-axis <0> speed <1500>;
turn body to z-axis <0> speed <1500>;
////////////////////////////////////////////
turn lthigh to x-axis <0> speed <1500>;
turn lleg to x-axis <0> speed <1500>;
turn lcalf to x-axis <0> speed <1500>;
turn lfoot to x-axis <0> speed <1500>;
////////////////////////////////////////////
turn rthigh to x-axis <0> speed <1500>;
turn rleg to x-axis <0> speed <1500>;
turn rcalf to x-axis <0> speed <1500>;
turn rfoot to x-axis <0> speed <1500>;
StillMoving=0;
sleep RandomSeed;
}
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
++StillMoving;
If(StillMoving == 5)
{
StillMoving = 1;
}
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
if(bMoving)
{
///////////////////////////////////////////////////// LEFT FOOT FULL FORWARDS
if(StillMoving == 1)
{
move body to y-axis [1] speed [10];
turn body to z-axis <5> speed <25>;
turn pelvis to z-axis <-5> speed <25>;
////////////////////////////////////////////
turn lthigh to x-axis <-7> speed <185>;
turn lleg to x-axis <-74> speed <305>;
turn lcalf to x-axis <63> speed <645>;
turn lfoot to x-axis <35> speed <530>;
////////////////////////////////////////////
turn rthigh to x-axis <15> speed <75>;
turn rleg to x-axis <13> speed <65>;
turn rcalf to x-axis <0> speed <0>;
turn rfoot to x-axis <-10> speed <50>;
wait-for-turn lcalf around x-axis;
}
///////////////////////////////////////////////////// LEFT FOOT LANDS, BODY TOP
if(StillMoving == 2)
{
move body to y-axis [0.5] speed [10];
turn body to z-axis <0> speed <25>;
turn pelvis to z-axis <0> speed <25>;
////////////////////////////////////////////
turn lthigh to x-axis <0> speed <35>;
turn lleg to x-axis <0> speed <370>;
turn lcalf to x-axis <0> speed <315>;
turn lfoot to x-axis <0> speed <175>;
////////////////////////////////////////////
turn rthigh to x-axis <30> speed <75>;
turn rleg to x-axis <-13> speed <130>;
turn rcalf to x-axis <-66> speed <330>;
turn rfoot to x-axis <71> speed <405>;
wait-for-turn rfoot around x-axis;
}
///////////////////////////////////////////////////// RIGHT FOOT FULL FORWARDS
if(StillMoving == 3)
{
move body to y-axis [1] speed [10];
turn body to z-axis <-5> speed <25>;
turn pelvis to z-axis <5> speed <25>;
////////////////////////////////////////////
turn rthigh to x-axis <-7> speed <185>;
turn rleg to x-axis <-74> speed <305>;
turn rcalf to x-axis <63> speed <645>;
turn rfoot to x-axis <35> speed <530>;
////////////////////////////////////////////
turn lthigh to x-axis <15> speed <75>;
turn lleg to x-axis <13> speed <65>;
turn lcalf to x-axis <0> speed <0>;
turn lfoot to x-axis <-10> speed <50>;
wait-for-turn rcalf around x-axis;
}
///////////////////////////////////////////////////// RIGHT FOOT LANDS, BODY TOP
if(StillMoving == 4)
{
move body to y-axis [0.5] speed [10];
turn body to z-axis <0> speed <25>;
turn pelvis to z-axis <0> speed <25>;
////////////////////////////////////////////
turn rthigh to x-axis <0> speed <35>;
turn rleg to x-axis <0> speed <370>;
turn rcalf to x-axis <0> speed <315>;
turn rfoot to x-axis <0> speed <175>;
////////////////////////////////////////////
turn lthigh to x-axis <30> speed <75>;
turn lleg to x-axis <-13> speed <130>;
turn lcalf to x-axis <-66> speed <330>;
turn lfoot to x-axis <71> speed <405>;
wait-for-turn lfoot around x-axis;
}
}
}
}
Create()
{
hide flare;
start-script Run();
start-script SmokeUnit_SWS();
}
Lastly, the fact that I do not understand everything does not mean I'm stupid, or that I should be treated like this. Gloat all ya want, guys, but every time you do this, the amount of helpful stuff I do for the community goes down again. It'd be one thing if you said, "Hey Argh, I like your ideas, but here's some even better SOURCECODE", but this kind of e-peen stuff is actually pretty lame, and I'm ashamed for you- your mothers would be appalled

Literals aren't static-vars, they're read by the interpreter in the order they're written in the stack. Again, go look at Mafia's assembler, you're not understanding how COB actually works, because you expect it to work like C.
And I'm using that one static-var because of the way that StartMoving() works. I've done a lot of experiments with using stuff within StartMoving(), but I have not been satisfied with the results- it just doesn't seem to report a TRUE / FALSE condition more than once every few frames in Spring.
Here, lemme show you this little chunk:
As you can see, the code is actually pushing the literals into the stack instructions as they occur. If you write it with a var, then it has to go fetch the var, which requires two steps, not one. If you use a static-var, then it has to do a search to the static-vars section of the COB, return the value, and populate the memory with it.
And I'm using that one static-var because of the way that StartMoving() works. I've done a lot of experiments with using stuff within StartMoving(), but I have not been satisfied with the results- it just doesn't seem to report a TRUE / FALSE condition more than once every few frames in Spring.
Here, lemme show you this little chunk:
Code: Select all
// if ( bMoving )
pushs bMoving;
jnz iflabel_Run_4;
// {
// if ( StillMoving == 1 )
pushl StillMoving;
pushc 1;
cmp;
jnz iflabel_Run_5;
// {
// move body to y-axis 163840 speed 1638400
pushc 1638400;
pushc 163840;
move;
ddw body;
ddw y-axis;
// turn body to z-axis 910 speed 4551
pushc 4551;
pushc 910;
turn;
ddw body;
ddw z-axis;
// turn pelvis to z-axis -910 speed 4551
pushc 4551;
pushc -910;
turn;
ddw pelvis;
ddw z-axis;
// turn lthigh to x-axis -1274 speed 33678
pushc 33678;
pushc -1274;
turn;
ddw lthigh;
ddw x-axis;
// turn lleg to x-axis -13471 speed 55524
pushc 55524;
pushc -13471;
turn;
ddw lleg;
ddw x-axis;
// turn lcalf to x-axis 11469 speed 117419
pushc 117419;
pushc 11469;
turn;
ddw lcalf;
ddw x-axis;
// turn lfoot to x-axis 6372 speed 96484
pushc 96484;
pushc 6372;
turn;
ddw lfoot;
ddw x-axis;
// turn rthigh to x-axis 2731 speed 13653
pushc 13653;
pushc 2731;
turn;
ddw rthigh;
ddw x-axis;
// turn rleg to x-axis 2367 speed 11833
pushc 11833;
pushc 2367;
turn;
ddw rleg;
ddw x-axis;
// turn rcalf to x-axis 0 speed 0
pushc 0;
pushc 0;
turn;
ddw rcalf;
ddw x-axis;
// turn rfoot to x-axis -1820 speed 9102
pushc 9102;
pushc -1820;
turn;
ddw rfoot;
ddw x-axis;
// wait-for-turn lcalf around x-axis
wait-for-turn;
ddw lcalf;
ddw x-axis;
// }
iflabel_Run_5:
Last edited by Argh on 03 Jun 2007, 20:48, edited 1 time in total.
Well, I have a lot of mechs / walkers / infantry to deal with, so this problem has been a big deal to me. I expect, in 4-player games, to see maybe 200 infantry walking around all the time. So, it's kind've a big deal that I eventually get all of the efficiency I can. I wasn't really worrying about that, when I wrote the first part of this- I was worrying about, "hey, how do I get about 30 cyclic walking scripts, all unique, written in less than a month". But it does matter.
And... what if you have tanks with moving tracks, or other stuff that can't just be solved with Spin? Here's a track script:
And... what if you have tanks with moving tracks, or other stuff that can't just be solved with Spin? Here's a track script:
Code: Select all
//Argh's Tank-Track Script with Deceleration Controls
//Released under the GPL, v. 2.0 or later
static-var bMoving, Counter;
TreadControl(RandomSeed, TreadSection)
{
RandomSeed = rand (200, 350);
While( TRUE )
{
if(!bMoving)
{
sleep RandomSeed;
}
++TreadSection;
If(TreadSection == 7)
{
TreadSection = 1;
}
if(bMoving)
{
If(TreadSection == 1)
{
show tread6;
hide tread1;
}
If(TreadSection == 2)
{
show tread5;
hide tread6;
}
If(TreadSection == 3)
{
show tread4;
hide tread5;
}
If(TreadSection == 4)
{
show tread3;
hide tread4;
}
If(TreadSection == 5)
{
show tread2;
hide tread3;
}
If(TreadSection == 6)
{
show tread1;
hide tread2;
}
sleep 30;
}
}
}
StartMoving()
{
Counter = Counter - 1;
if (Counter < 0)
{
Counter = 0;
}
bMoving = 1;
return (0);
}
StopMoving()
{
//Waits a bit before allowing Treads to quit animating, because StopMoving() is signalled before decelleration occurs, in Spring, so you may need to make this lengthy, or even adjust the sleeps in TreadControl(), to adequately simulate a slowly-decelerating Unit. Counter must be greater than 5
++Counter;
If (Counter >= 5);
{
bMoving = 0;
Counter = 5;
}
sleep 100;
return (0);
}
There is absolutely no reason why you can't use it, Fang, just make sure that your License is explicit about which parts are using the GPL'd sourcecode, and follow the rules. IOW, something like:
"Hey, everything in this mod is MINE, but the COB scripts use GPL'd code written by ARGH, which I have INCLUDED in this download, and are therefore covered under the GPL"
That doesn't give people the right to rip off your models, sounds, or whatever, and you can sell your game, if you choose, whether or not it is GPL. The GPL doesn't stop you from doing anything, so long as you adhere to the rules.
"Hey, everything in this mod is MINE, but the COB scripts use GPL'd code written by ARGH, which I have INCLUDED in this download, and are therefore covered under the GPL"
That doesn't give people the right to rip off your models, sounds, or whatever, and you can sell your game, if you choose, whether or not it is GPL. The GPL doesn't stop you from doing anything, so long as you adhere to the rules.
- Guessmyname
- Posts: 3301
- Joined: 28 Apr 2005, 21:07
I'm also rather confused by this statement. Seen as #defines are dealt with entirely outside of COB. Care to clarify the point you are trying to make Argh?KDR_11k wrote:So all literals are static vars? Why are you using literals then if you say local vars are the most efficient?Argh wrote:Static-vars and #defines are identical in actual function within the stack. There is no difference at the machine-language level.

Yes but what about #defines? That *should* replace the chunk of text before sending it off to the compiler, meaning it ends up as literals.Argh wrote:As you can see, the code is actually pushing the literals into the stack instructions as they occur. If you write it with a var, then it has to go fetch the var, which requires two steps, not one. If you use a static-var, then it has to do a search to the static-vars section of the COB, return the value, and populate the memory with it.
Well, OK, but it ends up executing the same way anyhow, and it takes longer to code that way.
Here's what it looks like:
Becomes:
Compare with this:
So I really don't see any efficiency gained here, when it actually runs. If it can make things significantly easier to write and maintain, though, I'm certainly listening. Thus far, though, I think it'd make it a lot more complicated to maintain, actually. It looks easier, because it'll do the math steps for us, but it also requires a lot more stuff be explicitly laid out in #define stages. A lot more work on setup, for minor time-savings later, when you could just as easily put a local-var speed multiplier in, test the bugger, then do the final math. It'd cut down on math errors, though.
Given that, what I'm doing is I write things the bad way first, for simplicity's sake, then I write things the good way, when I have the multiplier correct. Which is annoying.
I should probably figure out a grep method of doing all that math automatically, since I'm tragically bad even with a calculator and frequently miss errors, but meh.
Here's what it looks like:
Code: Select all
#define MY_VARIABLE_A 45
piece Part;
Create()
{
turn Part to x-axis MY_VARIABLE_A speed MY_VARIABLE_A;
}
Code: Select all
piece Part;
Create()
{
// PushConst->45.000000 StackPos 1
// PushConst->45.000000 StackPos 2
turn Part to x-axis <0.2> speed <0.2>;
// StackAllocate
}
Code: Select all
piece Part;
Create()
{
turn Part to x-axis 45 speed 45;
}
Code: Select all
piece Part;
Create()
{
// PushConst->45.0 StackPos 1
// PushConst->45.0 StackPos 2
turn Part to x-axis <0.2> speed <0.2>;
// StackAllocate
}
Given that, what I'm doing is I write things the bad way first, for simplicity's sake, then I write things the good way, when I have the multiplier correct. Which is annoying.
I should probably figure out a grep method of doing all that math automatically, since I'm tragically bad even with a calculator and frequently miss errors, but meh.
Last edited by Argh on 03 Jun 2007, 22:28, edited 1 time in total.