어느덧 2장까지 왔다..물론 책은 현재 3장 이상을 보고 있으나..다시 볼겸...블로그에 작성중에 있다.
이번부터 사용할 라이브러리 클래스는 다음과 같다고 설명한다.
책에서는 이 중 세가지 함수는 그냥 사용하면 되고..한가지는 직접 만들어야한다고 설명된다.
화면을 구성하는 픽셀 배열을 가져오는 함수라고 설명되어있다. 예를 들어 5 * 4픽셀 배열이라면 1차원배열이므로..(y * 폭 + x)로 나타낼 수 있다.
이 배열은 unsigned 배열이며 하나가 한 픽셀에 해당된다고 한다.
그리고 메인루프 한번에 해당하는 함수란다.
또한 라이브러리 전체가 GameLib 이름공간에 포함되어 있기 때문에 namespace GameLib 블록안에 넣어야하며 헤더로 include "GameLib/FrameWork.h" 를 포함하여야한다.
그러면 우선 픽셀배열을 가져와야하니.. unsigned* vram=videoMemory(); 를 해서 얻고
vram[200 * width() + 100]=0xff0000; 이라고 해야한다.
#include <iostream>
#include <fstream>
using namespace std;
⁄⁄듫릶긵깓긣?귽긵
void readFile( char** buffer, int* size, const char* filename );
⁄⁄볫렅뙰봹쀱긏깋긚
⁄⁄긡깛긵깒?긣궸궶궣귒궼궇귡궬귣궎궔갎궶궚귢궽딈멳궬궚궳귖뺈떗궢궲궓궞궎갃
⁄⁄궞궻긏깋긚먬뙻궻뭷궳궼T궴궋궎긏깋긚궕궇귡궔궻귝궎궸댌귦귢갂
⁄⁄궞귢귩럊궎렄궸궼T궻궴궞귣궸int궴궔bool궴궔볺귢궲럊궎갃
template< class T > class Array2D{
public:
Array2D() : mArray( 0 ){}
~Array2D(){
delete[] mArray;
mArray = 0; ⁄⁄?귽깛?궸0귩볺귢귡궻궼긏긜궸궢귝궎갃
}
void setSize( int size0, int size1 ){
mSize0 = size0;
mSize1 = size1;
mArray = new T[ size0 * size1 ];
}
T& operator()( int index0, int index1 ){
return mArray[ index1 * mSize0 + index0 ];
}
const T& operator()( int index0, int index1 ) const {
return mArray[ index1 * mSize0 + index0 ];
}
private:
T* mArray;
int mSize0;
int mSize1;
};
⁄⁄륉뫴긏깋긚
class State{
public:
State( const char* stageData, int size );
void update( char input );
void draw() const;
bool hasCleared() const;
private:
enum Object{
OBJ_SPACE,
OBJ_WALL,
OBJ_BLOCK,
OBJ_MAN,
OBJ_UNKNOWN,
OBJ_GOAL_FLAG = ( 1 << 7 ), ⁄⁄긕?깑긲깋긐
};
void setSize( const char* stageData, int size );
int mWidth;
int mHeight;
Array2D< unsigned char > mObjects; ⁄⁄긮긞긣뎶럁궥귡궻궳unsigned char갃궞궞귏궳궚궭귞궶궘궲귖궋궋궕갃
};
int main( int argc, char** argv ){
const char* filename = "stageData.txt";
if ( argc >= 2 ){
filename = argv[ 1 ];
}
char* stageData;
int fileSize;
readFile( &stageData, &fileSize, filename );
if ( !stageData ){
cout << "stage file could not be read." << endl;
return 1;
}
State* state = new State( stageData, fileSize );
⁄⁄긽귽깛깑?긵
while ( true ){
⁄⁄귏궦?됪
state->draw();
⁄⁄긏깏귺?긃긞긏
if ( state->hasCleared() ){
break; ⁄⁄긏깏귺?긃긞긏
}
⁄⁄볺쀍롦벦
cout << "a:left s:right w:up z:down. command?" << endl; ⁄⁄?띿먣뼻
char input;
cin >> input;
⁄⁄뛛륷
state->update( input );
}
⁄⁄뢪궋궻긽긞긜?긙
cout << "Congratulation's! you won." << endl;
⁄⁄뚣럑뼎
delete[] stageData;
stageData = 0;
⁄⁄뼰뙽깑?긵(ctrl-C댥둖궳룦롨궸뢎귦귞궶궋궫귕궻귖궻)
while ( true ){
;
}
return 0;
}
⁄⁄---------------------댥돷듫릶믦?------------------------------------------
void readFile( char** buffer, int* size, const char* filename ){
ifstream in( filename );
if ( !in ){
*buffer = 0;
*size = 0;
}else{
in.seekg( 0, ifstream::end );
*size = static_cast< int >( in.tellg() );
in.seekg( 0, ifstream::beg );
*buffer = new char[ *size ];
in.read( *buffer, *size );
}
}
State::State( const char* stageData, int size ){
⁄⁄긖귽긛뫇믦
setSize( stageData, size );
⁄⁄봹쀱둴뺎
mObjects.setSize( mWidth, mHeight );
⁄⁄룊딖뭠궳뻹귕궴궘
for ( int y = 0; y < mHeight; ++y ){
for ( int x = 0; x < mWidth; ++x ){
mObjects( x, y ) = OBJ_WALL; ⁄⁄궇귏궯궫븫빁궼빮
}
}
int x = 0;
int y = 0;
for ( int i = 0; i < size; ++i ){
unsigned char t;
switch ( stageData[ i ] ){
case '#': t = OBJ_WALL; break;
case ' ': t = OBJ_SPACE; break;
case 'o': t = OBJ_BLOCK; break;
case 'O': t = OBJ_BLOCK | OBJ_GOAL_FLAG; break;
case '.': t = OBJ_SPACE | OBJ_GOAL_FLAG; break;
case 'p': t = OBJ_MAN; break;
case 'P': t = OBJ_MAN | OBJ_GOAL_FLAG; break;
case '\n': x = 0; ++y; t = OBJ_UNKNOWN; break; ⁄⁄둂뛱룉뿚
default: t = OBJ_UNKNOWN; break;
}
if ( t != OBJ_UNKNOWN ){ ⁄⁄뭢귞궶궋빒럻궶귞뼰럨궥귡궻궳궞궻if빒궕궇귡
mObjects( x, y ) = t; ⁄⁄룕궖뜛귒
++x;
}
}
}
void State::setSize( const char* stageData, int size ){
mWidth = mHeight = 0; ⁄⁄룊딖돸
⁄⁄뙸띪댧뭫
int x = 0;
int y = 0;
for ( int i = 0; i < size; ++i ){
switch ( stageData[ i ] ){
case '#': case ' ': case 'o': case 'O':
case '.': case 'p': case 'P':
++x;
break;
case '\n':
++y;
⁄⁄띍묈뭠뛛륷
mWidth = max( mWidth, x );
mHeight = max( mHeight, y );
x = 0;
break;
}
}
}
void State::draw() const {
for ( int y = 0; y < mHeight; ++y ){
for ( int x = 0; x < mWidth; ++x ){
switch ( mObjects( x, y ) ){
case ( OBJ_SPACE | OBJ_GOAL_FLAG ): cout << '.'; break;
case ( OBJ_WALL | OBJ_GOAL_FLAG ): cout << '#'; break;
case ( OBJ_BLOCK | OBJ_GOAL_FLAG ): cout << 'O'; break;
case ( OBJ_MAN | OBJ_GOAL_FLAG ): cout << 'P'; break;
case OBJ_SPACE: cout << ' '; break;
case OBJ_WALL: cout << '#'; break;
case OBJ_BLOCK: cout << 'o'; break;
case OBJ_MAN: cout << 'p'; break;
}
}
cout << endl;
}
}
void State::update( char input ){
⁄⁄댷벍뜼빁궸빾듂
int dx = 0;
int dy = 0;
switch ( input ){
case 'a': dx = -1; break; ⁄⁄뜺
case 's': dx = 1; break; ⁄⁄덭
case 'w': dy = -1; break; ⁄⁄뤵갃Y궼돷궕긵깋긚
case 'z': dy = 1; break; ⁄⁄돷갃
}
⁄⁄뭒궋빾릶뼹귩궰궚귡갃랷뤖귩뼰뿚귘귟럊궯궲귒궫갃const븊궖궳궇귡궞궴궸뭾댰
const int& w = mWidth;
const int& h = mHeight;
Array2D< unsigned char >& o = mObjects;
⁄⁄릐띆뷭귩뙚랊
int x, y;
x = y = -1; ⁄⁄딅뙬궶뭠
bool found = false;
for ( y = 0; y < h; ++y ){
for ( x = 0; x < w; ++x ){
if ( ( o( x, y ) & ~OBJ_GOAL_FLAG ) == OBJ_MAN ){ ⁄⁄긕?깑긲깋긐댥둖귩롦귟뢯궥궫귕궻& ~OBJ_GOAL_FLAG
found = true;
break;
}
}
if ( found ){
break;
}
}
⁄⁄댷벍
⁄⁄댷벍뚣띆뷭
int tx = x + dx;
int ty = y + dy;
⁄⁄띆뷭궻띍묈띍룷?긃긞긏갃둖귢궲궋귢궽븉떀됀
if ( tx < 0 || ty < 0 || tx >= w || ty >= h ){
return;
}
⁄⁄A.궩궻뺴뛀궕뗴뵏귏궫궼긕?깑갃릐궕댷벍갃
if ( ( o( tx, ty ) & ~OBJ_GOAL_FLAG ) == OBJ_SPACE ){
o( tx, ty ) = ( o( tx, ty ) & OBJ_GOAL_FLAG ) | OBJ_MAN; ⁄⁄긕?깑긲깋긐귩뺎뫔궥귡궫귕궸궞귪궶뽋?궶궞궴궕뷠뾴갃댥돷귖귌귍벏궣
o( x, y ) = ( o( x, y ) & OBJ_GOAL_FLAG ) | OBJ_SPACE;
⁄⁄B.궩궻뺴뛀궕뵠갃궩궻뺴뛀궻렅궻?긚궕뗴뵏귏궫궼긕?깑궳궇귢궽댷벍갃
}else if ( o( tx, ty ) == OBJ_BLOCK ){
⁄⁄2?긚먩궕붝댪볙궔?긃긞긏
int tx2 = tx + dx;
int ty2 = ty + dy;
if ( tx2 < 0 || ty2 < 0 || tx2 >= w || ty2 >= h ){ ⁄⁄돓궧궶궋
return;
}
if ( ( o( tx2, ty2 ) & ~OBJ_GOAL_FLAG ) == OBJ_SPACE ){
⁄⁄룈렅볺귢뫶궑
o( tx2, ty2 ) = ( o( tx2, ty2 ) & OBJ_GOAL_FLAG ) | OBJ_BLOCK;
o( tx, ty ) = ( o( tx, ty ) & OBJ_GOAL_FLAG ) | OBJ_MAN;
o( x, y ) = ( o( x, y ) & OBJ_GOAL_FLAG ) | OBJ_SPACE;
}
}
}
⁄⁄긳깓긞긏궻궴궞귣궻goalFlag궕덇궰궳귖false궶귞
⁄⁄귏궬긏깏귺궢궲궶궋
bool State::hasCleared() const {
for ( int y = 0; y < mHeight; ++y ){
for ( int x = 0; x < mWidth; ++x ){
if ( mObjects( x, y ) == OBJ_BLOCK ){ ⁄⁄긕?깑긲깋긐궕궶궋궫궬궻긳깓긞긏
return false;
}
}
}
return true;
}
엄청 길게 느껴지지만..생각보다 짧은 량이다. 글씨가 깨지것은 이유를 모르겠음..원래 원본 소스자체가 깨져있다는...
이것을 바탕으로 라이브러리를 포함한 점 그래픽으로 발전해보도록 하겠다.(책에서는 라이브러리 및 전체 소스를 이용하는데 제한이 없다고 한다.; ㅋ 이렇게 좋은책이..!)
다음장에 이어서..