I'm trying to create a custom class that will create a tile (a small rounded square) when requested, with a small image on it. I can successfully create the tile, as shown in the code below, but I don't know how to pass the class the pictures data.
Is it possible to do this using bitmapData, or by referancing it throught the library (if i store my picture in a movieclip in the library?
Here is my class so far:
package com{
import flash.display.MovieClip;
import fl.transitions.Tween;
import fl.transitions.easing.Strong;
public class tileCreator extends MovieClip{
public var tiled:MovieClip;
public var sourceImage:MovieClip = new MovieClip;
public function tileCreator() {
trace("tile creator");
tiled = new MovieClip;
tiled.graphics.beginFill(0x666666, 0.3);
tiled.graphics.drawRoundRect(-55/2, -55/2, 55, 55, 15, 15);
this.addChild(tiled);
}
}
}
yes, it's possible using BitmapData.
import an image to the library and right-click it to change "settings ...".
you have to check "export for actionscript" and put a name into the second textfield underneath the checkbox - let's say 'MyImage'. (flash automatically adds the base-class of type flash.display.BitmapData).
then you can create an instance of the image saying:
var myImage:MyImage = new MyImage();
it's a BitmapData object, because your MyImage class extends BitmapData.
then you just have to add the BitmapData to the constructor as an argument (rename your class to Tile, because it's not a creator but the tile itself you create. and use a capital letter!).
public class Tile extends MovieClip
{
public function Tile (img:BitmapData)
{
var bmp:Bitmap = new Bitmap(img);
addChild(bmp);
tiled = new MovieClip;
tiled.graphics.beginFill(0x666666, 0.3);
tiled.graphics.drawRoundRect(-55/2, -55/2, 55, 55, 15, 15);
addChild(tiled);
bmp.mask = tiled;
}
}
you need to do it in the folowin way:
function createBitmap ( yourMovieClipYouWantToBeAsImage : DisplayObject ) : Bitmap
{
var bitmapData:BitmapData = new BitmapData ( width, height );
bitmapData.draw ( yourMovieClipYouWantToBeAsImage );
var bitmap:Bitmap = new Bitmap ( bitmapData );
return bitmap; // do what ever you want with it but now as an image
}
You can create a "snapshot" of this using bitmapData. You can then pass this to any other class you want. Code is shown below.
//This code goes into your TileCreator-class
public function draw():BitmapData
{
//True and 0 at the end of creating this bitmap ensure transparancy
//for the transparant pixels (else these would be opaque)
var bmp:BitmapData = new BitmapData(width, height, true, 0);
bmp.draw(this);
return bmp;
}
Related
i have .fla and .as files.
.fla:
import test ;
var b:test = new test();
var myBitmap:BitmapData = new BitmapData(150, 150, true, 0x80FF3300);
var test:BitmapData = new BitmapData(150, 150, false, 0xFF0000);
var myImage:Bitmap = new Bitmap(test);
addChild(myImage);
and .as
package
{
import flash.display.*;
public dynamic class test extends flash.display.BitmapData
{
public function test(arg1:int=621, arg2:int=427)
{
super(arg1, arg2);
return;
}
}
}
But its not working, BitmapData must have the same name like loading .as (test.as), but i don't know how do that :|
If you will not add some functionality on top of the BitmapData why bother creating another class and extend the BitmapBata Class you can just use it directly.
as i understand you are not seeing anything on the screen, well this is normal because you're adding a blank bitmap to the stage ie: its BitmapData has nothing to deliver.
Maybe you need to link the Test class to an image imported into your fla so you'll get something to see on the screen.
Okay, so I've recently been trying to get my head properly around OOP in AS3. Right now I have a really simple scenario where I've got a class, Paddle, which draws a rectangle. In my document class I create two instances of the Paddle class, paddle1 and paddle2.
I've also created a property for my Paddle class which I want to change the colour of the rectangle that it draws. I want to be able to adjust this property from the main class. I know I could do this by passing in attributes when instantiating the class but it seems like a property would be a better way, and now I want to know if this is the right way of thinking or not.
main class:
package
{
import flash.display.Sprite;
import flash.events.Event;
public class Engine extends Sprite
{
private var paddle1:Paddle = new Paddle();
private var paddle2:Paddle = new Paddle();
public function Engine()
{
paddle1.x = 30;
paddle1.color = 0xFF00FF;
stage.addChild(paddle1);
paddle2.x = stage.stageWidth - 45;
paddle2.color = 0xFF0000;
stage.addChild(paddle2);
}
}
}
Paddle class:
package
{
import flash.display.MovieClip;
import flash.display.Shape;
import flash.display.Graphics;
import flash.events.Event;
public class Paddle extends MovieClip
{
public var color:uint = 0xFFFFFF;
public function Paddle()
{
var child:Shape = new Shape();
child.graphics.beginFill(color);
child.graphics.drawRect(0, 260, 15, 80);
child.graphics.endFill();
addChild(child);
}
}
}
If changing the properties in this way is not the best way of doing things then of course say so. Otherwise, what am I doing wrong that it doesn't work? Seems like it's something to do with the order (by the time the main class changes the colour attribute, it's already created the rectangle and it's too late to change it?)
Thanks :D
EDIT: realised it might help to say what happens when I execute this code. Basically changing the color attribute from the Engine class doesn't change the colour of the rectangle and they both just stay white (FFFFFF)
The issue you're having is that when you do:
new Paddle();
Your constructor code is run. What this means is that the Rectangle has already been drawn with the color defined at the top of the class. You're then changing the color property after this, which as you can see has no effect.
I suggest you make a draw() function for your Paddle. It could accept a color and be used to draw the Rectangle. It might look like this:
public class Paddle extends MovieClip
{
private var _child:Shape;
public function Paddle()
{
_child = new Shape();
addChild(_child);
}
public function draw(color:uint):void
{
_child.graphics.clear();
_child.graphics.beginFill(color);
_child.graphics.drawRect(0, 260, 15, 80);
_child.graphics.endFill();
}
}
This way provides an advantage which is that you can modify the arguments of draw() to accept dimensions for your Rectangle or other elements that will affect the visuals. This will be cleaner and faster than having to add more properties to the class itself if you decide you want to do this.
You're then able to do this:
var paddle1:Paddle = new Paddle();
var paddle2:Paddle = new Paddle();
paddle1.draw(0xFF00FF);
paddle2.draw(0xFF0000);
What you might do is to allow the constructor to assign a color in addition to creating a setter for the color, having both calls subsequently drawing the paddle (which, by the way, could also be a simple flash.display.Shape):
Paddle.as:
package
{
//Imports
import flash.display.Sprite;
//Class
public class Paddle extends Sprite
{
//Constants
private static const DEFAULT_COLOR:uint = 0xFF0000;
//Properties
private var mColor:uint;
//Constructor
public function Paddle(color:uint = DEFAULT_COLOR)
{
mColor = color;
draw();
}
//Draw
private function draw():void
{
graphics.clear();
graphics.beginFill(mColor);
graphics.drawRect(0, 0, 15, 80);
graphics.endFill();
}
//Set Color
public function set color(value:uint):void
{
mColor = value;
draw();
}
//Get Color
public function get color():uint
{
return mColor;
}
}
}
so now you can create and position as many Paddle instances as you want, each having their own color setter:
Red Instance:
var paddleRed:Paddle = new Paddle();
paddleRed.y = 10;
addChild(paddleRed);
Green Instance:
var paddleGreen:Paddle = new Paddle(0x00FF00);
paddleGreen.y = 126;
addChild(paddleGreen);
Blue Instance:
var paddleBlue:Paddle = new Paddle();
paddleBlue.color = 0x00FF00;
paddleBlue.y = 260;
addChild(paddleBlue);
Why not do both? :D
public class Paddle extends MovieClip
{
private var color:uint;
private var rec:Shape;
public function Paddle(newColor:uint = 0xFFFFFF) // default color
{
color = newColor;
rec = new Shape();
drawShape();
addChild(rec);
}
public function drawShape()
{
child.graphics.clear();
child.graphics.beginFill(color);
child.graphics.drawRect(0, 260, 15, 80);
child.graphics.endFill();
}
public function setColor(newColor:uint)
{
color = newColor;
drawShape();
}
}
import flash.display.Shape;
import flash.display.Graphics;
stage.addEventListener(Event.ENTER_FRAME, startAnim);
function startAnim(e:Event):void
{
var shape1:Shape = new Shape();
shape1.graphics.beginFill(0x333333,1);
shape1.graphics.drawRect(40,50,250,125);
shape1.graphics.endFill();
addChild(shape1); // this will add a shape of rectangle to stage
}
This is a very simple function creating a rectangle shape on stage. Ok but the problem is how can I convert this SHAPE to MOVIECLIP using ActionScript only so I can add Events to the same (shape1).
hmmm by using a MovieClip instead of a Shape. a MovieClip also has a Graphics object.
import flash.display.MovieClip ;
//import flash.display.Graphics;//not needed
//stage.addEventListener(Event.ENTER_FRAME, startAnim); //remove enterframe
//function startAnim(e:Event):void { //no need for a handler
var shape1:MovieClip = new MovieClip();
shape1.graphics.beginFill(0x333333,1);
shape1.graphics.drawRect(40,50,250,125);
shape1.graphics.endFill();
addChild(shape1); // this will add a MovieClip of rectangle to stage
shape1.addEventListener(MouseEvent.MOUSE_DOWN, dragShape);
function dragShape(E:MouseEvent)
{
shape1.startDrag()
}
shape1.addEventListener(MouseEvent.MOUSE_UP, dropShape);
function dropShape(E:MouseEvent)
{
shape1.stopDrag()
}
//} no need for that either :)
beware that, as such, your function is called on ENTER_FRAME = 25 or more times per second, therefore you'll create and add a clip to stage 25 or more times per second
+ the reference is created locally, in the function, so you won't be able to access "shape1" from outside, once your object is created.
I don't think you can convert a Shape to a MovieClip. What you can do is to create a MovieClip class, and in the constructor generate the Shape object, and add it to the MovieClip.
public class Car extends MovieClip {
private var shape1:Shape = new Shape();
public function Car() {
shape1.graphics.beginFill(0x333333,1);
shape1.graphics.drawRect(40,50,250,125);
shape1.graphics.endFill();
addChild(shape1); // this will add a shape of rectangle to stage
}
}
Shape has also events.
activate
added
addedToStage
deactivate
enterFrame
removed
removedFromStage
render
But since it doesn't extends from InteractiveObject, you can't handle input.
Okay so I have two import pieces of code involved in this. This first tiny bit is what creates an object called OBJECT_arrow. It is located in the main function of my main class:
new OBJECT_arrow().CREATE(this,200,200);
It isn't really all that important. Now this next bit is the OBJECT_arrow class. What it does is loads an external png image and draws it.
package
{
import flash.net.URLRequest;
import flash.display.*;
import flash.system.*;
import flash.events.*;
import Math;
public class OBJECT_arrow extends Sprite
{
public var X:Number = 0; public var Y:Number = 0;
public var DEPTH:int = 0 ;
public var CONTAINER:Sprite = new Sprite();
public var imageLoader:Loader = new Loader();
public var image:URLRequest = new URLRequest ('ARROW.png');
public function CREATE(CONTAINER:Sprite,X:Number,Y:Number):void
{
this.X = X; imageLoader.x = this.X;
this.Y = Y; imageLoader.y = this.Y;
this.CONTAINER = CONTAINER;
CONTAINER.stage.addEventListener(Event.ENTER_FRAME,STEP);
imageLoader.load(image);
DRAW();
}
public function STEP(event:Event):void
{
DRAW();
}
public function DRAW():void
{
addChild (imageLoader);
(CONTAINER as MAIN).DRAW_LIST[(CONTAINER as MAIN).DRAW_LIST.length] = this;
(CONTAINER as MAIN).DRAW_LIST[(CONTAINER as MAIN).DRAW_LIST.length] = DEPTH;
}
}
}
Now I know the mathematics behind rotation and know to rotate before I translate and everything but I simply don't know how to apply the transformation to an external image in as3.
When you load an image with Loader it is stored as an object of type DisplayObject.
If you want it to be rotated, just set the rotation property.
To apply a matrix, you can use the transform() method of the DisplayObject.
You should also take a look at the BitmapData (raw image data) and Bitmap (DisplayObject to hold the BitmapData) classes. Depending on the complexity of what you're trying to do, they may serve you better. Specifically, BitmapData will allow you to lock() the image while you are fiddling with its bits. Flash won't render the BitmapData until you unlock() it, which can be a great performance improvement if you're doing a lot of fiddling.
how can i reference a display object's coordinates according to it's parent object or stage from within the class that creates the object?
essentially when i create a new sprite object from a custom class and add it to the display list, i'd like to include code within the custom class that limits the drag coordinates to the stage, or a section of the stage.
//Frame Script
import Swatch;
var test:Sprite = new Swatch();
addChild(test);
___________________
//Custom Class
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
public class Swatch extends Sprite
{
public function Swatch()
{
init();
}
private function init():void
{
var swatchObject:Sprite = new Sprite();
swatchObject.graphics.beginFill(0x0000FF, 1);
swatchObject.graphics.drawRect(100, 100, 150, 150);
swatchObject.graphics.endFill();
swatchObject.addEventListener(MouseEvent.MOUSE_DOWN, onDrag, false, 0, true);
swatchObject.addEventListener(MouseEvent.MOUSE_UP, onDrop, false, 0, true);
this.addChild(swatchObject);
}
private function onDrag(evt:MouseEvent):void
{
evt.target.startDrag();
//how to limit it's dragability to the Stage?
}
private function onDrop(evt:MouseEvent):void
{
evt.target.stopDrag();
}
}
}
There is some native support for what you want to do. startDrag() accepts a rectangle as a parameter which restricts the region in which the drag can take place.
function startDrag(lockCenter:Boolean = false, bounds:Rectangle = null):void
Hope that helps,
Tyler.