Search…

Hướng Dẫn Viết Game Zero Với Cocos2d-x - Phần 8: Hiện thực GameScene - Xử lý sự kiện trong game

30/09/20203 min read
Hướng dẫn cách nhận các sự kiện từ người chơi và xử lý chúng theo logic của game.

Hướng dẫn hiện thực lại game ZERO một cách đơn giản. Giúp làm quen cách để hoàn thành 1 game, cũng như cách tổ chức project trong game.

 Bài viết hướng dẫn cách nhận các sự kiện từ người chơi và xử lý chúng theo logic của game.

Hiện thực

Vào file config.h thêm mới vào 1 số định nghĩa như sau:

static const float      FP_EPSILON = 0.000001f;
static const float		OP_SCALE = 0.75f;

static const char       *PATH_SPR_OPS[] =
{
	"spr_op_greater.png",
	"spr_op_less.png",
	"spr_op_equal.png"
};

enum
{
	OP_GREATER,
	OP_LESS,
	OP_EQUAL,
	OP_COUNT
};

Tại GameScene.h

Tại file này thêm vào 2 biến _op, _resultTrue và 2 hàm computeResultinputHandle để được như sau:

#ifndef __GAME_SCENE_H__
#define __GAME_SCENE_H__

#include "cocos2d.h"
#include "ui/CocosGUI.h"

USING_NS_CC;

class GameScene : public cocos2d::Layer
{
public:
	// there's no 'id' in cpp, so we recommend returning the class instance pointer
	static cocos2d::Scene* createScene();

	// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
	virtual bool init();

	void update(float);
	void generateNextChallenge();
	void resetButtons();
	bool computeResult();
	void inputHandle();

	// implement the "static create()" method manually
	CREATE_FUNC(GameScene);

private:
	Layer           *_layerPresentation;
	ProgressTimer   *_timer;

	int				_nLeftSuits;
	int				_nRightSuits;
	int				_clickedButton;

	int _op;
	bool _resultTrue;

	Vec2			_centerSuitPostionLeft;
	Vec2			_centerSuitPostionRight;

	float           _currentTime;
	float			_maxTimer;

	cocos2d::ui::Button			*_btnRight;
	cocos2d::ui::Button			*_btnWrong;

	Size visibleSize;
	Vec2 origin;
};

#endif // __GAME_SCENE_H__

Giải thích: 

  • _op là biến quy định phép tính <, >, hoặc =.
  • _resultTrue là kết quả trả về của phép tính này đúng hay sai.

Tại GameScene.cpp

Trong hàm init

Khởi tạo giá trị cho biến _resultTrue:

_resultTrue = false;

Hiện thực hàm computeResult

bool GameScene::computeResult()
{
	return
		((_nLeftSuits < _nRightSuits) && _op == OP_LESS) ||
		((_nLeftSuits > _nRightSuits) && _op == OP_GREATER) ||
		((_nLeftSuits == _nRightSuits) && _op == OP_EQUAL);
}

Hàm này giúp trả về kết quả phép tính với 2 giá trị đúng hoặc sai.

Trong hàm generateNextChallenge

Thêm vào 1 số dòng code mới để được như sau:

void GameScene::generateNextChallenge()
{
	_layerPresentation->removeAllChildrenWithCleanup(true);
	_currentTime = _maxTimer = 1.5f;
	_timer->setColor(Color3B::WHITE);

	// randomize number of every suit
	_nLeftSuits = MIN_SUITS_PER_SIDE + CCRANDOM_0_1()*(MAX_SUITS_PER_SIDE - MIN_SUITS_PER_SIDE + 1 - FP_EPSILON);
	_nRightSuits = MIN_SUITS_PER_SIDE + CCRANDOM_0_1()*(MAX_SUITS_PER_SIDE - MIN_SUITS_PER_SIDE + 1 - FP_EPSILON);

	drawSuitsTable(_nLeftSuits, _centerSuitPostionLeft, origin.x, origin.y, _layerPresentation);
	drawSuitsTable(_nRightSuits, _centerSuitPostionRight, origin.x, origin.y, _layerPresentation);

	_op = CCRANDOM_0_1() * (OP_COUNT - FP_EPSILON);
	_resultTrue = computeResult();

	Sprite *spriteOp = Sprite::createWithSpriteFrameName(PATH_SPR_OPS[_op]);
	spriteOp->setPosition(Vec2(origin.x + visibleSize.width/2, origin.y + visibleSize.height/2));
	spriteOp->setScale(OP_SCALE);
	_layerPresentation->addChild(spriteOp);
}

Hiện thực hàm inputHandle

void GameScene::inputHandle()
{
	if (_clickedButton == BTN_NONE)
		return;

	if ((_resultTrue == true && (_clickedButton == BTN_RIGHT)) ||
		(_resultTrue == false && (_clickedButton == BTN_WRONG)))
	{
		generateNextChallenge();
	}
	else
	{
		Director::getInstance()->replaceScene(GameOverScene::createScene());
	}

	_clickedButton = BTN_NONE;
}

Hàm này xử lý logic game khi nhận sự kiện từ người chơi. Nếu đúng thì gọi hàm generateNextChallenge để chơi tiếp. Ngược lại sẽ chuyển qua GameOverScene (dòng 13).

Trong hàm update

Gọi hàm inputHandle đồng thời update thêm dòng chuyển scene khi hết thời gian:

void GameScene::update(float dt)
{
	this->inputHandle();

	_currentTime -= dt;

	if (_currentTime < 0)
	{
		_currentTime = 0.0f;
		Director::getInstance()->replaceScene(GameOverScene::createScene());
	}

	float percentage = _currentTime*100.0f / _maxTimer;
	_timer->setPercentage(percentage);
	_timer->setOpacity(TIMER_OPACITY);
	if (percentage < 50.0f)
	{
		_timer->setColor(Color3B(255, 255 * percentage / 50, 255 * percentage / 50));
	}
}	

Download

SOURCE_CODE

Bài chung series

IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024