Archived

This topic is now archived and is closed to further replies.

BalooBear

Isometric Engine Help

Recommended Posts

Ok, I want to program a Civisation / Alpha Centauri type game and have all the designs (in UML) and have read all the tutorials on Isometric programming on this site but there is just one problem. Not one of the tutorials takes the beginner (not to programming but just to isometric game programming) from setting up a direct 3d window to drawing the tiles to the screen in code form. Ideally in cut and paste style not so I can use it for myself (as I want to learn) but so I can see the whole picture. My question is, is there any isometric engine tutorials with complete examples or failing that a good engine with the source code? Thanks in advance, Baloo

Share this post


Link to post
Share on other sites
Weeeeeeell.

There''s FreeCraft. It uses SDL, rather than DirectX, but should be good for the parts of your game that don''t need to worry about DirectX.

Joseph "Ironblayde" Farrel made a Game Programming Genesis series of articles here on gamedev that talk about DirectX in general and specifically about tile-based games. The story begins to unfold at http://www.gamedev.net/reference/programming/features/gpgenesis1

Martin Estevao has a Tiling in DirectX pair of articles. They start at http://www.gamedev.net/reference/programming/features/tiling1/

I tried looking under Real Time Strategy in sourceforge. Sadly, there aren''t many examples that are past the design stage, and many of them seem to obviously not be RTS games.

If you find you need some illuminating theory (and you will), I suggest Auran''s manual for their Tactics engine (as used in Dark Reign). It, and a description of the AI system the engine uses, reside at http://www.auran.com/games/darkreign/drengine.htm. Although, if you''re after a Alpha Centauri type of game, you''ll need far more sophisticated AI than Tactics. In fairness, you want far more sophisticated AI regardless, Tactics is pretty dumb.


Uuuuuulrika-ka-ka-ka-ka-ka

Share this post


Link to post
Share on other sites
Actually, a lot of gamedev''s isometric tutorials include good source. Look back at those tutorials and download the source. If you have basic knowlege of directx and c++ you should be able to learn from just studying those.

Share this post


Link to post
Share on other sites
Ok, thanks for all your help, got an engine up and running based on one of the tutorials. Now I''m wondering if I can animate 3ds or similar models on a tile. As the game is a civilisation/alpha centauri turn based game I dont need anything fancy but I would like to animate the units i.e troops playing with thier guns when selected e.t.c. I know its possible but how hard is it?

Baloo

Share this post


Link to post
Share on other sites
<OFFTOPIC>

Chances are your browser is submitting the page twice, for some reason. I''ve not idea why it would do that, so I can''t be any help.

</OFFTOPIC>

Uuuuuulrika-ka-ka-ka-ka-ka

Share this post


Link to post
Share on other sites
Hmm. Animation. There are two things you might want to animate, and its possible to animate them in almost exactly the same way.

You can animate tiles. For this we''re talking about animating the tiles themselves, and not a ''unit'' placed upon the tile. For example, you could add a ripple effect to a sea tile, or you could put a waving flag onto a city. You shouldn''t overdo animated tiles, because one of the uses of animation is to draw your attention to something - so you should probably only animate something that the user can interact with.

As an aside, if you can have units underwater, it might be nice to have them ripple along with the water itself. This would look good, and tell you visually that the unit is underwater. There are some tutorials here on gamedev about water effects.

The way to animate a tile is really quite simple, once you''ve drawn the frames. Lets imagine that your tile''s image is 64 pixels high, and 32 across. You''re holding a bitmap for masking, and the pixmap itself. This could be held as the following type:


/* The size of one frame is 2304 bytes. */
typedef struct {
bool bitmap[64][32];
char pixmap[64][32];
} TILE_IMAGE;


Firstly, we need a way to hold the tile frames. The brute force method is to define the TILE_IMAGE type as:


/* The size of one frame is 2304 bytes. */
typedef struct {
bool bitmap[64][32];
char pixmap[64][32];
} TILE_IMAGE[MAX_FRAMES];


Where MAX_FRAMES is the maximum number of frames a tile can have, 16, for example. But this is obviously wasteful, even a tile with only one frame would have to have space allocated for extra frames, and it''s quite possible that a tile''s bitmask will be constant - it may be a building with blinkenlights, for example - so duplicating it is again wasteful.


/* The size of one unique frame is 2312 bytes
* The size of one duplicate frame is 8 bytes. */
typedef struct {
bool *(bitmap[64][32]);
char *(pixmap[64][32]);
} TILE_IMAGE[MAX_FRAMES];


In this structure, we use pointers to maps. Identical frames would point to the same map. Duplicate frames are over 2k smaller, but each tile takes up at least 128 bytes (MAX_FRAMES*8), even if it had no frames. For one tiles, that''s okay, but your game may have hundreds.


/* The size of one unique frame is 2320 bytes
* The size of one duplicate frame is 16 bytes. */
typedef struct {
char frame_count;
struct TILE_FRAME {
bool *(bitmap[64][32]);
char *(pixmap[64][32]);
} frame[frame_count];
} TILE_IMAGE;


In this example, the arrays of images are allocated dynamically. A tile with only one frame is 2321 bytes in size (2320 for the frame, and one for the frame count). That''s an extra 17 bytes per tile, which is considerably better than 128.

In reality, you can''t just cycle through each frame. You may want the tile to stay on a particular frame for a long time, and another for only a short time. You might also want the tile to only enter a particular frame if you explicitly tell it to. (A power plant would probably look different when turned off). You need to tell it how long to wait on a particular frame, and which frame to go to next.


typedef struct {
char frame_count;
struct TILE_FRAME {
bool *(bitmap[64][32]);
char *(pixmap[64][32]);
char wait_time;
char next_frame;
} frame[frame_count];
} TILE_IMAGE;


So here we have the next version. Each frame has a wait_time, and a next_frame. For the power plant mentioned earlier, you might have frames 0-5 for its ''on'' state, and 6-10 for its ''off'' state. Frame 5''s next_frame would be 0, and frame 10''s next_frame would be 6. Another part of the program would be responsible for ensuring that the plant moves to a new frame when it comes online, or goes offline. If you wanted to be complex about it, you might have frames for ''on'', ''going offline'', ''off'' and ''going online''.

In practice, this isn''t what I do. With this system, you have to keep a track not only of each tile''s image, but also what frame in that image it is using, and how long until we need to move to the next frame. That''s a lot of data to be holding on each tile. What I do is this:


typedef struct {
bool *(bitmap[64][32]);
char *(pixmap[64][32]);
char next_image;
} TILE_IMAGE;
TILE_IMAGE *tileImages;


Now, all we need to know about each tile is which element in the tileImages array to use. In this system, you can''t control how long each frame is - all tiles change frames at the same time. For control over frame duration, I use sprites. Although this makes tiles less flexible, it makes the map a lot smaller in memory. (Each of my map-tiles is two bytes - one for the graphic to use, and the other is used to speed up checks on what units are in the tile. This limits me to 256 tile frames, altogether, but since I''d draw cities and improvements as units, it''s not an unreasonable limit).

There are two ways of drawing animated tiles that spring immediately to mind. The first involves creating multiple surfaces for the background. Lets imagine that the rule is that each animation can only be four frames long. Render the background four times, one for each frame, and also render the units and any foreground stuff into another surface. Each time the background frame changes, blit the foreground surface onto the current background surface and then flip the combined surface to the display. I''m currently investigation using overlay surfaces, a kind of automatic blit, to speed the whole process. An overlay is automatically blitted onto a surface its attached to when that surface is displayed. This means you can overlay the foreground over the background, then when you flip the background, the foreground will be blitted over the top at the same time. The second method of drawing the tiles is simply to redraw the surfaces each time. If there are too many frames for you to reasonably keep them all in memory at the same time, this may be your only option. Of course, when the view scrolls, you will need to redraw the newly exposed parts of the surfaces.

Animating Sprites.

You can animate sprites in much the same way as animating tiles.


typedef struct {
bool *bitmap;
char *pixmap;
char width;
char height;
char next_image;
char wait_time;
} SPRITE_IMAGE;
SPRITE_IMAGE *spriteImages;


The only extra data here is the width and height of the sprite, and the time to wait in this frame. The bitmap and pixmaps are no longer of constant size.

The information about the sprite itself has fields that indicate what image to use, and how long is left before we need to move to the next frame.

You can''t draw an animated foreground quite as quickly as you can draw an animated background, simply because each sprite changes frame at a different time, and may have hundreds of frames to go through. Best is to do a zbuffered blit onto the foreground when the sprite is changed. If you don''t want to use zbuffering, you''ll need to make sure that you redraw any sprites and/or tiles that are meant to obscure the one you just redrew.

Contextual Animation

That''s what I''m calling gun-fiddling behaviour since I don''t know of an official name for it.

Basically, you want a unit (or tile) to display an animation in response to something that happened to it (or just at random). The solution is quite simple. For example, to have your unit fiddle its gun when you select it, first create a series of frames with the gun-fiddling animation, then, when you select the unit, put it in the first of those frames. You can also have the unit fiddle its gun at random: lets say you''ve got a method on your units that is called each game ''tick'', you can randomly select to move to the gun-fiddling animation, or stay where you are. Many games have units do something when they''re bored - in Settlers the guys wave, grin, or exercise with a skipping rope when they haven''t done something for a while. In many FPS, the bad guys will fidget at random, which is a nice feature.

Now, 3D models. One of my favourite games is Total Annihiliationm, it uses 3D models, but a tiled map. The models are simple, but they can be very well animated, which makes them far more believable then many nice-looking but badly-animated units in other games. Firstly, animating a 3D model is fundamentally no different from animating a sprite - it''s still based on frames. Naturally, drawing a 3D model is completely different.

I can see two ways of animating of a 3D model. I''ve never done either, so they are probably inefficient. There are other forums and articles that can tell you far more than I about animating 3D characters.

The first is a brute force method which is basically an exact analog of sprite-based animation. For each frame, you define shape of the model, and its mapping coordinates so that the texture doesn''t slide over the model as it moves (assuming you''re texturing the model)). Now, when you draw the unit, you simply draw the current model.

The second involves skeletons and kinematics. It is more complex, but allows for more a richer range of expression on the part of the unit. I know nothing about this kind of system except that it exists, so I can''t say anything about its implementation.

The way I understand it, the first method is the most memory efficient if you have a lot of visually identical units (as is usually the case in an RTS), and is always processor efficient. The second method is more flexible, but is probably overkill for an Alpha Centauri clone.

Uuuuuulrika-ka-ka-ka-ka-ka

Share this post


Link to post
Share on other sites
Thanks Mayrel, you have been a great help. Hope I can ask you some more questions as and when they pop up. Whats your background? Are you a hobby programmer or professional? Any project you working on at the moment? Currently I''m an Embedded Software Engineer with an ambition of being a games programmer. Maybe someday it will happen, this is definatley a step in the right direction.

Baloo

Share this post


Link to post
Share on other sites
Just a hobbyist, me, with asperations to being a professional.

At the moment, I''m working on a generic tile-based engine. All the behaviours of tiles and units will be scripted, so it should be possible to run a SimCity-clone and a C&C-clone using the same program.

I''m using OpenGL, which I''ve found is so much easier than DirectX, and it''s portable.

Right now, I''m making an OOP interface to OpenGL. (I call it IGLOO, because it''s GL, object orientated)) When I''ve finished that, I''ll put the source and some documentation somewhere.


Uuuuuulrika-ka-ka-ka-ka-ka

Share this post


Link to post
Share on other sites
If you''re interested in looking at OpenGL, incidentally, you can''t do much better than NeHe''s tutorials in the OpenGL articles section here on gamedev. And, if you have the MSDN, you get a competent reference of the OpenGL functions with that.


Uuuuuulrika-ka-ka-ka-ka-ka

Share this post


Link to post
Share on other sites
Open GL specifically needs a 3D graphics card doesn''t it? Programming in my lunch hour at work (with no 3D card) and at home so directx seemed like a good idea (no need for 3d card).

Baloo

Share this post


Link to post
Share on other sites
Happily, no. Microsoft do provide a software implementation of OpenGL: indeed, when OpenGL first arrived on Windows, it hardly had any hardware support at all, so most people had no choice but to use software.

Incidentally, if you''ve seen Microsoft''s OpenGL screen savers, they use the software engine. For reasons that are unclear to me, you can''t even tell them to use any hardware you''ve got, they''re always software. Anyway, they''re about the kind of quality and speed you can expect from the software OpenGL engine.

You may find that some OpenGL games will refuse to run without an accelerator. There are some advanced OpenGL features that Microsoft''s software engine doesn''t support, but you are unlikely to need to use them. You just have to make sure that you tell Windows that it''s okay for it to use its software engine.

The only (slight) complication with OpenGL is that 2D graphics are a little more tricky than with DirectX - there''s no direct (if you''ll excuse the pun) equivalent of DirectDraw. However, I assume (haven''t checked, will do when I get home) that you can use the normal Device Context functions just like you can with DirectX.

Uuuuuulrika-ka-ka-ka-ka-ka

Share this post


Link to post
Share on other sites
Just getting to the stage where I think I know slightly what I''m doing with DirectX (although I''m only doing simple things at the moment) so moving to OpenGL would probably cause more headaches that solve them.

Baloo

Share this post


Link to post
Share on other sites
Well, if it ain''t broke...

IGLOO still needs to use DirectX for keyboard/mouse input, and audio output; DirectX isn''t entirely useless.

On top of that, I also want to make a version of IGLOO that uses Direct3D for any folks who don''t have GL. So, chances are I''ll still be looking into things that will interest you.

Uuuuuulrika-ka-ka-ka-ka-ka

Share this post


Link to post
Share on other sites
Actually, there is a way to do "direct" drawing with OpenGL. You use a library called SDL(www.libsdl.org). Basically you can create an OpenGL canvas with it, then use SDL''s 2d graphics. I hear SDL''s API is DirectDrawish. I would not kow for sure cause I never used DirectDraw.

Share this post


Link to post
Share on other sites
Using SDL is pretty much the same as using DirectDraw, or Windows'' GDI. It has the benefit of being fairly portable, but it isn''t actually part of OpenGL.

OpenGL itself isn''t good at 2D graphics, just like Direct3D isn''t good at 2D graphics. Actually, GL can do 2D vector graphics okay, but it''s not so hot at 2D raster graphics.

Uuuuuulrika-ka-ka-ka-ka-ka

Share this post


Link to post
Share on other sites