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
Related
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);
}
I am trying to reset a scene an move every thing to its original position the reset function resets the array adds the nape bodies back to the stage and attaches the graphics but the original graphics still are on the stage in whatever position they were in when reset was called
private var brickGraphic:MovieClip = new Brick();
private var brick:Body;
private var brickArray:Array;
private function setUp():void
{
brickArray = new Array ;
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 = 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;
this.brickArray.push(brick);
}
private function reset():void
{
if (contains(brickGraphic)) removeChild(brickGraphic);
space.clear();
setUp();
}
}
this is the final issue i am having on this app and your help would be greatly appreciated
That's because you are not removing them with removeChild.
You need to call removeChild for each brickGraphic object you add to the stage.
Something like :
private function setUp():void
{
brickArray = [];
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 = 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;
this.brickArray.push(brick);
}
}
private function removeAllBricks():void
{
for(var i:int=0; i<brickArray.length; i++)
{
var dp:DisplayObject = brickArray[i].userData.sprite as DisplayObject;
if(dp && dp.parent)
dp.parent.removeChild(dp);
}
}
private function reset():void
{
removeAllBricks();
space.clear();
setUp();
}
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();
}
im trying to create a randomized array that will change the position of my pictures(in the tilelist) each time the application is launched. Hope you understand what im looking for, and i dont really understand how to link code correctly here :/
I think its easier simply copying into flash and view from there
thanks :)
Here's my code:
flash.events.MouseEvent;
btn_back.addEventListener(MouseEvent.CLICK, ftilbake);
function ftilbake(evt:MouseEvent)
{
gotoAndStop(1);
}
var heroArray:Array = new Array();
var randomizeArray:Array = new Array();
createArrays()
function createArrays()
{
heroArray[0] = new Array("Rumble","Garen","Lulu","Corki","Warwick");
heroArray[1] = new Array("Bilder/Champions/Rumble.jpg","Bilder/Champions/Garen.jpg","Bilder/Champions/Lulu.jpg","Bilder/Champions/Corki.jpg","Bilder/Champions/Warwick.jpg");
heroArray[2] = new Array("Bilder/Champions/Rumble1.jpg","Bilder/Champions/Garen1.jpg","Bilder/Champions/Lulu1.jpg","Bilder/Champions/Corki1.jpg","Bilder/Champions/Warwick1.jpg");
heroArray[3] = new Array("the Mechanized Menace","the Might of Demacia","the Fae Sorceress","the Daring Bombardier","the Blood Hunter");
heroArray[4] = new Array(0,0,0,0,0);
heroArray[5] = new Array("Rumble.wav","Garen.wav","Lulu.wav","Corki.wav","Warwick.wav");
randomizeArray[0] = new Array();
randomizeArray[1] = new Array();
randomizeArray[2] = new Array();
randomizeArray[3] = new Array();
randomizeArray[4] = new Array();
//randomizing the positions in the array(?)
var randomPos:int = 0;
for (var i:int = 0; i < heroArray.length; i++)
{
randomPos = int(Math.random() * heroArray[0].length);
while (randomizeArray[randomPos][0] != null)
{
randomPos = int(Math.random() * heroArray.length);
}
}
}
var totalKlikk:int = 0;
for (var teller1:int = 0; teller1 <heroArray[0].length; teller1++)
{
leagueChamps.addItem({label:heroArray[0][teller1], source:heroArray[1][teller1]});
}
leagueChamps.columnWidth = 80;
leagueChamps.rowHeight = 80;
leagueChamps.columnCount = 5;
leagueChamps.rowCount = 1;
leagueChamps.direction = "horizontal";
leagueChamps.addEventListener(MouseEvent.CLICK, bildeKlikk);
function bildeKlikk(evt:MouseEvent)
{
var element:Object = leagueChamps.selectedItem;
var fil:String = element.source;
txtChHero.visible = false;
totalKlikk++;
if (totalKlikk <11)
{
for (teller1 = 0; teller1 <heroArray[0].length; teller1++)
{
if (heroArray[1][teller1] == fil)
{
heroArray[4][teller1]++;
if (heroArray[4][teller1] == 1)
{
txtBox1.visible = true;
txtBox2.visible = true;
leagueShow.source = heroArray[2][teller1];
txtBox1.text = heroArray[0][teller1];
txtBox2.text = heroArray[3][teller1];
}
if (heroArray[4][teller1] == 2)
{
txtBox1.visible = true;
txtBox2.visible = true;
leagueShow.source = heroArray[2][teller1];
txtBox1.text = heroArray[0][teller1];
txtBox2.text = heroArray[3][teller1];
heroArray[5][teller1].play();
}
if (heroArray[4][teller1] == 3)
{
bildeKlikk3();
}
}
}
}
else
{
txtChHero.visible = true;
txtChHero.text = "Du har klikket følgende mange ganger på de forskjellige bildene:";
txtH1.text = heroArray[4][0]
txtH2.text = heroArray[4][1]
txtH3.text = heroArray[4][2]
txtH4.text = heroArray[4][3]
txtH5.text = heroArray[4][4]
txtBox1.visible = false;
txtBox2.visible = false;
leagueShow.visible = false;
}
}
function bildeKlikk3()
{
txtBox1.visible = true;
txtBox2.visible = true;
leagueShow.source = heroArray[2][teller1];
txtBox2.text = "Ikke mer informasjon";
}
txtBox2.visible = false;
txtBox1.visible = false;
Array randomization is something which comes up very frequently in all my projects so I ended up creating a static method in my Array utility class for it.
It uses the Fisher–Yates shuffle which is supposed to be the most unbiased (and efficient?) algorithm for shuffling the content of an array. There could be faster ways of doing it (like using the array.sortOn() method, but I am not sure how unbiased a result they get compared to this one.)
The shuffle method:
/**
* shuffle the given array
* #param array
* #return
*/
public static function shuffle(array:Array):Array
{
var index :int;
var item :*;
var limit :int = array.length as int;
for (var i:int = limit-1; i >= 0 ; --i)
{
index = Math.floor(Math.random() * (i + 1));
item = array[index];
array[index] = array[i];
array[i] = item;
}
return array;
}
Example:
var myArray:Array = new Array("Red","Orange","Yellow","Green","Blue");
myArray = ArrayUtils.shuffle(myArray);
where ArrayUtils is the name of the Array Utility class I use. You can simply use the function directly if you don't want to use a utility class of course.
Try this
while (heroArray.length > 0) {
randomizeArray.push(heroArray.splice(Math.round(Math.random() * (heroArray.length - 1)), 1)[0]);
}
Just instatiate randomizeArray though, and don't fill it with empty Arrays like in ur source!
I recommend creating a single object to hold related data, and using a single Array/Vector of that object type.
To answer your question, randomizing an array is fairly easy to do with array.sort() and a random selection function. This method can also be used to randomize any array. you don't need to splice arrays or iterate either.
function sortOnRandom(a:Object, b:Object):Number{
if(Math.random() > 0.5){
return 1;
}else{
return -1;
}
}
myArray.sort(sortOnRandom);
I'd like to cache my spritesheet (tilesheet) into an array. I do this because every spritesheet shall be cached inside of an array so my objects can pull their tiles from them easily. But my cache doesn't seem to work because absolutely nothing gets rendered out of it. I can't see anything.
There is something inside my cache (likely bitmapData) and it is not null so currently I don't know where the problem might be.
Can someone help me out with this issue, please?
this function shall render each tile of an array to a background via copypixels
public function renderCachedTile(canvasBitmapData:BitmapData, tileArray:Array):void
{
tileCache = tileArray;
tileArray = [];
x = nextX;
y = nextY;
point.x = x;
point.y = y;
tileRect.x = tileWidth;
tileRect.y = tileHeight;
if (animationCount >= animationDelay)
{
animationCount = 0;
if(reverse)
{
currentTile--;
if (currentTile < 1)
{
currentTile = tilesLength - 1;
}
} else {
currentTile++;
if (currentTile >= tilesLength - 1)
{
currentTile = 0;
}
}
} else {
animationCount++;
}
canvasBitmapData.lock();
canvasBitmapData.copyPixels(tileCache[currentTile], tileRect, point);
canvasBitmapData.unlock();
}
this function 'separates' my spritesheet into tiles and throws them into an array
private function tileToCache():void {
var tileBitmapData:BitmapData = new BitmapData(tileWidth, tileHeight, true, 0x00000000);
var tilePt:Point = new Point(0, 0);
var tileRect:Rectangle = new Rectangle;
tileCache = [];
for (var tileCtr:int = 0; tileCtr < tilesLength; tileCtr++) {
tileBitmapData.lock();
tileRect.x = int((tileCtr % spritesPerRow)) * tileWidth;
tileRect.y = int((tileCtr / spritesPerRow)) * tileHeight;
tileBitmapData.copyPixels(tileSheet, tileRect, tilePt);
tileBitmapData.unlock();
tileCache.push(tileBitmapData);
}
}
Unless there is code missing from your example, in your tileToCache you instantiate and use tileRect without defining a width and height:
private function tileToCache():void {
var tileRect:Rectangle = new Rectangle;
/* ... */
tileBitmapData.copyPixels(tileSheet, tileRect, tilePt);
If your source was at 0, 0 I presume you would want:
var tileRect:Rectangle = new Rectangle(0, 0, tileWidth, tileHeight);