Friday, 7 April 2023

RemoveEventListener added with bind - Easy

In html5 canvases, when you add an event listener to something, it persists even if the movie clip is no longer on the stage. This causes two problems:

1) This takes up memory because the memory will hold on to the movie clip as long as it still has event listeners. Not just for movie clips on previous frames, but also if you are dynamically adding and removing clips - they will never go away, and your animation will gradually (or quickly) grind to a halt.

2) You an accidentally add multiple listeners to movie clips, e.g. when adding a mouseup event after a mousedown event, which you might do for dragging a movie clip. This could lead to contradictory or exaggerated responses, as well as taking up memory.

You can check if movieclips have event listeners before adding them with 'hasEventListener' (pass the event), and remove event listeners with 'removeEventListener' (pass the event, and the function).

This won't work if you have used the bind function to control the scope of the function. You have to pass the bound version that was originally given. If you are adding the function to multiple movieClips, creating a variable for each bound function could get messy. One way around this is to get each movieClip to store it's own bound functions.

See the example below:

------------------------------

1    this.tempFunction = function(e) {
2        console.log('click');
3        this.removeEventListener('click',this.ck);
4    }
5
6    this.btn.addEventListener('click',this.btn.ck = this.tempFunction.bind(this.btn));

------------------------------

You should find that the first time you click the button, a message 'click' comes up in the console (Ctrl+Shift+i in Chrome), and then it stops responding.

6: This line adds an event listener to the button (this.btn), that will respond to a click. The function called in response to the click is this.tempFunction, and bind is used so that the tempFunction works from the perspective (or scope) of the button. 

This part: "this.btn.ck = this.tempFunction.bind(this.btn)" simultaneously passes a function that should respond to the event and assigns it to a variable at the same time, and this variable (this.btn.ck) belongs to the button (this.btn).

1: This line declares the function that will respond to the click event of btn.

3: Remember that when this function is called, it will run from the scope of the btn, so when the event is removed, we can pass it 'this.ck', because from the btn scope, that is how to refer to the function that was referred to in line 6.

WARNING: removeEventListener won't tell you if it doesn't work, i.e., if it can't find the event you are trying to remove, so check the event has really been removed.

Friday, 6 January 2023

Getting the position of a character in a text object in CreateJS

 For those of us who are accustomed to Flash, if we wanted to know the exact x,y coordinates of a character in a textbox, using AS3, we could use the getCharBoundaries function, which if I remember correctly, would return a Rectangle object with the x, y, width and height... I think? The point is, there was a built-in method to do it.

Such a function does not exist in CreateJS (or I couldn't find one).

I was trying to make a little missing-words-type activity, and I wanted users to select the word they were dealing with (could this have been done in HTML with less bother? Probably, I dunno) - so I needed to make a button that would go behind the part of the textbox where the specific word was created.

When I saw that CreateJS did not have an equivalent of the getCharBoundaries function in AS3, I was ready to give up and try an alternative approach. But then I remembered that there are monospaced fonts such as Courier New, that we use in biosciences so that DNA and protein sequences are easy to read. If I used one of those (please skip to the code excerpt(s) below if you aren't interested in the evolution of this, I just really enjoyed this little problem-solving journey, personally), I reasoned, then as long as I knew where the text started, I might be able to figure out the location of each letter, though working out where the line breaks were would be a pain.

On the stage, I manually measured the width of each letter (I realised later a better way of doing this, see below) at 21.6px in the font and size I was using. I used this letter width and the index of the character in the text to position a movieclip relative to the text area.

There were two empty movieclips on stage, the one on top (loadIt) was for loading the dynamic text, the one underneath (loadItBtn) was for loading the buttons.

It went something like this (just focusing on how to deal with a single line first):

tx = new createjs.Text('Hello _____.''36px Courier New','black');
this.loadIt.addChild(tx);

this.letterWidth = 21.6;//I measured this on the stage manually...blech
for(i=6; i<11; i++) {
	btn = new lib.btnMC();//this is just a rectangle made to match the height of the line, and the width of the letters.
	btn.x = i * this.letterWidth;
	this.loadItBtn.addChild(btn);
}

So, some useful functions: tx.getMeasuredWidth() could tell me how wide the text area was, as I was using short paragraphs. I would then use tx.lineWidth, to set how wide I wanted the text area to be, which would cause word wrapping. I would then use tx.getMeasuredHeight() to find out the height of the text area so I could position it on the canvas (you can use a function to get or set your lineHeight).

However, what if the text ends up with multiple lines? Enter (drumroll) getMetrics()!

This function will give you an array, called 'lines', which tells you what text is in each line! So I wrote a loop to check whether the index of the character in the text could be found in the line of the array. Then adjusted the y coordinate of the buttons I was adding based on that. Then I had to remember to figure out what the index of my character was in the line of the text, and use that as the x coordinate.

I won't go into all the details, but if you use console.log(text_name.getMetrics());, you can see the output for yourself in the console.


ISSUES:

1) Using scaleX to size an mc to match the word width did not work for me, it doesn't seem to be very accurate. I dealt with this by making a movieclip that was the perfect size and adding it multiple times, but a better solution would have been to draw a rectangle of the correct size.

2) Measuring the letter width manually is a pain, but manageable because you only need to do it once, but then you have to stick to that font size. I realised later that you could write a function to create a text area, add some text and measure the width to calculate the width of a single letter. Then I realised that actually, you could do this for any font! You'd have to make sure you measured every type of letter you were planning to use, and punctuation, but you could easily create an object that stores the widths of the characters you are using. Easily-ish. But basically, it means that you could work out the position of letters in text areas, and such a function would require some alteration if the text was left-, centre- or right-justified, and it would probably only shorten your life-span by a few years... But, yeah, doable.

You can see an example of what I was aiming for here: Missing words exercise

Have a nice day!

Wednesday, 24 August 2022

Off-topic: numpy loading text file with strings and floats

 When using np.loadtxt to load a text file (first column a single letter, second a float), I found the best way was this:

cons = np.dtype([('res','U1'),('con','f')])
dt = np.loadtxt("/content/drive/MyDrive/Colab Notebooks/bonds/zip14a_cons.txt",dtype=cons)

Trying to use 'S', or 'S1' put a b in front of the text, with quote marks. Just using 'U' returned nothing.


Thursday, 15 December 2016

How to: Input text box in Animate CC canvas, version 2

This method will allow you to put input text boxes within a particular location on your canvas, using co-ordinates etc that make sense, that will change if the page is resized.

By the end of it, you should be able to create an input textbox form within your canvas, just by calling a function like this:

createTextBox(250, 76.05, 315.1, 16);//width, xpos, ypos, fontsize

1) Put the canvas in a div, so that you can easily add input boxes just after the canvas.

 <div id='canvasHolder'>
<canvas id="canvas" width="800" height="450" style="display: block; background-color:rgba(0, 0, 0, 1.00)"></canvas>
</div>

2) My canvas is set to resize with the window, under Publish Settings, I chose: Center stage, Both; Make responsive, Both; Scale to fill visible area, Fit in view. So this code works for those settings, but seeing this might help if you are using something different.

So the canvas html contains a function that automatically resizes the canvas, and you will need some of those variables to figure out how big your textbox needs to be. So you need to give them a global scope. In the javascript,

var pRatio, xRatio, yRatio, sRatio;

Also, create an array that will hold all your text boxes so that you can resize them later.

var txtBoxes = new Array();

You also need to go into the resizing function and remove the 'var' so that they are global variables. In the resizeCanvas function, change:

var pRatio = window.devicePixelRatio || 1, xRatio=iw/w, yRatio=ih/h, sRatio=1;

to

pRatio = window.devicePixelRatio || 1, xRatio=iw/w, yRatio=ih/h, sRatio=1;

3) Now here is the function that will create the input text box:

function createTextBox(wid, xpos, ypos, fsize) {
var node = document.createElement("INPUT");
node.type = 'text';
node.style = "position: fixed; font-family:'Gill Sans MT'; border:none; border-bottom-style:solid; border-bottom-width:1px";
txtBoxes.push({'ele':node,'wid':wid,'xpos':xpos,'ypos':ypos,'fsize':fsize});
sizeBox(txtBoxes[txtBoxes.length-1]);
document.getElementById('canvasHolder').appendChild(node);
}

The first line of this function creates an input 'node', the second specifies it as a text input, although this is the default, so not strictly necessary.

Setting the css position to fixed works for me, but some others might work too, this isn't my strong point. Setting the font and border was a personal choice.

It adds an object containing the node and all its sizing properties to the txtBoxes array, so that this info can be used when resizing later.

It calls the sizeBox function with the object - this will position the object appropriately.

Then it adds the node to the canvasHolder element (where the canvas is).

4) Here is the sizeBox function:

function sizeBox(obj) {
var node = obj['ele'];
node.style.width =  Math.round((canvas.width/pRatio)*(obj['wid']/lib.properties.width)) + "px";
node.style.fontSize = Math.round(sRatio*obj['fsize'])+"px";
if(xRatio < yRatio) {
node.style.left = Math.round((canvas.width/pRatio)*(obj['xpos']/lib.properties.width))+"px";
node.style.top = Math.round((0.5*(window.innerHeight-(canvas.height/pRatio)))+((canvas.height/pRatio)*(obj['ypos']/lib.properties.height)))+"px";
}else{
node.style.left = Math.round((0.5*(window.innerWidth - (canvas.width/pRatio))) + ((canvas.width/pRatio) * (obj['xpos']/lib.properties.width))) + "px";
node.style.top = Math.round((canvas.height/pRatio)*(obj['ypos']/lib.properties.height)) + "px";
}
}

The size properties of the canvas is complex and I don't fully understand how it works, but I just kept fiddling around with things until it sort of made sense. Basically, you can set the width relative to the canvas' actual size, same for the font.

Its similar for the x and y position, but one will need to be offset because the ratio of the width and the height may not be equal.

5) Finally, alter the resizeCanvas function so that the textboxes are automatically altered.

After this line:

lastW = iw; lastH = ih; lastS = sRatio;

Add this:

for(i=0; i sizeBox(txtBoxes[i]);
}

It goes through each of the txtBoxes and resizes them, as the window is being resized.


6) Now you can create them from your canvas, like so:

createTextBox(250, 76.05, 315.1, 16);//width, xpos, ypos, fontsize


Just a few notes about this method, the alignment is 100% flawless, I think because everything has to be rounded off to pixels, but it is pretty good.
Also, how to access the value inside? You can't assign them an id, and use document.getElementById, because the node is dynamically added. But you can access the txtBoxes array and get the value of the node.

Wednesday, 14 December 2016

How to: Input text box in Animate CC Canvas, version 1

Am getting more used to animate CC canvas, and was quite happy until I found that you couldn't do input text boxes, at least not directly. But I suppose the nice thing about these difficulties is the smug feeling of self-satisfaction you get when you overcome it (entirely undeserved, with all the online help I got), anyway!

The strategy is basically to make an invisible text box that holds on to text when you type and passes it to the text box on your canvas.

In terms of making the text box invisible, you can't use display: none, as textboxes can't get the focus if they are not displayed, or hidden.

If you use opacity:0, then you won't be able to see the textbox, but it will still take up space, and someone could click on it by accident, possibly leading to upredictable results.

So I'm opting to use opacity, set its width to 0, and setting it to be off of the screen as well!

1)
Here is the html for the textbox:

<input type='text' id='testInput' oninput="sendInput();" style="position:absolute; z-index:-1; opacity:0; width:0; top:-30px">

If this is the very first element in the body tag, then it should be above the visible window, ie offstage. If you have other elements around your canvas you may need to fiddle with this, but I doubt it as the textbox doesn't need to be in any particular div to work.


2)
In the script tag in the head, you need to create variables for your input textbox, and whatever the receiving textbox might be, something like:
<script>
var txtTarget, txtInput;

And in the init function called by the loading body tag:
<body onLoad="init()">

You need to assign the input textbox to the txtInput variable:

function init() {
     txtInput = document.getElementById('testInput');
}


3)
As for the sendInput function, that goes in the script section:

function sendInput() {
 txtTarget.text = txtInput.value;
}

This sends the content of the input text box to the text box in the canvas element.

4)
In the animate CC flash file, you need to create a dynamic text box (call it textReceiver), and a button behind it (called txtbtn), you could save time by making it look like an input textbox.

The code for this is:

this.tstbtn.on('click', focusText.bind(this));
function focusText(e) {
 //txtInput.value = this.testReceive.text = '';
 txtInput.focus();
 txtTarget = this.testReceive;
}

This function means that when someone clicks on the button, it is as though they have clicked on the input textbox. It also sets the html page to recognise the canvas's text box as the text receiver.


In theory, you could create multiple textboxes (though not on the same frame in animate CC), and put a button behind each one, so that when it is clicked, it registers its textbox as txtTarget. In that case, you need to use the line that is commented out, so that the text from one textbox doesn't get copied over to another.

The downsides to this method, which occurred to me as I was writing the post, are that the user doesn't get a cursor, they can't highlight the text, and they can't easily edit the content, since they can't click part way through the text.

So I may go back to the drawing board on this, to get the full input text box functionality.

Monday, 14 November 2016

Animate CC/HTML5 Canvas Issues

I'm returning to this after a long period away, and it is really getting on my nerves, but I'm hoping that will pass as I get used to all the little (or big quirks).

Just making a note of some things I am figuring out as I go along.

1) You can't put different dynamic textboxes on the same frame.
a) If you put them on the same layer, Animate will insist that they are called by the same name. Best to just humour it and give them the same name.

2) Scope! Aaaarrrrggghhh!!!
If you use addEventListener as usual, it seems to switch to 'window'? Not really sure what this is, maybe one day it will be useful...

The syntax for 'on' is:

this.mc.on('added', function(e) {
console.log('hey there');
});

The above method seems to allow the mc to work from within itself?

On the other hand,

this.mc.addEventListener('click', someFunc.bind(this));

seems to make it have the scope of the place where the function is written, if I remember correctly. And can be altered to give it a different scope?

Each of these ways is removed differently, so that might influence what you choose to use.

CAUTION
Animate will add extra eventlisteners to the objects everytime you return to the frame, so use hasEventListener to check if the eventListener has already been attached (it only takes the event as a parameter).

3) Undefined for a movieclip that is on the screen?

So this is irritating, you are trying to do something to a movieclip that is on the stage, it has a name, so why on earth is the browser claiming it doesn't know who that is? And why is it able to find other movieclips easily?

Answer(s): You can add eventListeners to something that hasn't loaded yet, but you can't check its location or anything like that. So... use an added eventListener to check when it does exist, and then use it after that.

Thursday, 8 October 2015

Flash CC Pro/CreateJS: nextFrame

This function doesn't exist in Flash's HTML5 canvas, but the below will work instead.

this.forw.addEventListener("click", goNext.bind(this));
function goNext() {
this.gotoAndStop(this.currentFrame + 1);
}

Wednesday, 7 October 2015

Flash CC Pro/CreateJS

Another strange thing when working with Flash's HTML5 Canvas is that variables cease to exist when you move to the next frame.

I am used to having a root timeline that I can store info on that all other movieclips might need, but this won't work if they disappear between one frame and the next.

My current adjustment is to move everything down by one timeline. So I have a single frame on the uppermost timeline, and the movie clip sitting on that contains several frames, as I would normally lay things out. If something needs to be stored while moving to the next frame, then I just store it on the parent timeline.

for this function that I wanted all movie clips to be able to access:

this.giveDimensions = function (mc) {
mc.height = mc.nominalBounds.height * mc.scaleY;
mc.width = mc.nominalBounds.width * mc.scaleX;
}

In the timeline of the movieclip:

this.parent.giveDimensions(this.work_btn);

Flash CC Pro/CreateJS: Width and height of movieclips

I am currently trying out Flash CC Pro and the HTML5 Canvas publishing option.

One odd thing is not being able to access the height and width of the movie clips.

With the help of a stackoverflow post (http://stackoverflow.com/questions/29768424/how-to-get-width-height-of-a-movie-clip-in-createjs), I came across 'nominal bounds'. Couldn't find it in any of the documentation, it doesn't appear as one of the coding hints in the flash program either. Oh well.

I found that movieClip.nominalBounds gave me back an object that contained the original x, y, width and height of the unaltered movie clip. But on the stage, mine was a bit stretch and squashed, so I used

movieClip.nominalBounds.height * movieClip.scaleY

and this gave me the actual height. Ditto for the width.

Apparently the various bounds properties and functions vary depending on the exact type of object, but this worked for my movie clip.

Friday, 14 November 2014

How to Use Screen Shots in Flash

Sometimes, you want to take an exact picture of what is on your screen and put the image into Flash, but when you do, most of the image is transparent!

1) Press the PrtScn button on the keyboard to take a picture of the screen. Alternatively, to take a picture of a particular window, make sure the window is selected, hold down Alt, and then press PrtScn.

2) Open up a Word document, and press Ctrl+V (or just right-click and select Paste).

3) Select the resulting image, and copy it (right click, Copy, or Ctrl+C).

4) Now you can go back to your Flash document and paste the image, and it will look the way it should.

Have fun!

Monday, 18 August 2014

How to randomly generate -1 or +1, in one line.

A hobby of mine is avoiding if statements, with mathematical formula that return the right number based on other conditions.

It is easy to generate a 0 or a 1 randomly, simply use Math.round(Math.random());

That will work in a number of languages, or something similar.

For a random -1 or +1, try this:

var randNum = -1 + (2*Math.round(Math.random));

If the random number generated by Math.random() is 0.5 or above, then the answer will be 1. If the random number generated is less than 0.5, the answer will be 1.

Enjoy!

Sunday, 17 August 2014

How to make a RevoluteJoint in Box2D/CreateJS

There are plenty of posts on how to get box2d and createjs working, Lee Brimelow has a great youtbe video that covers how to get started very nicely.

But when I tried to make a revolute joint, I made a silly mistake that took me hours to find the source of. I'm a bit of a newbie, but I didn't find the problem to my solution online, so I thought I'd post it in case it happens to anyone else. And then maybe they can go to sleep before 5 in the morning...

Does this sound familiar?

"I can make the two objects, but when I try to create the joint, I get an 'Uncaught TypeError: undefined is not a function' message.'

Well, first, since I was working from the Lee Brimelow example as a starting point, I hadn't made sure I had setup the shortcut to the actual RevoluteJoint parts of box2d.

eg.
var box2d = {
b2Vec2 : Box2D.Common.Math.b2Vec2,
b2BodyDef : Box2D.Dynamics.b2BodyDef,
b2Body: Box2D.Dynamics.b2Body,
b2FixtureDef: Box2D.Dynamics.b2FixtureDef,
b2Fixture: Box2D.Dynamics.b2Fixture,
b2RevoluteJointDef: Box2D.Dynamics.Joints.b2RevoluteJointDef,
b2RevoluteJoint: Box2D.Dynamics.Joints.b2RevoluteJoint,
b2World: Box2D.Dynamics.b2World,
b2MassData: Box2D.Collision.Shapes.b2MassData,
b2PolygonShape: Box2D.Collision.Shapes.b2PolygonShape,
b2CircleShape: Box2D.Collision.Shapes.b2CircleShape,
b2DebugDraw: Box2D.Dynamics.b2DebugDraw
};

Still wouldn't work though. So here was the problem, my makeJoint function looked like this:
function makeJoint() {
var jDef = new box2d.b2RevoluteJointDef();
jDef.bodyB = c;
jDef.bodyA = a;
jDef.collideConnected = false;
jDef.localAnchorB = new box2d.b2Vec2(0/SCALE,80/SCALE);
jDef.localAnchorA = new box2d.b2Vec2(0,0);
j = world.CreateJoint(jDef);
}

where a (I thought) was the anchor body, and c was the other body I wanted to attach to it.

Unfortunately, a and c were actually the fixtures of those bodies, instead of the bodies themselves.

So in my function that made the anchor body, it said:
a = world.CreateBody(anchorBodyDef).CreateFixture(anchorFixtureDef) ;

So I changed it to:
a = world.CreateBody(anchorBodyDef);
a.CreateFixture(anchorFixtureDef);

Hope that helps.

Tuesday, 22 July 2014

How to rewind an animation, AS3

To make the animation rewindable, it needs to be all on one timeline for starters. With no movieclips doing anything complicated that will look weird if everything is going backwards while they are going forwards. Flashing or jiggling, or something like that is fine, but it has to work backwards and forwards.

Graphic symbols are fine, because they will play backwards as the movie clip goes backwards.

Anyway...

In order to make the clip go backwards:

clip.addEventListener(Event.EnterFrame, goBack);

function goBack(evnt:Event):void {

clip.prevFrame();

}

In order to get the clip to stop going backwards, either once it gets to the beginning, or at certain points along the way, put code on the relevant frames inside the movie clip that checks if the eventListener exists, and if it does, removes it.

I hope that was clear enough.

Friday, 4 July 2014

Flash: How to make the white transparent in a grey scale image

What if you want to get a picture and colour it in, but you don't want it to take forever, or lose any of the detail?

(Apologies if this can be done more easily in another program, but when it comes to pictures, I'm most comfortable with Flash.)

1) Find your image, the more contrast the better - ie, some really light areas and some really dark, the less grey the better.

2) Copy and paste it into flash.

3) Turn it into a movie clip, select it, and in the Properties box, select Adjust Colour, and increase the contrast. Try to choose an optimum value where you can see the details you need, but the grey areas have turned white.

4) Then choose the blending option Darken. The white areas should now be transparent.

5) Lock the layer of the photo, and create a new layer underneath. With this layer selected, draw lines to delineate the blocks of colour you want to show through the image. You can apply fills with gradients, or make areas of colour into movie clips and give them glows as ways of mixing colours etc.

6) If you want to make the lines darker, you can copy and paste the movie clip on top of itself (this way it will have the same contrast settings) and set the blending option of the one on top to Multiply.

Example:


Before

After
I'm no artist, and I'm not claiming that mine is an improvement on the original, but I am claiming that this didn't take me very long at all.

Wednesday, 29 January 2014

Arduino - Whoo!

I have in my posession, (it's not mine though) an Arduino Uno. Quite a departure from Actionscript, CreateJS etc (except I'm not departing them...)

What Is Arduino For?

I'm not quite sure yet, but it can take input from a variety of sensors, and it can connect to output, eg. lights motors etc. So although it seems quite limited in terms of memory, it seems to have a lot of potential. Anyway, I'm sure it has more potential than I'll ever be able to make use of, so, who cares what it's limits are! Also, I read somewhere that it may be able to work with Flash...

I've found some great tutorials online, the first one is here:

http://www.youtube.com/watch?v=fCxzA9_kg6s

I'm just making notes of anything extra.

I went through tutorial 1, and the first issue I came across was installing the driver. They guy in the video had a later version of Windows than me. The help on arduino.cc for XP users also didn't match what I saw on my screen.

So, I went to the Control Panel, System, Device Driver, and was faced with a long list of things... I don't know what they were. I couldn't see anything called Arduino, and I couldn't see what they suggested might be under ports either. But when I unplugged and replugged the arduino board back in, something appeared under USB. So I followed the recommended procedure (section number 4 on this page: http://arduino.cc/en/Guide/windows) with this instead. And that worked fine.

The second issue was when I tried to upload the program, actually, I think it worked the first time, but when I tried to make changes, I couldn't see any effect. In the video (the first link above), an error message came up when he had forgotten to set the serial port - which he changed but then didn't show how to do it from the menu.

When I tried to upload, I got this error message:

avrdude stk500_getsync(): not in sync resp=0x00

When I changed the com port (go to Tools, Serial Port, and then select a different com port) everything was fine after that.

Tuesday, 10 September 2013

Easy - Get REAL Co-ordinates of a Movieclip Inside a Movieclip: localToGlobal, AS3

localToGlobal allows you to get the actual position of a movie clip, that is inside another movieclip.

Normally, if you trace, or try to get, the x or y coordinate of a movie clip, you will get its position, relative to the 0,0 coordinates of the movie clip it is sitting in. These are the local coordinates of the child movieclip.

To get the global coordinates, ie, where it REALLY is on the main stage, you need points, and the localToGlobal function.

e.g

(On the stage, there is a squareHole_mc, and inside that is a roundPeg_mc.)

var pt:Point = new Point(squareHole_mc.roundPeg_mc.x,squareHole_mc.roundPeg_mc.y);
pt = squareHole.localToGlobal(pt);



So basically, you create a Point, that contains the local x and y coordinates you are interested in. Then you use localToGlobal to find out the global version of those coordinates, bearing in mind they are sitting in a parent movieclip.

UPDATE:

Now in one line(!!!):

var pt:Point = sqH.localToGlobal(new Point(sqH.rPeg.x,sqH.rPeg.y));

Monday, 9 September 2013

Losing Focus on Textfield, AS3

I had a problem with a text field, I wanted to click on it, have something happen, and be able to continue typing straight away, but it kept losing focus after the first letter.

So I added a trace statement to find out what was happening, and then it would lose focus after it was clicked.

The reason was the trace statement was causing the whole swf to lose focus. So I am sending a trace statement in the frame, so that the initial focus is dealt with. The losing of focus doesn't occur after the first trace statement.

P.S. To set focus using action script:

stage.focus = textfield_txt;
textfield_txt.setSelection(textfield_txt.length,textfield_txt.length);

Thursday, 6 June 2013

EaselJS: Spritesheets

Still figuring this out myself, but here is what I have so far...

A sprite sheet is an image of all the frames of an animation, I'm not sure if it has to be a .png, but that will work.


In the example file, there were loads of scripts added, but I replaced it with the one script and it still worked for me...


Line 24: Create a 'spritesheet' - seems to be a way of telling the page which sections of the spritesheet are what, etc.
"animations" is, I think, used if you want to use your spritesheet as an animation? I don't know.

Lines 26 and 27: These two lines both define certain frames as part of a sequence. Sort of like if you had frames in Flash, and a frame had a name, and then when it reached a certain frame, it would loop back to the beginning, or go to another named frame.
On line 26, it's saying that the run sequence is to start from section 0 of the sprite sheet, and go through to section 25, and then, though I have commented this out, to go to the sequence of frames called 'jump', which is defined on the next line.

Line 28: Defines the source file for the image that is the spritesheet.

Lines 29 to 36: Tells it how to recognise what frames are on the sprite sheet.
"hieght" and "width" are how many pixels each section of the image is that should be taken as a frame. I'm not sure how you are supposed to know this, I made a sprite sheet using zoe, and it gave me a file that was 2048 by 512 pixels, with two rows of 7 frames. So I divided 2048 by 7 to get "width", and 512 by 2 to get "height". It worked for me. I suggest you try altering these values so you can see what goes wrong.
"regX" and "regY" are the registration co-ordinates for the animation that will result from the sprite sheet.
"count" is how many frames you have in total, I think.

Line 38: Assign your animation to a variable (a BitmapAnimation) that you can then position etc, and generally treat like a movie clip.

Line 61: If you use gotoAndPlay without any parameters, it will just play everything that the spritesheet is capable of. Or you can tell it which 'frame' to go to.

Line 64: You need the Ticker to get it to work, but strangely, it won't pause in the way a Tween will. So...

Wednesday, 15 May 2013

EaselJS: Text width

In order to get the width of a text field you have created, you are supposed to use:

txt.getMeasuredWidth();

I was trying to add line breaks, EaselJS doesn't support html tags, so I used the \n line break, which works.

Problem? Now getting the measured width doesn't work (although height is fine). In fact, the more line breaks you add, the wider it thinks the text box is!

For myself, I am going to print out my longest line, and measure it's width, then replace it with the full text.