Get buttons to work inside animated interactive movie clip - actionscript-3

I have a filmstrip animation with 5 images (meant to be buttons to get urls) inside the filmstrip movie clip. I've only created a button of the first image so far. It works when it is not in the movie clip; however, once the movie clip is created that contains the button, it no longer works.
Additionally, the buttons have a rollover effect that works in or outside of the movie clip. If the button can detect the mouse over inside the movie clip, why can't it detect the mouse click?
Super grateful for any advice. I'm not well versed in AS, so you might want to dumb it down a bit.
ActionScript
var count = 1;
rtBtn.addEventListener(MouseEvent.CLICK, rightScroll);
lftBtn.addEventListener(MouseEvent.CLICK, leftScroll);
function panelOver() {
// this.onEnterFrame = scrollPanel;
// delete this.onRollOver;
}
function rightScroll(e:Event){
if (count < 5){
count++;
panel.x += 150;
}else{
count = 5;
}
//addEventListener(Event.ENTER_FRAME,rightAnimate);
//function rightAnimate(event:Event) {
//panel.x -= 140; //Math.round(140/7);
//}
}
function leftScroll(e:Event){
if (count > 1){
count --;
panel.x -= 150;
}else{
count=1;
}
//addEventListener(Event.ENTER_FRAME,leftAnimate);
//function leftAnimate(event:Event) {
//panel.x += 140;// - Math.round(.5);
//}
}
/* Click to Go to Web Page
Clicking on the specified symbol instance loads the URL in a new browser window.
Instructions:
1. Replace http://www.adobe.com with the desired URL address.
Keep the quotation marks ("").
*/
snowbtn.addEventListener(MouseEvent.CLICK, fl_ClickToGoToWebPage_3);
function fl_ClickToGoToWebPage_3(event:MouseEvent):void
{
navigateToURL(new URLRequest("http://www.adobe.com"), "_blank");
}

Related

Actionscript to make movie clip invisible before another is opened

I have a basic flash document that is showing football fixtures spread over several weeks. I have buttons for each week e.g. 'Gameweek 1', 'Gameweek 2' etc.
When the button is pressed, a movie clip is displayed below the buttons which shows the fixtures. The fixtures movie clip is always there but the button changes it to visible.
My problem is...if I have gameweek 1 fixtures showing and then i click on the 'Gameweek 2' button, both sets of fixtures are displayed because the gameweek 1 fixtures are still visible.
When I press a button to display new fixtures, I would like the previously visible movie clip to now be invisible so that just the new fixtures are visible.
Here is my actionscript:
stop();
btn_game1.addEventListener(MouseEvent.CLICK,openGame1);
function openGame1(evt:MouseEvent) {
if (game1.visible){
game1.visible = false;
}else {
game1.visible = true;
}
}
btn_game2.addEventListener(MouseEvent.CLICK,openGame2);
function openGame2(evt:MouseEvent) {
if (game2.visible){
game2.visible = false;
}else {
game2.visible = true;
}
}
I would like to propose a re-factored approach that cuts down on the amount of code and number of event handlers.
You only really need one button handler for all of your buttons. You'll also want to keep track of all of the clips that you're showing/hiding. They can be stored in an array.
You can "connect" a button to a clip by giving them similar names (btn_game1 and game1).
The following code assumes that your buttons are all named btn_gameN and your clips are named gameN (where N is a number):
var clips:Array = [game1, game2, game3, game4];
btn_game1.addEventListener(MouseEvent.CLICK, onGameButtonClicked);
btn_game2.addEventListener(MouseEvent.CLICK, onGameButtonClicked);
btn_game3.addEventListener(MouseEvent.CLICK, onGameButtonClicked);
btn_game4.addEventListener(MouseEvent.CLICK, onGameButtonClicked);
function onGameButtonClicked(e:MouseEvent):void
{
// figure out which button was just clicked by looking at its name
var clipNum:String = e.currentTarget.name.substr("btn_game".length);
// loop through all of your clips ...
for each(var clip:MovieClip in clips)
{
if(clip.name.substr("game".length) == clipNum)
{
// if the name matches, toggle the visibility
clip.visible = !clip.visible;
}
else
{
// if the name doesn't match, set visibility to false
clip.visible = false;
}
}
}
When you show game1 you must hide game2. Likewise for game2.
function openGame1(evt:MouseEvent) {
if (game1.visible) {
game1.visible = false;
}else {
game1.visible = true;
game2.visible = false;
}
}

Flash CS3 AS3 Movieclips carrying over to other frames

OK so I am having a weird issue. I have some movieclips on screen, 4 of them, each with the following code (with different instance names of course):
stage.addEventListener(MouseEvent.MOUSE_DOWN,globalMouseDown,false,0,true); //add a global mouse listener
function globalMouseDown(e:Event):void {
//find out if the target is a descendant of this, if not, then something else was clicked.
var parent:DisplayObject = e.target as DisplayObject;
while(parent && parent != stage){
if(parent == this) return;
parent = parent.parent;
}
//something else was clicked that wasn't this, so go to the up state
gotoAndStop(1);
}
stop();
addEventListener(MouseEvent.MOUSE_DOWN, onHs1Press);
addEventListener(MouseEvent.MOUSE_OVER, onHs1Over);
addEventListener(MouseEvent.MOUSE_OUT, onHs1Out);
function onHs1Press(event:MouseEvent):void
{
// toggle between frame 1 and 3 on button press
gotoAndStop(this.currentFrame == 3 ? 1 : 3);
parent.addChild(this)
}
function onHs1Over(event:MouseEvent):void
{
if (currentFrame != 3)
{
gotoAndStop(2);
}
}
function onHs1Out(event:MouseEvent):void
{
// only switch back to UP state if the button is "pressed"
if (currentFrame != 3)
{
gotoAndStop(1);
}
}
Basically it lets you hover your mouse and the movieclip changes and then when you click on it a little pop up window appears until you click the movieclip again to close it.
There is also a button on screen that allows you to move forward or backwards to other frames with this code:
Next.addEventListener(MouseEvent.CLICK,Nclick);
function Nclick(event:MouseEvent):void {
nextFrame();
}
Back.addEventListener(MouseEvent.CLICK,Bclick);
function Bclick(event:MouseEvent):void {
prevFrame();
}
The button code is on the main timeline and the movieclip code is on the movieclip's timeline.
For some reason if you have the movieclip in the DOWN state (with the popup window open) and you click the button to go to the next frame, the movieclip follows onto the next and any other frames instead of just going away.
I have this same code present on other frames and none of the other ones behave this way, it's really weird.
You can even click it still when its on the other frames and bring up the popup window where the movieclip and code aren't even present.
What's going on with it?
I tried testing this, and could reproduce your issue. If you add a movieclip to the stage in FlashPro, after changing it's index or parentage, it will from that point on be treated like an object created from code and the timeline will ignore it and even create another instance of it on a frame where it is created.
You'll have to manually remove the buttons from the display list.
function Nclick(event:MouseEvent):void {
nextFrame();
removeBtns();
}
function Bclick(event:MouseEvent):void {
prevFrame();
removeBtns();
}
function removeBtns():void {
if(currentFrame != 2){ //whatever the frame of your buttons is
if(btn1 && btn1.parent) removeChild(btn1); //btn1 being whatever your button instnace name is
if(btn2 && btn2.parent) removeChild(btn2); //repeat for all buttons
}
}
OR If you'd prefer to have encapsulated code, instead of the above, put this on your button class/timeline:
var myFrame:int = MovieClip(parent).currentFrame;
this.addEventListener(Event.ENTER_FRAME,enterFrameHandler);
this.addEventListener(Event.REMOVED_FROM_STAGE,removedHandler);
function enterFrameHandler(e:Event):void {
if(MovieClip(parent).currentFrame != myFrame){
parent.removeChild(this);
}
}
function removedHandler(e:Event):void {
this.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
this.removeEventListener(Event.REMOVED_FROM_STAGE, removedHandler);
}

as3 continuous movement of object with touch event

i am attempting to make an interactive scene fot my nexus 7 using actionscript. i am attempting to make a nape body to move continuously while a button is being pressed. the trace(event.target.name); in the tap handler is returning the instance name of the button being pressed as i expected it to but the same trace statement in the enter_frame pressed function is returning the buttons parent name and thus the movement is not happening below is my code..
resetBtn.addEventListener(TouchEvent.TOUCH_BEGIN , tapHandler);
ballBtn.addEventListener(TouchEvent.TOUCH_BEGIN , tapHandler );
leftArrow.addEventListener(TouchEvent.TOUCH_BEGIN , tapHandler );
rightArrow.addEventListener(TouchEvent.TOUCH_BEGIN , tapHandler );
private function tapHandler(event:TouchEvent):void
{
//listen for mouse up on the stage, in case the finger moved off of the button accidentally when they release.
rightArrow.addEventListener(TouchEvent.TOUCH_END, endTouch);
//while the mouse is down, run the tick function once every frame as per the project frame rate
addEventListener(Event.ENTER_FRAME, pressed);
trace(event.target.name);
//ball.applyImpulse(new Vec2(25,0));
}
function endTouch(e:Event):void
{
removeEventListener(Event.ENTER_FRAME, pressed);
//stop running the tick function every frame now that the mouse is up
this.removeEventListener(TouchEvent.TOUCH_END,endTouch);
//remove the listener for endTouch
}
function pressed(e:Event):void
{
space.step(1 / stage.frameRate);
trace(e.target.name);
if(e.target.name == "leftArrow")
{
trace("going left");
crane.position.x -= 5;
boom.position.x -= 5;
c.position.x -= 5;
}
if(e.target.name == "rightArrow")
{
trace("going Right");
crane.position.x += 5;
boom.position.x += 5;
c.position.x += 5;
}
}
if you can help me fix this or suggest a better way of achieving this wour help would be greatly appreciated.
Your issue is basically that you're adding the listener to the parent for the Enter_frame events so the target when that event dispatches isn't your buttons as you desire. I think instead of moving the listener though you're better off using a variable to hold a reference to your buttons like this:
private var curButton:Sprite;
resetBtn.addEventListener(TouchEvent.TOUCH_BEGIN , tapHandler);
ballBtn.addEventListener(TouchEvent.TOUCH_BEGIN , tapHandler );
leftArrow.addEventListener(TouchEvent.TOUCH_BEGIN , tapHandler );
rightArrow.addEventListener(TouchEvent.TOUCH_BEGIN , tapHandler );
private function tapHandler(event:TouchEvent):void
{
curButton = event.target;
curButton.addEventListener(TouchEvent.TOUCH_END, endTouch);
addEventListener(Event.ENTER_FRAME, pressed);
}
function endTouch(e:Event):void
{
trace("touch end received");
removeEventListener(Event.ENTER_FRAME, pressed);
curButton.removeEventListener(TouchEvent.TOUCH_END, endTouch);
curButton = null;
}
function pressed(e:Event):void
{
trace("currently pressed");
space.step(1 / stage.frameRate);
if(curButton == leftArrow)
{
trace("going left");
crane.position.x -= 5;
boom.position.x -= 5;
c.position.x -= 5;
}
if(curButton == rightArrow)
{
trace("going Right");
crane.position.x += 5;
boom.position.x += 5;
c.position.x += 5;
}
}
Okay see my edits above, hopefully should help resolve. Also as it seems you've probably already figured out the instance name that you give a variable when you define it, isn't the same as the .name property or the .id property, the instance name is no longer available at run time (if you really want to you can use the name property but you have to populate it yourself, and generally it's best to just use the instance names in the code instead, as this is checked at compile time, and incurs no extra run-time overhead).

Actionscript Image with clickable spots

Can any one help in suggesting a solution for the following:
i have a large image, consider it as a map, i want to put this image in a viewer that is smaller than the image and i have to be able to scroll the image by clicking and dragging it.
and i want to put in this image a clickable spots in a specified x and y coordinated, and be able to click the spots.
when clicking any spot in the image, the image will be changed with a new spots.. and so on..
can you help in suggesting what is the best object to load the image in and be able to do all the mentioned points.
Thanks in advance.
This is easier than you think. You have a few goals to consider:
"i want to put this image in a viewer that is smaller than the image": You dont need anything special to do this. The concept of this is simply that you have a mask overlay where you want the large image visible.
var viewer:Sprite = new Sprite; //200x200
var imageMask:Sprite = new Sprite; //200x200
var imageContainer:Sprite = new Sprite; //400x500
imageContainer.mask = imageMask;
viewer.addChild(imageContainer);
//this will allow you to visibly see only 200x200 of the
//imageContainer at any time
"i have to be able to scroll the image by clicking and dragging it": This is a little more logic as the imageContainer will have to move in the -(negative) direction of the mouse. Add some listeners to check for mouse actions, and drag as required.
var allowDrag:Boolean = false;
imageContainer.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
imageContainer.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
imageContainer.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
function onMouseDown(e:Event):void{
allowDrag = true;
}
function onMouseUp(e:Event):void{
allowDrag = false;
}
function onMouseMove(e:Event):void{
//return if not dragging
if(!allowDrag) return;
//move the imageContainer in a -(negative) direction of the mouse
//use an index relative to the size of the viewer and imageContainer
var speed:Number = 0.5;
imageContainer.x -= (viewer.width/imageContainer.width)*speed;
imageContainer.y -= (viewer.height/imageContainer.height)*speed;
//clean the positions so the image remains within the viewer
if(imageContainer.x > 0) imageContainer.x = 0;
if(imageContainer.x < -viewer.width) imageContainer.x = -viewer.width;
if(imageContainer.y > 0) imageContainer.y = 0;
if(imageContainer.y < -viewer.height) imageContainer.y = -viewer.height;
}
"i want to put in this image a clickable spots in a specified x and y coordinated, and be able to click the spots": This also requires a little more thinking. In this case what you want to do is create [hotspots] on the image that are clickable, when clicked = do actions.
//USAGE
//define the click area coords
var clickCoords:Rectangle = new Rectangle();
clickCoords.x = 10; //starts at x 10
clickCoords.y = 10; //starts at y 10
clickCoords.width = 100; //100 wide
clickCoords.height = 100; //100 tall
//add the click listener
var clickArea:Sprite = hotSpot(imageContainer,clickCoords);
clickArea.addEventListener(MouseEvent.CLICK, onHotSoptClick);
//hot spot factory
function hotSpot(target:Sprite,coords:Rectangle):Sprite{
//create the hotspot
var hs:Sprite = new Sprite;
hs.graphics.beginFill(0,0);
hs.graphics.drawRect(0,0,coords.width,coords.height);
hs.graphics.endFill();
//add the hotspot to the target
hs.x = coords.x;
hs.y = coords.y;
target.addChild(hs);
}
function onHotSoptClick(e:MouseEvent):void{
//do something
}
IMPORTANT:
You may want to keep a list of hot spots you create so you can do garbage cleanup, and you plan on dynamically generating hotspots per image... then YOU MUST keep an active list of hot spots and remove when not in use.
You can catch the events MouseDown, MouseUp, MouseMove, MouseOut, on your viewing window, this way you can control exactly what do you want to do.
Here is the pseudo-code:
reset()
{
isDown=false;
downPointX=0;
downPointY=0;
distanceX=0;
distanceY=0;
}
onMouseDown()
{
isDown=true;
downPointX=mouseX;
downPointY=mouseY;
}
onMouseUp()
{
if(distanceX+distanceY==0 and isDown)
click(downPointX,downPointY);
reset();
}
onMouseMove()
{
if isDown then
distanceX=mouseX-downPointX;
distanceY=mouseY-downPointY;
drag(distanceX,distanceY);
endif;
}
onMouseOut()
{
reset();
}
drag(distanceX,distanceY)
{
change your map coordinates
}
click(downPointX,downPointY)
{
if(inSpot(downPointX,downPointY)==true)
changeMap();
endif;
}
changeMap()
{
change your maps and spots
}
avoid implementing any event for your spots sprites or you can get unexpected results.
You can check these for more information
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Sprite.html#eventSummary

AS3 CS5 How can I refresh the stage after a SOUND_COMPLETE?

I have an educational game where children hear a sound and then have to choose the correct image out of 3 images.
When they want to hear the sound again they can press a speaker button.
The 3 images are movieclips (named card1, card2 and card3) dynamically added to the stage, with the buttonMode = true.
Whenever they press the speaker to hear the sound again or get feedback if they press the wrong image, I remove the mouse_events from the cards for the duration of the sound. I also set the buttonMode = false, so the children know they won't be able to click while the sound is playing.
On SOUND_COMPLETE I add the eventListeners again. Now the buttonMode = true again as well.
I want to do a refresh of the screen like event.updateAfterEvent(); so the cursor changes to a hand, should they have placed it on one of the cards. BUT the event.updateAfterEvent() can't be attached to a SOUND_COMPLETE, you can only use it after an interaction event like MOUSE or GESTURE.
tldr; How can I refresh my stage so the cursor changes back to a hand after the SOUND_COMPLETE ?
HereĀ“s some of the code:
function speakerClick(event:MouseEvent):void
{
remLst();
SoundMixer.stopAll();
cardCnl = gameSnd.play();
cardCnl.addEventListener(Event.SOUND_COMPLETE, sndComplete);
}
function sndComplete(event:Event):void
{
cardCnl.removeEventListener(Event.SOUND_COMPLETE, sndComplete);
addLst();
}
function addLst():void
{
for (var i:int = 1; i < 4; i++)
{
var card:Card = getChildByName("card" + i) as Card;
card.addEventListener(MouseEvent.CLICK, fnClick);
card.addEventListener(MouseEvent.MOUSE_OVER, fnOver);
card.addEventListener(MouseEvent.MOUSE_OUT, fnOut);
card.buttonMode = true;
}
}
In your addLst function, when cycling through the 4 cards, you could check for the current mouse position, and check if it is inside the boundaries of one of the cards.
It could work like this:
if ( mouseX > card.x && mouseX < (card.x + card.width)
mouseY > card.y && mouseY < (card.y + card.height))
{
Mouse.cursor = MouseCursor.BUTTON;
}
I am not 100% sure though if buttonMode changes it back to Arrow when the mouse leaves the object. I usually don't use buttonMode.