create sine wave audio with as3 - sweep up and down frequency - actionscript-3

I'm making sinewave sound with AS3 using SampleDataEvent. I can make a pure sinewave easily enough, but if i try to sweep through frequencies i get horrible popping. Here's the code i'm using - any help would be great.
package
{
import flash.display.*;
import flash.events.*;
import flash.media.*;
import flash.utils.Timer;
public class DynamicSound extends Sprite
{
private var sound:Sound;
private var noise:Number = 0;
private var f:Number = 1000;
private var v:Number = 1;
private var sweepDown:Boolean = true;
// make the sound
public function DynamicSound():void
{
sound = new Sound();
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onCallback);
sound.play();
sweep();
}
// create the sinewave
private function onCallback(e:SampleDataEvent):void
{
for (var i:int = 0; i < 8192; i++)
{
noise += 1;
var sampleNumber = noise;
e.data.writeFloat(v * Math.sin(sampleNumber * f / 44100));
e.data.writeFloat(v * Math.sin(sampleNumber * f / 44100));
}
}
// sweep up and down frequency
private function sweep() {
var timer:Timer = new Timer(100);
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.start();
function onTimer(event:TimerEvent):void
{
if(sweepDown){
f--;
} else {
f++;
}
if (f <=600 ){
sweepDown = false;
}
if (f >= 1000) {
sweepDown = true;
}
trace(f);
}
}
}
}

I believe the fault is with the approach, the sweep needs to be gradual, when you step it like that you create an abrupt change in the sound wave, which is interpreted as a short high-frequency signal - a pop or click. The way I'd recommend you do this modulation would be inside the callback loop.
set a destination freq (dF) and a current frequency(cF), and instead of doing an abrupt change set cF = cF*0.8 + dF*0.2 inside the loop, this should remove the abrupt change and have it happen over several samples.

//When the frequency changes, the phase will also change.
//By adjusting the phase, there will no longer be horrible popping.
//This will solve the problem:
var f_old:Number = f;
noise=noise*f_old/f; f_old=f;
//Copy/paste in the first frame of the main timeline:
import flash.display.*;
import flash.events.*;
import flash.media.*;
import flash.utils.Timer;
var sound:Sound;
var noise:Number = 0;
var f:Number = 1000;
var v:Number = 1;
var sweepDown:Boolean = true;
var f_old:Number = f;
// make the sound
sound = new Sound();
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onCallback);
sound.play();
sweep();
// create the sinewave
function onCallback(e:SampleDataEvent):void
{
for (var i:int = 0; i < 8192; i++)
{
noise += 1;
var sampleNumber = noise;
e.data.writeFloat(v * Math.sin(sampleNumber * f / 44100));
e.data.writeFloat(v * Math.sin(sampleNumber * f / 44100));
}
}
// sweep up and down frequency
function sweep() {
var timer:Timer = new Timer(100);
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.start();
function onTimer(event:TimerEvent):void
{
if(sweepDown){
f--;
} else {
f++;
}
if (f <=600 ){
sweepDown = false;
}
if (f >= 1000) {
sweepDown = true;
}
trace(f);
//Keep the instantaneous value at the same level:
noise=noise*f_old/f;
f_old=f;
}
}
//Explanation:
//The instantaneous value of the wave must not change at the moment of frequency change.
//In this script the instantaneous value is determined by:
//v * Math.sin(sampleNumber * f / 44100)
//noise = sampleNumber → v * Math.sin(sampleNumber * f / 44100) = v * Math.sin(noise * f / 44100)
//Keep the instantaneous value at the same level:
//v * Math.sin(noise_new * f / 44100) = v * Math.sin(noise* f_old / 44100)
//Cancel out v*Math.sin and /44100 →
//noise_new * f = noise* f_old → noise_new = noise*f_old/f
//Because noise gets a new value, there is no need to give noise the name noise_new. →
//noise = noise*f_old/f

Related

Ball bounce issue in AS3

[edit]
I was really stupid, all is working fine now.
So forget about this dummy question!
The rotation of the main clip was a big mistake.
I've changed this by adding a var called _rota with getter and setters.
I had not to rotate the clip but just to place another Sprite in it, so I can place the sub-Sprite in the right direction by using a simple function.
So I avoid all those loops...
My mistake SRY.
I just added a Sprite which have the rotation of the Main Sprite.
Changing the rotation of the main Sprite was the reason of this issue...
So, thank you and forget about this unclear question!!! :)
private function drawLine():void{
if(!clip){
clip = new Sprite();
addChild(clip);
}
var g:Graphics = clip.graphics;
g.clear();
g.lineStyle(1,0xffffff,1);
g.beginFill(0xffffff,1);
g.drawCircle(Math.sin(rota)*this.width/4,Math.cos(rota)*this.height/4,3);
g.endFill();
}
I was changing the rotation property of the clip, so it was usefulness
Now I have a pretty good result.
Solved...
Sorry again...
As you can see the particles are now set in the right direction an I have no more hitTest issues...
Particles are now moving on the direction showed by the white points.
[/edit]
The first thing that pops out at me is you're potentially modifying the position of both x and y properties twice.
If you run the logic once, and store your directionality, then you should be able to update the position of your ball in one go.
Replace your moveBall function with the following...
private var h:int = 1;
private var v:int = 1;
public function moveBall(e:Event):void {
speedx = Math.sin(deg2rad(rotation+90))*speed;
speedy = Math.cos(deg2rad(rotation+90))*speed;
if (x + radius + (speedx * h) > this.loaderInfo.width || (x + (speedx * h) - radius < 0)) {
h *= -1;
}
if (y + radius + (speedy * v) > this.loaderInfo.height || (y + (speedx * v) - radius < 0)) {
v *= -1;
}
this.x += (speedx * h);
this.y += (speedy * v);
}
As I need to set a Sprite in the right direction when the Ball instance change it's "pseudo rotation" (I avoid here the hitTest features)...
I've now two classes...
Do you thing I'm searching in the bright side of code or is it totally unclear? ;)
This is just a test, and I didn't spent time to code since a few years.
So this test is just to revise some basics about trigonometry...
Don't hesitate, to be rude if I'm wrong!
My new class Main :
package com
{
import com.display.Ball;
import flash.display.Graphics;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
[SWF(width = "400", height = "300", frameRate = "60", backgroundColor = "#dddddd")]
public class Main extends MovieClip
{
private var b1:Ball;
private var b2:Ball;
private var b3:Ball;
private var b4:Ball;
private var b5:Ball;
private var testClip:Sprite;
private const ANGLE_TOP_LEFT:int=135;
private const ANGLE_BOTTOM_LEFT:int=-135;
private const ANGLE_TOP_RIGHT:int=45;
private const ANGLE_BOTTOM_RIGHT:int=-45;
public function Main()
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
trace("stageSize = " + getStageSize() + ", fps = " + stage.frameRate);
drawlineGuides();
addBalls();
stage.addEventListener(Event.RESIZE,onStageResize);
}
private function addBalls():void{
b1 = new Ball(500/2,250/2,10);
addChild(b1);
b1.color = 0x6666cc;
b1.rota = 135;
b1.drawBall();
b1.move(5);
b2 = new Ball(100,100,10);
addChild(b2);
b2.color = 0xff9900;
b2.rota = -110;
b2.drawBall();
b2.move(4);
b3 = new Ball(50,80,10);
addChild(b3);
b3.color = 0xff0000;
b3.rota = 60;
b3.drawBall();
b3.move(3);
b4 = new Ball(75,20,10);
addChild(b4);
b4.color = 0x00aa00;
b4.rota = 10;
b4.drawBall();
b4.move(4);
b5 = new Ball(125,130,10);
addChild(b5);
b5.color = 0x8457a2;
b5.rota = -45;
b5.drawBall();
b5.move(4);
stage.addEventListener(MouseEvent.MOUSE_DOWN,b1.pauseResume);
stage.addEventListener(MouseEvent.MOUSE_DOWN,b2.pauseResume);
stage.addEventListener(MouseEvent.MOUSE_DOWN,b3.pauseResume);
stage.addEventListener(MouseEvent.MOUSE_DOWN,b4.pauseResume);
stage.addEventListener(MouseEvent.MOUSE_DOWN,b5.pauseResume);
}
private function rotate(e:Event):void{
testClip.rotation = b2.rotation-45;
}
private function getStageSize():Point{
var p:Point= new Point(stage.stageWidth,stage.stageHeight);
return p;
}
private function drawlineGuides():void{
var g:Graphics = this.graphics;
g.clear();
g.lineStyle(1,0x000000,1);
g.moveTo(0,stage.stageHeight/2);
g.lineTo(stage.stageWidth,stage.stageHeight/2);
g.moveTo(stage.stageWidth/2,0);
g.lineTo(stage.stageWidth/2,stage.stageHeight);
}
private function onStageResize(e:Event):void{
drawlineGuides();
}
}
}
And here is my new class Ball :
package com.display
{
/* this import is optionnal
if you want to run this class without the BongSound instance
comment all lines where the var bSound is called
*/
//import com.media.sound.BongSound;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.media.Sound;
public class Ball extends Sprite
{
private var _radius:int;
private var _rotation:Number;
private var _color:int;
private var _g:Graphics;
private var _g2:Graphics;
private var _speed:Number;
private var speedx:Number;
private var speedy:Number;
public var rota:Number;
private var smallCircle:Sprite;
private var rendered:Boolean = false;
public var paused:Boolean = false;
private const ZERO:uint = 0;
//private var bSound:BongSound;
/**
* Ball(posx:Number,posy:Number,radius:uint)<br/>
* this constructor create an instance of a bouncing ball<br/>
* the posx and posy must be included in the range of the defined stageWidth and stageHeight!<br/>
* Otherwise, the ball will be placed in the stage range.
*/
public function Ball(posx:Number,posy:Number,radius:uint)
{
//bSound = new BongSound();
smallCircle = new Sprite();
this.addChild(smallCircle);
this._radius = radius;
this.x = posx;
this.y = posy;
_g = this.graphics;
_g2 = smallCircle.graphics;
}
private function checkStageSize():void{
if(this.x + radius + speedx >= this.stage.stageWidth){
this.x = this.stage.stageWidth - this.width;
}
if(this.y + radius + speedy >= this.stage.stageHeight){
this.y = this.stage.stageHeight - this.height;
}
if(this.x - radius + speedx <= ZERO){
this.x = this.width;
}
if(this.y - radius + speedy <= ZERO){
this.y = this.height;
}
}
public function get speed():Number
{
return _speed;
}
public function set speed(value:Number):void
{
_speed = value;
}
public function get color():int
{
return _color;
}
public function set color(value:int):void
{
_color = value;
}
public function get radius():int
{
return _radius;
}
public function set radius(value:int):void
{
_radius = value;
}
/**
* drawBall()<br/>
* this function draws the main Ball Object
*/
public function drawBall():void
{
_g.clear();
_g.lineStyle(1,0x666666,1);
_g.beginFill(_color,1);
_g.drawCircle(0,0,this._radius);
_g.endFill();
_g.lineStyle(1,0x666666,1);
_g.beginFill(0xffffff,1);
_g.endFill();
}
/**
* drawPoint()<br/>
* this function draws the Point Object wich is placed in the direction/rotation of the main Ball instance.
*/
public function drawPoint():void{
_g2.clear();
_g2.lineStyle(1,0x666666,1);
_g2.beginFill(0xffffff,1);
_g2.drawCircle(ZERO, ZERO, this._radius/2);
smallCircle.x = Math.sin(deg2rad(rota+90))*this.radius/2;
smallCircle.y = Math.cos(deg2rad(rota+90))*this.radius/2;
_g2.endFill();
}
/**
* move(speed:Number):void<br/>
* this function set the speed and makes the Ball move.<br/>
* The displace function is called when an ENTER_FRAME event is triggered.
*/
public function move(speed:Number):void{
this.speed = speed;
this.addEventListener(Event.ENTER_FRAME,displace);
}
/**
* getRota():Number<br/>
* this function returns the rotation of the Ball instance.<br/>
* the rotation is returned in degrees.
*/
public function getRota():Number{
return rad2deg(Math.atan2(speedy,speedx));
}
/**
* pauseResume(e:MouseEvent):void
* Pause or resume movement.
*/
public function pauseResume(e:MouseEvent):void{
switch(paused){
case false:
this.removeEventListener(Event.ENTER_FRAME,displace);
paused = true;
break;
case true:
this.addEventListener(Event.ENTER_FRAME,displace);
paused = false;
break;
}
}
/**
* checkBounds():void<br/>
* <p>
* this function plays a Sound when the Ball instance hit the bounds.<br/>
* the rota variable is updated (even if the rotation of the Ball instance don't change).<br/>
* If the stage is resized, a call to checkStageSize() set the positions x & y in the bounds of the Stage.
* </p>
* #see checkStageSize()
*/
private function checkBounds():void{
if(this.x + radius + speedx >= this.stage.stageWidth){
//bSound.play();
rota = rad2deg(Math.atan2(-speedy,-speedx));
}
if(this.y + radius + speedy >= this.stage.stageHeight){
//bSound.play();
rota = rad2deg(Math.atan2(speedy,speedx));
}
if(this.x - radius + speedx <= ZERO){
//bSound.play();
rota = rad2deg(Math.atan2(-speedy,-speedx));
}
if(this.y - radius + speedy <= ZERO){
//bSound.play();
rota = rad2deg(Math.atan2(speedy,speedx));
}
checkStageSize();
}
/**
* <p>
* displace(e:Event):void
* displace the ball and calls drawPoint to place the sub-Sprite depending of the "rotation" of the Ball instance.</p>
* #see #drawPoint()
* #see #checkBounds()
*/
private function displace(e:Event):void{
checkBounds();
speedx = Math.sin(deg2rad(rota+90))*speed;
speedy = Math.cos(deg2rad(rota+90))*speed;
this.x += speedx;
this.y += speedy;
drawPoint();
}
public function deg2rad(value:Number):Number{
return value/180*Math.PI;
}
public function rad2deg(value:Number):Number{
return value*180/Math.PI;
}
}
}
PrintScreens :
It is now possible to continue the moves even when the Stage is Resized avoiding the issues I had in the past...

Error 1180 Call to possibly undefined method Bullet

I have a problem here and I have tried my best to figure out why I'm getting this error on Line 325. Here is the entire script. I'm using Flash CS5.5. Thank you for helping as I'm completely stuck. I changed the names of my movieClips but still the error persists. Thanks again.
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.filters.BlurFilter;
import flash.utils.getTimer;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.system.fscommand;
import flash.text.TextFormat;
import flash.text.TextField;
import flash.display.Graphics;
import flash.display.MovieClip;
import flash.display.SimpleButton;
var loader:Loader = new Loader();
var file:URLRequest = new URLRequest("vermin-ator.swf");
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteLoad);
loader.load(file);
function onCompleteLoad (loadEvent:Event):void
{
addChild(loadEvent.currentTarget.content);
}
// player settings
var _rotateSpeedMax:Number = 20;
//private var _gravity:Number = .68;
// projectile gun settings
var _bulletSpeed:Number = 8;
var _maxDistance:Number = 300;
var _reloadSpeed:Number = 250; //milliseconds
var _barrelLength:Number = 20;
var _bulletSpread:Number = 5;
var score:int = 0;
// gun stuff - do not edit
var _isLoaded:Boolean = true;
var _isFiring:Boolean = false;
var _endX:Number;
var _endY:Number;
var _startX:Number;
var _startY:Number;
var _reloadTimer:Timer;
var _bullets:Array = [];
// array that holds walls
//var _solidObjects:Array = [];
//array for rifle sounds
var mySoundArray:Array = [];
var mySoundRandom:Number;
//game scorings
//var myFormat:TextFormat = new TextFormat();
// myFormat.size = 20;
//var gameScoreField:TextField;
//var gameScore:int;
// gameScore = 0;
// var myText_txt:TextField = new TextField();
// global vars
var player:MovieClip;
//var _player2:MovieClip;
//var _player3:MovieClip;
var _dx:Number;
var _dy:Number;
var _pcos:Number;
var _psin:Number;
var _trueRotation:Number;
var count:Number;
var dougie:MovieClip;
var murphy:MovieClip;
var dougieTalk:MovieClip;
var murphyTalk:MovieClip;
var murphyScream:MovieClip;
var newRabbit:MovieClip;
var tempBullet:MovieClip;
var bullet_mc:MovieClip;
//how much time before another rabbit is made
var rabbitTime:int = 0;
//how much time is needed to make a rabbit
var rabbitLimit:int = 16;
//this movieclip holds the bullets
//var bulletContainer:MovieClip = new MovieClip();
//addChild(bulletContainer)
var soundOn:Boolean = true;
//var myTransform:SoundTransform;
//variable for rifle sound
var rifle1Sound:Sound = new rifle1sound();
//variable for rifle sound
var rifle2Sound:Sound = new rifle2sound();
//variable for rifle sound
var rifle3Sound:Sound = new rifle3sound();
//variable for rifle sound
var rifle4Sound:Sound = new rifle4sound();
//variable for man laughing
//var manLaughSound:Sound = new manlaughsound();
//variable for man laughing
//var manPleasedSound:Sound = new manpleasedsound();
//varible for background sound
var bckgroundSound:Sound = new bckgroundsound();
//varible for rabbit shot sound
//var rabbitSound:Sound = new rabbitsound();
//variable for button sound
var BtnSound:Sound = new buttonSound();
//make screen for Stop invisible
var stopScreen:MovieClip;
//make screen for Credits visible
var creditScreen:MovieClip;
//make screen for Rules visible
var rulesScreen:MovieClip;
murphyTalk.visible = true;
dougieTalk.visible = true;
dougie.visible = true;
murphy.visible = true;
murphyScream.visible = true;
creditScreen.visible = true;
rulesScreen.visible = true;
stopScreen.visible = false;
//enable hand cursors on mouse over over buttons
var movieClip_8:MovieClip;
var movieClip_9:MovieClip;
var movieClip_10:MovieClip;
var movieClip_11:MovieClip;
var newrabbit:MovieClip;
var closeGame:MovieClip;
//listener and function for how to play button
movieClip_10.addEventListener(MouseEvent.MOUSE_DOWN, helpScreen);
function helpScreen(evt:MouseEvent):void {
rulesScreen.visible=true;
}
//listener and function for how to play button
movieClip_9.addEventListener(MouseEvent.MOUSE_DOWN, ahelpScreen);
function ahelpScreen(evt:MouseEvent):void {
creditScreen.visible=true;
}
//Add event listeners for all 3 Over, Out and Down
movieClip_8.addEventListener(MouseEvent.MOUSE_OVER, mOver);
function mOver(e:MouseEvent):void {
murphyTalk.visible = false;
dougieTalk.visible = false;
dougie.visible = false;
murphy.visible = false;
murphyScream.visible= true;
}
movieClip_8.addEventListener(MouseEvent.MOUSE_OUT, mOut);
//Mouse methods
function mOut(e:MouseEvent):void {
murphyScream.visible= false;
removeChild(murphyTalk);
removeChild(dougieTalk);
removeChild(dougie);
removeChild(murphy);
//Remove all listeners
movieClip_8.removeEventListener(MouseEvent.MOUSE_OVER, mOver);
movieClip_8.removeEventListener(MouseEvent.MOUSE_OUT, mOut);
}
/**
* Constructor
*/
//public function Main()
/*recurring event listener for updates
addEventListener(Event.ENTER_FRAME,showGameScore);
function showGameScore() {
gameScoreField.text = "Game: "+String(gameScore);
addChild(gameScoreField); */
movieClip_8.addEventListener(MouseEvent.MOUSE_DOWN, mDown);
function mDown(e:MouseEvent):void {
createPlayer();
// add listeners
stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
stage.addEventListener(MouseEvent.MOUSE_DOWN, `enter code here`onMouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUpHandler);
// add movieclips to solidObjects array
// will test for collisions with bullets
//
// *** movieclips are located on stage in the fla
//_solidObjects = [rabbit01, rabbit02, rabbit03, rabbit04];
//adding enemies to stage
if(rabbitTime < rabbitLimit){
//if time hasn't reached the limit, then just increment
rabbitTime ++;
} else {
//defining a variable which will hold the new enemy
//var newRabbit:MovieClip = new Rabbit();
//making the enemy offstage when it is created
newrabbit.s = -1 * newrabbit.width;
//making the enemy's x coordinates random
//the "int" function will act the same as Math.floor but a bit faster
newrabbit.x = int(Math.random()*(stage.stageWidth - newrabbit.width));
//then add the enemy to stage
addChild(newrabbit);
//and reset the enemyTime
rabbitTime = 0;
}
//////////////////////////////////////
// Player & Weapon Methods
//////////////////////////////////////
/**
* Creates player
* Uses "Player" movieclip linked in library
*/
function createPlayer():void
{
// attach player movieclip from library
player = new Player();
// position player in center
player.x = stage.stageWidth / 2;
//_player.y = stage.stageHeight / 2;
// add to display list
stage.addChild(player);
}
/**
* Reload timer
* #param e Takes TimerEvent
*/
function reloadTimerHandler(e:TimerEvent):void
{
// stop timer
e.target.stop();
// clear timer var
_reloadTimer = null;
reloadWeapon();
}
/**
* Fire weapon
*/
function fire():void
{
// check if firing
if (!_isFiring) return;
// check if reloaded
if (!_isLoaded) return;
// create bullet
createBullet();
// start reload timer
_reloadTimer = new Timer(_reloadSpeed);
_reloadTimer.addEventListener(TimerEvent.TIMER, `enter code here`reloadTimerHandler);
_reloadTimer.start();
// set reload flag to false
_isLoaded = false;
}
/**
* Creates a bullet movieclip and sets it's properties
*/
function createBullet():void
{
// precalculate the cos & sine
_pcos = Math.cos(player.rotation * Math.PI / 180);
_psin = Math.sin(player.rotation * Math.PI / 180);
// start X & Y
// calculate the tip of the barrel
_startX = player.x - _barrelLength * _pcos;
_startY = player.y - _barrelLength * _psin;
// end X & Y
// calculate where the bullet needs to go
// aim 50 pixels in front of the gun
_endX = player.x - 50 * _pcos + Math.random() * _bulletSpread - `enter code here`_bulletSpread * .5;
_endY = player.y - 50 * _psin + Math.random() * _bulletSpread - `enter code here`_bulletSpread * .5;
// attach bullet from library
var tempBullets:MovieClip = new Bullet();
// calculate velocity
tempBullets.vx = (_endX - _startX) / _bulletSpeed;
tempBullets.vy = (_endY - _startY) / _bulletSpeed;
// set position
tempBullets.x = _startX;
tempBullets.y = _startY;
// save starting location
tempBullets.startX = _startX;
tempBullets.startY = _startY;
// set maximum allowed travel distance
tempBullets.maxDistance = _maxDistance;
// add bullet to bullets array
_bullets.push(tempBullets);
// add to display list
stage.addChild(tempBullets);
}
/**
* Updates bullets
*/
function updateBullets():void
{
var i:int;
var tempBullets:MovieClip;
// loop thru _bullets array
for (i = 0; i < _bullets.length; i++)
{
// save a reference to current bullet
tempBullets = _bullets[i];
// check if gravity is enabled
//if (gravityCheckbox.selected)
//{
// add gravity to Y velocity
//tempBullet.vy += _gravity;
}
// update bullet position
tempBullets.x += tempBullets.vx;
tempBullets.y += tempBullets.vy;
// check if bullet went too far
if (getDistance(tempBullets.startX - tempBullets.x, `enter code here`tempBullets.startY - tempBullets.y) > tempBullets.maxDistance + `enter code here`_barrelLength)
{
destroyBullet(tempBullets);
}
// check for collision with walls
if (checkCollisions(tempBullets.x, tempBullets.y))
{
destroyBullet(tempBullets);
}
}
/**
* Destroys bullet
* #param bullet Takes bullet movieclip
*/
function destroyBullet(bullet_mc:MovieClip):void
{
var i:int;
var tempBullets:MovieClip;
// loop thru _bullets array
for (i = 0; i < _bullets.length; i++)
{
// save a reference to current bullet
tempBullets = _bullets[i];
// if found bullet in array
if (tempBullets == bullet_mc)
{
// remove from array
_bullets.splice(i, 1);
// remove from display list
_bullets.removeChild(bullet_mc);
// stop loop
return;
}
}
}
/**
* Reload weapon
*/
function reloadWeapon():void
{
_isLoaded = true;
}
/**
* Checks for collisions between points and objects in _solidObjects
* #return Collision boolean
*/
function checkCollisions(testX:Number, testY:Number):Boolean
{
//var i:int;
var newrabbit:MovieClip;
// loop thru _solidObjects array
//for (i = 0; i < _solidObjects.length; i++)
{
// save a reference to current object
//newRabbit = _solidObjects[i];
// do a hit test
if (newrabbit.hitTestPoint(testX, testY, true))
{
return true;
// stop loop
//break;
}
}
return false;
}
/**checking if Rabbits is touching any bullets
for(var i:int = 0;i<_root.bulletContainer.numChildren;i++){
//numChildren is the amount of movieclips within the bulletContainer.
//we define a variable that will be the bullet that we are currently
//hit testing.
var bulletTarget:MovieClip = _root.bulletContainer.getChildAt(i);
//now we hit test
if(hitTestObject(bulletTarget)){
//remove this from the stage if it touches a bullet
removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
_root.removeChild(this);
//also remove the bullet and its listeners
_root.bulletContainer.removeChild(bulletTarget);
bulletTarget.removeListeners();
}
}*/
/**
* Calculate player rotation
*/
function updateRotation():void
{
// calculate rotation based on mouse X & Y
_dx = player.x - stage.mouseX;
_dy = player.y - stage.mouseY;
// which way to rotate
var rotateTo:Number = getDegrees(getRadians(_dx, _dy));
// keep rotation positive, between 0 and 360 degrees
if (rotateTo > player.rotation + 90) rotateTo -= 180;
if (rotateTo < player.rotation - 90) rotateTo += 180;
// ease rotation
_trueRotation = (rotateTo - player.rotation) / _rotateSpeedMax;
// update rotation
player.rotation += _trueRotation;
}
//////////////////////////////////////
// Event Handlers
//////////////////////////////////////
/**
* Enter Frame handler
* #param event Uses Event
*/
function enterFrameHandler(event:Event):void
{
updateRotation();
updateBullets();
fire();
}
/**
* Mouse Up handler
* #param e Uses MouseEvent
*/
function onMouseUpHandler(event:MouseEvent):void
{
_isFiring = false;
//make bubble for Run Scream invisible
murphyScream.visible = false;
}
/**
* Mouse Down handler
* #param e Uses MouseEvent
*/
function onMouseDownHandler(event:MouseEvent):void
{
_isFiring = true;
//play random rifle sound from an array
var mySoundArray:Array = new Array(rifle1sound, rifle2sound, `enter code here`rifle3sound, rifle4sound);
`enter code here`mySoundArray[Math.floor(Math.random()*mySoundArray.length)].play();
}
//////////////////////////////////////
// Utilities
//////////////////////////////////////
/**
* Get distance
* #param delta_x
* #param delta_y
* #return
*/
function getDistance(delta_x:Number, delta_y:Number):Number
{
return Math.sqrt((delta_x*delta_x)+(delta_y*delta_y));
}
/**
* Get radians
* #param delta_x
* #param delta_y
* #return
*/
function getRadians(delta_x:Number, delta_y:Number):Number
{
var r:Number = Math.atan2(delta_y, delta_x);
if (delta_y < 0)
{
r += (2 * Math.PI);
}
return r;
}
/**
* Get degrees
* #param radians Takes radians
* #return Returns degrees
*/
function getDegrees(radians:Number):Number
{
return Math.floor(radians/(Math.PI/180));
}
movieClip_8.removeEventListener(MouseEvent.MOUSE_DOWN, mDown);
}
//listener and function for how to play button
movieClip_11.addEventListener(MouseEvent.MOUSE_DOWN, bhelpScreen);
function bhelpScreen(evt:MouseEvent):void {
stopScreen.visible=true;
}
closeGame.addEventListener(MouseEvent.MOUSE_DOWN, closeApp);
function closeApp(event:MouseEvent):void {
fscommand("quit");
}
Check that Bullet is also the class name on the library.

how to make Astar pathfinding can used by multi enemy?

i have learn A star pathfinding from "AdvancED_ActionScript_Animation" e-book:
List item
i make node class, Node.as .
i make grid class, Grid.as .
i make AStar class, AStar.as .
and the main clas, Game.as .
A-star Pathfinding is work, but just 1 player.
how to make it work in multi player?
spoiler
4.Game.as :
package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
public class Game extends Sprite
{
private var _cellSize:int = 30;
private var _grid:Grid;
private var _player:Sprite;
private var _index:int;
private var _path:Array;
public function Game()
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
makePlayer();
makeGrid();
stage.addEventListener(MouseEvent.CLICK, onGridClick);
}
private function makePlayer():void
{
_player =new Sprite();
_player.graphics.beginFill(0x336633);
_player.graphics.drawCircle(0,0,5);
_player.graphics.endFill();
_player.x = Math.random() * 100;
_player.y = Math.random() * 100;
addChild(_player);
}
private function makeGrid():void
{
_grid = new Grid(10,10);
for (var i:int =0; i < 10; i++)
{
_grid.setWalkable(Math.floor(Math.random()*10),
Math.floor(Math.random()*10),false);
}
drawGrid();
}
private function drawGrid():void
{
graphics.clear();
for (var i:int =0; i < _grid.numCols; i++)
{
for (var j:int =0; j<_grid.numRows; j++)
{
var node:Node = _grid.getNode(i,j);
graphics.lineStyle(0);
graphics.beginFill(getColor(node));
graphics.drawRect(i *_cellSize,
j*_cellSize,_cellSize,
_cellSize);
}
}
}
private function getColor(node:Node):uint
{
if (! node.walkable)
{
return 0;
}
if (node == _grid.startNode)
{
return 0xcccccc;
}
if (node == _grid.endNode)
{
return 0xcccccc;
}
return 0xffffff;
}
private function onGridClick(event:MouseEvent):void
{
var xpos:int =Math.floor(mouseX/_cellSize);
var ypos:int =Math.floor(mouseY/_cellSize);
_grid.setEndNode(xpos,ypos);
xpos = Math.floor(_player.x / _cellSize);
ypos = Math.floor(_player.y / _cellSize);
_grid.setStartNode(xpos,ypos);
drawGrid();
findPath();
}
private function findPath():void
{
var astar:AStar = new AStar();
if (astar.findPath(_grid))
{
_path = astar.path;
_index = 0;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
}
private function onEnterFrame(event:Event):void
{
var targetX:Number = _path[_index].x * _cellSize
+ _cellSize / 2;
var targetY:Number = _path[_index].y * _cellSize
+ _cellSize / 2;
var dx:Number = targetX - _player.x;
var dy:Number = targetY - _player.y;
var dx2:Number = targetX - _box.x;
var dy2:Number = targetY - _box.y;
var dist2:Number =Math.sqrt(dx2*dx2+dy2+dy2);
var dist:Number =Math.sqrt(dx*dx+dy+dy);
if (dist<1)
{
_index++;
if (_index >= _path.length)
{
removeEventListener(Event.ENTER_FRAME,onEnterFrame);
}
}
else
{
_player.x += dx * .5;
_player.y += dy * .5;
}
}
}
}
I am not going to go the extra mile and code this for you. (Anyone else can feel free to do that)
What you need to do is create a function that accepts a start node and end node, and returns the path. Something like this :
public function getPath(starNode:Point, endNode:Point):Array
{
// get your path by utilizing the astar instance
// return that path array
// note that I have used Points to store the x,y location
// you'll need to apply those values to the grid before your astar call
// using the setStarNode and setEndNode methods of the grid instance
}
Then you can modify the code that is used in your enterFrame, to utilize an array containing path data for any player/enemy you want.
For example you might have a function you call for each entity such as :
public function followPath(entity:MovieClip, pathData:Array, pathIndex:int):void
{
// your modified code from onEnterFrame
// replace _player variable with entity
// replace _path variable with pathData
// replace _index with pathIndex
}
If you understand OOP well enough, you might want to create a class for your player/enemy entities that has properties for pathData and pathIndex. If you do that, than you can just call an update method that will update their movement each frame using the pathData and pathIndex properties of that instance.
This is a basic approach you could use to accomplish your goal.

AS3 playback of sound byte array doesn't begin at the start

I'm currently recording and storing a ByteArray of sound and then playing it back. But for some reason the playback starting position of the ByteArray is 163840, not 0 as I need it to be.
Would anyone have any ideas why this might be happening?
Thanks,
Mark
var soundBA:ByteArray = new ByteArray();
var sound:Sound = new Sound();
var ch:SoundChannel = new SoundChannel();
var recordingsArray:Array = new Array();
//imagine I have successfully recorded and stored the sound into recordingsArray
soundBA.clear();
soundBA.length = 0;
//I collect the recorded byteArray within an array
soundBA.writeBytes(recordingsArray[0]);
soundBA.position = 0;
trace("Start POS "+soundBA.position); //traces 0
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, sound_sampleDataHandler, false, 0, true);
ch=sound.play();
this.addEventListener(Event.ENTER_FRAME, updateSeek, false, 0, true);
public function updateSeek(event:Event):void {
trace("current Pos "+soundBA.position); //the first trace event is "current Pos 163840"
}
function sound_sampleDataHandler(event:SampleDataEvent):void {
for (var i:int = 0; i < 8192; i++)
{
if (soundBA.bytesAvailable < 4)
{
break;
}
var sample:Number = soundBA.readFloat();
event.data.writeFloat(sample);
event.data.writeFloat(sample);
}
}
This is because soundBA.position is position in byte array, not position of playback. It runs ahead of playback position because of sound lag. To determine current playback position use SoundChannel.position:
public function updateSeek(event:Event):void {
trace("current pos in ms: " + ch.position);
trace("current pos in bytes: " + (ch.position * 44.1 * 4 * 2));
trace("current pos in %: " + (100 * ch.position / sound.length));
}
UPD: I was referring to the case when sound is decoded using additional Sound object, e.g.:
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.SampleDataEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.net.URLRequest;
import flash.utils.ByteArray;
public class SoundTest extends Sprite
{
private var soundSrc:Sound;
private var soundPlayer:Sound;
private var soundData:ByteArray;
private var soundChannel:SoundChannel;
public function SoundTest()
{
soundSrc = new Sound();
soundSrc.addEventListener(Event.COMPLETE, startPlayback);
soundSrc.load(new URLRequest("sound.mp3"));
}
private function startPlayback(e:Event = null):void
{
soundData = new ByteArray();
soundSrc.extract(soundData, soundSrc.length * 44.1, 0);
soundData.position = 0;
soundPlayer = new Sound();
soundPlayer.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
soundChannel = soundPlayer.play();
addEventListener(Event.ENTER_FRAME, updateTime);
}
private function onSampleData(e:SampleDataEvent):void
{
for (var i:int = 0; i < 8192; i++)
{
if (soundData.bytesAvailable < 4)
{
break;
}
var sampleL:Number = soundData.readFloat();
var sampleR:Number = soundData.readFloat();
e.data.writeFloat(sampleL);
e.data.writeFloat(sampleR);
}
}
private function updateTime(e:Event):void
{
trace("current pos in ms: " + soundChannel.position);
trace("current pos in bytes: " + (soundChannel.position * 44.1 * 4 * 2));
trace("current pos in % (method 1): " + (100 * soundChannel.position / soundSrc.length));
// it also works
trace("current pos in % (method 2): " + (100 * soundChannel.position / (soundData.length / (44.1 * 4 * 2))));
}
}
}

ActionScript - Ignoring Passed Arguments?

i've been studying this code example for Rung-Kutta physics but i don't understand what is happening with the acceleration(p:Point, v:Point):Point function. the function accepts 2 point objects as required arguments but doesn't use them in the function while simply returning a new point.
i'm unfamiliar with this style of argument passing. can someone explain the significance of this function to me?
the source is from Keith Peters' book Advanced ActionScript 3.0 Animation, Chapter 6 - Advanced Physics, page 246.
package {
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.Point;
import flash.utils.getTimer;
public class RK2 extends Sprite
{
private var _ball:Sprite;
private var _position:Point;
private var _velocity:Point;
private var _gravity:Number = 32;
private var _bounce:Number = -0.6;
private var _oldTime:int;
private var _pixelsPerFoot:Number = 10;
public function RK2()
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
_ball = new Sprite();
_ball.graphics.beginFill(0xff0000);
_ball.graphics.drawCircle(0, 0, 20);
_ball.graphics.endFill();
_ball.x = 50;
_ball.y = 50;
addChild(_ball);
_velocity = new Point(10, 0);
_position = new Point(_ball.x / _pixelsPerFoot, _ball.y / _pixelsPerFoot);
_oldTime = getTimer();
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(event:Event):void
{
var time:int = getTimer();
var elapsed:Number = (time - _oldTime) / 1000;
_oldTime = time;
var accel1:Point = acceleration(_position, _velocity);
var position2:Point = new Point();
position2.x = _position.x + _velocity.x * elapsed;
position2.y = _position.y + _velocity.y * elapsed;
var velocity2:Point = new Point();
velocity2.x = _velocity.x + accel1.x * elapsed;
velocity2.y = _velocity.y + accel1.x * elapsed;
var accel2:Point = acceleration(position2, velocity2);
_position.x += (_velocity.x + velocity2.x) / 2 * elapsed;
_position.y += (_velocity.y + velocity2.y) / 2 * elapsed;
_velocity.x += (accel1.x + accel2.x) / 2 * elapsed;
_velocity.y += (accel1.y + accel2.y) / 2 * elapsed;
if(_position.y > (stage.stageHeight - 20) / _pixelsPerFoot)
{
_position.y = (stage.stageHeight - 20) / _pixelsPerFoot;
_velocity.y *= _bounce;
}
if(_position.x > (stage.stageWidth - 20) / _pixelsPerFoot)
{
_position.x = (stage.stageWidth - 20) / _pixelsPerFoot;
_velocity.x *= _bounce
}
else if(_position.x < 20 / _pixelsPerFoot)
{
_position.x = 20 / _pixelsPerFoot;
_velocity.x *= _bounce;
}
_ball.x = _position.x * _pixelsPerFoot;
_ball.y = _position.y * _pixelsPerFoot;
}
private function acceleration(p:Point, v:Point):Point
{
return new Point(0, _gravity);
}
}
}
I think the author may be using the method acceleration as a place holder, perhaps for updates on a subsequent chapter.
Of course as it is right now, the acceleration method could be rewritten as
private function acceleration(...rest):Point {
return new Point(0, _gravity);
}
Or the arguments could be removed completely (though that would require the places where the method is called to be updated to not contain any arguments.)
This isn't a style of programming per se, but, I have seen this type of placeholder code put into books before.
You also could set the arguments with a null as default, so they are optional.
private function acceleration(p:Point = null, v:Point = null):Point
{
return new Point(0, _gravity);
}