Mapping logical coordinates to graphical fails when scaling - java

I encountered a slight problem with my game's rendering system when I tried to scale certain objects. I think it must be the way I map objects with logical coordinates to graphical ones on the screen.
Renderable
/**
* Retrieve the image representing the object that should be rendered.
* #return The image sprite representing the object.
*/
public Texture getSprite();
/**
* Retrieve the x-coordinate where the object should be rendered.
* #return The x-coordinate of the object.
*/
public float getScreenX();
/**
* Retrieve the y-coordinate where the object should be rendered.
* #return The y-coordinate of the object.
*/
public float getScreenY();
Texture
......
......
/**
* Retrieve the width of the texture.
* #return The width of the texture.
*/
public int getWidth();
/**
* Retrieve the height of the texture.
* #return The height of the texture.
*/
public int getHeight();
......
......
This system works perfectly when I draw stuff like interfaces etc, which have no logical coordinates in my game world.
Let's take a look at an object that have logical coordinates and see how I map the coordinates to graphical ones and thus causing a problem when I scale the texture when drawing.
Tile
#Override
public float getScreenX() {
return x * width;
}
#Override
public float getScreenY() {
return y * height;
}
Let's say the size of the texture for any tile is 16*16 but for some reason I want to draw it at 32*32. This will cause a problem since the tile's graphical x- and y-coordinate messes up.
Note: I know that I can fix this by allowing the user to set a scale when loading the image into the system but I want it to be more flexible.
TL;DR: How can I accomplish a better mapping between logical coordinates in the game world to graphical ones while still being able to scale when I want to? There should be a better way to map instead of letting the logical objects be in charge of their graphical coordinates.

Related

Android MPAndroidChart xasis values showing more than 1

I am using android java MPAndroidChart Library.
As you can see from photo, value of x axis showing more than one. I just want to show tuesday one time. How can I do it
image of chart
I find the solution
lets say your name of the list is myArray and answer is
barChart.getXAxis().setLabelCount(myArray.size());
You can set a count of label by force. This will result into one label only on your axis.
For example:
xAxis.setLabelCount(1, true)
From the documentation:
/**
* sets the number of label entries for the y-axis max = 25, min = 2, default: 6, be aware
* that this number is not
* fixed (if force == false) and can only be approximated.
*
* #param count the number of y-axis labels that should be displayed
* #param force if enabled, the set label count will be forced, meaning that the exact
* specified count of labels will
* be drawn and evenly distributed alongside the axis - this might cause labels
* to have uneven values
*/
public void setLabelCount(int count, boolean force) {
setLabelCount(count);
mForceLabels = force;
}
The other thing you can try is working more with granularity.
Like so:
axisLeft.granularity = 3F
From the docs:
/**
* Set a minimum interval for the axis when zooming in. The axis is not allowed to go below
* that limit. This can be used to avoid label duplicating when zooming in.
*
* #param granularity
*/
public void setGranularity(float granularity) {
mGranularity = granularity;
// set this to true if it was disabled, as it makes no sense to call this method with granularity disabled
mGranularityEnabled = true;
}

Processing - ScreenToWorldCoordinate function?

I'm working on a project with Processing that requires the ability to determine whether or not the mouse is inside of a circle. Therefore, I need to obtain the position of the circle and the position of the mouse. However, the position of the circle has been modified using matrix functions such as translate and scale. For example:
float circle_x;
float circle_y;
float circle_radius;
void setup() {
circle_x = 10.0;
circle_y = 17.0;
circle_radius = 15.0;
}
void draw() {
pushMatrix();
/* ... arbitrary number of calls to modify the matrix ... */
translate(THING, THING);
scale(THING);
translate(THING);
/* ... */
/* draw the circle */
ellipse(circle_x, circle_y, circle_radius, circle_radius);
/* now I want to detect whether or not my mouse is inside of the
circle. In order to do that, I need to modify the coordinates
of the mouse in the same fashion as circle_x and circle_y. I'm
hoping to do something like this: */
float world_x = screenToWorld_X(mouseX);
float world_y = screenToWorld_Y(mouseY);
/* ... check if [world_x, world_y] is inside the circle ... */
popMatrix();
}
Is there any way to do this in Processing? I was looking at the documentation but I couldn't seem to find any functions. If not, how can I achieve my goal?
Thanks.
Check out the coordinates section of the reference.
Specifically, you're looking for the modelX() and modelY() functions. Or you could use the screenX() and screenY() functions to go the other way and convert your world coordinates into screen coordinates.

Whats general convention when defining camera/objects z position

I'm making a switch to generate matrices myself in java, to pass into my opengl shaders.
I've created a method to generate the perspective matrix which works fine. But currently I have my objects being drawn at z position 0.0f. Which means when the app runs, I can only see 1 of my custom objects (square) really close up.
Should I be setting my camera z position to 0.0f (which is happening currently) .. or all my objects z position to 0.0f?
createPerspectiveProjection(60.0f, width / height, 0.1f, 100.0f);
/**
* #param fov
* #param aspect
* #param zNear
* #param zFar
* #return projectionMatrix
*/
private Matrix4f createPerspectiveProjection(float fov, float aspect, float zNear, float zFar){
Matrix4f mat = new Matrix4f();
float yScale = (float) (1 / (Math.tan(Math.toRadians(fov / 2))));
float xScale = yScale / aspect;
float frustrumLength = zFar - zNear;
mat.m00 = xScale;
mat.m11 = yScale;
mat.m22 = -((zFar + zNear) / frustrumLength);
mat.m23 = -1;
mat.m32 = -((2 * zFar * zNear) / frustrumLength);
mat.m33 = 0;
return mat;
}
The standard projection matrix you are using corresponds to a camera placed at the origin, and looking down the negative z-axis. The near and far values determine the range of negative z-values that are within the view frustum. With the values in the example, this means that z-values between -0.1f and -100.0f are visible. That's as long as they're within the pyramid defined by the field of view angle, of course.
How you place your camera and objects in world space is completely up to you. If you emulate a traditional OpenGL rendering pipeline, you'll have a model-view matrix that transforms your objects to place them in the view frustum described above. This means that visible objects should have a negative z-value after the model-view transformation is applied.
The absolutely simplest way of achieving this is to use the identity transformation (i.e. no transformation at all) for the model-view transformation, and place your objects around the negative z-axis.
However, it's often convenient to have your objects placed somewhere around the origin. One simple way of allowing this to work is to place the camera on the positive z-axis, and point it at the origin. The model-view matrix then becomes particularly simple. It's only a translation in the negative z-direction, to shift the camera from its position on the positive z-axis to the origin, matching how the projection matrix was set up.
For example, with your near/far values of 0.1/100.0, you could place the camera at (0.0, 0.0, 50.0) in world space. The view transformation is then a translation by (0.0, 0.0, -50.0). The z-range from 49.9 to -50.0 in world space is then the visible range, allowing you to place your objects around the origin.

PDPageContentStream has no drawLine() method

So I just started using Apache PDFBox (0.7.3) in one of my projects to write to PDF. I want to draw a line across the whole page, which according to the docs and many examples I have seen, I should be able to do by calling the drawLine() method from my PDPageContentStream. However, in Eclipse I only see two drawImage methods and a drawString method. Does anyone know what I should do to fix this? Is the drawLine method deprecated or something?
In PDPageContentStream I see:
/**
* Draw a line on the page using the current non stroking color and the current line width.
*
* #param xStart The start x coordinate.
* #param yStart The start y coordinate.
* #param xEnd The end x coordinate.
* #param yEnd The end y coordinate.
* #throws IOException If there is an error while drawing on the screen.
*/
public void drawLine(float xStart, float yStart, float xEnd, float yEnd) throws IOException
{
if (inTextMode)
{
throw new IOException("Error: drawLine is not allowed within a text block.");
}
addLine(xStart, yStart, xEnd, yEnd);
// stroke
stroke();
}
Thus, either your PDFBox copy is outdated or your eclipse does not show existing methods.
I use eclipse Kepler here and see the method all right.
It is located between addLine and addPolygon in the source, far away from drawImage or drawString. If you are searching in the outline, you maybe should activate sort-by-name there.

How to build a Tiled map in Java for a 2D game?

Not sure how to approach this problem.
Basically, I want a Pixel -> Tile representation of a 400x400 window. Each coordinate on the screen, e.g 120x300 should be part of a tile. My smallest sprite is 4 pixels, so we can say that 1 tile = 4 pixels. The player and enemy sprites are all 20 x 20, so each player/bad guy will occupy 5 tiles.
Then I want to use this Map class to:
Retrieve the x/y coordinates of a player/monster sprite by suppling the index/id of the tile.
Knowing where the boundaries are, so it doesn't move the sprite beyond 400x400, thus hiding it.
Collision detection, knowing whether a tile is vacant or not.
How can this be done? Talking specifically about the x,y->tile or tile index->x,y conversion (for drawing the sprites appropriately) here.
Firstly, split out the concept of a pixel, which is just concerned with representation, with a tile, which is an actual game object with constraints it places on the game.
I find a good way to disentangle things like this is to start out sketching out the rough API of what you want. Something like:
public class Board {
public Board (int width, int height){.. }
public boolean isOccupied(int x, int y){.. }
public void moveTo(Point from, Point to) { ..
(maybe throws an exception for outofbounds )
where all internal units of the board are in tiles, not pixels.
Then pixel information can be derived from the board independantly from the tile representation with a bit of internal multiplication-
public Point getPixelPosition(int xTilePos, int yTilePos, int pixelsPerTile)..
The tiles can be internally represented as a 2d array or a single array, in which case you'd use some kind of internal representation scheme to map your array to the board squares, thus the mod arithmetic.
Short answer: Multiplication and Modulo operations.
But if this is stumping you, I'd suggest you do a serious math refresher before trying to write a game.
Also your statement
My smallest sprite is 4 pixels, so we
can say that 1 tile = 4 pixels. The
player and enemy sprites are all 20 x
20, so each player/bad guy will occupy
5 tiles.
doesn't work out for any reasonable geometry. If by "1 tile = 4 pixels" you mean that the tiles are 2x2, then a player takes 100, not five. If you mean they are 4x4 then players take 25, which still isn't 5.
/** size of a tile in pixel (for one dimension)*/
int TILE_SIZE_IN_PIXEL = 4;
/** size of a piece in tiles (for one dimension)*/
int PIECE_SIZE_IN_TILE = 5;
public int tileToPixel(int positionInTiles){
return TILE_SIZE_IN_PIXEL * positionInTiles;
}
/** returns the tile coordinate to which the given tile coordinate belongs
Note: tileToPixel(pixelToTile(x)) only returns x if x is the upper or left edge of a tile
*/
public int pixelToTile(int positionInPixel){
return positionInPixel / TILE_SIZE_IN_PIXEL;
}
You'll probably want methods operating on two arguments (x and y at) as well.
For the ID->piece conversion and vice versa you have various approaches available. Which one to choose depends on the exact requirements (speed, size of game ...). So make sure that you are hiding the implementation details, so you can change them later on.
I'd start with a real easy solution:
public class Piece{
/** x position measured in tiles */
private int x;
/** y position measured in tiles */
private int y;
/** I don't think you need this, but you asked for it. I'd pass around Piece instances instead */
private final Long id;
public void getX(){
return x;
}
public void getY(){
return y;
}
public void getID(){
return id;
}
}
public class Board(){
private Set<Long,Piece> pieces = new HashMap<Piece>(pieces);
public Piece getPieceOnTile(int tileX, int tileY){
for(Piece piece:pieces){
if (isPieceOnTile(piece, tileX, tileY)) return piece;
}
}
private boolean isPieceOnTile(piece, tileX, tileY){
if (piece.getX() < tileX) return false;
if (piece.getX() > tileX + PIECE_SIZE_IN_TILE) return false;
if (piece.getY() < tileY) return false;
if (piece.getY() > tileY + PIECE_SIZE_IN_TILE) return false;
return true;
}
}
Hope that gets you started. All code is writen without a compiler nearby so it will include typos and of course bugs, which may be distributed under the creative commons license.
The approach of keeping the pieces in a set should work well if there are not to many pieces. It should work better than a 2D array as long as most board area does not contain a piece. The whole thing currently assumes there are no overlapping pieces. If you need those getPieceOnTile must return a Collection of pieces. A set if order does not matter, a List if it does.

Categories

Resources