AS3 BitmapData Collision Detection - actionscript-3

So I'm working on a flash game where I'm using bitmapdata to determine collision detection with terrain. The idea was to have two sets of terrain tiles, one with the actual terrain on top and a simpler one with only a few basic colors to determine collision. That way if the hero comes into contact with a certain color on the "heightmap" his movement can be halted, slowed, he can receive damage or be scaled up and down to show variance in height. In order ot do this I need to add a whole bunch of heightmap tiles by means of an array, same way as I add the tiles themselves.
Doing this through bitmapdata is proving to be a lot more difficult than I expected and I keep running into errors when using the following code.
This is the Error that I get: TypeError: Error #1010: A term is undefined and has no properties.
As far as I can tell it's coming from the following bit of the code:
var bitmapData:BitmapData = new BitmapData(heightContainer.heightMapClip.width, heightContainer.heightMapClip.height);
But I have no idea what I'm doing wrong.
Here's the code in its entirety, though I haven't gotten around to the array part yet, just need to get this to work first and I really want to try and figure out the rest for myself:
var heightMapClip = new heightMap();
heightContainer.addChild(heightMapClip);
var heightData:String;
var hContainer:Sprite = new Sprite();
heightMapClip.x=-200;
heightMapClip.y=-200;
var bitmapData:BitmapData = new BitmapData(heightContainer.heightMapClip.width, heightContainer.heightMapClip.height);
bitmapData.draw(heightContainer.heightMapClip);
var myHeightMap:Bitmap = new Bitmap(bitmapData);
heightContainer.addChildAt(hContainer,0);
heightContainer.hContainer.addChild(myHeightMap);
heightContainer.hContainer.addEventListener(Event.ENTER_FRAME, onClick);
function onClick(e:Event):void
{
var obj:Sprite = e.currentTarget as Sprite;
var myHeightMap:Bitmap = Bitmap(obj.getChildAt(0));
var pixelValue:uint = heightContainer.myHeightMap.bitmapData.getPixel(mouseX,mouseY);
heightData=pixelValue.toString(16);
if(heightData=="99ff00"){
trace("Collision Detected");
}
}
Any help on this would be greatly appreciated.

heightContainer.addChild(heightMapClip);
by doing this you don't add property heightMapClip to the heightContainer
heightContainer.heightMapClip.width this will generate error
but this won't (as long as it exists and has width property:))
heightMapClip.width
best regards
p.s. "solved it by accident" doesn't specify solution. Write what you have done to answer to your question so others can see and learn from it.

Related

How to make an instance move

I got the following code and the flash events are all loaded properly. ball is a movie clip and is assigned a class.
var speedx: Number=5;
var speedy: Number=3;
var myball = new ball();
addChild(myball);
addEventListener(Event:ENTER_FRAME,ballmove);
function ballmove(e:Event):void{
myball.x+=speedx;
myball.y+=speedy;
}
But now the instance myball won't move, it is just stuck at position 0,0. Kindly help me and advice how to get this myball to move along a staright line..
If I had dragged and dropped the instance from the library, then
myball.x+=speedx;
myball.y+=speedy;
worked perfectly, but doesn't work after addChild is given.
In your code you incorrectly used Event:ENTER_FRAME when it should be : Event.ENTER_FRAME. I wonder if there is a "silent" error? When testing movies, use Ctrl+Shift+Enter to run the debugger (gives better feedback on issues/errors).
var myball = new ball(); does not mean anything. You declare instance by using this logic : var Name : Type of Data = Value, In your code here you've said only that var Name = Value. Surprisingly it works but I wonder if getting comfortable with that could lead to issues on bigger future projects?
Instance name only affects objects already on Stage. If you're adding by code (from Library) make sure you create a new instance of object by using its Linkage name.
Solution :
In the library, right-click the "ball" object and choose "properties", in there make sure "name" is ball and tick "Export for ActionScript" (you should see "Class" becomeClass: ball). OK that.
Now in your code, you can create new instance by : var myball: ball = new ball();...
Your code should look like
var speedx: Number=5;
var speedy: Number=3;
var myball: ball = new ball();
addChild(myball);
addEventListener(Event.ENTER_FRAME, ballmove);
function ballmove(e:Event):void
{
myball.x += speedx;
myball.y += speedy;
}

How to display an image from URLRequest twice (downloading it only once)?

I am just wondering, if it is possible to load an image via URLRequest once, and display that image twice? Or do i have to load the image 2 times?
Edit:
Also want to ask if it is possible to duplicate the bitmaps when they are loaded in a loop(array).
For example:
var duplicate:Array = new Array(loadedArray.push(e.target.content));
When i am trying the code :
loadedArray.push(e.target.content);
var duplicate:Array = new Array(loadedArray.push(e.target.content));
It doesnt give me any errors, but from before it adds the bitmap with no problem, but now, it doesnt add anything.
And when i tried
var duplicate:Array = new Array(loadedArray as Bitmap);
addChild(duplicate[0]);
I have an error Error #2007: Parameter child must be non-null.
Duplicating Bitmap or BitmapData is easy. There are a lot of options, these are few of them:
// in your case, but can be any Bitmap
var original:Bitmap = Bitmap(loader.content);
// we actually need the bitmapData; separate for easy reading
var originalBitmapData:BitmapData = original.bitmapData;
var duplicate:Bitmap = new Bitmap(originalBitmapData);
// this one returns brand new copy of the BitmapData (sometimes needed)
var duplicate:Bitmap = new Bitmap(originalBitmapData.clone());
copyPixels() on BitmapData is also super fast and can be used for duplication, depending if there is already Bitmap(Data) instantiated.

Edit movie clip definition as3

I'm a bit new to as3, so forgive me if these are dumb questions. Two questions...
Premise:
I'm loading a character from a swf file, and want to add avatar to it. I have him animated walking and also standing (stand_mc, walk_mc). I also have his body parts separated out, so inside each of the animations mc's is a head_mc, body_mc, etc etc.
First question, how can I access the body parts for any animation? here's my code so far:
var WalkAnim:Class = SWFLoader.getClass('walk_mc'); //Using Greensock loader; but it's the same as using appDomain.getDefinition();
var walkAnim:MovieClip = new WalkAnim();
addChild(walkAnim);
Second question, adding walkAnim just creates an instance of the mc definition. How can I edit the definition in the library to do something like..
var Hat:Class = SWFLoader.getClass('accessory_hat_mc');
var hat = new Hat();
WalkAnim:addChild(Hat)//???
So that if I have multiple instances on stage, they'll all be updated. Thanks in advance for the help!
Basically, to access child elements, you use dot syntax. That would look something like this (last line):
var WalkAnim:Class = SWFLoader.getClass('walk_mc');
var walkAnim:WalkAnim = new WalkAnim(); // I have typed your var as WalkAnim, not MovieClip.
addChild(walkAnim);
walkAnim.head_mc.rotation += 5;
To answer your second question, you wont be able to edit the definition at runtime. You can add an item to each instance though:
var Hat:Class = SWFLoader.getClass('accessory_hat_mc');
var myHat:Hat = new Hat();
walkAnim.head_mc.addChild(myHat);

flex: Create a screenshot of UI element

I want to make a screenshot of custom as3 ui element (which was extended from Canvas), and then upload the image on the server.
Could you help me with a small example of this?
I am trying to do the following:
// This is UI component extended from Canvas
var chessBoard:ChessBoard = new ChessBoard();
// I displayed pieces on the board, but didn't add it to the stage (I just need a
// a screenshot, not need them on the canvas)
chessBoard.displayPosition(DataStorage.getInstance().getStoredPosition(0));
var img:ImageSnapshot = ImageSnapshot.captureImage(chessBoard, 300, new PNGEncoder());
var obj:Object = new Object();
obj.complexity = complexity.value;
obj.img = img;
httpService.send(obj);
and getting this error:
ArgumentError: Error #2015: Invalid
BitmapData. at
flash.display::BitmapData() at
mx.graphics::ImageSnapshot$/captureBitmapData()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\graphics\ImageSnapshot.as:186]
at
mx.graphics::ImageSnapshot$/captureImage()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\graphics\ImageSnapshot.as:282]
at
ui::SendForm/send()[/Users/oleg/Documents/chess_problems/problemme/src/ui/SendForm.mxml:53]
at
> ui::SendForm/___SendForm_Button1_click()[/Users/oleg/Documents/chess_problems/problemme/src/ui/SendForm.mxml:16]
This error was caused by missing width and height of the Canvas. I set them and it helped to create bitmap data this way:
var bitmapData:BitmapData = new BitmapData(chessBoard.width,chessBoard.height);
var encoder:PNGEncoder = new PNGEncoder();
var data:ByteArray = encoder.encode(bitmapData);
I wonder how do I send the image to the server via httpService? Is there a way. Also is data = image file?
Here is a post on someone who has done this exact thing in AS3:
Dynamically Create an Image in Flash and Save it to the Desktop or Server
It is possible, and although I have never done it, this may be useful to you: http://www.flash-db.com/Tutorials/snapshot/

Is graphic object bitMapData type the same as bitmapData type?

The title might be a little misleading. Look at my code and I will explain
public static function loadTile(tileDir:String = "empty"):void
{
if(tileDir != "empty")
{
tPoint = new Point(0,0);
tRect = new Rectangle(0,0,30,30);
//load in tile sheet image
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT,tilesLoadInit);
loader.load(new URLRequest(tileDir));
}
}
private static function tilesLoadInit (e:Event):void {
tileImage = Bitmap(loader.content).bitmapData;
tileReady.dispatchEvent(new Event("TileReady"));
}
var tImage:BitmapData = new BitmapData(30,30);
tileNum = tileNumber;
tPoint.x = 0;
tPoint.y = 0;
tRect.x = 0;
tRect.y = 0;
tImage.copyPixels(tileImage,tRect,tPoint);
this.graphics.beginBitmapFill(tImage);
this.graphics.drawRect(0, 0,tWidth ,tHeight );
I create a empty bitMapData called tImage. I then take a predefined variable called tileImage which is a bitMapData as well and contains a picture of an image. tRect is predefined as well its width and height is 30x30. I copy a piece of the image and I put it in tImage. problem is that AS3 throws an error saying that tImage is a incorrect type
ArgumentError: Error #2015: Invalid BitmapData.
But clearly it isnt. my question is that is there something different about the data type of bitMapData and bitMapData type that the graphic object accepts ?
I am trying to do tiling with sprites. I want my tiles to be interactive, so that is why I am using the sprite object instead of using regular bitMaps to represent my tiles. You might be wondering why I wouldnt just use graphics.beginBitmapFill(tImage); and graphics.drawRect(0, 0,tWidth ,tHeight ); to pick out the tiles I want to use. Well reason being is because it turns out that drawRect() first and second parameters actually alter the location of where the actual sprite sits at.
So if I set the x and y properties of the sprite to x = 20, and y = 20. then I set my drawRect(20,20). it actually adds an extra 20 pixels to my x and y coords of my sprite. And I know the reason why, I just need to know a better way. Sorry for so much writing and thanks for your time!
It's not saying the type is wrong, it's saying the object is invalid. I expect you'd get a TypeError if the type was wrong.
You've also not stated where exactly the error is thrown, and are assuming the problem is with tImage on the 8th line. It looks more likely that the problem is with tileImage (which you've given no details about) on line 7.
This is probably because of Flash's inbuilt limit to the size of BitmapData objects. If the total number of pixels is larger than 16,777,215, Error #2015 is thrown.
You can read up on it in the docs: BitmapData, Right above "View the examples".
Here's a trick that used to work if you want to give it a shot: BitmapData workaround