Initial Results
1,775
2
Advertisement
This is what I have so far. Visually it's horrific but I don't see any need to find/make quality textures at this point. I would waste time doing that. In my opinion the graphics shouldn't be better than the gameplay and currently the gameplay is at zero.

The brown tiles are walls by the way, not mud pits or waffles. The "player" (that gray blob) can be moved around using the WSAD keys (to be clear there is no animation and the player image simply moves from one tile to the other instantly). The camera can pan using the cursor keys. The player cannot walk through the walls. That's it.
I should make it clear that I started this BEFORE the first journal entry so don't imagine I've done all this in 24 hours from scratch (although an expert would no doubt be able to do just that and more). I spent an age figuring out the basics of the high level shader language (hlsl) thingy and how to draw transparent overlays, how to tie that in with effects files in XNA and how to map textures.
World Representation
Here's the bare bones of the internal structure of the game world:
I went down the obvious route of the map internally being represented as a 2D array. I have a Tile class to represent a tile. Ultimately for extensibility I think each tile type should subclass the Tile class, but for now I use a TileType enum.
Rendering Implementation
The map looks 2D but is rendered in 3D. The world plane sits at Y=0 and the camera looks down from Y=10. I wanted to use 3D and shaders rather than 2D with blitting and sprites because part of the point of this project for me is to learn 3D and shaders in XNA.
I started off with a default XNA windows application project that draws a shaded triangle and corrupted it beyond recognition. The code in the Game class is now really a mess as it's full of the remnants of trial and error. It's simplistic to say the least. The Draw() method just pulls the tiles from the map one by one through the map::GetTile(x,y) method and renders them. Repeated calls to:
I know indexes and suchlike are probably the way to go performance-wise but I am going to stick with this for a while. I want to largely avoid spending time on optimizations for now, although I did optimize the draw code a little so that only tiles that are visible (or near enough) are obtained and rendered, not the whole map.
I am mulling over the idea of eventually having a massive, potentially infinite, game world that is loaded and saved to disk as needed.
Camera
The camera position is a Vector3 with the Y position is fixed (although later it could be controlled to support zooming) and the X and Z components controlled by the cursor keys. The X and Z camera values determine the middle tile on the screen (the camera is directly above it). I calculate the center tile during the Draw() method by:
And then I basically draw a load of tiles around that center tile. Enough that it fills up the screen.
Here's a diagram of the map and camera setup:

What this diagram tells us is that the artwork for this game is going to be terrible. It also shows how the camera sits above the map looking down and only the fraction (in red) of the map in the current view is rendered. As the camera moves across the map the red area will change. Because the map is fixed and the camera moves you can scroll fractions of a unit.
Entities, the Player and movement
My favorite part of this game design process is writing the gameplay classes. The rendering stuff I find is tiresome work in contrast. I don't know if other people find the opposite. I remember looking at the quake2 source code and seeing Carmacks class structure for everything that got me interested in how nice game engines can be. It's almost pure textbook OO and I don't get to do that or see that in many other applications.
I have an Entity class that will be a base class for all monsters, creatures, locatable monsters, creatures and probably items on the map. I think that's pretty standard for a lot of games. My entity class currently looks like this:
The base Entity::CanTravelThrough method implementation simply returns true if the tile has a type of TileType.StoneFloor and false if the tile has a type of TileType.Wall. This isn't the way I want to do it as it requires each entity type to list all the tile types it can travel through, when really you could generalize and say most entities cannot walk through solid tile types. I'll re-organize this eventually.
I have a Player class that is derived from Entity (it doesn't implement anything new) and the WASD keys are bound like so:
I render the player after the tiles are drawn using a shader technique that has a pixel shader that sets alpha to 0 for "pink/purplish" pixels, making them transparent. So all the entity images in this game will use pink to denote transparency.
I should probably take a look at some existing rouge-like code to get a perspective on how it's done but I am lazy. I'll get round to that eventually.
The next entry will be about implementing Line of Sight so that only the tiles that are visible to the player are drawn.

The brown tiles are walls by the way, not mud pits or waffles. The "player" (that gray blob) can be moved around using the WSAD keys (to be clear there is no animation and the player image simply moves from one tile to the other instantly). The camera can pan using the cursor keys. The player cannot walk through the walls. That's it.
I should make it clear that I started this BEFORE the first journal entry so don't imagine I've done all this in 24 hours from scratch (although an expert would no doubt be able to do just that and more). I spent an age figuring out the basics of the high level shader language (hlsl) thingy and how to draw transparent overlays, how to tie that in with effects files in XNA and how to map textures.
World Representation
Here's the bare bones of the internal structure of the game world:
public class Map
{
private Tile[,] _tiles;
public Map(int width, int height);
public Tile GetTile(int x, int z);
public int Width;
public int Height;
}
public class Tile
{
public Tile(Map map, int x, int z);
public TileType Type;
}
public enum TileType
{
Wall,
StoneFloor
}
I went down the obvious route of the map internally being represented as a 2D array. I have a Tile class to represent a tile. Ultimately for extensibility I think each tile type should subclass the Tile class, but for now I use a TileType enum.
Rendering Implementation
The map looks 2D but is rendered in 3D. The world plane sits at Y=0 and the camera looks down from Y=10. I wanted to use 3D and shaders rather than 2D with blitting and sprites because part of the point of this project for me is to learn 3D and shaders in XNA.
I started off with a default XNA windows application project that draws a shaded triangle and corrupted it beyond recognition. The code in the Game class is now really a mess as it's full of the remnants of trial and error. It's simplistic to say the least. The Draw() method just pulls the tiles from the map one by one through the map::GetTile(x,y) method and renders them. Repeated calls to:
GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, vertices, 0, 2, VertexPositionTexture.VertexDeclaration);I know indexes and suchlike are probably the way to go performance-wise but I am going to stick with this for a while. I want to largely avoid spending time on optimizations for now, although I did optimize the draw code a little so that only tiles that are visible (or near enough) are obtained and rendered, not the whole map.
I am mulling over the idea of eventually having a massive, potentially infinite, game world that is loaded and saved to disk as needed.
Camera
The camera position is a Vector3 with the Y position is fixed (although later it could be controlled to support zooming) and the X and Z components controlled by the cursor keys. The X and Z camera values determine the middle tile on the screen (the camera is directly above it). I calculate the center tile during the Draw() method by:
int centerTileX = (int)Math.Floor(cameraPos.X);
int centerTileZ = (int)Math.Floor(cameraPos.Z);And then I basically draw a load of tiles around that center tile. Enough that it fills up the screen.
Here's a diagram of the map and camera setup:

What this diagram tells us is that the artwork for this game is going to be terrible. It also shows how the camera sits above the map looking down and only the fraction (in red) of the map in the current view is rendered. As the camera moves across the map the red area will change. Because the map is fixed and the camera moves you can scroll fractions of a unit.
Entities, the Player and movement
My favorite part of this game design process is writing the gameplay classes. The rendering stuff I find is tiresome work in contrast. I don't know if other people find the opposite. I remember looking at the quake2 source code and seeing Carmacks class structure for everything that got me interested in how nice game engines can be. It's almost pure textbook OO and I don't get to do that or see that in many other applications.
I have an Entity class that will be a base class for all monsters, creatures, locatable monsters, creatures and probably items on the map. I think that's pretty standard for a lot of games. My entity class currently looks like this:
public class Entity
{
public Entity(Map map, int xPos, int zPos);
public int X;
public int Y;
public bool Move(CompassDirection direction);
//returns true if the entity can travel through the specified tile, false if it cannot
public bool CanTravelThrough(Tile tile);
}
public enum CompassDirection
{
North,
East,
South,
West
}
The base Entity::CanTravelThrough method implementation simply returns true if the tile has a type of TileType.StoneFloor and false if the tile has a type of TileType.Wall. This isn't the way I want to do it as it requires each entity type to list all the tile types it can travel through, when really you could generalize and say most entities cannot walk through solid tile types. I'll re-organize this eventually.
I have a Player class that is derived from Entity (it doesn't implement anything new) and the WASD keys are bound like so:
void KeyPressCallback(Keys key)
{
switch (key)
{
case Keys.W:
player.Move(CompassDirection.North);
break;
case Keys.A:
player.Move(CompassDirection.West);
break;
case Keys.S:
player.Move(CompassDirection.South);
break;
case Keys.D:
player.Move(CompassDirection.East);
break;
}
}I render the player after the tiles are drawn using a shader technique that has a pixel shader that sets alpha to 0 for "pink/purplish" pixels, making them transparent. So all the entity images in this game will use pink to denote transparency.
I should probably take a look at some existing rouge-like code to get a perspective on how it's done but I am lazy. I'll get round to that eventually.
The next entry will be about implementing Line of Sight so that only the tiles that are visible to the player are drawn.
Advertisement
Advertisement
Advertisement
Discussion