I'm working on a HTML5 game using a canvas element.
I'm drawing a circle like this (the user can move this circle around):
ctx.arc(chomperX,chomperY,chomperRadius,0,Math.PI*2);
I'm placing bomb images on in the canvas like this:
ctx.drawImage(bombImg,bombX,bombY,15,15);
The objective is for the user to move the "chomper" circle over the bomb image and eat it. My questions is, how can I detect that the bomb is INSIDE the circle? I'm trying to do this by calculating the distance from the circle to the bomb image, but I'm getting mixed results. Here's how I'm getting the distance.
bx = bombX - chomperX;
by = bombY - chomperY;
bombDistance = Math.floor(Math.sqrt(bx * bx + by * by))
if (bombDistance < bombRadius + chomperRadius) { console.log("THE BOMB IS IN THE CIRCLE!"); }
Assuming the bombRadius is less than chomperRadius,
bx = bombX - chomperX;
by = bombY - chomperY;
bombDistance = Math.sqrt(bx * bx + by * by);
if (bombDistance < chomperRadius - bombRadius) { console.log("THE BOMB IS IN THE CIRCLE!"); }
Related
Hey everyone so I am having some trouble with this. So I have an Array of Barrel Movie clips that are added to the stage and a movie clip called Circle that when comes in contact with any of the barrels in the array the barrel that it is currently hittesting starts to rotate. It rotates on its registration point which is centered. So in my ENTER_FRAME event is where I have everything setup for the barrel to rotate and hit Test etc...
This is how the circle is added to the barrels:
if (!circleFired)
{
circle.x = globalFirePoint.x;
circle.y = globalFirePoint.y;
currentCannon.addChildAt(circle, 0);
}
Now what I am trying to accomplish is when the user taps the screen the circle Movie clip is shot from the Barrel. Right now I have the circle shooting from the barrel in the angle that its supposed to shoot but instead of going in a straight line from the angle it shoots it shoots and starts to curve really quickly in the clockwise position that the barrel is rotating in.
Here is the code I have that is sort of working besides that one problem:
var dX:Number = globalFirePoint.x;
var dY:Number = globalFirePoint.y;
var angle:Number = Math.atan2(dY, dX);
if (circleFired)
{
circle.x += Math.sin(deg2rad(angle -90)) * velocity;
circle.y += Math.cos(deg2rad(angle - 90)) * velocity;
}
so the globalFirePointis this:
globalFirePoint = localToGlobal(new Point(currentCannon.mcFirePoint.x, currentCannon.mcFirePoint.y));
Its the starting point I want the circle to shoot from.
Here is the deg2rad Function:
private function deg2rad(num:Number):Number
{
var radians:Number = num * (Math.PI / 180);
return radians;
}
I know that I need sin and cos to calculate the angle correct? Is the math wrong? Why is the circle curving when the circle shoots from the globalFirePoint? What can I do to make it go in a straight line?
Any help would be appreciated thanks!
Does globalFirePoint change on each ENTER_FRAME event? If so then the calculated angle is going to change as well, leading to the curve you are experiencing.
One way to fix this is to only calculate globalFirePoint when the user presses the screen. Then on every ENTER_FRAME event instead of re-calculating globalFirePoint, use the already calculated globalFirePoint that won't change unless the user presses the screen when the circle is in a barrel.
You should only calculate the angle when the user presses the screen as well. There is no need to calculate it on every ENTER_FRAME event, since the only time you're interested in the angle is when the circle is shot from a barrel.
I'm building a simple space shooter game
using Tweener class I wrote a code that fires a bullet from the hero spaceship current position to the mouse current position
var fire = new Bullet();
addChild(fire);
fire.x = ship.x + (ship.width * 0.5);
fire.y = ship.y
Tweener.addTween(fire, {x:_me.currentTarget.mouseX, y:_me.currentTarget.mouseY, time: 5} );
the problem is this code makes the bullet stop at the last mouse position
and I want the bullet to continue moving in the same direction until it's outside of the stage.
theoretically, the most simple way would be to input x.y position of the mouse as if it was at the same angle but outside of the stage
but how can i get those x,y coordinates??
determine the angle of the bullet.
using the angle, consider the origin of the bullet the center of a circle and the first point as a coordinate at the edge of the circle.
for the bullet to follow the same path, its just a larger circle, so the radius will increase.
the angle will be the same and so will the origin.
I think what you you want is to find a point one the same straight line with (fire.x, fire.y) , (_me.currentTarget.mouseX, _me.currentTarget.mouseY). And the point's x would be stage width.
So assume target point is A(stage.width, targetY)
We get
(targetY - mouseY)/(targetX - mouseX) = (mouseY - fire.y)/(mouseX - fire.x)
So
targetY = (mouseY - fire.y)/(mouseX - fire.x)*(targetX - mouseX) + mouseY;
Hero mouseX is _me.currentTarget.mouseX, mouseY is _me.currentTarget.mouseY
You can set targetX = stage.width + 10, then targetY
So you can get targetY, and do another tween
Tweener.addTween(fire, {x:targetX, y:targetY , time: 5} );
I'm working on my own tile bliting engine, this one is using hexagonal tiles - but I think it doesn't differ much from regular tiles.
I have huge x,y array of tiles and they have their x,y coordinates for rendering on canvas, I iterate only the ones that should be visible on canvas in current camera position.
So I'm stuck with scaling and cant resolve this on my own.
Here is my code for drawing tiles on canvas:
public function draw():Void{
clearCanvas(); //Clear canvas (bitmapData)
var _m:Matrix;
iterateTiles(function(_tile:HexTile):Void{ // loop every tile that is visible on screen
_m = new Matrix();
_m.translate(_tile.x + cameraPoint.x,_tile.y + cameraPoint.y);//Get pre calculated tile x,y and add camera x,y
_m.scale(matrixScale, matrixScale);
drawToCanvas(_tile,_m);//Send to draw tile on canvas using Matrix
},true);
}
This works nice and fast but only problem is it scales tiles from left top corner (like regular scale would work)
Before scale
After scale
My question is how to transform tiles to always scale from center. So if tile 10:10 is in center of screen before scaling, then it should
stay there after scaling.
Sorry, I misunderstood the question, but I think I've got it now:
// Scale the distance from the original point to the center of the canvas
var xDistance:Number = ((_tile.x + cameraPoint.x) - xCenter) * matrixScale;
var yDistance:Number = ((_tile.y + cameraPoint.y) - yCenter) * matrixScale;
// Add the distances to the center of the canvas. This is where you want the tile
// to appear.
var x:Number = xCenter + xDistance;
var y:Number = yCenter + yDistance;
// Because the coordinate is going to be scaled, you need to increase it first.
x = (1 / matrixScale) * x;
y = (1 / matrixScale) * y;
_m.translate(x, y);
I have not tested this, I've just drawn it out on graph paper. Let me know if it works.
I have a big problem when I try to rotate my projectiles along with the ship's rotation.
I want my spaceship shoot two shots at once. So I used my first array of projectiles and placed them at the right side of the ship (one shot on the left and one on the right). So far so good.
But when I shoot with my spaceship and I turn around the rotations of the projectiles look very strange. It's hard to describe so here's an image that shows the error in action.
http://imageshack.us/photo/my-images/841/projectilebug.jpg
I have huge problems rotating the projectiles ALONG with the spaceship so that it looks really good. Currently there is one single shot only. My shooting gets screwed up when I rotate and fire at once.
The goal is to create a dual firing cannon like in the picture shown.
Here is some code that places the projectile at the left of the ship (that doesn't really work):
var projectileRadians:Number = (player.frame / 180) * 3.14159;
tempProjectile.x = (player.point.x + 6) + Math.cos(projectileRadians);
tempProjectile.y = (player.point.y + 3) + Math.sin(projectileRadians);
The velocity code:
tempProjectile.nextX = tempProjectile.x;
tempProjectile.nextY = tempProjectile.y;
tempProjectile.dx = rotationVectorList[player.frame].x;
tempProjectile.dy = rotationVectorList[player.frame].y;
This updates the position:
nextX += (dx * (speed + Math.abs(xAdjust))) * step;
nextY += (dy * (speed + Math.abs(yAdjust))) * step;
The velocity code looks ok. You don't seem to be calculating the gun position correctly.
Edit: we're not using the standard trig frame of reference; instead, we're using one where angle=0 means up and angles increase as you rotate clockwise. So we take the standard usage and swap sin and cos.
Here, gx and gy mean the coordinates of a gun relative to the coordinates around which the ship moves. We need to rotate the vector <gx, gy> by the angle before adding it to the ship coords:
cs = Math.cos(projectileRadians);
sn = Math.sin(projectileRadians);
tempProjectile.x = player.point.x + gx * sn - gy * cs;
tempProjectile.y = player.point.y + gx * cs + gy * sn;
It would be a good optimization to restrict the ship's angle to certain values (perhaps every 5 degrees), and put all the trig functions into a table ahead of time. Trig functions are expensive to compute.
Note that this also assumes that positive Y is "up". Computer graphics often start with (0, 0) in the upper left corner and increase Y as you move down, so you may have to switch the sign of Y.
Hey gang. Stumped on something.
I have a disc I am rotating with the mouse with event.MOUSE_MOVE, like a jog wheel on some audio equipment. Everything almost works as expected, but the problem I am experiencing is that the disc always jumps to the point where the user clicks on the disc. I need the point on the disc that the user clicks on to remain under the mouse while the user spins the disc but I can't seem to come up with the correct math to make it happen. Here's the code i am using:
var xd = (_knob.x - _stageRef.stage.mouseX);
var yd = (_knob.y - _stageRef.stage.mouseY);
var radAngle = Math.atan2(yd, xd);
_knob.rotation = int(radAngle * 360/(Math.PI * 2) - 90);
_knob is a vector circle wrapped in a movieclip, with the circle centered on the movieclip's reg point. _stageRef represents the main stage.
Any help would be awesome. I've scoured the interweb and can't come up with anything.
Thx!
You are setting _knob rotation to the angle between _knob and mouse cursor. So if rotation was 0, and angle 45, rotation becomes 45, therefore it jumps. What you need is measure changes in this angle, not setting it instantly:
var _mouseAngle:Number;
function getMouseAngle():Number
{
var xd = (_knob.x - _stageRef.stage.mouseX);
var yd = (_knob.y - _stageRef.stage.mouseY);
return Math.atan2(yd, xd);
}
function onMouseDown(event:MouseEvent):void
{
_mouseAngle = getMouseAngle();
}
function onMouseMove(event:MouseEvent):void
{
var newAngle:Number = getMouseAngle();
_knob.rotation += (newAngle - _mouseAngle) * 180.0 / Math.PI; //EDIT: forgot to convert into degrees
_mouseAngle = newAngle;
}
(Code not tested)