I'm trying to rotate a sprite based upon where my finger is placed on the touch screen.
I have an arrow and i want the arrow to be pointing at my finger at all times as i'm drag it around over the screen.
I could easily set the sprite to any rotation using sprite.setRotation(angle)
How should i go about this?
Much appreciated if you can point me in the right direction.
(ax, ay) is coordinates of the center of the arrow, and (fx, fy) is the coordinates of the finger, and a is the angle, here is some pseudocode:
dx = fx - ax
dy = fy - ay
if (dx == 0) {
a = 90
return
}
if (dy == 0) {
a = 0
return
}
//tan(a) == abs(dy) / abs(dx) therefore
a = arctan(dy / dx)
if (dx > 0 && dy > 0) {
// do nothing, a is correct
} else if (dx > 0 && dy < 0) {
a = 360 - a
} else if (dx < 0 && dy > 0) {
a = 180 - a
} else {
a = 180 + a
}
I didn't implement and test it yet, I'll do it later if there will be need
Related
I want to move an image over the screen by the accelerometer detection, but the only example I found on is something like this:
public void onSensorChanged(SensorEvent event){
float x = event.values[0];
float y = event.values[1];
if (Math.abs(x) > Math.abs(y)) {
if (x < 0) {
image.setImageResource(R.drawable.right);
textView.setText("You tilt the device right");
}
if (x > 0) {
image.setImageResource(R.drawable.left);
textView.setText("You tilt the device left");
}
} else {
if (y < 0) {
image.setImageResource(R.drawable.up);
textView.setText("You tilt the device up");
}
if (y > 0) {
image.setImageResource(R.drawable.down);
textView.setText("You tilt the device down");
}
}
if (x > (-2) && x < (2) && y > (-2) && y < (2)) {
image.setImageResource(R.drawable.center);
textView.setText("Not tilt device");
}
}
That code only displays a different image depends on the tilt of the phone, but I want to move the same image like "a ball into the screen".
So, i am creating a joystic for a android game, so in my Touching class(implementing InputProcessor) it looks like a :
public class Touching implements InputProcessor{
int y = 0;
int x = 0;
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
x = Gdx.input.getX();
y = Gdx.input.getY();
if (x > 122 && x < 202 && y > 620 && y < 700 )
{
Core.player1.anmov(2); //button 1
}
if ( x > 122 && x < 202 && y > 520 && y < 600)
{
Core.player1.anmov(1); //button 2
}
if (x > 20 && x < 100 && y > 620 && y < 700)
{
Core.player1.anmov(3); //button 3
}
if (x > 222 && x < 302 && y > 620 && y < 700)
{
Core.player1.anmov(4); // button 4
}
return true;
}
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
x = Gdx.input.getX();
y = Gdx.input.getY();
if (x > 122 && x < 202 && y > 620 && y < 700)
{
Core.player1.anmov(7); // button 1
}
if ( x > 122 && x < 202 && y > 520 && y < 600)
{
Core.player1.anmov(8); // button 2
}
if (x > 20 && x < 100 && y > 620 && y < 700)
{
Core.player1.anmov(5); // button 3
}
if (x > 222 && x < 302 && y > 620 && y < 700)
{
Core.player1.anmov(6); // button 4
}
return false;
}
public boolean touchDragged(int screenX, int screenY, int pointer) {
x = Gdx.input.getX();
y = Gdx.input.getY();
return true;
}
so now, if i touch the button which represents moving on X, dragg to button which represents moving on Y, it is still moving on X, until i get my finger out of screen(the touchUP is calling), and then, it it standing, it does not move on Y..
Can anybody help me please? I think this is a very primitive, but i cant find a solution.
I would probably go for something like this in the player class update method itself
//Declare velocity on top so you just have to change this to fine tune speed.
float velocity = 10;
if (Gdx.input.isTouched()) //isTouched should register as long as a screen is touched, you can use pointers for multiple fingers.
{
if (touch within button) //just use Gdx.input.getX / Gdx.input.getY
{
position.X += velocity * Gdx.graphics.getDeltaTime();
{
//do for each button
}
Never used dragging for onscreen buttons myself but theoretically this should work since isTouched registers as long screen is touched. Gdx.input.getX/Y should update. You probably had something in there that only ran once and continued moving your player until a release was registered.
I'm trying to make a game for Android, I have a problem when dealing with multiple resolutions, this is a example of my gameview: http://oi42.tinypic.com/vh6ir6.jpg.
In the small area, there are several pieces of information, while the largest area is my play area. My purpose is to prevent the image (bitmap) from going beyond the edges of the playing area. This is partially working, but it only works with 800x432 resolution (the resolution of my tablet xD )
This is my code:
case MotionEvent.ACTION_MOVE:
//left edge
if (deltaX <= 90 && deltaY <= 400 && deltaY >28){
Static_PositionX = 52;
Static_PositionY = (int)deltaY-35;
Drag = false;
}
//down edge
else if (deltaY >= 380 && deltaX > 90 && deltaX <770) {
Static_PositionX = (int)deltaX-42;
Static_PositionY = 360;
Drag = false;
//right edge
}else if((deltaY <= 390 && deltaY > 20) && deltaX > 770){
Static_PositionX =723;
Static_PositionY = (int)deltaY-35;
Drag = false;
}
// up edge
else if ((deltaX >= 90 && deltaX < 770) && deltaY <= 35 ){
Static_PositionX =(int)deltaX-42;
Static_PositionY = 0;
Drag = false;
}
where deltaX and deltaY are my image coordinates and Static_PositionX/Static_PositionY are a random start position
deltaX=event.getX();
deltaY=event.getY();
Stop using absolute numbers for screen dimensions.
Refer to this answer here in SO on how to get them for current device.
Design your game for a specific resolution.
boolean isLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
int frameBufferWidth = isLandscape ? 480 : 320;
int frameBufferHeight = isLandscape ? 320 : 480;
Bitmap frameBuffer = Bitmap.createBitmap(frameBufferWidth,
frameBufferHeight, Config.RGB_565);
Canvas canvas = new Canvas(frameBuffer); // Do all your drawing on frame buffer
When you actually render graphics on screen, draw the frame buffer on the actual canvas. This way all scaling for different screens would be handled for you.
Canvas canvas = holder.lockCanvas();
canvas.getClipBounds(dstRect);
canvas.drawBitmap(framebuffer, null, dstRect, null);
holder.unlockCanvasAndPost(canvas);
I've got this graph-like circle that is divided in several "portions". I draw these using drawArc on a canvas.
canvas.drawArc(oval, startAngle, sweepAngle, true, fillPaint);
I would like to make these arcs clickeable so I can trigger events when the user taps them. So I decided to override onTouchEvent, then for ACTION_DOWN go through all my portions and check if the touch position lies within them.
I tried this code here which is answering to a similar question, but I am getting strange angle values (i.e. negative values for top right quadrant, values between 180-270 in the rest of them).
public boolean isInArea(float x, float y){
int deltaX = (int) (x - oval.centerX());
int deltaY = (int) (y - oval.centerY());
if (Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)) > mRectShape.width()/2) {
return false;
}
// offset for radiant, depending on quadrant
double offset = 0;
if (deltaX > 0 && deltaY < 0) {
// top right -> nothing to do
} else if (deltaX > 0 && deltaY > 0) {
// bottom right -> add 90 degrees
offset = Math.PI/2;
} else if (deltaX < 0 && deltaY > 0) {
// bottom left -> add 180 degrees
offset = Math.PI;
} else if (deltaX < 0 && deltaY < 0) {
// top left -> add 270 degrees
offset = Math.PI * 3/2;
}
//now calculate angle
double angle = Math.asin(deltaY / deltaX);
double total = angle + offset;
double totalDeg = total * 180 / Math.PI;
Log.d(LOG_TAG, "angle :" + totalDeg);
if(totalDeg > mStartAngle && totalDeg < mSweepAngle){
return true;
}
return false;
}
I also tried without setting the offsets nand then I get negative values for top quadrants, and positive values between 0 and 180 in the bottom ones.
Also tried using atan2 like this:
angle = Math.atan2(deltaY, -deltaX);
What am I missing here?
I have an written an Object called Shape which has a Point representing the topLeftCorner and a Dimension with represents its width and height.
To get the topRightCorner I can simply add the width to the topLeftPoint.x. I use to rotate them on a certain degree around their center. The problem after the rotation is, that my intersects(Shape) method fails, because it does not honor the rotation of the Shapes. The rotation will be the same for each Shape. My current implementation looks like this inside my Shape Object:
public boolean intersects(Shape s){
// functions returning a Point of shape s
return intersects(s.topLeft())
|| intersects(s.topRight())
|| intersects(s.bottomLeft())
|| intersects(s.bottomRight())
|| intersects(s.leftCenter())
|| intersects(s.rightCenter())
|| intersects(s.center());
}
public boolean intersects(Point p){
return p.x >= leftX()
&& p.x <= rightX()
&& p.y >= topY()
&& p.y <= bottomY();
}
Basically I need functions like rotatedLeftX() or rotatedTopRight() to work properly. Also for that calculation I think it doesn't matter when the topLeft point before a rotation of ie 90 will turn into topRight...
I already read this and this Question here, but do not understand it fully.
I modified an algorithm from Stackoverflow to do what you are indicating with rectangles for a battleship game I wrote. Here is the code:
private boolean overlaid(int [][][] shps, int curr)
{
for (int i = curr-1; i>=0; --i)
{
// From: http://stackoverflow.com/questions/306316/determine-if-two-rectangles-overlap-each-other/306332#306332
// if (RectA.X1 < RectB.X2 && RectA.X2 > RectB.X1 &&
// RectA.Y1 < RectB.Y2 && RectA.Y2 > RectB.Y1)
if (shps[curr][0][1] <= shps[i][1][1] &&
shps[curr][1][1] >= shps[i][0][1] &&
shps[curr][0][0] <= shps[i][1][0] &&
shps[curr][1][0] >= shps[i][0][0])
return true;
}
return false;
}
private int [][][] shps = { {{-1,-1},{-1,-1}},
{{-1,-1},{-1,-1}},
{{-1,-1},{-1,-1}} };
The shps parameter is just a matrix indicating the location of the top-left and bottom-right corners of each rectangle using {x0,y0}, {x1,y1}. For example, shps[curr][0][1] == the current shp's y0. For my purposes, I had to use <= and >=. Also, you have to be mindful of the reverse of y if you are using screen coordinates versus Cartesian coordinates. Also DeMorgan's Law if you want to use NOT overlaid.
I have a solution:
lets assume I want to calculate the rotation (90 degrees) of a Shape with x =1, y=1 (topLeft Point) and a width of 4 and a height of 6 around its center (3, 4) == (x1, y2)
rotatedX = x1 + cos(q) * (x - x1) - sin(q) * (y - y1)
rotatedY = y1 + sin(q) * (x - x1) + cos(q) * (y - y1)
in this case:
rotatedX = 3 + cos(90) * (1 - 3) - sin(90) * (1 - 4)
rotatedY = 4 + sin(90) * (1 - 3) + cos(90) * (1 - 4)
this is for a rotation in a cartesian-plane (where positive rotation values means rotation counter-clockwise)
So if you wanna aply a rotation of 90 degrees CLOCKWISE you just have to multiply rotation with -1;