I am writing a program in visual basic 2010 to create a 2D scrolling map. I am using Pictureboxes at the moment, all 50 by 70 in size. It starts with 1, and depending on what is needed may easily end up with 1000 - 2000 of them. They all need to be clickable. I am concerned it might use too many resources and run too slow. Can anyone tell me what the best approach to make something like would be.
Thankyou.
A common method is to only draw the tiles (or pictureboxes in your case) when they can be seen by the player's camera. So you should first determine how many boxes fill the screen and then calculate whether or not they are within the bounds of the player camera as represented by a rectangle. Additionally, you should draw boxes slightly outside the player's view (1 or 2 additional boxes per edge, this is explained below).
When the player moves, move the position of the world, not the player. So if the player moves left, scroll all of the tiles to the right while the player sprite remains stationary. Now when a player's position changes you should check again which tiles are visible in the player's screen. Since you are drawing additional rows slightly outside the view of the player, the edges will smoothly scroll in and will not 'pop' in as is a common problem when starting out.
Since you are only drawing tiles which are visible to the player, your game should run a lot more efficiently. It is OK to store this data in a 2D array in memory for now. In the future when you have huge maps, it may be a good idea to load sections of your map which are far outside of the player's view from disk to memory. You don't want to load in map data from disk which the player can navigate to before it is fully loaded.
Exactly how much map data to store in memory is up to you and depends on what platforms you want to release on and other constraints.
Additionally, you may want to look into different rendering libraries. Common low-level libraries are DirectX and OpenGL. These libraries work directly with your graphics card to dramatically speed up rendering. There are libraries built on top of those for various languages, but I don't know any for Visual Basic. An example for JavaScript is PixiJS. Additionally, there are full featured game creation libraries such as Unity or the Unreal Engine 3.
Related
I’m building a Starflight-inspired 2D space exploration game with a procedural world. The gameplay is divided into different « scenes » (to use Godot terminology) to manage the different « depths » of the game. For example, interstellar flight is a scene where the star systems are simply represented by star sprites. When the player gets in range, the view is moved to the solar system scene, where the player moves his ship inside the actual solar system.
So far so good, I generate the universe (the solar systems) from a hard coded array of coordinates and seeds. Now I also want to make the universe generation procedural, but I’m guessing that loading a whole universe (there is no real limit to the number of solar systems once it becomes procedural) in memory won’t be efficient.
I’m thinking of generating the universe on the first run and saving the data to a file, but I’m wondering how to load the relevant data in an efficient way that would let me load only a certain « radius » of data around the player’s ship. I feel like it would be the way to go if I use my generation algorithms that generate « realistic » galaxy shapes, since it implies many steps of data processing (different cluster shapes are generated, arms, blobs, etc. and then stars are spinned around the center to simulate the galaxy rotation, etc.) that would be probably too long to calculate in realtime.
I’m wondering which approach I should take on this problem. It’s not really language or engine dependant, so references to generic articles and algorithms on the subject would suffice.
I also read a bit about QuadTrees and I think I’m getting to something there, but I’m not exactly sure how to use that with a file on disk.
Thanks in advance for your help!
I have some suggestions:
Do not generate the whole universe on the first run, generate only the areas that are somehow visible. Then, instead of loading the whole universe from disk, you just generate it whenever your spaceship (or whatever) come within view distance of that area. This makes game initialization much faster and allows an (almost) infinite universe.
If you want the universe to be modifiable, store only the `edits' that a player makes. So if you want to show a part of the universe, generate the part from your seed and then overlay the stored edits. This makes storage much smaller.
For storage on disk, have a look at R-Tree, especially R*Tree and R+Tree, they are designed for storing data in disk pages.
as TilmannZ suggested, you should not be generating the whole dataset for the galaxy when you start the game, because there is likely no need (unless the player needs to see/interact with all the data at once - e.g. all stars). If this is the case, for example for a starmap, then you may be better loading all the data once and saving the result in an image file.
Instead, you should only genereated the data as needed around the player. The most obvious way to do this would be to construct a grid around the player, and keep this grid centered on the player as they move around. As the player moves around, you only need to update the conceptual galaxy coordinates of each cell (not the rendered coordinates). Then for each cell you can then use the coordinates as the input into a value or gradient generator like Perlin to determine what features should spawn in that location.
As for 'shaping' the galaxy or universe, one effective way is to sample the pixel data of a greyscale image of a galaxy which has the shape you want. You could load the image's RGB data at run time, and use the coordinates of your grid as you generate the stars to get the RGB value, which you can use as a density factor for the star generation; the whiter the pixel, the higher the star density at this location and visa-versa for black pixels. This method lets you effectively draw the shape of the galaxy in paint.
Maybe think about different layers of abstractions. Each layer uses the parent layer, designer input, events & procedural generation algorithms to generate the needed data.
The Universe layer contains user or randomly placed galaxy polygons & types.
The Galaxy layers can add more details (number & density of spiral arms) or a density map.
A cluster of solar systems.
The solar system adds the stars & planets.
And only create the details for currently needed elements.
I'm programming a 2D game with HTML5 canvas. so it won't take a lot of time for rendering all the objects and frames.
I want to ask about both 2D and 3D games.
Suppose that I made a change or more on one of the objects.should I render all the objects when I only need to redraw that object? is rendering all objects and frames is the only option? and if the game was 3D, won't rendering take a lot of time? specially on slow internet connections
So [performance] depends only on the browser and computer of the user.
If you are making a game which is played simultaneously across several computers then the connection speed is important. Otherwise, the connection speed is mostly irrelevant (except as it relates to initially downloading your game resources). A better CPU/GPU, memory on the local computer will most affect your app performance.
About performance
In theory, you get better performance if you redraw only those game items which have changed since the last frame.
In practice, redrawing one game item often requires redrawing multiple other game items. You might want to redraw the player who moved, but in doing so you must also redraw the background plus any other game items colliding with the player.
As a result, it's often better to clear the entire canvas and redraw all the game items in their current position. So the unsatisfying answer to your question is that you should test your unique game app to determine if you can efficiently redraw just changed items or if a complete redrawing is faster.
As an exercise, I decided to write a SimCity (original) clone in Swift for OSX. I started the project using SpriteKit, originally having each tile as an instance of SKSpriteNode and swapping the texture of each node when that tile changed. This caused terrible performance, so I switched the drawing over to regular Cocoa windows, implementing drawRect to draw NSImages at the correct tile position. This solution worked well until I needed to implement animated tiles which refresh very quickly.
From here, I went back to the first approach, this time using a texture atlas to reduce the amount of draws needed, however, swapping textures of nodes that need to be animated was still very slow and had a huge detrimental effect on frame rate.
I'm attempting to display a 44x44 tile map where each tile is 16x16 pixels. I know here must be an efficient (or perhaps more correct way) to do this. This leads to my question:
Is there an efficient way to support 1500+ nodes in SpriteKit and which are animated through changing their textures? More importantly, am I taking the wrong approach by using SpriteKit and SKSpriteNode for each tile in the map (even if I only redraw the dirty ones)? Would another approach (perhaps, OpenGL?) be better?
Any help would be greatly appreciated. I'd be happy to provide code samples, but I'm not sure how relevant/helpful they would be for this question.
Edit
Here are some links to relevant drawing code and images to demonstrate the issue:
Screenshot:
When the player clicks on the small map, the center position of the large map changes. An event is fired from the small map the central engine powering the game which is then forwarded to listeners. The code that gets executed on the large map the change all of the textures can be found here:
https://github.com/chrisbenincasa/Swiftopolis/blob/drawing-performance/Swiftopolis/GameScene.swift#L489
That code uses tileImages which is a wrapper around a Texture Atlas that is generated at runtime.
https://github.com/chrisbenincasa/Swiftopolis/blob/drawing-performance/Swiftopolis/TileImages.swift
Please excuse the messiness of the code -- I made an alternate branch for this investigation and haven't cleaned up a lot of residual code that has been hanging around from pervious iterations.
I don't know if this will "answer" your question, but may help.
SpriteKit will likely be able to handle what you need but you need to look at different optimizations for SpriteKit and more so your game logic.
SpriteKit. Creating a .atlas is by far one of the best things you can do and will help keep your draw calls down. Also as I learned the hard way keep a pointer to your SKTextures as long as you need them and only generate the ones you needs. For instance don't create textureWithImageNamed#"myImage" every time you need a texture for myImage instead keep reusing a texture and store it in a dictionary. Also skView.ignoresSiblingOrder = YES; helps a bunch but you have to manage your own zPosition on all the sprites.
Game logic. Updating every tile every loop is going to be very expensive. You will want to look at a better way to do that. keeping smaller arrays or maybe doing logic (model) updates on a background thread.
I currently have a project you can look into if you want called Old Frank. I have a map that is 75 x 75 with 32px by 32px tiles that may be stacked 2 tall. I have both Mac and iOS target so you could in theory blow up the scene size and see how the performance holds up. Not saying there isn't optimization work to be done (it is a work in progress), but I feel it might help get you pointed in the right direction at least.
Hope that helps.
I am creating a tile-based 2D game as a way of learning basic "modern" OpenGL concepts. I'm using shaders with OpenGL 2.1., and am familiar with the rendering pipeline and how to actually draw geometry on-screen. What I'm wondering is the best way to organize a tilemap to render quickly and efficiently. I have thought of several potential methods:
1.) Store the quad representing a single tile (vertices and texture coordinates) in a VBO and render each tile with a separate draw* call, translating it to the correct position onscreen and using uniform2i to give the location in the texture atlas for that particular tile;
2.) Keep a VBO containing every tile onscreen (already-computed screen coordinates and texture atlas coordinates), using BufferSubData to update the tiles every frame but using a single draw* call;
3.) Keep VBOs containing static NxN "chunks" of tiles, drawing however many chunks of tiles are at least partially visible onscreen and translating them each into position.
*I'd like to stay away from the last option if possible unless rendering chunks of 64x64 is not too inefficient. Tiles are loaded into memory in blocks of that size, and even though only about 20x40 tiles are visible onscreen at a time, I would have to render up to four chunks at once. This method would also complicate my code in several other ways.
So, which of these is the most efficient way to render a screen of tiles? Are there any better methods?
You could do any one of these and they would probably be fine; what you're proposing to render is very, very simple.
#1 will definitely be worse in principle than the other options, because you would be drawing many extremely simple “models” rather than letting the GPU do a whole lot of batch work on one draw call. However, if you have only 20×40 = 800 tiles visible on screen at once, then this is a trivial amount of work for any modern CPU and GPU (unless you're doing some crazy fragment shader).
I recommend you go with whichever is simplest to program for you, so that you can continue work on your game. I imagine this would be #1, or possibly #2. If and when you find yourself with a performance problem, do whichever of #2 or #3 (64×64 sounds like a fine chunk size) lets you spend the least CPU time on your program's part of drawing (i.e. updating the buffer(s)).
I've been recently learning modern OpenGL myself, through OpenGL ES 2.0 on Android. The OpenGL ES 2.0 Programming Guide recommends an "array of structures", that is,
"Store vertex attributes together in a single buffer. The structure represents all attributes of a vertex and we have an array of these attributes per vertex."
While this may seem like it would initially consume a lot of space, it allows for efficient rendering using VBOs and flexibility in texture mapping each tile. I recently did a tiled hex grid using interleaved arrays containing vertex, normals, color, and texture data for a 20x20 tile hex grid on a Droid 2. So far things are running smoothly.
I'm looking for advice more than direct help.
I am working on an 8 bit platformer game in XNA. I've probably sunk 160 hours into it already, and I'm starting to get into issues with the engine I have. It is basically an adapted/modified version of the XNA platformer demo. All or most of my tiles are 32x32, but some are 64 wide and 32 px tall, like a desk. Some are 32 wide and 64 tall, like a plant.
I am shipping them to the gpu just one .png at a time similar to the way that the XNA tutorial's author does tile mapping. For animated sprites I do use a tile map of different frames of the character. For the tile map data, I read in a text file just like the XNA tutorial.
How should I accommodate for the wide and tall tiles? Should I make a two layered tile system (I figured I should abide by the keep-it-simple-stupid rule)?
Right now I'm using transparent tiles to extend the wide tiles.
Desk with chair:
chair http://dl.dropbox.com/u/8446900/game_screen_desk.png
.....
...h.
..d".
#####
Plant and chair:
desk http://dl.dropbox.com/u/8446900/game_screen_plant.png
..p...h.
..,...,.
########
The chair is 'h', 'd' is for desk, 'p' is plant, and ',' is for a transparent background tile (no interaction with the user). '"' is for a transparent tile that the user can stand on (extending the desk). The problem is, as you can see, the background appears to have a hole in it.
Should I make an actual tile map and combine everything into one large png? Another option I could take is to actually cut each wide or tall tile into two different tiles. How would a pro do this? I'm not looking for a quick and dirty fix, just how a modern day platformer would run.
UPDATE: After reviewing the answer, I found a very useful tool that packs sprites into a sheet.
http://spritesheetpacker.codeplex.com/
UPDATE: My newly upgraded tile engine is much faster and almost just as simple. The advice below was great. Strongly recommended.
First off - don't introduce special-width/height tiles. Make the artist slice up large objects into single tiles (and hence re-compose them on the map editor). Every tile should be a PNG with an alpha channel so they can be correctly composed.
Keeping that in mind, my recommendations are:
Your tiles should comprise of only single tiles that have pre-composed parts of different objects, for example the left part of the desk is a single tile, the right part without a chair is another and one more with the chair behind it. (tilevalue = "dc", perhaps?)
You can define multiple layers of single tiles and render them back-to-front. You can also define a parallax factor for multiple layers and thus get a nice parallax effect between two layers quite easily. Of course, the player must "exist" in one layer at a time or you won't know what collision geometry to use for his/her current position.
You should also not create one texture per tile - but a compiled tilesheet (exactly like a spritesheet) so that the number of renderstate changes you make are minimized. Making many changes per draw call is bad because each time you make a change (current texture, drawing color or something else that affects that draw call) the API, the driver and possibly the GPU itself has to do work to update its state - this adds up quick.
Note that this doesn't mean you should put characters and levels into a HUGE spritesheet - this is bad for other reasons. You could, for example: put all level-related tiles in one tilesheet, the hero's animation tiles on another and all enemies on one (together) or something similar.
Hope that helps, otherwise I'd be glad to explain things further.