Actionscript convert background to Transparent - actionscript-3

The purpose of the function is to covert the background to transparent and then return the bitmapdata, but it seems it do not work. The code is following:
private function transparentConverter( source:BitmapData, threshold:Number = 0.1 ):BitmapData
{
var bitmapData:BitmapData = new BitmapData( source.width, source.height, true, 0x00000000 );
bitmapData.lock();
var color:uint = source.getPixel( 0, 0 );
var x:uint, y:uint;
for ( y = 0; y < source.height; y++ )
{
for ( x = 0; x < source.width; x++ )
{
var c1:uint = source.getPixel( x, y );
var c2:uint = color;
var rx:uint = Math.abs((( c1 & 0xff0000 ) >> 16 ) - (( c2 & 0xff0000 ) >> 16 ));
var gx:uint = Math.abs((( c1 & 0xff00) >> 8 ) - (( c2 & 0xff00 ) >> 8 ));
var bx:uint = Math.abs(( c1 & 0xff ) - ( c2 & 0xff ));
var dist:uint = Math.sqrt( rx*rx + gx*gx + bx*bx );
if ( dist <= threshold )
{
bitmapData.setPixel32( x, y, 0x00000000 );
}else
{
bitmapData.setPixel32( x, y, c1 );
}
}
}
bitmapData.unlock();
return bitmapData;
}
Please advice.

Can you try this :
// This bitmapData should be defined for real, wherever you get that from ...
var source:BitmapData;
if(source == null)
trace("The source cannot be empty");
// Here you get the transformed BitmapData
var destination:bitmapData = transparentConverter( source );
// You apply it to a Bitmap in order to visualize it
var viewBitmap:Bitmap = new Bitmap(destination);
// You add the Bitmap to the stage so you can see it
addChild(viewBitmap);

Theo, thanks for your effort. I think the problem is the functions takes too long to run. After I try your script, a warning messages come out. It said the program takes more than 15 seconds to run and told me to stop running.
I think the function should be OK, but, maybe, not quite practical.
Theo, thank for your time and advice again.
I think the question can be closed.

Theo, the function seems can run, but take some time, however no bitmapdata return.
I receive the bitmpadata by the following code:
bitmapData = transparentConverter( bitmapData );
var bitmap:Bitmap = new Bitmap( bitmapData );
image1.source = bitmap;
The image do not appear.
And also, I can trace( c1 ), and I get a long list of data.
Thanks for your response.

Related

HitTestObject distance bug between two object

I have a car game which is drive reverse.The game over when enemy and car hit each other.I have problem with collision.
Car and enemy hit when they get close each other,but they have still big space in there.
Please check this image.
https://s8.postimg.cc/p85w0wm2t/image.gif
I use this code.
if(dubageri1.hitTestObject(carMC)){
dubageri1.gotoAndPlay(2);
geribas.gericarpti = true;
stage.removeEventListener(Event.ENTER_FRAME,engeller1geri1lev1)
}
Also I tried something like this.But this time collision has late.
var nDistX:Number = Math.abs ( carMC.x - dubageri1.x );
var nDistY:Number = Math.abs ( carMC.y - dubageri1.y );
var nDistance:Number = Math.sqrt ( nDistX * nDistX + nDistY * nDistY );
var sDistx:Number = Math.abs ( carMC.x - dubageri1.x );
var sDisty:Number = Math.abs ( carMC.y - dubageri1.y );
var nsistance:Number = Math.sqrt ( sDistx * sDistx + sDisty * sDisty );
collect.text=String(nDistance);
if ( nDistance < 120 )
{
trace("aha");
dubageri1.gotoAndPlay(2);
stage.removeEventListener(Event.ENTER_FRAME,dsaa);
}
Note:My objects was made as vector.
Does anybody tell me what im doing wrong ?
UPDATE
var aPoint:Point = new Point();
aPoint = carMC.localToGlobal(aPoint);
var bPoint:Point = new Point();
bPoint = dubageri1.localToGlobal(bPoint);
stage.addEventListener(Event.ENTER_FRAME,ilkcikis);
function ilkcikis(event:Event) {
bPoint = root.globalToLocal(bPoint);
var zHit:Boolean = carMC.hitTestPoint(bPoint.x, bPoint.y, true);
textbaba.text = zHit? "! HIT !": "NO HIT";
carMC.x=mouseX;
carMC.y=mouseY;
}

How to place multiple bitmaps in a scrollable rectangle? AS3

This code builds a palette of tiles for use in a map maker program. It takes in an array set by its parent and uses the bitmaps(from the objects) in that array to display a grid of tiles. Right now it only does a 5x5 grid, but what if there are more than 25 tiles in my tileSet? I want to display only the 5x5 tile grid, but be able to scroll through the images. I imagine that I need to make another rectangle to use as its mask and use a ScrollBar to make it scrollRect, but I can't get this working. Please Help.
public function Palette(X:uint, Y:uint, tileSet:Array)
{
addChild(handleGraphics);
var palette:Rectangle = new Rectangle(X, Y, 5*32, tileSet.length*32); //Default size is 5x5 tiles.
handleGraphics.DrawGrid(32,palette.x,palette.y,5,5);
var counter:int = 0;
for(var i:int = 0; i < 5; i++)
{
paletteArray[i] = [];
for(var u:int = 0; u < 5; u++)
{
if(counter >= tileSet.length)
{
counter = 0; //Which frame to show?
}
var b:Bitmap = new Bitmap(tileSet[counter].Graphic);
b.x = (palette.x) + 32 * u; //Align with palette Rectangle.
b.y = (palette.y) + 32 * i; ///////////////////////////////
addChild(b);
var tileObj:Object = new Object();
tileObj.Name = tileSet[counter].Name;
tileObj.Frame = tileSet[counter].Frame;
tileObj.Graphic = tileSet[counter].Graphic;
paletteArray[i].push(tileObj);
setChildIndex(b, 0); //Under grid.
counter++;
}
}
ActivatePaletteListeners();
}
This code works great for a tileSet array that has less than 25 objects. It loops and shows them continuously until it hits 25. I could do without this I guess, but it is a neat affect.
In another class (HandleTiles) I cycle through my tileSet MovieClip and use each frame to create a new object for each tile.
public function GetPaletteTiles(MC:MovieClip)
{
if (tileArray != null)
{
tileArray.length = 0;
}
for(var i:int = 1; i <= MC.totalFrames; i++)
{
MC.gotoAndStop(i); //Change frame for new info.
var tileObj:Object = new Object(); //The object to push to an array of tiles.
var graphicData:BitmapData = new BitmapData(32,32);
graphicData.draw(MC); //Graphic data from sampleTS.
tileObj.Name = MC.currentFrameLabel;
tileObj.Frame = MC.currentFrame;
tileObj.Graphic = graphicData;
tileArray.push(tileObj);
}
BuildIndexArray(15, 20); //Default size 15 x 20.
}
And here I set the tileSet to use
private function ChangeActiveTileset(Mc:MovieClip)
{
activeTileset = Mc;
GetPaletteTiles(activeTileset);
UpdatePalette();
}
I can change the tileSet with a comboBox. That's why I tear down the tileArray every time I call GetPaletteTiles(). Each tileSet is a different MovieClip, like Buildings, Samples, InTheCity, etc.
Sorry I didn't have time to get this code together earlier. Here's tiling code pieces. Because you're using rectangle and you have to stay under max dimensions you have to move the source mc. I think you already know everything else in there.
// set the bmp dimensions to device screensize to prevent exceeding device's max bmp dimensions
if (bStagePortrait) {
iTileWidth = Capabilities.screenResolutionX;
iTileHeight = Capabilities.screenResolutionY;
} else {
iTileWidth = Capabilities.screenResolutionY;
iTileHeight = Capabilities.screenResolutionX;
}
// mcList.mcListVector is the source mc - a regular mc containing mcs, jpgs, dynamic text, vector shapes, etc.
// mcList.mcListBmp is an empty mc
aListTiles = new Array();
iNumberOfTiles = Math.ceil(mcList.height / iTileHeight);
for (i = 0; i < iNumberOfTiles; i++) {
var bmpTile: Bitmap;
// move the source mc
mcList.mcListVector.y = -(i * iTileHeight);
bmpTile = fDrawTile(mcList, 0, 0, iTileWidth, iTileHeight);
mcList.mcListBmp.addChild(bmpTile);
bmpTile.x = 0;
bmpTile.y = (i * iTileHeight);
aListTiles.push(bmpTile);
}
// remove the regular mc
mcList.mcListVector.removeChild(mcList.mcListVector.mcPic);
mcList.mcListVector.mcPic = null;
mcList.removeChild(mcList.mcListVector);
mcList.mcListVector = null;
}
function fDrawTile(pClip: MovieClip, pX: int, pY: int, pWidth: int, pHeight: int): Bitmap {
trace("fDrawTile: " + pX + "," + pY + " " + pWidth + "," + pHeight);
var rectTemp: Rectangle = new Rectangle(pX, pY, pWidth, pHeight);
var bdClip: BitmapData = new BitmapData(pWidth, pHeight, true, 0x00000000);
var bdTemp: BitmapData = new BitmapData(pWidth, pHeight, true, 0x00000000);
bdClip.draw(pClip, null, null, null, rectTemp, true);
bdTemp.copyPixels(bdClip, rectTemp, new Point(0, 0));
var bmpReturn: Bitmap = new Bitmap(bdTemp, "auto", true);
return bmpReturn;
}

Applying shader filter to a BitmapData object ignores passed rectangle - how to properly apply shader filter?

I have the following code, made for testing only, as this was a kind of a bug I wanted to nail:
_shader = new Shader(new TheShader() as ByteArray);
_shader.data.width.value = [64.0];
_shader.data.height.value = [64.0];
_shaderFilter = new ShaderFilter(_shader);
_sequence = new Vector.<BitmapData>();
var smallBD:BitmapData;
var i:int;
_delta = new Point();
var megabase:BitmapData = new TheBitmap().bitmapData;
var _rect:Rectangle = new Rectangle(0, 0, 64, 64);
for (i = 0; i < 64; i++) {
smallBD = new BitmapData(64, 64, true, 0x00808080);
//_rect.x = i;
_rect.y = i;
smallBD.applyFilter(megabase, _rect, _delta, _shaderFilter);
_sequence.push(smallBD);
}
Then I cycle through _sequence in order to see if changing rectangle actually does something. It does nothing, if _shaderFilter is actually a shader filter. Testing with any of the built-in Flash filter works as intended, but with ShaderFilter it sometimes works as if the rectangle supplied is plainly sourceBitmapData.rect, whatever is the source bitmap, and sometimes it behaves like there's no data passed, with boundary being located at weird position - with a bitmap of size 512x384, the edge of the region that's passed to the shader is apparently located at (256,192) or the center of the bitmap. So far I was only able to implement a workaround, that is, first copyPixels() the required region, then applyFilter() in place. Can someone prove that it's a bug and not me doing something wrong?
PS: I am using FlashDevelop with project target being Flash Player 10.3, and I am unaware if FP11 fixes this.
Well, sadly I can't tell you how to fix this, but I can confirm that it isn't your fault!
The problem seems to be that Flash ignores sourceRect entirely when using custom shaders. At first I thought it might be passing the values to an undocumented parameter in the shader, but then I noticed that every pixel of the output bitmap gets changed, even when the sourceRect is smaller or the destPoint is non-zero. Also there doesn't appear to be an inCoord() function to match outCoord(), so it looks like this isn't a use the developers expected!
I can offer one suggestion; instead of copying the ROI to a new BitmapData object, add a float2 offset parameter to your shader, and shift all pixel lookups by this value. It will save some processing.
Here's the reduced test case I used to confirm the behaviour:
ShaderTest.as:
package {
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Shader;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.filters.ShaderFilter;
final public class ShaderTest extends Sprite {
[Embed(source="test.pbj",mimeType="application/octet-stream")]
private static const sCopy : Class;
final private function R( x, y, w, h ) : Rectangle {
return new Rectangle( x, y, w, h );
}
final public function ShaderTest( ) {
super( );
var
s : Shader = new Shader( new sCopy( ) ),
f : ShaderFilter = new ShaderFilter( s ),
d1 : BitmapData = new BitmapData( 256, 256, false, 0 ),
d2 : BitmapData = new BitmapData( 128, 128, false ),
b1 : Bitmap = new Bitmap( d1 ),
b2 : Bitmap = new Bitmap( d2 ),
w : Rectangle = R( 16, 16, 64, 64 );
b2.x = 274;
addChild( b1 );
addChild( b2 );
for( var i : int = 0; i < 8; ++ i ) {
for( var j : int = 0; j < 8; ++ j ) {
d1.fillRect( R( i * 32 + 1, j * 32 + 1, 30, 30 ), (((i + j) & 1) * 0x00FF00) | (i << 21) | (j << 5) );
}
}
d2.applyFilter( d1, w, new Point( 10, 10 ), f );
d1.fillRect( R( w.x, w.y, 1, w.height ), 0xFF0000 );
d1.fillRect( R( w.x, w.y, w.width, 1 ), 0xFF0000 );
d1.fillRect( R( w.x, w.y + w.height - 1, w.width, 1 ), 0xFF0000 );
d1.fillRect( R( w.x + w.width - 1, w.y, 1, w.height ), 0xFF0000 );
}
}
}
test.pbk:
<languageVersion:1.0;>
kernel bugtest <namespace:"Me";vendor:"Me";version:1;>{
input image4 src;
output pixel4 dst;
void evaluatePixel(){
dst = sampleNearest(src,outCoord());
}
}
Output:
(the small square on the right copies from the large square using a shader. The red box shows the sourceRect. The destPoint is (10,10). Despite both of these settings, it actually renders the entire bitmap)

8 queens problem

I am trying to solve the 8 queens problem (where you select a space and it will put down 8 queens so that none of them will hit each other) but i am having trouble making the chess board.
right now i have this
var chessBoard:Array = new Array();
chessBoard["row1"] = [1,0,1,0,1,0,1,0];
chessBoard["row2"] = [0,1,0,1,0,1,0,1];
chessBoard["row3"] = [1,0,1,0,1,0,1,0];
chessBoard["row4"] = [0,1,0,1,0,1,0,1];
chessBoard["row5"] = [1,0,1,0,1,0,1,0];
chessBoard["row6"] = [0,1,0,1,0,1,0,1];
chessBoard["row7"] = [1,0,1,0,1,0,1,0];
chessBoard["row8"] = [0,1,0,1,0,1,0,1];
and i need to know two things
a) will i be able to use this for the problem (will i be able to have it check if any queens will collide by its array coordinates)
b) how do i draw the squares on the chess board to correspond with the numbers
var chessBoard:Array = new Array();
// Setup the array
for(var i:int = 0; i < 4; i++)
{
chessBoard.push(new Array(1,0,1,0,1,0,1,0));
chessBoard.push(new Array(0,1,0,1,0,1,0,1));
}
// Size of the tile
var tileSize:int = 20;
function createChessBoard():void
{
// Itterate through the "chessBoard"-array
for(var i:int = 0; i < chessBoard.length; i++)
{
// Itterate through the arrays in the "chessBoard"-array
for(var j:int = 0; j < chessBoard[i].length; j++)
{
// Create new tile
var tile:Sprite = new Sprite();
// Create the color variable and check to see what value to put
// in it dependingin the value of the current itteration - 1 or 0
var tileColor:int = chessBoard[i][j] * 0xffffff;
// Tile-coloring-setup-thingie-routine
tile.graphics.beginFill(tileColor);
tile.graphics.drawRect(0, 0, tileSize, tileSize);
tile.graphics.endFill();
// Tile positioning
tile.x = j * tileSize;
tile.y = i * tileSize;
// Adding tile to the displaylist
addChild(tile);
}
}
}
// Run function
createChessBoard();
You can assume that cell is black when sum of its coordinates is odd and white if even:
function getColor(x, y) {
return (x + y) % 2 == 0 ? 0 : 1;
}
// or even
function getColor(x, y) {
return (x + y) % 2;
}
You could start with creating a Square class, this would enable you to give specific properties to each Square. You want to avoid having two pieces on one square for instance, you want to set the color, also you would need to know the coordinates such as a1, c4 etc...
To draw your Chessboard, you could create rows of Squares.
private function squares:Array = [];
private function addRow( black:Boolean , _y:int , rowName:String ):void
{
for( var i:int ; i < 8 ; ++i )
{
var sq:Square = new Square();
//alternate colors
if( black )
sq.color = 0;
else
sq.color = 0xffffff;
black = !black;
sq.x = i* sq.width;
sq.y = _y;
//save square Chess coordinates
sq.coord = {letter: rowName , number: i + 1}
addChild(sq);
//add the Square instance to an Array for further reference
squares.push( sq );
}
}
Then simply add the rows
private function createBoard():void
{
var black:Boolean;
var letters:Array = [ a , b , c , d , e , f , g , h ]
for( var i:int ; i < 8 ; ++i )
{
addRow( black , i * squareSize , letters[i] );
black = !black;
}
}
To add a Queen to a specific Square instance , use the squares Array.

Drawing an honeycomb with as3

I'm trying to create an honeycomb with as3 but I have some problem on cells positioning.
I've already created the cells (not with code) and for cycled them to a funcion and send to it the parameters which what I thought was need (the honeycomb cell is allready on a sprite container in the center of the stage).
to see the structure of the cycle and which parameters passes, please see the example below, the only thing i calculate in placeCell is the angle which I should obtain directly inside tha called function
alt text http://img293.imageshack.us/img293/1064/honeycomb.png
Note: the angle is reversed but it isn't important, and the color are useful in example only for visually divide cases.
My for cycle calls placeCell and passes cell, current_case, counter (index) and the honeycomb cell_lv (cell level).
I thought it was what i needed but I'm not skilled in geometry and trigonometry, so I don't know how to position cells correctly:
import flash.display.Sprite;
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
function createHoneycomb (cells:int):void {
var honeycomb:Sprite = new Sprite ();
addChild (honeycomb);
var cell_lv:int = 1;
var increment:int = 6;
var tot_cur_cells:int = 1;
var current_case:int = 0;
var case_counter:int = 1;
var case_length:int = 1;
var max_cases:int = 6;
var nucleus:Sprite = new cell (); // hexagon from library
honeycomb.addChild (nucleus);
for (var i:int = 1; i <= cells; i ++) {
if (case_counter < case_length) {
case_counter ++;
} else {
current_case ++;
if (current_case > max_cases) current_case = 1;
case_counter = 1;
}
if (i == tot_cur_cells) { // if i reach the current level
if (i > 1) cell_lv ++;
case_length = cell_lv;
tot_cur_cells += (increment * cell_lv);
}
var current_cell:Sprite = new cell (); // hexagon from library
honeycomb.addChild (current_cell);
placeCell (current_cell, case_counter, current_case, cell_lv);
}
function centerHoneycomb (e:Event):void {
honeycomb.x = stage.stageWidth / 2
honeycomb.y = Math.round (stage.stageHeight / 2);
}
stage.addEventListener (Event.RESIZE, centerHoneycomb)
stage.dispatchEvent (new Event (Event.RESIZE));
}
function placeCell (cell:Sprite, counter:int, current_case:int, cell_lv:int):void {
var margin:int = 2;
// THIS IS MY PROBLEM
var start_degree:Number = (360 / (cell_lv * 6));
var angle:Number = (start_degree * ((current_case - 1) + counter) - start_degree);
var radius:Number = (cell.width + margin) * cell_lv;
cell.x = radius * Math.cos (angle);
cell.y = radius * Math.sin (angle);
// end of the problem
if (angle != 0) trace ("LV " + cell_lv + " current_case " + current_case + " counter " + counter + " angle " + angle + " radius " + radius);
else trace ("LV " + cell_lv + " current_case " + current_case + " counter " + counter + " angle " + angle + " radius " + radius);
}
createHoneycomb (64);
if you copy and paste this code, it works but you need to create an hexagon and call it in the actionscript library as cell
how can I do to solve it?
I've also thought to use a switch with the cases to align it, but i think is a little bit buggy doing this
Okay, I really loved this question. It was interesting, and challenging, and I got a working result. I didn’t use any of your code as the base though, but started from scratch, so depending on your final use, you might need to change a bit.
I did however created similar variables to those inside of your cells (in the picture). For each cell you have the following properties:
the iterating variable i is equally to your cell number
the radius r equals your level, and expresses the distance from the center (with 0 being the center)
the position p expresses the position in the current radius
the sector s equals your case, but starts with zero
p % r equals your index
I don’t have an angle, simply because I don’t position the individual hexagons using an angle. Instead I base the position of the (fixed) positions of the hexagons at radius 1 and calculate the missing ones in between.
The following code shows my implementation with 61 (60 + the center; but it’s configurable). You can also see the code in action on Wonderfl.
package
{
import flash.display.Sprite;
public class Comb extends Sprite
{
public function Comb ()
{
Hexagon.scale = 0.5;
this.x = stage.stageWidth / 2;
this.y = stage.stageHeight / 2;
// draw honeycomb with 60 cells
drawComb( 60 );
}
private function drawComb ( n:uint ):void
{
var colors:Array = new Array( 0x33CC33, 0x006699, 0xCC3300, 0x663399, 0xFF9900, 0x336666 );
var sectors:Array = new Array(
new Array( 2, 0 ),
new Array( 1, 1 ),
new Array( -1, 1 ),
new Array( -2, 0 ),
new Array( -1, -1 ),
new Array( 1, -1 ) );
var w:Number = 0.50 * Hexagon.hxWidth;
var h:Number = 0.75 * Hexagon.hxHeight;
var r:uint, p:uint, s:uint;
var hx:Hexagon;
for ( var i:uint = 0; i <= n; i++ )
{
r = getRadius( i );
p = getPosition( i, r );
s = getSector( i, r, p );
// create hexagon
if ( r == 0 )
hx = new Hexagon( 0xCCCCCC );
else
hx = new Hexagon( colors[s] );
hx.x = w * ( r * sectors[s][0] - ( p % r ) * ( sectors[s][0] - sectors[ ( s + 1 ) % 6 ][0] ) );
hx.y = h * ( r * sectors[s][1] - ( p % r ) * ( sectors[s][1] - sectors[ ( s + 1 ) % 6 ][1] ) );
addChild( hx );
}
}
private function getRadius ( i:uint ):uint
{
var r:uint = 0;
while ( i > r * 6 )
i -= r++ * 6;
return r;
}
private function getPosition ( i:uint, r:uint ):uint
{
if ( r == 0 )
return i;
while ( r-- > 0 )
i -= r * 6;
return i - 1;
}
private function getSector ( i:uint, r:uint, s:uint ):uint
{
return Math.floor( s / r );
}
}
}
import flash.display.Shape;
class Hexagon extends Shape
{
public static var hxWidth:Number = 90;
public static var hxHeight:Number = 100;
private static var _scale:Number = 1;
public function Hexagon ( color:uint )
{
graphics.beginFill( color );
graphics.lineStyle( 3, 0xFFFFFF );
graphics.moveTo( 0, -50 );
graphics.lineTo( 45, -25 );
graphics.lineTo( 45, 25 );
graphics.lineTo( 0, 50 ),
graphics.lineTo( -45, 25 );
graphics.lineTo( -45, -25 );
graphics.lineTo( 0, -50 );
this.scaleX = this.scaleY = _scale;
}
public static function set scale ( value:Number ):void
{
_scale = value;
hxWidth = value * 90;
hxHeight = value * 100;
}
public static function get scale ():Number
{
return _scale;
}
}