项目源码地址:
源码
下一章:
cocos2dx 4.0入门之泡泡龙项目的分解(二)
前言
本文只是作为一个业余爱好者的见解,不会涉及太深入的讲解(太深入我也不会—(笑)),目的在于带领想学习cocos2dx引擎的而不知如何开始的爱好者,如何开头(俗话说:万事开头难,cocos2dx对于业余爱好者往往在入门这一关就劝退了),这是一篇不涉及太多专业知识以及复杂讲解的教程,旨在纵览cocos2dx完成一个完整项目的步骤流程。(接下来的学习会涉及大量《cocos2d-x 3.0 游戏开发实战详解》里的内容,请结合书籍阅读)
正文
最近在学习cocos,看的书是《cocos2d-x 3.0 游戏开发实战详解》,这本书有576页,但是我不喜欢按书中传统的方法,从基础开始,看精灵、层等blabla一堆,半天还没真正开始项目,这会让我失去兴趣。
因此,我打算直接从第12章开始,虽然没有了解深入基础知识,但是作为一只小白只有从项目中学习才是最快的,而不是半天捧着一本词典看,再来写文章。( 对于完全没接触过一个东西的小白,有的时候我觉得好的教程应该一步步带小白实现功能,并且给出每一步的代码,慢慢修改成为一个完整项目,而不是从完整的项目讲解,慢慢拆分(很多时候完整的代码反而因为各种原因不可编译或执行,对于小白来说各种解决项目报错反而最花时间以及打击学习兴趣),从地基开始最小化的代码完成一个基础的可运行的项目,然后慢慢讲解每一步怎么填充,我觉得是最优的)
第十二章是泡泡龙游戏,书上的例子是在cocos2dx3.0 安卓环境下进行的。 我的环境是vs2019 +cocos2dx 4.0+win32项目。先下载资源文件,接下来对项目进行最小化开始的删减,先运行起来,再一步步完成这个项目。(如果没有C++基础,建议先看C++)
言归正传,开始项目:
一、首先拷出,书中光盘的第十二章项目中的classes和resource两个资源,classes是源码,resource是图片、声音等资源。
先把resource是资源一股脑全拷进,cocos项目目录的resource文件夹,全放一个目录,不要子目录。
二、然后全部导入vs中,虽然前面带.的文件不是我们需要的,以及将全部资源导入项目不合适。但是作为一个小白,我啥也不知道,就是蛮干啊,能运行起来就ok了,咱们就是干。
三、处理源文件,现在先在classes目录选取一下几个源文件导入
修改代码如下:
AppMacros.h文件不用修改
头文件
#ifndef __ShootBubbleSceneManager_H__
#define __ShootBubbleSceneManager_H__
#include "cocos2d.h"
using namespace cocos2d;
//”√”⁄¥¥Ω®≥°æ∞µƒ¿‡
class ShootBubbleSceneManager
{
public:
//创建第一次进入游戏的场景
Scene* createScene();
// 声明指向不同场景对象的指针
Scene* mainScene;
/*
Scene* gameScene;
Scene* helpScene;
Scene* GKScene;
Scene* AboutUSScene;
Scene* JbfScene;
*/
/*
//切换到游戏场景到方法
void goGameScene();
//切换到主场景到方法
void goMainScene();
//切换到帮助场景到方法
void gohelpScene();
//切换到选关场景到方法
void goGKScene();
//切换到关于场景到方法
void goAboutUSScene();
void goJbfScene();
*/
};
#endif
#ifndef __StartLayer_H__
#define __StartLayer_H__
#include "cocos2d.h"
#include "ShootBubbleSceneManager.h"
using namespace cocos2d;
class StartLayer: public Layer
{
public:
// 初始化布景
virtual bool init();
void initSound();
// 加载完成一副图片时回调的方法
void loadingCallBack(Texture2D* tt);
// 异步加载的方法
void loadingTexturesAsync();
// 点击开始游戏时被回调的方法
void startCallback();
// 点击声音按钮时被回调的方法
void soundCallback();
// 点击帮助按钮时被回调的方法
void helpCallback();
// 点击关于按钮时被回调的方法
void aboutCallback();
// 点击排行榜按钮时被回调的方法
void phbCallback();
public:
// 声明一个指向场景管理器对象的指针
ShootBubbleSceneManager *sbsm;
// 声明一个一个bool变量,用于是否播放声音
static bool soundB;
// 声明一个int变量,用于记录是否将资源异步加载完全
int jd=0;
// 声明一个用于加载图片资源时显示的精灵
Sprite* loadingPic;
Label* lPros;
// 声明一个指向菜单项的指针
MenuItemImage* soundon;
MenuItemImage* soundoff;
CREATE_FUNC(StartLayer);
};
#endif
cpp文件
#include "ShootBubbleSceneManager.h"
//#include "ShootBubbleLayer.h"
#include "StartLayer.h"
//#include "HelpLayer.h"
//#include "ChooseGKLayer.h"
//#include "AboutUSLayer.h"
//#include "JFBLayer.h"
using namespace cocos2d;
//创建第一进入游戏场景
Scene* ShootBubbleSceneManager::createScene()
{
//创建一个场景对象
mainScene = Scene::create();
//创建一个布景对象
auto mlayer = StartLayer::create();
mlayer->sbsm=this;
//将布景添加到场景中
mainScene->addChild(mlayer);
//返回主场景
return mainScene;
}
/*
//切换到游戏场景的方法
void ShootBubbleSceneManager::goGameScene()
{
// 设置深度检测
//Director::getInstance()->setDepthTest(true);
// 创建一个场景对象
gameScene = Scene::create();
// 创建一个布景对象
ShootBubbleLayer* glayer = ShootBubbleLayer::create();
glayer->sbsm=this;
// 将布景对象添加到场景中
gameScene->addChild(glayer);
// 创建一个切换场景到特效
auto ss=TransitionProgressInOut::create(1, gameScene);
// 切换到游戏场景
Director::getInstance()->replaceScene(ss);
}
//切换到主场景的方法
void ShootBubbleSceneManager::goMainScene()
{
// 设置深度检测
//Director::getInstance()->setDepthTest(true);
// 创建一个场景对象
mainScene = Scene::create();
// 创建一个布景对象
auto mlayer = StartLayer::create();
mlayer->sbsm=this;
// 将布景对象添加到场景中
mainScene->addChild(mlayer);
// 创建一个切换场景到特效
auto ss=TransitionProgressInOut::create(1, mainScene);
// 切换到主场景
Director::getInstance()->replaceScene(ss);
}
//切换到帮助场景的方法
void ShootBubbleSceneManager::gohelpScene()
{
// 设置深度检测
//Director::getInstance()->setDepthTest(true);
// 创建一个场景对象
helpScene = Scene::create();
// 创建一个布景对象
HelpLayer* hlayer = HelpLayer::create();
hlayer->sbsm=this;
// 将布景对象添加到场景中
helpScene->addChild(hlayer);
// 创建一个切换场景到特效
auto ss=TransitionProgressOutIn::create(1, helpScene);
// 切换到帮助场景
Director::getInstance()->replaceScene(ss);
}
//切换到主场景的方法
void ShootBubbleSceneManager::goGKScene()
{
// 设置深度检测
//Director::getInstance()->setDepthTest(true);
// 创建一个场景对象
GKScene = Scene::create();
// 创建一个布景对象
auto clayer = ChooseGKLayer::create();
clayer->sbsm=this;
// 将布景对象添加到场景中
GKScene->addChild(clayer);
// 创建一个切换场景到特效
auto ss=TransitionProgressOutIn::create(1, GKScene);
// 切换到帮助场景
Director::getInstance()->replaceScene(ss);
}
//切换到主场景的方法
void ShootBubbleSceneManager::goAboutUSScene()
{
// 设置深度检测
//Director::getInstance()->setDepthTest(true);
// 创建一个场景对象
AboutUSScene = Scene::create();
// 创建一个布景对象
auto alayer = AboutUSLayer::create();
alayer->sbsm=this;
// 将布景对象添加到场景中
AboutUSScene->addChild(alayer);
// 创建一个切换场景到特效
auto ss=TransitionProgressOutIn::create(1, AboutUSScene);
// 切换到帮助场景
Director::getInstance()->replaceScene(ss);
}
//切换到主场景的方法
void ShootBubbleSceneManager::goJbfScene()
{
// 设置深度检测
//Director::getInstance()->setDepthTest(true);
// 创建一个场景对象
JbfScene = Scene::create();
// 创建一个布景对象
auto jlayer = JFBLayer::create();
jlayer->sbsm=this;
// 将布景对象添加到场景中
JbfScene->addChild(jlayer);
// 创建一个切换场景到特效
auto ss=TransitionProgressOutIn::create(1, JbfScene);
// 切换到帮助场景
Director::getInstance()->replaceScene(ss);
}
*/
#include "StartLayer.h"
#include "cocos2d.h"
#include "SimpleAudioEngine.h"
#include "extensions/cocos-ext.h"
//引用cocos2d名称空间
using namespace cocos2d;
bool StartLayer::soundB=true;
//实现初始化布景方法
bool StartLayer::init()
{
//调用父类的初始化方法
if ( !Layer::init() )
{
return false;
}
//获取可见区域的尺寸
Size visibleSize = Director::getInstance()->getVisibleSize();
// 创建一个精灵当作背景图片
loadingPic = Sprite::create("loading.jpg");
// 设置其位置
loadingPic->setPosition(visibleSize.width/2,visibleSize.height/2);
// 将其添加到布景中
this->addChild(loadingPic,0);
lPros = Label::createWithTTF("0%","FZKATJW.ttf",50);
lPros->setPosition(Point(270,480));
this->addChild(lPros,1);
initSound();
loadingTexturesAsync();
return true;
}
void StartLayer::loadingTexturesAsync()
{
// 将需要加载到图片储存在一个数组中
std::string sa[16]=
{
"ball_1.png","ball_2.png","ball_3.png","ball_4.png",
"ball_5.png","ball_6.png","ball_7.png","ball_8.png",
"frozen_1.png","frozen_2.png","frozen_3.png","frozen_4.png",
"frozen_5.png","frozen_6.png","frozen_7.png","frozen_8.png"
};
for(int i=0;i<16;i++)
{
Director::getInstance()->getTextureCache()->addImageAsync( //加载图片资源
sa[i], //图片资源路径
CC_CALLBACK_1(StartLayer::loadingCallBack, this) //加载完成时被回调的方法
);
}
}
void StartLayer::loadingCallBack(Texture2D* tt)//加载完成时被回调的方法
{
// 记录加载的图片资源的个数
jd=jd+1;
if(jd==16)
{// 如果加载完成
lPros->setString("100%");
this->removeChild(lPros);
// 获取可见区域的尺寸
Size visibleSize = Director::getInstance()->getVisibleSize();
// 删除加载时用作背景的精灵对象
this->removeChild(loadingPic);
// 创建一个精灵用于显示当前背景
Sprite* mainbg = Sprite::create("bg.png");
// 设置其位置
mainbg->setPosition(Point(visibleSize.width/2,visibleSize.height/2));
// 将其添加到布景中
this->addChild(mainbg,0);
Sprite* sppl = Sprite::create("menu_title.png");
sppl->setPosition(Point(270,800));
this->addChild(sppl,2);
ParticleSystemQuad* psq = ParticleSystemQuad::create("stars.plist");
psq->setBlendAdditive(true);
this->addChild(psq, 10);
psq->setPosition( Point( 270, 800) );
ParticleSystemQuad* psq1 = ParticleSystemQuad::create("point3.plist");
psq1->setBlendAdditive(true);
this->addChild(psq1, 10);
psq1->setPosition( Point( 449, 83) );
ParticleSystemQuad* psqp = ParticleSystemQuad::create("point.plist");
psqp->setBlendAdditive(true);
this->addChild(psqp, 10);
psqp->setPosition(Point( 100, 183));
// 创建一个开始菜单项
MenuItemImage* puzzle = MenuItemImage::create
(
"start.png", //正常图片
"startp.png", //按下时图片
CC_CALLBACK_0(StartLayer::startCallback, this) //点击被回调掉的方法
);
//设置其位置
puzzle->setPosition(Point(270,630));
//创建帮助菜单项
MenuItemImage* arcade = MenuItemImage::create(
"help.png", //正常图片
"helpp.png", //按下时的图片
CC_CALLBACK_0(StartLayer::helpCallback, this) //点击时被回调的方法
);
//设置其位置
arcade->setPosition(Point(270,530));
//创建帮助菜单项
MenuItemImage* jfb = MenuItemImage::create(
"board.png", //正常图片
"boardp.png", //按下时的图片
CC_CALLBACK_0(StartLayer::phbCallback, this) //点击时被回调的方法
);
//设置其位置
jfb->setPosition(Point(270,430));
//创建关于菜单项
MenuItemImage* aboutUS = MenuItemImage::create(
"aboutus.png", //正常图片
"aboutusp.png", //按下时的图片
CC_CALLBACK_0(StartLayer::aboutCallback, this) //按下时被回调的方法
);
//设置其位置
aboutUS->setPosition(Point(270,230));
Sprite* s = Sprite::create("yinxiao.png");
s->setPosition(Point(270,330));
this->addChild(s);
// 创建返回菜单项
soundon = MenuItemImage::create(
"yinyue.png", //正常图片
"jingyin.png", //按下图片
CC_CALLBACK_0(StartLayer::soundCallback, this) //被点击时回调的方法
);
//设置其位置
soundon->setPosition(Point(400,330));
soundon->setScale(0.5);
// 创建返回菜单项
soundoff = MenuItemImage::create(
"jingyin.png", //正常图片
"yinyue.png", //按下图片
CC_CALLBACK_0(StartLayer::soundCallback, this) //被点击时回调的方法
);
//设置其位置
soundoff->setPosition(Point(400,330));
soundoff->setScale(0.5);
//创建一个菜单对象
Menu* menu = Menu::create(puzzle,arcade,aboutUS,soundon,soundoff,jfb,NULL);
//设置其位置
menu->setPosition(Point::ZERO);
//将其添加到布景中
this->addChild(menu, 2);
if(soundB)
{
soundon->setVisible(true);
soundoff->setVisible(false);
}else{
soundon->setVisible(false);
soundoff->setVisible(true);
}
}else
{
lPros->setString(StringUtils::format("%d",100/16*jd)+"%");
}
}
void StartLayer::initSound()
{
CocosDenshion::SimpleAudioEngine::getInstance()->preloadEffect(
"shijian.mp3"
);
CocosDenshion::SimpleAudioEngine::getInstance()->preloadEffect(
"winp.mp3"
);
CocosDenshion::SimpleAudioEngine::getInstance()->preloadEffect(
"regame.mp3"
);
CocosDenshion::SimpleAudioEngine::getInstance()->preloadEffect( //º”‘ÿ“Ù–ß
"stickp.mp3"
);
CocosDenshion::SimpleAudioEngine::getInstance()->preloadEffect(
"hit.mp3"
);
CocosDenshion::SimpleAudioEngine::getInstance()->preloadEffect(
"explodeEffect.mp3"
);
CocosDenshion::SimpleAudioEngine::getInstance()->preloadEffect(
"caidanyin.mp3"
);
CocosDenshion::SimpleAudioEngine::getInstance()->preloadEffect(
"losep.mp3"
);
}
//点击开始游戏被回调的方法
void StartLayer::startCallback()
{
if(StartLayer::soundB)
{
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("caidanyin.mp3");
}
// 切换到选关界面
//sbsm->goGKScene();
}
//播放/暂停声音菜单被点击的回调方法
void StartLayer::soundCallback()
{
if(!StartLayer::soundB)
{
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("caidanyin.mp3");
}
if (soundB==true)
{//如果原本时播放声音,则此时将声音暂停
// 设置播放声音菜单不显示
soundon->setVisible(false);
// 设置关闭声音菜单显示
soundoff->setVisible(true);
暂停声音播放
// CocosDenshion::SimpleAudioEngine::getInstance()->pauseAllEffects();
CCLOG("startLayer====false");
}
else
{//播放声音
// 设置播放声音菜单为可见
soundon->setVisible(true);
// 设置暂停声音菜单为不可见
soundoff->setVisible(false);
// 播放声音
// CocosDenshion::SimpleAudioEngine::getInstance()->resumeAllEffects();
CCLOG("startLayer====true");
}
// 将声音的标志为设置为相反值
soundB=!soundB;
}
//帮助菜单被点击时回调的方法
void StartLayer::helpCallback()
{
if(StartLayer::soundB)
{
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("caidanyin.mp3");
}
// 切换到帮助场景
// sbsm->gohelpScene();
}
//关于菜单被点击时回调的方法
void StartLayer::aboutCallback()
{
if(StartLayer::soundB)
{
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("caidanyin.mp3");
}
// 切换到关于菜单场景
// sbsm->goAboutUSScene();
}void StartLayer::phbCallback()
{
if(StartLayer::soundB)
{
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("caidanyin.mp3");
}
// 切换到关于记分板场景
// sbsm->goJbfScene();
}
四、如果存在有库文件的错误,添加附加包含目录可以解决大部分错误
最后修改AppDelegate.cpp的内容,大小全部修改为540x960,不要问为什么,我也不知道,先瞎搞再说。
最终调试效果如下:
1.博客中标注原创的文章,版权归原作者 酒与花生米 所有;
2.未经原作者允许不得转载本文内容,否则将视为侵权;
3.转载或者引用本文内容请注明来源及原作者;
4.对于不遵守此声明或者其他违法使用本文内容者,本人依法保留追究权等。