Cocos2dx 3.2 横版过关游戏Brave学习笔记(一)

最近看了一下《http://cn.cocos2d-x.org/tutorial/show?id=1193》这个教程。当然这个游戏的名字叫做Brave

我不太懂lua,但感觉代码意思基本能看出来,就想用C++重新写一下这个示例,一方面了解一下lua,另一方面还可以熟悉一下用C++的开发。本人小白,免不了会犯些愚蠢的错误,不过犯了错只要能发现就是进步。

环境:
Cocos2dx 3.2
VS2012
Win32平台

资源及源码:
https://github.com/douxt/Brave_cpp (不包含cocos2d文件夹,大概4.3MB)
点击 Download Zip 即可下载。

强烈建议自己新建项目,可以避免一些版本相关的错误。

目录

http://www.cocoachina.com/bbs/read.php?tid=227226
http://www.cocoachina.com/bbs/read.php?tid=227229
http://www.cocoachina.com/bbs/read.php?tid=227305
http://www.cocoachina.com/bbs/read.php?tid=227328
http://www.cocoachina.com/bbs/read.php?tid=227522
http://www.cocoachina.com/bbs/read.php?tid=227643
http://www.cocoachina.com/bbs/read.php?tid=227702
http://www.cocoachina.com/bbs/read.php?tid=232616
完]

1.创建工程

打开命令行,输入:

cocos new -l cpp -d e:/projects/ Brave_cpp

这个命令会帮你创建一个新的HelloWorld工程,而且把整个cocos2d的源码给你拷了一份放在工程下面。

运行一下这个工程,什么,竟然报错了。果断关闭所有VS窗口,重新打开运行,发现竟然正常运行了。
将资源文件复制到Resource文件夹下面备用。
删除掉init中按钮,精灵,标签等代码,让程序变成只显示一个黑屏。

给游戏添加角色

添加背景:

加入代码,加完后init函数内容如下:

bool HelloWorld::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
    
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
   
    Sprite* background = Sprite::create("image/background.png");
    background->setPosition(origin + visibleSize/2);
    this->addChild(background);

    return true;
}
```


这样应该就可以显示出背景了。咦,Vec2类型竟然可以直接与Size类型相加?Size可以支持除法?这是怎么一回事呢?看一下Size源码,Size类定义了除法运算,Vec2难道定义了对Size的加法?不对,Vec2里没有关于Size的加法运算符。那就是Size可以自动转化成Vec2了?看到Size中有个如下的定义:
public:
    operator Vec2() const
    {
        return Vec2(width, height);
    }
```

精确的含义我没查到,不过应该可以理解为:如果有人把Size当作Vec2,就按这个方法给他一个Vec2.

冥冥之中自有天意,本来应该是一时的手误竟然背后还隐藏着道理……另外,Size还重载了=操作符,可以用Vec2给Size赋值。

导入精灵帧资源
继续在init函数中加入:
 SpriteFrameCache::getInstance()->addSpriteFramesWithFile("image/role.plist","image/role.pvr.ccz");
```


这个资源里包含了一些玩家、敌人动作的精灵帧,需要提前导入缓存。


显示玩家和怪物

玩家应该是一个类,可以继承自Sprite。原文中为Player建立了一个类,为Enemy1也建立了一个类,然后在后面出现Enemy2的时候又建立了一个类。
我觉得这几个类可以用一个类代替,因为他们属性十分类似,目前只是贴图不同,仅仅因为这个就建立这么多类不太划算。
添加的Player.h如下:
#ifndef __Player__
#define __Player__
#include "cocos2d.h"
USING_NS_CC;

class Player : public Sprite
{
public:
 enum PlayerType
 {
  PLAYER,
  ENEMY1,
  ENEMY2
 };

 bool initWithPlayerType(PlayerType type);

 static Player* create(PlayerType type);


};

#endif

```

目前先考虑三类角色,player , enemy1, enemy2。创建时,用枚举类型指定是哪一种。

Player.cpp 如下:
#include "Player.h"

bool Player::initWithPlayerType(PlayerType type)
{
 std::string spName = "";
 switch(type)
 {
 case PlayerType::PLAYER:
  spName = "player1-1-1.png";
  break;
 case PlayerType::ENEMY1:
  spName = "enemy1-1-1.png";
  break;
 case PlayerType::ENEMY2:
  spName = "enemy2-1-1.png";
  break;
 }
 this->initWithSpriteFrameName(spName);
 return true;
}


Player* Player::create(PlayerType type)
{
 Player* player = new Player();
 if(player && player->initWithPlayerType(type))
 {
  player->autorelease();
  return player;
 }
 else
 {
  delete player;
  player = NULL;
  return NULL;
 }
}
```


可以看出,其核心就是根据不同的角色类型,用不同的SpriteFrameName来初始化精灵。

继续在HelloWorld的init类中加入:

 Player* player = Player::create(Player::PlayerType::PLAYER);
 player->setPosition(origin.x + player->getContentSize().width/2, origin.y + visibleSize.height/2);
 this->addChild(player);

 Player* enemy1 = Player::create(Player::PlayerType::ENEMY1);
 enemy1->setPosition(origin.x + visibleSize.width - player->getContentSize().width/2, origin.y + visibleSize.height/2);
 this->addChild(enemy1);

```

运行程序,结果如下:
  




刚开始用git,发现项目目录下好多文件是不需要提交的,比如lib文件什么的。虽说可以靠只add需要的文件来实现,但系统总是有提示。
在项目目录下建立一个.gitignore文件,可以使其忽略没必要上传的文件。
例如:


```
*.
*.lib
*.sdf
*.opensdf
cocos2d/
.git*
proj.win32/Debug.win32/
proj.android/
proj.ios_mac/
proj.linux/
proj.wp8-xaml/
```


这样提交,上传就感觉顺多了。


下一篇:
 http://www.cocoachina.com/bbs/read.php?tid=227229

支持一下,本人也在学习,期待你C++的版本。

这个C++版本已经和原版教程进度差不多了,目前还在整理笔记。
谢谢支持!

顶楼主! :2: :2: :2: :2: :2:

谢谢哈,小白求指点。 :2:

大家共同努力! :2: :2:

为什么加载失败啊???

请问有没有把资源放到Resources下面?

在最后一步 为什么说我没有定义标识符Player 可是我其他步骤都和你一样都是对的

头文件包含了么……Player.h文件需要被包含到HelloWorldScene.h里

我认为用枚举去确定一个类的行为特性有点不太合适。如果杖举的数量多了,这些特性的行为(例如if…else…)会变得不容易维护。我觉得还是把类的公共行为特性抽取出来做一个抽象类,让不同的类去继承更容易维护

赞同:8::8::8::8::8::8::8::8::8::8::8::8::8::8::8::8::8:

为什么我源码编译有错呢,是在vs2013上的,

请问:这个在安卓实体机上可以运行不?