So I've been reading a lot about inheritance and circular dependency and I see no way around this. Still a little new to multiple classes. My document class creates Field. My Field class creates player and pushes bitmapData from the Tile MovieClip. I want player to be able to draw that bitmapData to the field. Engine.as(document class):
package {
import flash.display.MovieClip;
public class Engine extends MovieClip {
private var field:Field;
public static var _tilesData:Array = [];
public function Engine()
{
field = new Field();
field.x = 0;
field.y = 0;
addChild(field);
}
}
Field.as:
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.display.BitmapData;
import flash.display.Bitmap;
public class Field extends MovieClip{
private var player:Player;
private var sampleTile:Tile = new Tile();
public function Field()
{
player = new Player();
player.x = 0;
player.y = 0;
addChild(player);
GetSampleTiles();
}
public function GetSampleTiles()
{
for (var i:int = 0;i < 3; i++)
{
sampleTile.gotoAndStop(i);
var graphicData:BitmapData = new BitmapData(32,32);
graphicData.draw(sampleTile);
Engine._tilesData.push(graphicData);
}
}
public function DrawATile(tileToDraw:BitmapData)
{
var newTile:Bitmap = new Bitmap(tileToDraw);
newTile.x = player.x;
newTile.y = player.y;
addChild(newTile);
}
}
}
Player.as:
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.display.BitmapData;
import flash.display.Bitmap;
public class Player extends MovieClip
{
public var _inp:Input = new Input();
public function Player()
{
addChild(_inp);
addEventListener(Event.ENTER_FRAME, HandleKeys);
}
public function HandleKeys(e:Event)
{
if(_inp.keyUp)
{
y -= 32;
}
if(_inp.keyDown)
{
y += 32;
}
if(_inp.keyLeft)
{
x -= 32;
}
if(_inp.keyRight)
{
x += 32;
}
if(_inp.keySpace)
{
parent.DrawATile(Engine._tilesData[0]);
}
}
}
}
Is there a better way of doing this than I am seeing? When I put DrawATile function in Player.as it works... but the tiles move around with the player.
I placed the DrawATile function in Player.as and in it I add the newTile to parent like this - parent.addChild(newTile). that way it adds it to whatever its parent is and not to itself.
Related
I am getting an error whenever I try running the game. I get errors for every class saying that the public attribute can only be used inside a package and on this line with "private function moveMe" "the private attribute may only be used on class functions". I verified if I have the as file linked properly. I am not sure what the issue is.
package {
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.events.Event;
public class banana_fall extends MovieClip {
public function banana_fall (){
var velX:Number=0;
var velY:Number=0;
var falling:Boolean=false;
var gravity:Number=2;
public function banana() {
var timing:Timer = new Timer(20,0);
timing.addEventListener(TimerEvent.TIMER,moveMe);
timing.start();
}
private function moveMe(event:TimerEvent){
this.x=this.x+velX;
this.y=this.y+velY;
if (falling) {
velY=velY+gravity;
}
}
public function setSpot(atX,atY){
this.x=atX;
this.y=atY;
}
//
public function setSpeed(dx,dy){
velX=dx;
velY=dy;
}
}
}
}
The problem is that your public functions were inside your constructor function, which doesnt work in as3.
try this code:
package {
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.events.Event;
public class banana_fall extends MovieClip {
var velX: Number = 0;
var velY: Number = 0;
var falling: Boolean = false;
var gravity: Number = 2;
public function banana_fall() {
var timing: Timer = new Timer(20, 0);
timing.addEventListener(TimerEvent.TIMER, moveMe);
timing.start();
}
private function moveMe(event: TimerEvent) {
this.x = this.x + velX;
this.y = this.y + velY;
if (falling) {
velY = velY + gravity;
}
}
public function setSpot(atX, atY) {
this.x = atX;
this.y = atY;
}
//
public function setSpeed(dx, dy) {
velX = dx;
velY = dy;
}
}
}
I had these two in the same Main class. Now there are Main.as and MainChar.as
When compiling doesn't show any errors but it isn't displaying the object either :c
It is the first time I am splitting code into different classes. I just figured what should be in the hero creation class and what should stay in Main.
package
{
import flash.display.Sprite;
import flash.events.Event;
import nape.geom.Vec2;
import nape.phys.Body;
import nape.phys.BodyList;
import nape.space.Space;
import MainChar;
public class Main extends Sprite
{
public var gravity:Number = 600;
public var space:Space = new Space(new Vec2(0, gravity));
public var hero:MainChar = new MainChar();
public function Main():void
{
hero.createMainCharacter(stage.stageWidth/2, stage.stageHeight/2, 50, 50);
addEventListener(Event.ENTER_FRAME, update);
}
private function update(e:Event):void
{
space.step(1 / stage.frameRate, 10, 10);
var bodies:BodyList = space.bodies;
for (var i:int = 0; i < bodies.length; i++)
{
var body:Body=bodies.at(i);
if (body.userData.sprite != null)
{
body.userData.sprite.x = body.position.x;
body.userData.sprite.y = body.position.y;
body.userData.sprite.rotation=(body.rotation*180/Math.PI)%360;
}
}
}
}
}
Hero creator class:
package
{
import flash.display.Graphics;
import flash.display.Sprite;
import nape.geom.Vec2;
import nape.phys.Body;
import nape.phys.BodyType;
import nape.shape.Polygon;
import nape.space.Space;
public class MainChar extends Sprite
{
public var space:Space = new Space(new Vec2(0, 600));
public function MainChar():void
{
}
public function createMainCharacter(x:Number, y:Number, width:Number, height:Number):void
{
var mainChar:Body = new Body(BodyType.DYNAMIC);
var mainCharShape:Polygon = new Polygon(Polygon.box(width, height));
mainChar.shapes.add(mainCharShape);
mainChar.position.setxy(x, y);
mainChar.space = space;
var mainCharSprite:Sprite = new Sprite();
mainCharSprite.graphics.beginFill(0x000000);
mainCharSprite.graphics.drawRect( -width/2, -height/2, width, height);
mainCharSprite.graphics.endFill;
addChild(mainCharSprite);
mainChar.userData.sprite = mainCharSprite;
addChild(mainChar.userData.sprite);
}
}
}
You need to add your hero as a child of your Main sprite EG:
public function Main():void
{
hero.createMainCharacter(stage.stageWidth/2, stage.stageHeight/2, 50, 50);
addEventListener(Event.ENTER_FRAME, update);
addChild(hero);
}
hey im doing the "Flash Bubbles: Paricle Systems with TimelineMax" from youtube. i got this code:
package
{
import com.greensock.*;
import com.greensock.easing.*;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class main extends Sprite
{
private var BG:bg= new bg;
private var start_btn:start_button= new start_button;
private var tl:TimelineMax= new TimelineMax();
private var bubbleMax:Number = 50;
public function main()
{
stage.addChild(BG);
stage.addChild(start_btn);
BG.y= (stage.stageWidth)/2;
BG.x = (stage.stageWidth)/2;
start_btn.x = (stage.stageWidth)/2;
start_btn.y = (stage.stageHeight)/2;
start_btn.addEventListener(MouseEvent.CLICK,StartGame);
}
private function StartGame(e:Event)
{
stage.removeChild(BG);
stage.removeChild(start_btn);
createBubble();
}
private function createBubble()
{
var Bubble:bubble= new bubble();
Bubble.y=200;
Bubble.x= randomRange(50,1100);
Bubble.alpha= .5;
addChild(Bubble);
}
private function randomRange(min:Number,Max:Number):Number
{
return min + (Math.random() * (Max - min));
}
private function init()
{
for (var count:Number = 0; count<bubbleMax; count++)
{
createBubble();
}
}
init();
}
}
bg, start_button, and bubble are all movie clips made in flash (and been given a as3 class)
I'm aspect to 50 bubbles, but can only see one.. thanks for help!
Change the StartGame function to this:
private function StartGame(e:Event)
{
stage.removeChild(BG);
stage.removeChild(start_btn);
// Your init function is where you're creating all the bubbles. That's what the "for" loop is doing.
init();
}
Also, don't call init(); towards the bottom like you are doing. Your code should look more like this:
package
{
import com.greensock.*;
import com.greensock.easing.*;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class main extends Sprite
{
private var BG:bg= new bg();
private var start_btn:start_button= new start_button();
private var tl:TimelineMax= new TimelineMax();
private var bubbleMax:Number = 50;
public function main()
{
stage.addChild(BG);
stage.addChild(start_btn);
BG.y= (stage.stageWidth)/2;
BG.x = (stage.stageWidth)/2;
start_btn.x = (stage.stageWidth)/2;
start_btn.y = (stage.stageHeight)/2;
start_btn.addEventListener(MouseEvent.CLICK,StartGame);
}
private function StartGame(e:Event)
{
stage.removeChild(BG);
stage.removeChild(start_btn);
init();
}
private function createBubble()
{
var Bubble:bubble= new bubble();
Bubble.y=200;
Bubble.x= randomRange(50,1100);
Bubble.alpha= .5;
addChild(Bubble);
}
private function randomRange(min:Number,Max:Number):Number
{
return min + (Math.random() * (Max - min));
}
private function init()
{
for (var count:Number = 0; count<bubbleMax; count++)
{
createBubble();
}
}
}
}
I'm unsuccessfully attempting to instantiate a reference of a class that is passed as a parameter to another class.
in this example there are 3 classes: MainClass, Canvas, MyCircle
from the MainClass i am creating an instance of Canvas, which is passed a class reference of MyCircle as i want to create instances of MyCircle from within Canvas. however, the MyCircle constructor contains required parameters that are created from within Canvas.
how can i pass and instantiate a class reference with required parameters?
MyCircle:
package
{
//Imports
import flash.display.Shape;
//Class
public class MyCircle extends Shape
{
//Constructor
public function MyCircle(color:uint, radius:uint)
{
graphics.beginFill(color, 1.0);
graphics.drawCircle(0, 0, radius);
graphics.endFill();
}
}
}
Canvas:
package
{
//Imports
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.utils.getDefinitionByName;
//Class
public class Canvas extends Sprite
{
//Constructor
public function Canvas(circleClassReference:String, amount:uint)
{
var CircleReference:Class = getDefinitionByName(circleClassReference) as Class;
for (var i:uint = 0; i < amount; i++)
{
var randomColor:uint = Math.random() * 0xFFFFFF;
var randomRadius:uint = Math.random() * 100 + 50;
var circleInstance:DisplayObject = new CircleReference(randomColor, randomRadius);
circleInstance.y = i * randomRadius;
addChild(circleInstance);
}
}
}
}
MainClass:
package
{
//Imports
import flash.display.Sprite;
//Class
public class MainClass extends Sprite
{
//Constructor
public function MainClass()
{
var myCanvas:Canvas = new Canvas("MyCircle", 10);
addChild(myCanvas)
}
}
}
[EDIT]
it seems that passing the actual Class instead of the name of the class avoids the need for the dirty fix that is mentioned below.
MainClass Constructor
public function MainClass()
{
var myCanvas:Canvas = new Canvas(MyCircle, 10);
addChild(myCanvas)
}
Canvas Constructor
public function Canvas(circleClassReference:Class, amount:uint)
{
var CircleReference:Class = circleClassReference;
for (var i:uint = 0; i < amount; i++)
{
var randomColor:uint = Math.random() * 0xFFFFFF;
var randomRadius:uint = Math.random() * 100 + 50;
var circleInstance:DisplayObject = new CircleReference(randomColor, randomRadius);
circleInstance.y = i * randomRadius;
addChild(circleInstance);
}
}
Importing (or being in the same package) isn't enough to make the compiler include a class definition in the Application Domain. You will actually have to use the class you want somewhere, or embed the definition in an SWF that you load in. This should fix your error though:
package
{
//Imports
import flash.display.Sprite;
//Class
public class MainClass extends Sprite
{
//Constructor
public function MainClass()
{
//unused variable definition for class embedding purposes
var tempCircle:MyCircle;
var myCanvas:Canvas = new Canvas("MyCircle", 10);
addChild(myCanvas)
}
}
}
While this will prevent MyCircle from being undefined later on, I've always thought of it as a bit of a dirty fix (despite having it in some fairly major projects). I'd love to know a better solution, other than embedding the definition in a separate SWF.
Are you aware that you can treat classes as Objects?
Depending on what you're trying to do you could do something like this:
My Circle:
package
{
//Imports
import flash.display.Shape;
//Class
public class MyCircle extends Shape
{
//Constructor
public function MyCircle(color:uint, radius:uint);
{
graphics.beginFill(color, 1.0);
graphics.drawCircle(0, 0, radius);
graphics.endFill();
}
}
}
Canvas:
package
{
//Imports
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.utils.getDefinitionByName;
//Class
public class Canvas extends Sprite
{
//Constructor
public function Canvas(classToCreate:Class, amount:uint)
{
for (var i:uint = 0; i < amount; i++)
{
var randomColor:uint = Math.random() * 0xFFFFFF;
var randomRadius:uint = Math.random() * 100 + 50;
var circleInstance:DisplayObject = new classToCreate(randomColor, randomRadius);
circleInstance.y = i * randomRadius;
addChild(circleInstance);
}
}
}
}
MainClass:
package
{
//Imports
import flash.display.Sprite;
//Class
public class MainClass extends Sprite
{
//Constructor
public function MainClass()
{
var myCanvas:Canvas = new Canvas(MyCircle, 10);
addChild(myCanvas)
}
}
}
Say i have these two classes:
MAIN.as
package
{
import flash.display.*; import mx.core.*;
import flash.events.*; import mx.collections.*;
import flash.geom.*; import mx.controls.*;
import flash.text.*; import mx.events.*;
import mx.styles.*;
import mx.containers.*;
public class MAIN extends Sprite
{
public var APPLICATION:Application = Application(Application.application);
public var keyDownText:TextField = new TextField();
public function MAIN()
{
stage.addEventListener(KeyboardEvent.KEY_DOWN,KEY_DOWN);
addEventListener(Event.ENTER_FRAME,STEP);
new OBJECT_square().CREATE(10,100,1);
}
public function STEP():void {}
public function DRAW():void {}
public function KEY_DOWN(event:KeyboardEvent):void
{
keyDownText.text = "Key code: " + event.keyCode;
this.addChild(keyDownText);
}
}
}
OBJECT_square.as
package
{
import flash.display.*;
import flash.events.*;
public class OBJECT_square extends Sprite
{
public var X:int = 0;
public var Y:int = 0;
public var DEPTH:int = 0;
public var SPRITE:Sprite = new Sprite();
public function CREATE(X:int,Y:int,DEPTH:int):void
{
this.DEPTH = DEPTH;
this.X = X;
this.Y = Y;
DRAW();
}
public function DRAW():void
{
SPRITE.graphics.beginFill(0xFF0000,1);
SPRITE.graphics.drawRect(X - 10,Y - 10,20,20);
SPRITE.graphics.endFill();
addChild(SPRITE);
}
}
}
Now how is it that I can add the variable SPRITE which is a Sprite in the OBJECT_square class to the display list of MAIN class? I've tried addChild(SPRITE) and super.addChild(SPRITE). If everything works I should see a red square somewhere on the screen but right now its all blank, except for the text drawn in the MAIN class.
Basically I want it so i can just make a new OBJECT_square and it will draw itself without any more instructions from the MAIN class.
Try this:
var obj:OBJECT_square = new OBJECT_square();
obj.CREATE(10,100,1);
addChild(obj);
Or, if you really want to do it in one go, you could try this:
In main
addChild((new OBJECT_square()).CREATE(10,100,1));
And change your draw function to return the square object
public function DRAW():OBJECT_square
{
SPRITE.graphics.beginFill(0xFF0000,1);
SPRITE.graphics.drawRect(X - 10,Y - 10,20,20);
SPRITE.graphics.endFill();
addChild(SPRITE);
return this;
}