   Help me build my tile engine!
  Hello everyone,I'm bored at work and I've never accomplished anything while browsing on these boards (although I've tried a few time and always failed...) so I'm *going* to build a very simple tiling engine using SDL and C#. I'm not asking specific C# or SDL help but I'd like input for my design. I know NOTHING about these although I've read a bit on the subject. So if you guys would be so kind and point to potential flaws and/or tell me my design is total crap I'll take it very well and try to make it better... After all my job sucks and I nothing better to do :)I want to be able to make a map editor in C#.NET (using a windows form) once I have my tiling engine setup. Here are a few things I want:-Smooth scrolling-Have my own map format (not grandios... just so I can load and save maps)So far I've come up with the following classes:Tileset:int width int height // height+width of the imageint grid_xint grid_y // the grid size to determine how big tiles arefile image----------loadTileset()Tile:Tileset parentint coord_xint coord_y------------drawTile(coord_x, coord_y)Map:widthheightTile layout[][]-----------drawMap(layout[][])saveMap()loadMap() //I'm not sure about theseCamera:position_xposition_y // represent the center of the window-----------update() // draw || update the screenSo far I can figure out the following relationships:Tileset (1)-(*) Tile (*)-(*) Map (*)-(1) CameraAm I totally off? Do you guys see something I missed that should be important for one of the features I've mentioned? Is there something from the way I setup my system that will hinder performance or keep me from seting up some kind of smooth scrolling? Any advice in general? I'd like to make  this with the help of the forum so I can show progress and learn from the small engine.Thanks to anyone who wants to take the time and help me out, it's really appreciated!   
  I don't know if it would help but in this thread I've just described a bit of the approach I use for 2D tile based scrolling maps.That was responding to a different question though so don't hesitate to ask if it is not too clear.Generally, I don't think you need to maintain the position of each tile in each tile in a regular tile map since the world co-ords are more easily generated on the fly as you loop through drawing the tiles.As for saving and loading, if each tile is represented by a number that indexes a tile image, it is pretty simple to save and load the information using fstreams really.HTH Paul   ;  Thanks,You made a good point regarding the tile's position... I actually made a mistake in the process of designing it. The x and y values in the Tile class are meant to represent it's position in the tileset.As far as the saving of the maps; I wasn't sure where I'd have to implement the saving feature. I'd like to keep some sort of consistent OO design and I don't know if the save and load functions are in the right place. I suppose in my simple engine it wouldn't make much sense putting them anywhere else.Also, I'm currently reading the thread you pointed at. You say this:Quote:let's assume our map is represented by a 2D array (horror!)Why is it a horror? What would you recommend instead?   ;  Perhaps that was a bit strong. I am just not a fan of 2D arrays since they are a nightmare to pass around to functions and so on. You also can't resize them once they have been declared, or size them dynamically.Personally, I'd recommend wrapping a 1D vector in a map class and overloading operator() to access it, a bit like:#include <vector>class map_cell{public:    map_cell(int t=0) : tile(t) { }   int tile;};class map{private:    std::vector<map_cell> v; int wt,ht; map_cell blank;public:    map(int w=10,int h=10) : v(w*h),wt(w),ht(h) { }    int width() const { return wt; }    int height() const { return ht; }    map_cell &operator()(int x,int y);    const map_cell &operator()(int x,int y) const;    void resize(int w,int h){ wt=w; ht=h; v.resize(w*h); }};map_cell &map::operator()(int x,int y){    if(x<0 || x>=wt || y<0 || y>=ht) return blank;    return v[(y*wt)+x];}const map_cell &map::operator()(int x,int y) const{    if(x<0 || x>=wt || y<0 || y>=ht) return blank;    return v[(y*wt)+x];}Not everyone would agree with my returning the blank on out of bounds but I personally find it simplifies my code when drawing the tiles to the screen.I'd be inclined not to make load and save member functions but make them non-members that use the interface above. Say your map file was a text file that looked a bit like10 10 // width and height01 01 01 01 01 01 01 01 01 0101 00 00 00 00 00 00 00 00 0101 00 00 00 00 00 00 00 00 0101 00 00 00 00 02 02 02 00 0101 00 00 00 00 00 00 00 00 0101 00 00 00 00 00 00 00 00 0101 00 00 01 01 00 00 00 00 0101 00 00 01 00 00 00 00 00 0101 00 00 01 00 00 00 00 00 0101 01 01 01 01 01 01 01 01 01You could make a load function with the standard library:#include <fstream>#include <string>bool load_map(const std::string &s,map &m){    std::ifstream is(s.c_str()); if(!is.open()) return false;    int w,h; is >> w >> h;    m.resize(w,h);    for(int y=0;y<h;++y)   {   for(int x=0;x<w;++x)  {  is >> m(x,y).tile;  }   }    return true;}You wouldn't normally want to save a map from a game engine since they would be created with a level editor (or notepad in the above example) or whatever. The principle would be much the same though.   ;  Okay so I'm currently trying to build my map format.I realized that I was improvising WAY TOO MUCH so I'm back at the drawing board to try and figure out a system that will stay flexible and allow me to make maps through an editor.However I'm having a few problems figuring things out. I know I will have the map layout mentioned in the previous post but how much information needs to be external? I can't hardcode anything if I want this to be flexible.So should I have a file for:-tileset.ts-map.map?Say I went this route, should my tileset file hold the tile's information such as collision information and such? This is where I'm a bit at a loss. How do people usually proceed for this kind of thing?   ;  For what it is worth, the last 2D tile based game I was writing worked like this:The start of the level file contained a list of tile classes that were read into a vector. For each tile, it specified the image index, a byte whose bits dictated whether or not the tile was solid, whether touching it was fatal to the player and so on, and an ID number that identified the tile class. This meant I could have two different tiles with the same image but different solid attributes or whatever.The map then followed, with each cell in the map being a reference to the above mentioned ID to identify which tile class was in that cell. The point of using an ID rather than an index was that I could add tile classes to the above list without having to change the existing map.When the map was loaded, the IDs were converted into literal indexes into the tile class vector to save searching it once the game was actually running.I see no reason you couldn't store tile information in a seperate file. In fact I can see several advantages to doing this. The problem, as I see it, is that stuff like the tile attributes may vary from game to game, so writing a single map editor that will cater for every eventuality may be a bit tough.   ;  I figured the tiles shouldn't hold too much information on their own aside from the collision detection box. I'll see what I can do :D   ;  Yeah, that would make sense and be nice and reusable. Might do something like that myself in future.Would be nice to have just one map editor that would work for loads of different games. I suppose you could always have any additional attributes for tiles loaded in seperately to the actual tile information.I can certainly see the advantage to coming up with a standard .map format that was flexible enough to work with anything. Cheers for the food for thought.   ;  Hi,About the map I'd recommend you create a map object...class MAP2D{  char map[256][256];   char blockmap[256][256];   ...constructors and access methods...}That way you can send a MAP2D* parameter to your functions if required and not your array.The blockmap can be used to define which terrain is used so you the map class may expose the a path search function.Now as an advice... think a lot your texture manager and about the sprite organization. Its crucial to all this... try to engineer the collowing classes.class CONSOLE -- your access to your window and device inicializationclass DEVICE:public CONSOLE -- your rendering deviceclass RESOURCE -- basic file control and management. A resource should control a time index in order to know the last time it was used.class TEXTURE:public RESOURCE -- A texture resource. Should support active and inactive textures. An active texture has the texture info loaded. An inactive texture unloads the texture data but keeps reference to the texture name and path so it can quickly be reactivated or deactivated using Activate()/Deactivate() methods.class BASEMAN -- manages the list of directoriesclass TEXTUREMAN -- holds an array/list of textures. Exposes methods like LoadTexture() and GetTexture(). Loading a texture means you have to check if the texture was created successfully and in case it fails because there is no more meory it should search and deactivate the least recently used texture. and activate the new one. Texture man should also be able to unload all the textures or delete them from the list. THis is an extremely important component.For graph servers:class FRAME - an animation frame. Can be used for sprites. This object represents a single square over your texture. As a hint, try to use a dual coordinate system. That is... pixels and UV coordinates. A frame should reference its texture.class SEQUENCE - A group of animation frames which form an animation cycle or strip. Like running or shooting IN A SINGLE DIRECTION. Can be used to define animated tiles or fonts. A sequence also defines an animation speed so the strip is played in 1 second, 2 seconds or whatever you wish.class ANIMATION - While a sequence represents a single animation strip, an animation is used to group many sequences that represent a single animation. Like running. Your character can run left, right, up, down or diagonally. An animation holds all the sequences that describe that animation. So you should have Running, shooting, crouching etc animations each one with sequences facing a single direction.class GSERVER - A graphics server is group of animations which define a single character. So you may have a GSERVER for a soldier, a GSERVER for a wizard, a GSERVER for an orc. Note this is NOT a sprite. Is a model from which all the sprites are drawn.class GSERVERMAN - a manager for all the gservers. This is a collection for all your basic objects.For scene:class SCENEOBJECT - Define a basic scene posable nodeclass SPRITE:public SCENEOBJECT - Define a n object which can be placed on the scene. IT should reference a GSERVER so the engine knows which images to draw. Also add a time counter so each sprite will have its own timing management. Add an animation index so you know which animation the sprite is performing. Add x and y coordinates AS FLOATING POINTS so you will be able to control your objects but not depend on the screen.class LIGHT:public SCENEOBJECT - Defines a light emmiting point. Keep it simple as a point light.class SCENEOBJECTLIST - Defines a list of objects. If you remove an object from the list it wont destroy the original object at all.class SCENEOBJECTTREE - Defines a strong structure of objects. You may implement more advanced control structures like binary or quad trees.class SCENE - Define a scene class. I'd recommend to add many object lists as layers. That way you will have:SCENEOBJECTTREE layer[10];so the layer 0 can be the objects at the ground level, pickpups, gold, treasure, rocks and so on. Layer 1 can be static objects like trees, houses or big rocks. Layer 2 can be mobile objects like monsters or the player character and missile objects. Layer 3 can be aerial creatures like dragons. Layer 5 can be aerial extras like a flying birs that happens to move by or some butterfly. Layer 6 may be diyng creatures that are waiting to be removed from scene. Layer 7 may be adornments over the ground like flowers or blood pools. I hope you have the idea.Also, add:SCENEOBJECTLIST lights;That is a list of all the light emmiting objects. Notice that the same object should be part of one of the scene trees.SCENEOBJECTLIST shadows;That is a list of all the objects which cast shadows. Notice that the same object should be part of one of the scene trees.Of course add the map object to the scene. I hope this server you as a base for implemntation.Luck!Guimo