I've edited the following code in order to let those green rectangles to follow my cursor which is customized by a small rectangle. But I've encountered several problems:
Although I haven't defined any coordinate in the separate class, but the size is abviously wrong in the stage when publish with only half size for the cursor coordinate.
The reset button cannot be activated, although I've tested well in the other code.
Here is the work I've published: http://neowudesign.com/hwu_ex04.html
The code on timeline
//hw//Creating a new cursor
newcursor.startDrag ("true");
Mouse.hide();
//hw//Creating a holder to hold the butterfly objects
var mothHolder = new Sprite();
addChild(mothHolder);
//hw//Creating seven moths at the beginning
makeMoths(7);
//hw//creating a function which can generate limited numbers of moths.
function makeMoths(MothsNumber:Number)
{
for (var i = 0; i < MothsNumber; i++)
{
newMoth = new Moth();
mothHolder.addChild(newMoth);
}
}
//hw//Set the reset button at the top for clicking, but it's failed to work;
//hw//Set the cursor back to the default one, and remove the custom one when hovering;
mothHolder.setChildIndex(reset,mothHolder.numChildren);
reset.addEventListener(MouseEvent.MOUSE_OVER, cursorchange);
function cursorchange(event:MouseEvent):void
{
Mouse.show();
newcursor.visible = false;
trace("alert!!");
}
//hw//creating a function of reset
reset.addEventListener(MouseEvent.CLICK, resetClick, false, 0, true);
function resetClick(evt:MouseEvent):void
{
removeChild(mothHolder);
mothHolder = new MovieClip();
addChild(mothHolder);
var numMoths:Number = Math.round(Math.random() * 6) + 1;
trace("Moths Numeber: "+ numMoths);
makeButterflies(numButterflies);
}
//hw//when the cursor leave the reset region, it turns back to the customized one
reset.addEventListener(MouseEvent.MOUSE_OUT, fl_MouseOutHandler);
function fl_MouseOutHandler(event:MouseEvent):void
{
removeEventListener(MouseEvent.MOUSE_OVER, cursorchange);
Mouse.hide();
newcursor.visible = true;
}
And the code for class "Moth" separately named "angle.as"
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.geom.Point;
public class angle extends MovieClip {
var speed:Number = 8;
function angle() {
//letting every moth follow the moving of the cursor
addEventListener(Event.ENTER_FRAME,mothMove);
function mothMove(myEvent:Event) {
trace(mouseX);
trace(mouseY);
var angle:Number = Math.atan2(mouseY - y, mouseX - x);
x += Math.cos( angle ) * speed;
y += Math.sin( angle ) * speed;
}
}
}
}
Related
I need to test the collision between 2 movie clips, using air for android action script 3.
Its a collision between an object and several obstacles.
My structure is the following :
The base FLA file, is linked to Action Script file called baseCode.as.
In this AS file, i create the obsctacles, using the following code :
baseCode.as :
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.geom.Point;
import Mc_MC; // Not strictly needed
public class baseCode extends flash.display.MovieClip
{
//private static var SYMBOLS:Array = new Array(MySymbol1, MySymbol2);
public var t:int = 0;
public function baseCode()
{
// Create five symbols:
for (var i:int = 0; i < 5; i++) {
trace(i);
makeSymbol();
}
}
function randomRange(minNum:Number, maxNum:Number):Number
{
return (Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum);
}
public function makeSymbol():void
{
trace("IT entered makeSymbol");
// Pick a random symbol from the array:
// var symType:Class = SYMBOLS[0];
//trace(SYMBOLS[Math.random() * SYMBOLS.length]);
// Construct the new symbol:
//var Positi : Number = new Number(Math.random);
var loc:Point = new Point(randomRange(100,stage.stage.height),0);
var loc2:Point = new Point(randomRange(110,stage.stage.height),0);
//var loc:Point = new Point(10*randomRange(15, stage.width),100*randomRange(10 , stage.width));
trace("this is the starting point" , loc);
var sym:Mc_MC = new Mc_MC(1 + Math.random() *10, loc);
if( t % 2 == 0 ){
var sym2:Mc_MC2 = new Mc_MC2(15 + Math.random() *10, loc);
// Listen for the object hitting the left edge:
//sym2.addEventListener(Event.COMPLETE, remakeObject);
this.addChild(sym2);
}
sym.addEventListener(Event.COMPLETE, remakeObject);
this.addChild(sym);
t ++;
}
public function remakeObject(e:Event):void
{
e.target.removeEventListener(Event.COMPLETE, remakeObject);
//e.removeChild(sym);
//e.parent.removeChild(this.child);
// removeChild(this);
// this.removeChild(sym);
// Replace the dead symbol:
makeSymbol();
}
}
}
Mc_MC and Mc_MC2 are two Action Script file in which the obstacles are called :
Mc_MC.as :
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.geom.*;
import flash.display.Screen;
import flash.system.Capabilities;
public class Mc_MC extends MovieClip
{
public var speed:Number; // Pixels moved per frame
var valuee:baseCode;
public function Mc_MC(speed:Number, startPosition:Point)
{
this.speed = speed;
this.addEventListener(Event.ENTER_FRAME, update);
this.x = startPosition.x;
this.y = startPosition.y;
}
public function update(speed:Number)
{
var screenWidth:Number = Capabilities.screenResolutionX;
var screenHeight:Number = Capabilities.screenResolutionY;
trace("this.y" , this.y);
trace("this is the stage height" , screenHeight);
trace("this.speed" , this.speed);
if (this.y >= screenHeight - 100) { // We're at the left edge
trace("Entered if");
trace("new Starting Pos" , this.y);
this.y = stage.height;
parent.removeChild(this);
this.removeEventListener(Event.ENTER_FRAME, update);
this.dispatchEvent(new Event(Event.COMPLETE));
}
else this.y += this.speed;
}
}
}
In the base FLA file, i create the main object that will collide with all the obstacles created using Mc_MC and Mc_MC2. I create it using the following code :
Home.fla
import flash.events.*
//import flash.events.EventDispatcher.addEventListener()
import flash.display.DisplayObject;
//import flash.events.MouseEvent;
import flashx.textLayout.events.UpdateCompleteEvent;
import flash.display.MovieClip;
var offsetX:Number;
var offsetY:Number;
//var draggedObject:DisplayObject;
var my_obj:OriginalObject = new OriginalObject();
//left.addEventListener(MouseEvent.MOUSE_MOVE, drag);
//The speed of the scroll movement.
var scrollSpeed:uint = 2;
//This adds two instances of the movie clip onto the stage.
var s1:ScrollBg = new ScrollBg();
var s2:ScrollBg = new ScrollBg();
left.addEventListener(MouseEvent.MOUSE_DOWN,mouseDown);
function mouseDown(e:MouseEvent):void {
stage.addEventListener(MouseEvent.MOUSE_UP,mouseUp); //listen for mouse up on the stage, in case the finger/mouse moved off of the button accidentally when they release.
addEventListener(Event.ENTER_FRAME,myButtonClick); //while the mouse is down, run the tick function once every frame as per the project frame rate
}
function mouseUp(e:MouseEvent):void {
removeEventListener(Event.ENTER_FRAME,myButtonClick); //stop running the tick function every frame now that the mouse is up
stage.removeEventListener(MouseEvent.MOUSE_UP,mouseUp); //remove the listener for mouse up
}
right.addEventListener(MouseEvent.MOUSE_DOWN,mouseDown2);
function mouseDown2(e:MouseEvent):void {
stage.addEventListener(MouseEvent.MOUSE_UP,mouseUp2); //listen for mouse up on the stage, in case the finger/mouse moved off of the button accidentally when they release.
addEventListener(Event.ENTER_FRAME,stopDragging); //while the mouse is down, run the tick function once every frame as per the project frame rate
}
function mouseUp2(e:MouseEvent):void {
removeEventListener(Event.ENTER_FRAME,stopDragging); //stop running the tick function every frame now that the mouse is up
stage.removeEventListener(MouseEvent.MOUSE_UP,mouseUp2); //remove the listener for mouse up
}
my_obj.x = stage.width / 2;
my_obj.y = stage.height - (stage.height / 3 );
stage.addChild(my_obj);
function myButtonClick(ev:Event):void
{
trace("UPPP");
if(my_obj.x > (my_obj.width*2)){
my_obj.x = my_obj.x - 10;
trace("In the limit");
}
else {
trace("out of bounds");
}
trace("myButton has been clicked.");
}
//// This function is called when the mouse button is released.
function stopDragging(ev2:Event):void
{
trace("Down");
if(my_obj.x <= right.x){
my_obj.x = my_obj.x + 10;
}
}
How can I test the collision of the moving Mc_MC / Mc_MC2 with my_obj considering that the come from different AS files?
I am new to AS, so any help would be appreciated!
If you want to be able to collision test objects from different classes / parentage, then you need to set up your project in a way that you can gain a reference to said objects.
From the looks of it, your two objects are actually in the same class already (as your main timeline code and document class code share the same scope, so what you declare in one should be available in the other).
The only thing you are missing, is a top-level reference to your obstacle/Mc_MC. As currently you assign it to a var that is scoped to the makeSymbol function (so you only have a reference to it inside that function).
Solution
In your document class (baseCode.as) , create a top-level var to hold a reference to that obstacle: (for reference, you have a top level var called t, put this line above or below that)
private var obstacle:Mc_MC;
later in your function that instantiates the new Mc_MC (makeSymbol), assign the instance to that top level var:
obstacle = new Mc_MC(1 + Math.random() *10, loc);
addChild(obstacle);
Now you can access that obstacle var anywhere else in the main timeline or document class.
if(my_obj.hitTest(obstacle)){
}
As an aside, if you have a document class, there is no point in having code on the first frame of your main timeline as that code would work the same in your document class (though it has to be contained in a function). Here is an example of where to move main timeline code:
public class Main extends MovieClip {
public function Main():void {
//listen for the added to stage event prior to do anything display oriented
this.addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event):void {
//this is the best place to put the equivalent of timeline code (not including vars or functions, put those in the class root NOT nested here)
}
}
I'm working on a Flash game for an assignment. It's a pretty standard missile defense-type game, with a rotating missile launcher in the center firing up at passing bombers above. The missiles and bombers are functioning correctly by themselves, but I'm running into a problem when I try to get the two to interact. Specifically, when a missile hits a bomber, I want the specific instances of that missile and that bomber to be removed from the screen and have their respective event listeners removed, but everything I've tried has failed and I can't seem to figure out just how to do it.
Here are the Main, Bomber, and Missile classes I'm working with:
The Main Class:
package {
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main extends MovieClip {
public var background:Background;
public var launcher:Launcher;
public var mount:Mount;
public var missile:Missile;
public var salvo:Array = [];
public var bomber:Bomber;
public var squadron:Array = [];
/*
* This function sets up the permanent items (items that remain on-stage for
* the duration of the game) and adds event listeners that call functions to
* add non-permanent items to the stage
*/
public function Main() {
// Add background to the stage
background = new Background(stage);
stage.addChild(background);
stage.setChildIndex(background, 0);
// Add the rotating launcher to the stage
launcher = new Launcher(stage);
stage.addChild(launcher);
stage.setChildIndex(launcher, 1);
// Add the static mount to the stage (on top of launcher)
mount = new Mount(stage);
stage.addChild(mount);
stage.setChildIndex(mount, 2);
// Call loop() every new frame
stage.addEventListener(Event.ENTER_FRAME, loop);
// Call fire() every time the mouse is clicked
stage.addEventListener(MouseEvent.CLICK, fire);
}
/*
* This function runs every time the program enters a new frame, or 60 times
* every second. Each time this function runs, it tries to add a new Bomber
* to the squadron array and checks to see if there are any Missiles or
* Bombers currently in their respective arrays (and if so, calls a function
* to make them move).
*/
public function loop(evt:Event) {
// If the random number generated by Math.random() is less than
// waveLimiter, create a new Bomber and add it to the squadron array.
if(Math.random() < 0.02 /* Change this number to change how fast bombers spawn */) {
bomber = new Bomber(stage);
bomber.addEventListener(Event.REMOVED_FROM_STAGE, removeBomber); // If the Bomber is removed from the stage, call removeBomber() to remove its event handler.
squadron.push(bomber);
stage.addChild(bomber);
stage.setChildIndex(bomber, 1);
}
// Check to see if there is at least one missile in the salvo array, and
// if so, call Missile.velocity() to make it move.
if(salvo.length > 0) {
for(var i:int = salvo.length - 1; i >= 0; i--) {
salvo[i].velocity();
}
}
// Check to see if there is at least one bomber in the squadron array,
// and if so, call Bomber.fly() to make it move.
if(squadron.length > 0) {
for(var j:int = squadron.length - 1; j >= 0; j--) {
squadron[j].fly();
}
}
}
/*
* This function checks for a mouse click, and if it detects one, creates a
* new Missile and adds it to the salvo array.
*/
public function fire(evt:MouseEvent) {
missile = new Missile(stage, launcher.rotation);
missile.addEventListener(Event.REMOVED_FROM_STAGE, removeMissile); // If the Missile is removed from the stage, call removeMissile() to remove its event handler.
salvo.push(missile);
stage.addChild(missile);
stage.setChildIndex(missile, 1);
}
/*
* This function removes the EVENT LISTENER for the current Missile instance.
* It does not remove the Missile itself from the stage.
*/
public function removeMissile(evt:Event):void {
evt.currentTarget.removeEventListener(Event.REMOVED_FROM_STAGE, removeMissile);
salvo.splice(salvo.indexOf(evt.currentTarget), 1);
}
/*
* This function removes the EVENT LISTENER for the current Bomber instance.
* It does not remove the Bomber itself from the stage.
*/
public function removeBomber(evt:Event) {
evt.currentTarget.removeEventListener(Event.REMOVED_FROM_STAGE, removeBomber);
squadron.splice(squadron.indexOf(evt.currentTarget), 1);
}
}
}
The Bomber class:
package {
import flash.display.Stage;
import flash.display.MovieClip;
public class Bomber extends MovieClip {
var stageInstance:Stage;
var randomNumber:Number = Math.round(Math.random() * 1);
public function Bomber(stageInstance:Stage):void {
this.stageInstance = stageInstance;
if(randomNumber == 1) {
x = -39;
y = (Math.random() * 120) + 30;
}
else if(randomNumber == 0) {
scaleX *= -1;
x = 679;
y = (Math.random() * 120) + 30;
}
}
public function fly():void {
if(randomNumber == 1) {
x = x + 4;
}
else if(randomNumber == 0) {
x = x - 4;
}
if(x > 680 || x < -40) {
this.parent.removeChild(this);
}
}
}
}
The Missile Class:
package {
import flash.display.Stage;
import flash.display.MovieClip;
public class Missile extends MovieClip {
var stageInstance:Stage;
var velocityX:Number;
var velocityY:Number;
var speed:Number = 10;
var rotationRadians:Number;
var rotationDegrees:Number;
public function Missile(stageInstance:Stage, rotationDegrees:Number):void {
this.stageInstance = stageInstance;
x = 320;
y = 363;
rotation = rotationDegrees;
rotationRadians = rotationDegrees * Math.PI / 180;
}
public function velocity():void {
velocityX = Math.cos(rotationRadians) * speed;
velocityY = Math.sin(rotationRadians) * speed;
x += velocityX;
y += velocityY;
if(x > 640 || x < 0 || y > 480 || y < 0) {
this.parent.removeChild(this);
}
}
}
}
In the Main Class, I've tried adding something like this:
if(squadron.length > 0) {
for(var j:int = squadron.length - 1; j >= 0; j--) {
squadron[j].fly();
if(salvo.length > 0) {
if(missile.hitTestObject(squadron[j])) {
this.parent.removeChild(this);
}
}
}
}
But no luck. I've also tried using a trace statement, and it doesn't even give me an output, which leads me to think it's not even detecting collision at all. Any ideas?
Update: I added a few more details.
this represents the object on which the function is called. So
this.parent.removeChild(this); makes no sense when it is written in the main class.
When you write it in the Missile Class, this is the Missile instance, and this.parent is the stage.
Try replacing it with: stage.removeChild(missile), in the last sample of code you posted, and call removeMissile() just after.
Try to use stage.removeChild instead this.parent.removeChild(this);
Actually you have many problems in your code. First of all, you don't need to work with Stage. You can work with your main container Main. When you add object to the display list, don't do after setChildIndex. In your code It doesn't have any sense. Also you don't need any length conditions. And create light objects by extending Sprite, not MovieClip.
Code for your loop, for missiles:
private function loop(e: Event):void {
//...not full listing
var i:uint, j:uint, salvos:uint = salvo.length, bombers:uint = squadron.length, missile:Missle, bomber:Bomber;
var disposeMissiles:Array = [];
var disposeBombers:Array = [];
//Rendering missiles
for (i = 0; i < salvos; ++i) {
missile = salvo[i];
missile.valocity();
for (j = 0; j < bombers; ++j) {
bomber = squadron[j];
if (!bomber.isHitted() && missile.hitTestObject(bomber)) {
//Dispose both missile and bomber
bomber.setHitted = true;
disposeMissiles.push(missile);
disposeBombers.push(bomber);
}
}
}
//Clear lists and display list
disposeObjects(disposeMissiles, salvo);
disposeObjects(disposeBombers, squadron);
}
private function disposeObjects(objects:Array, from:Array):void {
//Create interface for both missiles and bombers, like IGameActor
var i:uint, len:uint = objects.length, objectToRemove:IGameActor;
for (i; i < len; ++i) {
objectToRemove = objects[i];
//Remove from the display list, in your design Parent is Stage
this.stage.removeChild(DisplayObject(objectToRemove));
//Release memory, links, event listeners
objectToRemove.dispose();
//Try manage also indexes, splice is slow operation
from.splice(from.indexOf(objectToRemove), 1);
}
}
I'm new to Flash Actionscript 3.0 and object programming in general. I'm trying to create a simple game, which is drawing a shape based on steering.
public class Player extends Shape
{
public var X,Y,v,vX,vY,size,a,r:Number;
public var k,counter,leftKey,rightKey,_color:uint;
public var line:Shape = new Shape();
public var dot:Shape = new Shape();
/*...*/
/*constructor, giving values to variables here, not important*/
/*...*/
public function Move():void
{
a=a+0.05*k;
//player controls k parameter k=0 by default
//k=1 when right key pressed
//k=-1 when left key pressed
vX=v*Math.cos(a);
vY=v*Math.sin(a);
X=X+vX;
Y=Y+vY;
dot.x=X+vX*size/(2*v);
dot.y=Y+vY*size/(2*v);
if (counter==0)
{
line.graphics.lineTo(X,Y);
if (Math.random()<0.008) counter=12;
} else
{
line.graphics.moveTo(X, Y);
counter--;
}
}
}
Function Move is in my Player class, which is called from inifinite TimerEvent function in my Main Class
public function mainLoop(TimerEvent:Event):void
{
for (var i:uint=0; i<players; i++) player[i].Move();
}
It seems to be working well at the beginning but after some time CPU usage raises dramatically and game becomes unplayble. I belivie it's caused by my shape (line) getting more and more complex.
Is there some reasonable way to optimize it? Can I somehow draw a line in less consuming way? I tried to convert it to bitmap but that looked ugly and didn't really help.
Thanks and cheers!
You're right in assuming that your slowdown in coming from your shape code - vector data is redrawn every frame in flash, so the more complex it is, the longer it takes to draw. Some solutions, depending on what you're willing to do:
Your fidelity is way to high - you're calling your Move function every frame; you probably don't need it that high, as the difference in movement since the last frame is probably less than a pixel. Sample your position every X frames instead (where X is the level of fidelity your willing to go down to). This can be done with a simple counter in the enter frame
If you don't need to keep the entire history of the drawing, put all your points into an array/vector, culling the length as needed. Then every frame, do a line.graphics.clear() and just draw the points in the array
If you do need to keep the entire history, then keep a BitmapData under your line (e.g. the size of the stage). Every so often, draw the line to the BitmapData and call clear() on your graphics to get right of the vector data. You shouldn't notice any loss in quality (set smoothing to true when you're drawing)
I'd do the first point in any case, then choose between the second and third, depending on your use case
Expanding my comment, try something like this:
public class Player extends Shape
{
public var X,Y,v,vX,vY,size,a,r:Number;
public var k,counter,leftKey,rightKey,_color:uint;
public var line:Shape = new Shape();
public var dot:Shape = new Shape();
/*...*/
/*constructor, giving values to variables here, not important*/
/*...*/
public function Player(){
//draw shapes
graphics.lineStyle(1);
graphics.drawCircle(0,0,r);
graphics.lineTo(size,0);//can't test this now, but make sure the line is in the same direction as rotation 0 (guessing it's to the right)
//your other constructor code here
}
public function Move():void
{
a=a+0.05*k;
//player controls k parameter k=0 by default
//k=1 when right key pressed
//k=-1 when left key pressed
vX=v*Math.cos(a);
vY=v*Math.sin(a);
X=X+vX;
Y=Y+vY;
x=X+vX*size/(2*v);
y=Y+vY*size/(2*v);
rotation = a * 57.2957795;//quick'n'dirty radians to degrees
}
and if you want to draw the trails you can try something like this:
var canvas:Bitmap = new BitmapData(state.stageWidth,stage.stageHeight,true,0xFF000000);
var ct:ColorTransform = new ColorTransform(1,1,1,.1);
public function mainLoop(TimerEvent:Event):void
{
for (var i:uint=0; i<players; i++) {
player[i].Move();
canvas.draw(player[i],player[i].transform.concatenatedMatrix,ct);
}
}
Hope this makes sense.
Update
Here is a standalone code snippet to illustrate the idea above(which has untested syntax):
package {
import flash.display.Bitmap;
import flash.geom.ColorTransform;
import flash.display.BitmapData;
import flash.text.TextField;
import flash.ui.Keyboard;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.utils.Dictionary;
import flash.display.Sprite;
public class PlayerMoveTest extends Sprite {
private var keys:Dictionary = new Dictionary();
private var players:Vector.<Player> = new Vector.<Player>();
private var trails:BitmapData;
private var fade:ColorTransform = new ColorTransform(1,1,1,.1);
public function PlayerMoveTest() {
addEventListener(Event.ADDED_TO_STAGE,init);
}
private function init(e:Event):void{
trails = new BitmapData(stage.stageWidth,stage.stageHeight,true,0x00FFFFFF);
addChild(new Bitmap(trails));
for(var i:int = 0 ; i < 2; i++){
var p:Player = addChild(new Player(10+i*10)) as Player;
p.x = stage.stageWidth * .5;
p.y = stage.stageHeight * .5;
players.push(p);
}
stage.addEventListener(KeyboardEvent.KEY_DOWN,onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP,onKeyUp);
stage.addEventListener(Event.ENTER_FRAME,update);
}
private function onKeyDown(e:KeyboardEvent):void{
keys[e.keyCode] = true;
}
private function onKeyUp(e:KeyboardEvent):void{
keys[e.keyCode] = null;
}
private function update(e:Event):void{
if(keys[Keyboard.LEFT] != undefined) {players[0].a -= .05;players[1].a += .05;}
if(keys[Keyboard.RIGHT] != undefined) {players[0].a += .05;players[1].a -= .05;}
if(keys[Keyboard.UP] != undefined) {players[0].s += .15;players[1].s -= .15;}
if(keys[Keyboard.DOWN] != undefined) {players[0].s -= .15;players[0].s += .15;}
for(var i:int = 0 ; i < players.length; i++) {
players[i].move();
trails.draw(players[i],players[i].transform.concatenatedMatrix,fade);
}
}
}
}
import flash.display.*;
class Player extends Shape{
public var vx:Number,vy:Number,a:Number,size:Number,r:Number,s:Number;
public function Player(size:Number){
init(size);
}
private function init(size:Number):void{
vx = vy = a = s = 0;
this.size = size;
this.r = size * .25;
graphics.lineStyle(1);
graphics.drawCircle(0,0,r);
graphics.lineTo(size,0);
}
public function move():void{
rotation = a * 57.2957795;
vx = Math.cos(a) * s;
vy = Math.sin(a) * s;
x += vx;
y += vy;
if(x < 0) x = 0;
if(y < 0) y = 0;
if(x > stage.stageWidth) x = stage.stageWidth-width;
if(y > stage.stageHeight) y = stage.stageHeight-height;
}
}
You can test this code here and here's a preview:
Use the arrow keys to drive(up arrow accelerates, left/right steer).
The first player is the smaller one, having the correct controls, the other is simply mirroring the previous controls)
How can I make my object stop when it reaches the destination i gave it with my mouse click? The code makes the object move towards the point of a mouse click but I can't seem to find out how to make it stop, because it will almost never pass the specific destination point. :/ Somebody who knows how to accomplish this?
public function onMouseDown(evt:MouseEvent)
{
if (this._character != null)
{
_character.isMoving = false;
_character.dx = 0;
_character.dy = 0;
targetX = mouseX - _character.x;
targetY = mouseY - _character.y;
var angle:Number = Math.atan2(targetY,targetX);
var dx:Number = Math.cos(angle) * _character.speed;
var dy:Number = Math.sin(angle) * _character.speed;
_character.dx = dx;
_character.dy = dy;
_character.isMoving = true;
}
}
public function updateCharacter(e:Event):void
{
if (this._character.isMoving)
{
this._character.x += this._character.dx;
this._character.y += this._character.dy;
}
}
Easiest way to do it would be to calculate the angle to the point you want to stop at each time you move. This value should remain the same if you're moving in a straight line until you pass the point you're trying to stop at, at which point it will change drastically.
Once this happens, simply move your object back to the position it should have stopped at before you render it again.
I've created a demo with source code for you. There's a fair amount of code, so rather than posting everything here you can download the source instead:
http://martywallace.com/testing/gotoPoint.zip
Try this
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class Guest extends MovieClip
{
var walkSpeed:Number = 5;
var oldPosX;
var oldPosY;
public function Guest()
{
stage.addEventListener(MouseEvent.CLICK, walk);
}
function walk(event:MouseEvent):void
{
oldPosX = parent.mouseX;
oldPosY = parent.mouseY;
rotation = Math.atan2(oldPosY - y,oldPosX - x) / Math.PI * 180;
addEventListener(Event.ENTER_FRAME, loop);
}
function loop(event:Event):void
{
// see if you're near the target
var dx:Number = oldPosX - x;
var dy:Number = oldPosY - y;
var distance:Number = Math.sqrt((dx*dx)+(dy*dy));
if (distance<walkSpeed)
{
// if you are near the target, snap to it
x = oldPosX;
y = oldPosY;
removeEventListener(Event.ENTER_FRAME, loop);
}
else
{
x = x+Math.cos(rotation/180*Math.PI)*walkSpeed;
y = y+Math.sin(rotation/180*Math.PI)*walkSpeed;
}
}
}
}
Similar questions have been asked many times.
However, see the code in my answer here that should explain how to move and stop.
Movement of Objects in a simulation
I'm trying to make a simple animation with Flash CS4 and Action Script 3.0 to make a number of Symbols fly by from right to left constantly. What I want is that once a symbol has reached the end of the screen it is destroyed and another one is placed at the start position.
I intend to give each symbol a random speed and create a random symbol each time one is 'destroyed'. Any clues where I can start?
As you seem new to flash as a platform I would think writing classes shouldn't be your first port of call when learning ActionScript. Definitely just play about on the timeline for now and learn the basics. As very simple solution to this, I would suggest creating a MovieClip in the library with a class name like 'MyBall'... then paste this onto the first frame of the main timeline et voila.
// Create some variables to store data
var numberOfBalls : int = 20;
var myBalls : Array = [];
var xVelocities : Array = [];
var maxXVelocitySpeed : Number = 5;
var minXVelocitySpeed : Number = 2;
// Add your orginal balls to the stage
for (var i : int = 0; i < numberOfBalls; i++)
{
var myBall : MyBall = new MyBall();
myBall.x = -(Math.random() * stage.stageWidth);
myBall.y = Math.random() * stage.stageHeight;
var xVelocity : Number = minXVelocitySpeed + (Math.random() * (maxXVelocitySpeed - minXVelocitySpeed));
myBalls.push(myBall);
xVelocities.push(xVelocity);
addChild(myBall);
}
// Add a listener for enter frame events
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
//Run this code on every frame to move the balls and reposition them if they are off the stage
function enterFrameHandler(event : Event) : void
{
for each( var myBall : MyBall in myBalls)
{
var ballIndex : int = myBalls.indexOf(myBall);
myBall.x += xVelocity[ballIndex];
if (myBall.x > stage.stageWidth)
{
myBall.x = -(Math.random() * stage.stageWidth);
myBall.y = Math.random() * stage.stageHeight;
}
}
}
First, turn your symbols into MovieClips. Then create a base class MySymbol.as for your symbols, something like:
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.geom.Point;
public class MySymbol extends MovieClip
{
public var speed:Number; // Pixels moved per frame
public function MySymbol(speed:Number, startPosition:Point)
{
this.speed = speed;
this.addEventListener(Event.ENTER_FRAME, update);
this.x = startPosition.x;
this.y = startPosition.y;
}
private function update():void
{
this.x -= this.speed;
if (this.x < 0 - this.width) { // We're at the left edge
this.removeEventListener(Event.ENTER_FRAME, update);
this.dispatchEvent(new Event(Event.COMPLETE));
}
}
}
}
Then make sure your movie clips are exported for AS3 (the "linkage" option on the item in the library). Make the class name for each item unique (e.g. MySymbol1, MySymbol2), and set the base class to MySymbol.
Your document class might look something like this:
package {
import flash.display.MovieClip;
import flash.events.Event;
import MySymbol; // Not strictly needed
public class DocumentClass extends flash.display.MovieClip
{
private static var SYMBOLS:Array = new Array(MySymbol1, MySymbol2);
public function DocumentClass()
{
// Create five symbols:
for (var i:int = 0; i < 5; i++) {
makeSymbol();
}
}
private function makeSymbol():void
{
// Pick a random symbol from the array:
var symType:Class = SYMBOLS[Math.random() * SYMBOLS.length];
// Construct the new symbol:
var loc:Point = new Point(stage.stageWidth, Math.random() * stage.stageHeight);
var sym:MySymbol = new symType(1 + Math.random() * 30, loc);
// Listen for the object hitting the left edge:
sym.addEventListener(Event.COMPLETE, remakeObject);
this.addChild(sym);
}
private function remakeObject(e:Event):void
{
e.target.removeEventListener(Event.COMPLETE, remakeObject);
this.removeChild(e.target);
// Replace the dead symbol:
makeSymbol();
}
}
}
It is a lot more efficient if instead of destroying and re-creating an object that flies off-stage you re-use the existing one and move it back to the right. But this is an optimization you can implement later, if things become slow.
Note that all the code above is UNTESTED and I have not coded AS3 in a while, so there's likely at least a few bugs in it. Hopefully it will serve as a good enough starting point.
Define a Circle (symbol) class that extends Sprite/Shape and has a velocity variable
Draw a circle (or whatever) with a random color
Math.floor(Math.random() * 0xffffff)
Assign a random value to velocity
minVelocity + Math.floor(Math.random() * velocityRange)
Create a start() method inside the Circle class that registers an enter frame handler
Increment this.y inside the enter frame handler, and dispatch a 'recycleMe' event if y is more than the max value.
Create N instances of Circle, addChild them, and call their start() methods.
listen to 'recycleMe' events on each of them, and reset the value of y from the handler.
Here's a few prompts to get you started.
MovieClips have an x and y property. If you were to add to these numbers over time you would see the MovieClip move along the x and/or y axis of the stage. Look into doing this using the Event.ENTER_FRAME which will allow you to change the values every time the screen is going to update.
Your stage will have a given width (a stageWidth property). You probably want to monitor when your MovieClip's x property is greater than the width of your stage. If it is remove (removeChild) it and add a new one (addChild) and place it back at the start x/y position.