The Millionth Monkey Gets Its Typewriter. - Page 4

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

Egarwaen
Posts: 1207
Joined: 27 Feb 2006, 21:19

Post by Egarwaen »

zwzsg wrote:- Argh's way has 6 functions (not counting create) in the bos, mine 2. (More difficult to read)
Actually, this isn't strictly speaking true. More, smaller functions are generally easier to read as you can tell what code that uses them does without having to reason through the lines of code that actually do the work. However, single parameterized functions are generally preferred to multiple copy-and-pasted functions. (See: Refactoring)
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

<laughs> it's not an excuse... you will see what I'm talking about. I've already done this experiment with 499 of the previous Archers...

As for the specific questions/comments:

1. So far as I can tell, the COB interpreter is sync code. Therefore, it has a top speed of 30FPS, absolute, for the actual positions returned... for things like aiming. However, the animation interpolator appears to be able to operate at a higher FPS value. Watch your script running at a speed of 0.3... you will watch it jerkily step through each step (or, if you have SmoothAnim=1 active, it won't jerk, but that eats very large amounts of CPU).

2.
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
Your method requires a math step (calculating LEG_1_DOWN_ANGLE), and a memory search step(finding all of the values you're storing via Defines), during every operation. This is because you're not feeding it a value right there in the COB step. I'll grant, for the sake of argument, that the math step (the multiplication) is trivial, because it can be done so quickly, even after being interpreted by the COB interpreter and finally run through the virtual machine. However, the memory search, to find the variable name and then get its value... is not trivial, and should be avoided where possible. In general, you want to refer to static variables as infrequently as possible, and pass them from sub-script to another sub-script when it's absolutely necessary... such as my calls in StartMoving(). I'd like to avoid the StartMoving() and StopMoving() entirely, but I'm pretty sure that Spring doesn't allow us to get the state of Moving otherwise. If I'm wrong, somebody please enlighten me, because I'd like to clean up all the MotionControl mess with a simple logical state-check, like so:

Code: Select all

IsMoving()
{
If(Moving)
{
bMoving=1;
}
If(!Moving)
{
bMoving=0;
}
sleep 100;
}
... which would get rid of all of the stupid MotionControls all at once. If anybody knows a way to do that... that won't lock up... I'm completely ready to drop all of those logic checks, and lose a lot of redundant code.
Hmm, on any give frame, my code run even lines fewer than yours.
Again, you're wrong. Your code, as written, has to be parsed in whole, and it's going outside of the Function on a regular basis. So far as I can tell, only things between brackets in a Function are currently running and in memory. This was how Cavedog did things, to reduce the size and memory footprint. That is one of the reasons why they did the IF(TRUE){blahblahblah} stuff in their WalkLegs scripts, etc.... to keep the chunks down to one-frame actions, run it through the parser, and move on. I think that commands between brackets are all being loaded at once into memory, and the it's operating according to the schedule set within that script. So, in a sense, you're both right and wrong. Your code's calling very few lines in the main script, then pausing, then continuing. It's feeding operations to the animation side of Spring in short, easily-digested chunks. However, on the BOS interpreter side, it's calling outside the script over and over again during each operational step, instead of staying within itself- this is inefficient.
I'm pretty sure Spring do care how many scripts are running simultaneously within a given COB.
We'll look at a proof for that, doing a simple apples vs. apples comparision where we need to accomplish the same task with one script vs., say... 100. I strongly suspect that the single-script solution will run less efficiently. Why? Because I think that there's an upward limit on how far the COB interpreter looks ahead, in terms of commands. That's just a theory, mind you... I may very well be wrong. But, based on past experiments, I think that may be the case.
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.
You're joking, right? No, you're probably not. I'll do a proof of that statement as soon as I get home, as I don't need to put any time into it... just build 499 Archers and have them just... stand there, supposedly killing the processor with their repeating script. I think you're going to be disappointed- that theory doesn't hold any water. A Sleep/NoSleep of a tenth of a second, absent anything else going on... is totally harmless, even multiplied by large numbers. I'm more worried about the fact that it requires so darn many logical state checks to make sure it's really going to sleep.

At any rate, I welcome the challenge to build the most efficient thing possible, but it's not totally the point. The main reason I am extremely excited about this whole thing... is that, by utilizing TURN/MOVE and WAIT-FOR-TURN and WAIT-FOR-MOVE... we can get away from static, frame-based animation techniques... and move towards much more dynamic approaches. I'm serious about things like de-tuned animation sequences, and using random number generators in scripts- they'd add a lot more lifelike oomph to existing animation models.

If the best way to do it is through your techniques, that's fine, and I welcome your approach. I just don't think so, though. I've beat my head against the wall on this problem since OTA, and I just think that what you're doing is... basically... just an ultra-fancy extension of WalkLegs, with a lot've bells and whistles.

Lastly... I am glad that zwzsg is here to argue for his case! There is no doubt, at all, that he is the guy who has done the most with scripting in the TA community. Absolutely no disrespect is meant, and I take none from his points- if anybody can show where I'm doing things in a poorly thought-out fashion, it would be he, and I am flattered that he thought this was worth bothering with.
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

And yes, I hadn't gotten done reading the results of the test yet. I will take the same two models and see if my results vary any, and if I can improve things by seeking any optimizations. I think I may have found one possibility already.

I don't like the test, as it was run, btw... I'm going to run another one that's free of possible CPU issues during the run. I'm going to load up GreenFields, and then have 498 of these things run a huge Patrol path, where they will never run into one another. That will take the pathfinder, unit collisions and other noise out of the sample. I thought that the observation that Sim time was adversely affected by my script, though, was a very important point, and I will want to test that observation. If true, that's a pretty big argument against utilising this method where speed is crucial. However... speed of scripting execution's hardly the big cause of lag on any machine that's even halfway modern. I see much more Sim time usage due to other factors that aren't easily predicted or controlled, frankly...
Egarwaen
Posts: 1207
Joined: 27 Feb 2006, 21:19

Post by Egarwaen »

I don't know how BOS/COB do things, but in C, a #define is a "preprocessor directive". It basically gets pasted into the text by a fancy automated text editor. This means that #define's are very efficient - the value's right there - but also very error-prone. (Ever accidentally put a ; in one? Uh-huh.)
User avatar
Dragon45
Posts: 2883
Joined: 16 Aug 2004, 04:36

Post by Dragon45 »

Argh, i think i can see your point on the function-chunking.


But, I fail to see how "wait-for-turn", and "turn piece to [5] speed <3>" is new or even itneresting. I'm pretty sure OTA has been using it for ages; as it stands, i remember making every single one of my cap ships' turrets turn with this, and some of the fancy unfolding anims with these commands...


And I'm pretty sure that there have been plenty of third party units that have used that sort of gradual motion instead of ten NOWs for speed.


In short: What's the fuss about, mate? :o
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

Ok, then that means that where possible, I should use #defines to build certain things, to cut down the lag. I can buy that.

I also think I've solved the problem of elminating the MotionControl check entirely, in a way that's reasonably fast and cuts the number of loops down to one. That should help.
User avatar
zwzsg
Kernel Panic Co-Developer
Posts: 7052
Joined: 16 Nov 2004, 13:08

Post by zwzsg »

Argh wrote:Lastly... I am glad that zwzsg is here to argue for his case!
Thanks, I'll continue then. I was getting worried that my insistence might start to sound like I'm flaming, but I really would like to understand what's that "radical improvement" you're talking about in your first post.

Egarwaen wrote:However, single parameterized functions are generally preferred to multiple copy-and-pasted functions.
Agreed. However, parametrised function, while easier to read and maintain, might be slower to run ingame than raw copy'n'pasted function.

Argh wrote:Your method requires a math step (calculating LEG_1_DOWN_ANGLE), and a memory search step(finding all of the values you're storing via Defines), during every operation. This is because you're not feeding it a value right there in the COB step. I'll grant, for the sake of argument, that the math step (the multiplication) is trivial, because it can be done so quickly, even after being interpreted by the COB interpreter and finally run through the virtual machine. However, the memory search, to find the variable name and then get its value... is not trivial, and should be avoided where possible. In general, you want to refer to static variables as infrequently as possible, and pass them from sub-script to another sub-script when it's absolutely necessary...
Just to make sure it's clear, the "#define" are not static-var. They're like copy'n'paste, done by the preprocessor, before even the compilation is done. So something like:
#define ANGLE <20>
turn pieceN to x-axis ANGLE now;
is exactly equivalent to:
turn pieceN to x-axis <20> now;
What I mean by exactly equivalent, is that they output the very same COB, not any byte of difference in the COB.
As proved by : If you take the first, compile it, then un-compile it, you get the second.
Ok you probably knew what are preprocessing commands, but just making sure, because you're talking about a "memory search, to find the variable name and then get its value, while there is none of this with "#define".

But I agree that caculating the "speed" of my "turn" from complex calculation using that many "#define" propably result in poorly efficient code. For instance, in my Scorpion walkscript, when I write:
BACK_4_LEFT
it's replaced by:
turn leg141 to y-axis 0 - (LEG_41_BACK_ANGLE) speed ((LEG_41_FRONT_ANGLE) - (LEG_41_BACK_ANGLE))*1000/(BACK_TIME);
where all the values in capital letter are replaced by their value
so it really is:
turn leg141 to y-axis 0 - (-7280) speed ( 910 - (-7280) ) * 1000 / 179 * 12;
(You can see that by compiling then uncompiling the bos)
I don't know how much cost doing multiplication and division compared to performing commands like "turn", but all those multiplication and division could be avoided with the animation looking exactly the same. Note that if Scriptor was a good compilator, it would realise everything is constant in these formula, and so would optimise the code by writing the end result in the COB, instead of letting the COB virtual machine do all that calculation everytime the line is run.

Ok, so using that many value calculated from "#define" may be bad performance wise. I did it only because it made writing the code, and mostly tuning it, easier: I change one value at the top, and everything adapt. Maybe, once I have found the timing and angles that result in a good looking animation, I could go and replace every calculation involving only constants with its result, but generally that's too much work for little performance gain, and I don't do it.

But anyway, I'm the only one abusing "#define" 'ed constant like that, and I can do without if I need to, so I don't think this where your optimisation idea lies.
I'd like to avoid the StartMoving() and StopMoving() entirely, but I'm pretty sure that Spring doesn't allow us to get the state of Moving otherwise. If I'm wrong, somebody please enlighten me, because I'd like to clean up all the MotionControl mess with a simple logical state-check, like so [...] ... which would get rid of all of the stupid MotionControls all at once. If anybody knows a way to do that... that won't lock up... I'm completely ready to drop all of those logic checks, and lose a lot of redundant code.
Note sure I understand you, but get a look at my script, the 2 leg walk script I posted page 3 or the AmazonZ.bos in this ufo, to be precise. There I use no variable keeping the state of moving, as I simply put the whole walkscript inside the StartMoving(), and stop the walking animation by killing the StartMoving() with a "signal" in the StopMoving() function. Note that this method would have a little bug if you control the unit in first person, as in FPS the Spring engine constantly call the StartMoving function (or so I heard).

Another way I use often (like in the Scorpion), is:

Code: Select all

static-var moving;

WalkScriptFunction()
	{
	while(1)
		{
		if(moving)
			{
			turn ...
			....
			wait-for... or sleep...
			....
			...
		}
		if(!notmoving)
			{
			....
			just don't forget any pause in here
			...
			}
		}
	}

StartMoving()
	{
	moving=TRUE;
	}

StopMoving()
	{
	moving=TRUE;
	}

Create()
	{
	moving=FALSE;
	....
	start-script WalkScriptFunction();
	}
Actually in the scorpion, after every "pose" followed by a "pause", I do a while(NOT moving){sleep 200;}, which allow my Scorpion to suddenly freeze its walking, at every stage of the walk animation, when it stops moving, and later resume the walk animation where it left it.

If you really want to remove StartMoving and StopMoving althogether, well, you could periodically store get PIECE_XZ(base) and check if it changed, but I am sure that it would be a lot more inefficient. I don't see why you want to avoid StartMoving() and StopMoving() entirely, they're only called once when the unit start moving, and once when the unit stop moving (duh!), (save in FPS mode but that's a very special case), I mean, they're not like ever looping function eating CPU at every frame.

Anyway, all I wanted to say, is that I hate the MotionControl mess, and had no trouble never using it. (Ok, one might say that my WalkScriptFunction() is just a merger of MotionControl() and Go(), and that wouldn't be false, but I still find it simpler that way).

Well, I aren't sure this what you asked when you wanted to remove the use of the moving static-var and the MotionControl.
Hmm, on any give frame, my code run even lines fewer than yours.
Again, you're wrong. Your code, as written, has to be parsed in whole, and it's going outside of the Function on a regular basis. So far as I can tell, only things between brackets in a Function are currently running and in memory. This was how Cavedog did things, to reduce the size and memory footprint. That is one of the reasons why they did the IF(TRUE){blahblahblah} stuff in their WalkLegs scripts, etc.... to keep the chunks down to one-frame actions, run it through the parser, and move on. I think that commands between brackets are all being loaded at once into memory, and the it's operating according to the schedule set within that script.
Ok. We need to ask Fnordia how the COB virtual machine really works. I assumed that, just like a processor running machine code, it had a program counter register storing the adress of the line being run, and that it read from the cob and stored in memory one line at a time. Again, we need to ask Fnordia how the COB language is actually implemented in Spring, but it just seem the most logical way. Reading from the COB file and putting in memory everything into { } at once just seem inefficient and useless, and I don't see why the virtual machine would do that, but I'm very glad to hear an interesting theory about why Cavedogs used so many if(TRUE){...}. For very long I wondered why! Xon (formerly ggs) had another theory (he said that in old version of TA, the COB virtual machine could force a pause in script if it had run for too long, but only on "if" statement (or only on { or }, don't remember exactly)). But so far you are the only two people proposing plausible theories! Well, interesting theory as it is, I'll still have doubt on the COB virtual machine reading everything into { } at once until confirmed by Fnordia (or another SY), as I don't see the point in working that way.

I don't see why are you talking about parser, COB being compiled code, it doesn't require parsing, does it?
So, in a sense, you're both right and wrong. Your code's calling very few lines in the main script, then pausing, then continuing. It's feeding operations to the animation side of Spring in short, easily-digested chunks. However, on the BOS interpreter side, it's calling outside the script over and over again during each operational step, instead of staying within itself- this is inefficient.
My script stay as much within itself as it could possibly do! How can you say less inside yourself than by having a single loop in a single function, never returning? You'll to explain that point in more detail to me.



I'm pretty sure Spring do care how many scripts are running simultaneously within a given COB.
We'll look at a proof for that, doing a simple apples vs. apples comparision where we need to accomplish the same task with one script vs., say... 100. I strongly suspect that the single-script solution will run less efficiently. [...] But, based on past experiments, I think that may be the case.
Ahead of you: Already run a comparaison, between 1000 kbots scripted your way, and 1000 kbots scripted my way, everything else equal, see my post near the bottom of page 3, and don't forget to check the ufo containing the two test units. Yes, the one thread walkscript used less ressource than the two threads one.

Why? Because I think that there's an upward limit on how far the COB interpreter looks ahead, in terms of commands.
What? "looking ahead, in terms of commands"? What is that nonsense? The COB interpreter execute one line after the other, it doesn't go looking ahead. At least that's what I always believed and assumed. You'll need some very strong argument, or Fnordia's word, to convince me otherwise. Not even the smoothing looks ahead, it just store in the memory that a "now" movement is being smoothed, an immediatly finish it on certain condition.
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.
You're joking, right? No, you're probably not. I'll do a proof of that statement as soon as I get home, as I don't need to put any time into it... just build 499 Archers and have them just... stand there, supposedly killing the processor with their repeating script. I think you're going to be disappointed- that theory doesn't hold any water. A Sleep/NoSleep of a tenth of a second, absent anything else going on... is totally harmless, even multiplied by large numbers. I'm more worried about the fact that it requires so darn many logical state checks to make sure it's really going to sleep.
Ok, I'll assume that you agree about the "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", and only disagree about the other part. Well, guess what, I already ran the experiment (of comparing 1000 kbot standing still, first scripted your way, then scripted your way), and with my script, it was at 0%, with yours, at 13%. If you had bothered reading the previous page, I wouldn't have had to repeat that.

The main reason I am extremely excited about this whole thing... is that, by utilizing TURN/MOVE and WAIT-FOR-TURN and WAIT-FOR-MOVE... we can get away from static, frame-based animation techniques... and move towards much more dynamic approaches. I'm serious about things like de-tuned animation sequences, and using random number generators in scripts- they'd add a lot more lifelike oomph to existing animation models.
That I agree with.... and I am already using since ... years ago. Basically since my very first TA unit.

Maybe after all the miscomprehension between you and me comes from that, you're comparing your script to Cavedog script, which are very ugly and unoptimised, with lots of messy incomprenhensible code with static and local var to store thing like 'just_moved' and 'somebody_was_playing_with_my_cannon', and which use pages and pages of turn/move ... now; instead of few turn/move ... speed .. ;. So yeah, if your standards are Cavedog scripts, it's not hard to do better.

Hmm, while I was typing that, I see more post where posted, such as "cuts the number of loops down to one". I had eventually came to the conclusion that maybe your "radical improvment" was to have each limb animation in its own thread, and now you're moving everything into one thread!

Ok, please, just answer my initial question:
What is the "radical improvement" we were supposed to see in your first post?
User avatar
Das Bruce
Posts: 3544
Joined: 23 Nov 2005, 06:16

Post by Das Bruce »

zwzsg wrote:Ok, please, just answer my initial question:
What is the "radical improvement" we were supposed to see in your first post?
I've thought it was less code for same effect or reuseability or something.
User avatar
jcnossen
Former Engine Dev
Posts: 2440
Joined: 05 Jun 2005, 19:13

Post by jcnossen »

I think zwzsg is mostly right about the implementation of the COB interpreter:

- There is no memory search, reading a static var will probably be a "memory index" which is in a script language such as this probably nearly as fast as just pushing a constant on the stack.

- I think you can assume constants such as ((LEG_41_FRONT_ANGLE) - (LEG_41_BACK_ANGLE))*1000/(BACK_TIME); are optimized to 1 constant by the cob compiler. Every script language does that.
User avatar
zwzsg
Kernel Panic Co-Developer
Posts: 7052
Joined: 16 Nov 2004, 13:08

Post by zwzsg »

jcnossen wrote:- There is no memory search, reading a static var will probably be a "memory index" which is in a script language such as this probably nearly as fast as just pushing a constant on the stack.
Good!
- I think you can assume constants such as ((LEG_41_FRONT_ANGLE) - (LEG_41_BACK_ANGLE))*1000/(BACK_TIME); are optimized to 1 constant by the cob compiler. Every script language does that.
Sadly, Scriptor isn't as good as a professional compiler. And it does not optimise the code. By compiling, then decompiling the code, you see that Scriptor replaced constants by their values, but did not think about replacing product and division of constants by their result. Maybe one day someone could take Scriptor source and perfect it, but eh, it's hardly a priority.
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Post by AF »

Ok. We need to ask Fnordia how the COB virtual machine really works. I assumed that, just like a processor running machine code, it had a program counter register storing the adress of the line being run, and that it read from the cob and stored in memory one line at a time. Again, we need to ask Fnordia how the COB language is actually implemented in Spring, but it just seem the most logical way. Reading from the COB file and putting in memory everything into { } at once just seem inefficient and useless, and I don't see why the virtual machine would do that, but I'm very glad to hear an interesting theory about why Cavedogs used so many if(TRUE){...}. For very long I wondered why! Xon (formerly ggs) had another theory (he said that in old version of TA, the COB virtual machine could force a pause in script if it had run for too long, but only on "if" statement (or only on { or }, don't remember exactly)). But so far you are the only two people proposing plausible theories! Well, interesting theory as it is, I'll still have doubt on the COB virtual machine reading everything into { } at once until confirmed by Fnordia (or another SY), as I don't see the point in working that way.
Look at my previous posts. The COB VM does not deal with lines. Lines are a human thing and are only bothered with by parsers and compilers.

COB is bytecode

In spring COB is a stackbased Virtual machine setup, and it is very very likely it's also that in OTA.

there is no difference between if(){statement} and
if(){
statement
}

They're both the same in byte code.

Here the cob is bytecode and each byte represents an isntruction. Instructions are put on a stack and read off of the top of the stack as they're executed. Variables, return values, active functions etc all have positions on the stack. It's a common system used in many interpeters and virtual machines and is a core integral component of cpu's.

The number of lines is irrelevant. It's the number of instructions or operations the code performs.
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

First, the test results.

Test Environment:

GreenerFields.sdz

Machine Specs:

Athlon XP 2.17 Ghz, 1.5GB RAM, Radeon 9600 (this is my mom's crappy rig, where I thought the results might be significant enough).

Test protocol: have two AutoFacs build the units as rapidly as possible, walking a very, very long Patrol path to spread them out and keep interactions at a minimum. For testing purposes, raw FPS is not really a factor- there's too much noise involved, coming from other sources of CPU use. Ignore those figures.

zwzsg's script. Speed is 10! Very important!

Image

Mine.

Image

Look at the raw figure for Scripts, on our Debugger Output. Whoa... 4.5% difference there!

Except, that's at Speed 10. So it's really a 0.45% difference, at Speed 1. Hmm... wow, that's a big cost to pay, for simplicity, ease of maintenance, and ... I'm not even done figuring out ways to optimize this yet... hmm...

I couldn't believe the difference was so small, really. I expected it to be worse. So, I ran the experiment again, and then slowed everything down to Speed 1.

Results:

zwzsg's script. Speed is 1! Very important!

Image

Mine.

Image

I'll let the results speak for themselves. I'd have to say that zwzsg wins this round, hands-down... if we're talking about pure speed. Which is important.

Now that I've had time to reflect on all of this, it's pretty clear that when you add inefficiency on inefficiency, that I'd see a pretty big drain on processor, with multiple movement cycles going all at once.

So, let's talk about what this was really about.

Radical Improvements:

1. It is far easier to grasp how to code the methods I'm describing. Really! Whether or not it is more efficient... which, as I haven't even reached a day where I can begin working on serious optimization yet, isn't fully resolved.

That, by itself, argues strongly for this approach. Especially if we want (like I do) to do animations with offset parts, for de-tuned walk cycles and the like. Look, zwzsg... you're making this an argument about pure efficiency. That's not what this is about. If you downloaded NanoBlobs, and substituted the new Archer script for the previous one, done with static methods, you'd see immediately why I got so excited. The previous script, a brilliant second effort by DRB, has four legs walking in a detuned way, in a very natural, non-synchronous movement.

What I did, in a nutshell, was re-create that de-tuned script and lower the number of lines by half. That, apparantly, has passed by everybody, including you, because I didn't post up the modified version of NanoBlobs so that people could compare the old and new versions of my script that I posted here...

Anybody with very little skill can code the way I'm describing, once I've documented it and given people example code and some illustrations. It will make it possible for people to kick out walking animations in just a few minutes, and then tune them over less than an hour, instead of many, many hours of writing down coordinates, putting together a script, testing it, and so forth, only to have it not look very nice the first few dozen times it is assembled. You're looking at this from your position of experience- I'm looking at this from the perspective of somebody who wants more people making complex animated characters for Spring.

2. Maintaining the code is easier.

Once you get past a certain stage, your scripts are horrifically complex structures. Again, I think you're coming at this from your perspective of experience, not from my perspective as a content developer, who wants to get things done (and changed) in a big hurry. I'm looking at Project Two... and I do not want to maintain dozens of scripts of very large size. This will slow me down considerably as a developer.

What if I need to change the speed, or the emphasis? What if I need to add a new conditional loop... for example, make a leg start "limping", due to damage? Your way is just too much work! I'm perfectly willing to trade a few percentage points of raw performance for code that's easier to maintain and modify.



Now... all of that said... I am coming back to this tomorrow, which I have off from work, and I will see if I cannot:

A. Close the gap, on pure efficiency.
B. Show some examples of how clean and simple this can get, so that others can learn from this. It's very clear though that I need to study zwzsg's methods more, and learn where his technique is superior!
Last edited by Argh on 17 Aug 2006, 20:37, edited 1 time in total.
User avatar
jcnossen
Former Engine Dev
Posts: 2440
Joined: 05 Jun 2005, 19:13

Post by jcnossen »

But still, what do the millionth monkey and his typewriter have to do with this ? ;)
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

Ah, just go here.

And just for the record, no, zwzsg is not flaming me. He's teaching me! I thank him for this, even when I'm arguing my case :-)

The results of all of this should be a new approach to making walk-cycles that everybody can use... and a Tutorial to teach it. Because, at this point, it's very clear that I need to document the final results and do yet another teaching document... what I'm learning here could help everybody make far better scripts!
Sheekel
Posts: 1391
Joined: 19 Apr 2005, 19:23

Post by Sheekel »

that tail is the shit!
User avatar
zwzsg
Kernel Panic Co-Developer
Posts: 7052
Joined: 16 Nov 2004, 13:08

Post by zwzsg »

Sheekel, Wolf-In-Exile, Buggi, jcnossen:
My scorpion tail has some issues:
- The tail is "aiming from" its first segment which is a piece turned by the aiming animation. While this cause no problem under the TA engine, with Spring engine reaiming constly, it cause the little jerks you see when it's nearing the final position.
- More concerning, as you can see in the 1.27 mark in the vid, in certain condition the tail get stuck hesitating between going left or going right.
But that is easily fixeable, simply by just aiming from a point not moved by the aiming animation.
- But a bug that I don't see how to fix, is that it aims wrongly. To make it turn like that, I wrote a little function to which you give the 3 angles at the beginning of the tail, the three angles at the end of the tail, and it turn every segments on all 3 axis, spreading the angle of rotations linearly. Then with lots of trial and error I invented some formula giving 6 angles out of the "heading", but, it's purely with messing with the numbers until it looked good that I made it seem to aim at the target. I don't now the real equations that would link tails rotation to the orientation of the end sting (as I insist on turning all segment on a least two axis), and I don't even think it's possible to make it aim perfectly, as by curling, the tail also change the position of its end segment, and if it fire from another place, then the sting angle shouldn't be the same. The relation I used are mathematically incorrect, it appears to aim at target, but only because I tweaked it until it looks good. I don't even use the "pitch"! Completly unlike my sandworms, which themselves use script based on true math equation.
- I doubt actual scorpions tails are that souple! My tail bend and curl more like a pig tail. But I agree that nevertheless, the tail animation is quite impressive. Which was one of my goal when I decided to make this unit.


AlantaiFirestar, sorry, when I said "lines", what I really meant is, "those things that end with a ;"(plus things like if() that don't end with a ; but nevertheless blablabla). I know perfectly you can break one single instruction into several lines, and that you can put several instruction into one single line. Sorry if I caused any confusion, I can't hold myself from saying "lines" when I mean "instruction".


Argh, ok, you're not aiming at better performance ingame, but at easier way to write scripts. Fine. Still, what's the radical improvement over current method we are meant to see in your code? To give each limb its own looping function? To use "speed" instead of "now"? Something else I'm failing to see?
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

Basically, the seperate loops let me do a couple of things:

1. I can offset the start positions of all the legs, then begin Turn and Wait-For-Turn cycles, and then I don't have to worry about complicated offsets or timing issues. That's why I have the redundant-looking Wait-For-Turns in the Archer script- so that when I have an offset, it goes to the next instruction when it needs to, and doesn't de-sync the other parts of the animation.

I am very big on de-tuning animations, because it looks so much more natural. I'm going to re-do the Strider and the SpireRook next, getting rid of code that's huge and bloated with Move NOW commands and replacing them with loops that cut down everything.

2. I can use nothing but turn and move, and Wait-Fors, so that I never, ever use Now during anything. This will allow me to design things more quickly.

******

I know it's probably hard to see from your perspective, zwzsg, but the main thing stopping me from getting things done quickly with Spring has been the scripting side of things. I can build and skin complete 3D models in a few hours... I have zero problems making uber-fancy content... it's getting it to move accurately that's been the main problem. And, while I've learned a fair amount from studying your posts on TAU, reading through Maestro's old stuff, etc... there's a lot I just have had to learn the hard way. I really wish there was a better tutorial out there, and I think I may just have to write one- one that talks about all of the stuff people really want to do, like walk-cycles, and takes people through the scripting process with screenshots, so that it all sinks in. If this whole back-and-forth had any really useful outcome, it's been showing me just how much I'm reinventing the wheel- and doing it the hard way, to boot!

I've made very slow progress on stuff, mainly because I dread the animation process. It's not that I can't do it... I always manage to muddle through. But this was a big step towards something that I can visualise very clearly and then execute rapidly. As I just haven't ever read about this multi-thread approach before, I assumed that this was a big deal! I still think that using it for de-tuned walk cycles for multilegged things works. And we'll see after I sit down and optimize things a bit- I really think I can get efficiency down to close to your margins, even if I can't quite beat it.
User avatar
Fanger
Expand & Exterminate Developer
Posts: 1509
Joined: 22 Nov 2005, 22:58

Post by Fanger »

I suspect that the results of this foray into animation script tuning might come in handy when I redo my robots... I suppose I can borrow some of this stuff?
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

Of course!
User avatar
Forboding Angel
Evolution RTS Developer
Posts: 14673
Joined: 17 Nov 2005, 02:43

Post by Forboding Angel »

I love the idea of script de-tuning, as I actually understand about 90% of what has been said in this thread.

In particular, de-tuning randomly, an 8 legged spider bot is just sexy.

Keep up the good work argh! Zwzsg, I command you and argh to put thine heads together and come up with new uber omgwtfpwn scripting methods for all mod makers of spring. This is what god intended. :P
Post Reply

Return to “Game Development”