Ok, so I have my isometric map where the width of each tile is 64 and the height is 32.
This is the equation I came up with to place the tiles
xPos = (this.getPos().getX() - this.getPos().getY()) * (64 / 2) - Main.gameWindow.getCamera().getxOffset().intValue();
xPos -= 32;
yPos = (this.getPos().getX() + this.getPos().getY()) * (32 / 2) - Main.gameWindow.getCamera().getyOffset().intValue();
I subtract xPos by 32 to make up for the fact that the origin point of the tile is in the far left corner.
What I've been trying to do is find the tile that is beneath my mouse.
So first I tried simply reversing the equation (I was sure it would work)
And this is the code I ended up with when I reversed it.
int yMouseTile = ( (cursorY / (32 / 2) - (cursorX / 32)) / 2 );
int xMouseTile = ( (cursorX / 32) + yMouseTile);
This only sort of works. But as it turns out, this code actually treats each tile as if it were a square, not a diamond.
The next weird part is that when my mouse passes over the center of the tile, the tile changes. So what should happen, is that my mouse should go over the edge of the tile, and then it changes to the next one. But instead, it acts as if the center of tile is actually the edge.
But really, all I want is the equation that will cause my mouse to work like this
http://www.tonypa.pri.ee/tbw/tut18.html
On that link, click the "Click Here to Start" Button, and watch how the mouse interacts with the tiles. That is my goal :), thanks
P.S. I've tried a myriad of different equations, many of which have the exact same result as the equation I have above
Refactor your variable names.
int TILE_WIDTH = 64;
int TILE_HEIGHT = TILE_WIDTH / 2;
int xMap = this.getPos().getX();
int yMap = this.getPos().getY();
int xScreenCameraOffset = Main.gameWindow.getCamera().getxOffset().intValue();
int yScreenCameraOffset = Main.gameWindow.getCamera().getyOffset().intValue();
xScreen = (xMap - yMap) * (TILE_WIDTH / 2) - yScreenCameraOffset;
yScreen = (xMap + yMap) * (TILE_HEIGHT / 2) - yScreenCameraOffset;
This might seem excessive, but in my opinion is way easier to read and reason about. According to this tutorial If you try to derive The reverse equation you would get:
xMouseTile = (xCursor / TILE_WIDTH / 2 + yCursor / TILE_HEIGHT / 2) / 2;
yMouseTile = (yCursor / TILE_HEIGHT / 2 - xCursor / TILE_WIDTH / 2) / 2;
This doesn't take into account the camera offset.
Related
I'm making a Conway's Game of Life simulator because I thought that would be a fun project to try out, but I got stuck when trying to implement a function to keep changing cells to alive or dead when I drag my mouse over them.
scrollPane.setOnMousePressed(e -> {
double translation = (SQ_SIZE + SPACING) * SIZE + SPACING;
double xPosition = e.getX() + scrollPane.hvalueProperty().doubleValue() * (translation - PREF_WIDTH);
double yPosition = e.getY() + scrollPane.vvalueProperty().doubleValue() * (translation - PREF_HEIGHT);
// row and column of the click on the grid
int row = (int) ((yPosition - SPACING * (int) (yPosition / (SQ_SIZE + SPACING))) / SQ_SIZE);
int col = (int) ((xPosition - SPACING * (int) (xPosition / (SQ_SIZE + SPACING))) / SQ_SIZE);
grid[row][col].setAlive();
});
scrollPane.setOnMouseReleased(e -> {
//??
});
This was just to see if I could make the mouse change the cells. I dragged it over to alive and it does not seem to work. It can change the cell where it was initially pressed, but all the other cells do not change.
There is probably a very obvious solution I'm missing, but I'm quite new to JavaFX.
Ok so basically you cant use setOnMouseDragged for a scrollpane, so i set it on the gridpane and it worked.
I have two images
the first image of a cup ->
the second image is the label I want to wrap around the cup (this image is just an example, the actual app works with dynamic images).
I'm planning to clip the label image several time and place it on the cup, therefor creating a 36 jpegs from different angles, I'll use a 360 viewer to display the result on my website.
so far I've managed to take a trapezoid area of the lable image to create this
(code is here)
The last step is to create this (used GIMP for this - using distort -> curve-bending)
Thank you
What comes in my mind, is a technique called uv-mapping.
See https://en.wikipedia.org/wiki/UV_mapping as a starting point.
See also J3D - How to use a UV mapping of an object to convert 2D coordinates to 3D ones
I've managed to do some work.
At first, I use ImageMagick , it took 50 sec to generate 36 images... way to long for me.
So I turned to Java, I've managed to do the simple transformation using a simple pixel by pixel and apply a Sin function
for(int y = 0; y < bounds.height ; y++)
{
for (int x = 0; x < bounds.width ; x++) {
int pixelRGB = img.getRGB(x, y);
int newX = x;
int newY = ((int)(Math.sin(x*Math.PI/bounds.width) * 40 )) + y ;
newImg.setRGB(newX, newY, pixelRGB);
}
}
main line is -> (Math.sin(x * Math.PI / bounds.width) * 40) + y
Math.PI / bounds.width -> make sure I get only the positive values for Y from the Sin function.
bounds.width - is the original image width, for the Sin function it tells to start from 0,0 go to positive Y values and intersec with th X axis back at bounds.width.
40 -> is the level of curvature you'll want to use
y - just a Y axis offset. if not applied you'll get a single line in the target image
I have an isometric map drawn.
I take the current position of my sprite and the target position of where my sprite should be at after the move:
// region is my TextureRegion.
int x1 = getIsometricX(1,1,region);
int x2 = getIsometricX(1,2,region);
int y1= getIsometricY(1,1,region);
int y2 = getIsometricY(1,2,region);
And then I draw a simple line using ShapeRenderer to see if the local/target points are correctly set, and the rectangle so you can see where the sprite rendering starts.
renderer.setProjectionMatrix(camera.combined);
renderer.begin(ShapeRenderer.ShapeType.Line);
renderer.setColor(Color.RED);
renderer.line(x1 + location.getOffsetx(), y1 + location.getOffsety(), x2 + location.getOffsetx(), y2 + location.getOffsety());
renderer.rect(x1 + location.getOffsetx(), y1 + location.getOffsety(), region.getRegionWidth(), region.getRegionHeight());
renderer.end();
Every sprite of mine has set offsetX and offsetY to adjust its location on the isometric tile, because every sprite is different.
Output looks like this:
what you can see here, is the starting point of where the sprite starts to draw (you see that offsets adjusted it so the sprite looks like its on the 1,1 tile.
and you can see the line which starts at the starting draw point of the sprite, and ends at the target draw point of the sprite.
Now my question is, how can I make that sprite move on that line's path, so it will look like the ship is moving forward?
So the main concept of the question is.. How can you make a sprite move in a straight line, from local point to target point?
Some functions you might need to see:
public int getIsometricX(int x, int y, TextureRegion region) {
return (x * GameTile.TILE_WIDTH / 2) - (y * GameTile.TILE_WIDTH / 2) - (region.getRegionWidth() / 2);
}
public int getIsometricY(int x, int y, TextureRegion region) {
return (x * GameTile.TILE_HEIGHT / 2) + (y * GameTile.TILE_HEIGHT / 2) - (region.getRegionHeight() / 2);
}
Tiles are drawn using the same method, just with Tile's texture.
I would like to answer myself this question, because other people might have the same issue and just over-complicate it like me.
If you want to perform any move on your isometric map, do not follow my misunderstandings and calculate it on the isometric coordinates.
You have to calculate it on your flat screen matrix coordinates, and then convert it to isometric coordinates.
For example, I want to move up like this line, all I need to do is this:
ship.y += 0.1f // when it reaches 1, then it will be at 0, 1
So you know that you want to be at 0,1 on your non-isometric map.
So you do this increment, and then for last, you have to convert it to isometric coordinates before drawing:
float x = (ship.x * GameTile.TILE_WIDTH / 2) - (ship.y * GameTile.TILE_WIDTH / 2) - (textyure.getWidth() / 2);
float y = (ship.x * GameTile.TILE_HEIGHT / 2) + (ship.y * GameTile.TILE_HEIGHT / 2) - (texture.getHeight() / 2);
And that will draw it on the isometric map, exactly like on your screen-coordinates, but on an isometric format.
for(float x : new float[targetx - currentx]) {ship.setPosition(ship.getX + x, ship.getY); }
And you would do the same for y.
Edit:
I guess this is wrong since you're calling this every frame I assume.
Instead you would keep track of your distance traveled between target and ship and you would increment sip position by 1 each time to x and y until it reached the distance.
I'm trying to draw a map with hexagonal tiles. However, I'm struggling to get the tiles to line up properly, so there is no space inbetween them. One with the tiles I use normally and one zoomed in on with another tile made to make sure it's not just the antialiasing playing tricks on me.
This is the code that's responsible to get the pixel coordinates for every tile. Apparently there's some miscalculation with the offset of every odd row, but simply adding or subtracting a pixel only increases the gaps.
private static final float HEX_WIDTH = 97; // 139 for colored tiles
private static final float HEX_HEIGHT = (float) (Math.sqrt(3)/2 * HEX_WIDTH);
public Vector2 getHexCoordinates(Hexagon hex) {
float x = (float) HEX_WIDTH * hex.getGridX() * 3 / 4;
float y = (float) HEX_HEIGHT * (hex.getGridX() / 2 + hex.getGridY());
y = (hex.getGridX() % 2 == 0) ? y : y + HEX_HEIGHT / 2;
return new Vector2(x, y);
}
In addition here's the tiles I'm using in case anyone is wondering.
Have you tried simply decreasing HEX_WIDTH by 1?
private static final float HEX_WIDTH = 96;
Your Height is apparently fine because you have no horizontal gaps.
Scaling the individual Sprites by 1.01f reduced the size of the gaps enough to consider this problem solved.
I'm trying to create rope physics for a 2D game, so as a starting point I have a small rotating image and I need to add another piece of rope to the end of it. Unfortunately I'm having trouble trying to track the bottom part of the image as the rotation occurs at the top of it. I've managed to track the (0,0) coordinate of the image using the following code but I need to be able to track point (32,57). This is what I have so far:
xr = xm + (xPos - xm) * Math.cos(a) - (yPos - ym) * Math.sin(a);
yr = ym + (xPos - xm) * Math.sin(a) + (yPos - ym) * Math.cos(a);
Any help is appreciated!
EDIT:
So hey, I got it working =D Using polar coordinates turned out to be a lot easier then whatever I had going on before.
The top 2 variables are constant and stay the same:
theta0 = Math.atan2(y, x);
r = 25;
theta = theta0 + a;
xr = (r * Math.cos(theta)) + xm;
yr = (r * Math.sin(theta)) + ym;
xm and ym are the positions of my image.
Use polar coordinates. Set your origin at the point of rotation of your image, and pick your favorite angular reference (say 0 degrees is directly to the right, and positive rotations go counterclockwise from there).
Compute the polar coordinates of your desired point (32, 57) relative to this coordinate system. Say the answer is (r, theta).
Now, the only thing that's changing as you spin the image around is the value of theta. Now you can go back to x-y coordinates with your new value of theta.
Hope this helps.