Play random frames in movie clip actionscript3 - actionscript-3

I am trying to create small gaming app in flash.
So have one movie clip , inside that I have 4 frames.
I am calling one frame from those four randomly but I need to call it randomly again and again. setTimeout not working in my case, so how can I achieve randomly call any frame out of 4 repeatedly.
function createRandomCoinValues()
{
for(var i = 0; i< 5; i++)
{
var my_timedProcess:Number = setTimeout(createMc(i),4000);
if(my_timedProcess)
{
trace(my_timedProcess);
clearTimeout(my_timedProcess);
}
}
addListeners();
}
function createMc(i:Number)
{
associatedRandomValues[i] = randomNumbers(1,5);
var mc:MovieClip = this.getChildByName("coin"+ (i + 1) + "_mc") as MovieClip;
mc.gotoAndStop(generateRandomAnimation(1,100));
//By generateRandomAnimation() giving input to only either go to vertical or horizontal named frame.
}
Any help suggestion is very important to me. Thanks in advance.

What you need is addFrameScript().
Here is an example, not real code.
mc.addFrameScript( frame, function(){ mc.gotoAndStop(randomFrame) } )
Note: addFrameScript() start from frame 0 and end to totalFrame - 1.

Related

AS3 shuffling movieclips

I've added the basic targets and applying drag and drop for my puzzle pieces, now Im having trouble making the shuffling aspect. As in, after the player completes or opens up the fla, each time will start the puzzle pieces in random places of the stage. I understand using arrays for shuffling somehow but Im not sure exactly how to achieve this. I've stored the instance of my 19 puzzle pieces inside the array but now I have no idea what to do with this array. Other tutorials were abit out of my league and leaves my head scratching.
Just started doing coding for flash professional so yeah, any help with the shuffling movie clips ie the puzzles pieces would be greatly appreciated.
Heres's my code, Im not posting the whole thing since from P1 to P19 is basically copy pasting:
import flash.events.Event;
stage.addEventListener(Event.ENTER_FRAME, EntFrame)
function EntFrame(e: Event) : void
{
P1.addEventListener(MouseEvent.MOUSE_DOWN, fl_ClickToDrag);
function fl_ClickToDrag(event:MouseEvent):void
{
P1.startDrag();
}
stage.addEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop);
function fl_ReleaseToDrop(event:MouseEvent):void
{
P1.stopDrag();
}
if (T1.hitTestObject(P1.Tar1))
{
P1.x = 313.15;
P1.y = 242.75;
}
P19.addEventListener(MouseEvent.MOUSE_DOWN, fl_ClickToDrag_19);
function fl_ClickToDrag_19(event:MouseEvent):void
{
P19.startDrag();
}
stage.addEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop_19);
function fl_ReleaseToDrop_19(event:MouseEvent):void
{
P19.stopDrag();
}
if (T19.hitTestObject(P19.Tar19))
{
P19.x = 624.35;
P19.y = 455.60;
}
}
Here is what I hope is more holistic answer.
First, ditch those inline functions. Right now you make an ENTER_FRAME listener and inside that function you have inline function defined. This means every frame tick (which is tied to your frame rate, not the main timeline), those functions are going to get created again, and since you are adding them as handlers for listeners, they will stay in memory forever.
Here is a way you code this, showing ways to reduce redundancy and get rid of those memory leaks. This assumes the following:
You have 19 objects on the stage called T1 - T19, that represent the possible locations the pieces can go.
You have 19 pieces on the stage called P1 - P19, that, and the numbers correlate to the T locations as per the correct location of the piece.
//let's create a function to randomize the piece location
function seedPieces() {
//create an array consisting of the integers 1 - 19
var unusedSpaces:Vector.<int> = new Vector.<int>;
var i:int;
for (i = 1; i <= 19; i++) {
//populate that array
unusedSpaces.push(i);
}
var curLocation:DisplayObject; //helper var for the loop below
var curPiece:Sprite; //helper var for the loop below
//loop 19 times (from 1 - 19) - one iteration for each piece
for (i = 1; i <= 19; i++) {
curPiece = this["P" + i] as Sprite; //you can get the piece this way, or use an array if you've made one, like `pieces[i];`
trace(curPiece.name);
//splice removes and returns the item at the specified index (in this case a random number between 0 and arrays length less 1) - the second parameter is amount of items to remove (just 1 for this case)
curLocation = this["T" + unusedSpaces.splice(int(Math.random() * unusedSpaces.length), 1)] as DisplayObject;
trace(" ",curLocation.name);
//move the piece to the random location:
curPiece.x = curLocation.x;
curPiece.y = curLocation.y;
}
}
//NOW, as an aside, you should use a loop to add all your listeners for the sake of sanity - if you have them in an array, loop through that, or use the sloppy way like this:
for (var i:int = 1; i <= 19; i++) {
Sprite(this["P" + i]).addEventListener(MouseEvent.MOUSE_DOWN, fl_ClickToDrag);
}
//create a var to hold any piece that is currently being dragged, so you know which piece to stop drag on later
var currentDraggingItem:Sprite;
seedPieces();
function fl_ClickToDrag(event:MouseEvent):void
{
//assign this clicked item to the currentDraggingItem var
currentDraggingItem = event.currentTarget as Sprite;
//bring this one to the front
currentDraggingItem.parent.addChild(currentDraggingItem);
//you can use this one click handler for all pieces
//the piece that was actually clicked, is referenced by event.currentTarget
currentDraggingItem.startDrag();
//add the mouse up listener now that the mouse is currently DOWN
stage.addEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop);
//listen every frame while dragging
stage.addEventListener(Event.ENTER_FRAME, EntFrame);
}
function fl_ReleaseToDrop(event:MouseEvent):void
{
//if currentDraggingItem has a value, stop drag it
if (currentDraggingItem) {
currentDraggingItem.stopDrag();
//send to the back
currentDraggingItem.parent.addChildAt(currentDraggingItem,0);
}
//remove the mouse up and enter frame listener now that the mouse is UP
stage.removeEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop);
stage.removeEventListener(Event.ENTER_FRAME, EntFrame);
if(checkComplete()){
//game over, do something
}
}
function EntFrame(e: Event) : void
{
//this will snap the peice to the correct spot when the mouse is touching the correct spot
if(currentDraggingItem){
if (this[currentDraggingItem.name.replace("P","T")].hitTestPoint(mouseX,mouseY))
{
currentDraggingItem.x = this[currentDraggingItem.name.replace("P","T")].x;
currentDraggingItem.y = this[currentDraggingItem.name.replace("P","T")].y;
}
}
}
function checkComplete():Boolean {
//use a loop to go through all your pieces and check if they are in the right spot. Again, you could have them in an array, or do it the lazy way
for (var i:int = 1; i <= 19; i++) {
if (!this["T"+i].hitTestObject(this["P"+i]))
{
return false;
}
}
return true;
}
Well, in general you can shuffle with the following code:
var shuffledVector:Vector.<someClass> = new Vector.<someClass>;
while (originalVector.length > 0) {
shuffledVector.push(originalVector.splice(Math.random() * originalVector.length, 1)[0]);
}
Longer, explained version:
var shuffledVector:Vector.<someClass> = new Vector.<someClass>; //We will store our shuffled vector in here
var randomIndex:int; //Random index from the originalVector
var resultVector:Vector.<someClass>; //result from the originalVector.splice(...) function
var randomElement:someClass; //Random element from the originalVector
while (originalVector.length > 0) { //We will reduce the size of the originalVector until the originalVector is empty.
randomIndex = Math.random() * originalVector.length; //Calculate a random index within the range of the originalVector from 0 to originalVector.lenght-1 (note that the range decreases by one on every loop)
randomVector = originalVector.splice(randomIndex, 1); //Use splice to remove one element at the randomly choosen index, we will receive a vector with the removed element...
randomElement = randomVector[0]; //...so we need to access the element
shuffledVector.push(randomElement); //Add the randomly choosen element to our shuffled vector
}
I've written the code for a vector as i suggest to use a vector instead of an array, but the principle behind it is the same for an array.
In your case the originalVector is a vector filled with your P1-P19 Movieclips and someClass would be MovieClip. The originalVector is empty at the end and could be replaced with the shuffled one and of course it would make a lot more sense if you put the code in a seperate function like this:
function Shuffle(originalVector:Vector.<someClass>) : void {
var shuffledVector:Vector.<someClass> = new Vector.<someClass>;
while (originalVector.length > 0) {
shuffledVector.push(originalVector.splice(Math.random() * originalVector.length, 1)[0]);
}
originalVector = shuffledVector;
}
Offtopic, but important for further coding: Someone else already mentioned, that it is not good to add EventListeners on every frame, because it is absolutely unnecessary. You only need to add the Listeners once. Your code is very repetitive, you should use a function which accepts a MovieClip, x and y then call that function 19 times.
e.g.:
function setUpMovieClip(MC:MovieClip, x:int, y:int) : {
MC.addEventListener(MouseEvent.MOUSE_DOWN, clickToDrag);
//more code...
}
within the clickToDrag function you can access the MovieClip which was clicked via the event.target property:
function clickToDrag(e:MouseEvent) : {
e.target.startDrag();
//more code...
}
I hope you get the idea.

Problems with an object appearing on a frame I don't want it to appear on AS3

I am a total noob at AS3, roughly 1 year experience so please be lenient with me :)
I currently am making an endless runner game and I'm making the obstacles spawn using this method
var therespawn:RespawnObject;
var thecone:trafficcone;
var started:Boolean = false;
var dx:Number = 10;
var dy:Number = 10;
stage.addEventListener(Event.ENTER_FRAME, startGame);
addEventListener(Event.ENTER_FRAME, collision);
addEventListener(Event.ENTER_FRAME, coneCollision);
function startGame(evt:Event):void {
if (started == false) {
spawnHazard();
}
}
function spawnHazard() {
started = true;
therespawn = new RespawnObject();
addChild(therespawn);
thecone = new trafficcone();
addChild(thecone);
therespawn.x = -50;
therespawn.y = 310;
thecone.x = 600;
thecone.y = 310;
}
function collision(evt:Event):void {
thecone.x -= 15;
if(thecone.hitTestObject(therespawn)) {
thecone.x = 600;
}
}
Now the only way to finish the game or end it is to get hit by an obstacle which ive shown down below:
function coneCollision(evt:Event):void {
if(MainChar.hitTestObject(thecone)) {
gotoAndStop("frameFive");
}
}
Everytime the highscore frame appears the cone is still spawning and despawning, why is that?
I haven't declared them as global?
Any help appreciated, thanks!
You can fix your problem by setting started to false:
function coneCollision(evt:Event):void {
if(MainChar.hitTestObject(thecone)) {
started = false;
gotoAndStop("frameFive");
}
}
The flash timeline really only has to with the way MovieClips are visually displayed as children of the stage. Removing an object from the timeline doesn't just suddenly nullify all the code associated with that object. In other words, your ENTER_FRAME method still runs in the background even if the object is no longer a child of the Stage, regardless of the frame number for the MovieClip. If you're serious about coding you might consider investigating in Classes and Object Oriented AS3. Classes are much nicer to work with than the Flash timeline.

AS2 carousel gallery to AS3

I'm making carousel gallery for my class, however we got a code written in AS2 and have to transform it into AS3. I have a problem with two fragments:
// create the objects for the circular motion
for (var i:Number = 0; i < numberOfObjects; i++)
{
this.createEmptyMovieClip('object'+i, i);
this['object'+i].loadMovie('p'+(i+1)+'.jpg');
}
Where I'm adding movie clips as objects, and then I want to use them as:
// create the motion along the circular path
this.addEventListener(Event.ENTER_FRAME, function()
{
// loop over all the objects
for (var i:Number = 0; i < numberOfObjects; i++)
{
thisObj = this['object'+i];
placeObj(thisObj,i);
displayObj(thisObj);
}
})
Of course I get an exception:
Scene 1, Layer 'actions', Frame 1, Line 85 1120: Access of undefined property thisObj.
I know that createEmptyMovieClip as well as loadMovie don't work in AS3, and I probably should make MovieClip as new MovieClip, however I still have troubles how to make this work. I'll be truly grateful for any advices.
You need to apply var keyword before you introduce a new variable.
Correct your as3 code this:
var thisObj:Sprite = this['object'+i];

addEventListener adding again and again

My pictures gallery has 8 frames. There are a few lines of AS3 on the AS3 layer in the first frame:
stop();
var picsArrayYouthVillage:Array = new Array(pic1,pic2,pic3,pic4,pic5,pic6,pic7,pic8);
for each (var pic in picsArrayYouthVillage)
{
pic.buttonMode = true;
}
for(var i = 0; i<8; i++)
{
trace("hi");
picsArrayYouthVillage[i].addEventListener(MouseEvent.CLICK, jumpToFrame);
}
function jumpToFrame(m:MouseEvent):void{
gotoAndStop(m.target.name + "_frame");
}
On the Pictures layer there are 8 frames containing pictures and thumbnail buttons (pic1,...pic8)
The problem is when I navigate using the thumbs, every time I click the first button and jumping to frame 1, the event listeners are added again.
Any ideas? Thank you all in advance.
You may check the object has the event listener or not before add event listener to it
for(var i = 0; i<8; i++) {
if (!picsArrayYouthVillage[i].hasEventListener(MouseEvent.CLICK)) {
trace("hi");
picsArrayYouthVillage[i].addEventListener(MouseEvent.CLICK, jumpToFrame);
}
}
EDIT
After I tried the code, I have found the problem,change this code too
var picsArrayYouthVillage:Array = new Array(pic1,pic2,pic3,pic4,pic5,pic6,pic7,pic8);
to
var picsArrayYouthVillage:Array;
if (picsArrayYouthVillage == null) {
picsArrayYouthVillage = new Array(pic1,pic2,pic3,pic4,pic5,pic6,pic7,pic8);
}
Remember to trace hi in the if condition. If it works, it should eight hi and only one time.

Randomize Saved movieclips stored on children

I'm having a hard time with some code in actionscript 3.0. I don'y know how to randomize the movieclips stored on child and pick only 8 movieclips wherein there are 10 movieclips stored. I hope you'll be able to help me with this problem. thanks
Here is the code:
//start stage function
this.mainmc.addEventListener (Event.ENTER_FRAME, setupStage1);
this.waitingCounter=0;
//set up current stage
function setupStage1 (e:Event) {
//wait for timeline
if (this.waitingCounter<2) {
this.waitingCounter++;
//not ready yet, do nothing
return;
}
//Start the timer
timer.start();
//hide hint
this.mainmc.hintmc.visible=false;
//hide star animation
this.mainmc.starAnimation.visible=false;
//listener for hint button
this.mainmc.hintbut.addEventListener (MouseEvent.CLICK, showHint1);
//create objects array
this.obArr=[];
//count the objects on stage
for (var n=0; n<this.mainmc.numChildren; n++) {
//get the children
var ob=this.mainmc.getChildAt(n);
//only take movie clips
if (ob is MovieClip) {
//only count the movie clips that have name declared
if (ob.myname!=null) {
//push to array
this.obArr.push (MovieClip(ob));
}
}
}
on the code above, the code will store all the movieclips that are present in the stage. it stores them in a child. each 10 movieclips has a variable name "myname".
If you simply want to randomly sort items within an array, use the array.sort method and within your sort function, simply create a random number between 1 and 2. If it's 1, return true, if it's 2, return false. Here is an actionscript 2 snippet along with a link to a couple of tutorials:
var a:Array = new Array(“a”, “b”, “c”, “d”, “e”);
function shuffle(a,b):Number {
var num : Number = Math.round(Math.random()*2)-1;
return num;
}
var b:Array = a.sort(shuffle);
trace(b);
http://mrsteel.wordpress.com/2007/05/26/random-array-in-as2-as3-example-using-sort/
http://sierakowski.eu/list-of-tips/75-random-sort-function-comes-handy-when-building-applications-with-playlists.html
This is a much longer and more in-depth tutorial:
http://active.tutsplus.com/tutorials/actionscript/quick-tip-how-to-randomly-shuffle-an-array-in-as3/