How to make carousel loop back to beginning - actionscript-3

I have a 800w movieclip containing 4 panels next to each other, each with 200 width (See picture here). When I click and drag then mouse_out, it detects the direction of the mouse and move the panels by 200 either left or right depending on the direction.
My problem is I want this to loop, so when it gets to the very left panel, it'll continue on to the left, and visa versa when it gets to the very right panel, I should be able to continue with the click and drag motion.
I'm not sure if this is considered a carousel.
Anyhow this is what I have so far. I've made 2 comments "What happens now" toLeftTween() and toRightTween() to indicate where I'm stuck.
import com.greensock.*;
import com.greensock.easing.*;
var selectX:Number = 0;
var mouseX1:int = 0;
var mouseX2:int = 0;
var mcPosX:int = 0;
var contents:MovieClip = all_mc;
var draggable:Boolean = true;
contents.buttonMode = true;
contents.mouseChildren = false;
contents.x = 0;
contents.y = 70;
addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
function mouseDownHandler(e:MouseEvent):void {
//select the correct point on mc
selectX = contents.x - mouseX;
//for prediction direction later - mouse point 1
mouseX1 = stage.mouseX;
//trace("1: " + mouseX1);
// move mc with mouse
if (draggable) {
addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
} else {
trace("unable to drag");
}
}
function mouseUpHandler(e:MouseEvent):void {
//for prediction direction later - mouse point 2
mouseX2 = stage.mouseX;
//trace("2: " + mouseX2);
//remove mc move with mouse
removeEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
//check for direction of the mc based on mouseX1 and mouseX2
mouseDirection();
}
function onEnterFrameHandler(e:Event):void {
contents.x = parent.mouseX + selectX;
}
function mouseDirection():void {
if (mouseX1 > mouseX2) {
trace("to the left");
toLeftTween();
} else if (mouseX1 < mouseX2) {
trace("to the right");
toRightTween();
} else {
trace("nothing happened");
}
}
function toLeftTween():void {
if(contents.x<1 && contents.x>199) {
mcPosX = 0;
trace("to left - Panel 1");
} else if(contents.x<-1 && contents.x>-199) {
mcPosX = -200;
trace("to left - Panel 2");
} else if(contents.x<-201 && contents.x>-399) {
mcPosX = -400;
trace("to left - Panel 3");
} else if(contents.x<-401 && contents.x>-599) {
mcPosX = -600;
trace("to left - Panel 4");
} else if(contents.x>-600) {
//What happens now?
}
var toLeftTween:TweenLite = new TweenLite(contents,0.25, {x:mcPosX});
}
function toRightTween():void {
if(contents.x<-601 && contents.x>-799) {
mcPosX = -600;
trace("to right - Panel 4");
} else if(contents.x<-401 && contents.x>-599) {
mcPosX = -400;
trace("to right - Panel 3");
} else if(contents.x<-201 && contents.x>-399) {
mcPosX = -200;
trace("to right - Panel 2");
} else if(contents.x<-1 && contents.x>-199) {
mcPosX = 0;
trace("to right - Panel 1");
} else if(contents.x<-2) {
//What happens now?
}
var toRightTween:TweenLite = new TweenLite(contents,0.25, {x:mcPosX});
}

Good work. The solution is actually quite simple, when you see it.
You need to check the distance between your starting mouse point and your current mouse point, every frame, which it looks like you're doing with selectX and mouseX. Your problem is that when you go past a certain distance, you have no logic to handle your loop.
Because it's a loop, you want to check whether the distance between your starting point and current point is greater than the width of your carousel movieclip, which is 800. If so, you need the logic to loop back on itself. (However, I'm not sure why your toLeftTween and toRightTween functions check that contents.x is in a negative range....I suppose that's because of the registration point on the movieclip?)
(Edit: I see what you did - why you have the negative numbers. You're sliding the movieclip to the left as needed. Now that I'm looking at the way you did this, the modulus won't actually work because you're checking a range between -600 and 200, instead of a range between 0 and 800...)
You'll need something like this.
function toLeftTween():void {
// If contents.x is divisible by the width of the movieclip, it's greater than the mc width.
// We check this here, and grab the remainder.
if (contents.x > 800 || contents.x < -600)
contents.x = contents.x % 800; // Modulus operator. Returns remainder.
if(contents.x<1 && contents.x>199) {
mcPosX = 0;
trace("to left - Panel 1");
} else if(contents.x<-1 && contents.x>-199) {
mcPosX = -200;
trace("to left - Panel 2");
} else if(contents.x<-201 && contents.x>-399) {
mcPosX = -400;
trace("to left - Panel 3");
} else if(contents.x<-401 && contents.x>-599) {
mcPosX = -600;
trace("to left - Panel 4");
} else if(contents.x>-600) { // I think you flipped a sign here... -lunchmeat
//What happens now?
// Due to the modulus, we should never find ourselves in this situation!
}
var toLeftTween:TweenLite = new TweenLite(contents,0.25, {x:mcPosX});
}
That should do the trick, more or less. You'll need to add this to both tween functions. (It might need a little tweaking.) Let me know if you run into any problems. Good luck!

if you want something like
(Note:numbers stands for panels, and index 0 is initial point.)
for index 0
1 - 2 - 3 - 4
for index 1
2 - 3 - 4 - 1
for index -1
4 - 1 - 2 - 3
Seems like you heading wrong way.
First if u need continues loop you have to move movieclips that is out of view to the end. And you need a clone of first element at the end of items for continues look. I would prefer to use bitmapData of content so you wont need a clone of first element and it ll compute faster and the way is easier.

Related

Dragging and placing movieclips

I'm trying to make an animation using AS3 which consists of dragging and placing movieclips (small images) inside some rectangles (bitmaps) and then presenting the images (big images) corresponding to the movieclips by the same order as they were placed along the rectangles.
However, there is a little trick with which I'm having a few difficulties. When a movieclip is placed inside a rectangle and I try to drag another movieclip to the same rectangle, the one that I'm dragging should return to the initial position. The code I have is working sometimes, but others, it doesn't (still possible to place the movieclip above or under the other).
Another question is: How can I make for the movieclip that I'm dragging to always go above another movieclip and not under? (sometimes they go above, anothers they go under).
Thanks in advance. Best regards.
Here is my code:
function returnToInitial(k:int){
this["foto"+String(k)+"_mc"].x = this["foto"+String(k)+"_mc"].iniX;
this["foto"+String(k)+"_mc"].y = this["foto"+String(k)+"_mc"].iniY;}
for(i=1; i<7; i++){
this["foto"+String(i)+"_mc"].addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
this["foto"+String(i)+"_mc"].num = i;
if(i <= 3){
this["foto"+String(i)+"_mc"].iniX = (160*i)+(i-1)*100;
this["foto"+String(i)+"_mc"].iniY = 100;
}else if(i > 3){
this["foto"+String(i)+"_mc"].iniX = (160*(i-3))+((i-3)-1)*100;;
this["foto"+String(i)+"_mc"].iniY = 260;
}
}
function startDragging(me:MouseEvent):void {
stage.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
MovieClip(me.currentTarget).startDrag(true);
currentDragged = MovieClip(me.currentTarget);}
function stopDragging(evt:Event):void {
stage.removeEventListener(MouseEvent.MOUSE_UP, stopDragging);
stopDrag();
checkPosition(currentDragged);}
function firstCheck(mcR:MovieClip){
for(q = 0; q < icons.length; q++){
if(this[icons[q]].y == 455){
posX = Math.abs(mcR.x - this[icons[q]].x);
if(posX < 10){
returnToInitial(mcR.num);
}
}
}
}
function checkPosition(mc:MovieClip){
firstCheck(mc);
if(mc.y > 420 && mc.y < 490){
mc.y = 455;
for(k=0; k<6; k++){
if(mc.x > 60+(k*135) && mc.x < 120+(k*135)){
mc.x = 90+(k*135);
array[k] = mc.num;
}
}
}
}
For making the movieclip you are dragging appear on top of everything else, add this to startDragging:
setChildIndex(MovieClip(me.currentTarget), this.numChildren-1);

My Actionsript is Skipping Frame 3 and Going Straight to Frame 4

I'm trying to make a primitive game in Flash. I'm using AS3 to build it. So far everything I have coded is working fine. Until now, I've only had 3 frames. However, I am ready to move on so I added a fourth frame. But, when I test the animation, it skips from frame 2 to frame 4. I put a trace in Frame 3 to see if Flash was even running it, and the trace executes the trace so I know Flash isn't completely ignoring Frame 3. But, I have a stop(); at the end of frame 3 and I have a stop(); on Frame 4. So, I'm not sure why Frame 3 is being skipped. The game doesn't have any tweens or actual animations so it shouldn't be anything of that sort. The only interaction is clicking on dots. I've put the code for all 4 of my frames below (I'm not sure if this is frowned upon. If it is, please tell me and I'll remove it but I'm putting it because it seems like it may be helpful). I'm also uploading a link to my .FLA file in case someone wants to see the whole thing.
Frame 1:
import flash.events.MouseEvent;
var dotList = new Array(); var level:int = 10; var invisoDotList = new Array();
var loop:int;
for(loop = 0; loop < level; loop++)
{
var dot:Dot = new Dot();
var invisoDot:InvisoDot = new InvisoDot();
var tester:Boolean = true;
var xval:int = Math.floor(Math.random()*(1+520))+14;
var looper:int = 0;
while(looper < dotList.length)
{
if(Math.abs(xval - dotList[looper].x) > 30)//minimum spacing
{
looper++;
}
else
{
looper = 0;
xval = Math.floor(Math.random()*(1+520))+14;
}
}
dot.x = xval;
dot.y = 187;
invisoDot.x = xval;
invisoDot.y = 187;
invisoDot.alpha = 0;
dotList[loop] = dot;
invisoDotList[loop] = invisoDot;
addChild(invisoDot);
addChild(dot);
}
//trace(dotList); test to ensure that dots are added to the array
button.addEventListener(MouseEvent.CLICK, hideDots);
function hideDots(e:MouseEvent)
{
for(var loop:int = 0; loop < dotList.length; loop++)
{
dotList[loop].alpha = 0;//make dots disappear
}
nextFrame();
}
stop();
Frame 2:
import flash.events.MouseEvent;
button.addEventListener(MouseEvent.CLICK, next);
function next(e:MouseEvent)
{
nextFrame();
}
stop();
Frame 3:
import flash.events.MouseEvent;
removeChild(button);
var clicks:int = -1;
//trace(dotList.length);
stage.addEventListener(MouseEvent.CLICK, clickCount);
for(var loopvar:int = 0; loopvar < dotList.length; loopvar++)
{
//trace("loop");
dot = dotList[loopvar];
invisoDot = invisoDotList[loopvar];
dot.addEventListener(MouseEvent.CLICK, onClick);
invisoDot.addEventListener(MouseEvent.CLICK, onClick);
//trace("event");
}
//trace(dotList.length);
function onClick(e:MouseEvent)
{
//e.currentTarget.alpha = .5;
for(var hitcheck:int = 0; hitcheck < dotList.length; hitcheck++)
{
if(dotList[hitcheck].x == e.currentTarget.x)
{
dotList[hitcheck].alpha = 1;
}
}
//trace("check");
}
function clickCount(e:MouseEvent)
{
clicks++;
//trace(clicks);
var numChanged:int = 0;
for(var index:int = 0; index < dotList.length; index++)//check whether the user has gotten all the dots
{
if(dotList[index].alpha == 1)
{
numChanged++;
}
}
if(numChanged == level)//if the user has gotten all the dots
{
trace("next screen for sucess");
trace(clicks);
}
else if((clicks - numChanged) >= 2)//this ends the session as soon as 2 mistakes are made
{
trace("next screen for failed number of clicks");
trace(clicks);
}
/*else if((clicks - level) >= 2)//if the user has made too many mistakes. This ends the session after the maximum number of tries have been used
{
trace("next screen too many clicks");
trace(clicks);
}*/
}
trace("end");
stop();
Frame 4:
stop();
Link to the .FLA file: https://www.dropbox.com/s/x1vim49tnz227id/Game.fla
If any of the conventions I've used in this question are wrong or frowned upon, please let me know and I'll correct them. It's been over a year since I've last posted on StackOverflow.
Does the same button instance exist on both frame 1 and 2?
If so you will end up with two click event handlers on the button on frame 2 (hideDots() and next()). If you click on the button then they both call nextFrame() which would skip frame 3.
Possible solutions:
Remove the first event listener before moving to the next frame:
button.addEventListener(MouseEvent.CLICK, hideDots);
function hideDots(e:MouseEvent)
{
for(var loop:int = 0; loop < dotList.length; loop++)
{
dotList[loop].alpha = 0;//make dots disappear
}
// Remove the event listener here:
button.removeEventListener(MouseEvent.CLICK, hideDots);
nextFrame();
}
OR
Have different instances of the button on frame 1 and 2.
You can do this by having a keyframe for the button on frame 1 and 2 - Flash will create a new instance of the button when it hits that frame.

how to stop a movieclip on the Y-axis with buttons?

I have two buttons that moves a movieclip up/down the Y-axis. How do I get the movieclip to stop at a certain height, and still be able to move it in the opposite direction?
I need this to work like this:
When you press the down-button, the movieclip goes downwards, but not past Y=500.
When you press the up-button, the movieclip goes upwards, but not past Y= 300.
I get the movieclip to stop at the correct point (500), but when it reaches this point it's stuck..
so it won't go upwards again if I press the up-button.
can someone help me please?:)
here's my code so far:
1) decrease = the down-button
2) increase = up-button
3) stempel = the movieclip I want to stop on the Y-axis
var moveStempel = 0;
decrease.addEventListener(MouseEvent.MOUSE_DOWN, decreasePressed);
decrease.addEventListener(MouseEvent.MOUSE_UP, removeEnterFrame);
increase.addEventListener(MouseEvent.MOUSE_DOWN, increasePressed);
increase.addEventListener(MouseEvent.MOUSE_UP, removeEnterFrame);
function decreasePressed(e:MouseEvent):void
{
moveStempel = 2;
addEnterFrame();
}
function increasePressed(e:MouseEvent):void
{
moveStempel = -2;
addEnterFrame();
}
// ADD ENTER FRAME
function addEnterFrame():void
{
this.addEventListener(Event.ENTER_FRAME, update);
}
function removeEnterFrame(e:MouseEvent):void
{
this.removeEventListener(Event.ENTER_FRAME, update);
}
function update(e:Event):void
{
if (stempel.y < 500)
{
stempel.y += moveStempel;
trace("inside");
}
else if (stempel.y > 500)
{
stempel.stop();
trace("outside");
}
In your code right now, once stempel has a y value greater than 500, it will never be able to move again.
There are two conditions when stempel can move: if it's moving down, it can't be at the bottom of the allowed area, and if it's moving up, it can't be at the top of the allowed area.
if ((stempel.y < 500 && moveStempel == 2) || (stempel.y > 300 && moveStempel == -2))
{
stempel.y += moveStempel;
trace("inside");
}
else
{
stempel.stop();
trace("outside");
}

Removing child override by another code

I have a button that automatically adds a child and takes away health once clicked. I also made the button take away 0 if the child = true. However, I have another button that once clicked, it should move to another frame and remove the child. For some reason, it isn't removing the child. Before, I didn't have the button take away 0 if the child = true and the removeChild worked fine. The code is all in a frame named actions on the main timeline.
var createGirlText = new GirlSpeechBoxClass();
if(EnergyNumber <= 0) {
Girl_btn.buttonMode = false;
Girl_btn.mouseEnabled = false;
}
Girl_btn.addEventListener(MouseEvent.CLICK, GirlTalk);
Girl_btn.buttonMode = true;
function GirlTalk(event:MouseEvent){
addChild(createGirlText);
createGirlText.x = 350.95;
createGirlText.y = 488.95;
EnergyNumber -= 10;
if(createGirlText = true){
EnergyNumber -= 0;
}
if(EnergyNumber < 0) {
EnergyNumber = 0;
}
if(EnergyNumber <= 0) {
Girl_btn.buttonMode = false;
Girl_btn.mouseEnabled = false;
}
}
//Action for clicking Main Button
BacktoOutside_btn.addEventListener(MouseEvent.CLICK, gotoMainArea2);
BacktoOutside_btn.buttonMode = true;
function gotoMainArea2(event:MouseEvent){
gotoAndStop("MainArea");
MovieClip(this.root).removeChild(createGirlText);
}
Try createGirlText.parent.removeChild(createGirlText);
It's also worth testing if the parent exists before removing it.

AS3: How to make this mouse position detection work properly?

I'm new to AS3 so please bare with my basic questions.
What I want to do is have a left arrow MC on the left side of the stage and right arrow MC on the right side of stage. When the mouse is over the left 1/3 of the stage, the left arrow appears, on the right 1/3 of the stage, the right arrow appears, but the middle 1/3 the arrows fade out.
I do NOT want to make large invisible MCs and detect the mouse movement that way. I just want it to be relative to the mouse position on the stage.
I thought it would be very easy, but the eventListener fires everytime the mouse moves, so the left and right arrow MC animation is constantly being triggered, and they look like they are "shaking" for a lack of a better word.
What I have so far is the following. Could someone please give me some help with this?
var stagePos:int = stage.width/3;
addEventListener(MouseEvent.MOUSE_MOVE, arrowDetectHandler);
function arrowDetectHandler(e:MouseEvent) {
var mouseArrow:int = mouseX;
if (mouseArrow<stagePos) {
arrowLeft_mc.gotoAndPlay("Show");
trace ("left arrow show");
} else if (mouseArrow>stagePos && mouseArrow<stagePos*2) {
arrowLeft_mc.gotoAndPlay("Hide");
arrowRight_mc.gotoAndPlay("Hide");
trace ("nothing happens");
} else if (mouseArrow>stagePos*2) {
arrowRight_mc.gotoAndPlay("Show");
trace ("right arrow show");
}
}
if...else seem to be ok. The only thing which may couse the problem is mc.gotoAndPlay. Try to use alpha property instead:
var stagePos:int = stage.width/3;
addEventListener(MouseEvent.MOUSE_MOVE, arrowDetectHandler);
function arrowDetectHandler(e:MouseEvent) {
var mouseArrow:int = mouseX;
if (mouseArrow<stagePos) {
arrowLeft_mc.alpha = 1; //alpha is 1, arrow is shown
trace ("left arrow show");
} else if (mouseArrow>stagePos && mouseArrow<stagePos*2) {
arrowLeft_mc.alpha = 0; //alpha is 0, arrow is hidden
arrowRight_mc.alpha = 0;
trace ("nothing happens");
} else if (mouseArrow>stagePos*2) {
arrowRight_mc.alpha = 1;
trace ("right arrow show");
}
}
The trouble is the speed with which your code is getting called repeatedly.
If you you are listening to MouseEvent.MOUSE_MOVE then it will happen way too fast for any 'gotoAndPlay' business to finish.
Since you don't want to do the invisible MovieClips ( which gives you the very handy MouseEvent.ROLL_OVER and MouseEvent.ROLL_OUT events ) then you are left polling to evaluate coordinates like you have in your code.
You need to remember the last 'answer' your code gave and then ignore the case that is already true next time. You'll have to bear with my preference for switch statements.
var stagePos:int = stage.width/3;
var _arrowShowing : int = 0;
addEventListener(MouseEvent.MOUSE_MOVE, arrowDetectHandler);
function arrowDetectHandler(e:MouseEvent)
{
var mouseArrow:int = mouseX;
switch( true )
{
case ( !_arrowShowing == 1 && mouseArrow < stagePos ) :
_arrowShowing = 1;
arrowLeft_mc.gotoAndPlay("Show");
trace ("left arrow show");
break;
case ( !_arrowShowing == 0 && mouseArrow > stagePos && mouseArrow < stagePos * 2 ) :
_arrowShowing = 0;
arrowLeft_mc.gotoAndPlay("Hide");
arrowRight_mc.gotoAndPlay("Hide");
trace ("nothing happens");
break;
case ( !_arrowShowing == 2 && mouseArrow>stagePos*2 ) :
_arrowShowing = 2;
arrowRight_mc.gotoAndPlay("Show");
trace ("right arrow show");
break;
}
}