var circles:Array = new Array();
for(var i:int = 0; i < 8; i++)
{
var ball:Ball = new Ball();
ball.x = ???
ball.y = ???
circles.push(ball);
}
What is the best way to position balls around some point lets say in 5-10 distance of each other, is there some formula?
for(var i:int = 0; i < 8; i++)
{
var ball:Ball = new Ball();
// Point has a useful static function for this, it takes two parameters
// First, length, in other words how far from the center we want to be
// Second, it wants the angle in radians, a complete circle is 2 * Math.PI
// So, we're multiplying that with (i / 8) to place them equally far apart
var pos:Point = Point.polar(50, (i / 8) * Math.PI * 2);
// Finally, set the position of the ball
ball.x = pos.x;
ball.y = pos.y;
circles.push(ball);
}
I don't know actionscript3, so this exact code will not work, but it should give you a basic idea
for(int c = 0; c < 8; c++)
{
Ball ball;
ball.x = point.x;
ball.y = point.y;
ball.x += sin(toRadians((c/8) * 360));
ball.y += cos(toRadians((c/8) * 360));
circles.add(ball);
}
If you don't know what "sin" and "cos" do, or what "toRadians" means, just Google something like: "Sine Cosine Trigonometry". You'll find plenty of tutorials.
Here, I found this. It will teach you what "sin", "cos" and "radians" mean.
http://www.khanacademy.org/math/trigonometry
Obviously you could just stick with grapefrukt's answer, it works, but if you want to know what's really going on behind the hood in "Point.polar", check out those videos.
Related
So I am trying to create random, falling snow in a Flash application. Using the following code I have my snow appearing at a random point on the screen.
var mc:snowFalling = new snowFalling();
addChild(mc);
var result:Number = Math.random() * 100;
var randomX:Number = Math.random() * stage.stageWidth;
mc.x = randomX;
snowFalling is the linkage name.
I am unsure how to have the snow both appear multiple times and respawn. Could someone give me a rundown of the code I will need to do this.
First, you need to create as many snowflakes on the screen as you'd like to have. Then, you need to move each snow flake every frame tick. Something like the following is ONE way you could do it. (there are many ways to accomplish this).
var flakes:Vector.<snowFalling> = new Vector.<snowFalling>(); //an array to store all your snow flakes
var mc:snowFalling;
var mc2:snowFalling;
var columns:int = 5;
var rows:int = 7;
var columnWidth:Number = stage.stageWidth / columns;
var rowHeight:Number = stage.stageHeight / rows;
//make 5 columns
for (var i:int = 0; i < columns; i++) {
mc = new snowFalling();
mc.x = (columnWidth * i);// + (Math.random() * (columnWidth * .25)); //to randomize the x position within the column size
addChild(mc);
flakes.push(mc);
//make 7 rows in each column
for (var j:int = 0; j < rows; j++) {
mc2 = new snowFalling();
mc2.x = mc.x;
mc2.y = (rowHeight * j);// + (Math.random() * (rowHeight * .25)); //to randomize the y within the row size
addChild(mc2);
flakes.push(mc2);
}
}
//run the enterFrame function below every frame tick of the application
this.addEventListener(Event.ENTER_FRAME, enterFrame);
function enterFrame(e:Event):void {
//loop through each snowflake in the flakes array
for (var i:int = 0; i < flakes.length; i++) {
flakes[i].y += 2; //move it down 2 pixels
//check to see if it's off screen, if so, move back to the top of the screen (less it's height so it's just off screen at the top)
if (flakes[i].y > stage.stageHeight) flakes[i].y = -flakes[i].height;
}
}
Or, if you wanted a traditional spawn type method, this:
//create a container to hold all the snowflakes
var snowContainer:Sprite = new Sprite();
addChild(snowContainer);
//this function creates a snowflake and puts it at the top of the screen in a random x spot
function spawnFlake(e:Event = null):void {
var mc:snowFalling;
snowContainer.addChild(mc);
mc.x = Math.random() * (stage.stageWidth - mc.width);
mc.y = -mc.height; //just off screen at the top
}
//create a timer that will call the spanFlake function every second
var timer:Timer = new Timer(1000);
timer.addEventListener(TimerEvent.TIMER, spawnFlake);
timer.start();
this.addEventListener(Event.ENTER_FRAME, enterFrame);
//every frame, iterate through all the children of snowContainer and move the flakes down 2 pixels
function enterFrame(e:Event):void {
var flake:snowFalling;
var i:int = snowContainer.numChildren;
//we need to iterate backwards because we are potentially removing items (which would throw our i value out of whack if iterating forwards)
while(i--){
flake = snowContainer.getChildAt(i) as snowFalling;
flake.y += 2;
//if out of bounds, remove the flake
if (flake.y > stage.stageHeight) {
snowContainer.removeChild(flake);
}
}
}
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);
}
}
i'm trying to create a minigame with circles rotating around circles
however, i have a problem when i shoot the circle and it hits the second circle it doesnt continue the angle but "jumping" to the other side i'm sure it something with the angle var that should reset or something. can you help me im getting nervous around here... :(
check the example
This is my code for the enter frame function that deals with the circles
public function UpdateCircles(e:Event):void
{
for (var i:int = 0; i < EnemySpriteVector.length; i++)
{
EnemySpriteVector[i].rotation += EnemySpriteVector[i].enemyspeed;
}
var rad:Number = angle * (Math.PI / 180); // Converting Degrees To Radians
if (IsplayerShoot)
{
playerSprite.x += Math.cos(rad) * PlayerCircleShootSpeed;
playerSprite.y += Math.sin(rad) * PlayerCircleShootSpeed;
for (var j:int = 0; j < EnemySpriteVector.length; j++)
{
if (EnemySpriteVector[j].hitTestPoint(playerSprite.x,playerSprite.y) && (EnemySpriteVector[j].IsCircleHit == false))
{
trace("hit");
EnemySpriteVector[j].IsCircleHit = true;
removeChild(EnemySpriteVector[0]);
EnemySpriteVector.splice(0, 1);
var EnemySprite:Sprite = new EnemySpriteClass();
EnemySpriteVector.push(EnemySprite);
addChild(EnemySprite);
EnemySprite.x = Math.random() * stage.stageWidth;
EnemySprite.y = Math.random() * stage.stageHeight;
IsplayerShoot = false;
}
}
}
else
{
playerSprite.x = EnemySpriteVector[0].x + EnemySpriteVector[0].radius * Math.cos(rad); // Position The Orbiter Along x-axis
playerSprite.y = EnemySpriteVector[0].y + EnemySpriteVector[0].radius * Math.sin(rad); // Position The Orbiter Along y-axis
angle += EnemySpriteVector[0].enemyspeed; // Object will orbit clockwise
playerSprite.rotation = (Math.atan2(playerSprite.y - EnemySpriteVector[0].y, playerSprite.x - EnemySpriteVector[0].x) * 180 / Math.PI); //only rotates the player circle itself
}
}
Looks like when the pink circle hits the green one it simply continues its rotation from where it left of. A quick solution would be to add 180 degrees to the angle. Keep in mind this will only work for static objects. If you want a more dynamic environment I would recommend using vectors (linear algebra). Vector math is really easy to understand and it hides a lot of complex trigonometry. You can start here :)
I’m trying to make a game like tower defence in AS3 and currently cant find solution to check which item in an array has the lower value of distance between enemy and turret, in order to choose which enemy to attack first.
I'm really stuck with this problem and asking for your help.
Here is a short code:
var enemyArray:Array = new Array();
var turretArray:Array = new Array();
addEventListener(Event.EnterFrame, loop);
// adding enemies
for(var i:int=0; i<3; i++){
var enemy:Enemy = new Enemy();
...
...
enemyArray.push(enemy);
addChild(enemy);
}
// adding turret
for(var t:int=0; t<2; t++){
var turret:Turret = new Turret();
...
...
turret.destinationX = 0;
turret.destinationY = 0;
turret.distance = 0;
turretArray.push(turret);
addChild(turret);
}
// loop
function loop(event:Event):void{
for(var j:int=enemyArray.length-1; j>=0; j--){
for(var k:int=turretArray.length-1; k>=0; k--){
// getting destination
turretArray[k].destinationX = turretArray[k].x - enemyArray[j].x;
turretArray[k].destinationY = turretArray[k].y - enemyArray[j].y;
// getting distance between turret and enemy
turretArray[k].distance = Math.sqrt(turretArray[k].destinationX*turretArray[k].destinationX+turretArray[k].destinationY*turretArray[k].destinationY);
// here i need to get min value from all turrets distance
}
}
}
Looks like you just need to be keeping track of the lowest value you've found as you go rather than overwriting it every time (if I've understood your code, correctly).
// loop
function loop(event:Event):void{
for(var k:int=turretArray.length-1; k>=0; k--)
{
turretArray[k].distance = -1;
for(var j:int=enemyArray.length-1; j>=0; j--)
{
var dx = turretArray[k].x - enemyArray[j].x;
var dy = turretArray[k].y - enemyArray[j].y;
var dist = Math.sqrt(dx * dx + dy * dy);
if(dist < turretArray[k].distance || turretArray[k].distance < 0)
{
turretArray[k].distance = dist;
turretArray[k].destinationX = dx;
turretArray[k].destinationY = dy;
}
}
}
}
Here, we store the initial distance value found in turretArray[k].distance, and only overwrite that if we find a lower one. We set it to -1 each time so we can tell if it's been set, yet, or not.
This is the equation you want:
http://www.mathopenref.com/coorddist.html
sqrt( (turret1X - turret2x)^2 + (turret1Y - turret2Y)^2 )
I have several markers on my map and want to center dynamily each time I click on a selected point which show a bunch of markers group.
Does anyone know how to do that in As3?
You could try to use the a formula to get the centroid of the polygon drawn by your markers, assuming it's a polygon. If not, and they're a bunch of scattered points, you need to get the ones on that form the outer bounding segments first.Also, the code assumes the polygon is closed(loops), so the last point is your first point again.
function centreOfMass(polyPoints:Array):Point{
var cx:Number = 0;
var cy:Number = 0;
var area:Number = area(polyPoints);
var result:Point = new Point();
var i:Number,j:Number,n:Number = polyPoints.length;
var factor:Number = 0;
for(i = 0; i < n ; i++){
j = (i+1) % n;
factor = polyPoints[i].x * polyPoints[j].y - polyPoints[j].x * polyPoints[i].y;
cx += polyPoints[i].x + polyPoints[j].x * factor;
cy += polyPoints[i].y + polyPoints[j].y * factor;
}
area *= 6.0;
factor = 1 / area;
cx *= factor;
cy *= factor;
result.offset(cx,cy);//sets x and y to cx and cy
return result;
}
function area(polyPoints:Array):Number{
var i:int,j:int,n:int = polyPoints.length;
var area:Number = 0;
for(i = 0; i < n; i++){
j = (i+1) % n;
area += polyPoints[i].x * polyPoints[j].y;
area -= polyPoints[j].x * polyPoints[i].y;
}
area *= 0.5;
return area;
}
You create an array of points and you use the lat/lon coords as x,y coords. If you're using flash player 10, feel free to change the array into a Vector. and don't forget to do the import.flash.geom.Point.
I didn't come up with the code, I just ported what was on the amazing Paul Bourke website. Tons of handy stuff there.