Need to remove a child using hit test object function - actionscript-3

i am trying to make a function where i drop some seeds into a bucket and the seeds are removed however the function will just be the seeds colliding with the bucket.
I have both of the objects as movieclips and have a basic hitTestObject conditional statement, i have no idea why the feed_mc wont be removed.
if(bucket_mc.hitTestObject(feed_mc))
{
if(stage.contains(feed_mc))
removeChild(feed_mc);
}
thank you in advance
Sorry should have edited here
my code
var Necessities:Array = new Array (Seed, shelter, water);
for(var i:int = 0; i< 10; i++)
{
var pickObjects = Necessities[int(Math.random()* Necessities.length)];
var Objects:MovieClip = new pickObjects();
addChild(Objects);
Objects.x = Math.random() + 600;
Objects.y = Math.random() * stage.stageHeight;
}
stage.addEventListener(Event.ENTER_FRAME, feedHen);
function feedHen(e:Event):void {
if(hen_mc.hitTestObject(Objects))
{
if (Objects.parent)
Objects.parent.removeChild(Objects);
}
}

Seems like
if(feed_mc.parent){
feed_mc.parent.removeChild(feed_mc);
}
should help - if you are not sure what DisplayObjectContainer is parent
edit
I think this should work
var Necessities:Array = new Array (Seed, shelter, water);
//store Objects here
var objectsVector:Vector.<MovieClip> = new Vector.<MovieClip>();
for(var i:int = 0; i< 10; i++){
var pickObjects = Necessities[int(Math.random()* Necessities.length)];
var Objects:MovieClip = new pickObjects();
addChild(Objects);
objectsVector.push(Objects);//add to Vector
Objects.x = Math.random() + 600;
Objects.y = Math.random() * stage.stageHeight;
}
stage.addEventListener(Event.ENTER_FRAME, feedHen);
function feedHen(e:Event):void {
for(var i: int = objectsVector.length - 1; i >= 0; i--){//loop through stored objects
if(hen_mc.hitTestObject(objectsVector[i])){
if (objectsVector[i].parent){
objectsVector[i].parent.removeChild(objectsVector[i]);
objectsVector.splice(i, 1);//remove from storage
}
}
}
}
However I'd suggest checking on some mouse events instead of ENTER_FRAME to reduce number of function calls

Related

AS3 - Array called into a new function... HOW?

Sup everyone, well since my last post as been super fast to fix due to my tired eyes. I'm gonna ask you one more favor...
It's about an Array, so before i had only one "target" showing. So i thought my game was way to simple...
So i decided to add more target that moves, and place with random math...
Well they are correctly placed, but only one is moving. I think is the first one that is being created....
This is my line of code :
// Creating multiple targetwith ADDCHILD and ARRAY at different location //
var arraymc_target:Array = [];
for(var i:int = 1; i<8; i++)
{
var mc_target:target = new target();
mc_target.x = Math.floor(Math.random() * 400);
mc_target.y = Math.floor(Math.random() * 550);
addChild(mc_target);
arraymc_target.push(mc_target);
}
// Creating the TARGETS MOVEMENT //
function goesside_1(event:Event):void {
mc_target.x -= 2;
if (mc_target.x < -20){
mc_target.x = 550;
}
}
mc_target.addEventListener(Event.ENTER_FRAME, goesside_1);
// ----------------------------------------------- //
Your main issue is that in goesside_1, you're moving mc_target which is simply a reference to the last instance of target you created in the loop and pushed to the array.
Another quirk I noticed is that you're adding the ENTER_FRAME listener to one of your targets instead of to the stage.
What you want to do is add the listener to the stage, and then loop over each of the targets in your array:
var arraymc_target:Array = [];
for(var i:int = 1; i<8; i++)
{
var mc_target:target = new target();
mc_target.x = Math.floor(Math.random() * 400);
mc_target.y = Math.floor(Math.random() * 550);
addChild(mc_target);
arraymc_target.push(mc_target);
}
// Creating the TARGETS MOVEMENT //
function goesside_1(event:Event):void {
for each(var mc_target:target in arraymc_target)
{
mc_target.x -= 2;
if (mc_target.x < -20){
mc_target.x = 550;
}
}
}
stage.addEventListener(Event.ENTER_FRAME, goesside_1);

Why doesn't my For loop create more than one object on the screen?

Having a bit of a problem. I'm trying to add 10 items to the stage but it is only adding 1. Any insight on what I'm doing wrong?
public var numCells:Array = [];
public function addCell():void
{
var cell:Cell = new Cell();
var i:int = 0;
cell.x = Math.floor(Math.random() * 1366);
cell.y = Math.floor(Math.random() * 768);
for(var i:int = 0; i < 10; i++)
{
numCells.push(cell);
addChild(cell);
}
return;
}
You are only ever instantiating one cell. calling addChild a second time with the same object passed in doesn't make a copy of that object, it just moves it to the top most 'layer'.
You need to instantiate a new cell inside the for loop. Something like this:
private function addCells():void {
for(var i:int = 0; i < 10; i++){
var cell:Cell = new Cell();
cell.x = Math.floor(Math.random() * 1366);
cell.y = Math.floor(Math.random() * 768);
numCells.push(cell);
addChild(cell);
}
}

Remove unvanted clicks in generated sound in AS3

I am having the following problem when generating sound wave in Flash.
This is the generator part :
const SAMPLING_RATE:int = 44100;
const TWO_PI:Number = 2 * Math.PI;
const TWO_PI_OVER_SR:Number = TWO_PI / SAMPLING_RATE;
const SAMPLE_SIZE:int = 8192 / 4;
function generateSine(fq:Number):ByteArray
{
var bytes:ByteArray = new ByteArray();
var sample:Number;
var amp:Number = 1;
for (var i:int=0; i<SAMPLE_SIZE; i++)
{
sample = amp* Math.sin(i * TWO_PI_OVER_SR * fq );
bytes.writeFloat(sample);
}
bytes.position = 0;
return bytes;
}
and this is the playback part:
function playbackSampleHandler(event:SampleDataEvent):void
{
var sample:Number;
for (var i:int = 0; i < SAMPLE_SIZE && soundData.bytesAvailable; i++)
{
sample = soundData.readFloat();
event.data.writeFloat(sample);
event.data.writeFloat(sample);
}
}
function onClickPlay(e:MouseEvent)
{
soundData= new ByteArray();
var sound:ByteArray= new ByteArray();
sound=generateSine(440);
soundData.writeBytes(sound,0,sound.length);
soundData.position = 0;
morphedSound.addEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler);
soundChannel = morphedSound.play();
}
Quick explanation:
I basically write values for the sine function into the ByteArray and than playback handler reads that array and plays back the sound. I write only one 8192/4 sample buffer.
Problem:
My problem is that when you do this there are annoying clicks on the end of sound, which are the artifacts of sine wave being cut on a value other than 0. So my question is how can I avoid this?
Bonus:
I would also like to know how can I generate for example exactly 100 ms of sine wave when buffers in Flash are so strict i.e. from 2048 to 8192 ?
Links:
If it helps my code is based on this tutorial
http://www.bit-101.com/blog/?p=2669
and my own explorations.
You need to preserve phase of sine wave that occurs at the end of your sample data processing. Otherwise your sine wave is not continued smoothly and you get the clicks you speak of.
var totalSamples:int=0;
function generateSine(fq:Number):ByteArray
{
var bytes:ByteArray = new ByteArray();
var sample:Number;
var amp:Number = 1;
for (var i:int=0; i<SAMPLE_SIZE; i++)
{
sample = amp* Math.sin((i+totalSamples) * TWO_PI_OVER_SR * fq );
// this uses stored phase ^^^
bytes.writeFloat(sample);
}
totalSamples+=SAMPLE_SIZE; // this preserves phase between subsequent samples
bytes.position = 0;
return bytes;
}
Update: I've noticed you are calling generator twice in a row - this is awful. You must never call a function twice if you only need one result of its work.
function onClickPlay(e:MouseEvent)
{
soundData= generateSine(440); // why using writeBytes if we can just use assignment?
soundData.position = 0;
morphedSound.addEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler);
soundChannel = morphedSound.play();
}
Also, to make the sound end with a full (half-)wave of sound and remove the last click you need, use this technique:
function generateSine(fq:Number,cleanFinish:Boolean=false):ByteArray
{
var bytes:ByteArray = new ByteArray();
var sample:Number;
var amp:Number = 1;
for (var i:int=0; i<SAMPLE_SIZE; i++)
{
sample = amp* Math.sin((i+totalSamples) * TWO_PI_OVER_SR * fq );
// this uses stored phase ^^^
bytes.writeFloat(sample);
if (cleanFinish)
if ((Math.abs(sample)<(SAMPLING_RATE/fq/3))&&(i>SAMPLE_SIZE-SAMPLING_RATE/fq)) break;
// this triggers a drop if we are sampling the last wave already
}
totalSamples+=i; // this preserves phase between subsequent samples
bytes.position = 0;
return bytes;
}
Call this function with an optional Boolean parameter set to true to receive correctly terminated wave.
All SAMPLE_SIZE values of "sample" must be split in three pieces:
The first and the third piece must have 250 values each and the middle one
the rest: SAMPLE_SIZE - 500. Make this as follows:
Generate an array of 250 values between 0 and .996 with step .004 :
I mean: .000, .004, .008, ... , .996, and fill with them an array, say, mod[i]
with i from zero to 249.(mod is for modulation...)
Modify initial loop as below and so will result a fade from 0 to (+/-)amp(first 250 values) then the rest of values up to the last 250 remain (+/-)amp and, finally, the last 250 values have a fade from (+/-)amp to 0. The nasty clicks remain...history! I Hope this help.
function generateSine(fq:Number):ByteArray
{
var bytes:ByteArray = new ByteArray();
var sample:Number;
var amp:Number = 1;
for (var i:int=0; i< 250; i++)
{
sample = amp* Math.sin(i * TWO_PI_OVER_SR * fq ) * mod[i];
bytes.writeFloat(sample);
}
for (var i:int=250; i<SAMPLE_SIZE - 250; i++)
{
sample = amp* Math.sin(i * TWO_PI_OVER_SR * fq );
bytes.writeFloat(sample);
}
for (var i:int=SAMPLE_SIZE - 250; i<SAMPLE_SIZE; i++)
{
sample = amp* Math.sin(i * TWO_PI_OVER_SR * fq ) * (.996 - mod[i]);
bytes.writeFloat(sample);
}
bytes.position = 0;
return bytes;
}

how to call objects created in a loop?

Newbie question:
If I create several shape objects in a loop, like:
var i:int;
for (i = 0; i < 3; i++) {
var circle:Shape = new Shape();
circle.graphics.beginFill(color);
circle.graphics.drawCircle(100,100, radius);
circle.graphics.endFill();
addChild(circle);
}
How can I then call those different shapes separately, so I could manipulate their properties? It would seem to me they would all have the same name?
You can access them via their index (the order they have been put on the stage).
So something like:
DisplayObject(getChildAt(1)).x = 100; // Where the 1 is the index (starting at 0)
Actually, you can just have an array (or vector) of objects, so you won't depend on current displaylist.
var i:int;
var circleArray:Array = new Array();
for (i = 0; i < 3; i++) {
var circle:Shape = new Shape();
circleArrayList.push(circle);
circle.graphics.beginFill(color);
circle.graphics.drawCircle(100,100, radius);
circle.graphics.endFill();
addChild(circle);
}
//And then access them with
for(i = 0; i < circleArray.length, i++)
{
circleArrayList[i].x = 15 * i;
}
//Or
foreach(var circle:DisplayObject in circleArray)
{
circle.x = 15 * i;
}
for(int i=0;i<3;i++)
{
class x =new class(i);
x.print()
}

Intermittent/staggered loading of an object

I've just recently tried my hand at actionscript 3 and have come across a road block.
How do I go about rendering the cubes (cube1) intermittently, ie. staggered loading. I need the cubes to load a split second from each other.
Below is a snippet of what I have so far:
var rows:int = 5;
var cols:int = 3;
var spacery:int = 100;
var spacerx:int = 120;
var box_count:int = 8;
for(var i:int; i < box_count; i++) {
cube1 = new Cube(ml,100,10,80,1,1,1);
cube1.y = ((i % rows)) * (cube1.x + spacery);
cube1.x = Math.floor(i/rows) * (cube1.x +spacerx);
cube1.z = 0;
bigBox.addChild(cube1);
}
//Create an array out side the function; as a global (instance) variable:
var cubes:Array = [];
//instead of bigBox.addChild(cube1), store them in the array:
cubes.push(cube1);
//initialize a timer outside after for loop
//Fire every 100 milliseconds, box_count times
var timer:Timer = new Timer(100, box_count);
timer.addEventListener(TimerEvent.TIMER, onTick);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, onTickDone);
function onTick(e:Event):void
{
bigBox.addChild(cubes[timer.currentCount]);
}
function onTickDone(e:Event):void
{
cubes = null;
timer.removeEventListener(TimerEvent.TIMER, onTick);
timer.removeEventListener(TimerEvent.TIMER_COMPLETE, onTickDone);
timer = null;
}