action script moving movieclips separately - actionscript-3

I've write a actionscript 3.0 code, I have a background movie clip and and a simple space ship movie clip. I want to move spaceship right when left arrow button is pushed.To do that I've write the following code:
package{
import flash .display.*;
import flash.events.*;
public class main extends MovieClip{
public function main(){
var bground_mc:backGround_mc=new backGround_mc();
bground_mc.x=0;
bground_mc.y=0;
bground_mc.height=400;
bground_mc.width=550;
addChild(bground_mc);
var myHero:Ship=new Ship();
addChild(myHero);
// setChildIndex(myHero,numChildren - 1);
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyPressedDown);
}
function keyPressedDown(event:KeyboardEvent):void{
if (event.keyCode == 37){
x+=50;
// myHero.x+=50; according to me, It should be like this???
}
else{
trace("non left arrow key is pushed");
}
}
}
}
Here is my first view of screen:
http://prntscr.com/2pkwga
When I push the left arow button, not only space ship but also background moves through right. How could I solve my problem ?
After one push to left arrow :
http://prntscr.com/2pkwxn

Your x+=50; in this case refers to whole main class. If you just want to move just a space ship you should change 'myHero' property.
So:
myHero.x += 50;
EDIT
Sorry, myHero is local variable in constructor so it's not accessible from outside.
Do:
private var myHero:Ship;
just before the constructor and inside just change it to
myHero = new Ship();

Related

Cursor movement too fast for code to read

I have created a MOUSE_MOVE MouseEvent and a code to draw circles while I move the mouse cursor. The problem is, it doesn't draw out every single circle if I move the mouse too fast.
Here are the codes I have for the MOUSE_MOVE event.
stage.addEventListener(MouseEvent.MOUSE_MOVE, mCursor);
public function mCursor(e:MouseEvent):void
{
var cursor:Shape = new Shape();
cursor.graphics.beginFill(1, 1);
cursor.graphics.drawCircle(e.stageX, e.stageY, 10);
cursor.graphics.endFill();
addChild(cursor);
}
Would there be an arithmetic equation or physics formula to have it add every single circle such that it can draw a straight line without the blanks in between?
Just use
cursor.graphics.lineTo(…);
To draw a continuous line between points instead of adding discrete individual circles.
I erased the above codes and just added this one line of code cursor.graphics.lineTo(e.localX, e.localY); I tested it and there were blanks in between
You have to set the line width first by calling lineStyle() method of the graphics object. Otherwise the line width is zero (its default value).
Here's a full working document class:
package
{
import flash.display.Sprite;
import flash.display.Shape;
import flash.events.MouseEvent;
public class Main extends Sprite
{
private var cursor:Shape;
public function Main()
{
cursor = new Shape();
cursor.graphics.lineStyle(2);
addChild(cursor);
stage.addEventListener(MouseEvent.MOUSE_MOVE, mCursor);
}
private function mCursor(e:MouseEvent):void
{
cursor.graphics.lineTo(e.stageX, e.stageY);
}
}
}
You likely have to fiddle around with moveTo in order to set an appropriate starting position. As the code is now, it starts at 0/0.

ActionScript classes reference

I have a class Square and a class Circle.
This my class Circle:
public class Circle extends MovieClip
{
var growthRate:Number = 2;
public function Circle()
{
addEventListener(Event.ENTER_FRAME, grow);
}
function grow(e :Event):void
{
e.target.width +=growthRate;
e.target.height +=growthRate;
}
}
I need to stop growing the circle inside a function from Shape.
public function Square() {
buttonMode = true;
addEventListener(MouseEvent.MOUSE_DOWN, down);
}
protected function down ( event: MouseEvent):void
{
//here i need to stop the circle
}
I don't know how to make a relation with the Circle class in order to stop the circle growing.
Thank you in advance.
I don't know how to make a relation with the Circle class in order to stop the circle growing.
That's because you cannot with the code you have right now. There's nothing in your class that's accessible from outside (public), that stops the growth. But there's not even something private in your class that does this. The functionality simply is not there.
So first of all, create the desired functionality. and make it available to public.
Here's how your Circle class could look like:
public class Circle extends Sprite
{
private var growthRate:Number = 2;
public function Circle()
{
// nothing here
// this is just to create a circle graphic, if you have artwork in your library symbol, you do not need this
graphics.beginFill(0xffffff * Math.random());
graphics.drawCircle(0, 0, 10 + 30 * Math.random());
graphics.endFill();
}
public function startGrowing(rate:Number = 0):void
{
if(rate != 0)
{
growthRate = rate;
}
addEventListener(Event.ENTER_FRAME, grow);
}
public function stopGrowing():void
{
removeEventListener(Event.ENTER_FRAME, grow);
}
private function grow(e:Event):void
{
width += growthRate;
height += growthRate;
}
}
Pay attention to
the constructor: I create a circle graphic there with code. As the comment says, if Circle is a class associated to a library symbol, you do not need this, because you already created the artwork in the symbol.
the super class: It's Sprite. This should be your default superclass. The only real reason to use MovieClip is if you have a timeline animation. It doesn't look like you have any of that from what you posted, so I recommend Sprite.
the two new public methods: startGrowing and stopGrowing, which do exactly what their names imply. startGrowing has an optional parameter to to start growing at a different growth rate.
the lack of e.target: which is unnecessary here.
A simple demo of that code looks like this:
var circle:Circle = new Circle();
circle.x = 200;
circle.y = 200;
addChild(circle);
circle.startGrowing();
//circle.startGrowing(1); // grow slowly
//circle.startGrowing(5); // grow fast
To stop the growth, stop listening for the ENTER_FRAME Event.
So far so good, now to your actual question:
how to make a relation with the Circle class
protected function down ( event: MouseEvent):void
{
//here i need to stop the circle
}
You think that you should make this connection in your Square class, but you are wrong about that. It's very bad practice to connect two classes this way. You want the classes to be as individual as possible.
Think about it like phones. Does your phone have a direct way to a specific other phone? No. It has the ability to connect to any phone, which makes it a lot more universally useful than a phone hard wired to another phone.
You make the connection outside both classes with events. That's like your phone making a call to the network with a number it wants to call. The network then figures out how to find the other phone with that number and how to establish the connection.
As a short interlude and so that we are on the same page about it, here's the Square class that I'm using:
public class Square extends Sprite
{
public function Square()
{
// nothing here
// this is just to create a circle graphic, if you have artwork in your library symbol, you do not need this
graphics.beginFill(0xffffff * Math.random());
graphics.drawRect(0, 0, 100, 100);
graphics.endFill();
}
}
As you can see, it only has a constructor in which I programmatically draw a rectangle. Again, if you have the desired artwork in your library symbol, there's no need for this. In that case, the constructor would be empty and in turn the entire class file would be empty. In this case, you do not even need a class file. Just associate the library symbol with the name. The Square is only a graphic asset without any code attached to it.
Here's a full fledged document class using both classes:
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
public class Main extends Sprite
{
private var circle:Circle;
public function Main()
{
circle = new Circle();
circle.x = 200;
circle.y = 200;
addChild(circle);
circle.startGrowing(1);
var square:Square = new Square();
addChild(square);
square.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
private function onMouseDown(e:MouseEvent):void
{
circle.stopGrowing();
}
}
}
As you can see, the event listener is added in the document class and also the function that is executed when the event occurs is in Main.
Here's a variation of that without the square. This time you have to click on the circle to stop it growing:
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
public class Main extends Sprite
{
private var circle:Circle;
public function Main()
{
circle = new Circle();
circle.x = 200;
circle.y = 200;
addChild(circle);
circle.startGrowing(1);
circle.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
private function onMouseDown(e:MouseEvent):void
{
circle.stopGrowing();
}
}
}
As you can see, making the connection outside both classes with events gives you a lot of flexibility to wire things up in a different way. Just like having a phone that connects to a network instead of another phone directly.

Creating Top Down Shooter in Adobe Flash CS4 using ActionScript 3 but bullets behaving weirdly

I am making a TDS in Flash CS4 using AS3 but there seems to be a problem. It's hard to explain so I'm gonna link the flash file. Click this.
This is the first time uploading a file for sharing so for those who can't or are unable to download the file, this is what happens:
Player has mouse rotation that is, Player looks at where the mouse is. On Mouse down I've put the script for creating bullets. The bullets are being created alright. But when the bullets move that's when the problem arises. Say that at position and rotation X, I shot 5 bullets and they are moving in X direction. Now if I shoot a bullet in Y position and rotation, the bullet that was created there goes in Y direction but so do all the other bullets that were created in the X position and direction. They change their course.
Here is the code for the game.
package {
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.MouseEvent;
import flash.ui.Keyboard;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Mouse;
import flash.events.TimerEvent;
public class Main extends MovieClip {
var player : Player = new Player();
//Customizable Weapon Settings
var bulletNumber:Number;//number of bullets per shot
var bulletOffset:Number;//bigger number = less acurate
var bulletSpeed:Number;//pixels per frame
var bulletMaxAge:Number;//1000 = 1 second
var reloadSpeed:Number;//1000 = 1 second
var randomNum:Number;
public static var xSpeed:Number;
public static var ySpeed:Number;
var bulletAngle:Number;
var timer:Number=0;
var flag:Boolean;
//other variables (do not edit)
var mouseClicked:Boolean=false;
var radians:Number=Math.PI/180;
public function Main() {
player.x=stage.stageWidth/2;
player.y=stage.stageHeight/2;
stage.addChild(player);
player.gotoAndStop(5);
loadWeapon("Machine Gun");
addEventListener(Event.ENTER_FRAME,on_enter_frame);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUpHandler);
}
public function onMouseDownHandler(event:MouseEvent) {
//trace("Mouse Down");
mouseClicked=true;
flag=true;
}
public function onMouseUpHandler(event:MouseEvent) {
//trace("Mouse Up");
mouseClicked=false;
flag=false;
timer=0;
}
public function loadWeapon(weaponType:String) {
switch (weaponType) {
case "Machine Gun" :
//bulletNumber = 100;
bulletOffset=10;
bulletSpeed=10;
bulletMaxAge=1000;
break;
}
}
function on_enter_frame(e:Event) {
trace("Click: "+ mouseClicked);
fireWeapon();
}
function fireWeapon() {
//check if mouse is clicked
//if true, create bullet
if (mouseClicked) {
createBullet();
player.gotoAndStop(10);
} else {
player.gotoAndStop(1);
}
}
public function createBullet() {
var bullet : Bullet2= new Bullet2();
bullet.x=player.x;
bullet.y=player.y;
if (flag) {
timer++;
if (timer==10) {
trace("lol");
//calculate random bullet offset.
randomNum = Math.random() * (bulletOffset);
//set bullet firing angle
bulletAngle = (player.rotation + randomNum) * radians;
//set bullet speed based on angle
xSpeed=Math.cos(bulletAngle)*bulletSpeed;
ySpeed=Math.sin(bulletAngle)*bulletSpeed;
//trace (bulletAngle);
stage.addChild(bullet);
bullet.addEventListener(Event.ENTER_FRAME, runForest);
//mouseClicked = false;
timer=0;
}
}
function runForest(e:Event) {
bullet.x+=xSpeed;
bullet.y+=ySpeed;
}
}
}
}
Things that I've tried:
1) I put the "runForest()" funtion outside of "createbullet()" function which give me a "1120: Access of undefined property bullet." Error. (Which doesn't make sense since I am giving it a enter frame event listener.)
2) For solving this, I made the bullet variable global and declared it inside the "createbullet()" function like this- "var bullet : Bullet2;" And inside createbullet()- "bullet = new Bullet2();" That gives me a completely different output.
3) I put the "runForest()" function in its own class file. But the same thing is happening.
I was referring to a Tutorial that used AS2. This is the link.
Help me solve this please.
Thanks!
Review this code:
//set bullet speed based on angle
xSpeed=Math.cos(bulletAngle)*bulletSpeed;
ySpeed=Math.sin(bulletAngle)*bulletSpeed;
then take a look at how these variables for speed are created:
public static var xSpeed:Number;
public static var ySpeed:Number;
You have 1 variable for the x direction of the speed. If there is only one variable, there can only be 1 value for speed.
that's why all your bullets are moving in the same direction, because they all share that one single value for speed, which causes them to go into the same direction.
Your Main class is doing everything at the moment and you should really refactor some of that code into several other classes.
Even your own understanding of the code you are writing is not reflected by the code, your comment says:
//set bullet speed based on angle
Now why is that bullet speed a variable of Main? Object oriented programming is made exactly for that. You can literally turn your plain English description of the desired behaviour into code.
When you say that you "want to have Bullets", then create a Bullet class.
When you say "each Bullet object should have its own speed", then add a property to that class that is the speed.
You will encounter the same problem with your weapons and the same solution applies.

Label is not showing up

I'm building a simple menu from basic Flash UI components using bare ActionScript 3.0, and the very first Label control doesn't show up during the movie testing(Ctrl+Enter). Why is that?
I have no symbols in the Library or anything on the stage. My document is linked to main.as
What should happen is when the .swf is launched main() gets the instruction to generate mainMenu which in turn will display the only label in the center-top part of the movie screen.
main.as
package {
import flash.display.*;
public class main extends MovieClip{
public function main(){
changeState(null, "mainMenu");
}
public function changeState(currentState, nextState){
if(currentState != null){
removeChild(currentState);
}
if(nextState == "mainMenu"){
var main_menu:mainMenu = new mainMenu(changeState);
addChild(main_menu);
}// else if(nextState == "deckManager"){
// var deck_manager:deckManager = new deckManager(changeState);
// addChild(deck_manager);
// }
}
}
}
mainMenu.as
package {
import flash.display.*;
import flash.events.MouseEvent;
import fl.controls.Label;
import fl.controls.RadioButton;
import fl.controls.ComboBox;
import fl.controls.Button;
public class mainMenu extends Sprite{
const difficultyRadioGroupName:String = "difficultyGroup"; // group name for easy, normal and hard difficulty radio buttons
var difficultyLabel:Label; // "Difficulty" label
var easyDifficultyRadio:RadioButton; // "Easy" difficulty radio button
var normalDifficultyRadio:RadioButton; // "Normal" difficulty radio button
var hardDifficultyRadio:RadioButton; // "Hard" difficulty radio button
var yourDeckLabel:Label; // "Your deck" label
var yourDeckCombo:ComboBox; // combobox to select your deck(1)
var editSelectedDeckButton:Button; // button to edit currently selected deck
var startTheGameButton:Button; // button to start the game
var theCallbackFunction:Function; // callback function to change between mainMenu and deckManager
public function mainMenu(callback){
// create and position the difficulty label
difficultyLabel = new Label();
difficultyLabel.text = "Difficulty";
difficultyLabel.x = width / 2;
difficultyLabel.y = height / 4;
addChild(difficultyLabel);
theCallbackFunction = callback;
}
//public function backButtonClicked(evt:MouseEvent){
// theCallbackFunction(this, "back");
// return;
// }
}
}
On the surface this seems ok.
However, the X/Y coordinates you are assigning to the Label might not be what you are expecting. You set them based on the width/height of the mainMenu Sprite. But that Sprite has no children yet (the child is added on the next line), so the width/height are still 0.
This may not be the problem. To further trouble shoot this I would set some breakpoints and use a debugger, or add a bunch of trace statements to make sure your code is executing using the proper values.
I believe everything in the 'fl.controls' package requires the appropriate asset in your library to show up. If you just import things from fl.controls you get no UI aspect to the control unless you add that element to your library or ingest a swc/swf with the appropriate library assets in it.
So I'd guess that if in the flash IDE, if you dragged the appropriate UI elements from the components tab to your library, they would start showing up. They don't have to be on the stage or anything, just in the library so the UI elements get compiled with your code.

ArgumentError: Error #2025 when removeChild

I wrote a AS3 class to make a Counter function. Click and hold mouse in blue area to define a value. I try to show a indicator picture to users that reminding the variation.
But when I drag mouse a little quick in the blue area a error will occur:
ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
at flash.display::DisplayObjectContainer/removeChild()
at test/get2()
I have read some similar issue posts, but I can't fix this. Could you give me any help? Thank you!
Download .fla and .as in CS6
Download .fla and .as in CS5
The code is below:
package {
import flash.display.Sprite;
import flash.text.TextField;
import flash.events.MouseEvent;
import flash.text.TextFormat;
import flash.events.Event;
public class test extends Sprite{
var i:int=20; //Set a var for the number displayed in stage.
var mx1:Number; //Set a var to save MouseY when MOUSE_DOWN
var mx2:Number; //Set a var to save MouseY when MOUSE_UP
var num:int=0; //Set a var to calculate result
var sub1:subbar1=new subbar1();
var sub2:subbar2=new subbar2();
var sub3:subbar3=new subbar3();
var add1:addbar1=new addbar1();
var add2:addbar2=new addbar2();
var add3:addbar3=new addbar3();
public function test() {
init1(); //Set TextField and addEventListener
initbar(); //Set indicator picture position when drag mouse
}
private function init1():void{
label=new TextField();
label.text=String(i);
label.width=280;
label.selectable=false;
label.x=140;
label.y=90;
addChild(label);
Controler.addEventListener(MouseEvent.MOUSE_DOWN,get1); //addEventListener to bluearea
}
private function initbar(){
sub1.x=sub2.x=sub3.x=add1.x=add2.x=add3.x=30;
sub1.y=35;
sub2.y=55;
add3.y=sub3.y=75;
add2.y=95;
add1.y=115;
}
private function get1(evt:MouseEvent):void{
mx1=mouseY;
trace(mx1);
Controler.removeEventListener(MouseEvent.MOUSE_DOWN,get1);
stage.addEventListener(MouseEvent.MOUSE_UP,get2); //addEventListener to MOUSE_UP
stage.addEventListener(Event.ENTER_FRAME,lifebar); //add ENTER_FRAME to display indicator picture when move mouse
}
private function get2(evt:MouseEvent):void{
mx2=mouseY;
trace(mx2);
if(mx2<=135&&mx2>=35&&mouseX<=130&&mouseX>=50){ //Limited enable area as the blue area
if(num>=4){ //Set i value depends on num
i=i-3;
}else if(num<=-4){
i=i+3;
}else{
i=i-num;
}
label.text=String(i);
}
if(num==1){ //remove indicator picture when MOUSE_UP
removeChild(sub1);
}
if(num==2){
removeChild(sub1);
removeChild(sub2);
}
if(num>=3){
removeChild(sub1);
removeChild(sub2);
removeChild(sub3);
}
if(num==-1){
removeChild(add1);
}
if(num==-2){
removeChild(add1);
removeChild(add2);
}
if(num<=-3){
removeChild(add1);
removeChild(add2);
removeChild(add3);
}
stage.removeEventListener(MouseEvent.MOUSE_UP,get2);
Controler.addEventListener(MouseEvent.MOUSE_DOWN,get1);
stage.removeEventListener(Event.ENTER_FRAME,lifebar);
}
private function lifebar(evt:Event):void{ //Set a ENTER_FRAME to display indicator picture
num=(mouseY-mx1)/12+1;
trace(num);
if(mouseY!=mx1&&num==1){
addChild(sub1);
}
if(num==2){
addChild(sub2);
}
if(num==3){
addChild(sub3);
}
if(num==-1){
addChild(add1);
}
if(num==-2){
addChild(add2);
}
if(num==-3){
addChild(add3);
}
}
}
}
You are attempting to remove display objects that have not yet been added as a child to the display list.
Even though sub1 has been instantiated, it has not been added at the time you attempt to remove it:
Before calling removeChild(obj) on the display object, first test if it has been added as a child by evaluating whether if(contains(obj)) is true.
At line 67 in test.as, you should perform condition testing to see if sub1 has been added to the display list:
if(num==1) {
if(contains(sub1)) // test to see if sub1 is on the display list
removeChild(sub1);
}
If this issue continues with other children, you should add additional testing in blocks like these:
if(num==2){
removeChild(sub1);
removeChild(sub2);
}