Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

mike3

Member Since 06 Feb 2012
Offline Last Active Jan 31 2013 07:15 PM
-----

Topics I've Started

Rendering system for a "rogue-like" game.

18 January 2013 - 02:30 AM

Hi.

 

I was wondering about this. For those of you who don't know, "rogue-like" games are a kind of game that feature randomly-generated levels and other content, are a kind of RPG, are turn-based, feature "permanent death" (no save games, or saves only work as indefinite game pauses and not reversion steps), and usually have simple graphics, sometimes even just "text-based graphics" (using symbols like "#" for walls). Now, I was wondering: how would one go about making the "rendering" system for such a game, so as to be able to support both text-based graphics and also being abstracted right so as to relatively easily drop in a render system to render tile-based graphics? Note that these two may use both hugely different low-level libraries and APIs (e.g. terminal output for text mode, SDL or similar for tile mode), and also the data that need rendering are different (you render text characters in text mode, sprites in tile mode).

 

What would you suggest? I was using C++ to write the program. It also needs the ability to put up a "dialog box" (perhaps drawn in with text characters, or with simple graphics in graphical mode) that can have options/lists, e.g. the stuff you're carrying in your pack, magic spells, etc. .

 


What's the best way to implement a level map like this?

27 February 2012 - 06:08 PM

Hi.

I've got another little dilemma for you. I'm wondering what the best way is to implement this kind of level map for a game in C++ is. The map is supposed to be a regular 2D grid of. What I have is something similar to this:

enum TileType { // not an enum in the current code though but should be changed to one
	 ...
};

class LevelTile {
	 private:
		  TileType tileType;
		  ... (various flags and settings in here) ...
	 public:
		  ...
};

class LevelMap {
	 private:
		  ...
		  std::vector< std::vector< LevelTile > > mapTiles;
		  ...
	 public:
		  ...
};

The trick part is representing the different types of tiles. Here, I have the tiles referred to by a type-field. But then we need a bunch of switch statements to give different tile behaviors based on different types of tiles. Would it be better to use multiple types of LevelTile (i.e. derived classes)? But then comes the questions of:

1. we need to then store an array of pointers,

2. we need to allocate on the heap with new (and that takes more time, doesn't it, than just updating a type field) if we want to change a tile

3. when changing a tile, we need to be able to preserve its flags, which means we need some kind of "copyFlags()" function or something in LevelTile that would need to be called when doing such a change and so would complicate setting one tile to that of another type, or have conversion code for each kind of tile

Though these may not be insurmountable problems (e.g. in issue 3, we could have some kind of "mutateTile()" function in LevelMap that wraps up that calling of copyFlags() etc.). But I'd like to be clear as to which way is the "preferred" way of doing this: multiple types of Tile or type-field.

What is the best way to implement this "weird" kind of graph in C++ for a game?

06 February 2012 - 01:10 AM

Hi.

I've asked this on a couple of other forums and got some useful responses but I'm still not 100% sure as to the best way to proceed with this. I've got this problem of representing a "weird" kind of graph structure, which is like a normal graph but it has an additional layer of structure called "strings" which are composed of nodes connected together and ordered in a linear order. The purpose of this graph is to represent a system of levels in a game. In one of the responses I got, it was suggested I should implement this using a conventional graph type (i.e. just an implementation of a conventional graph, like Boost's graphs). But the problems appear when considering the "strings". Namely, I have something like this:

class WeirdGraph {
	  private:
		  class NodeString {
			    private:
				    <...>
				    std::vector<WeirdGraphNodeIterator> nodes;
				    <...>
			    public:
				    <...>
		  };

		  <... (there is a graph variable declared here) ...>
		  std::vector<NodeString *> strings;
		  <...>
	  public:
		  <...>
		  
};

i.e. the weird graph object contains a private class to represent the strings. Problems are that: 1. iterators in the graph get invalidated. Each node string stores the nodes comprising it as iterators into the graph. When a node is deleted, the iterators get invalidated, and this seems to require an update to the NodeStrings. What can be done? Obviously, one could just use a graph that does not invalidate iterators (though this may lead to a penalty accessing/traversing the graph, hence why I'm a little hesitant, since I'm going to be accessing more than I'm going to be deleting stuff, though I doubt this is used in performance-critical code in any case so it probably doesn't matter.). But I'm curious to know if there may be a technique that would work even in the case of invalidating iterators. 2. To update, the node strings need to know what nodes belong to them. So the nodes contain a string ID field, which is user-specified when the user creates a string and the WeirdGraph enforces uniqueness. Is it "good form in C++" to have WeirdGraph do the enforcing and not NodeString? It feels iffy. 3. Regarding that, is there an alternative to using the user-specified string IDs that won't fail (e.g. incrementing a counter may fail long off into the future, but I doubt one will be creating and deleting billions of times. But is having that "latent failure" possibility in there OK? As it feels iffy too.)? 4. NodeString constructs nodes in its constructor, then deletes them in the destructor. This last bit makes me feel iffy as then it's not okay to pass one by value -- though we can always not do that, but I'm not sure whether having such requirements which are enforced only by user understanding is a good idea (although does it matter here since NodeString is a private internal of WeirdGraph?).

Any comments on these issues? Right now I'm really leaning toward using a non-invalidating graph type, as that would entirely eliminate 3 out of the 4 issues above, but I'd still like to know what the deal is on the 4th. The 4th is also why I'm using pointers above (perhaps I should use std::auto_ptr instead of raw pointers there? hmm) instead of objects directly, since that would necessitate some copying/by-value passing when filling that vector.

PARTNERS