I develop my own way of doing this simple task. However, I'm now wondering if there is a better way to do it.
The buttons:
var menuBtnEscrit:MovieClip = new MovieClip();
var mbe:btnEscritorio = new btnEscritorio();
menuBtnEscrit.addChild(mbe);
menuBtnEscrit.val = "escrit";
menuBtnEscrit.x = 80;
menuBtnEscrit.addEventListener(MouseEvent.CLICK, novoCont);
dMenu.addChild(menuBtnEscrit);
var menuBtnPublic:MovieClip = new MovieClip();
var mbp:btnPublic = new btnPublic();
menuBtnPublic.addChild(mbp);
menuBtnPublic.val = "public";
menuBtnPublic.x = 244;
menuBtnPublic.addEventListener(MouseEvent.CLICK, novoCont);
dMenu.addChild(menuBtnPublic);
And I can keep going, or create buttons trough some algorithm, and put more properties and take advantage of a MovieClip.
The handler:
private function novoCont(e=null){
if(e!=null) selecCont = new String(e.target.parent.val);
clearDisplay(dSubMenu);
clearDisplay(dConteudo);
var func:String = "cont_"+selecCont;
this[func]();
}
As you can see, there is some common task for all buttons.
If I click the first button, it will call cont_escrit() function. This mechanics works, but it is the best practice? Is there a way of optimize it?
public class BaseButton extends Button {
private var _func:Function;
public function get handler():Function {
return _func;
}
public function set handler(value:Function):void {
_func = value;
}
}
So hero you can create mbe like this
mbe = new BaseButton ();
mbe.hanler = cont_escrit;
The event hanler would be
private function novoCont(e=null){
if(e!=null) {
var selecContent:BaseButton = e.targe as BaseButton ;
var handler:Function = selecContent.handler;
handler();
}
}
Here is an example.
var menuBtnEscrit:MovieClip = new MovieClip();
var mbe:btnEscritorio = new btnEscritorio();
menuBtnEscrit.addChild(mbe);
//menuBtnEscrit.val = "escrit";
menuBtnEscrit.func = this.cont_escrit;
menuBtnEscrit.x = 80;
menuBtnEscrit.addEventListener(MouseEvent.CLICK, novoCont);
private function novoCont(e=null){
if(e!=null) {
var mc:MovieClip = e.target as MovieClip;
var func:Function = mc.func;
func();
}
clearDisplay(dSubMenu);
clearDisplay(dConteudo);
}
Related
I'm having an issue trying to get my code work for my Adobe Flash project. Basically I'm trying to get a button to play a random sound everytime it's clicked which works but I can't have that same code on the same frame for a different button which is why it gives me this error.
Here is my code:
import flash.utils.Dictionary;
import flash.events.MouseEvent;
var request:URLRequest = new URLRequest("19103_b.mp3");
var ci_diese:Sound = new Sound();
ci_diese.load(request);
var request_two:URLRequest = new URLRequest("19203_b.mp3");
var d_diese:Sound = new Sound();
d_diese.load(request_two);
var request_three:URLRequest = new URLRequest("19204_b.mp3");
var f_diese:Sound = new Sound();
f_diese.load(request_three);
var play_liste = 0;
var dictSounds = new Dictionary ();
dictSounds[1] = d_diese;
dictSounds[2] = ci_diese;
dictSounds[3] = f_diese;
fireweapon_H3AR.addEventListener (MouseEvent.MOUSE_DOWN, mouseDownHandler);
function mouseDownHandler (event:MouseEvent) : void {
play_liste = Math.ceil(Math.random () *3);
dictSounds[play_liste].play ();
ready_H3AR.addEventListener (MouseEvent.MOUSE_DOWN, mouseDownHandler);
function mouseDownHandler (event:MouseEvent) : void {
play_liste = Math.ceil(Math.random () *3);
dictSounds[play_liste].play ();}
}
import flash.utils.Dictionary;
import flash.events.MouseEvent;
var request:URLRequest = new URLRequest("Readya.mp3");
var ci_diese2:Sound = new Sound();
ci_diese2.load(request);
var request_two:URLRequest = new URLRequest("Readyb.mp3");
var d_diese2:Sound = new Sound();
d_diese2.load(request_two);
var request_three:URLRequest = new URLRequest("Readyc.mp3");
var f_diese2:Sound = new Sound();
f_diese2.load(request_three);
var play_liste = 0;
var dictSounds = new Dictionary ();
dictSounds[1] = d_diese2;
dictSounds[2] = ci_diese2;
dictSounds[3] = f_diese2;
ready_H3AR.addEventListener (MouseEvent.MOUSE_DOWN, mouseDownHandler);
function mouseDownHandler (event:MouseEvent) : void {
play_liste = Math.ceil(Math.random () *3);
dictSounds[play_liste].play ();}
}
Any way to rewrite this to accommodate more than one button? The first half works up until it repeats itself at "import flash." I've been searching everywhere for answers so please help!!
You should not name two functions or two variables the same, because the last ones are going to overwrite the first ones.
For example
var request:URLRequest = new URLRequest("19103_b.mp3");
is then overwritten
var request:URLRequest = new URLRequest("Readya.mp3");
The same happens with the button ready_H3AR an the function listener mouseDownHandler
By the way, you don't need to import the classes twice:
import flash.utils.Dictionary;
import flash.events.MouseEvent;
Usually when a task or a block of code is intended to be used many times, it's better to put it in a function to get a simpler and more maintainable code.
So you can do like this :
var sounds:Array = [
['01.mp3', '02.mp3', '03.mp3'], // sounds for the 1st button
['04.mp3', '05.mp3', '06.mp3'] // sounds for the 2nd button
];
var sound:Sound,
sound_channel:SoundChannel = new SoundChannel();
function play_sound(sound_name:String): void
{
var request:URLRequest = new URLRequest('mp3/' + sound_name);
sound = new Sound();
sound.addEventListener(Event.COMPLETE, on_sound_loaded);
sound.load(request);
}
function on_sound_loaded(e:Event): void
{
// if you want, you can stop the current playing sound
// otherwise you don't need the SoundChannel
sound_channel.stop();
sound_channel = Sound(e.target).play();
}
button_01.addEventListener(MouseEvent.MOUSE_DOWN, on_press);
button_02.addEventListener(MouseEvent.MOUSE_DOWN, on_press);
function on_press(e:MouseEvent): void
{
// to get values : 0, 1 or 2
var random:int = int(Math.random () * sounds[0].length);
// if it's the 1st button so pick the sound from the 1st sounds array
if(e.currentTarget.name == 'button_01'){
play_sound(sounds[0][random]);
} else {
play_sound(sounds[1][random]);
}
}
Hope that can help.
I'm trying to have this hero shoot the bullet. Ex: The bullet has fire and ice type. if the hero placed is fire type then it will shoot fire bullet, if it's ice type then it will shoot ice bullet. And each bullet have each own effects and damages.
So, I've tried to get the index of hero chosen and later on the index will be used to define which bullet used by tracing (heroesArray.indexOf(heroClicked)); but the value of heroclicked is (object Hero1). so I can't use it since the array of heroesArray is [hero1,hero2]. I did splitting and joining too but it kinda messed up...
My question is how to get the String value that only contains the variable of clicked object (hero1 or hero2)? Is there any 'vocabulary' to get the variable name like getqualifiedclassname used for getting class name of an object?
Or is there any other idea to create bullet type the same as hero type without using indexOf ?
Thanks !
Here is the code :
package {
import flash.display.MovieClip
import flash.events.MouseEvent
import flash.events.Event
import flash.display.Sprite
import flash.utils.*
public class Hero {
private var heroesArray:Array;
private var heroContainer:Sprite = new Sprite;
private var hero1:MovieClip = new Hero1();
private var hero2:MovieClip = new Hero2();
private var bulletArray:Array;
private var bullet1:MovieClip = new Bullet1();
private var bullet2:MovieClip = new Bullet2();
private var moveHero:Boolean = false;
private var movingHero:MovieClip;
private var _money:Money = new Money();
private var _main:Main;
private var _enemy:Enemy = new Enemy(_main);
public function Hero(main:Main)
{ _main = main;
heroesArray = [hero1,hero2];
bulletArray = [bullet1,bullet2];
}
private function playerMoving(e:Event):void
{
if (moveHero == true)
{
movingHero.x = _main.mouseX;
movingHero.y = _main.mouseY;
}
}
private function chooseHero(e:MouseEvent):void
{
var heroClicked:MovieClip = e.currentTarget as MovieClip;
var cost:int = _main._money.money ;
if(cost >= 10 && moveHero == false)
{
_main._money.money -= 10;
_main._money.addText(_main);
moveHero = true;
var heroClass:Class = getDefinitionByName(getQualifiedClassName(heroClicked)) as Class;
movingHero = new heroClass();
heroContainer.addChild(movingHero);
movingHero.addEventListener(MouseEvent.CLICK, placeHero);
}
}
private function placeHero(e:MouseEvent):void
{
var heroClicked:MovieClip = e.currentTarget as MovieClip;
var heroRow:int = Math.floor(_main.mouseY/75);
var heroCol:int = Math.floor((_main.mouseX-10)/65);
if(heroRow>0 && heroCol>0 && heroRow<6 && heroCol<10&&
_main.field[heroRow][heroCol]==0)
{
movingHero.fireRate =75;
movingHero.recharge = 0;
movingHero.firing = false;
movingHero.heroRow = heroRow;
movingHero.x = 42+heroCol*65;
movingHero.y = 10+heroRow*75;
_main.field[heroRow][heroCol]=1;
moveHero = false;
movingHero.removeEventListener(MouseEvent.CLICK, placeHero);
}
}
public function displayHero(stage:Object):void
{
stage.addChild(heroContainer);
for (var i:int = 0; i<2;i++)
{
stage.addChild(heroesArray[i]);
heroesArray[i].x = 37;
heroesArray[i].y = 80+i*70;
heroesArray[i].width=60;
heroesArray[i].height=55;
heroesArray[i].buttonMode = true;
heroesArray[i].addEventListener(MouseEvent.CLICK, chooseHero);
heroesArray[i].addEventListener(Event.ENTER_FRAME, playerMoving);
}
}
}
}
You've pretty much got the answer right in front of you. The two heros are of classes Hero1 and Hero2, and you find the class via
var heroClass:Class = getDefinitionByName(getQualifiedClassName(heroClicked)) as Class;
All you need to do is compare heroClass to those two classes like so:
if(heroClass == Hero1)
{
...
}
else
{
...
}
Linking hero to bullet type
If you don't know, or don't want to learn classes (see my comment for an excellent tutorial) then you'll need a lookup table/Dictionary so that you can link bullet type to hero.
//Put this in your constructor after the bullet types and heroes have been declared
var bulletDict = new Dictionary();
bulletDict[hero1] = bulletTypeIce; //Note the lack of quotations around hero1 and 2
bulletDict[hero2] = bulletTypeFire;
So, to get the bullet type out:
var bulletType = bulletDict[heroClicked];
i have a TheList.as class..in which i have created a list for an android app.
Here is TheList.as(Cut down to the specific stuff for this question)
public var _ListItem:ListItem;
public var _Data:Array;
public var _Values:Array;
public var $CurrentValue:String;
public var _TextLabel:TextField;
public function TheList(Data:Array,Values:Array)
{
_Data = Data;
_Values = Values;
initialize();
}
private function initialize():void
{
_TextLabel = new TextField();
addChild(_TextLabel);
_TextLabel.text = "Data";
_Container = new ListContainer ;
addChild(_Container);
_Container.x = 0;
_Container.y = 0;
currentY = _Container.y;
lastY = _Container.y;
for (var i:int = 0; i < _Data.length; i++)
{
_ListItem = new ListItem ;
_Container.addChild(_ListItem);
_ListItem.y = _ListItem.height * i;
_ListItem.addEventListener(MouseEvent.MOUSE_DOWN,onItemDown,false,0,true);
_ListItem.addEventListener(MouseEvent.MOUSE_UP,onItemUp,false,0,true);
_ListItem.mouseChildren = false;
_ListItem.value = _Values[i];
_ListItem.name = _Data[i];
_ListItem.ItemLabel.text = _ListItem.name ;
}
}
Here is the class "TheList" is being used in (Again Cut Down to specific stuff)
$myList = new TheList($Data,$Values);
addChild($myList);
$myList.x = -240;
$myList.y = -203;
$myList.visible = false;
$ListFrom = new TheList($DataFromTo, $ValuesFromTo);
addChild($ListFrom);
$ListFrom.x = -240;
$ListFrom.y = -203;
$ListFrom.visible = false;
$ListFrom._TextLabel.text = $DataFromTo[0];
$ListTo = new TheList($DataFromTo, $ValuesFromTo);
addChild($ListTo);
$ListTo.x = -240;
$ListTo.y = -203;
$ListTo.visible = false;
$ListTo._TextLabel.text = $DataFromTo[0];
Now what i am trying to achieve is that i want to change "$Data" and "$Values" Arrays..as you can see i have a main list and two sublists... when "Time" is selected in the main list, i want the sub-lists to be populated with "Time" related unit names...i tried
if($myList._TextLabel.text == "Time")
{
$ListFrom._Data = ["this", "this", "this" etc]
}
But its not working. I am not getting any error either. I'd really appreciate any help!
What you try to achieve is not pissible in this way. You initialize you lists with data fields. When you reset the data, you need to invalidate your list again. You can achieve this with an item setter
private var __Data:Array;
public function get _Data():Array
{
return __Data;
}
public function set _Data(value:Array):void
{
this.__Data = value;
initialize();
}
make sure that you first cleanup you list before you rebuild it again.
your code:
$ListFrom._Data = ["this", "this", "this" etc]
will automaticly call the setter. A getter and setter method looks like a function but is invoked like a property. means:
object.property = "something" //will call the setter
var something:String = object.property //will call the getter
I can't add name and image from Facebook contacts to SqLite, becouse adding is inside in loop and loader start when Event is Complete. Fllowing code adds data to the database, but in the name of the object is the last person out of the loop. Any thoughts? Thanks!
private var person:PersonVO;
protected function handleFriendsLoad(response:Object, fail:Object):void
{
if (fail) { return }
var friends:Array = response as Array;
var l:uint=friends.length;
for (var i:uint=0;i<l;i++) {
var friend:Object = friends[i];
FacebookDesktop.api('/'+friend.id, loadData);
}
}
private function loadData(object:Object, fail:Object):void
{
if (fail) { return; }
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageToByteArray);
loader.load(new URLRequest(FacebookDesktop.getImageUrl(object.id, 'large')));
person = new PersonVO()
person.name = object.first_name;
}
private function imageToByteArray(event:Event):void
{
var wczytaj:Loader = (event.target as LoaderInfo).loader;
var image:Bitmap = Bitmap(wczytaj.content);
var encoderJpeg:JPEGEncoder = new JPEGEncoder();
var byteArray:ByteArray = encoderJpeg.encode(image.bitmapData);
person.image= byteArray;
insert(person);
}
private function insert(person:PersonVO):void
{
dbStatement.text = "INSERT INTO person (name,image) values(:name,:jpeg)";
dbStatement.parameters[":name"] = person.name;
dbStatement.parameters[":jpeg"] = person.image;
dbStatement.execute();
}
Extend Loader class functionality:
dynamic class DynamicLoader extends Loader{}
Then store whatever you want in instances of DynamicLoader:
private function loadData(object:Object, fail:Object):void
{
if (fail) { return; }
var person:PersonVO = new PersonVO();
person.name = object.first_name;
var loader:DynamicLoader = new DynamicLoader();
loader.person = person;
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageToByteArray);
loader.load(new URLRequest(FacebookDesktop.getImageUrl(object.id, 'large')));
}
private function imageToByteArray(event:Event):void
{
var wczytaj:DynamicLoader = (event.target as LoaderInfo).loader as DynamicLoader;
var image:Bitmap = Bitmap(wczytaj.content);
var encoderJpeg:JPEGEncoder = new JPEGEncoder();
var byteArray:ByteArray = encoderJpeg.encode(image.bitmapData);
var person:PersonVO = wczytaj.person;
person.image= byteArray;
insert(person);
}
I have not used private var person:PersonVO;. So if you are not using it in the other methods of your class, you could remove it completely.
I am new and having an issue with the use of classes in as3.
I have created an array of objects in my main timeline
function badPlayer()
{
var bads:Array = new Array();
for (var i=0; i<5; i++)
{
var mc = new bman();
mc.name=["mc"+i];
bads.push(mc);
_backGround.addChild(mc);
mc.x = 100;
mc.y = 100;
trace (bads);
Baddies(_backGround.mc); //here I am trying to export mc to my class
}
}
Here is a snip-it from my class. My trace statement wont even output.
public class Baddies extends MovieClip
{
private var pistolSound:pistolShot = new pistolShot();
//private var mc = new mc();
private var _rotateSpeedMax:Number = 2;
private var _gravity:Number = .68;
private var _bulletSpeed:Number = 2;
private var _maxDistance:Number = 200;
private var _reloadSpeed:Number = 500; //milliseconds
private var _barrelLength:Number = 20;
private var _bulletSpread:Number = 5;
private var _isLoaded:Boolean = true;
private var _isFiring:Boolean = true;
private var _endX:Number;
private var _endY:Number;
private var _startX:Number;
private var _startY:Number;
private var _reloadTimer:Timer;
private var _bullets:Array = [];
private var _gun:MovieClip;
private var _enemy:MovieClip;
private var _yx:Number;
private var _yy:Number;
private var _pcos:Number;
private var _psin:Number;
private var _trueRotation:Number;
public function Baddies()
{
trace("working");
stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
Basically I am trying to create several bad guys (bman) and have the same code apply to each of them. I have also tried to change the linkage name of bman to Baddies with no success.
There are a few thing that are very wrong with this code.
Baddies(_backGround.mc); //here I am trying to export mc to my class
This is a typecast, as already stated in the comments. By the way Baddies isn't a good name, because it plural. You probably want to create a new bad guy, which would be done with this line:
var baddie = new Baddies();
Now your constructor uses the stage variable. This won't work because the object isn't on the stage, therefore stage is null (it may works if you drag and drop an instance to the stage in the editor). So before using the stage you actually need to add the object to the stage:
public function Baddies() {
trace("new baddie created");
}
public function init(mc:MovieClip) {
mc.addChild(this); // display this baddie
trace("working");
stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
And in the badPlayer function:
var baddie = new Baddies();
baddie.init(_backGround);