Sprite collideswith circle (Android AndEngine)? - android

I have circular sprites and I need to check to see if they collide with any other circle. I tried:
public boolean collision(){
boolean collide=false;
if(spriteNum>0)
for(int x=0;x<spriteNum;x++)
if(yourSprite[spriteNum].collidesWith(yourSprite[x]))
collide=true;
return collide;
}
But that creates a rectangle around it which kind of throws it off. I could use the distance formula to manually calculate if two sprites are in contact, but that seems taxing and each sprite is attached with a circle physics body, meaning there centers are constantly moving (and I don't know how to find the center). Any ideas?

As Alexandru points out, no circle collision detection is supported by AndEngine so far. The best way is to implement it yourself. His solution works fine (fast), but just in case you need a bit more precision, I will post another approximation:
// There is no need to use Sprites, we will use the superclass Entity
boolean collidesWith(Entity circle){
final float x1 = this.getX();
final float y1 = this.getY();
final float x2 = circle.getX();
final float y2 = circle.getY();
final float xDifference = x2 - x1;
final float yDifference = y2 - y1;
// The ideal would be to provide a radius, but as
// we assume they are perfect circles, half the
// width will be just as good
final float radius1 = this.getWidth()/2;
final float radius2 = circle.getWidth()/2;
// Note we are using inverseSqrt but not normal sqrt,
// please look below to see a fast implementation of it.
// Using normal sqrt would not need "1.0f/", is more precise
// but less efficient
final float euclideanDistance = 1.0f/inverseSqrt(
xDifference*xDifference +
yDifference*yDifference);
return euclideanDistance < (radius1+radius2);
}
/**
* Gets an aproximation of the inverse square root with float precision.
* #param x float to be square-rooted
* #return an aproximation to sqrt(x)
*/
public static float inverseSqrt(float x) {
float xhalf = 0.5f*x;
int i = Float.floatToIntBits(x);
i = 0x5f3759df - (i>>1);
x = Float.intBitsToFloat(i);
x = x*(1.5f - xhalf*x*x);
return x;
}
Note I am not the author of the fast inverseSqrt method, it works in Java (and more precisely in Android) because of its floating point representation (see IEEE 754 floating point representation and Java float to byte representation).
For further research, see:
Quake3 fast inverse Sqrt origins
Fast inverse Sqrt implementation in Java

Because there is no circle collision detection in Andengine the only way is to calculate the distance between them
boolean collidesWithCircle(Sprite circle) {
float x1 = this.getX();
float y1 = this.getY();
float x2 = circle.getX();
float y2 = circle.getY();
double a = x1 - x2;
double b = y1 - y2;
double c = (a * a) + (b * b);
if (c <= this.getWidth()*this.getWidth())
return true;
else return false;
}

You can create circular bodies if you are using physics world by using PhysicsFactory.createCircularBody() method.

Related

How can I spawn an object in front of the camera unless the position and direction of my device?

I'm creating a AR game with ARfoundation where the player can swipe a ball to whatever direction.
The problem I encounter is that when the ball is spawned the first time all the other balls that are spawned, will load on the same position as the first ball whatever direction I'm aiming at with my camera.
I want it to get it always spawned in front of the camera no matter the location, position and direction of my phone's camera. Tried using tags to get the location of the camera en the cup of where the ball need to get thrown in but still the ball doesn't get loaded in front of the camera no matter the location. I guess this is not the right way to achieve this and I was wondering what is?
The code I'm using for spawning the ball on a certain location
[SerializeField]
GameObject ball;
public float distanceX;
public float distanceY;
public float distanceZ;
public float ballX;
public float ballY;
public float ballZ;
public void Spawn()
{
distanceX = GameObject.FindGameObjectWithTag("Cup").transform.position.x - GameObject.FindGameObjectWithTag("MainCamera").transform.position.x;
distanceY = GameObject.FindGameObjectWithTag("Cup").transform.position.y - GameObject.FindGameObjectWithTag("MainCamera").transform.position.y;
distanceZ = GameObject.FindGameObjectWithTag("Cup").transform.position.z - GameObject.FindGameObjectWithTag("MainCamera").transform.position.z;
ballX = distanceX / 4;
ballY = distanceY / 4;
ballZ = distanceZ / 4;
Instantiate(ball, new Vector3(ballX, ballY, 10f), Quaternion.identity);
}
A bit hard to tell how your camera and this Cup Object are related and where exactly your object shall be spawned.
But in general for spawning something in front of your main camera you can do e.g.
public void Spawn()
{
// this basically does FindObjectWithTag("Main camera")
var camera = Camera.main.transform;
Instantiate(ball, camera.position + camera.forward * 10f, Quaternion.identity);
}
If you need a different distance then 10 e.g. based on that Cup object you just replace that or add another offset vector.
Either way you should not store it in individual floats just to build a new vector again ;)
E.g. instead of
distanceX = GameObject.FindGameObjectWithTag("Cup").transform.position.x - GameObject.FindGameObjectWithTag("MainCamera").transform.position.x;
distanceY = GameObject.FindGameObjectWithTag("Cup").transform.position.y - GameObject.FindGameObjectWithTag("MainCamera").transform.position.y;
distanceZ = GameObject.FindGameObjectWithTag("Cup").transform.position.z - GameObject.FindGameObjectWithTag("MainCamera").transform.position.z;
ballX = distanceX / 4;
ballY = distanceY / 4;
ballZ = distanceZ / 4;
you would rather do
Vevtor3 distance = GameObject.FindGameObjectWithTag("Cup").transform.position - GameObject.FindGameObjectWithTag("MainCamera").transform.position;
Vector3 ballDelta = distanceX / 4f;
...

How to check the touch points of the circles as in the image in Libgdx?

I am facing problem in getting the touch point of the circle for the game i was developing
I tried to solve this by getting the points as below
public Actor hit(float x, float y, boolean touchable){
if(!this.isVisible() || this.getTouchable() == Touchable.disabled)
return null;
// Get center-point of bounding circle, also known as the center of the Rect
float centerX = _texture.getRegionWidth() / 2;
float centerY = _texture.getRegionHeight() / 2;
// Calculate radius of circle
float radius = (float) (Math.sqrt(centerX * centerX + centerY * centerY))-5f;
// And distance of point from the center of the circle
float distance = (float) Math.sqrt(((centerX - x) * (centerX - x))
+ ((centerY - y) * (centerY - y)));
// If the distance is less than the circle radius, it's a hit
if(distance <= radius) return this;
// Otherwise, it isn't
return null;}
I am getting hit positions inside circle but also the points around it near black spots, i only need the touch points near circle.
Would some body suggest the approach for achieving this.
Im guessing that you are comparing local rect coordinates (ie centerX, centerY) with screen coordinates x,y parameters that you are feeding to the function.
So you probably want to subtract the rect's x,y position from the parameters x,y so your parameters are in local coordinates.
So:
float lLocalX = x-rectX (assuming this is the rects x position on the screen)
float lLocalY = y-rectY (assuming this is the rects y position on the screen)
now you can compare them!
float distance = (float) Math.sqrt(((centerX - lLocalX ) * (centerX - lLocalX ))
+ ((centerY - lLocalY ) * (centerY - lLocalY )));
You can have a Circle object in your Actor: http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Circle.html
Then check if the circle contains that point using the circle.contains(float x, float y) function.
Basically it'll look something like this:
public Actor hit(float x, float y, boolean touchable){
if(!this.isVisible() || this.getTouchable() == Touchable.disabled)
return null;
if (circle.contains(x,y)) return this;
return null;
}
Of course the downside is that if this is a dynamic object and it moves around a lot, then you'd have to constantly update the circles position. Hope this helps :)

opengl 2.0 es view distance

I've just stated learning Opengl ES 2.0 in android and I run into a problem that i don't know how to solve.
I want to create a large plane field, I created it, put on texture but here comes my problem
It doesn't draw all of it it only displays about 10 unit on the Z axe.. X i fine.
So i want to create a big square but it displays a rectangle. It is like someone took a scissors and cut it off a certaint Z coordinate.
I don't even know what part of my code should i put it here, shader ? plane coordinates ? camera settings ?
Thank you for your patient.
It sounds like your plane is getting clipped by the frustum or viewing volume. That is typically set by either glOrtho() or glPerspective(). Try increasing the distance between the near and far plane parameters to these functions.
If you are relying on a default frustum provided by Android, you may have to construct your own frustum, which would look something like this for glOrtho():
typedef struct
{
float f0;
float f1;
float f2;
float f3;
float f4;
float f5;
float f6;
float f7;
float f8;
float f9;
float f10;
float f11;
float f12;
float f13;
float f14;
float f15;
} Mat4;
void Ortho(Mat4 * pMat4, float left, float top, float right, float bottom, float nearPlane, float farPlane)
{
float rcplmr = 1.0f / (left - right);
float rcpbmt = 1.0f / (bottom - top);
float rcpnmf = 1.0f / (nearPlane - farPlane);
pMat4->f0 = -2.0f * rcplmr;
pMat4->f1 = 0.0f;
pMat4->f2 = 0.0f;
pMat4->f3 = 0.0f;
pMat4->f4 = 0.0f;
pMat4->f5 = -2.0f * rcpbmt;
pMat4->f6 = 0.0f;
pMat4->f7 = 0.0f;
pMat4->f8 = 0.0f;
pMat4->f9 = 0.0f;
pMat4->f10 = -2.0f * rcpnmf;
pMat4->f11 = 0.0f;
pMat4->f12 = (right + left) * rcplmr;
pMat4->f13 = (top + bottom) * rcpbmt;
pMat4->f14 = (nearPlane + farPlane) * rcpnmf;
pMat4->f15 = 1.0f;
}

Drawing an arrow head in android

I am trying to draw an arrow to point to objects in am image. I have been able to write code to draw the line but cant seem to be able to find a way to draw the arrowhead.The code I wrote to draw a dragabble line is as follows.I need to draw an arrowhead on ACTION_UP event to the direction in which the line is pointing
if(event.getAction() ==MotionEvent.ACTION_DOWN) {
if (count==1){
x1 = event.getX();
y1 = event.getY();
System.out.println(count+"count of value a;skd");
Toast.makeText(getApplicationContext(), ""+(radius+count), Toast.LENGTH_LONG).show();
Log.i(TAG, "coordinate x1 : "+String.valueOf(x1)+" y1 : "+String.valueOf(y1));
}
}
else if(event.getAction() ==MotionEvent.ACTION_MOVE){
imageView.setImageBitmap(bmp2);
x2 = event.getX();
y2 = event.getY();
posX=(float)(x1+x2)/2;
posY=(float)(y1+y2)/2;
radius=(float) Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))/2;
onDraw();
Toast.makeText(getApplicationContext(), ""+radius, Toast.LENGTH_LONG).show();
}
Hi, for anyone still needing help .This is how I did it in the end
float h=(float) 30.0;
float phi = (float) Math.atan2(y2 - y1, x2 - x1);
float angle1 = (float) (phi - Math.PI / 6);
float angle2 = (float) (phi + Math.PI / 6);
float x3 = (float) (x2 - h * Math.cos(angle1));
float x4 = (float) (x2 - h * Math.cos(angle2));
float y3 = (float) (y2 - h * Math.sin(angle1));
float y4 = (float) (y2 - h * Math.sin(angle2));
c.drawLine(x1, y1,x2,y2 ,pnt);
c.drawLine(x2, y2,x3,y3 ,pnt);
c.drawLine(x2, y2,x4,y4 ,pnt);
I got help from the accepted answer and ios section in stackoverflow
How I would do this is to find the slope of the line, which is drawn between two points(start and end). The slope would be (dy/dx), and that would be a good start point for your arrow. Assuming you want the base of the arrowhead to be perpendicular to the line of the arrow, to find the slope of the base you would find the opposite reciprocal of the slope of the line. for example, lets say that your line has a slope of 2. The slope for the base of your triangle would be (-1/2), because you do (1/(oldslope)) and multiply by -1. I don't know android very well, but if I remember correctly, in Java, you would use a drawPolygon method, and you would have to specify 4 points(3 unique and 1 the same as the first to close it). Given the slope of the base of the tip, we can get our first two points and our final point. You should know before you start the dimensions of the arrowhead you wish to draw, so in this case b will be the length of your baseline. If you take ϴ=arctan(dy/dx), that will give you an angle between the x axis and your baseline. With that ϴ value, you can do ydif = b*sin(ϴ) to get the difference in y value between the two base corners of your arrow. Doing the same thing but with xdif = b*cos(ϴ) gives you the difference in the x value between the two base points. If the location of the final point of the line that the user drew is, say, (x1, y1), then the locations of the basepoints of the triangle would be (x1-(xdif/2), y1-(ydif/2)) and (x1+(xdif/2), y1+(ydif/2)). These two points, p1 and p2, are the first, second, and fourth points in the draw polygon method. To find the third point, we need to find the angle of the original line, by doing ϴ=arctan(dy/dx), this time using your original dy/dx. with that angle. Before we finish the actual calculation of the point, you first have to know how far from the end of your line the tip of the arrow should actually be, in my case, I will use the var h and h = 10. To get the cordinate, (x,y), assuming the cordinate for the line tip is (x1, y1)you would do (x1+hcosϴ, y1+hsinϴ). Use that for the third value in drawPolygon(), and you should be done. sorry if I kind of rushed at the end, I got kind of tired of typing, comment if you need help.
If you managed to draw a line from the input event, you might additionally draw a triangle on its end indicating the direction.
On another project I drew a square everytime a magnetic point on a grid was touched (as you can see here) Sorry I can not provide you any sample code right now. But if that's a suitable approach for you, I might post it later.
Here is a good code, its not mine, It was a Java Graphics2D code that I converted to Canvas. All credit go to the original guy/lady who wrote it
private void drawArrowHead(Canvas canvas, Point tip, Point tail)
{
double dy = tip.y - tail.y;
double dx = tip.x - tail.x;
double theta = Math.atan2(dy, dx);
int tempX = tip.x ,tempY = tip.y;
//make arrow touch the circle
if(tip.x>tail.x && tip.y==tail.y)
{
tempX = (tip.x-10);
}
else if(tip.x<tail.x && tip.y==tail.y)
{
tempX = (tip.x+10);
}
else if(tip.y>tail.y && tip.x==tail.x)
{
tempY = (tip.y-10);
}
else if(tip.y<tail.y && tip.x==tail.x)
{
tempY = (tip.y+10);
}
else if(tip.x>tail.x || tip.x<tail.x)
{
int rCosTheta = (int) ((10)*Math.cos(theta)) ;
int xx = tip.x - rCosTheta;
int yy = (int) ((xx-tip.x)*(dy/dx) + tip.y);
tempX = xx;
tempY = yy;
}
double x, y, rho = theta + phi;
for(int j = 0; j < 2; j++)
{
x = tempX - arrowLength * Math.cos(rho);
y = tempY - arrowLength * Math.sin(rho);
canvas.drawLine(tempX,tempY,(int)x,(int)y,this.paint);
rho = theta - phi;
}
}
Just call this for both sides of your line and it will draw an arrow at each side!

Approach 2D position

I started working on a concept that requires me to find a way to move a rectangle toward a given point at a given speed. I'm developing for Android so this is relatively speed critical (it's going to be calculated every frame for potentially hundreds of objects, as well.)
The solutions I could think of are as follows:
float diff_x = x2 - x1;
float diff_y = y2 - y1;
float length = sqrt((diff_x * diff_x) + (diff_y * diff_y));
float dir_x = diff_x / len;
float dir_y = diff_y / len;
float move_x = dir_x * MOVE_SPEED;
float move_y = dir_y * MOVE_SPEED;
As you can see, this way requires a square root, which I know to be quite costly. I thought of an alternative, which uses trigonometry, but it's costly as well.
float diff_x = x2 - x1;
float diff_y = y2 - y1;
float angle = atan2(diff_y, diff_x);
float move_x = sin(angle) * MOVE_SPEED;
float move_y = cos(angle) * MOVE_SPEED;
Are there any other ways? If not, which of my solutions would be faster? Thanks for any help.
A very common tric you can use is to put everything squarred/power of two/ ^2
this way instead of using sqrt you just use
length = (diff_x * diff_x) + (diff_y * diff_y);
diff_x*diff_x/length

Categories

Resources