thanx :DQuote:
Originally posted by Squize
jtnw:
Is the fastest way to do it.PHP Code:i = 0
while(i++<50) {
//code
}
Printable View
thanx :DQuote:
Originally posted by Squize
jtnw:
Is the fastest way to do it.PHP Code:i = 0
while(i++<50) {
//code
}
Quote:
Originally posted by Squize
tomsamson:
I know what you mean about the Tablet, I do all my work on the laptop now with my big ol' box PC being nothing more than a server most of the time.
Regards pred's routine:
For fear of sounding patronising why doesn't someone speed it up using what's in this thread ?
I honestly think this board is at it's best when it's used as a true community, where someone shares some code which is then improved on and then re-shared.
If someone does that then I'll speed it up with FLASM and use that as a tut piece.
Fantastic bit of code btw pred. Sorry I've been too wrapped up writing my short story on FLASM to say sooner.
Squize.
you´re damn right as always ;)
paste this code in place of old code:
//HitTestArray: Learn from it what you will. io::pred 2003;
//flashcoders rock. tomsamson
hitTestArray = new Array();
function removeClip(obj) {
if (typeof obj == "number") {
var temp = hitTestArray[obj];
removeClip(temp);
} else {
trace("removed: "+obj);
l2 = hitTestArray.length;
while (--l2-(-1)){
if (hitTestArray[l2] == obj) {
hitTestArray.splice(l2, 1);
obj.removeMovieClip("");
break;
}
}
}
}
function addClip(clip) {
hitTestArray.push(clip);
}
function addBox() {
var temp = attachMovie("Ball", "Ball"+i, i++);
temp._y = temp._width/2+random(400-temp._width);
temp._x = temp._width/2+random(550-temp._width);
return temp;
}
function checkCollision(clip) {
l = hitTestArray.length;
while (--l-(-1)){
if (clip.hitTest(hitTestArray[l])) {
removeClip(hitTestArray[l]);
}
}
}
function moveKillBox() {
if (Key.isDown(Key.RIGHT)) {
killBox._x += 3;
}
if (Key.isDown(Key.LEFT)) {
killBox._x -= 3;
}
if (Key.isDown(Key.DOWN)) {
killBox._y += 3;
}
if (Key.isDown(Key.UP)) {
killBox._y -= 3;
}
}
ticks = 0;
droptime = 5;
i = 0;
maxnum = 15;
onEnterFrame = function () {
ticks++;
if (ticks>droptime && hitTestArray.length<maxnum) {
addClip(addBox());
ticks = 0;
}
moveKillBox();
checkCollision(killBox);
};
bout the mobile pc,yep,i think that´s on my list for next months to-buys :)
um,yeah,i see the above as first step,there might be quite some other things which can be speeded up,who´s gonna take this further?
Nice work Tom, you little minx you ;)
(I hope you didn't think that comment about improving on the code was directed at you though, it was just a general one to anyone reading).
Over at http://proto.layer51.com/default.aspx there is a faster slice prototype written by bma
I don't know if this still applies under Flash6 but if someone wants to test it with pred's routine it'd be kinda nice :)PHP Code:Array.prototype.slice=function(s,e) {
var x=[];
for (n=s; n<e; n++) {
x[x.length]=this[n];
}
return x;
}
I know I may seem anal about trying to get a routine running as quickly as possible, but once it's done it's done. Everyone can click on this thread and know they're going to get fast working routines.
Squize.
yep,i got what you meant,just was fun to have a go at it ;)Quote:
Originally posted by Squize
Nice work Tom, you little minx you ;)
(I hope you didn't think that comment about improving on the code was directed at you though, it was just a general one to anyone reading).
also not sure if the normal splice is still slower than the proto one in f6,really would be cool if someone tries that.
i think i´ll replace the hittest with cell comparison next to see how much that affects speed :)
yep :)Quote:
Originally posted by Squize
I know I may seem anal about trying to get a routine running as quickly as possible, but once it's done it's done. Everyone can click on this thread and know they're going to get fast working routines.
Squize.
MyTurn
//HitTestArray: Learn from it what you will. io::pred 2003;
//flashcoders rock. tomsamson
//taking the stage again: io::pred.
_global.hitTestArray = new Array();
function removeClip(obj) {
if (typeof obj == "number") {
var temp = hitTestArray[obj];
removeClip(temp);
} else {
var l2 = hitTestArray.length;
while (--l2-(-1)){
if (hitTestArray[l2] == obj) {
hitTestArray.splice(l2, 1);
obj.removeMovieClip("");
break;
}
}
}
}
function addClip(clip) {
hitTestArray.push(clip);
}
function addBox() {
var temp = attachMovie("Ball", "Ball"+i, i++);
temp._y = temp._width/2+random(400-temp._width);
temp._x = temp._width/2+random(550-temp._width);
return temp;
}
function checkCollision(clip) {
var l = hitTestArray.length;
while (--l-(-1)){
if (clip.hitTest(hitTestArray[l])) {
removeClip(hitTestArray[l]);
}
}
}
function moveKillBox() {
if (Key.isDown(Key.RIGHT)) {
killBox._x += 3;
}
if (Key.isDown(Key.LEFT)) {
killBox._x -= 3;
}
if (Key.isDown(Key.DOWN)) {
killBox._y += 3;
}
if (Key.isDown(Key.UP)) {
killBox._y -= 3;
}
}
ticks = 0;
droptime = 5;
i = 0;
maxnum = 15;
onEnterFrame = function () {
ticks++;
if (ticks>droptime && hitTestArray.length<maxnum) {
addClip(addBox());
ticks = 0;
}
moveKillBox();
checkCollision(killBox);
};
Just made some variables VAR's and made the array global, muahaha
Why did I post a prototype for slice when the routine uses splice ?
Next time I'm a dumbarse, let me know :o
Quick thought, to try and make amends, would it be quicker to use a var to keep track of the hitTestArray.length ( I know the value is shoved into a var before running the loop, but there might be a gain in ripping out the .length line altogether, ie
function addClip(clip) {
hitTestArray.push(clip);
cnt++;
}
var l2 = cnt; //hitTestArray.length;
) ?
Squize.
Yeah I was going to program it like that, but that puts more variable overhead.. but then again, that stop you defining a variable at every iteration of the function..
We could go one step further and make the first element of the hitTest array the length of it.. then start all the loops for(i = 1;i<l;i++)
but then again, that removes tomsamsons while code, cause that relies on a variable we can modify..
So I guess we may wanna just leave it? cause every iteration were going to do:
var l = array.length (if we keep)
or
var l = arraylength (if we do it ur way)
Thinking while im typing, it may actually be faster to keep it like it is, because we dont have to add a new expression of variable++ ever time we add a new element.
Oh, and your splice function kinda does belong here, it optimises the Flash5 splice function, because as far as I remember String,Array etc. were programmed in Actionscript, and were reprogrammed in C++ for Flash6.
I'll get my coat...
Squize.
Wha???Quote:
Originally posted by Squize
I'll get my coat...
Squize.
Just playing matey :)
Squize.
When I first thought about this "mini" tutorial I planned it to accompany the documentation on the official website. With that in mind I'm not going to go through all the instruction set, just enough to get you started off. Hopefully at the end of all this you'll dance your way through the more detailed documentation with a grin on your face and maybe even a stirring in your pants.
To recap, FLASM is installed, you know the theory of the Flash Player being a virtual machine and you know how to include bytecode back into your swf. Sweet.
Example - Bubble Sort:
As you know Flash assembler is called "bytecode" ( Or "P-Code" depending on whose writing ).
Assembler is a low level language, which means that it's very simplistic. It helps us because it means there is only a small instruction set to learn, but you can only have one instruction per line ( Which means a huge output file ).
The example I'm going to use as an introduction is jobem's bubble sort ( Posted here: http://www.flashkit.com/board/showth...hreadid=451478 ) 'cause it's a nice little example of a loop that we can do something with.
Firstly copy and paste the code into a new fla, save it as "bubbleSortOriginal.fla", publish it as normal and disassemble it.
Open the new flm file. The top lines will read:
We don't need any of that ( It goes without saying that the actual top line will be different. Duh ) so just delete it all. You'll always be able to delete these lines in every disassembled swf, we don't need them. Then scroll down until you find:PHP Code:movie 'C:\Shoah\Tutorial - FLASM\bubbleSortOriginal.swf' compressed // flash 6, total frames: 1, frame rate: 12
fps, 550x400 px
frame 0
constants 'Array', 'prototype', 'bubblesort', 'i', 'this', 'length', 'n', 'temp1', 'temp2', 'arguments',
'b', 'nums', 'bubbleSort'
Delete all the lines from ( And including ) "end // of function". The lines after this aren't part of the prototype so we don't need them here.PHP Code:label6:
end // of function
Open the fla again and the follow the procedure for embedding a macro as detailed in the previous post ( The inserting a new layer, _global.FLASM=false; thing. ). Alter the start of the prototype code to:
( I covered this in the last post as well ). Save the fla as "bubbleSortOptimised.fla", and publish it. If you then update it with FLASM it will be running the bytecode version.PHP Code:Array.prototype.bubblesort = function() {
if (FLASM==true){
$include ("bubbleSortOriginal.flm")
} else {
Cool. The only thing is that we haven't actually optimised the bytecode yet so it'll run at exactly the same speed, but we're getting there.
For the last part of this part ( Excellent use of language ) I'm going to cover some other bits and bobs you've got to get your head around before we can finally optimise something.
Labels:
Open up the flm file. Look at the listing and you'll find "Label1" etc.
Think of a label as a line number, like in the example way back in the first part ( Hopefully this is starting to fall into place ? ). We don't need a line number for every line, only when there is a branch ( Coming next ) or a loop to that particular line number, ie a reason for the code to go to that specific line.
So to avoid having a line number for every line, which let's face it is a bit of a waste, we just have a line number as and when we need it. And because this is programming we don't call it a line number, we call it a label. And a label can have pretty much any name you want.
Let's re-do that example using labels:
Branch:PHP Code:exampleFunction();
...
...
label1:
function exampleFunction() {
trace ("Wow the line numbers did make sense I now I get labels too!");
}
This may be something you are not that familar with in Action Script. It's considered bad practise in med/high-level languages ( Which should take an OOP approach ) but we're getting our hands filthy dirty with assembler, so we can use every trick in the book to get our swf running faster than every one elses.
Now we all get conditional branches, we use them every time we fire up flash.
A conditional branch in all it's glory. Depending on the outcome of the test ( The conditional ) we either branch to one bit of code or the other.PHP Code:if (lives==0){
trace ("Game Over");
} else {
trace ("Life Lost. Bummer.");
}
Something we can't do in Flash ( You can, but humor me here. ) is just branch to a specific line. Well, and you know this is coming, with FLASM you can. The bytecode is, this is going to blow you away,
branch label
As easy as getting me to drink lager and smoke fags.
Registers revisited:
The Flash virtual machine has 4 registers called r:0,r:1,r:2,r:3. Going back to part one again we know that a register is in effect a cpu variable. Because it's held in the cpu and not memory it's quicker to use than a normal variable.
So what does that mean to us assembler coders ( 'Cause that's what we are now kids ) ?
Well if you push an often used variable into a register you can get to it quicker. So every time you need that value you don't have to get it from slow ol' memory but from an ultra quick register.
For example, you may have some action script code like:
And you use that a lot in your function. Every time you need to use that variable, for whatever reason, the following bytecode is produced:PHP Code:speed=4;
What this does is push the variable name onto the stack, then the getVariable instruction retrieves the value of speed, pops the name speed from the stack and then pushs the actual value back on there.PHP Code:push 'speed'
getVariable
If you could see it in action it would look like:
Stack = 'speed'
Stack = nothing
Stack = 4
Now if we had the value of speed stored in register r:1 the bytecode would only be:
And the stack would bePHP Code:push r:1
Stack = 4
You can see where the saving is coming from.
You may remember from the first page ( I think ) of this thread I wrote
a=b=c=d=0;
is quicker than
a=0;
b=0;
c=0;
d=0;
And now you're going to find out why. When you publish a movie in Flash it converts your Action Script into bytecode ( Compiling ) and it dosen't do it as well as we could ( But it does do it a lot quicker :) ). Well to be fair it does try, and when it comes across a line like a=b=c=d=0; it uses register r:0 to store the value '0' into.
How do we put a value into a register ?
So we push the value 4 onto the stack, and then we use the setRegister instruction to put it into a register. Now setRegister dosen't affect the stack, so we have to use pop to remove that value from the stack again if we are not going to use it there and then.PHP Code:push 4
setRegister r:1
pop
The hardest thing about writing in bytecode is ensuring that the stack is "Balanced". You put something on it you have to make sure you take it off again. If you don't the Flash player will soon either get out of sync and put the wrong values in the wrong places or even worse the stack will just grow and grow and steal all the memory in your computer making it grind down to a halt.
Next time we are going to make that bubble sort routine fly! ( I'm sorry if this seems to be dragging but it's not the easiest thing in the world teaching people a new programming language :) )
Squize.
PS. I'm writing a stupid amount on this, feedback would be nice! I don't mean as a stupid ego thing, but I don't want to be just talking to the walls. Thanks for your feedback Tom :D but you already understand all this stuff, is anyone else getting this who didn't understand it before hand ? Thanks.
hey,
im still having trouble getting flasm open, i did the right click thing for dissasemble, but when i tried to make the update option, i dont get where you are suppost to put the parameter -u.
btw great tutorial so far!
Thanks jtnw :D It's hard 'cause I'm writing each part as I go so I'm trying to get it into some kind of order that'll make sense.
I've got a bad feeling that I won't be able to optimise the bubble sort that much and everyone'll be left thinking "Whats the point?" ( Perhaps I should have done it first. Oh well )
Sorry I should have explained setting up the update command a bit better ( My bad ).
Follow the instructions as for disassembling, and where you put the program you want to use ( In this case FLASM ) follow it with -u %1 and it should work.
I've attached a screeny which should help.
If anyone has any questions about anything so far please feel free to ask.
Squize.
following it, keep going :) when all parts are there ill read a few times and give it a try :)
ditto for me. keep it going
Cheers guys!
I guess the best way to go is just finish it all off and let everyone field questions then. I was just worried that I was so wrapped up in myself that I was writing poo without realising it.
Squize.
thanks squize!:D it works now
At the bottom you'll find the original fla, the slightly modified one with our FLASM macro, the untouched disassembled output and our new super duper code.
I'm just going to dive in and work through the ( Interesting ) altered code.
The line for (n=0; n<=i; n++) { converts to the following in byte code
We are going to put the variable 'n' into a register because it crops up a lot in the routine and so it will give us a good overall saving.PHP Code:push 'i'
getVariable
push -1
greaterThan
not
branchIfTrue label6
push 'n', 0.0
setVariable
label2:
...
...
label4:
push 'n', 'n'
getVariable
increment
setVariable
branch label2
The first 6 lines we'll leave alone, so we'll just push the counter value in a register.
We just push 0 as opposed to push 0.0 'cause an integer will do just fine ( Update does this automatically for us as part of its junk removal ) and then we put the value into r:0.PHP Code:push 'i'
getVariable
push -1
greaterThan
not
branchIfTrue label6
push 0
setRegister r:0
pop
...
...
label4:
push r:0
increment
setRegister r:0
pop
branch label2
The code in label4 just simply pushs the register onto the stack, increments it, and then stores it. Next to no work really and we've saved having to both create a variable and push / pop it from memory when we need it.
The next bit to look at is var temp1 = this[n];
Again we are going to substitue the var temp1 with a register 'cause this will give us a big saving throughout the loops.PHP Code:push 'temp1', 'this'
getVariable
push 'n'
getVariable
getMember
varEquals
I think that's it for now. It may seem a little bit anti climatic after all the theory but I've really commented the files and this was only meant to be a companion to the official site, not a full blown tutorial. The example could be speeded up even more ( Even at an action script level ) but this is only a starting point.PHP Code:push 'this'
getVariable
push r:0 //r:0 = n
getMember
setRegister r:1 //r:1 = temp1
pop
As ever any questions then just ask and thanks for sticking with me through this.
Squize.
Could someone breakdown the syntax of this for me, I understand while loops, but this is a notation I have never seen before.Quote:
Originally posted by tomsamson
while (--l-(-1)){
Great thread by the way, makes you realise how much there is to learn out there. Keep up the good work, most appreciated.
\= siriuss.
// hello by the way, kinda new to the board