关于cocos2dx 3.2的井字过三关
在闲暇时光,我编写了这个基于Cocos2d-x 3.2的井字过三关游戏。目前该游戏没有集成人工智能,玩家可以自己玩,也能邀请朋友一同游戏。需要注意的是,之前版本存在的 BUG 已经修复,之前下载过的朋友请重新下载。
代码实现
1. AppDelegate.cpp
此文件是应用程序的入口点,负责初始化游戏窗口和场景,以下是具体代码:
bool AppDelegate::applicationDidFinishLaunching() {
auto director = Director::getInstance();
auto glview = director->getOpenGLView();
if (!glview) {
glview = GLView::createWithRect("Tic Tac Toe", Rect(0, 0, 286, 512), 1.0f);
director->setOpenGLView(glview);
}
glview->setDesignResolutionSize(268, 512, ResolutionPolicy::EXACT_FIT);
// 开启 FPS 显示
director->setDisplayStats(true);
// 设置帧率,默认值为 1.0 / 60
director->setAnimationInterval(1.0 / 60);
// 创建场景,场景是自动释放对象
auto scene = HelloWorld::createScene();
// 运行场景
director->runWithScene(scene);
return true;
}
2. Card.h
该头文件定义了 Card 类,继承自 Sprite,用于表示游戏中的卡片,具体如下:
#include "cocos2d.h"
USING_NS_CC;
class Card : public Sprite {
public:
static Card* createCards(Color3B bgColor, Size cardSize);
virtual bool init(Color3B bgColor, Size cardSize);
void setLineIndex(int index);
int getLineIndex();
void removeCard();
// 获取向量里的对象
static Vector<Card*> *getCard();
// 清空向量
static void renewVector();
// 显示图案 1
void showO();
// 显示图案 2
void showX();
// 设定标记判断是否已经按下
void setFlag(int i);
// 获取标记数字
int getFlag();
// 设定图案标记
void setPattern(int num);
// 获取图案标记
int getPattern();
private:
// 用向量存放 Card
static Vector<Card*> *cards;
// 记录卡片所在的行
int lineIndex;
// Card 的 Size
Size cSize;
// 判定是否已经被按下
int flag;
// 判断当前卡片是什么图案,0 是圈,1 是叉
int pattern;
};
3. Card.cpp
这是 Card 类的实现文件,包含了 Card 类各个方法的具体实现:
#include "Card.h"
USING_NS_CC;
Vector<Card*> *Card::cards = new Vector<Card*>();
Card* Card::createCards(Color3B bgColor, Size cardSize) {
auto card = new Card();
card->init(bgColor, cardSize);
card->autorelease();
card->flag = 0;
cards->pushBack(card);
return card;
}
bool Card::init(Color3B bgColor, Size cardSize) {
Sprite::init();
lineIndex = 0;
setContentSize(cardSize);
cSize = cardSize;
setAnchorPoint(Point::ZERO);
setTextureRect(Rect(0, 0, cardSize.width, cardSize.height));
setColor(bgColor);
return true;
}
Vector<Card*> * Card::getCard() {
return cards;
}
void Card::renewVector() {
cards->clear();
}
// 显示图案 1
void Card::showO() {
auto s = Sprite::create("sun.png");
s->setPosition(Point(cSize.width / 2, cSize.height / 2));
addChild(s);
}
// 显示图案 2
void Card::showX() {
auto r = Sprite::create("moon.png");
r->setPosition(Point(cSize.width / 2, cSize.height / 2));
addChild(r);
}
// 设定图案标记
void Card::setFlag(int i) {
this->flag = i;
}
// 获取标记数字
int Card::getFlag() {
return this->flag;
}
// 设定图案标记
void Card::setPattern(int num) {
this->pattern = num;
}
// 获取图案标记
int Card::getPattern() {
return this->pattern;
}
4. HelloWorldScene.h
此头文件定义了 HelloWorld 类,继承自 cocos2d::Layer,负责管理游戏场景和逻辑:
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
#include "Card.h"
class HelloWorld : public cocos2d::Layer {
public:
static cocos2d::Scene* createScene();
virtual bool init();
void menuCloseCallback(cocos2d::Ref* pSender);
CREATE_FUNC(HelloWorld);
// 添加卡片
void addCard();
// 判断游戏是否结束
void isGameOver();
// 重新开始游戏
void reStart();
private:
Size visibleSize;
Point origin;
// 记录点击的次数,奇数次的为图案 1,偶数次的为图案 2
int count;
// 卡片二维数组,方便操作
Card *cardArr[3][3];
// 用于初始化图案标记
int initPatternNum;
Vector<Card*> *c;
};
#endif // __HELLOWORLD_SCENE_H__
5. HelloWorldScene.cpp
这是 HelloWorld 类的实现文件,包含了游戏场景的初始化、卡片添加、游戏结束判断等逻辑:
#include "HelloWorldScene.h"
USING_NS_CC;
Scene* HelloWorld::createScene() {
auto scene = Scene::create();
auto layer = HelloWorld::create();
scene->addChild(layer);
return scene;
}
bool HelloWorld::init() {
if (!Layer::init()) {
return false;
}
visibleSize = Director::getInstance()->getVisibleSize();
origin = Director::getInstance()->getVisibleOrigin();
// 游戏背景
auto layerClour = LayerColor::create(Color4B(255, 255, 255, 255));
this->addChild(layerClour);
// 添加标题
auto title = LabelTTF::create("Tic-Tac-Toe", "Arial", 30);
title->setColor(Color3B(139, 69, 19));
title->setPosition(Point(visibleSize.width / 2, visibleSize.height - 50));
addChild(title);
// 添加卡片
addCard();
// 初始化点击次数和图案标记
count = 1;
initPatternNum = 10;
auto listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = [this](Touch *t, Event *e) {
c = Card::getCard();
Card *it;
for (auto iterator = c->begin(); iterator != c->end(); iterator++) {
it = *iterator;
if ((it->getFlag() == 0) && (it->getBoundingBox().containsPoint(t->getLocation())) && (count == 1 || count == 3 || count == 5 || count == 7 || count == 9)) {
it->setFlag(1);
it->setPattern(0);
it->showO();
count++;
}
if ((it->getFlag() == 0) && (it->getBoundingBox().containsPoint(t->getLocation())) && (count == 2 || count == 4 || count == 6 || count == 8)) {
it->setFlag(1);
it->setPattern(1);
it->showX();
count++;
}
}
this->isGameOver();
return false;
};
Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
return true;
}
void HelloWorld::menuCloseCallback(Ref* pSender) {
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.", "Alert");
return;
#endif
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}
void HelloWorld::addCard() {
Card *card;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
card = Card::createCards(Color3B::GRAY, Size(visibleSize.width / 3 - 3, visibleSize.height / 4 - 3));
card->setPosition(Point(i * visibleSize.width / 3, j * visibleSize.height / 4));
card->setPattern(initPatternNum++);
cardArr[i][j] = card;
addChild(card);
}
}
}
void HelloWorld::isGameOver() {
if (count == 10) {
reStart();
}
for (int x = 0; x < 3; x++) {
if (cardArr[x][0]->getPattern() == cardArr[x][1]->getPattern() && cardArr[x][1]->getPattern() == cardArr[x][2]->getPattern()) {
reStart();
}
}
for (int y = 0; y < 3; y++) {
if (cardArr[0][y]->getPattern() == cardArr[1][y]->getPattern() && cardArr[1][y]->getPattern() == cardArr[2][y]->getPattern()) {
reStart();
}
}
if (cardArr[0][0]->getPattern() == cardArr[1][1]->getPattern() && cardArr[1][1]->getPattern() == cardArr[2][2]->getPattern()) {
reStart();
}
if (cardArr[0][2]->getPattern() == cardArr[1][1]->getPattern() && cardArr[1][1]->getPattern() == cardArr[2][0]->getPattern()) {
reStart();
}
}
void HelloWorld::reStart() {
c->clear();
Director::getInstance()->replaceScene(TransitionFade::create(1, HelloWorld::createScene()));
}
通过以上代码,我们实现了一个简单的井字过三关游戏,玩家可以通过点击卡片来进行游戏,当有三个相同图案连成一线或者卡片全部被点击完时,游戏将重新开始。