So I've been working on my game and I have the most rudimentary tile system ever yet I haven't see one on here I figured I'd post the beginnings of it. If anyone has any suggested improvements feel free to make them and I'll gladly update the code. Hopefully this helps some newbie get a grip on how things run.
Side note: I realize I'm including cpp, feel free to clean that up for your own project or you can wait until I'm done and by then it'll be clean.
Main.cpp-
#include "Enum.h"
#include "Matrix.cpp"
#include "player.cpp"
#include "sector.cpp"
// Dark GDK - The Game Creators - www.thegamecreators.com
// the wizard has created a very simple project that uses Dark GDK
// it contains the basic code for a GDK application
// whenever using Dark GDK you must ensure you include the header file
#include "DarkGDK.h"
// the main entry point for the application is this function
void DarkGDK ( void )
{
// turn on sync rate and set maximum rate to 60 fps
dbSyncOn ( );
dbSyncRate ( 60 );
dbSetImageColorKey(255,0,255);
dbSetDisplayMode(800,600,32);
dbSetWindowSize(800,600);
sector this_sector("c:\\Space_Files\\sector_1.txt");
player main_char("c:\\Space_Files\\star_andromeda_sprite.png",0,0,3,3,3,ID_PLAYER,ID_PLAYER);
// our main loop
while ( LoopGDK ( ) )
{
dbCLS();
this_sector.draw_sector();
if(!this_sector.check_collision(main_char.get_x_direction(),main_char.get_y_direction()))
{
main_char.update();
}
else
{
main_char.unupdate();
}
// update the screen
dbSync ( );
}
// return back to windows
return;
}
player.cpp-
#include "DarkGDK.h"
#include "Enum.h"
class player
{
private:
int player_x,player_y,player_frame,sprite_id,image_id,x_direction,y_direction;
void draw()
{
dbSprite(this->sprite_id,this->player_x,player_y,this->image_id);
}
public:
player(char player_image[],int x_pos,int y_pos,int rows,int columns,int starting_frame,int image_id,int sprite_id)
{
this->sprite_id=sprite_id;
this->image_id=image_id;
dbCreateAnimatedSprite(this->sprite_id,player_image,rows,columns,this->image_id);
this->player_x=x_pos;
this->player_y=y_pos;
this->x_direction=0;
this->y_direction=0;
this->player_frame=starting_frame;
}
int get_x_direction()
{
return this->x_direction;
}
int get_y_direction()
{
return this->y_direction;
}
void set_x_coord(int new_coord)
{
this->player_x=new_coord;
}
void set_y_coord(int new_coord)
{
this->player_y=new_coord;
}
void update()
{
if(dbKeyState(KEY_S) && dbKeyState(KEY_D))
{
this->player_y++;
this->player_x++;
this->x_direction=this->player_x+1;
this->y_direction=this->player_y+1;
this->player_frame=4;
}
else if(dbKeyState(KEY_S) && dbKeyState(KEY_A))
{
this->player_y++;
this->player_x--;
this->x_direction=this->player_x-1;
this->y_direction=this->player_y+1;
this->player_frame=6;
}
else if(dbKeyState(KEY_W) && dbKeyState(KEY_D))
{
this->player_y--;
this->player_x++;
this->x_direction=this->player_x+1;
this->y_direction=this->player_y-1;
this->player_frame=2;
}
else if(dbKeyState(KEY_W) && dbKeyState(KEY_A))
{
this->player_y--;
this->player_x--;
this->x_direction=this->player_x-1;
this->y_direction=this->player_y-1;
this->player_frame=8;
}
else if(dbKeyState(KEY_S))
{
this->player_y++;
this->y_direction=this->player_y+1;
this->player_frame=5;
}
else if(dbKeyState(KEY_D))
{
this->player_x++;
this->x_direction=this->player_x+1;
this->player_frame=3;
}
else if(dbKeyState(KEY_W))
{
this->player_y--;
this->y_direction=this->player_y-1;
this->player_frame=1;
}
else if(dbKeyState(KEY_A))
{
this->player_x--;
this->x_direction=this->player_x-1;
this->player_frame=7;
}
dbSetSpriteFrame(this->sprite_id,this->player_frame);
this->draw();
}
void unupdate()
{
if(dbKeyState(KEY_S) && dbKeyState(KEY_D))
{
this->player_y--;
this->player_x--;
this->x_direction=this->player_x+1;
this->y_direction=this->player_y+1;
this->player_frame=4;
}
else if(dbKeyState(KEY_S) && dbKeyState(KEY_A))
{
this->player_y--;
this->player_x++;
this->x_direction=this->player_x-1;
this->y_direction=this->player_y+1;
this->player_frame=6;
}
else if(dbKeyState(KEY_W) && dbKeyState(KEY_D))
{
this->player_y++;
this->player_x--;
this->x_direction=this->player_x+1;
this->y_direction=this->player_y-1;
this->player_frame=2;
}
else if(dbKeyState(KEY_W) && dbKeyState(KEY_A))
{
this->player_y++;
this->player_x++;
this->x_direction=this->player_x-1;
this->y_direction=this->player_y-1;
this->player_frame=8;
}
else if(dbKeyState(KEY_S))
{
this->player_y--;
this->y_direction=this->player_y+1;
this->player_frame=5;
}
else if(dbKeyState(KEY_D))
{
this->player_x--;
this->x_direction=this->player_x+1;
this->player_frame=3;
}
else if(dbKeyState(KEY_W))
{
this->player_y++;
this->y_direction=this->player_y-1;
this->player_frame=1;
}
else if(dbKeyState(KEY_A))
{
this->player_x++;
this->x_direction=this->player_x-1;
this->player_frame=7;
}
dbSetSpriteFrame(this->sprite_id,this->player_frame);
this->draw();
}
};
Sector.cpp is where all the fun happens. Below this I'll be attaching a sample sector file.
Sector.cpp-
#include "DarkGDK.h"
#include "Matrix.cpp"
#include "Enum.h"
class sector : public Matrix<int>
{
private:
/*
* Base Layer: A numerical index into the tiles in the map’s texture, specifying the first sprite drawn in the space. Typically, this is the ground.
* Fringe Layer: A numerical index into the tiles in the map’s texture, specifying the second sprite drawn in the space. Typically, these sprites are trees, buildings, fences – anything that is at ground level, but might be matched up with various ground tiles. The separation between the base and fringe layers means you can have one tree sprite (fringe layer) that can sit on top of any kind of ground sprite (base layer).
* Object Layer: A numerical index into the tiles in the map’s texture, specifying the sprite drawn in the space after all objects have been drawn. These sprites always appear on top of all other objects in the same tile – characters, chests, and so on. These include treetops and signs.
* Collision Layer: An integer of value 0 (false) or nonzero (true), used as a Boolean value representing whether that tile can be entered by the player.
*/
Matrix *base_layer,*fringe_layer,*object_layer,*collision_layer;
int tile_width,tile_height,width,height;
char *filename;
public:
sector(char *filename)
{
this->filename=filename;
char szLine[40];
char *pstring;
bool process_width=false,process_height=false,process_twidth=false,
process_theight=false,process_baset=false,process_fringet=false,
process_objectt=false,process_base=false,process_fringe=false,
process_object=false,process_collision=false;
if( dbFileExist( this->filename) )
{
dbPrint( "file exists\n" );
dbOpenToRead( 1, this->filename);
if( dbFileOpen( 1 ) )
{
dbPrint( "opened the file\n" );
int x=0,y=0;
while( !dbFileEnd( 1 ) )
{
//sprintf( szLine, "%c", dbReadByte( 1 ) );
pstring = dbReadString( 1, szLine );
if(strcmp(pstring,"<WIDTH>")==0)
{
process_width=true;
process_height=false;process_twidth=false;
process_theight=false;process_baset=false;process_fringet=false;
process_objectt=false;process_base=false;process_fringe=false;
process_object=false;process_collision=false;
}
else if(strcmp(pstring,"<HEIGHT>")==0)
{
process_width=false;
process_height=true;process_twidth=false;
process_theight=false;process_baset=false;process_fringet=false;
process_objectt=false;process_base=false;process_fringe=false;
process_object=false;process_collision=false;
}
else if(strcmp(pstring,"<TILE_WIDTH>")==0)
{
process_width=false;
process_height=false;process_twidth=true;
process_theight=false;process_baset=false;process_fringet=false;
process_objectt=false;process_base=false;process_fringe=false;
process_object=false;process_collision=false;
}
else if(strcmp(pstring,"<TILE_HEIGHT>")==0)
{
process_width=false;
process_height=false;process_twidth=false;
process_theight=true;process_baset=false;process_fringet=false;
process_objectt=false;process_base=false;process_fringe=false;
process_object=false;process_collision=false;
}
else if(strcmp(pstring,"<BASE_TEXTURES>")==0)
{
process_width=false;
process_height=false;process_twidth=false;
process_theight=false;process_baset=true;process_fringet=false;
process_objectt=false;process_base=false;process_fringe=false;
process_object=false;process_collision=false;
}
else if(strcmp(pstring,"<FRINGE_TEXTURES>")==0)
{
process_width=false;
process_height=false;process_twidth=false;
process_theight=false;process_baset=false;process_fringet=true;
process_objectt=false;process_base=false;process_fringe=false;
process_object=false;process_collision=false;
}
else if(strcmp(pstring,"<OBJECT_TEXTURES>")==0)
{
process_width=false;
process_height=false;process_twidth=false;
process_theight=false;process_baset=false;process_fringet=false;
process_objectt=true;process_base=false;process_fringe=false;
process_object=false;process_collision=false;
}
else if(strcmp(pstring,"<BASE>")==0)
{
process_width=false;
process_height=false;process_twidth=false;
process_theight=false;process_baset=false;process_fringet=false;
process_objectt=false;process_base=true;process_fringe=false;
process_object=false;process_collision=false;
}
else if(strcmp(pstring,"<FRINGE>")==0)
{
process_width=false;
process_height=false;process_twidth=false;
process_theight=false;process_baset=false;process_fringet=false;
process_objectt=false;process_base=false;process_fringe=true;
process_object=false;process_collision=false;
}
else if(strcmp(pstring,"<OBJECT>")==0)
{
process_width=false;
process_height=false;process_twidth=false;
process_theight=false;process_baset=false;process_fringet=false;
process_objectt=false;process_base=false;process_fringe=false;
process_object=true;process_collision=false;
}
else if(strcmp(pstring,"<COLLISION>")==0)
{
process_width=false;
process_height=false;process_twidth=false;
process_theight=false;process_baset=false;process_fringet=false;
process_objectt=false;process_base=false;process_fringe=false;
process_object=false;process_collision=true;
}
if(process_width)
{
if(strcmp(pstring,"<WIDTH>")!=0)
{
this->width=atoi(pstring);
process_width=false;
}
}
else if(process_height)
{
if(strcmp(pstring,"<HEIGHT>")!=0)
{
this->height=atoi(pstring);
process_height=false;
}
}
else if(process_twidth)
{
if(strcmp(pstring,"<TILE_WIDTH>")!=0)
{
this->tile_width=atoi(pstring);
process_twidth=false;
}
}
else if(process_theight)
{
if(strcmp(pstring,"<TILE_HEIGHT>")!=0)
{
this->tile_height=atoi(pstring);
process_theight=false;
}
}
else if(process_baset)
{
if(strcmp(pstring,"<BASE_TEXTURES>")!=0 && strcmp(pstring,"<FRINGE_TEXTURES>")!=0 && strcmp(pstring,"")!=0)
{
char * result;
char *image_name;
int id,i=0;
result=strtok(pstring," ");
while(result!=NULL)
{
if(i==0)
{
image_name=result;
}
else if(i==1)
{
id=atoi(result);
break;
}
i++;
result=strtok(NULL," ");
}
dbLoadImage(image_name,id,1);
}
}
else if(process_fringet)
{
if(strcmp(pstring,"<FRINGE_TEXTURES>")!=0 && strcmp(pstring,"<OBJECT_TEXTURES>")!=0 && strcmp(pstring,"")!=0)
{
char * result;
char *image_name;
int id,i=0;
result=strtok(pstring," ");
while(result!=NULL)
{
if(i==0)
{
image_name=result;
}
else if(i==1)
{
id=atoi(result);
break;
}
i++;
result=strtok(NULL," ");
}
dbLoadImage(image_name,id,1);
}
}
else if(process_objectt)
{
if(strcmp(pstring,"<OBJECT_TEXTURES>")!=0 && strcmp(pstring,"<BASE>")!=0 && strcmp(pstring,"")!=0)
{
char * result;
char *image_name;
int id,i=0;
result=strtok(pstring," ");
while(result!=NULL)
{
if(i==0)
{
image_name=result;
}
else if(i==1)
{
id=atoi(result);
break;
}
i++;
result=strtok(NULL," ");
}
dbLoadImage(image_name,id,1);
}
}
else if(process_base)
{
if(strcmp(pstring,"<BASE>")==0)
{
this->base_layer=new Matrix(this->height,this->width);
}
if(strcmp(pstring,"<BASE>")!=0 && y<(this->height))
{
int value;
char * result;
result=strtok(pstring," ");
while(result!=NULL)
{
value=atoi(result);
this->base_layer->Set(y,x,value);
x++;
if(x>(this->width-1))
{
x=0;
break;
}
result=strtok(NULL," ");
}
y++;
}
else
{
y=0;
}
}
else if(process_fringe)
{
if(strcmp(pstring,"<FRINGE>")==0)
{
this->fringe_layer=new Matrix(this->height,this->width);
}
if(strcmp(pstring,"<FRING>")!=0 && y<(this->height))
{
int value;
char * result;
result=strtok(pstring," ");
while(result!=NULL)
{
value=atoi(result);
this->fringe_layer->Set(y,x,value);
x++;
if(x>(this->width-1))
{
x=0;
break;
}
result=strtok(NULL," ");
}
y++;
}
else
{
y=0;
}
}
else if(process_object)
{
if(strcmp(pstring,"<OBJECT>")==0)
{
this->object_layer=new Matrix(this->height,this->width);
}
if(strcmp(pstring,"<OBJECT>")!=0 && y<(this->height))
{
int value;
char * result;
result=strtok(pstring," ");
while(result!=NULL)
{
value=atoi(result);
this->object_layer->Set(y,x,value);
x++;
if(x>(this->width-1))
{
x=0;
break;
}
result=strtok(NULL," ");
}
y++;
}
else
{
y=0;
}
}
else if(process_collision)
{
if(strcmp(pstring,"<COLLISION>")==0)
{
this->collision_layer=new Matrix(this->height,this->width);
}
if(strcmp(pstring,"<COLLISION>")!=0 && y<(this->height))
{
int value;
char * result;
result=strtok(pstring," ");
while(result!=NULL)
{
value=atoi(result);
this->collision_layer->Set(y,x,value);
x++;
if(x>(this->width-1))
{
x=0;
break;
}
result=strtok(NULL," ");
}
y++;
}
else
{
y=0;
}
}
}
dbCloseFile( 1 );
}
}
}
bool check_collision(int x_coord,int y_coord)
{
int x_space=this->tile_width;;
int y_space=this->tile_height;
for(int y=0;y<this->height;y++)
{
for(int x=0;x<this->width;x++)
{
int collision=collision_layer->Get(y,x);
if(collision!=0)
{
if(x_coord>=(x_space*x) && x_coord<=(x_space*x+this->tile_width))
{
if(y_coord>=(y_space*y) && y_coord<=(y_space*y+this->tile_height))
{
return true;
}
}
}
}
}
return false;
}
void draw_sector()
{
int x_space=this->tile_width;;
int y_space=this->tile_height;
int image_id;
for(int y=0;y<this->height;y++)
{
for(int x=0;x<this->width;x++)
{
image_id=base_layer->Get(y,x);
if(image_id!=0)
{
dbPasteImage(image_id,(x_space*x),(y_space*y));
}
}
}
for(int y=0;y<this->height;y++)
{
for(int x=0;x<this->width;x++)
{
image_id=fringe_layer->Get(y,x);
if(fringe_layer->Get(y,x)!=0)
{
dbPasteImage(image_id,(x_space*x),(y_space*y));
}
}
}
for(int y=0;y<this->height;y++)
{
for(int x=0;x<this->width;x++)
{
image_id=object_layer->Get(y,x);
if(image_id!=0)
{
dbPasteImage(image_id,(x_space*x),(y_space*y));
}
}
}
}
};
Enum.h-
#ifndef ENUM_INCLUDE
#define ENUM_INCLUDE
enum KEYBOARD
{
KEY_NONE,
KEY_ESC,
KEY_ONE,
KEY_TWO,
KEY_THREE,
KEY_FOUR,
KEY_FIVE,
KEY_SIX,
KEY_SEVEN,
KEY_EIGHT,
KEY_NINE,
KEY_ZERO,
KEY_DASH,
KEY_EQUAL,
KEY_BACK_SPACE,
KEY_TAB,
KEY_Q,
KEY_W,
KEY_E,
KEY_R,
KEY_T,
KEY_Y,
KEY_U,
KEY_I,
KEY_O,
KEY_P,
KEY_LEFT_BRACKET,
KEY_RIGHT_BRACKET,
KEY_ENTER,
KEY_LEFT_CTRL,
KEY_A,
KEY_S,
KEY_D,
KEY_F,
KEY_G,
KEY_H,
KEY_J,
KEY_K,
KEY_L,
KEY_SEMI_COLON,
KEY_APOSTROPHE,
KEY_TILDA,
KEY_LEFT_SHIFT,
KEY_BACK_SLASH,
KEY_Z,
KEY_X,
KEY_C,
KEY_V,
KEY_B,
KEY_N,
KEY_M,
KEY_COMMA,
KEY_PERIOD,
KEY_FORWARD_SLASH,
KEY_RIGHT_SHIFT,
KEY_PRINT_SCREEN,KEY_ALT,KEY_SPACE,KEY_CAPS,KEY_F1,KEY_F2,KEY_F3,KEY_F4,
KEY_F5,KEY_F6,KEY_F7,KEY_F8,KEY_F9,KEY_F10,KEY_NUM_LOCK,KEY_SCROLL,KEY_NUM_7,KEY_NUM_8,KEY_NUM_9,
KEY_NUM_DASH,KEY_NUM_4,KEY_NUM_5,KEY_NUM_6,KEY_NUM_PLUS,KEY_NUM_1,KEY_NUM_2,KEY_NUM_3,
KEY_NUM_0,KEY_NUM_DEL,KEY_EMPTY_1,KEY_EMPTY_2,KEY_EMPTY_3,KEY_F11,KEY_F12,KEY_EMPTY_89,
KEY_EMPTY_90,KEY_EMPTY_91,KEY_EMPTY_92,KEY_EMPTY_93,KEY_EMPTY_94,KEY_EMPTY_95,
KEY_EMPTY_96,KEY_EMPTY_97,KEY_EMPTY_98,KEY_EMPTY_99,KEY_EMPTY_100,KEY_EMPTY_101,
KEY_EMPTY_102,KEY_HOME,KEY_UP,KEY_PAGE_UP,KEY_EMPTY_106,KEY_LEFT,KEY_EMPTY_108,KEY_RIGHT,
KEY_EMPTY_110,KEY_END,KEY_DOWN,KEY_PAGE_DOWN,KEY_INSERT,KEY_DELETE
};
enum DIFFICULTY{EASY,MEDIUM,HARD};
enum GRAPHIC_ID{ID_NONE,ID_PLAYER,ID_BACKGROUND};
enum GAME_STATE{WAITING,GENERATING,PLAYING,GAME_OVER,VICTORY};
enum MOUSE{NO_CLICK,LEFT_CLICK,RIGHT_CLICK};
#endif
Matrix.cpp-
#ifndef MATRIX_INCLUDE
#define MATRIX_INCLUDE
/**
* 2D Matrix with non-contiguous 2D storage internally.
*/
template <typename TValue>
class Matrix
{
public:
/**
* the value type.
*/
typedef TValue ValueType;
/**
* the value type.
*/
typedef Matrix<ValueType> Self;
/**
* the pointer type.
*/
typedef ValueType* PointerType;
/**
* the storage type.
*/
typedef ValueType** StorageType;
/**
* the size type.
*/
typedef int SizeType;
/**
* contructor.
*/
Matrix( SizeType nrow, SizeType ncol )
: m_nrow( nrow )
, m_ncol( ncol )
, m_data( Create( nrow, ncol ) )
{
}
Matrix()
{
}
/**
* destructor.
*/
virtual ~Matrix()
{
/*for ( int row = 0; row < Rows(); ++row )
{
delete[] m_data[ row ];
}*/
/*delete[] m_data;*/
}
/**
* the i-th row;
* this allows you to write matrix[y][x] to access an element.
*/
PointerType operator[]( int i )
{
return m_data[ i ];
}
/**
* alias for Get(y,x) (const);
* this allows you to write int x = matrix(y,x) to access an element.
*/
ValueType operator()( SizeType y, SizeType x ) const
{
return Get( y, x );
}
/**
* alias for Get(y,x) (non-const);
* this allows you to write matrix(y,x) = x; to access an element.
*/
ValueType& operator()( SizeType y, SizeType x )
{
return Get( y, x );
}
/**
* the number of rows.
*/
SizeType Rows() const
{
return m_nrow;
}
/**
* the number of columns.
*/
SizeType Columns() const
{
return m_ncol;
}
/**
* the value of the given location (const).
*/
ValueType Get( SizeType y, SizeType x ) const
{
return m_data[ y ][ x ];
}
/**
* the value of the given location (non-const).
*/
ValueType& Get( SizeType y, SizeType x )
{
return m_data[ y ][ x ];
}
/**
* set the value of the given location.
*/
void Set( SizeType y, SizeType x, const ValueType& value )
{
m_data[ y ][ x ] = value;
}
/**
* the internal representation.
*/
friend StorageType GetImpl( Self& matrix )
{
return matrix.m_data;
}
protected:
/**
* convenience function to create the internal representation inside the
* member initialization list (MIL).
*/
StorageType Create( SizeType nrow, SizeType ncol )
{
StorageType m = new PointerType[ nrow ];
for ( int row = 0; row < nrow; ++row )
{
m[ row ] = new ValueType[ ncol ];
}
return m;
}
private:
/**
* the number of columns.
*/
SizeType m_ncol;
/**
* the number of rows.
*/
SizeType m_nrow;
/**
* the internal representation.
*/
StorageType m_data;
private:
/**
* prevent asignement.
*/
Self& operator= ( const Self& );
/**
* prevent copy-asignement.
*/
Matrix( const Self& );
};
#endif
sector_1.txt-
<WIDTH>
11
<HEIGHT>
10
<TILE_WIDTH>
75
<TILE_HEIGHT>
75
<BASE_TEXTURES>
c:\\Space_Files\\star_background.png 2
c:\\Space_Files\\star_background.png 3
<FRINGE_TEXTURES>
<OBJECT_TEXTURES>
<BASE>
2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2
<FRINGE>
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
<OBJECT>
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
<COLLISION>
0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
Just remember spacing really really matters in the text file. Let me know if you have any questions or suggestions.
Charles Thompson