I'm looking at creating a basic side-scroller using OpenGL and C++, however I'm having trouble tackling a few basic conceptual issues, namely:
Dividing the window into easy "blocks" (some sort of grid system). On what level would I want to do this? (The OpenGL viewport size, or through some abstraction that ensures working with multiples of x?)
Storing the data for all these "blocks" to allow for collision detection and some special effects. What's a sensible way of going about this - I was thinking along the lines of a multi-dimensional array of objects (which contain information such as the tile type), but this doesn't seem like a very elegant or efficient solution.
Usually, it isn't the window (ie. viewport) which is divided into a grid but rather the "gameplay area". Pick a good size according to the style of your art (something like 64px - you might want to select a size that is a power of two for technical reasons) and create tiles of that size for your game (stored and loaded as a 1D array)
Then, these tiles are referenced (by an offset) in a tilemap, which actually describes what your level looks like. Each tile can also have extra metadata for handling collisions and game events. You might want to use an existing map format and toolset to save time, like Mappy.
Tips:
Think of the display and the data separately (lookup Model-View-Controller).
How you store the data depends on how it's going to be accessed, not on how it's going to be displayed. Think of it from the computers point of view!
Hint, it's often easiest to work in a one dimensional storage of the data and work out where along it the next point up/down is than work in 2d.
Related
I am looking for a way to create an infinite view on a model that is not initialized completely. I would like to create something similar to an Excel spreadsheet, and all I came in was to start with an initialized model (e.g. 100x100 empty cells, maybe working on a database that has empty values), and then just dynamically add next rows/columns (and update view) once we are close to the end of a scrollbar.
But I am wondering if it is the best solution - I think I would definitively benefit from a model that's filled in only partially - by that, I mean store information in the model only about filled cells, and let view handle showing 'empty cells' (which would have been created once we - for example - click them).
I know it would be necessary to store XY positions and cell data (instead of only a 2D container with data), but I would like to try different solutions:
a) have a pointer-like container which would contain a list of filled cells with their positions on a 2D plane
b) have a 2D container with size (x,y), where x and y would mean the 'last filled cell' in a given dimension
And for both solutions, I would like to dynamically allocate more place once data is written.
So there is my question - how can it be achieved with QT model/view programming, if it is even possible to show 'ghost cells' without a model filled with empty data? It would be also nice if I could get a brief explanation of how it is done in apps like excel etc.
Well, your table will never be truly infinite unless you implement some indexing with numbers with infinite digit count and in that case, you will probably not be able to use Qt classes.
But I think you should choose some big enough number to define the maximum. It can be a really large number... if you are on a 64-bit machine, then your 'infinite' table can have 9,223,372,036,854,775,807 rows and the same number of columns. This big number happens to be the maximum of signed 64-bit int. And int is used for indexing with QModelIndex in QAbstractItemModel. So you can have a total of 8.5070592e+37 cells in your two-dimensional 'Excel' table. If this table size is not big enough for you then I do not know what is. Just for comparison, there are approximately 7e+27 atoms in the average human body, maybe a bit more after the covid lockdowns because people were eating instead of practicing sports. :) So you can count all atoms of all people on this planet (say there are a bit less than 10e+10 people altogether). But you will need to buy a bit bigger computer for this task.
So if you decide to go this way, then you can easily override QAbstractTableModel and display it in QTableView. Of course, you cannot save the underlying data in a two-dimensional array because you do not have enough memory. But you have to choose some other method. For example a QHash<QPoint, QString> where QPoint will represent the coordinates and QString the value (you can choose any other type instead of a string of course). Then when you will want to get the value for the given coordinates, you just look up the value in the hash table. The number of data points you will be able to hold depends only on your memory size. This solution is very simple, I guess it will be some 30 rows of code, not more.
I want to be able to register/de-register Objects to a list and check if the mouse is hovering over them to display tool-tips. However I'm stumbling at the beginning.
I'm going to use: al_get_pixel & al_unmap_rgba to retrieve the alpha of each pixel and decide if it's visible enough to count as a hit when hovering over it with the mouse.
The major problem I'm having is working out how best to store this individual "hitmap" & the reference to the object that generated it; As many different types objects (as struct's) of different sizes may need hitmaps generated. I was hoping I could do something similar to checking if the complex object 'extends' the base object but I don't see how I can achieve this in c++.
Ps; I know I could create an array the size of the screen for each object, but I'm doing this mainly with the purpose of maximizing efficiency. I'd make dynamic sized arrays but...
al_get_pixel will work, but it will be terribly slow, even if you lock all your bitmaps, unless you use something like a picking buffer. The basic idea is to render every interactive area on each object with a different color id. This means you need to draw your scene twice, once normally, and once with picking colors. Then when you need to read back a mouse position, you can use the picking buffer to read a single pixel and get its color id.
You might also want to try different methods of collision detection, such as bounding boxes, bounding circles, or other easily collision detectable shapes.
There is a third option, which is pixel perfect collision. It involves making 1bpp masks out of all your objects and then checking for collision between those.
I work on a project which demands to use A* algorithm. In this project you select your player with the left click and you guide him in the map with the right click, like the gameplay of thousand strategy game. The graphics are 2D, a little like the game Don't Starve and the game is developped with SFML / C++.
I need to use A* for the deplacement of the player, indeed if an obstacle appears on his road he has to avoid it. But for the moment, i don't know how to apply a grid to the map, i want to place any tree / rocks and other stuff anywhere in order not to see the grid cells. For now the open list is only composed of pixels, which is not the good solution I think ^^, the algorithm is pretty slow. If you have any solution for a realistic rendering while keeping a fast algorithm I'd be happy to hear it. :)
Thank you in advance,
Do you have a screenshot?
The pathfinding grid, and rendering grid can be different. Zelda used different sized tiles for movement and rendering.
navigation mesh
This may be overkill for your map structure, but you may use a navigation mesh.
,
edit: If you haven't read it, Amit has a great resource: http://theory.stanford.edu/~amitp/GameProgramming/
What you're looking for is discretization. Behind this obscene name stands a simple principle : you can't deal with an infinite amount of data.
You need then to perform a transformation on your world : instead of allowing your character/unit to go at any location (x and y being real numbers), you can divide your world into some sort of a grid (this is what the navigation mesh and waypoints are doing), and only allow your char to go on these cells (or points, you can see it as you want). This is discretising : you are going from continuous values (real coordinates) to discrete values (integer coordinates / point). The more precise you go, the nicer it'll look.
After doing this, assigning moving costs between cells/points is rather simple, and performing A* on it as well.
If you begin to render points, render a ton of vertices, and then end, you get noticeably better performance than if you begin points, render a vertex, end, and repeat a ton of times (e.g., redraws during pan and zoom actions for, say, 200,000 points are MUCH smoother).
I guess this might make sense, but it's disappointing. Is there a way to get back the performance while still rendering each point in its own begin-end block?
BACKGROUND:
I wanted to design a control that could contain a ton (upwards of a million in an extreme case) of "objects" that each do its own rendering. Many of these objects will represent themselves as points.
If I let a hundred-thousand points individually render themselves in their own begin-end blocks, I get a major performance hit (as opposed to rendering them all in a single begin-end block). It thus seems I might have to make the container aware of the way the objects render themselves (for example, beginning points, telling everything that needs to render a point to do so, and then ending).
This messes up the independent nature of the display-object relationship I wanted. It also messes up hit testing by selection because I don't think you can add a name to a vertex inside a begin-end block of points, right?
FYI (in case this helps) my project will be displaying a 2D scene (using an ortho projection) and requires hit testing to determine which related object a user might click. In general, the objects will represent "tracks" containing individual points connected with lines. The position data is generally static, but point and track colors and display representations may change due to user settings and selection information. One exception--a "playback" mode may allow the user to see only one track point at a time (the "current" point in the playback) and step through time from one point to the next. However, even in that case I assumed I would simply change which point on each track is actually displayed (at its "static" location) depending on the current time in the playback. If any of that brings to mind further suggestions for an OpenGL newbie, then much thanks!
To solve this issue, I started by using VBOs (which did speed things up). I then allowed my "track" objects to each draw their own set of points as well as the lines connecting the points (each track using two DrawArrays: one for the line strip and one for the points). Each point does not have to draw itself independent of the other points--this was the major performance improvement.
BUT, I still needed hit-testing against the points, so..
Finally, I needed allowed each displayed object (in this case, the tracks) to do its own selection routine so each object can do what it needs for efficient selection. For tracks, they took a two-step process. First, a track names its entire line strip with one name (0) and performs the select. IF that results in a hit, then the track does a second render pass, naming each individual point and line segment to hit-test against each part of the track. This makes hit-testing against each point quite fast.
As an aside, I'm using .Net (C#) for my programming. With it, I created a class (SelectEventArgs) derived from EventArgs to describe selection criteria to objects being displayed. My SelectEventArgs class includes a list meant to be filled with selected objects. The display class then has an EventHandler<SelectEventArgs> event. When an object is added to a display, it subscribes to that event. When the event fires, each object determines whether it's been selected and fills the list of selected objects (in the SelectEventArgs passed in the event) with its information. After the event fires, I can access the list of objects returned in the SelectEventArgs instance to handle the user interaction. I find this to be a nice pattern for creating flexible display objects and selection tools.
I was wandering how it's possible to create a large terrain in opengl. My first idea was using blender and create a plane, subdevide it, create the terrain and export it as .obj. After taking a look at blender I thought this should be possible but soon I realized that my hexacore + 8GB RAM aren't able too keep up the subdeviding in order to support the required precision for a very large terrain.
So my question is, what is the best way to do this?
Maybe trying another 3D rendering software like cinema4d?
Creating the terrain step-by-step in blender and put it together later? (might be problematic to maintain the ratio between the segments)
Some methods I don't know about?
I could create a large landscape with a random generation algorithm but I don't want a random landscape I need a customized landscape with many details. (heights, depth, paths)
Edit
What I'll do is:
Create 3 different heightmaps (1. cave ground (+maybe half of the wall height), 2. inverted heightmap for cave ceiling, 3. standard surface heightmap)
Combine all three heightmaps
Save them in a obj file or whatever format required
do some fine tuning in 3d editing tool (if it's too large to handle I'll create an app with LOD algorithm where I can edit some minor stuff)
save it again as whatever is required (maybe do some optimization)
be happy
Edit2
The map I'm creating is so big that Photoshop is using all of my 8GB Ram so I have to split all 3 heightmaps in smaller parts and assemble them on the fly when moving over the map.
I believe you would just want to make a height map. The larger you make the image, the further it can stretch. Perhaps if you made the seams match up, you could tile it, but if you want an endless terrain it's probably worth the effort to generate a terrain.
To make a height map, you'll make an image where each pixel represents a set height (you don't really have to represent it as an image, but it makes it very easy to visualize) which becomes a grey-scaled color. You can then scale this value to the desired maximum height (precision is decided by the bit-depth of the image).
If you wanted to do this with OpenGL, you could make an interface where you click at points to raise the height of particular points or areas.
Once you have this image, rendering it isn't too hard, because the X and Y coordinates are set for your space and the image will give you the Z coordinate.
This would have the downside of not allowing for caves and similar features (because there is only one height given for a point). If you needed these features, they might be added with meshes or a 2nd
If you're trying to store more data than fits in memory, you need to keep most of it on disk. Dividing the map into segments, loading the nearer segments as necessary, is the technique. A lot of groups access the map segments via quadtrees, which usually don't need much traversion to get to the "nearby" parts.
Variations include creating lower-resolution versions of larger chunks of map for use in rendering long views, so you're keeping a really low-res version of the Whole Map, a medium-res version of This Valley Here, and a high-res copy of This Grove Of Trees I'm Looking At.
It's complicated stuff, which is why nobody really put the whole thing together until about GTA:San Andreas or Oblivion.