How to generate random number and use It few times? - actionscript-3

So I need to generate random number and use It few times, problem is that It generating on EnterFrame function.
This function generate number 0-5:
function pn():Number {
var pn:Number = Math.round(Math.random()*5);
return pn;
}
Here I check if character not jumping and stage.addEventListener(Event.ENTER_FRAME, jump);
if(!mainJumping){
mainJumping = true;
stage.addEventListener(Event.ENTER_FRAME, jump)
}
And here is jump function where I need to use random generated number:
function jump(e) {
if ( i < 50) {
i++;
item[1][pn()].y -=1
} else {
item[1][pn()].y += 1;
if (item[1][pn()].y == 0){
stage.removeEventListener(Event.ENTER_FRAME, jump)
}
}
Problem is that in jump function every time IF is checked It generates new number. I need to make that number will be generated and not changed till this part:
if (item[1][pn()].y == 0){
stage.removeEventListener(Event.ENTER_FRAME, jump)
}
After this It can generate new number. Have you ideas? Thank you.

// Create a variable higher up the scope chain to store the number
var random = 0;
// Assuming this is in a function at the same level as the jump function
//function() ???? {
if(!mainJumping){
mainJumping = true;
random = pn(); // Generate new random number when jump begins
stage.addEventListener(Event.ENTER_FRAME, jump)
}
//}
function jump(e) {
var item = item[1][random]; // Grab the random item
if ( i < 50) {
i++;
item.y -=1
} else {
item.y += 1;
if (item.y == 0){
stage.removeEventListener(Event.ENTER_FRAME, jump)
}
}
}

Create an instance variable called myRandomNumber. In the getter for it, if it is null, call pn() to populate it.
Something like this:
In your class, define the variable:
private var _myRandomNumber:int = 0;
And in your getter:
public function get myRandomNumber():int {
if (_myRandomNumber == 0) {
_myRandomNumber = pn();
}
return _myRandomNumber;
}
Now, when you call myRandomNumber, you'll get a "random number" :)

Related

Add moveclips on stage when elements of an array are clicked in as3

I have an array with six buttons called "sostaletters" and an array with six elements called "addedletters". What I want is every time a button is been clicked a new movieclip from the array "addedletters" to be added on stage. For example if the third element of the array "sostaletters" is been clicked then the third element of the array "addedletters" to be added on stage. How i can do that?
This is what i have done for my array "sostaletters"
var sostaletters:Array = [a7,a17,a24,a1,a18]
for each (var letter:MovieClip in sostaletters) {
letter.buttonMode = true;
letter.isClicked = false;
letter.addEventListener(MouseEvent.CLICK, kanoklick2);
function kanoklick2(event:MouseEvent):void
{
event.target.alpha = 0.5;
if(event.currentTarget.isClicked == false){
clickCount2 ++;
event.currentTarget.isClicked = true;
sostaletters[i].x = positionsArray[i].xPos;
sostaletters[i].y = positionsArray[i].yPos;
setChildIndex(MovieClip(e.currentTarget), numChildren - 1);
}
if(clickCount2 == sostaletters.length){
addChild(welldoneman);
myTimer.start();
if (contains(kremmala)) {
removeChild(kremmala)
}
for (var i:int= 0; i< wrongletters.length; i++)
{
wrongletters[i].removeEventListener(MouseEvent.CLICK, kanoklick);
}
for (var o:int= 0; o< sostaletters.length; o++)
{
sostaletters[o].removeEventListener(MouseEvent.CLICK, kanoklick2);
}
trace("All buttons have been clicked");
}
}
}
Neal Davis has already gave a right answer. But I shall make a code review for more clarity. See my comments in the code.
var sostaletters:Array = [a7,a17,a24,a1,a18]
// "sostaletters" is an Array. So it is better to use iteration by index
for each (var letter:MovieClip in sostaletters) {
letter.buttonMode = true;
letter.isClicked = false;
letter.addEventListener(MouseEvent.CLICK, kanoklick2);
// You will create "kanoklick2" function at each iteration.
// Move this declaration from this loop
function kanoklick2(event:MouseEvent):void {
event.target.alpha = 0.5;
// There is no need to compare a boolean property with "false" or "true"
// You can write "if(event.currentTarget.isClicked)"
if(event.currentTarget.isClicked == false) {
clickCount2 ++;
event.currentTarget.isClicked = true;
// You declare an "i" variable below.
// So the compiler will not fire en error.
// But you will not get an index of the current letter.
sostaletters[i].x = positionsArray[i].xPos;
sostaletters[i].y = positionsArray[i].yPos;
setChildIndex(MovieClip(e.currentTarget), numChildren - 1);
}
// If number of "sostaletters" are not changed
// you can save its value in a variable for an example "sostalettersNum"
if (clickCount2 == sostaletters.length) {
addChild(welldoneman);
myTimer.start();
if (contains(kremmala)) {
removeChild(kremmala)
}
// You declare an "i" variable. And use it above to get a current letter.
// But an "i" will not contain its index.
// It will be equal to "wrongletters.length"
for (var i:int= 0; i

Adding multiple instances of the same object to the stage

I'm making a "spit" card game and I'm trying to be able to have 3 cards on the stage at once to be able to drag to the pile. So my question is how do I have multiple instances of the same object on the stage, but be able to assign each card different frames, etc. Here is the code to understand the context of it.
"cardArray" has 53 frames, 52 of which have a card face, 53rd is a "deck" picture.
//variables, constants
var cardDeck:Array = new Array();
var timer:Timer = new Timer(2000);
var j:int = 0;
var card:MovieClip = new CardArray();
var cardInDeck:Boolean;
const deckSize:int = 52;
//events:
card.addEventListener(MouseEvent.MOUSE_DOWN,fDown);
card.addEventListener(MouseEvent.MOUSE_UP,fUp);
startRandomise();
//This is where the unshuffled "deck" is created - values loaded into the array.
function createDeck():void
{
var i:int;
for(i =0; i<deckSize; i++)
{
cardDeck[i] = i+1;
}
}
function randomizeDeck( a : *, b : * ):int
{
return (Math.random()>.5) ? 1 : -1;
}
//Grab the value from the (presumably) current frame of the card
function convertCard(cardNo:int):int
{
var deckPos:int;
if (cardNo <= deckSize/4)
{
deckPos = cardNo;
}
else if (cardNo > deckSize/4 && cardNo <= deckSize/2)
{
deckPos = cardNo -13;
}
else if (cardNo > deckSize/2 && cardNo <=deckSize*3/4)
{
deckPos = cardNo -deckSize/2;
}
else if (cardNo >39)
{
deckPos = cardNo -39;
}
return deckPos;
}
btn.addEventListener(MouseEvent.MOUSE_UP,showArray);
function showArray(event:MouseEvent):void
{
if(j<deckSize /2)
{
addChild(card);
card.gotoAndStop(cardDeck[j]);
trace(cardDeck[j]+","+deckCompare[j]);
j++;
}
if(cardInDeck)
{
card.x = 200;
card.y = 200;
cardInDeck+false;
}
}
function fDown(evt:MouseEvent)
{
card.startDrag();
}
function fUp(evt:MouseEvent)
{
stopDrag();
if(card.hitTestObject(deck))
{
trace("deck: "+convertCard(deck.currentFrame));
trace("card: "+convertCard(card.currentFrame));
if(convertCard(card.currentFrame) == convertCard(deck.currentFrame)+1 || convertCard(card.currentFrame) == convertCard(deck.currentFrame)-1 || convertCard(card.currentFrame) == 13 && convertCard(deck.currentFrame) == 1 || convertCard(card.currentFrame) == 1 && convertCard(deck.currentFrame) == 13 || convertCard(deck.currentFrame) == 14)
{
deck.gotoAndStop(card.currentFrame);
removeChild(card);
cardInDeck=true;
}
else
{
card.x = 200;
card.y = 200;
}
}
else
{
card.x = 200;
card.y = 200;
}
}
function startRandomise():void
{
createDeck();
cardDeck.sort(randomizeDeck);
cardDeck.sort(randomizeDeck);
trace("random: "+cardDeck);
trace("deckCompare: "+deckCompare);
card.x = 200;
card.y = 200;
deck.gotoAndStop(53);
}
To have multiple cards, you need to instantiate more than one card. I don't know anything about the card game spit and don't understand the purpose of many of your functions, but you'll want to do something along these lines:
Create a function that generates (instantiates) a new card:
function createCard(faceFrame):MovieClip {
var tmpCard:MovieClip = new CardArray(); //this creates a new instance of a card
tmpCard.addEventListener(MouseEvent.MOUSE_DOWN, cardMouseDown); //make the card call the mouse down function when that event is triggered
tmpCard.gotoAndStop(faceFrame); //assign the card it's face (frame)
addChild(tmpCard); //add the card to the screen
return tmpCard;
}
Then, in your mouse down handler (I renamed it to be more clear what is is), you can do the following to card that was mouse downed:
function cardMouseDown(evt:MouseEvent) {
//the events currentTarget property is reference to the item that you attached the listener to, so in this case the card who triggered the mouse down
card = evt.currentTarget as MovieClip; //assign the current clicked card to the global card variable (so we can access it in the mouse up function)
card.startDrag();
//add the mouse up listener on the stage, since there are cases where you can drag so fast that the mouse isn't over the item it's dragging (and then if you were to release the mouse at that moment it wouldn't dispatch the event)
stage.addEventListener(MouseEvent.MOUSE_UP, stageMouseUp);
}
Then your mouse up function would look something like this:
function stageMouseUp(evt:MouseEvent) {
//remove the mouse up listener from the stage
stage.removeEventListener(MouseEvent.MOUSE_UP, stageMouseUp);
card.stopDrag();
if(card.hitTestObject(deck))
{
......//rest if the code
Seems like you would want to generate a new card in the showArray function you have? So something like this:
function showArray(event:MouseEvent):void
{
var newCard:MovieClip = createCard(cardDeck[j]);
j++
newCard.y = newCard.x = 200;
trace(cardDeck[j]+","+deckCompare[j]);
}
As an aside, you should consider calling your Card object something more sensible, like Card instead of CardArray, as it's not an array...

Objects spawn randomly in Flash actionscript 3.0

I am creating a game that a sheep need to jump or crouch to avoid obstacles.
I had create 2 types of obstacles but they come in a constant speed.
Sometimes the 2 obstacles come together make it impossible to avoid. Is there any way to change this?
Can I make the 2 obstacles come in randomly in a random speed?Here is my code.`
hole_mc.visible = false;
bird_mc.visible = false;
playhotarea_btn.addEventListener(MouseEvent.CLICK, removeInstructionBox);
function removeInstructionBox(event:MouseEvent):void
{
playhotarea_btn.removeEventListener(MouseEvent.CLICK, removeInstructionBox);
instructionbox_mc.visible = false;
instructiontext_mc.visible = false;
playbtn_mc.visible = false;
playbtntext_mc.visible = false;
sheep_mc.sheepIN_mc.visible = false;
sheep_mc.gotoAndPlay("sheepwalk");
treebg_mc.gotoAndPlay("bgloop");
hole_mc.visible = true;
bird_mc.visible = true;
timer.start();
}
hole_mc.addEventListener(Event.ENTER_FRAME, holeMove);
function holeMove(event:Event):void {
if (hole_mc.x>= -200) {
hole_mc.x -=7;
}else{
hole_mc.x=1080;
trace("hole loops");
}
}
bird_mc.addEventListener(Event.ENTER_FRAME, birdMove);
function birdMove(event:Event):void {
if (bird_mc.x>= -200) {
bird_mc.x -=10;
}else{
bird_mc.x=1080;
trace("bird loops");
}
}
stage.addEventListener(Event.ENTER_FRAME, hitHole);
function hitHole(event:Event):void{
if (sheep_mc.hitTestObject(hole_mc)){
gotoAndStop("GameOver");
hole_mc.removeEventListener(Event.ENTER_FRAME, holeMove);
stage.removeEventListener(Event.ENTER_FRAME, hitHole);
bird_mc.removeEventListener(Event.ENTER_FRAME, birdMove);
stage.removeEventListener(Event.ENTER_FRAME, hitBird);
}
}
stage.addEventListener(Event.ENTER_FRAME, hitBird);
function hitBird(event:Event):void{
if (sheep_mc.hitTestObject(bird_mc)){
gotoAndStop("GameOver");
bird_mc.removeEventListener(Event.ENTER_FRAME, birdMove);
stage.removeEventListener(Event.ENTER_FRAME, hitBird);
hole_mc.removeEventListener(Event.ENTER_FRAME, holeMove);
stage.removeEventListener(Event.ENTER_FRAME, hitHole);
}
}
var currentSecond:Number = 0;
var delay:Number = 1000;
var timer:Timer = new Timer(delay);
timer.addEventListener(TimerEvent.TIMER, timerEventHandler);
function timerEventHandler(event:TimerEvent):void
{
currentSecond++;
trace(currentSecond);
score_txt.text = String(currentSecond + " s");
}
`
You can always avoid spawning things in the same place by testing for "collision" before you create (or in your case, move) the new object. You should do the testing in whatever class has a reference to all the objects on the screen. In this case, the class you posted has references to the hole and bird, which are the two objects you want to NOT have the same x value.
Try something along the lines of:
function birdMove(event:Event):void {
if (bird_mc.x>= -200) {
bird_mc.x -=10;
}else{
if(hole_mc.x > 1000){ // See notes below
bird_mc.x=1080;
trace("bird loops");
}}}
I put 1000 under the assumption that you would want a little bit of space between the two obstacles. If you're only worried about them being EXACTLY on top of each other, then you can just use if hole_mc.x = 1080. But by using > some number, you can guarantee a little bit of room between them.
You should add a similar line to the hole mover as well so that it doesn't matter which one gets called first. They both check before they respawn.

HitTest Function with two parameters not initializing

Hey guys so Basically what I'm trying to do is when my player collides with all 5 of the points MovieClips in an array and the Goal Movie Clip i want a text to appear saying "Perfect. But i cant quite accomplish this. I set up the function and it seems like it would but i think what might be wrong is the hitTest with all the Movie clips in the array.
Here is how i set it up:
This is in my loop Function:
private function gameLoop(e:Event):void
{
perfectTextFunction();
}
This is the function:
private function perfectTextFunction():void
{
if (player.hitTestObject(mcGoal_1 && points))
{
trace("perfect Text");
mcPerfect = new perfectText();
mcPerfect.x = (stage.stageWidth / 2);
mcPerfect.y = (stage.stageHeight/ 2);
stage.addChild(mcPerfect);
}
}
The Trace doesn't pick anything up.
Here is how the points are added to the stage if needed:
public function addPointsToStage():void
{
for (var i = 0; i < nPoints; i++)
{
trace(aPointsArray.length);
points = new mcGainPoints();
stage.addChild(points);
points.x = startPoint.x + (xSpacing * i);
points.y = startPoint.y - (ySpacing * i);
aPointsArray.push(points);
}
}
Please any help would be appreciated! THank you!
VESPER here is how I made the NESTED LOOP:
//If all points are hit then Perfect Hit Text
if (player.hitTestObject(mcGoal_1 || mcGoal_2))
{
var weHitAll:Boolean = true;
for (var s in aPointsArray)
{
weHitAll = weHitAll && player.hitTestObject(aPointsArray[s]);
if (!weHitAll)
break;
}
if (weHitAll)
{
trace("perfect Hit");
mcPerfect = new perfectText();
mcPerfect.x = (stage.stageWidth / 2);
mcPerfect.y = (stage.stageHeight/ 2) - 80;
stage.addChild(mcPerfect);
nScore += 25;
updateHighScore();
}
}
var weHitAll:Boolean=true;
for (var s in aPointsArray) {
weHitAll = weHitAll&&player.hitTestObject(aPointsArray[s]);
if (!weHitAll) break; // missed one, drop cycle
}
if (weHitAll) {
trace('Perfect hit!');
... // etc
}
Function hitTestObject accepts only a single object as parameter, in order to check against an array you need to iterate through it, checking against one object at a time (here it's in aPointsArray[s]).

to create quiz using StartDrag and stopDrag

Actually i have a quiz.fla. In the file ,two of them fill inthe blank questions and others are
multiple questions.
square1_mc must run only once not twice. İf user correct selected, doesnt run it again.
However,if mybadscoretext is 1 not increase 2,3,4. :S
how i can do all?
stop();
var myScore:Number = 0;
var myBadScore:Number=0;
square1_mc.addEventListener(MouseEvent.MOUSE_DOWN, drag);
stage.addEventListener(MouseEvent.MOUSE_UP, drop);
function drag(e:MouseEvent):void
{
e.target.startDrag();
}
function drop(e:MouseEvent):void
{
square1_mc.stopDrag();
if (square1_mc.hitTestObject(square2_mc)== true)
{
square1_mc.x=129;
square1_mc.y=133;
this.graphics.clear();
this.graphics.lineStyle(2, 000000);
this.graphics.moveTo(square1_mc.x, square1_mc.y);
this.graphics.lineTo(square2_mc.x, square2_mc.y);
this.graphics.endFill();
myScore += 1;
score_txt.text=String(myScore);
square1_mc.removeEventListener(MouseEvent.MOUSE_DOWN, drag);
}
else
{
square1_mc.x=129;
square1_mc.y=133;
myBadScore += 1;
mybadscore_txt.text=String(myBadScore);
}
}
Add a variable to keep track of whether the bad score has been added:
var badMarked:Boolean = false;
function drag(e:MouseEvent):void
{
e.target.startDrag();
badMarked = false;
}
[...]
function drop(e:MouseEvent):void
{
if (square1_mc.hitTestObject(square2_mc)== true)
{
[...]
}
else if ( !badMarked )
{
square1_mc.x=129;
square1_mc.y=133;
myBadScore += 1;
mybadscore_txt.text=String(myBadScore);
badMarked = true;
}
}