Add multiple images to multiple bodies - actionscript-3

I have the following code and it puts an image to 1 random body.
for (var b:b2Body=world.GetBodyList(); b; b=b.GetNext()) {
for (var i:int=0; i<3; i++) {
var distX:Number = b.GetPosition().x * worldScale - (220 + i * 100);
var distY:Number = b.GetPosition().y * worldScale - 180;
if (b.GetType()==b2Body.b2_dynamicBody) {
myBlock.x = distX + (220 + i * 100);
myBlock.y = distY + 180;
myBlock.rotation = b.GetAngle() * 180 / Math.PI;
//world.DestroyBody(b);
//createBox(220 + i * 100,180,b2Body.b2_staticBody);
}
}
}
I want to be able to add multiple images to multiple bodies. How can I do that?

Im not sure but I can give you a great website. I was learning box2d with it and its very useful
here it is

Related

Properly hovering over isometric tile sprite

I have four classes: Room, TileGrid, HoverTile, and Tile.
Room is composed of walls and a TileGrid. TileGrid is made out of Tile. Currently, I use this code to generate a TileGrid out of Tiles:
this.mapArray = [[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1, 1, 1, 1, 1, 1, 1]];
this._mapHeight = this.mapArray.length;
this._mapWidth = this.mapArray[0].length;
this._tileHeight = 23;
this._tileWidth = 46;
var initialX:Number = 260;
var initialY:Number = 150;
for (var isoY:int = 0; isoY < mapArray.length; isoY++)
{
for (var isoX:int = 0; isoX < mapArray[isoY].length; isoX++)
{
if (isoX == 0 && isoY == 0)
{
var _tile:Tile = new Tile();
_tile.x = initialX;
_tile.y = initialY;
this.addChild(_tile);
}
if (this.mapArray[isoY][isoX] == 1)
{
var _tile:Tile = new Tile();
_tile.x = initialX - (isoX * 20) - (isoY * 20);
_tile.y = initialY - (isoX * 10) + (isoY * 10);
addChild(_tile);
_tile.addEventListener(MouseEvent.MOUSE_OVER, updateHover);
}
}
}
My current issue is that I want to add a white square around the tile that a mouse is hovering over. The code I used to use wasn't sufficient, because transparent parts of the Tile sprite are still counted as part of it. So even if I'm pointing at another Tile2 (which is next to Tile1), for example, if I'm not far enough onto Tile2, it'll highlight Tile1.
So, here's the current code I'm using:
public function updateHover(e:MouseEvent):void
{
var mX:int = e.stageX - (_tileWidth / 2);
var tPoint:Point = pointToXY(mX, e.stageY);
var isoX = tPoint.x;
var isoY = tPoint.y;
if (isoX >= 0 && isoY >= 0)
{
if (isoY < mapArray.length)
{
if (isoX < mapArray[0].length)
{
tPoint = xyToPoint(isoX, isoY);
_tileHover.x = tPoint.x;
_tileHover.y = tPoint.y;
_tileHover.visible = true;
return;
}
}
}
_tileHover.visible = false;
}
public function pointToXY(x:int, y:int):Point
{
x -= 260;
y -= 150;
var pRatio:int = (_tileWidth / 2) / (_tileHeight / 2);
var tX:int = (y + x / pRatio) * (pRatio / 2) / (_tileWidth / 2);
var tY:int = (y - x / pRatio) * (pRatio / 2) / (_tileWidth / 2);
return new Point(tX, tY);
}
public function xyToPoint(x:int, y:int):Point
{
x -= 1;
var worldPoint:Point = new Point(0, 0);
worldPoint.x = (x * (_tileWidth / 2)) - (y * (_tileWidth / 2));
worldPoint.y = (x * (_tileHeight / 2)) + (y * (_tileHeight / 2));
worldPoint.x = worldPoint.x + (_tileWidth / 2);
worldPoint.y = worldPoint.y + (_tileHeight / 2);
worldPoint.x += 260;
worldPoint.y += 150;
return worldPoint;
}
Sorry I have to post so many code blocks. Now, 260 and 150 are the default starting point for the entire room. That said, I'm really confused on how to get the last two functions in particular to work so that they'll give me the correct answer. This is what I expected from using this code:
That would be perfect. But, again, I don't know why the code isn't working. The sizes are all correct and I believe the offset is, too. So, I'm
First, you should add the listener to this, not to _tile, because then you are locked to stage coordinates to determine the tile that's selected, which is not good. Second, your listener should be against MouseEvent.MOUSE_MOVE event, not over, this way you'll constantly get updated mouse coords to properly move your rectangle over tiles. And you have a minor error out there, you have a (0,0) tile created two times, one being inactive.
for (var isoY:int = 0; isoY < mapArray.length; isoY++)
{
for (var isoX:int = 0; isoX < mapArray[isoY].length; isoX++)
{
if (this.mapArray[isoY][isoX] == 1)
{
var _tile:Tile = new Tile();
_tile.x = initialX - (isoX * 20) - (isoY * 20);
_tile.y = initialY - (isoX * 10) + (isoY * 10);
addChild(_tile);
}
}
}
this.addEventListener(MouseEvent.MOUSE_MOVE, updateHover);
Also, it'll be better that you'd store (x,y) pairs on the array (as tiles, most likely), so that your initial array of zeroes and ones would transform into an array of Tile objects. To do that, you first do this:
this.tileArray=[];
for (var i:int=0;i<this.mapArray.length;i++)
this.tileArray.push(new Array(this.mapArray[i].length));
This will create an array of nulls that matches your mapArray by dimensions, that will serve as placeholder for created Tile objects. After you do this, you call this.tileArray[isoY][isoX]=_tile; to place the newly created tile to its place. After that, you can rewrite your listener to this:
public function updateHover(e:MouseEvent):void
{
var p:Point=pointToXY(e.localX,e.localY);
_tileHover.visible = false; // hide hover for now
if ((p.y<0) || (p.y>=tileArray.length)) return; // range error on Y
if ((p.x<0)||(p.x>=tileArray[p.y].length)) return; // range error on X
if (!tileArray[p.y][p.x]) return; // no tile
var _tile:Tile=tileArray[p.y][p.x];
_tileHover.x=_tile.x;
_tileHover.y=_tile.y; // no need to convert xyToPoint() we have coords stored in tile
_tileHover.visible=true;
}

How to position objects randomly on y-axis with a variable distance between each of the objects, which is always greater than a specific value?

I am placing 4 objects through a for-loop on the y-axis. Each object is placed randomly on the y-axis using the following method:
myObject.y = stage.stageHeight * Math.random();
The problem is sometimes the objects are too far from each other and other times they are over lapping each other. What I want to achieve is to always have some distance between each of the two objects. I want that distance to be always greater than a specific value. I have been trying to work this out for 2 days but couldn't figure it out.
Here is what I tried to get rid of overlapping:
function createObstacles():void
{
var currentElements:Array = [];
var myRect:Obstacle;
for(var k:int = 0; k < 4; k++)
{
myRect = new Obstacle();
addChild(myRect);
myRect.x = stage.stageWidth + 30;
myRect.y = stage.stageHeight * Math.random();
obstacles.push(myRect);
currentElements.push(myRect);
}
checkOverlap(myRect,currentElements);
}
function checkOverlap(rect:Obstacle, elements:Array)
{
for(var n:uint = 0; n < elements.length; n++)
{
if(rect.hitTestObject(elements[n]))
{
rect.y = stage.stageHeight * Math.random();
}
}
}
The elements still overlap. About always keeping a distance between each of the two objects, I just couldn't get my head around that. I googled but nothing relevant returned. Any kind of help would be greatly appreciated.
You can set the object's y based on the previous object'y value.
function createObstacles():void
{
var currentElements:Array = [];
var myRect:Obstacle;
var minDistance:int = 5;//the min distance between two objects
var maxDistance:int = 10;//the max distance between two objects.
for(var k:int = 0; k < 4; k++)
{
myRect = new Obstacle();
addChild(myRect);
myRect.x = stage.stageWidth + 30;
if (k == 0)
{
// make sure four objects in one page
myRect.y = stage.stageHeight/2 * Math.random();
}
else
{
var distance:int = (maxDistance - minDistance)*Math.random() + minDistance;
myRect.y = obstacles[k - 1].y + distance;
}
obstacles.push(myRect);
currentElements.push(myRect);
}
}

Wrong angle while drawing a partial circle with AS3

For a flash game project I am working on I want to create a camera which should be able to detect a player through ray-casting. The camera should be able to have different view angles (eg. 45 degrees or 90 degrees), and according to these view angles the ray-casting should vary. Creating the actual view angles using ray-casting doesn't cause a problem, however, for some reason that is beyond me the angles in which these view angles are positioned are wrong.
This is the code I use:
for (var i:Number = 0; i < this._viewAngle; i++)
{
var pointX:Number = (this._viewRange) * Math.cos(this._viewAngle + (i * Math.PI / 180));
var pointY:Number = (this._viewRange) * Math.sin(this._viewAngle + (i * Math.PI / 180));
this._rayHolder.graphics.lineTo(pointX, pointY);
this._rayHolder.graphics.moveTo(0, 0);
}
And this is the result:
(90 degrees)
(45 degrees)
I hope what I wrote was understandable enough, because I don't know how to explain it more clearlyIf anybody could shed some light on what I am doing wrong here, that would be awesome.
EDIT:
Changing Math.cos(this._viewAngle + (i * Math.PI / 180)); to Math.cos((this._viewAngle + i) * Math.PI / 180); results in this:
(90 degrees)
(45 degrees)
I think you're close with your update. As Sunil D points out, you presumably just want to align the vision cone so that it's centred at 90˚ from the vertical. In other words, starting from -_viewAngle * 0.5:
for (var i:Number = 0; i < this._viewAngle; i++)
{
var pointX:Number = (this._viewRange) * Math.cos((-this._viewAngle * 0.5 + i) * Math.PI / 180);
var pointY:Number = (this._viewRange) * Math.sin((-this._viewAngle * 0.5 + i) * Math.PI / 180);
this._rayHolder.graphics.lineTo(pointX, pointY);
this._rayHolder.graphics.moveTo(0, 0);
}
Edit: While these equations work for this application, the following reflect Flash's odd coordinate systems more accurately. Specifically, with positive x to the right, positive y downwards:
for (var i:Number = 0; i < this._viewAngle; i++)
{
var pointX:Number = (this._viewRange) * Math.sin((90 - this._viewAngle * 0.5 + i) * Math.PI / 180);
var pointY:Number = (this._viewRange) * -Math.cos((90 - this._viewAngle * 0.5 + i) * Math.PI / 180);
graphics.lineTo(pointX + 100, pointY + 100);
graphics.moveTo(100, 100);
}

How to create a polygon shape with flat sides in HTML5?

I'm using the following JS code to draw a 16-sided polygon:
context.beginPath();
var x_offset = 350;
var y_offset = 350;
var sides = 16;
var r = 300;
context.strokeStyle = "#000000";
for (i = 0; i < (sides); i++) {
x = x_offset + (r * Math.cos(2 * Math.PI * i / sides));
y = y_offset + (r * Math.sin(2 * Math.PI * i / sides));
context.moveTo(x, y);
x = x_offset + (r * Math.cos(2 * Math.PI * (i+1) / sides));
y = y_offset + (r * Math.sin(2 * Math.PI * (i+1) / sides));
context.lineTo(x, y);
}
context.stroke();
This is working fine, except that I want the polygon to have a 'flat' sides (top, bottom, left, right). In the picture below you see 2 polygons: the polygon with the red background color is what I want to achieve, the transparent polygon is the one generated by the code above.
Question: how can I generate a polygon with flat sides like the red one? Do I need to do a context.rotate()? I would prefer not too, to avoid all the translate() stuff.
You can just rotate by half of the stepping angle
context.beginPath();
for (var i = 0; i < sides; i++) {
var angle = 2 * Math.PI * (i + 0.5) / sides;
var x = x_offset + (r * Math.cos(angle));
var y = y_offset + (r * Math.sin(angle));
if (i == 0) context.moveTo(x, y);
else context.lineTo(x, y);
}
context.closePath();
I made some minor changes like using local variables and factoring out the angle computation (the added 0.5 is what is needed to have a vertical side).
Note that the polygon will have also horizontal sides only if the number of sides is a multiple of 4.

Box to Circle Collision AS3

I'm trying to implement a aabb to circle collision.
Here's my code:
//From another file
radius = (sprite.width + sprite.height) / 4;
private function BoxToCircleCollision(box1:BoundingBox, circle1:BoundingCircle):Boolean
{
var nBoxMinX:Number = box1.sprite.x - box1.sprite.width / 2;
//var nBoxMinY:Number = box1.sprite.x + box1.sprite.width / 2;
var nBoxMaxX:Number = box1.sprite.y - box1.sprite.height / 2;
//var nBoxMaxY:Number = box1.sprite.y + box1.sprite.height / 2;
var nCirMinX:Number = circle1.sprite.x - circle1.radius / 2;
//var nCirMinY:Number = circle1.sprite.y - circle1.radius;
var nCirMaxX:Number = circle1.sprite.x + circle1.radius / 2;
//var nCirMaxY:Number = circle1.sprite.y + circle1.radius;
if (nBoxMaxX, 2 > nCirMinX))
{
Main.WriteDebug("Box max: " + nBoxMaxX + " | Circle min: " + nCirMinX);
return true;
}
else
{
Main.WriteDebug("Box max: " + nBoxMaxX + " | Circle min: " + nCirMinX);
return false;
}
}
Somehow the collision does work as expected.
Either they never move at all and "collided" was traced, or they'll continue moving and never collide when I tried swapping values around.
Is there something i'm missing in my logic???
My box-box and circle-circle collision are working fine.
Thanks in advance for your help.
This row doesn't look at all correct:
var nBoxMaxX:Number = box1.sprite.y - box1.sprite.height / 2;
Maybe you meant this:
var nBoxMaxX:Number = box1.sprite.x + box1.sprite.width / 2;
This line won't compile:
if (nBoxMaxX, 2 > nCirMinX))
Edit:
Here's a function to help you get the AABB <-> Circle collision right. It's not a complete solution but you can combine it with the calculations you have for the AABB min and max values, should be trivial:
private function collideAABBandCircle(c : Circle, aabb:AABB) : Boolean {
var sqDist : Number = sqDist(c.centerPoint, aabb);
return sqDist <= c.radius * c.radius:
}
private function sqDist(p : Point, aabb:AABB) : Number {
/* CALCULATE min and max values of aabb bounds */
var sqDist : Number = 0.0;
if(p.x < minX) {
sqDist += (minX - p.x) * (minX - p.x);
}
if(p.x > maxX) {
sqDist += (p.x - maxX) * (p.x - maxX);
}
if(p.y < minY) {
sqDist += (minY - p.y) * (minY - p.y);
}
if(p.y > maxY) {
sqDist += (p.y - maxY) * (p.y - maxY);
}
return sqDist;
}
There's a good article about using Separating Axis Theorem for 2d collision detection. Great read if you want to find out how 2d collision detection works.