How do I control adding the same movieclip different places in AS3? - arrays

Time for a really nooby question, but I can't find a satisfying answer.. Everytime I search for array tutorials, they are about how you put different strings of text into an array and accessing them again.
Here is what I have:
When you start the game, you are able to press lets just say 5 buttons. When you press button 1 flash (simplified) goes:
addChild(backGround)
addChild(world)
world.gotoAndStop(1)
addChild(character)
And so on with the other buttons, changing which world you're in.
Here is what I want:
I want to be able to add the same enemy movieclip specific places, according to which button the player presses.
So let's say the player presses button 3, and in world 3 I want there to be an enemy at x 200, y 300, and an enemy at x 600, y 450 and one more enemy some other specific place. All enemies are the same movieclip.
So how can add enemies like that???
I know I need an array, but how do i access the movieclip like I want to?
My code:
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main extends MovieClip {
public var character:Character;
public var backGround:BackGround;
public var world:World;
public var worldMap:WorldMap;
public var monster1:Monster1;
public var worldLevel:int;
public var currentLevel:int;
public function Main() {
backGround = new BackGround;
world = new World;
monster1 = new Monster1
character = new Character();
worldMap = new WorldMap;
// Every world lies in a different frame in the "world" movieclip
world.worldDangers.gotoAndStop(currentLevel);
world.SafeGround.gotoAndStop(currentLevel);
world.GroundViz.gotoAndStop(currentLevel);
world.PortaltoNew.gotoAndStop(currentLevel);
//----- on the world map is the different world buttons ---
addChild(worldMap);
addEventListener(Event.ENTER_FRAME, moveWorld)
//------------------- world buttons --------------------
worldMap.buttonWorld1.addEventListener(MouseEvent.CLICK, gotoWorld1)
worldMap.buttonWorld2.addEventListener(MouseEvent.CLICK, gotoWorld2)
worldMap.buttonWorld3.addEventListener(MouseEvent.CLICK, gotoWorld3)
worldMap.buttonWorld4.addEventListener(MouseEvent.CLICK, gotoWorld4)
}
function gotoWorld1 (m:MouseEvent):void
{
currentLevel = 1;
addChild(backGround);
addChild(world);
world.x = 0;
world.y = 0;
isinWorld = true
addChild(character);
character.x = 300;
character.y = 650;
character.gotoAndStop(3);
worldMap.parent.removeChild(worldMap);
}
//----------------- function world 2 ---------------------
function gotoWorld2 (m:MouseEvent):void
{
currentLevel = 2;
addChild(backGround);
addChild(world);
world.x = 0;
world.y = 0;
isinWorld = true
addChild(character);
character.x = 300;
character.y = 650;
character.gotoAndStop(3);
worldMap.parent.removeChild(worldMap);
}
//----------------- function world 3 -----------------------
function gotoWorld3 (m:MouseEvent):void
{
currentLevel = 3;
addChild(backGround);
addChild(world);
world.x = 0;
world.y = 0;
isinWorld = true
addChild(character);
character.x = 300;
character.y = 650;
character.gotoAndStop(3);
worldMap.parent.removeChild(worldMap);
}
function gotoWorld4 (m:MouseEvent):void
{
currentLevel = 4;
addChild(backGround);
addChild(world);
world.x = 0;
world.y = 0;
isinWorld = true
addChild(character);
character.x = 300;
character.y = 650;
character.gotoAndStop(3);
worldMap.parent.removeChild(worldMap);
}
function moveWorld (e:Event)
{
if (isinWorld)
{
world.y = world.y + 5;
if (character.hitTestObject(monster1))
{
world.parent.removeChild(world);
backGround.parent.removeChild(backGround);
character.parent.removeChild(character);
isinWorld = false
}
}
}
}
}

Something like the following should do the trick:
// Define a bunch of positions for this world
var positions:Array = [
new Point(200, 300),
new Point(600, 450),
new Point(50, 350)
];
// Probably makes sense to store your enemies on
// an array for access later in your game
var enemies:Array = [];
// Temporary variables for the loop
var enemy:Enemy;
var position:Point;
// Iterate over the positions array
for (var i:int = 0; i < positions.length; i ++)
{
// Get the position
position = positions[i] as Point;
// Create a new enemy and position him
enemy = new Enemy();
enemy.x = position.x;
enemy.y = position.y;
// Add child and store it on an array
addChild(enemy);
enemies.push(enemy);
}

Related

Drag and Drop Arrays AS3

I'm trying to create a drag and drop game in Actionscript 3 using mostly arrays. I'm doing it on a simpler game first before going to the main game because I need to know how the codes work first.
The simpler game is just there are two squares and two circles. The two squares are on a different array while the two circles are in the same one. What should happen is that when either circles hit (hitTestPoint) the right square, their x and y becomes the center of the square. (like it clicks to the center). And when either circles hit the left square, it should return the circles to their last position (doesn't have to be their original position).
Here's the code:
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.display.DisplayObject;
import flash.geom.Point;
import flash.events.Event;
public class MC_MAIN extends MovieClip
{
var mc1:mc_circle;
var mc2:mc_circle;
var mc3:mc_square;
var mc4:mc_square;
var Shapes:Array;
var Target:Array;
var WTarget:Array;
var newPlace:Point;
public function MC_MAIN()
{
// constructor code
init();
}
function init():void
{
Shapes = new Array ;
Target = new Array ;
WTarget = new Array ;
mc3 = new mc_square();
mc3.height = 75;
mc3.width = 75;
mc3.x = 400;
mc3.y = 200;
Target.push(mc3);
addChild(mc3);
mc4 = new mc_square();
mc4.height = 75;
mc4.width = 75;
mc4.x = 150;
mc4.y = 200;
WTarget.push(mc4);
addChild(mc4);
mc1 = new mc_circle();
mc1.height = 25;
mc1.width = 25;
mc1.x = 100;
mc1.y = 100;
Shapes.push(mc1);
addChild(mc1);
mc2 = new mc_circle();
mc2.height = 25;
mc2.width = 25;
mc2.x = 200;
mc2.y = 200;
Shapes.push(mc2);
addChild(mc2);
for (var i:int = 0; i<Shapes.length; i++)
{
Shapes[i].addEventListener(MouseEvent.MOUSE_DOWN, DRG);
Shapes[i].addEventListener(MouseEvent.MOUSE_UP, SDRG);
}
}
function DRG(e:MouseEvent):void
{
e.currentTarget.startDrag();
}
function SDRG(e:MouseEvent):void
{
e.currentTarget.stopDrag();
for (var m:int = 0; m<Shapes.length; m++)
{
newPlace = new Point(Shapes[m].x,Shapes[m].y);
}
trace(newPlace);
for (var a:int = 0; a<Target.length; a++)
{
for (var b:int = 0; b<Shapes.length; b++)
{
if (Target[a].hitTestPoint(Shapes[b].x,Shapes[b].y))
{
Shapes[b].x = Target[a].x;
Shapes[b].y = Target[a].y;
}
}
}
for (var c:int = 0; c<WTarget.length; c++)
{
for (var d:int = 0; d<Shapes.length; d++)
{
if (WTarget[c].hitTestPoint(Shapes[d].x,Shapes[d].y))
{
Shapes[d].x = newPlace.x;
Shapes[d].y = newPlace.y;
}
}
}
}
}
}
What happens is that the code for the left square doesn't work but their are no syntax errors. Nothing happens when either circles hit the left square.
And when I'm trying to trace the position of the circles, It just shows the x & y coordinate of only one of them. (I guess it's tracing the first object of the array which is at index 0. I'm just asking if I guessed right for this part.)
I is a bit difficult to follow the logic and there are some points that doesn't make much sense like:
for (var m:int = 0; m<Shapes.length; m++)
{
newPlace = new Point(Shapes[m].x,Shapes[m].y);
}
newPlace will be the position of the last shape in Shapes, so the loop is fairly useless.
I guess what you need is something like that:
public class MC_MAIN extends MovieClip
{
private leftSquares:Array;
private rightSquares:Array;
//more of the members from above
private startPos:Point;
//init the thing and add left and right squares
//to there respective Array
function DRG(e:MouseEvent):void
{
var t:DisplayObject = e.currentTarget;
//save the starting position
startPos = new Point(t.x,t.y);
t.startDrag();
}
function SDRG(e:MouseEvent):void {
var t:DisplayObject = e.currentTarget;
//find all squares from the left
//the target »hits«
var leftHits:Array = leftSquares.filter(
function (square:DisplayObject) {
return square.hitTestPoint(t.x, t.y);
});
//same for the right
var leftHits:Array = rightSquares.filter(
function (square:DisplayObject) {
return square.hitTestPoint(t.x, t.y);
});
//now you can apply the logic
//based on the hit Test result
//this way you can handle the case
//if it hits both, to throw an error
//or alike
if(leftHits.length > 0) {
//reset position
t.x = startPos.x;
t.y = startPos.y;
}
else if (rightHits.length > 0) {
//set the position tp the desired item in rightHits
}
else {
}
}
}
Please not that my Action Script skills haven't been used for a long time, so the code above might not compile. It is meant to illustrate the idea. Important are the following steps:
1. Save the starting position, to be able to reset it
2. Sort the `squares` in respective lists for left and right
3. Hit test both and apply the logic.

Use the same array to next frame

Im making a game and i complete the level1 at frame1.
When im trying to make the level2 to frame2 i dont know how to transfer my Arrays
to frame2.All the other buttons and functions are working(i copy the eventListeners to frame2)but my enemies wich are in Arrays does nothing!!
Thanks a lot!!!
import flash.events.Event;
stop();
//variables the helicopters
var enemy1Array:Array = new Array();
for (var e1:int = numChildren - 1; e1 >= 0; e1--)
{
var child:DisplayObject = getChildAt(e1);
if (child.name == "enemy1")
{
enemy1Array.push(child);
}
}
stage.addEventListener(Event.ENTER_FRAME, allloop);
function allloop(event:Event):void
{
//move the helicopters
for each(var enemy1:Sprite in enemy1Array)
{
enemy1.x = enemy1.x -= enemy1speed;
if(enemy1.hitTestObject(defense))
{
addChild(explotionbonus3);
explotionbonus3.gotoAndPlay(2);
explotionbonus3.x = enemy1.x;
explotionbonus3.y = enemy1.y;
enemy1.y = 1000;
score -=5;
scoretxt.text = String (score);
}
}
}

Select pairs from an array (matching game) And add sound to that selection AS3 Flash CS4

I'm using a tutorial I found on Google - which works well. However, I have a few issues to make it work how I would like. This code uses a MovieClip for the card faces with the back of the card on frame1 and 2-17 different pictures or movieclips.
The questions are - Is there a way to get the ActionScript to choose from the whole array? But still produce pairs to choose from. As it stands now - If I select the game to be 4 across by 2 down (8 cards in total) It has the back of card (frame1) and will then randomly select, but only from frames 2-5 . If I modify these lines...
public function MatchingGameObject10():void {
// make a list of card numbers
var cardlist:Array = new Array();
for(var i:uint=0;i<boardWidth*boardHeight/2;i++) {
cardlist.push(i);
cardlist.push(i);
}
to
public function MatchingGameObject10():void {
// make a list of card numbers
var cardlist:Array = new Array(0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17);
}
I get random cards - but no pairs...
If I can ask another question here - it is - how to add a seperate sound to each card..So if it shows a Bee - the Bee.mp3 is played.. Here's the whole code..
package {
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.utils.getTimer;
import flash.utils.Timer;
import flash.media.Sound;
import flash.media.SoundChannel;
public class MatchingGameObject10 extends MovieClip {
// game constants
private static const boardWidth:uint = 4;
private static const boardHeight:uint = 2;
private static const cardHorizontalSpacing:Number = 500;
private static const cardVerticalSpacing:Number = 700;
private static const boardOffsetX:Number = 50;
private static const boardOffsetY:Number = 70;
private static const pointsForMatch:int = 10;
private static const pointsForMiss:int = -1;
// variables
private var firstCard:Card10;
private var secondCard:Card10;
private var cardsLeft:uint;
private var gameScore:int;
private var gameStartTime:uint;
private var gameTime:uint;
// text fields
private var gameScoreField:TextField;
private var gameTimeField:TextField;
// timer to return cards to face-down
private var flipBackTimer:Timer;
// set up sounds
var theFirstCardSound:FirstCardSound = new FirstCardSound();
var theMissSound:MissSound = new MissSound();
var theMatchSound:MatchSound = new MatchSound();
// initialization function
public function MatchingGameObject10():void {
// make a list of card numbers
var cardlist:Array = new Array();
for(var i:uint=0;i<boardWidth*boardHeight/2;i++) {
cardlist.push(i);
cardlist.push(i);
}
// create all the cards, position them, and assign a randomcard face to each
cardsLeft = 0;
for (var x:uint=0; x<boardWidth; x++) {// horizontal
for (var y:uint=0; y<boardHeight; y++) {// vertical
var c:Card10 = new Card10();// copy the movie clip
c.stop();// stop on first frame
c.x = x*cardHorizontalSpacing+boardOffsetX;// set position
c.y = y*cardVerticalSpacing+boardOffsetY;
var r:uint = Math.floor(Math.random()*cardlist.length);// get a random face
c.cardface = cardlist[r];// assign face to card
cardlist.splice(r,1);// remove face from list
c.addEventListener(MouseEvent.CLICK,clickCard);// have it listen for clicks
c.buttonMode = true;
addChild(c);// show the card
cardsLeft++;
}
}
// set up the score
gameScoreField = new TextField();
addChild(gameScoreField);
gameScore = 0;
showGameScore();
// set up the clock
gameTimeField = new TextField();
gameTimeField.x = 450;
addChild(gameTimeField);
gameStartTime = getTimer();
gameTime = 0;
addEventListener(Event.ENTER_FRAME,showTime);
}
// player clicked on a card
public function clickCard(event:MouseEvent) {
var thisCard:Card10 = (event.target as Card10); // what card?
if (firstCard == null) { // first card in a pair
firstCard = thisCard; // note it
thisCard.startFlip(thisCard.cardface+2);
playSound(theFirstCardSound);
} else if (firstCard == thisCard) { // clicked first card again
firstCard.startFlip(1);
firstCard = null;
playSound(theMissSound);
} else if (secondCard == null) { // second card in a pair
secondCard = thisCard; // note it
thisCard.startFlip(thisCard.cardface+2);
// compare two cards
if (firstCard.cardface == secondCard.cardface) {
// remove a match
removeChild(firstCard);
removeChild(secondCard);
// reset selection
firstCard = null;
secondCard = null;
// add points
gameScore += pointsForMatch;
showGameScore();
playSound(theMatchSound);
// check for game over
cardsLeft -= 2; // 2 less cards
if (cardsLeft == 0) {
MovieClip(root).gameScore = gameScore;
MovieClip(root).gameTime = clockTime(gameTime);
MovieClip(root).gotoAndStop("gameover");
}
} else {
gameScore += pointsForMiss;
showGameScore();
playSound(theMissSound);
flipBackTimer = new Timer(2000,1);
flipBackTimer.addEventListener(TimerEvent.TIMER_COMPLETE,returnCards);
flipBackTimer.start();
}
} else { // starting to pick another pair
returnCards(null);
playSound(theFirstCardSound);
// select first card in next pair
firstCard = thisCard;
firstCard.startFlip(thisCard.cardface+2);
}
}
// return cards to face-down
public function returnCards(event:TimerEvent) {
firstCard.startFlip(1);
secondCard.startFlip(1);
firstCard = null;
secondCard = null;
flipBackTimer.removeEventListener(TimerEvent.TIMER_COMPLETE,returnCards);
}
public function showGameScore() {
gameScoreField.text = "Score: "+String(gameScore);
}
public function showTime(event:Event) {
gameTime = getTimer()-gameStartTime;
gameTimeField.text = "Time: "+clockTime(gameTime);
}
public function clockTime(ms:int) {
var seconds:int = Math.floor(ms/1000);
var minutes:int = Math.floor(seconds/60);
seconds -= minutes*60;
var timeString:String = minutes+":"+String(seconds+100).substr(1,2);
return timeString;
}
public function playSound(soundObject:Object) {
var channel:SoundChannel = soundObject.play();
}
}
}
Here's Card10 class
package {
import flash.display.*;
import flash.events.*;
public dynamic class Card extends MovieClip {
private var flipStep:uint;
private var isFlipping:Boolean = false;
private var flipToFrame:uint;
// begin the flip, remember which frame to jump to
public function startFlip(flipToWhichFrame:uint) {
isFlipping = true;
flipStep = 10;
flipToFrame = flipToWhichFrame;
this.addEventListener(Event.ENTER_FRAME, flip);
}
// take 10 steps to flip
public function flip(event:Event) {
flipStep--; // next step
if (flipStep > 5) { // first half of flip
this.scaleX = .20*(flipStep-6);
} else { // second half of flip
this.scaleX = .20*(5-flipStep);
}
// when it is the middle of the flip, go to new frame
if (flipStep == 5) {
gotoAndStop(flipToFrame);
}
// at the end of the flip, stop the animation
if (flipStep == 0) {
this.removeEventListener(Event.ENTER_FRAME, flip);
}
}
}
}
So without completely re-factoring how this game works, the best way to make it dynamic based off the amount of frames (card faces) in your Card10 Clip, is change this code:
var cardlist:Array = new Array();
for(var i:uint=0;i<boardWidth*boardHeight/2;i++) {
cardlist.push(i);
cardlist.push(i);
}
To the following:
var allCards:Array = new Array(); //an array of all available frame numbers
var cardlist:Array = new Array(); //an array of just those cards to show
var tmpCard:Card10 = new Card10(); //create a temporary card for the sole purpose of counting how many frames it has
var i:int;
//populate the array with all the frames from the Card MC
for (i = 0; i < tmpCard.totalFrames;i++) {
allCards.push(i);//add card frame to allCards array
}
//now create the list of cards to show (since the amount of cards may be more than the amount you want to show
for (i = 0; i < (boardWidth * boardHeight) / 2; i++) {
var cardIndex:int = Math.floor(Math.random() * allCards.length);// get a random card from the all card list
//add the card twice (so there is a pair) in the list of cards to show
cardlist.push(cardIndex);
cardlist.push(cardIndex);
//remove it from the all cards array so it doesn't come up again in the random bit above
allCards.splice(cardIndex,1);
}

Trying to access the first instance of an array in Actionscript 3

I am trying to do deat detection in actionscript 3. My idea is to create an array of dots (MovieClips) on the x axis which represents the frequency spectrum, SoundMixer.computeSpectrum(bytes, true, 0); is set to true. How do I access the first dot instance of my array. I then want to check it's highest value on each current frame and and measure it against the last value. I think I need to set a threshold and when the value is within the threshold call that a beat....I'm lost, can anybody point me in the right direction..
Thanks in advance.
var snd: Sound = new Sound();
var req: URLRequest = new URLRequest("mySong.mp3");
snd.load(req);
var channel: SoundChannel;
channel = snd.play();
addEventListener(Event.ENTER_FRAME, onEnterFrame);
snd.addEventListener(Event.SOUND_COMPLETE, onPlaybackComplete);
const CHANNEL_LENGTH: int = 256;
const BUFFER_LENGTH: int = 512;
var dot:Dot;
dot.cacheAsBitmap = true;
var myArray:Array = new Array();
var bytes:ByteArray = new ByteArray();
function onEnterFrame(event: Event): void
{
SoundMixer.computeSpectrum(bytes, true, 0);
for (var i:int = 0; i < CHANNEL_LENGTH; i+=8) // channel_length = 256
{
var sampleValue:Number = bytes.readFloat();
dot = new Dot();
dot.x = i * 2;
dot.y = sampleValue * 250; //50 + (i * 30)
addChild(dot);
myArray.push(dot);
}
}
I am not sure what excetly you are going to do.
But if you want to do a sound spectrum visualizer, I think your direction is right.
I follow what you do and get result like this: (http://www.imageupload.co.uk/5M3n) Those dots will dance with the music
just move dot.cacheAsBitmap = true; after dot = new Dot(); or you can remove it.
and in Dot class, don't forget to dispose itself after some time.
But actually I dont need to use myArray at all.
Here is my code:
import flash.events.Event;
var snd: Sound = new Sound();
var req: URLRequest = new URLRequest("mySong.mp3");
snd.load(req);
var channel: SoundChannel;
channel = snd.play();
addEventListener(Event.ENTER_FRAME, onEnterFrame);
snd.addEventListener(Event.SOUND_COMPLETE, onPlaybackComplete);
const CHANNEL_LENGTH: int = 256;
const BUFFER_LENGTH: int = 512;
var dot:Dot;
var myArray:Array;
var bytes:ByteArray = new ByteArray();
function onEnterFrame(event: Event): void
{
SoundMixer.computeSpectrum(bytes, true, 0);
myArray = [];
for (var i:int = 0; i < CHANNEL_LENGTH; i+=8) // channel_length = 256
{
var sampleValue:Number = bytes.readFloat();
dot = new Dot();
dot.cacheAsBitmap = true;
dot.x = i * 2;
dot.y = sampleValue * stage.StageHeight;
addChild(dot);
myArray.push(dot);
}
var firstElement:Dot = myArray.length>0?myArray[0]:null;
if(firstElement)
{
handleWithFirstElement(firstElement);
}
}
function onPlaybackComplete(e:Event):void
{
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
}
function handleWithFirstElement(ele:Dot):void
{
//your code
}
And in Dot class:
flash.utils.setTimeout(this.parent.removeChild, 100, this);
// Run this just after added on Stage

as3 how to remove graphics from removed nape bodies

i have attached multiple instances of a moviecCip to multiple nape bodies and have a reset button to restore them to their original position. when the reset function is called the bodies are reset and have the mc attached to them. the problem is the original mc are still on the stage frozen in the position thy were when reset was called.
private var brickGraphic:MovieClip = new Brick();
private var brickArray:Array;
private function setUp():void
{
var brickType:CbType = new CbType();
var w:int = stage.stageWidth;
var h:int = stage.stageHeight;
var ag:int = stage.stageHeight - 58;// height ofarea above ground
brickArray = new Array ;
//wall
for (var i:int = 0; i < 10; i++)
{
var brick:Body = new Body(BodyType.DYNAMIC);
var brickShape:Polygon = new Polygon(Polygon.box(10,25));
var brickGraphic:MovieClip = new Brick();
brickGraphic.width = 10;
brickGraphic.height = 25;
addChild(brickGraphic);
brickGraphic.cacheAsBitmap = true;
brick.shapes.add(brickShape);
brick.position.setxy(450, ((ag ) - 30 * (i + 0.5)));
brick.angularVel = 0;
brick.shapes.at(0).material.elasticity = .5;
brick.shapes.at(0).material.density = 150;
brick.cbTypes.add(brickType);
brick.space = space;
brickGraphic.stop();
brick.userData.sprite = brickGraphic;
brick.userData.sprite.x = brick.position.x;
brick.userData.sprite.y = brick.position.y;
this.brickArray.push(brick);
}
}
private function reset():void
{
space.clear();
setUp();
}
any help would be greatly appreciated
Add a statement that will remove that linked MovieClip from those nape bodies into your reset() function. I expect this is what you need:
private function reset():void
{
if (contains(brick.userData.sprite)) removeChild(brick.userData.sprite);
space.clear();
setUp();
}

Resources