Marker not showing up in the center of circle - java

This is my below code which is drawing a Circle within Circle and taking my current location as the center of the circle. And I am showing a Star Sign Marker on my current location.
Problem Statement:-
Below code is working fine, but the only problem I am having is, the Star Sign Marker, it is not coming in the center of circle. I need my Star Sign Marker (android.R.drawable.star_on) always in the center of the circle exactly.
imageNames[0] is the Center of the Circle (Star Sign Marker) in the below code.
Any suggestions will be of great help to me.
#Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) {
super.draw(canvas, mapView, shadow);
Point screenPts = new Point();
mapView.getProjection().toPixels(pointToDraw, screenPts);
//--------------draw circle----------------------
Point pt = mapView.getProjection().toPixels(pointToDraw,screenPts);
Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setColor(0x30000000);
circlePaint.setStyle(Style.FILL_AND_STROKE);
int totalCircle=4;
int radius=40;
int centerimagesize=13;
for (int i = 1; i <= totalCircle; i ++) {
canvas.drawCircle(screenPts.x,screenPts.y, i*radius, circlePaint);
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),imageNames[i]), ((screenPts.x)+(i*radius)),(screenPts.y), null);
}
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),imageNames[0]), (screenPts.x-(centerimagesize/2)),(screenPts.y-(centerimagesize/2)), null);
super.draw(canvas,mapView,shadow);
return true;
}
Below is the screenshot which I am getting currently in my emulator. I need star sign always to be in the center of circle. I am running android 4.1

To me it seems like you forgot to take your markers size in account. You should probably start to draw somewhere like:
screenPts.x - (centerimagesize + starSignWidth)/2
screenPts.y - (centerimagesize + starSignHeight)/2
All you actually do is to tell the canvas to start drawing your markers top left corner in the middle of the screen. Which means that the star markers center won't be the same as your screens center.
The API for Canvas.drawBitmap(Bitmap bitmap, float left, float top, Paint paint) says:
Draw the specified bitmap, with its top/left corner at (x,y)
http://developer.android.com/reference/android/graphics/Canvas.html#drawBitmap%28android.graphics.Bitmap,%20float,%20float,%20android.graphics.Paint%29
Which is exactly what you do. Your markers top left corner is in the middle of the screen.

Related

How to zoom into mouse position with correct translation

I'm trying to zoom a grid in Processing and I am having trouble with applying the correct translation such that zooming is centered around the mouse position. I have searched the web for a while but nothing I try seems to work.
The screen size is width and height and the mouse position is mouseX and mouseY.
The code I have at the moment is below, but it zooms the grid (controlled by player.zoom) from the top left corner which is not what I want. To update the translation of the grid, player has the 2d vector player.translate.
void mouseWheel(MouseEvent event) {
float zoomFactor = 200.0f;
float scroll = event.getCount();
player.zoom -= scroll * player.zoom / zoomFactor;
// player.translate.x += something;
// player.translate.y += something;
}
If you need more details to answer I can link the repo with the source code.
I have created a very simple mock-up for you which will hopefully point you in the right direction into applying this to your player.
So this little demo shows the zooming in to the centre of an ellipse whilst keeping it as the central focus.
float scale = 1;
// displacement left/right
float xPan = 720;
// displacement up/down
float yPan = 450;
boolean zoomIn = true;
void setup() {
size(1440, 900);
}
void draw() {
// allows us to zoom into the center of the screen rather than the corner
translate(width/2, height/2);
scale(scale);
translate(-xPan, -yPan);
background(200);
// draws the ellipse in the center
ellipse(width/2, height/2, 100, 100);
// does the zooming
if (zoomIn) {
scale *= 1.01;
}
}
I suggest you to copy this into a new project and then comment out specific lines to try to understand what's going on and how you can transfer this over to your own project.
The same principles still apply, I didn't do this with mouse input in the effort of making the program as simple as possible.

How to set rotation of a view based on other view position

I know the question doesn't make a lot of sense, but I have two views.
The first one I set its position X & Y based on touch event on the activity.
The second one is like an arrow fixed in the middle of the activity and I want it to point exactly where the the first view is positioned.
so is there a way that can convert a view's position coordinates into a angle value based from the center of the screen.?
parentView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
marker.setX(event.getX()); // marker is the first view
marker.setY(event.getY());
FixedArrow.setRotation(/* ??? */); //FixedArrow is the second view
return true;
}
});
It's task from geometry from middle school. Basically what you need is to solve right triangle. One side of this triangle is always a line from the centre of the screen to the nearest screen border, another one from centre to the point of user click. Applying there trigonometry, you can calculate an angle.
Final formula and explanation with picture for understanding can be found in this answer
try something like this
public float getAngle(Point target, Point center) {
float angle = (float) Math.toDegrees(Math.atan2(target.y - center.y, target.x - center.x));
if(angle < 0){
angle += 360;
}
return angle;
}
to call it do something like this
Point target = new Point((int) event.getX(), (int) event.getY());
Point center = new Point(parentView.getWidth()/2, parentView.getHeight()/2);
FixedArrow.setRotation(getAngle(target,center));

How to rotate sprite via draw method

I have not found answer for this question anywhere, so let's go.
What i expect:
I want to render rocket. Rocket is flying from given start point with evaluated angle. I'm evaluating angle like this:
getVelocity().angle() - 90f
My problem is to calibrate rocket position on top of the rocket. Image below shows how should it work:
In the top picture is how libgdx render not rotated texture region. In the bottom picture is what i expect: I want to move and rotate texture region with given angle to have (x,y) coordinate on the top of rocket.
What i have:
I tired to write method to draw sprite how i expect but i failed. I think it is caused due to fact that i don't understand documentation of this method.
Following manual:
void com.badlogic.gdx.graphics.g2d.SpriteBatch.draw(TextureRegion region, float x, float y, float originX, float originY, float width, float height, float scaleX, float scaleY, float rotation)
Draws a rectangle with the bottom left corner at x,y and stretching the region to cover the given width and height. The rectangle is offset by originX, originY relative to the origin. Scale specifies the scaling factor by which the rectangle should be scaled around originX, originY. Rotation specifies the angle of counter clockwise rotation of the rectangle around originX, originY.
My code:
public static void drawRotatedTex(SpriteBatch pmRenderer, TextureRegion pmTex, float pmPosX, float pmPosY, float pmAngle)
{
pmRenderer.begin();
pmRenderer.draw(
pmTex, pmPosX, pmPosY, -pmTex.getRegionWidth()/2, pmTex.getRegionHeight(), pmTex.getRegionWidth(), pmTex.getRegionHeight(), 1f, 1f, pmAngle);
pmRenderer.end();
}
Results:
It is moment of collision. As we can see coordinates are offset in relation to rocket.
I don't ask about full solution. For me will be sufficient if someone explain me (on drawing or something) like this method works.
EDIT
Moderation suggested that this question is duplicate of:
libgdx: Rotate a texture when drawing it with spritebatch
I read this topic, but it is not my solution. I know how to rotate my sprite by i don't have idea why coordinates of rocket are offset in relation to rocket top.
EDIT
Invocation of my drawRotatedTex from rocket class:
#Override
public void render(Renderer pmRenderer, float pmX, float pmY) {
SpriteBatch lvSpritebatch = pmRenderer.getSpriteBatch();
Sprite lvSprite = null;
if(mIsExploding)
{
if((lvSprite = mExplosion.getTexture()) != null)
{
lvSpritebatch.begin();
lvSpritebatch.draw(lvSprite, pmX + lvSprite.getWidth()/2, pmY - lvSprite.getHeight()/2);
lvSpritebatch.end();
}
}
else
{
lvSprite = mAnimation.getTexture();
RendererTools.drawRotatedTex(lvSpritebatch,lvSprite,pmX,pmY,getVelocity().angle() - 90f);
}
}
It is not very clear what you are asking, if it's only about moving the origin you would not need that much text. Anyway, I will take a shot at it.
If you want to accomplish what you have in your picture you setup your sprite like this:
sprite.setOrigin(s.getWidth()/2, s.getHeight()); //Centers sprite on top of image.
If I now rotate it in the draw method it rotates around the top center.
sprite.rotate(5);
sprite.draw(batch);
Despite being rotated around the center top of itself it remains position remains the same. If I would set the origin far away from the image and rotate it then the image would travel very far but the position remains the same. Still if you would move it's position 10 pixels to the right the image (wherever it may be) will be moved to the right.
Hope this helps.

Rotated rect changes location

I am trying to rotate a rect and i have to rotate the canvas to do so but the rect changes its location for example, if the rect is in the middle of the screen after the rotation it will go to the side and i cannot figure out how to get it back to the middle.
Here is the code i used:
canvas.save();
canvas.rotate(45);
canvas.drawRect(width/2,height/2, width/2+200, height/2+200, paint);
canvas.restore();
Is there a way to rotate the rect without rotating the canvas so its location will stay the same?
Your rectangle's center differs from the pivot point of the canvas. You can try using the other rotate method to specify the x/y coordinates of the pivot point. As in:
int offset = 200;
int left = width/2;
int top = height/2;
int right = left + offset;
int bottom = top + offset;
canvas.save();
canvas.rotate(45, left + offset/2, top + offset/2);
canvas.drawRect(left, top, right, bottom, paint);
canvas.restore();
Edit:
Just tested the code above and verified that it works (given a few tweaks that I just added, above).
'canvas.rotate' rotates the canvas around the origin of canvas. Origin is top left corner of canvas at initial state.
If you want to rotate a rectangle around the center of the rectangle, move origin of canvas to the center of the rectancle before using 'canvas.rotate'.
Try following code:
canvas.save();
canvas.drawRect(width/2,height/2, width/2+200, height/2+200, paint); // drow rectangle
canvas.translate(width/2+100, height/2+100); // move origin of canvas to the center of the rectangle
canvas.rotate(45); // canvas is roteted around the origine that is the center of the rectangle also. As a result, rectangle is roteted around its center.
canvas.translate(-(width/2+100), -(height/2+100)); // restore origin of canvas at original position
canvas.restore();

libgdx coordinate system differences between rendering and touch input

I have a screen (BaseScreen implements the Screen interface) that renders a PNG image. On click of the screen, it moves the character to the position touched (for testing purposes).
public class DrawingSpriteScreen extends BaseScreen {
private Texture _sourceTexture = null;
float x = 0, y = 0;
#Override
public void create() {
_sourceTexture = new Texture(Gdx.files.internal("data/character.png"));
}
.
.
}
During rendering of the screen, if the user touched the screen, I grab the coordinates of the touch, and then use these to render the character image.
#Override
public void render(float delta) {
if (Gdx.input.justTouched()) {
x = Gdx.input.getX();
y = Gdx.input.getY();
}
super.getGame().batch.draw(_sourceTexture, x, y);
}
The issue is the coordinates for drawing the image start from the bottom left position (as noted in the LibGDX Wiki) and the coordinates for the touch input starts from the upper left corner. So the issue I'm having is that I click on the bottom right, it moves the image to the top right. My coordinates may be X 675 Y 13, which on touch would be near the top of the screen. But the character shows at the bottom, since the coordinates start from the bottom left.
Why is what? Why are the coordinate systems reversed? Am I using the wrong objects to determine this?
To detect collision I use camera.unproject(vector3). I set vector3 as:
x = Gdx.input.getX();
y = Gdx.input.getY();
z=0;
Now I pass this vector in camera.unproject(vector3). Use x and y of this vector to draw your character.
You're doing it right. Libgdx generally provides coordinate systems in their "native" format (in this case the native touch screen coordinates, and the default OpenGL coordinates). This doesn't create any consistency but it does mean the library doesn't have to get in between you and everything else. Most OpenGL games use a camera that maps relatively arbitrary "world" coordinates onto the screen, so the world/game coordinates are often very different from screen coordinates (so consistency is impossible). See Changing the Coordinate System in LibGDX (Java)
There are two ways you can work around this. One is transform your touch coordinates. The other is to use a different camera (a different projection).
To fix the touch coordinates, just subtract the y from the screen height. That's a bit of a hack. More generally you want to "unproject" from the screen into the world (see the
Camera.unproject() variations). This is probably the easiest.
Alternatively, to fix the camera see "Changing the Coordinate System in LibGDX (Java)", or this post on the libgdx forum. Basically you define a custom camera, and then set the SpriteBatch to use that instead of the default.:
// Create a full-screen camera:
camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
// Set it to an orthographic projection with "y down" (the first boolean parameter)
camera.setToOrtho(true, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.update();
// Create a full screen sprite renderer and use the above camera
batch = new SpriteBatch(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.setProjectionMatrix(camera.combined);
While fixing the camera works, it is "swimming upstream" a bit. You'll run into other renderers (ShapeRenderer, the font renderers, etc) that will also default to the "wrong" camera and need to be fixed up.
I had same problem , i simply did this.
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
screenY = (int) (gheight - screenY);
return true;
}
and every time you want to take input from user dont use Gdx.input.getY();
instead use (Gdx.graphics.getHeight()-Gdx.input.getY())
that worked for me.
The link below discusses this problem.
Projects the given coords in world space to screen coordinates.
You need to use the method project(Vector3 worldCoords) in class com.badlogic.gdx.graphics.Camera.
private Camera camera;
............
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
Create an instance of the vector and initialize it with the coordinates of the input event handler.
Vector3 worldCoors = new Vector3(screenX, screenY, 0);
Projects the worldCoors given in world space to screen coordinates.
camera.project(worldCoors);
Use projected coordinates.
world.hitPoint((int) worldCoors.x, (int) worldCoors.y);
OnTouch();
return true;
}

Categories