i have ran into a quick problem which i do not know how to do it by myself but i'm sure with your help i will understand more.
I've created a level editor for the game engine i am creating and i am trying to make the mouse position snap to a 32x32(grid) or 64x64(grid) so that the tiles are placed correctly and not overlapping each other.
So that its not like this :
http://imgur.com/Sa3bh0H
but more like this :
http://imgur.com/a/nck9N
Sorry for the really bad explanation.
The mouse position code i am using is
public int getMouseX() {
return mouseX; // Get MouseX
}
public int getMouseY() {
return mouseY; // Get Mouse Y
}
public void mouseMoved(MouseEvent e) {
mouseX = (int)(e.getX() / gc.getScale() /*+ gc.getWindow().getFrame().get*/);
mouseY = (int)(e.getY() / gc.getScale()); //CODE TO GET MOUSE X AND Y
}
//Code Which Loads the texture/image where the mouse is
tMouseX = gc.getInput().getMouseX() -32;
tMouseY = gc.getInput().getMouseY() - 32;
putImage((int)tMouseX,(int)tMouseY,r);
//putImage Function
public void putImage(int x, int y)
{
objects.add(new Grass(x,y));
}
Trying to make the images snap to 32x32
Don't worry about snapping the mouse to the grid, you don't really want to do that. What you want is to snap the tile to the grid.
The best way to do this is with integer division. Divide by your tile size using integers to truncate the remainder (or use floor) and then scale back up by multiplying by your tile size.
int tilepos_x = (int)(mousex / tileSize) * tileSize;
int tilepos_y = (int)(mousey / tileSize) * tileSize;
Related
Faced a problem while trying to handle clicking on a moving image.
I used InputAdapter.touchDown() to handle the click and created Sprite for the image. Then I set the borders through Sprite.setBounds(). Further, in fact, the problem: if the coordinates in setBounds() are unchanged - the click is handled correctly. But if you change them (position.x++, for example) - the object comes into motion, but clicks are not read.
I can’t understand where the reason.
I tried to make a alterable variable outside the method, but this also didn't bring any result.
I tried using batch.draw(img) instead of img.draw(batch) - the effect is the same.
I tried to relocate Gdx.input.setInputProcessor() to the render() method, after img.setBounds() - nothing changed.
I even compared the coordinates of the Img and the Bounds area online, in motion - they are the same, as it should be.
Img and handler in constructor:
img = new Sprite(new Texture(finSize));
centerX = Gdx.graphics.getWidth()/2-img.getWidth()/2;
centerY = Gdx.graphics.getHeight()/2-img.getHeight()/2;
startPosition = new Vector2(centerX, centerY);
Gdx.input.setInputProcessor(new InputAdapter(){
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
if(img.getBoundingRectangle().contains(screenX, screenY))
System.out.println("Image Clicked");
return true;
}
});
Render:
public void render(SpriteBatch batch, float radius, float boost) {
speed+=boost;
nextX = radius * (float) Math.cos(speed); // Offset step X
nextY = radius * (float) Math.sin(speed); // Offset step Y
// Img is moving, but clicks is not handling
img.setBounds(startPosition.x+ nextX, startPosition.y + nextY, 100, 100);
// Handling clicks fine, but img is motionless
img.setBounds(startPosition.x, startPosition.y, 100, 100);
img.draw(batch);
// Checking coordinates - all's fine
System.out.println(img.getBoundingRectangle().getX());
System.out.println(startPosition.x + nextX);
System.out.println(img.getBoundingRectangle().getY());
System.out.println(startPosition.y + nextY);
}
So, I sequentially compared the XY coordinates of the image and the mouse click point and came to the conclusion that InputAdaper and Sprite consider Y differently - from above and from below. Therefore, X always coincided, and Y had a big difference in values.
As a result, I entered two corrected coordinates xPos \ yPos (Y subtracted from the total field height) for the center of the pic and in the touchDown() method, instead of comparing with BoundRectangle, simply compared the difference in the coordinates of the pic and the click modulo. If the result into the image size range - everything is ok.
Now clicks on the moving image works correctly.
public void render(SpriteBatch batch, float radius, float boost) {
speed+=boost; // rotational speed
nextX = radius * (float) Math.cos(speed); // Offset step X
nextY = radius * (float) Math.sin(speed); // Offset step Y
// set image size and position
img.setBounds(startPosition.x+nextX, startPosition.y+nextY, 100, 100);
img.draw(batch);
// Corrected coordinates of the image for InputAdapter coordinate system
xPos = img.getX()+img.getWidth()/2;
yPos = Gdx.graphics.getHeight()-img.getY()- img.getHeight()/2;
// Check the coincidence of the coordinates of the image area and the click point
Gdx.input.setInputProcessor(new InputAdapter(){
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
if((Math.abs(xPos-screenX)<=img.getWidth()) && (Math.abs(yPos-screenY)<=img.getHeight()))
{System.out.println("Image Clicked");}
return true;
}
});
}
Is there some sort of formula for rotating the arrow in this link right here to make sure it's always pointing toward the red? Each time I've tried, I'd always get a number that's off, and the arrow's rotation is not in sync with the arrow's turning and movement.
A couple of snippets of code to show what I'm working with:
arrow.moveX(true);
arrow.moveY(true);
if(arrow.turning) {
arrow.turn(player.direction / (0.75 * arrow.getSpeed()));
}
The arrow's speed is 12.5 units/time if that's important. As for the movement itself:
public void moveX(boolean turn) {
if(turn) {
x += speed * Math.cos(angle);
} else {
x += speed;
}
}
public void moveY(boolean turn) {
if(turn) {
y += speed * Math.sin(angle);
} else {
y += speed;
}
}
I'm trying to figure out how to render the arrow's sprite make sure that the pointer itself is facing that "forward" direction that it's moving in, no matter how much it rotates. Here is the render method itself if that's necessary:
#Override
public void render(Canvas c, Paint p) {
matrix.setTranslate((float)x, (float)y);
if(alive) {
matrix.postRotate(drawnAngle, (float) (x + width / 2), (float) (y + height / 2));
} else {
matrix.postRotate(angle, (float) (x + width / 2), (float) (y + height / 2));
angle += speed * 2;
}
c.drawBitmap(getSprite(), matrix, p);
}
The variable drawnAngle has a value of 0 right now, it's a placeholder. It was just my attempt of trying to find the right number to rotate the arrow by.
So I've actually spent hours trying to figure this out, and the moment I decide to post for help, I figured it out! It turns out that while I was using radians in the first snippet of code (the actual movement), I was supposed to be using degrees in the actual rotate in that last snippet!
I changed drawnAngle to (float)(angle * (180 / Math.PI)) and this worked as a solution for me!
Hopefully no one else has this problem.
I have a Camera class that basically follows the player around the map and keeps him centered on the screen. The math im applying works great until the scale(Zooming in and OUt) of the camera is altered. Here it is:
x = -cell.x - cell.mass/2 + Game.width/2 / sX;
// Where x is the Camera's X, Cell is the Player and sX is the scale factor
I've been playing around with different equations but they all fail once the scale is altered. I can't seem to wrap my head around this and I could really use some insight on how to factor it in.
Here are some bits of the Camera Class:
public void set(Graphics bbg){
Graphics2D g2 = (Graphics2D)bbg;
g2.translate(x, y);
g2.scale(sX, sY);
}
public void unset(Graphics bbg){
Graphics2D g2 = (Graphics2D)bbg;
g2.translate(-x, -y);
}
public void scale(double sx, double sy){
sX = sx;
sY = sy;
}
public void Update(Cell cell){
scale(0.9,0.9);
x = -cell.x - cell.mass/2 + Game.width/2 / sX;
y = -cell.y - cell.mass/2 + Game.height/2 / sY;
}
public double toWorldX(int x){
return x - this.x / sX;
}
public double toWorldY(int y){
return y - this.y / sY;
}
The first image displays the result when the scale factor is 1(Normal Zoom). The second image displays the result when the scale factor is 0.9(Zoomed Out).
I'm having a little difficulty in determining what some of your variables mean (such as cell.mass, I'm assuming it is the size) and I assume that Game.width is the actual width of the window. It would help to know what EXACTLY happen when the zoom is changed (like is the "center" of the zoom at a particular corner of the screen).
Now for an answer, without know what happens to the actual zoom... have you tried the addition of parenthesis like this...
x = ((cell.x + cell.mass/2) - Game.width/2) / sX;
or (because you use '-' a lot, I'm not sure how your coordinates work)
x = ((-cell.x - cell.mass/2) + Game.width/2) / sX;
Just an idea.
The working equation for making the camera follow a player while factoring a scale factor is:
x =((cell.x + cell.mass * 0.5) - Game.width/sX * 0.5);
I am making a game where a ball goes and collects other balls.
I have written a collision detector, but I am finding that it is a little off kilter.
If the controlled ball is about 10 pixels to the right of the ball to be collected, it will still register a collision.
If the user's ball is on the left side of the ball to be collected, the collision works well.
Could someone please explain why this is happening and/or suggest a fix? Thanks!
Here is my collision detector:
private void checkForCollision(UserBall b) {
int ballX = b.getX();
int ballY = b.getY();
int ballR = b.getRadius();
int a = x - ballX;
int bb = y - ballY;
int collide =radius + ballR;
if (a*a + bb*bb <=collide*collide){
performAction(b);
createNew= true;
}
}
This is js code, nearest I found on my computer. It works fine.
Ball.prototype.intersects = function (p) {
'use strict';
switch (p.id) {
case IDS.Ball:
var dist = this.radius + p.radius,
dx = this.x - p.x, //x - is center of Ball
dy = this.y - p.y;
return dist * dist >= (dx * dx + dy * dy);
default:
throw "Ball does not provide intersects for " + p.id;
}
};
Also C++ code, I found on my computer. It also works fine
bool Ball::intersects(Ball &b) {
if (this != &b) {
int dx = b.x - this->x; //x is center of Ball
int dy = b.y - this->y;
int sqrdist = dx*dx + dy*dy;
int sumrad = b.radius + this->radius;
return sumrad*sumrad >= sqrdist;
}
return false;
}
It also works fine. So I suggest that you calculate position of balls before check for intersection.
P.S. And please, distinguish method to check intersection, which return bool. Do not mix checking of event with action on event.
I just inserted your code snippet on a similar collision detection method in one of my games and it worked as expected.
However, i remember i ran into a similar issue when i was testing mine, the issue was with the image displaying, not the collision detection. If you are using LWJGL or something like that for rendering, check that your textures/images are of a power of two size. Sometimes, they just add padding to the nearest power of two and it "seems" like they are not colliding when they actually are, just not visually.
Alright, I'm trying to do some simple object moving in the direction of where you touched the screen.
If I touch directly northwest of the object, it'll kind of move into the direction of the touch position. If I touch directly southeast of the object, it will kind of move into the direction of the touch position as well. However, if I touch directly northeast of the object, it'll move into the opposite direction towards the southwest. If I touch directly southwest of the object, it'll also move to the opposite direction towards northeast.
Also, if I touch north of the object, but just a little to the west, it will go straight west with a little to the north. Same with touching west of the object with a little bit to the north, it'll go straight north with a little bit to the west. Same thing for other directions.
Really, all the directions are from somewhat to obviously incorrect. I've been doing some paper calculations as well and I've seemed to be getting some correct angles, but at this point I'm completely stumped.
Does anyone know what the problem may be?
package com.badlogic.androidgames.texasholdem;
import java.util.List;
import android.util.FloatMath;
import com.badlogic.androidgames.framework.Game;
import com.badlogic.androidgames.framework.Graphics;
import com.badlogic.androidgames.framework.Input.TouchEvent;
import com.badlogic.androidgames.framework.Screen;
public class MainMenuScreen extends Screen {
public static float TO_RADIANS = (1 / 180.0f) * (float) Math.PI;
public static float TO_DEGREES = (1 / (float) Math.PI) * 180;
float num_x = 0; // Position of object on X axis
float num_y = 0; // Position of object on Y axis
float angle = 0;
public MainMenuScreen(Game game) {
super(game);
}
public void update(float deltaTime) {
Graphics g = game.getGraphics();
List<TouchEvent> touchEvents = game.getInput().getTouchEvents();
game.getInput().getKeyEvents();
int len = touchEvents.size();
for(int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
if(event.type == TouchEvent.TOUCH_UP) {
if(inBounds(event, 0, 0, g.getWidth(), g.getHeight()) ) {
// Calculate the angle of the direction between two points
angle = (float) Math.atan2(event.x - num_x, event.y - num_y) * TO_DEGREES;
if (angle < 0)
angle += 360;
// This is just to give me numbers on the Math.atan2 result, angle, to/from X position, and to/from Y position
System.out.println("Pressed! - ATAN: " + Math.atan2(event.x - num_x, event.y - num_y)
+ " - ANGLE:" + angle + " - POS: " + event.x + "tx/"
+ (int)num_x + "fx " + event.y + "ty/" + (int)num_y + "fy");
}
}
}
// Moving object in direction at 1f speed
num_x += (1f * (float) Math.cos(angle * TO_RADIANS));
num_y += (1f * (float) Math.sin(angle * TO_RADIANS));
}
private boolean inBounds(TouchEvent event, int x, int y, int width, int height) {
if(event.x > x && event.x < x + width - 1 &&
event.y > y && event.y < y + height - 1)
return true;
else
return false;
}
public void present(float deltaTime) {
Graphics g = game.getGraphics();
g.drawPixmap(Assets.background, 0, 0);
g.drawPixmap(Assets.backcard, (int)num_x, (int)num_y);
}
public void pause() {
Settings.save(game.getFileIO());
}
public void resume() {
}
public void dispose() {
}
}
if event x> x then x must be positive to move toward event.x
the problem here is that when event.x< x then your moving x must be negative
int dx,dy;
dx = (1f * (float) Math.cos(angle * TO_RADIANS));
dy = (1f * (float) Math.sin(angle * TO_RADIANS));
if(event.x<x){
dx=-dx;}
if(event.y<y){
dy=-dy;}
num_x+=dx;
num_y+=dy;
this way is simpler but less precise....
public void update(){
//(find dif between item x, and touch x)
float xdif=destx-x;
float ydif=desty-y;
if(x<destx){
dx=xdif/8;
}
else if(x>destx){
//we devide both x and y differences by the same number
dx=xdif/8;
}
else if(x==destx){
dx=0;
}
if(y<desty){
dy=ydif/5;
}
else if(y>desty){
dy=ydif/5;
}
else if(y==desty){
dy=0;
}
x+=dx;
y+=dy;
there u go, pathing in a straight line between two points, item.x and touch x.
Firstly, the math - I think the problem is that, for example, tan(135deg) = tan (-45deg) = -1. Therefore, atan has return values ranging between -90deg and 90deg as a resolution to ambiguity (look at its graph here). I think La5t5tarfighter's solution - negating the x movement in some cases - is on the right track, but you need to negate the y component in those cases as well. You could try that, but it would be much simpler if you used libGDX's Vector2 class. This is how I'd do it:
move.set(touchX, touchY); // y should be through flipping or unproject() before this
move.sub(objectPos); // move now points from object to where you touched
move.nor(); // now 1 unit long
move.scl(SPEED*deltaTime); // multiplied by a constant and delta - framerate-independent
objectPos.add(move);
You could even chain it into just one line if you want:
objectPos.add(move.set(x,y).sub(objectPos).nor().scl(SPEED*deltaTime));
Secondly, you're not using a Camera. I'm not completely sure what the default coordinate system is, but I believe the y axis points up which is not the same as the one used for inputs - Input.getY() is given with an y axis pointing down from the top left corner. If you had a Camera, you'd do this:
cam.unproject(someVector.set(Gdx.input.getX(), Gdx.input.getY(), 0));
Lacking that, you might need to flip the y axis:
event.y = Gdx.graphics.getHeight() - event.y;
Still, this could be wrong. Try drawing the object right at the touch position - if I'm right in this, it'll seem mirrored vertically. If it draws correctly where you touch, ignore this part.