AS3 - Move Array objects relative to angle - arrays

I am creating a game where i need to move ships at a set speed towards the angle they are facing. I have used this code to move singular ships elsewhere in the game but i assume having them in an array has complicated things.
Any help would be appreciated.
var ship1 = this.addChild(new Ship());
var ship2 = this.addChild(new Ship());
var ship3 = this.addChild(new Ship());
var ship4 = this.addChild(new Ship());
var shipSpeed1 = 10;
var shipArray: Array = [];
shipArray.push(ship1, ship2, ship3, ship4);
for (var i: int = 0; i < shipArray.length; i++) {
var randomX: Number = Math.random() * stage.stageHeight;
var randomY: Number = Math.random() * stage.stageHeight;
shipArray[i].x = randomX;
shipArray[i].y = randomY;
shipArray[i].rotation = 90;
shipArray[i].x += Math.sin(shipArray[i].rotation * (Math.PI / 180)) * shipSpeed1;
shipArray[i].y -= Math.cos(shipArray[i].rotation * (Math.PI / 180)) * shipSpeed1;
}
I've also included this within the same function, but i cant get this to work either. Once again i have had this working
if (shipArray[i].x < 0) { //This allows the boat to leave the scene and
enter on the other side.
shipArray[i].x = 750;
}
if (shipArray[i].x > 750) {
shipArray[i].x = 0;
}
if (shipArray[i].y < 0) {
shipArray[i].y = 600;
}
if (shipArray[i].y > 600) {
shipArray[i].y = 0;
}

First, you need to separate your code into a spawn / initialization phase and an update phase.
Something like the following:
var shipArray: Array = [];
//spawn and set initial values (first phase)
//spawn 4 new ships
var i:int;
for(i=0;i<4;i++){
//instantiate the new ship
var ship:Ship = new Ship();
//add it to the array
shipArray.push(ship);
//set it's initial x/y value
ship.x = Math.random() * (stage.stageWidth - ship.width);
ship.y = Math.random() * (stage.stageHeight - ship.height);
//set it's initial rotation
ship.rotation = Math.round(Math.random() * 360);
//set the ships speed (dynamic property)
ship.speed = 10;
//add the new ship to the display
addChild(ship);
}
//NEXT, add an enter frame listener that runs an update function every frame tick of the application
this.addEventListener(Event.ENTER_FRAME, gameUpdate);
function gameUpdate(e:Event):void {
//loop through each ship in the array
for (var i: int = 0; i < shipArray.length; i++) {
//move it the direction it's rotated, the amount of it's speed property
shipArray[i].x += Math.sin(shipArray[i].rotation * (Math.PI / 180)) * shipArray[i].speed;
shipArray[i].y -= Math.cos(shipArray[i].rotation * (Math.PI / 180)) * shipArray[i].speed;
}
}

Related

Scrolling through an array

So I have a project in GameMaker, which has a chatbox. The messages for this are stored in an array. I would like to be able to scroll through this array, so I can view earlier chat messages.
This is what I currently have:
Create Event
chatLog[0] = "";
chatIndex = 0;
Step Event
if (chatIndex > 0) {
if (mouse_wheel_down()) {
chatIndex--;
}
}
if (chatIndex < array_length_1d(chatLog) - 1) {
if (mouse_wheel_up()) {
chatIndex++;
}
}
var _maxLines = 5;
for (i = 0; i < _maxLines; i++) {
if (i > (array_length_1d(chatLog) - 1)) { exit; }
var _chatLength = array_length_1d(chatLog) - 1;
draw_text(0, 50 - chatHeight, chatLog[_chatLength - i + chatIndex]);
}
First, for convenience of being able to add messages to front / remove them from the back (once there are too many), let's suppose that the log is a list, item 0 being the newest message,
chatLog = ds_list_create();
chatIndex = 0;
for (var i = 1; i <= 15; i++) {
ds_list_insert(chatLog, 0, "message " + string(i));
}
then, the Step Draw event can use information from the list to clamp scroll offset range and draw items:
var maxLines = 5;
// scrolling:
var dz = (mouse_wheel_up() - mouse_wheel_down()) * 3;
if (dz != 0) {
chatIndex = clamp(chatIndex + dz, 0, ds_list_size(chatLog) - maxLines);
}
// drawing:
var i = chatIndex;
var _x = 40;
var _y = 200;
repeat (maxLines) {
var m = chatLog[|i++];
if (m == undefined) break; // reached the end of the list
draw_text(_x, _y, m);
_y -= string_height(m); // draw the next item above the current one
}
live demo

My for loop won't display my object, but no errors show up

For some reason my for loop isn't working, the enemies won't spawn and nothing appears in the Output when I used trace. However, there also is no error, so I'm wondering what the issue is.
Here is my code:
var playerX = 0;
var playerY = 0;
var mapWidth = 5000;
var mapHeight = 5000;
//enemy
var myEnemies:Array = new Array();
var enemySprite:Sprite;
var Enemy:enemy;
var enemyCount:int = 0;
//event listeners
stage.addEventListener(Event.ENTER_FRAME, spawnEnemies);
//spawn enemies
function spawnEnemies(spawn:Event) {
if (enemyCount < 20) {
for (var i = 0; i < myEnemies.length; i++) {
enemySprite = new Sprite();
this.addChild(enemySprite);
Enemy = new enemy();
Enemy.x = (Math.random() * this.width);
Enemy.y = (Math.random() * this.height);
enemySprite.addChild(Enemy);
enemyCount++;
myEnemies[enemyCount] = enemySprite;
trace(myEnemies.length);
}
stage.addEventListener(Event.ENTER_FRAME, moveEnemy);
}
}
//move the enemies
function moveEnemy(enemyMovement:Event){
for (var k = 0; k < myEnemies.length; k++) {
trace("move enemy");
if (myEnemies[k].y > playerY) {
myEnemies[k].y -= 1;
myEnemies[k].rotation = 0;
}
else if (myEnemies[k].x < playerX) {
myEnemies[k].x += 1;
myEnemies[k].rotation = 90;
}
else if (myEnemies[k].y < playerY) {
myEnemies[k].y += 1;
myEnemies[k].rotation = 180;
}
else {
myEnemies[k].x -= 1;
myEnemies[k].rotation = 270;
}
}
}
Thank you for your help!
OK, I did not work with AS3 for a long time, but... Why do you expect new enemies to be created if myEnemies length is 0?
Also, you created two different ENTER_FRAME functions and there is no need to do that. Create only one function and call it for exmaple update:
private function update(e:event)
{
}
stage.addEventListener(Event.ENTER_FRAME, update);
You should not create new sprites using for loop inside ENTER_FRAME function, because this function runs 30 or more times in a second.
Create for loop inside "init" or "create" function, unless you want to update code on each frame.
Add 10 enemies:
for (var i = 0; i < 10; i++) {
Enemy = new enemy();
Enemy.x = (Math.random() * this.width);
Enemy.y = (Math.random() * this.height);
this.addChild(Enemy);
// add it to array
myEnemies.push(Enemy);
}
You cannot use myEnemies to create new Enemy sprite because it's empty, so you create 0 enemies. If you want to create 10 enemies use this code, or simple change number 10 to any number you want.

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

Arrays and MovieClips

i stored some mc's in an array.
Now I want to assign coordinates to the mc's in the array in order to put these mc's on the sage at a certain position.
How can I do that?
Thank you for your time
Iterate through your Array of MovieClips using for each()
for each(var i:MovieClip in YOUR_ARRAY)
{
i.x = 17;
i.y = 100;
}
To randomize the positions of the MovieClips:
var min_x:Number = 0;
var max_x:Number = 550;
var min_y:Number = 0;
var max_y:Number = 400;
for each(var i:MovieClip in YOUR_ARRAY)
{
i.x = Math.random() * (max_x-min_x) + min_x;
i.y = Math.random() * (max_y-min_y) + min_y;
}
This can be optimized a bit:
var min_x:Number = 0;
var max_x:Number = 550;
var min_y:Number = 0;
var max_y:Number = 400;
var n:uint = YOUR_ARRAY.length;
for (var i:uint = 0; i < n; i++)
{
var mc:MovieClip = YOUR_ARRAY[i];
mc.x = Math.random() * (max_x-min_x) + min_x;
mc.y = Math.random() * (max_y-min_y) + min_y;
}

Objects stuck at top of stage and won't fall down

I am using math.random to randomly drop objects from the top of the stage. I had it working with one object. But as I wanted to increase the number to 6 objects, I added the following code: But I am "stuck" and so are the 6 objects at the top of the stage. What am I doing wrong here? I appreciate the help.
private function bombInit(): void {
roachBombArray = new Array();
for (var i:uint =0; i < numBombs; i++) {
roachBomb= new RoachBomb();
roachBomb.x = Math.random() * stage.stageWidth;
roachBomb.vy = Math.random() * 2 -1;
roachBomb.y = -10;
addChild(roachBomb);
roachBombArray.push(roachBomb);
}
addEventListener(Event.ENTER_FRAME, onEntry);
}
private function onEntry(event:Event):void {
for (var i:uint = 0; i< numBombs; i++) {
var roachBomb = roachBombArray[i];
vy += ay;
roachBombArray[i] += vy;
if (roachBombArray[i] > 620) {
removeChild(roachBombArray[i]);
removeEventListener(Event.ENTER_FRAME, onEntry);
You are trying to add the velocity to the RoachBomb rather than to the RoachBomb y position.
roachBombArray[i] += vy;
should be
roachBombArray[i].y += vy;
Additionally you create a local variable:
var roachBomb = roachBombArray[i];
but you never manipulate it.
Perhaps you meant to do something like this?
var roachBomb:RoachBomb = roachBombArray[i]; // I added the type to the local variable
roachBomb.vy += ay;
roachBomb.y += vy; // Manipulate the local variable
if (roachBomb.y > 620) {
removeChild(roachBomb);
}
You're removing your enterFrame listener when the first bomb goes off the bottom, at which point you're no longer listening for ENTER_FRAME events and updating any of your bombs.
You don't want to remove this listener until you're done animating ALL the bombs.
UPDATE: How I would expect things to look, incorperating Ethan's observation that you ought to use the local roachBomb that you declare...
public class BombDropper extends Sprite {
private static const GRAVITY:int = 1; // Set gravity to what you want in pixels/frame^2
private static const BOTTOM_OF_SCREEN:int = 620;
private var numBombs:int = 6;
private var roachBombArray:Array;
// ... constructor and other class stuff here
private function bombInit(): void
{
roachBombArray = new Array();
for (var i:int =0; i < numBombs; ++i)
{
var roachBomb:RoachBomb = new RoachBomb();
roachBomb.x = Math.random() * stage.stageWidth;
roachBomb.vy = Math.random() * 2 -1;
roachBomb.y = -10;
this.addChild(roachBomb);
roachBombArray.push(roachBomb);
}
this.addEventListener(Event.ENTER_FRAME, onEntry);
}
private function onEntry(event:Event):void
{
for each ( var roachBomb:RoachBomb in roachBombArray)
{
roachBomb.vy += GRAVITY;
roachBomb.y += vy;
if (roachBomb.y > BOTTOM_OF_SCREEN)
{
this.removeChild(roachBomb);
roachBombArray.splice(roachBombArray.indexOf(roachBomb),1);
if (roachBombArray.length == 0)
{
this.removeEventListener(Event.ENTER_FRAME, onEntry);
}
}
}
}
}

Resources