Cocos2d-x 3.2制作三消游戏《万圣大作战》1:开始界面&创建精灵

2015年03月19日 11:22 0 点赞 0 评论 更新于 2025-11-21 17:41

三消游戏是一类将三个相同元素点击合成即可消除的游戏。今天,我们以《万圣大作战》这款时下受众多玩家喜爱的三消游戏为例,进行一次实例学习。

1. 准备工作

前期的环境配置步骤,可参考有关Cocos2d-x 3.0在WIN7 + VS2012平台搭建的知识,该知识在3.0及以上版本基本通用,至少在3.2版本中没有问题。

建立项目

第一步,调整分辨率。在AppDelegate.cpp文件中的applicationDidFinishLaunching函数里进行如下操作:

bool AppDelegate::applicationDidFinishLaunching() {
// 初始化导演
auto director = Director::getInstance();
auto glview = director->getOpenGLView();
if (!glview) {
glview = GLView::create("My Game");
director->setOpenGLView(glview);
glview->setFrameSize(320, 480);
}
glview->setDesignResolutionSize(480, 800, 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. 界面的制作

制作开始界面

新建一个类WelcomeScene

WelcomeScene.h文件

#ifndef __WELCOME_SCENE_H__
#define __WELCOME_SCENE_H__

#include "cocos2d.h"

class WelcomeScene : public cocos2d::Layer {
public:
static cocos2d::Scene* createScene();
virtual bool init();
void menuStartCallback(Ref* pSender);
CREATE_FUNC(WelcomeScene);
};

#endif // __WELCOME_SCENE_H__

在这中间,需要先创建一个GameDefine.h头文件,用于存放一些关于游戏的宏定义,本次用于存放画布的宽高,后续还会存放其他定义。

GameDefine.h文件

#ifndef _Inkmoo_Elimination_h_
#define _Inkmoo_Elimination_h_

// 定义屏幕宽高,这与所做的图片有关
#define GAME_SCREEN_WIDTH 480
#define GAME_SCREEN_HEIGHT 800

#endif

现在,我们就可以在其他文件中使用这些宏定义了。

WelcomeScene.cpp文件

#include "WelcomeScene.h"
#include "GameDefine.h"
USING_NS_CC;

Scene* WelcomeScene::createScene() {
auto scene = Scene::create();
auto layer = WelcomeScene::create();
scene->addChild(layer);
return scene;
}

// 欢迎界面初始化函数
bool WelcomeScene::init() {
// 先初始化父类,不成功则返回false
if (!Layer::init()) {
return false;
}

// 添加背景图片
auto sprite = Sprite::create("scene_sta.png");
sprite->setPosition(Point(GAME_SCREEN_WIDTH / 2, GAME_SCREEN_HEIGHT / 2));
this->addChild(sprite);

// 添加开始按钮
auto startItem = MenuItemImage::create(
"btn_start01.png",
"btn_start02.png",
CC_CALLBACK_1(WelcomeScene::menuStartCallback, this)
);
startItem->setPosition(Vec2(GAME_SCREEN_WIDTH / 2, GAME_SCREEN_HEIGHT / 6));
auto menu = Menu::create(startItem, NULL);
menu->setPosition(Vec2::ZERO);
this->addChild(menu);

return true;
}

void WelcomeScene::menuStartCallback(Ref* pSender) {
// 跳转到游戏界面
}

制作游戏界面

GameScene.h文件

#ifndef __GAME_SCENE_H__
#define __GAME_SCENE_H__

#include "cocos2d.h"

class GameScene : public cocos2d::Layer {
public:
static cocos2d::Scene* createScene();
virtual bool init();
// 返回欢迎界面函数
void menuBackCallback(Ref* pSender);
CREATE_FUNC(GameScene);
};

#endif // __GAME_SCENE_H__

GameScene.cpp文件

#include "GameScene.h"
#include "GameDefine.h"
#include "WelcomeScene.h"
USING_NS_CC;

Scene* GameScene::createScene() {
auto scene = Scene::create();
auto layer = GameScene::create();
scene->addChild(layer);
return scene;
}

// 游戏界面初始化函数
bool GameScene::init() {
// 先初始化父类,不成功则返回false
if (!Layer::init()) {
return false;
}

// 添加背景图片
auto sprite = Sprite::create("scene_bg.png");
sprite->setPosition(Point(GAME_SCREEN_WIDTH / 2, GAME_SCREEN_HEIGHT / 2));
this->addChild(sprite, -1);

// 添加返回按钮
auto backItem = MenuItemImage::create(
"btn_back01.png",
"btn_back02.png",
CC_CALLBACK_1(GameScene::menuBackCallback, this)
);
backItem->setPosition(Vec2(GAME_SCREEN_WIDTH - backItem->getContentSize().width / 2, backItem->getContentSize().height / 2));
auto menu = Menu::create(backItem, NULL);
menu->setPosition(Vec2::ZERO);
this->addChild(menu);

return true;
}

// 返回函数,跳转到欢迎界面
void GameScene::menuBackCallback(Ref* pSender) {
auto scene = WelcomeScene::createScene();
CCDirector::sharedDirector()->replaceScene(scene);
}

需要注意的是,要修改之前欢迎界面的menuStartCallback函数:

void WelcomeScene::menuStartCallback(Ref* pSender) {
// 跳转到游戏界面
auto scene = GameScene::createScene();
CCDirector::sharedDirector()->replaceScene(scene);
}

现在,我们可以运行程序,在欢迎界面点击“开始”进入游戏界面,在游戏界面点击“返回主菜单”回到欢迎界面。

3. 精灵相关

前面的内容都是准备工作,接下来,我们要添加相应的精灵。这些精灵的素材存放在一张png图片里,可使用TexturePacker进行压缩(如果不会使用,请参考《Cocos2d-x 3.x使用plist和png制作动画》)。

三消游戏主要涉及精灵的创建、移动和消除操作。这些精灵在游戏界面的存储方式类似于二维表格,因此需要一个单独的类来管理精灵。

SpriteShape.h文件

#include "cocos2d.h"
#include "GameDefine.h"
USING_NS_CC;

class SpriteShape : public Sprite {
public:
static SpriteShape* create(int row, int col);
CC_SYNTHESIZE(int, m_row, Row);
CC_SYNTHESIZE(int, m_col, Col);
CC_SYNTHESIZE(int, m_imgIndex, ImgIndex);
};

create函数用于根据传入的行列值,在相应位置创建精灵。CC_SYNTHESIZE宏相当于自动生成两个函数,以CC_SYNTHESIZE(int, m_row, Row)为例,它会定义一个int类型的保护型变量m_row,并定义一个setRow函数和一个getRow函数,用于对m_row进行操作。

SpriteShape.cpp文件

#include "SpriteShape.h"

SpriteShape* SpriteShape::create(int row, int col) {
SpriteShape* spr = new SpriteShape();
spr->m_row = row;
spr->m_col = col;
spr->m_imgIndex = rand() % TOTAL_SPRITE;
spr->initWithSpriteFrameName(spriteNormal[spr->m_imgIndex]);
spr->autorelease();
return spr;
}

该函数的实现步骤为:先通过传参定位精灵的位置,然后获取一个随机数,该随机数的范围要在精灵种类数内,最后根据随机数获取对应的图片。

GameDefine.h文件补充

// 定义每个精灵大小与边框大小
#define SPRITE_WIDTH 48
#define BOADER_WIDTH 2

// 游戏精灵行数和列数
#define ROWS 8
#define COLS 8

// 精灵种类总数
#define TOTAL_SPRITE 6

// 普通的精灵
static const char* spriteNormal[TOTAL_SPRITE] = {
"icon1.png",
"icon2.png",
"icon3.png",
"icon4.png",
"icon5.png",
"icon6.png"
};

在游戏界面显示精灵

游戏界面类似于一个大的二维表格,我们需要先创建这个表格,然后定义一个初始化地图函数来初始化表格。

GameScene.cpp文件补充

// 初始化地图
void GameScene::initMap() {
for (int r = 0; r < ROWS; ++r) {
for (int c = 0; c < COLS; ++c) {
createSprite(r, c);
}
}
}

// 创建精灵
void GameScene::createSprite(int row, int col) {
// 先创建一个精灵
SpriteShape* spr = SpriteShape::create(row, col);
Point endPosition = positionOfItem(row, col);
spr->setPosition(endPosition);

// 加入到spriteSheet中,等待绘制
spriteSheet->addChild(spr);

// 数组相应位置,置上精灵对象
map[row][col] = spr;
}

// 根据行列,获取坐标值
Point GameScene::positionOfItem(int row, int col) {
float x = mapLBX + (SPRITE_WIDTH + BOADER_WIDTH) * col + SPRITE_WIDTH / 2;
float y = mapLBY + (SPRITE_WIDTH + BOADER_WIDTH) * row + SPRITE_WIDTH / 2;
return Point(x, y);
}

现在运行程序,精灵就会出现在游戏界面中。

4. 额外改进

目前实现的效果有些过于平面,我们可以添加一个2.1D的下落动作。具体做法是在创建精灵时,将其放置在原来位置上方一定距离处,然后通过一定速度下落到原来位置,这可以通过添加一个动作来实现。

GameScene.cpp文件修改

// 创建精灵
void GameScene::createSprite(int row, int col) {
// 先创建一个精灵
SpriteShape* spr = SpriteShape::create(row, col);

// 创建下落动画
Point endPosition = positionOfItem(row, col);
Point startPosition = Point(endPosition.x, endPosition.y + GAME_SCREEN_HEIGHT / 2);
spr->setPosition(startPosition);

float speed = startPosition.y / (1.5 * GAME_SCREEN_HEIGHT);
spr->runAction(MoveTo::create(speed, endPosition));

// 加入到spriteSheet中,等待绘制
spriteSheet->addChild(spr);

// 数组相应位置,置上精灵对象
map[row][col] = spr;
}

现在可以运行程序,体验改进后的效果。

作者信息

boke

boke

共发布了 3994 篇文章