Basic AS 3.0 query - actionscript-3

What is the best way to navigate through an actionscript swf using arrows?

set the tabIndex property of the TextInput. That should allow you to tab through the form.
It is inadvisable to override the default functionality for arrow keys because they are used to move the text insertion point within the textInput
As for enter, you'll have to listen for the keyUp event and, if you detect an enter key, move to the next field.
//add this eventlistener for each textbox (through a loop or manually)
t.addEventListener(KeyboardEvent.KEY_UP, k);
//The event handler
protected function k(e:KeyboardEvent):void {
if(e.keyCode==Keyboard.ENTER) {
focusManager.getNextFocusManagerComponent().setFocus();
}
}
EDIT
For Flash CS5, this code should work:
import flash.events.KeyboardEvent;
import fl.managers.FocusManager;
import flash.display.InteractiveObject;
import fl.managers.IFocusManagerComponent;
import fl.managers.IFocusManager;
t1.addEventListener(KeyboardEvent.KEY_UP, k);
t1.tabIndex=1;
t2.tabIndex=2;
var fm:FocusManager=new FocusManager(this);
t1.tabEnabled=true;
t2.tabEnabled=true;
function k(e:KeyboardEvent):void {
if(e.keyCode==Keyboard.ENTER) {
var fx:InteractiveObject = fm.getNextFocusManagerComponent();
fm.setFocus(fx);
}
}
important: first drag a component from the "User Interface" group onto the stage and delete it. This should put all the required components in the library ready for you to use
EDIT2
Change
for(var i:int=0; i < textbox.length; i++) {
//textbox[i].buttonMode = true;
//box[i].addEventListener(MouseEvent.CLICK, myclick_ftn);
//box[i].addEventListener(FocusEvent.FOCUS_IN,textInputHandler);
//box[i].addEventListener(FocusEvent.FOCUS_OUT,textInputHandlerOut);
textbox[i].restrict = "0-9";
textbox[i].addEventListener(KeyboardEvent.KEY_UP, k);
textbox[i].tabIndex=i;
//t2.tabIndex=2;
//textbox[i].tabEnabled=true;
var fm:FocusManager=new FocusManager(this);
function k(e:KeyboardEvent):void {
if(e.keyCode==Keyboard.ENTER) {
var fx:InteractiveObject = fm.getNextFocusManagerComponent();
fm.setFocus(fx);
}
}
//t2.tabEnabled=true;
}
in your code to this:
var fm:FocusManager=new FocusManager(this);
function k(e:KeyboardEvent):void {
if(e.keyCode==Keyboard.ENTER) {
var fx:InteractiveObject = fm.getNextFocusManagerComponent();
fm.setFocus(fx);
}
}
for(var i:int=0; i < textbox.length; i++) {
//textbox[i].buttonMode = true;
//box[i].addEventListener(MouseEvent.CLICK, myclick_ftn);
//box[i].addEventListener(FocusEvent.FOCUS_IN,textInputHandler);
//box[i].addEventListener(FocusEvent.FOCUS_OUT,textInputHandlerOut);
textbox[i].restrict = "0-9";
textbox[i].addEventListener(KeyboardEvent.KEY_UP, k);
textbox[i].tabIndex=i;
//t2.tabIndex=2;
//textbox[i].tabEnabled=true;
}

Related

Flash AS3 AddEventListener with Parameter using loop

I have 34 buttons in my scene, if I click any of them a MovieClip will be visible and jump (gotoAndStop) to a frame based on which button I pressed.
import flash.events.Event;
import flash.events.MouseEvent;
stop();
MC.visible = false;
var btns:Array = new Array(
prov1, prov2, prov3, prov4, prov5, prov6, prov7, prov8, prov9, prov10,
prov11, prov12, prov13, prov14, prov15, prov16, prov17, prov18, prov19, prov20,
prov21, prov22, prov23, prov24, prov25, prov26, prov27, prov28, prov29, prov30,
prov31, prov32, prov33, prov34
);
for(var i:int = 0; i < 34; i++)
{
btns[i].addEventListener(MouseEvent.CLICK, function(e:Event):void{OpenDetail(i+1)});
trace(i);
}
function OpenDetail(frame:int)
{
MC.visible = true;
MC.gotoAndPlay(1);
MC.MSC.gotoAndStop(frame);
}
In the code above it should be that if I click prov1 it will open MC.MSC and goto frame 1, if I click prov2 it will open MC.MSC goto frame 2, etc.
But what really happened is when I click any of my buttons above, MC.MSC is opened but goes to frame 34.
Where did I do wrong? Any help would be very appreciated. Thanks.
Your mistake is not understanding what closure (an unnamed unbound function) is and how it works. The thing is, your i iterator goes to 34 and all the closures you create read i value from variable reference rather than use i value of the moment they were created.
Instead, you should do the following:
for (var i:int = 0; i < 34; i++)
{
btns[i].addEventListener(MouseEvent.CLICK, onClick);
}
function onClick(e:MouseEvent):void
{
// Get reference to the clicked button.
var aBut:DisplayObject = e.currentTarget as DisplayObject;
// Option 1: figure its index within the list.
var anIndex:int = btns.indexOf(aBut) + 1;
// Option 2: figure its index from the button's name.
var anIndex:int = int(aBut.name.substr(4));
// Go to the relevant frame.
OpenDetail(anIndex);
}

How to get symbols to revert back to starting position in AS3 flash

Hi im trying to create a very simple drag and drop game in flash and I the scene to just loop round itself so say, if ( user does this) then go back to the beginning of the scene. but when I try this the symbols that the user has moved stay to where they have moved them too rather than returning to the position they were in at the start of the scene.
Can anyone explain a way to get the symbols to return to where they were at the begining of the scene once the if statement has completed?
The following example will traverse the display list, storing symbols along with their initial positions in a Dictionary. When it's time to reset, just call the resetToOriginalPositions method, passing it the Dictionary that was created.
import flash.utils.Dictionary;
import flash.display.DisplayObject;
import flash.geom.Point;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.display.MovieClip;
var originalPositions:Dictionary;
if(!originalPositions)
{
originalPositions = collectPositions(this);
}
function collectPositions(container:DisplayObjectContainer):Dictionary
{
var positions:Dictionary = new Dictionary(true);
for(var i:int = 0; i < container.numChildren; i++)
{
var currentSymbol:DisplayObject = container.getChildAt(i);
positions[currentSymbol] = new Point(currentSymbol.x, currentSymbol.y);
// this will allow the symbols to be dragged/dropped
currentSymbol.addEventListener(MouseEvent.MOUSE_DOWN, clickHandler);
currentSymbol.addEventListener(MouseEvent.MOUSE_UP, clickHandler);
}
return positions;
}
function clickHandler(e:MouseEvent):void
{
var target:MovieClip = e.target as MovieClip;
if(e.type == MouseEvent.MOUSE_DOWN)
{
target.startDrag();
}
else
{
target.stopDrag();
}
}
function resetToOriginalPositions(positions:Dictionary):void
{
for(var currentSymbol:Object in positions)
{
var position:Point = positions[currentSymbol];
DisplayObject(currentSymbol).x = position.x;
DisplayObject(currentSymbol).y = position.y;
}
}
// this line should be called in your if statement that you already have set up
resetToOriginalPositions(originalPositions);
Marcela's answer may work for you, but just in case you would like something a little simpler...you can store the original positions on a dynamic property of each object. When the condition you require is met to go back to the original positions you can call a function that resets the current x and y positions to the original ones.
//place in frame 1
dragObject1.originalY = dragObject1.y;
dragObject1.originalX = dragObject1.x;
dragObject2.originalY = dragObject2.y;
dragObject2.originalX = dragObject2.x;
//...rest of object posisitions
function resetObjectPositions()
{
dragObject1.y = dragObject1.originalY;
dragObject1.x = dragObject1.originalX;
dragObject2.y = dragObject2.originalY;
dragObject2.x = dragObject2.originalX;
//...rest of object positions
}
//later in scene
if(condition)
{
resetObjectPositions();//make sure to run this code before going back to frame one in the scene to use the original values;
}

Flash remove child from timer

I have 25 objects of movie clip class named drone, and when i click it, after 2 seconds I want the object to disappear. I also have 25 timers named countdown. Here is what i do:
function clickHandler (event:MouseEvent):void{
event.currentTarget.hp--;
if(event.currentTarget.hp <= 0)
{
for(var i:int = 0;i<25;i++)
{
if(event.currentTarget == _drone[i])
{
countdown[i].start(); //start timer
}
}
}
}
Here is my timer:
for(var i:int = 0;i<25;i++)
{
countdown[i] = new Timer(2000);
countdown[i].addEventListener(TimerEvent.TIMER,timerHandler);
}
function timerHandler(e:TimerEvent):void {
//remove the drone I clicked
//I also dont know which drone i'm clicking
}
What should I do in the timerHandler to remove the object I clicked?
You can use Dictionary. Use the timer as key and movielcip as value.
import flash.utils.Dictionary;
var dict:Dictionary = new Dictionary();
function clickHandler (event:MouseEvent):void{
event.currentTarget.hp--;
if(event.currentTarget.hp <= 0)
{
for(var i:int = 0;i<25;i++)
{
if(event.currentTarget == _drone[i])
{
dict[countdown[i]] = _drone[i];//set the target mc here
countdown[i].start(); //start timer
break;
}
}
}
}
function timerHandler(e:TimerEvent):void {
var mc:MovieClip = dict[e.target] as MovieClip;//get the object been clicked
if (mc && mc.parent) {
mc.parent.removeChild(mc);//remove it
}
}
With minimal changes, set up an array to track the drones:
var arrayToRemove:Array = new Array();
and then in the click handler store drones to be removed in there:
arrayToRemove.push(event.currentTarget);
and in the timerHandler just remove the first element of the array:
removeChild(arrayToRemove.shift());
Since every delay is the same the order of the events and removals will be preserved. Although, it would probably be better to generalize the code using the above example and store all drones and timers in an arrays, so you can have any number of them.

AS3: drag by mouse or move by key

I've got 6 objects with drag'n'drop and hitTest function. It's obvious that when i drag one object to their hitTest area it's correct.
But my question is that i want to control these 6 object by mouse and keyboard keys. if i dont want to drag them, then i can move them by key arrows.
Second question is that when these two methods will be done if i want to move an object by key then i grab first free object which is not "hitTested"
Can I do these things in AS3? Pretty weird solutions in these project but i need to know if is possible.
Here's my code for drag and drop functions
package {
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.display.MovieClip;
public class Main extends MovieClip
{
var xPos:int;
var yPos:int;
var errors:int;
var wins:int;
public function Main():void
{
addListeners(objectone,objecttwo,objectthree,objectfour,objectfive);
errors = 1;
wins = 1;
}
private function getPosition(target:Object):void
{
xPos = target.x;
yPos = target.y;
}
private function dragObject(e:MouseEvent):void
{
info.text = "";
getPosition(e.target);
e.target.startDrag(true);
}
private function stopDragObject(e:MouseEvent):void
{
if (e.target.hitTestObject(getChildByName(e.target.name + "Target")))
{
e.target.x = getChildByName(e.target.name + "Target").x;
e.target.y = getChildByName(e.target.name + "Target").y;
info.text = "Bingo!";
wins++;
}
else
{
e.target.x = xPos;
e.target.y = yPos;
bledy.text = "Wrong: " + errors++;
}
if(errors == 4) {
errors = 1;
gotoAndPlay(2);
}
if(wins == 9) {
wins = 1;
gotoAndStop(3);
}
e.target.stopDrag();
}
private function addListeners(... objects):void
{
for (var i:int = 0; i < objects.length; i++)
{
objects[i].addEventListener(MouseEvent.MOUSE_DOWN, dragObject);
objects[i].addEventListener(MouseEvent.MOUSE_UP, stopDragObject);
}
}
}
}
Please give me some code tips!
Cheers!
For sure it is possible... and for sure there are several options to achieve that.
For the keyboard interaction I suggest you check FocusManager class so you can learn how to cycle trough selected objects using tab, and get the focused object.
Then listen for stage keyboard events to move with arrows the object.
Regarding dragging to move check the DragManager class related samples if using Flex, or look up google for tutorials in flash.

AS3, for loop create button inside movieclip and how to call it?

Here is my full code
import fl.controls.*;
var test:MovieClip = new MovieClip();
var btn:Button;
for(var i:int = 1; i<=7; i++){
btn = new Button();
btn.name = "btn" + i;
btn.x = i * 100;
test.addChild(btn);
btn.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent) { nothing(i); });
}
addChild(test);
function nothing(bla:int):void {
trace("You clicked " + bla);
}
Result:
You clicked 8
You clicked 8
You clicked 8...
Is there anyway, such that, I can use for loop to create different name button, and add it to an event listener?
Your problem is the function(evt:MouseEvent){} closure (JavaScript info applies to ActionScript too, as they're both ECMAScript). Here's what you can do:
function makeClickListener(i:int) {
return function(evt:MouseEvent) {
nothing(i);
};
}
...
for(...) {
...
btn.addEventListener(MouseEvent.CLICK, makeClickListener(i));
}
in your example your i is not doing what you think it's doing. You've declared it as a global variable and passing into the function as you're doing is meaningless. In the end your buttons are simply reporting the current value of i (which after the loop is always 8).
I like the other solution offered, but here's a more object oriented solution, which may be of some use depending on what you're doing with your button (or other objects in the future).
public class MyButton extends Button{
public var myIndex:Number;
}
Now you use MyButton instead of Button and in your loop throw in
btn.myIndex = i;
then attach generic event handler
btn.addEventListener(MouseEvent.CLICK, myHandler);
which would look like this:
function myHandler(evt:MouseEvent){
trace(evt.target.myIndex);
}
See... the target of the event will always be the object to which you attached the event. It is to that object that you should attach whatever values you wish it to retain. Personally I prefer this approach because then the information is with the object (and can be used by other elements that might need it) rather than in the handler and only in the handler.
var test:MovieClip = new MovieClip();
var btn:Button;
for(var i:int = 1; i<=7; i++){
btn = new Button();
btn.name = i.toString();
btn.x = i * 100;
test.addChild(btn);
btn.addEventListener(MouseEvent.CLICK, nothing);
}
function nothing(event:MouseEvent):void {
//trace("You clicked " + int( event.currentTarget.name ) );
trace("You clicked " + event.currentTarget.name );
}