I want to create a 2D Game with Java and LWJGL. It is a retro styled RPG game. So there is a really big map(about 1000x1000 or bigger). I want to do it with tiles but I don't know how to save it/how to render it.
I thought at something like a 2D-Array with numbers in it and the render just sets the right tile at the right place.
But i think the bigger the map gets the more it will slow down.
I hope you can help me. :)
My second suggestion was to make a big image and just pick a part of it(the part where the player is) but than its hard to know where I have to do a collision detection, so this ist just an absurd idea.
Thank you for your suggestions!
As one of the comments mentioned, this subject is far too large to be easily covered with a single answer. But I will give you some advice from personal experience.
As far as saving the map in a 2D array, as long as the map is fairly simple in nature there is no problem. I have created similar style maps (tiled) using 2D integer arrays to represent the map. Then have a drawing method to render the map to an image which I can display. I use multiple layers so I just render each layer of the map separately. Mind you most of my maps are 100x100 or smaller.
I would recommend for such large maps to use some sort of buffer. For example, render only the playable screen plus a slight offset area outside of the map. E.g. if your screen if effectively 30x20 tiles, render 35x25, and just change what is rendered based on current location. One way that you could do this would be to load the map in "chunks". Basically have your map automatically break the map into 50x50 chunks, and only render a chunk if you get close enough that it might be used.
I also recommend having the drawing methods run in their own thread outside of the main game methods. This way you constantly draw the map, without having random blinking or delays.
I'm maintaining my 400*400 tiles map in the Tiled map editor and render it with the Slick2D framework. It provides support for rendering only visible subsections of the map. (TiledMap class).
I've tried both approaches - Image based and tiled based map creation and ended up with the latter. With tiles you can not only create the view of your map but also invisible meta data layers, like collision, spawn spots, item locations etc.
Related
I'm taking my first steps in JavaFX. I want to animate a lot of graphic elements (ellipses, bézier curves, not images) with javafx. These elements are organized in groups of about 10 elements that have to move together. I'm trying to achieve 60 fps and I want to move thousands of these elements.
There are at least four ways to do this:
Using a single canvas, and its graphical context to draw directly at every frame.
Using groups and nodes. Each element is a node. I like this way because there are a lot of classes that can be used to draw easily what I need, and the logical structure of nodes and groups is just what I need.
Each group is a canvas. Draw its elements in its constructor using the canvas graphical context, and then move all the canvases at each frame.
Creating images with the elements that have to stick together, and then move these images. I haven't found already how this can be done, but I suppose it's not hard. The elements may change from time to time, so I will need to recreate some images, but only once in a while.
My question is, which of these ways (or another) would be the fastest way to do it? In particular, does the use of a lot of nodes and groups has a high performance impact?
I would start with option two as this seems to logically fit your needs best. It is also the most straight forward and cleanest way of doing it with JavaFX. If it later turns out that the performance is not good enough you can try to improve this by using caching together with the appropriate cache hints. For example you can optimize your code for speed or for quality this way. This even works dynamically because you can switch between these cache hints depending on the state of your application. If you switch caching on for a group this has basically the same effect as drawing it into a canvas or an image.
I'm having quite a bit of difficulty wrapping my head around the actual display side of things with libgdx. That is, it just seems fairly jumbled in terms of what needs to be done in order to actually put something up onto the screen. I guess my confusion can sort of be separated into two parts:
What exactly needs to be done in terms of creating an image? There's
Texture, TextureRegion, TextureAtlas, Sprite, Batch, and probably a
few other art related assets that I'm missing. How do these all
relate and tie into each other? What's the "production chain" among
these I guess would be a way of putting it.
In terms of putting
whatever is created from the stuff above onto the monitor or
display, how do the different coordinate and sizing measures relate
and translate to and from each other? Say there's some image X that
I want to put on the screen. IT's got it's own set of dimensions and
coordinates, but then there's also a viewport size (is there a
viewport position?) and a camera position (is there a camera size?).
On top of all that, there's also the overall dispaly size that's
from Gdx.graphics. A few examples of things I might want to do could
be as follow:
X is my "global map" that is bigger than my screen
size. I want to be able to scroll/pan across it. What are the
coordinates/positions I should use when displaying it?
Y is bigger
than my screen size. I want to scale it down and have it always be
in the center of the screen/display. What scaling factor do I use
here, and which coordinates/positions?
Z is smaller than my screen
size. I want to stick it in the upper left corner of my screen and
have it "stick" to the global map I mentioned earlier. Which
positioning system do I use?
Sorry if that was a bunch of stuff... I guess the tl;dr of that second part is just which set of positions/coordinates, sizes, and scales am I supposed to do everything in terms of?
I know this might be a lot to ask at once, and I also know that most of this stuff can be found online, but after sifting through tutorial after tutorial, I can't seem to get a straight answer as to how these things all relate to each other. Any help would be appreciated.
Texture is essentially the raw image data.
TextureRegion allows you to grab smaller areas from a larger texture. For example, it is common practice to pack all of the images for your game/app into a single large texture (the LibGDX “TexturePacker” is a separate program that does this) and then use regions of the larger texture for your individual graphics. This is done because switching textures is a heavy and slow operation and you want to minimize this process.
When you pack your images into a single large image with the TexturePacker it creates a “.atlas” file which stores the names and locations of your individual images. TextureAtlas allows you to load the .atlas file and then extract your original images to use in your program.
Sprite adds position and color capabilities to the texture. Notice that the Texture API has no methods for setting/getting position or color. Sprites will be your characters and other objects that you can actually move around and position on the screen.
Batch/SpriteBatch is an efficient way of drawing multiple sprites to the screen. Instead of making drawing calls for each sprite one at a time the Batch does multiple drawing calls at once.
And hopefully I’m not adding to the confusion, but another I option I really like is using the “Actor” and “Stage” classes over the “Sprite” and “SpriteBatch” classes. Actor is similar to Sprite but adds additional functionality for moving/animating, via the act method. The Stage replaces the SpriteBatch as it uses its own internal SpriteBatch so you do not need to use the SpriteBatch explicitly.
There is also an entire set of UI components (table, button, textfield, slider, progress bar, etc) which are all based off of Actor and work with the Stage.
I can’t really help with question 2. I stick to UI-based apps, so I don’t know the best practices for working with large game worlds. But hopefully someone more knowledgeable in that area can help you with that.
This was to long to reply as a comment so I’m responding as another answer...
I think both Sprite/SpriteBatch and Actor/Stage are equally powerful as you can still animate and move with Sprite/SpriteBatch, but Actor/Stage is easier to work with. The stage has two methods called “act” and “draw” which allows the stage to update and draw every actor it contains very easily. You override the act method for each of your actors to specify what kind of action you want it to do. Look up a few different tutorials for Stage/Actor with sample code and it should become clear how to use it.
Also, I was slightly incorrect before that “Actor” is equivalent to Sprite, because Sprite includes a texture, but Actor by itself does not have any kind of graphical component. There is an extension of Actor called “Image” that includes a Drawable, so the Image class is actually the equivalent to Sprite. Actor is the base class that provides the methods for acting (or “updating”), but it doesn’t have to be graphical. I've used Actors for other purposes such as triggering audio sounds at specific times.
Atlas creates the large Texture containing all of your png files and then allows you to get regions from it for individual png's. So the pipeline for getting a specific png graphic would be Atlas > Region > Sprite/Image. Both Image and Sprite classes have constructors that take a region.
I have got a single object.
A heightmap.
(Ignore the flag and the water - We have imaginations, right? ;) )
However, the issue is that I display this as a single display list. Therefore, I cannot "check the distance" of the map from the player, nor make the map less detailed, because I am only able to treat the map as a single object.
I have tried using shaders, however these are too late in the pipeline to be able to affect performance (If I use a shader to cut out EVERYTHING in the entire game, the game still lags as if it has everything else).
So, how can I add a Continuous Level Of Detail to the terrain, before it is too late, without splitting it into a ton of different objects (And even that wouldn't work well)?
You can split your map up into squares that you can display independently and only create those mesh objects when the player comes close enough to potentially render, and only render when inside the sight of the player.
besides that you can use a tesselation shader to create the continuous level of detail. it involves drawing flat quads and using the control shader to say how many vertices must be drawn and the evaluation shader to displace them upwards based on the height map (that you pass in as a texture).
or to be radical you can create a flat mesh that is fine grained in the center and decreases in detail further out, then using the vertex shader you can displace the vertices with the height map, the center remains under the camera but you use the position of the camera to offset the sampled coordinates of the height map (and texture map)
I've written the beginnings of a 2D isometric engine using Java. I've got most of the basics covered such as tiling orders and object depth sorting on the map. However, I've run into a problem which I can't seem to solve without making my methods really messy.
The problem is that, in my isometric world, each object is rendered when the tile that the object base is on is rendered on the screen. However, some objects have a large height (such as a building) which can extend from a non-rendered off-screen area into the rendered screen area, and I have no way to detect this as my engine so far relies on object bases being present to render images.
My question is, how would I detect that an object with a large height value should be present in the rendered area while its base is in the off-screen area? I really don't want to be just rendering the whole map (including the off-screen area) as this is very CPU-intensive, so I'm looking for an algorithm or method which allows me to detect this problematic area.
EDIT: Updated the question to visually represent the problem below.
Can you modify your concept of 'tile' to include something like an 'envelope'...a rectangle that delimits the maximum height and width? e.g. when the 'large height' object is created / assigned to a tile, you could increase the height of its envelope.
Then you only need to render for tiles whose envelopes overlap with the screen.
I would have a method on my object "boolean isVisible(Rectangle2D bounds)". Call this method before sorting the objects and before rending the sorted objects.
I'm trying to develop a 2D game to android using opengl.
I know how to print images on the screen and animate them. But in my game I have a map and a want to zoom in and out and scroll the map. But I can't figure out the best way of doing it.
Can anybody help me?
I don't have any api examples but I did games design at college so I'll give my two bits.
The method you use will depend on your map style, size, functionality and format.
For example if you are looking for a very static non changing map, use a simple picture image. You can use the API frame for a picture view, enabling you to zoom in and out as you do in the gallery and to scroll on zoomed images, or in this case, zoom locations on your map.
Alternatively, if your map is based off a tiling system, a good example of this is the original Pokémon and Legend of Zelda games from the old game boy, then each area stores a tile 'thumbnail' for itself as a bitmap. These are then put into their appropriate locations on a grid depending on what areas are discovered.
This is the probably the most flexible way to build your map as you are not relying on a set bitmap for the entirety your map meaning it can change its look efficiently; you can build it as desired to show areas of choice (useful for if the map only reveals places the gamer has covered) and it also means you can do tile based overlay:
ie - if a certain area should contain treasure, theres a treasure icon overlayed on that tiles x,y position on the map grid.
I used the tiling option in my game projects from college and it made everything else map related easier. It also made the map side of things smaller storage wise.
The simplest approach would be to just call glTranslatef(-scrollX,-scrollY,0) followed by glScalef(zoom,zoom,zoom) before you render your map.