0
votes

I am starting a new project that is done 100% in FlashDevelop as an AS3 Project. To clarify, I am not creating an FLA in Adobe Flash at any point; Adobe Flash will never be used.

In the document class of my AS3 project I will need to create and reference movieclips that are set up in separate .as class files. The document class will have eventlisteners that watch for keyboard presses and move the movieclips when required. Movements via the keyboard inputs work fine when the movieclip is set up and added to the stage from the document class. However, I have problems when the movieclip is set up from a separate class.

Apart from my project I am working on, I have created a sample project that runs three tests for this Stack Overflow question. This sample project contains three files all stored in the same folder: Main.as (the document class), createSquare.as (creates square MC), and createCircle.as (creates circle MC).

Test #1 (Blue Rectangle): In Main.as I create a new MC called charRectangle. The size, dimensions, color, etc are defined here and then it is added to the stage. When the function keyIsDown() executes, the blue rectangle moves left or right on the stage correctly. This is a succesful test.

Test #2 (Green Square): Now I test creating a movieclip from a separate class file. In Main.as I create a new variable called charSquare and define it as a new createSquare(). createSquare.as defines the characteristics and adds the child to the stage. Problem: When the project is tested no green square is visible on the stage; however, trace output shows the the left and right arrow keys are in fact updating the X position of charSquare. How do I make the movieclip show? My solution to that is in...

Test #3 (Yellow Circle): I start everything the same way for the yellow circle as I did for the green square. We name this one charCircle. In Main.as when defining the variable as a new charCircle() I pass along the word "this" to the function in createCircle.as. This in turn tells the function createCircle to add the child to "this", the parent MC on the stage. Now we can see a visible shape. Problem: Trace output shows the left and right arrow keys are updating the X position, but the yellow circle does not move. How do I make this movie clip move?

Primary Goal: I want to avoid stating all the attributes of the character shapes in Main.as and keep that isolated to other class files. In Main.as I want to just create a new variable, define it as a new createSquare()/createCircle(),and then use a keyboard function in Main.as to handle movements. I would later keep keyboard controls in a fourth testing class called keyboardControls.as.

I can solve these problems when starting from an FLA in Adobe Flash, stating the document class, creating MC symbols on the stage, giving them an instance name, and then working on the AS files in FlashDevelop. But again, this project requires that I omit Adobe Flash/FLA so this is not the solution i am looking for.. I need to create it 100% dynamic in FlashDevelop AS3.

Thank you for any and all assistance. The source code for the three test files are found below.

Main.as

package {
    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.events.KeyboardEvent;

    public class Main extends MovieClip {

        private var charRectangle:MovieClip;
        private var charSquare:createSquare;
        private var charCircle:createCircle;

        public function Main() {

            trace("Function: Main() has started.");

            // Create rectangle character right here
            charRectangle = new MovieClip();
            charRectangle.graphics.beginFill(0x0000FF);
            charRectangle.graphics.drawRect(200,20,250,100);
            charRectangle.graphics.endFill();
            stage.addChild(charRectangle);

            // Create square character from class
            charSquare = new createSquare();

            // Create square character from class
            charCircle = new createCircle(this);

            // Event listener for user input
            stage.addEventListener(KeyboardEvent.KEY_DOWN,keyIsDown);
        }

        private function keyIsDown(e:KeyboardEvent):void {
            // Left arrow key actions
            if (e.keyCode == 37) {
                charRectangle.x -= 5;
                charSquare.x -= 5;
                charCircle.x -= 5;
            }
            // Right arrow key actions
            if (e.keyCode == 39) {
                charRectangle.x += 5;
                charSquare.x += 5;
                charCircle.x += 5;
            }
            trace("charRectangle.x = " + charRectangle.x + ", charSquare.x = " + charSquare.x + ", charCircle.x = " + charCircle.x);
        }

    }

}

createSquare.as

package {

    import flash.display.MovieClip;

    public class createSquare extends MovieClip {

        private var square:MovieClip;

        public function createSquare() {

            trace("Function: createSquare() has started.");

            square = new MovieClip();
            square.graphics.beginFill(0xFF0000);
            square.graphics.drawRect(200,140,100,100);
            square.graphics.endFill();
            addChild(square);

        }

    }

}

createCircle.as

package {

    import flash.display.MovieClip;

    public class createCircle extends MovieClip {

        private var circle:MovieClip;

        public function createCircle(parentMC:MovieClip) {

            trace("Function: createCircle() has started.");

            circle = new MovieClip();
            circle.graphics.beginFill(0x00FF00);
            circle.graphics.drawCircle(200,350,75);
            circle.graphics.endFill();
            parentMC.addChild(circle);

        }
    }

}
1

1 Answers

1
votes

I'm guessing you should play more with the display list from actionscript to get used to manipulated display objects (addChild/removeChild/nesting/etc.)

You create charRectangle and you add that to the stage, so you can see it. You initialize charCircle like so

charCircle = new createCircle(this);

and internally you add it to Main(passed in the constructor), both of the clips above are also displayed. That's not the case for charSquare which you do create (and can therefore access it as you can see in your traces), but you do not add to the display list. Try this:

// Create square character from class
charSquare = new createSquare();
// add it to the display list
addChild(charSquare)

Also, you mentioned that you'd like to move all of the clips at once, which you can do if you simply nest all 3 of them into a separate Sprite/MovieClip:

package {
    import flash.display.Sprite;
    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.ui.Keyboard;

    public class Main extends MovieClip {

        private var char:Sprite;

        public function Main() {

            trace("Function: Main() has started.");

            char = new Sprite();
            addChild(char);

            // Create rectangle character right here
            var charRectangle:MovieClip = new MovieClip();
            charRectangle.graphics.beginFill(0x0000FF);
            charRectangle.graphics.drawRect(200,20,250,100);
            charRectangle.graphics.endFill();
            char.addChild(charRectangle);

            // Create square character from class
            var charSquare:MovieClip = new createSquare();
            char.addChild(charSquare);
            // Create square character from class
            charCircle = new createCircle(char);

            // Event listener for user input
            stage.addEventListener(KeyboardEvent.KEY_DOWN,keyIsDown);
        }

        private function keyIsDown(e:KeyboardEvent):void {
            if(e.keyCode == Keyboard.LEFT)  char.x -= 5;
            if(e.keyCode == Keyboard.RIGHT) char.x += 5;
            trace("char position",char.x,char.y);
        }

    }

}

(I haven't tested the above code, so there might be syntax errors, but it should illustrate the idea clearly).

Two other side notes:

  1. MovieClip is a dynamic class which is slower than simpler classes like Sprite. Unless you're using a timeline (and your project doesn't look like it will), I recommend using Sprite instead. For a simple project it won't impact performance a lot, but on the long run(for more complex projects), it's safer to save resources.
  2. I imagine your createCircle and createSquare classes will change and become more complex, but if they are to remain as they are now, they could be even simpler:

    package {

    import flash.display.Sprite;
    
    public class Square extends Sprite {
    
    
        public function Square() {
    
            trace(this);
    
            graphics.beginFill(0xFF0000);
            graphics.drawRect(200,140,100,100);
            graphics.endFill();
    
        }
    
    }
    

    }

If don't need to nest elements in createSquare or createCircle, you can use the Shape which is really basic, although you might find Sprite more flexible. Also note that I've named the class Square. It's a convention to start a class' name with an uppercase letter (e.g. Sprite/MovieClip/etc.), properties and methods with a lowercase letter (e.g. x/alpha/etc.), constants all in caps (e.g. KEY_DOWN, CLICK, etc.) and so on. By this convention, createSquare sounds more like a function name than a class. You're not obliged to follow the convention, but it might make it easier for other people to easily scan through your code in the future. The main idea is to be consistent.