Thiết kế các lớp đối tƣợng

Một phần của tài liệu (Trang 55 - 65)

Chƣơng 2 : PHÂN TÍCH VÀ XÂY DỰNG ĐỀ TÀI

3. Thiết kế các lớp đối tƣợng

Để bắt tay vào xây dựng game, trƣớc tiên cần tạo ra một Game Engine, đây là một số thành phần cơ bản của game engine đã xây dựng:

Lớp mơ hình – Model

Mơ hình là lớp chứa dữ liệu các đỉnh vertex, tọa độ các đỉnh, màu sắc, tex coords,… struct FACE_LINE

{

int v1; int t1; int n1; int v2; int t2; int n2; int v3; int t3; int n3; }; struct frameModel { float max_x; float max_y; float max_z; float min_x; float min_y; float min_z; }; class Model { public: GLuint vboID; int numCount; frameModel frM; Model(void); ~Model(void);

bool init(const char* fileName); };

Lớp Texture

Một lớp texture chứa dữ liệu hình ảnh cần load và vị trí của biến texture sau khi load vào bộ nhớ. Cấu trúc của hàm load dữ liệu cho lớp texture nhƣ sau:

bool Texture::init(const char* fileName, const char* tiling) {

glGenTextures(1, &texID);

glBindTexture(GL_TEXTURE_2D, texID); int imgWidth, imgHeight, imgBpp; char* fileToRead = (char*)fileName; #ifdef _ANDROID

LOGI("\nAndroid detected\n");

fileToRead[strlen(fileToRead)-1] = '\0'; #endif

char* imgData = LoadTGA(fileToRead, &imgWidth, &imgHeight, &imgBpp);

56

imgWidth, imgHeight, imgBpp);

glTexImage2D(GL_TEXTURE_2D, 0, (imgBpp==32)?GL_RGBA:GL_RGB, imgWidth, imgHeight, 0, (imgBpp==32)?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, imgData);

if (tiling == "REPEAT") { glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); } else

//if (tiling == "CLAMP")

{

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); }

// not using mipmap

/*glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);*/ // using mipmap glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); glGenerateMipmap(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); delete[] imgData; return true; } Lớp Shader

Để sử dụng Shader, ta cần tạo ra một lớp quản lý shader, lớp này làm nhiệm vụ load các shader, biên dịch và đƣa vào trong một biến program

int Shaders::Init(const char * fileVertexShader, const char *

fileFragmentShader) { vertexShader = Graphic::GetInstance()->LoadShader(GL_VERTEX_SHADER, fileVertexShader); if ( vertexShader == 0 ) return -1;

LOGI("\nVertex shader %s loaded", fileVertexShader);

fragmentShader = Graphic::GetInstance()- >LoadShader(GL_FRAGMENT_SHADER, fileFragmentShader); if ( fragmentShader == 0 ) { glDeleteShader( vertexShader ); return -2; }

57

program = Graphic::GetInstance()->LoadProgram(vertexShader, fragmentShader);

LOGI("\nProgram compiled with ID: %d", program);

return 0; }

Lớp Game Object

Sau khi đã có đầy đủ các thành phần thì chúng ta bắt đầu xây dựng lớp quản lý một đối tƣợng trong game. Một đối tƣợng bao gồm các model, texture, shader,… và các ma trận biến đổi cần thiết

class Objects { public: Vector3 Position; Vector3 Rotation; Vector3 Scale; int type; bool coll; Matrix mvpMatrix; float getDeltaTime;

float speed; // speed of object

GLuint modelID;

int modelVerNum;

GLuint textureID; GLuint shaderID;

frameModel * frM, frame; // get values max vertex and min vertex of

Model

void UpdateFrame( void ); // change values max vertex and min vertex

of Model at present time

Objects(void); ~Objects(void); virtual void init();

void init(int _model, int _texture, int _shader); virtual void Draw();

virtual void Update(float deltaTime);

//void Destroy();

};

Resource Manager – Quản lý tài nguyên game

Lớp resource manager có nhiệm vụ load các tài ngun nhƣ Mơ hình, Texture, các Shader và lƣu vào trong bộ nhớ của GPU.

class ResourcesManager: public Singleton<ResourcesManager> {

58 Model* _modelList; int _modelCount; Texture* _textureList; int _textureCount; Shaders* _shaderList; int _shaderCount; public: ResourcesManager(void); ~ResourcesManager(void);

void LoadResouces(const char* fileName);

frameModel * getFrameModel ( int id ); Model* getModel(int id);

Texture* getTexture(int id); Shaders* getShader(int id);

int loadingCount, loadingTotal; int isPlaySound;

};

Scene Manager - Lớp quản lý màn hình game

Lớp quản lý màn hình game quản lý các màn hình hiện có trong game, cơ chế load một màn hình đƣợc biểu diễn trong đoạn code sau

void SceneManager::LoadScene(const char* fileName) {

string section_name;

int _num = 0;

int _current = 0, _count = 0;

DATA_LINE* _rline = NULL;

int _curLine = 0;

char* fileToRead = (char*)fileName; #ifdef _ANDROID LOGI("\nAndroid detected\n"); fileToRead[strlen(fileToRead)-1] = '\0'; #endif ifstream f(FileSystem::GetInstance()->GetPath(fileToRead).c_str()); if (f) { while (!f.eof()) { string line; getline(f, line); if (line.substr(0, 1) == "#") {

// Begin read section

int split_pos = line.find(':');

section_name = line.substr(1, split_pos - 1);

LOGI("\n[RM] Parsing \t%s \n",

section_name.data());

59 2); LOGI("[RM] Count \t%s \n", section_num_data.data()); _current = 0; _count = 0; _num = atoi(section_num_data.data()); objectList = new Objects[_num];

objectCount = 0;

if (_rline != NULL) delete[] _rline; _rline = new DATA_LINE[8];

_curLine = 0; } else { _count++; if (_current < _num) { if (section_name == "Objects") {

int space_pos = line.find(' ');

DATA_LINE ln;

ln.key = line.substr(0, space_pos); ln.value = line.substr(space_pos + 1); _rline[_curLine].key = line.substr(0, space_pos); _rline[_curLine].value = line.substr(space_pos + 1); _curLine++; if (_count >= 8) {

LOGI("[SM] Count %s \tModelID %s \tTexID %s \tShaderID %s\n", _rline[1].value.data(), _rline[2].value.data(),

_rline[3].value.data(), _rline[4].value.data()); objectList[objectCount].init(atoi(_rline[2].value.data()), atoi(_rline[3].value.data()), atoi(_rline[4].value.data())); sscanf(_rline[5].value.data(), "%f %f %f", &objectList[objectCount].Position.x, &objectList[objectCount].Position.y, &objectList[objectCount].Position.z); sscanf(_rline[6].value.data(), "%f %f %f", &objectList[objectCount].Rotation.x, &objectList[objectCount].Rotation.y, &objectList[objectCount].Rotation.z); sscanf(_rline[7].value.data(), "%f %f %f", &objectList[objectCount].Scale.x, &objectList[objectCount].Scale.y, &objectList[objectCount].Scale.z); objectCount++;

/*for (int i = 0; i < 8; i++) {

LOGI("%d \tID: %s \tVAL: %s\n", i, _rline[i].key.data(), _rline[i].value.data());

60 _count = 0; _current++; _curLine = 0; } } } } } } else {

LOGE("[SME] Scene file not found !\n");

} }

Sau khi đã có lớp quản lý màn hình thì chúng ta tạo ra các màn hình game, một màn hình game cơ bản có cấu trúc nhƣ sau:

class GameState {

public:

virtual void Init() = 0; virtual void Draw() = 0;

virtual void Update(float deltaTime) = 0; virtual void Destroy() = 0;

};

Ví dụ màn hình chọn level sẽ có cấu trúc nhƣ sau: class LevelSelectState: public GameState {

public:

Rectangle bgRect,survivalRect,storyRect; string *story;

int currentPage, numPages; float timer;

LevelSelectState(void); ~LevelSelectState(void); void Init();

void Draw();

void Update(float deltaTime); void Destroy();

};

Sau đó, chúng ta bắt đầu xây dựng các lớp đối tƣợng của game, gồm có: Cannon là khẩu súng đại bác

61

WarShip – các tàu địch Castle – tòa thành

HP – thanh máu của ngƣời chơi. Sea – mặt biển

Khẩu súng đại bác có cấu trúc đối tƣợng nhƣ sau:

class Cannon : public Singleton<Cannon>, public Objects {

private:

unsigned int numBullet;// số đạn hiện đang có cũng đồng thời là số

đạn giới hạn khi mới bắt đầu chơi.

public:

float angle; //góc quay của súng float count;

unsigned int reload_time; bool isUnlimited;

Cannon(void); ~Cannon(void); void init(); void Draw();

void setBullet(unsigned int);// set num of bullet unsigned int getBullet(void);

void Update(float deltaTime); void rotLeft(float deltaTime); void rotRight(float deltaTime); void shock();

void reBegin();

void Fire(float _angle, float _v0); };

Cấu trúc đối tƣợng của một viên đạn:

class Bullet : public Objects, public Singleton<Bullet> {

public:

int MAX_POW; int MIN_POW; float increase;

float angle;// góc bay của viên đạn so với trục Ox float v0;//vận tốc ban đầu của viên đạn

float time;//thời điểm của viên đạn tính từ lúc bắn

Vector3 cur_pos;// vị trí ban đầu của viên đạn

bool isFire; //biến lưu lại trạng thái của viên đạn: bắn/chưa bắn Bullet(void);

void init();

void reBegin(void);

void Fire(float _angle, float _v0); void Update(float deltaTime);

62

};

Lớp HP – hiển thị trạng thái máu của ngƣời chơi class HP :

public Status_Bar, public Singleton<HP> { float cur_hit; public: HP(void); void init(); void Draw();

void Update(float deltaTime); void Change(int value);

bool getHit(); ~HP(void); };

Lớp WarShip – Định nghĩa tàu của quân địch class WarShip : public Objects

{

int x, y;

int dir; // direction of WarShip

bool addScoreC, addScoreB; // test add score when colliding Castle or

Bullet

float leftW, rightW, topW, bottomW, frontW, backW; int num_Rotate; // test warship rotate?

float dx, dz, agl;

float Angle; // the symbol of angle rotatate around Oy

Matrix mLocation; bool isBombed; bool direct ; bool checkColl; int typeColl; public:

//bool movePearl; // direction when press button PEARL

EnemyBullet* ebullet;

int accurate; int timefire;

Vector3 pos, rot, cmr;

bool isUpdate; int count; WarShip(void); WarShip(int );

63

~WarShip(void);

void Rotate( float, float, float, float );

//void Draw();

void UpdateWS1( float ); void UpdateWS2( float ); bool isCollideBullet(void); bool isCollideCastle(void); bool isCollideWS ( WarShip ws ); void Update(float deltaTime); void Draw();

};

Để di chuyển súng đại bác sang trái và phải theo các sự kiện nhấn phím hoặc bấm vào nút trên màn hình. Ta xử lý nhƣ sau:

//cannon turn right

if (GL2D::IsInRect(holdX, holdY, rectDirectionRight) ||

GL2D::IsInRect(holdX2, holdY2, rectDirectionRight))

{ if (Camera::GetInstance()->getRotation().y >= -0.1) Camera::GetInstance()->Key(deltaTime, 39); cannon->rotRight(deltaTime); #ifdef _ANDROID if (ResourcesManager::GetInstance()->isPlaySound == 1) { StopSound(); PlaySound(2, 0); } #endif LOGI("Turn right\n"); }

//cannon turn left

if (GL2D::IsInRect(holdX, holdY, rectDirectionLeft) ||

GL2D::IsInRect(holdX2, holdY2, rectDirectionLeft))

{ if (Camera::GetInstance()->getRotation().y <= 0.1) Camera::GetInstance()->Key(deltaTime, 37); cannon->rotLeft(deltaTime); #ifdef _ANDROID if (ResourcesManager::GetInstance()->isPlaySound == 1) { StopSound(); PlaySound(2, 0); } #endif LOGI("Turn left\n"); }

Khi ngƣời chơi nhấn vào nút Fire, ta sẽ điều khiển cho thanh lực bắn tăng lên và giảm xuống nhƣ sau:

64 if (GL2D::IsInRect(holdX, holdY, rectFireBT) || GL2D::IsInRect(holdX2, holdY2, rectFireBT)) { if ( power < 0 ) { bullet->increase *= -1; pow_bar->increase *= -1; } if ( power > bullet->MAX_POW ) {

bullet->increase *= -1; //nếu lực bắn đặt tối đa thì lực bắn

sẽ giảm xuống nếu tiếp tục nhấn

pow_bar->increase *= -1; }

power += bullet->increase * (deltaTime * 50);

pow_bar->scale += pow_bar->increase * (deltaTime * 50);

LOGI("power: %f\tlengh bar: %f\n",power, pow_bar->scale);

}

Khi thả ra thì sẽ bắt đầu sự kiện bắn:

if (GL2D::IsInRect(holdX, holdY, rectFireBT) || GL2D::IsInRect(holdX2, holdY2, rectFireBT)) { LOGI("Power: %f\n", power); pow_bar->Reset(); cannon->Fire(cannon->angle, power); //cannon->shock(); #ifdef _ANDROID if (ResourcesManager::GetInstance()->isPlaySound == 1) { StopSound(); PlaySound(1, 0); } #endif power = 0; }

65

Một phần của tài liệu (Trang 55 - 65)

Tải bản đầy đủ (PDF)

(74 trang)