Creating a isomatricStagged Map with libGDX - java

I am learning creating a simple game with libgdx and already had some success.
Now, i like to know the best way to use to create a simple isomatricStagged world.
Even with some camera troubles I have, I already implements a map, rendered, and use a cam.
What I want to know is, should I use Box2d and include my map to get boundaries? Or should I just render a 2 dimensional array for a map (this one is really slow after using more than 100x100 tiles).
thabnks for the rough overview or for some links to get these information. =)
opened on https://gamedev.stackexchange.com/questions/140750/creating-a-isomatricstagged-map-with-libgdx as well)

Not sure what you want to do with box 2D but an array should not be slow for just 100x100 tiles but you need to only draw what is needed unless your loop will draw thousands of off-screen assets. Calculating this for a staggered map is pretty straight forward:
Tiles X position in 2D array = worldX / tileWidth;
Tiles Y position in 2D array = worldY / (TileHeight / 2); // Since they overlap half on y axis.
So if that worldX/worldY would be the bottom left corner or center of your camera you can alter your draw loop to just draw what is on the screen. You calculate what tile would go in the top left corner and bottom right corner and iterate through.
Gridpoint topLeft; //Calculate based on camera position.
Gridpoint bottomRight; //Calculate based on camera position.
for (int y = bottomRight.y; y <= topLeft.y; y++)
{
for (int x = topLeft.x; x <= bottomRight.x; x++)
{
drawTile[x,y];
}
}
Now you are able to have a 1024x1024 map without hassle at all. But this does require a lot of memory since the large map array is stored. This is why you should only keep necessary data within a Tile object, like instead of a Texture a int referencing to a specific texture.

Related

How to properly combine two camera view matrices?

Basically, I have a 3D hexagonal tile map (think something like a simplified Civ 5 map). It is optimized to use a single large mesh to reduce draw calls and easily allow for some cool Civ 5 features (terrain continuity and uv texture bleeding).
I want to support wraparound maps in my game, and so was brainstorming ideas on how to best do this.
For example, if the main camera is approaching the far east of the map, then I can simply perform the translation to the far west by doing:
if(camera.x >= MAP_WIDTH)
camera.translate(0, 0, y);
However, by doing this, there will be a brief timespan in which the player will see the "end" of the board before the translation. I want to eliminate this.
The first idea I had to solve this problem was to basically just modify the above code as follows:
if((camera.x + camera.viewportWidth >= MAP_WIDTH)
camera.translate(0, 0, y);
However, this has the side effect of a "jump" during the translation that feels unnatural.
My final solution, and the subject of the question:
I have three cameras, my main camera, one to the far east, and one to the far west. I basically want to "combine" the matrices of these cameras to render the map outside of its actual bounds.
Basically, if the camera is a certain distance from the world bounds, I want to draw the scene from the other side of the world in the following location. So, for example, this is the pseudo code of what I want to do:
int MAP_WIDTH = 25;
float viewportSize = 10f;
float mainCamX = 24f;
float mainCamY = 15f;
Matrix4 cbnd = camera.combined;
if(camX >= MAP_WIDTH)
camX = 0;
else if(camX < 0)
camX = MAP_WIDTH - camX;
if(camX + viewportSize >= MAP_WIDTH)
cbnd = combineMatrices(mainCam.combined, westCam.combined);
modelBatch.setProjectionMatrix(cbnd);
modelBatch.begin();
//Draw map model
//Draw unit models.
modelBatch.end();
modelBatch.setProjectionMatrix(mainCam.combined);
But I am unsure of how to appropriately combine matrices, and am new to the concept of matrices in general.
Can somebody give me a hand in combining these matrices?
Sounds too complicated. Here is my idea:
I.e. you can display 10x10 fields on screen
you have map 100x100 fields
just increase your map to 110x110 and in that extra space repeat your first (zero-est rows and columns)
that way you can scroll smoothly and when camera reaches i.e. most right position you have on map just return it to 0 X position. Same goes for vertical movement.
So, idea is to have double most left part of map in width of screen width and most top part of map in size of screen height at rigth/bottom of the map respectively.

How to detect a colored rectangles in an image?

I'm trying to write an AI maze solver program. To do this, I will draw 2-color mazes in GIMP with red being walls and blue being background or floor. Then I will export from GIMP as a png and use ImageIO.read() to get a BufferedImage object of the maze. Finally, I will assign Rectangle hitboxes to walls and store them in an ArrayList so I can use .intersect() to check for sprite contact with walls. I can work with it from here.
However, there is one thing I want to be able to do for my program that I don't know how to do: Once I have stored my image as a BufferedImage, how can I detect the red parts (all the exact same RGB shade of red) and create matching Rectangles?
Notes:
Mazes will always be of fixed size (1000x1000 pixels).
There is a fixed starting point for each maze
The red areas will always form straight rectangles. The Rectangle objects which I create are just used as hitboxes so I can use .intersect(), never drawn or anything like that.
Rectangles that are created will be stored in an ArrayList.
Example Maze: (a simple one)
What I want to be able to do: (green areas being where the java.awt.Rectangles are created and stored into ArrayList)
I will provide a quite naive way of solving the problem (not fully implemented, just so you get the idea)..
Have a list of all rectangles List<Rectangle> mazeRectangles. All rectangles will be stored here.. And of course the image BufferedImage image;
Now we will iterate over all pictures until we find one with the right colour
Every time we found a rectangle, we will skip all x values for the width of the rectangle..
//iterate over every pixel..
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
//check if current pixel has maze colour
if(isMazeColour(image.getRGB(x, y))){
Rectangle rect = findRectangle(x, y);
x+=rect.width;
}
}
}
Your method for checking the colour:
public boolean isMazeColour(int colour){
// here you should actually check for a range of colours, since you can
// never expect to get a nicely encoded image..
return colour == Color.RED.getRGB();
}
The interesting part is the findRectangle method..
We see if there is already a Rectangle which contains our coordinates. If so return it, otherwise create a new Rectangle, add it to the list and return it.
If we have to create a new Rectangle, we will first check it's width. The annoying part about this is, that you'll still have to check every pixel for the rest of the rectangle, since you might have a configuration like that:
+++++++
+++++++
###
###
where # and + are separate boxes. So we first find the width:
public Rectangle findRectangle(int x, int y){
// this could be optimized. You could keep a separate collection where
// you remove rectangles from, once your cursor is below that rectangle
for(Rectangle rectangle : mazeRectangles){
if(!rectangle.contains(x, y)){
return rectangle;
}
}
//find the width of the `Rectangle`
int xD = 0;
while(x+xD < width && isMazeColour(image.getRGB(x+xD+1, y))){
xD++;
}
int yD = 0; //todo: find height of rect..
Rectangle toReturn = new Rectangle(x, y, xD, yD);
mazeRectangles.add(toReturn);
return toReturn;
}
I didn't implement the yD part, since it's a bit messy and I am a little lazy, but you'd need to iterate over y and check each row (so two nested loops)
Note that this algorithm might result in overlapping Rectangles. if you don't want that, when finding xD check for each pixel if it is already contained in a Rectangle. Only expand xD as long as you are not inside another Rectangle.
Another thing: You might end up with strange artefacts at the border of your rectangles, due to the interpolation of colours between red and blue. Maybe you want to check for Rectangles being to small (like only 1 pixel wide) and get rid of them..
Last year, someone asked about a more general case for solving a maze. They had one additional complexity in that there were multiple paths, but the "correct" path through an intersection was straight.
Python: solve "n-to-n" maze
The solution provided solves the maze by ray-casting. Starting at the beginning of a path, it projects lines down the path in all directions. Then it sorts the list and chooses the longest line and uses that to calculate the next starting point. Now, it repeats projecting lines in all directions except in the direction it came - the backtrack could be longer than the forward progress. That would just bounced the solution around in the longest leg of the maze.
If you are certain your angles are always 90 degrees, you could modify the code accordingly.

Android translated canvas collision of rectangles

im trying do develop a Zelda like game. So far i am using bitmaps and everything runs smooth. At this point the camera of the hero is fixed, meaning, that he can be anywhere on the screen.
The problem with that is scaling. Supporting every device and keeping every in perfect sized rects doesnt seem to be that easy :D
To prevent that i need a moving camera. Than i can scale everything to be equally sized on every device. The hero would than be in the middle of the screen for the first step.
The working solution for that is
xCam += hero.moveX;
yCam += hero.moveY;
canvas.translate(xCam,yCam);
drawRoom();
canvas.restore();
drawHero();
I do it like this, because i dont wand to rearrange every tile in the game. I guess that could be too much processing on some devices. As i said, this works just fine. the hero is in the middle of the screen, and the whole room is moving.
But the problem is collision detection.
Here a quick example:
wall.rect.intersects(hero.rect);
Assuming the wall was originally on (0/0) and the hero is on (screenWitdh/2 / screenHeight/2) they should collide on some point.
The problem is, that the x and y of the wall.rect never change. They are (0/0) at any point of the canvas translation, so they can never collide.
I know, that I can work with canvas.getClipBounds() and then use the coordinates of the returned rect to change every tile, but as I mentioned above, I am trying to avoid that plus, the returned rect only works with int values, and not float.
Do you guys know any solution for that problem, or has anyone ever fixed something like this?
Looking forward to your answers!
You can separate your model logic and view logic. Suppose your development dimension for the window is WxH. In this case if your sprite in the model is 100x100 and placed at 0,0, it will cover area from 0,0 to 100, 100. Let's add next sprite (same 100x100 dimension) at 105,0 (basically slightly to the right of the first one), which covers area from 105,0 to 205,100. It is obvious that in the model they are not colliding. Now, as for view if your target device happens to be WxH you just draw the model as it is. If your device has a screen with w = 2*W, h = 2*H, so twice as big in each direction. You just multiply the x and y by w / W and h / H respectively. Therefore we get 2x for x and y, which on screen becomes 1st object - from 0,0 to 200, 200, 2nd object - from 210,0 to 410, 200. As can be seen they are still not colliding. To sum up, separate your game logic from your drawing (rendering) logic.
I think you should have variables holding the player's position on the "map". So you can use this to determine the collision with the non changing wall. It should look something like (depensing on the rest of your code):
canvas.translate(-hero.rect.centerX(), -.rect.centerY());
drawRoom();
canvas.restore();
drawHero();
Generally you should do the calculations in map coordinates, not on screen. For rendering just use the (negative) player position for translation.

Moving Objects Help

I want to know how is it possible,I could have an Object drawn at a certain point and move to the point that is touched on the screen. I am trying to use it for my game where when the user touches on the screen, the gun fires from the position of the player, but the player is stationary.
Thanks in advance.
P.S.
Is there a visual graphic of some sort that shows where every plot is on android.
I don't know what kind of library you're using to draw all of your things, but that basically doesn't matter since you only need to know two things in order to do this:
Without going into specifics on vector geometry:
1. You need to calculate the direction (x and y component) that the projectile moves in depending on your mouses position. You get this direction by simply subtracting the position of the mouse from the position of the player:
//x component of direction
float direction_x = mousePosition.x - playerPosition.x;
//y component of direction
float direction_y = mousePosition.y - playerPosition.y;
In order to just get a direction instead of adding a velocity component to this vector, you need to normalize it (so it has a length of 1):
float length =(float) Math.sqrt(direction_x*direction_x + direction_y*direction_y);
direction_x /= length;
direction_y /= length;
You then need to update the projectiles position by adding the direction_x and direction_y components to it, multiplied by the speed that you want the projectile to have (This process is called linear interpolation, by the way):
projectile_x += direction_x*speed;
projectile_y += direction_y*speed;
If you have some way of measuring the time between two frames, the speed variable should depend on the elapsed time between those frames, in order to create smooth movements on different platforms.

Hide Rubik's Cube Internal Wirings

In the context of a Java/OpenGL application I am drawing a black wired only (without filling) big cube composed of 27 smaller cubes. To do that I wrote the following code:
for (int x = 1; x <= 3; x++) {
for (int y = 1; y <= 3; y++) {
for (int z = 1; z <= 3; z++) {
wireCube(x - 2, 2 - y, 2 - z);
}
}
}
The wireCube method is implemented using GL11.glBegin(GL11.GL_LINE_LOOP);
Using the right call to gluPerspective to define the projection and the correct call to gluLookAt to position the "camera" I am able to display my big cube as needed and ....I am very happy with that !!!
My new problem is now, how to modify this code in order to "hide" all the wirings that are inside the big cube ? To help visualize the scene, these wirings are the ones that are usually drawn has dashed lines when learning 3D geometry at school.
Thanks in advance for help
Manu
Enable depth testing (glEnable(GL_DEPTH_TEST)) and put quads on the surfaces of the cubes.
To draw a quad, use glBegin(GL_QUADS) followed by the four vertices and the glEnd() call.
Draw all your cubes with black polygons (or disable color output : glColorMask(false,false,false,false); ): this will fill the depth buffer.
Then draw your lines. The ones hidden by the polygons will not appear. There will be z-fighting though, so glDepthTest(GL_LEQUAL);
If you want to draw "unvisible" lines dashed, this won't be enough. You can draw again with glDepthTest(GL_GREATER);
Another solution is to draw polygons that face the camera with a solid line, and other with a dashed line. This is a simple dot product (camDir.faceNorm).
Use glPolygonOffset() to drown or to emerge your wireframe above (or below) the polygons with the same coordinates.

Categories

Resources