AS3 How to make an object shrink when it is not tapped - actionscript-3

I have stumbled upon a problem that I do not seem to know how to solve. I have searched it up online but no answer has been found. It is that when you tap the Monster on the screen it grows, but when you don't tap it returns to its default size. I have managed to make it grow when tapped but I can not seem to make it so that when you release the tap it shrinks. An example of what I am talking about is on cookie clicker, that when you click the big cookie it grows but when you don't it goes to its original size. Here is my code so far:
var score:Number = 0;
var score_str:String;
var score_str_len:int;
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
Monster.addEventListener(TouchEvent.TOUCH_TAP, fl_TapHandler);
Monster.width = 363.5;
Monster.height = 344.9;
function fl_TapHandler(event:TouchEvent):void
{
Monster.width = 378.4;
Monster.height = 359;
score = score + 1;
score_str = score.toString();
score_str_len = score_str.length;
Taps_txt.text =
score_str_len > 3
? score_str.substr(0, score_str_len-3) + ',' + score_str.substr(score_str_len-3)
: score_str
;
}
Help will be greatly appreciated.

According to the actionscript reference, there are a lot of other touch events you can use, such as TouchEvent.TOUCH_OUT or TouchEvent.TOUCH_END.
I haven't used them so i can't tell you which one would be helpful to you but you can run some tests and see which of the event is fired when you remove your finger from the monster, just as you would do with mouse events.
So basically you would add another listener (best would be inside the fl_TapHandler function) for the release touchevent and put the monster variables back to their normal level.
If you want to have several monsters, the best way would be to create a class for it and call the functions that would be inside this class. Exemple:
Monster.addEventListener(TouchEvent.TOUCH_TAP, Monster.fl_TapHandler);
I hope this helps.

How about you store all monsters in an array?
var monsters:Vector.<Monster> = new Vector.<Monster>();
monsters.push(new Monster());
monsters.push(new Monster());
monsters.push(new Monster());
for(var monster : monsters) {
if(monster.isTapped){
monster.grow()
} else {
monster.shrink()
}
}

Related

AS3 tween object not working with .hitTestObject()

I am having a major problem in my new browser app.
Okay so I made game where different cubes (squares) spawn at the top of the screen and I use the Tween class to make them go down the screen and then disappear.
However I want to detect a collision when a cube hits the player (that is also a flying cube).
I tried everything, truly everything but it does not seem to work. The problematic thing is that when I remove the "Tween" function it does detect collision with the hitTestObject method but when I add the "Tween" line collision won't be detected anymore.
It looks like this:
function enemiesTimer (e:TimerEvent):void
{
newEnemy = new Enemy1();
layer2.addChild(newEnemy);
newEnemy.x = Math.random() * 700;
newEnemy.y = 10;
if (enemiesThere == 0)
{
enemiesThere = true;
player.addEventListener(Event.ENTER_FRAME, collisionDetection)
}
var Tween1:Tween = new Tween(newEnemy, "y", null, newEnemy.y, newEnemy.y+distance, movingTime, true);
}
And the collision detection part:
private function collisionDetection (e:Event):void
{
if (player.hitTestObject(newEnemy))
{
trace("aaa");
}
}
I am desperate for some information/help on the topic, it's been bugging me for days.
Thanks for your time, I would be very happy if someone could help me out^^
First, make sure the "newEnemy" instance and the "player" instance are within the same container. If they are not, their coordinate systems might not match up and could be the source of your problem.
Otherwise, you need to keep a reference to each enemy instance you create. It looks like you are only checking against a single "newEnemy" variable which is being overwritten every time you create a new enemy. This might be why you can successfully detect collision between the player and the most recent "enemy" instance.
So... you need a list of the enemies, you can use an Array for that.
private var enemyList:Array = [];
Every time you create an enemy, push it to the Array.
enemyList.push(newEnemy);
In your "collisionDetection" function, you need to loop through all of the enemies and check if the player is touching any of them.
for(var i:int = 0; i < enemyList.length; i++)
{
var enemy = enemies[i];
if (player.hitTestObject(enemy))
{
trace("Collision Detected!");
enemy.parent.removeChild(enemy); // remove the enemy from the stage
enemies.splice(i, 1); // remove the enemy from the list
}
}
I'd suggest that you move to TweenMax, it just might solve your problem, and in my experience it's much better in every possible way.
Scroll down the following page to see a few variations of this library, I myself use TweenNano, they're completely free of charge:
https://greensock.com/gsap-as
I think some plugins cost money, but I doubt you'll ever need them.

Unable to reference MovieClip inside Button AS3

I have this annoying issue that I hope someone might be able to help me with.
I have a mute button that I created and I have another movieclip inside of that button. All I want it to do is when I toggle the mute the movieclip inside will go to the according frame.
However, every time I try to call the movieclip inside of the button, this error comes up:
Access of possibly undefined property mcMuteToggle through a reference with static type flash.display:SimpleButton.
The instance name for the movieclip within is "mcMuteToggle".
Why not make movieClips that act like buttons?? Since I dont think actual button (simpleButton) types can deal with sub-MovieClips (especially if they too have code). Even if possible don't do it, I can predict a mess whereby Button does things it shouldn't do depending on what code you have in those MClips.
Try an alternate button method, just for a test... You didnt show any test code to work with so I will make assumptions..
1) Make a shape (rectangle?) and convert to MovieClip (or if all coded, then addchild shape to new MovieClip). Let's assume you called it mc_testBtn.
2) Make that MC clickable by coding mc_testBtn.buttonMode = true;
3) Add your mcMuteToggle inside the mc_testBtn
(or by code: mc_testBtn.addChild(mcMuteToggle);
Now you can try something like..
mc_testBtn.addEventListener (MouseEvent.CLICK, toggle_Mute );
function toggle_Mute (evt:MouseEvent) : void
{
if ( whatever condition )
{
mc_testBtn.mcMuteToggle.gotoAndStop(2); //go frame 2
}
else
{
mc_testBtn.mcMuteToggle.gotoAndStop(1); //go frame 1
}
}
This is likely due to strict mode. You can either disable it in the ActionScript settings dialog, access it with a different syntax myButton['mcMuteToggle'], or make a class for the symbol that includes a property mcMuteToggle.
You can also check to make sure the symbol is actually on the stage and that clip is actually in the button:
if('myButton' in root) {
// ...
}
if('mcMuteToggle' in myButton) {
// ...
}
i think u just overwrite that codes. You u can use something like this:
var soundOpen:Boolean = true;
var mySound:Sound = new Sound(new URLRequest("Whatever your sound is"));
var mySc:SoundChannel = new SoundChannel();
var mySt:SoundTransform = new SoundTransform();
mySc = mySound.play();
mcMuteToggle.addEventListener(MouseEvent.CLICK, muteOpenSound);
function muteOpenSound(e:MouseEvent):void
{
if(soundOpen == true)
{
mcMuteToggle.gotoAndStop(2);
/*on frame 2 u need to hold ur soundClose buton so ppl can see :)*/
soundOpen = false;
mySt.volume = 0;
mySc.soundTransfrom = st;
}
else
{
mcMuteToggle.gotoAndStop(1);
soundOpen = true;
mySt.volume = 1;
mySc.soundTransfrom = st;
}
}
This is working for me everytime. Hope u can use it well ;)

Can i create a function to tell a button to open a movie clip of the same name

I am new to the actionscript side of flash,
I am working on a map that has say 20 popups(movieclips) and the countries are the buttons, i have just been informed i need to add 60 more.
Below is an example of the code i have been using
english_movie.visible=french_movie.visible=turkish_movie.visible=false
english_btn.addEventListener(MouseEvent.CLICK, englishButtonClick);
french_btn.addEventListener(MouseEvent.CLICK, frenchButtonClick);
turkish_btn.addEventListener(MouseEvent.CLICK, turkishButtonClick)
function englishButtonClick(event:MouseEvent):void {
english_movie.visible=true;
english_movie.play();
french_movie.visible=turkish_movie.visible=false
}
function frenchButtonClick(event:MouseEvent):void {
french_movie.visible=true;
french_movie.play();
english_movie.visible=turkish_movie.visible=false
}
function turkishButtonClick(event:MouseEvent):void {
turkish_movie.visible=true;
turkish_movie.play();
english_movie.visible=french_movie.visible=false
}
Im thinking there must be an easier way to do this than replicating the code over and over.
Any help would be much appreciated.
Here's how to simplify the whole thing with code: Each btn object is
related to one movie object. This can be achieved with a Dictionary.
var btnToMovieAssociation:Dictionary = new Dictionary();
btnToMovieAssociation[english_btn] = english_movie; // repeat this line for every btn/movie pair
Now you have to generalise your click handler. The key difference
between each function (apart from making one certain movie visible)
is that they all make certain other movies invisible. But actually,
it's sufficient to only make the previously visible movie invisble.
To do this, create a variable that keeps track of the current visible
movie.
var currentMovie:MovieClip = english_movie;
Initialising the variable with english_movie has no effect on the
program. you can pick any other of the movies. It will make things
easier in the following code if this variable is initialised.
Now your function does effectively this:
make movie of clicked button visible
play this movie
make last movie invisible
Here's the cool part. You only add one listener. Look up if something
is in the dictionary for the clicked thing and consider that the
movie you want to show next.
addEventListener(MouseEvent.CLICK, buttonClick);
function buttonClick(event:MouseEvent):void
{
var movie:MovieClip = btnToMovieAssociation[event.target]
if (movie == null)
return; // nothing in the dictionary, it wasn't a button that was clicked.
movie.visible=true;
movie.play();
currentMovie.visible = false;
currentMovie = movie;
}
There are problems with this solution:
You still have to declare every pair, which is still tedious and prone to erro. (you have to type every name twice)
If your buttons are made up of several objects, event.target might point to them instead of the button as a whole. But with only
the btns in the dictionary and not all their individual parts,
nothing would be found in the dictionary. This can be circumvented by
setting mouseChildren = false; on every btn.
i posted this question else where and got this response
var tl:MovieClip=this;
var mc:MovieClip;
var i:int;
var buttonA:Array=[english_btn,french_btn,turkish_btn];
for(i=0;i<buttonA.length;i++){
buttonA[i].addEventListener(MouseEvent.CLICK,buttonF);
tl[buttonA[i].name.split("_")[0]+"_movie"].visible = false;
}
function buttonF(e:MouseEvent):void{
for(i=0;i<buttonA.length;i++){
tl[buttonA[i].name.split("_")[0]+"_movie"].visible = false;
}
tl[e.currentTarget.name.split("_")[0]+"_movie"].visible=true;
}
Which works great.

nonClickable buttons after loading same FLA 2nd time

Basically Im trying to make a FLA where if i click a button and close the FLA, next time I load the same FLA, the buttons that have been clicked before , now have an alpha of 0.5 and are nonClickable.
Currently i have only the logic for creating the buttons and saving the data:
private var savedData:SharedObject = SharedObject.getLocal("sharedStorage10");
private var buttonInfoArr:Array = [];
public function Main()
{
for (var i:int = 0; i < 4; i++)
{
var myImage_mc:MovieClip = new MovieClip();
myImage_mc.graphics.beginFill( 0xFFFFFF * Math.random() );
myImage_mc.graphics.drawRect(0,0,100,100);
myImage_mc.graphics.endFill();
myImage_mc.x = 50 + i * (myImage_mc.width + 10);
myImage_mc.y = 100;
myImage_mc.name = "myImage_mc" + i
this.addChild(myImage_mc);
myImage_mc.mouseEnabled = true;
myImage_mc.buttonMode = true;
myImage_mc.addEventListener(MouseEvent.CLICK, onClick);
}
}
private function onClick(ev:MouseEvent):void
{
var thisButton:MovieClip = ev.currentTarget as MovieClip
trace(thisButton.name)
thisButton.alpha = 0.5
thisButton.buttonMode = false;
thisButton.removeEventListener(MouseEvent.CLICK, onClick);
buttonInfoArr.push( thisButton.name );
savedData.data.myArray = buttonInfoArr;
}
But i dont know how to load/use the data and make the buttons (that have been clicked before) start with an alpha of 0.5 and without an EventListener(MouseEvent.CLICK, onClick)
PS:Could it be done without the use of Dictionary, cause i haven`t grasp my mind over it yet.
_EDIT__
to represent my problem in a more detailed way:
So im creating a game in which I collect objects that represent money.After I die in the game i get into the Shop Class in which i can buy different items depending on the money i have.
So lets say that after dying i have enough money to get item1 and item2. So i Click on button1 (representing item1) and button2 (representing item2) (when clicked their alpha gets to 0.5) and start the game again.Ok so now i have 1 life more and i get more money.But suddenly out of nowhere i feel something strange deep in me, something that i have never felt before -> HUNGER,
I shut down the PC (cause I love Earth )and run as fast as possible to the nearest shop.
lets say item1 is : +1life and item2 is : get more money from objects
After I had satisfied my primal needs I feel the strong urge to play that awesome game of mine again. But when i start the game I start to see some strange things: It seems that I havent got one life more and neither do i get more money and just to be sure that Im not hallucinating (or that i didnt rememer the lifes i had last time) I die on purpose so the Shop menu shows. So now what I see is making me sad -> button1 and button2 are active and have an alpha of 1( and that means that the game thinks that they were never bought/clicked, that i have never played this game before in my life)
So i go crazy (cause all that play before was for nothing and i have to start all over again).
After i calm down, I decide to change my life. 1st BIG change is adding some code into the game. To be more specific: a method that will save the items that i bougth, so when i close the game and start again the things i see will bring joy to my life - >: I still have the items that i bougth last time.
So long story short:
how do i make that when i click a button (it changes its alpha to 0.5)and close the FLA ,
whenever i open the same FLA, the button that i clicked before will be shown as clicked now(it alpha will be 0.5)
What is happening is normal. All variables are stored in RAM, which is temporary memory. Your button states are variables, too. Whenever any program closes, everything it has in RAM is deleted, thus the variables are cleared. This is true of all programs, in all programming languages. There are absolutely no exceptions.
Quite simply, you need to create a file that can store all this data long-term, on the hard drive (which is "permanent" memory).
If you're creating a game for the internet, you're going to need to store this data using SharedObjects (a.k.a. cookies).
If you're creating a game to be installed on the computer or mobile, you'll want to store data in a file. I recommend XML files, as they're the easiest to work with by far.
I am not going into either here, because those are lectures, not SO answers. See the above links to get started.
I didn't understand what exactly you're trying to do. But here is my simply approach would be that way.
// this is basically saved your latest clip we will control this if user click this button then we will be blocked
private var lastClickedButton:MovieClip;
private function onClick(ev:MouseEvent):void
{
var thisButton:MovieClip = ev.currentTarget as MovieClip
trace(thisButton.name)
thisButton.alpha = 0.5
thisButton.buttonMode = false;
thisButton.removeEventListener(MouseEvent.CLICK, onClick);
buttonInfoArr.push( thisButton.name );
savedData.data.myArray = buttonInfoArr;
// set the lastclicked button
lastClickedButton = thisButton;
// save this savedData sharedObject
savedData.data.lastClickedItem = lastClickedButton;
}
addEventListener(Event.ENTER_FRAME, loop)
{
if(savedData.data.lastClickedItem)
{
// do something here.
lastClickedButton.alpha = 0.5;
lastClickedButton.mouseEnabled=false;
// clear your sharedobject
savedData.flush();
}
}
I hope this will help you. good luck...

ActionScript 3 name property is not returning the right name...?

I experienced a problem with the name property in as3, I created this "dot" movieclip and I exported to a class,
then I anonymously created a bunch of dots using a loop. I assigned numbers as name to each dots
private function callDots(num:Number):void
{
for (var i = 0; i < subImagesTotal[num]; i++)
{
var d:Dot = new Dot();
d.x = i*23;
d.y = 0;
d.name = i;
dotContainer.addChild(d]);
}
}
so far so good, I checked that if I trace the name here, I will get the number I want.
However, it's not giving me the numbers if I trace it in other functions.
I added all of my dots to "dotContainer", and if I click on one of the dots, it will call this function
private function callFullSub(e:MouseEvent):void
{
var full_loader:Loader = new Loader();
var temp:XMLList = subImages[sub];
var full_url = temp[e.target.name].#IMG;
full_loader.load(new URLRequest(full_url));
full_loader.contentLoaderInfo.addEventListener(Event.INIT, fullLoaded);
}
e.target.name is suppose to be numbers like 1 or 2, but it's giving me "instance66" "instance70" and I
have no idea why. Because I did the same thing with loaders before and it totally worked.
Any ideas? Thanks.
christine
The e.target returns the inner most object clicked on, this could be a TextField, another MovieClip or posibly a shape (I'm not 100% of the last one) inside the "Dot".
To prevent this you could try to set the mouseChildren property to false on the Dot's when you add them. This should insure that nothing inside the dots can dispatch the click event, and thus the Dot's should do it.
Perhaps you could also in the event handler verify the target type with code like this:
private function callFullSub(e:MouseEvent):void
{
if(!e.target is Dot)
throw new Error("target in callFullSub is not Dot but: " + e.target.toString());
//The rest of you code here
}
The answer is [e.currentTarget.name] I perform this all the time!
Should return "Dot1" "Dot2", etc.
If the value you wish to return is a number or other data type other than a string (name of object) use [e.currentTarget.name.substr(3,1).toString()]
Should return 1, 2, etc.
Navee
I tried to reproduce your problem first with Flex using runtime created movieClips and then with Flash using Dot movieClip symbols exported for ActionScript. Neither application exhibited the problem.
You may already know names like "instance66" "instance70" are default enumerated instance names. So, whatever is dispatching the MouseEvent is NOT the dot instance. Perhaps you are unintentionally assigning callFullSub to the wrong targets, maybe your containers? Try assigning it to dot instance right after you create them, like this:
private function callDots(num:Number):void
{
for (var i = 0; i < subImagesTotal[num]; i++)
{
var d:Dot = new Dot();
d.x = i*23;
d.y = 0;
d.name = i;
d.addEventListener(MouseEvent.CLICK, callFullSub);
dotContainer.addChild(d]);
}
}
Be sure to temporarily comment out your original assignment.
Try this might work,..
d.name = i.toString();
You have not shown enough of your code for me to be able to give you a DEFINATE answer, I will however say this.
//After you create each loader you need to set its mouseEnabled
//property to false if you do not want it to be the target of
//Mouse Events, which may be superseding the actual intended target;
var full_loader:Loader = new Loader();
full_loader.mouseEnabled = false;
//Also you could name the loaders and see if what comes back when you click is the same.
ALSO! Add this to your Mouse Event handler for CLICK or MOUSE_DOWN:
trace(e.target is Loader); //If traces true you have an answer
I believe that the mouse events are being dispatched by the Loaders.
please provide more of your code, the code where the Loader.contentLoaderInfo's COMPLETE handler fires. I assume this is where you adding the loaders to the display list as I cannot see that now.