cocos2d-x 3.0制作2D横版格斗游戏-part1

2023-11-10 04:11

本文主要是介绍cocos2d-x 3.0制作2D横版格斗游戏-part1,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://codingnow.cn/cocos2d-x/1295.html


马上就要放假回家了,最近几天也比较闲,所以抽空来学习一下cocos2d-x 3.0,目前我使用的是最新版:cocos2d-x-3.0alpha1,开发环境为win7+vs2012。这个游戏demo是在网上看到的,觉得挺有意思,网上也已经有很多了文章和例子了,不过基本上都是用cocos2d-x较早的版本实现的,本文使用cocos2d-x 3.0重新实现了一遍。cocos2d-x 3.0更新了一些API,加入了c++ 11特性。我们将要学习精灵动作切换和保存、碰撞检测、简单的机器人AI、3.0新功能的使用等等,最终效果如下图:

项目源码:http://download.csdn.net/detail/zhoujianghai/6962541

废话少说,现在就开始吧。

 1. 创建项目
切换到tools\project-creator目录下,shift+右键,打开命令提示符窗口,输入:
python create_project.py -p PompaDroid -k com.alexzhou.pompadroid -l cpp
环境配置和项目创建可以参考 http://codingnow.cn/cocos2d-x/1285.html这篇博客。
项目目录如下图:
双击cocos2d-x-3.0\projects\PompaDroid\proj.win32\PompaDroid.sln,打开项目。
2. 下载游戏所需资源文件: http://download.csdn.net/detail/zhoujianghai/6880595
使用Tiled打开pd_tilemap.tmx,就可以看到游戏的整个地图:
根据地图,我们可以得到以下信息:
1.地图分成两层:Wall(墙)和Floor(地板),关闭每个层的透明度可以查看每层的构成。
2.每个瓦片都是32*32,地图瓦片数100×10(宽x高)。
3.从下往上数,前三行瓦片是可以行走的。
3. 添加地图
创建GameLayer类,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
GameLayer.h
class GameLayer : public cocos2d::Layer
{
public :
  GameLayer();
  ~GameLayer();
  virtual bool init();
  CREATE_FUNC(GameLayer);
private :
  cocos2d::TMXTiledMap *m_pTiledMap;
};
GameLayer.cpp
GameLayer::GameLayer()
  :m_pTiledMap(NULL)
{
}
GameLayer::~GameLayer()
{
}
bool GameLayer::init()
{
  bool ret = false ;
  do {
   CC_BREAK_IF( !Layer::init());
   m_pTiledMap = TMXTiledMap::create( "pd_tilemap.tmx" );
   this ->addChild(m_pTiledMap, -10);
   ret = true ;
  } while (0);
  return ret;
}

这里设置z-order的值为-10,可以设置为其他值,因为地图一般是显示在最底层,所以添加其他元素的时候可以设置z-order的值大于该值即可。
接着创建场景类GameScene:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
GameScene.h
class GameScene
{
public :
  static cocos2d::Scene* createScene();
};
GameScene.cpp
Scene* GameScene::createScene()
{
  auto scene = Scene::create();
  auto gameLayer = GameLayer::create();
  scene->addChild(gameLayer, 0);
  return scene;
}

然后修改AppDelegate.cpp的applicationDidFinishLaunching函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bool AppDelegate::applicationDidFinishLaunching() {
     // initialize director
     auto director = Director::getInstance();
     auto eglView = EGLView::getInstance();
     director->setOpenGLView(eglView);
  eglView->setDesignResolutionSize(480, 320, ResolutionPolicy::SHOW_ALL);
     // turn on display FPS
     director->setDisplayStats( false );
     // set FPS. the default value is 1.0/60 if you don't call this
     director->setAnimationInterval(1.0 / 60);
     // create a scene. it's an autorelease object
  auto scene = GameScene::createScene();
     // run
     director->runWithScene(scene);
     return true ;
}

setDesignResolutionSize这个设置资源分辨率尺寸,为了适配多个分辨率的。
因为这里资源分辨率是480×320,所以在main.cpp中设置宽高为480×320效果最好。
编译运行项目会看到地图已经显示出来了,效果如下:

现在地图上啥也没有,太单调了,那就创造一个英雄吧。

4. 添加英雄
英雄的资源文件是pd_sprites.pvr.ccz,可以使用TexturePacker打开,如下图:

英雄有5种状态:
1. 空闲(站着不动时)
2. 行走
3. 攻击
4. 被攻击
5. 死亡

每个状态都对应一组动画,因为英雄不可能同时处于多种状态下,所以我们要考虑的是如何实现状态切换,然后播放状态对应的动画。
这里当英雄处于空闲状态时,只能切换到行走、攻击、受伤状态,不会还没受伤就死亡了,当英雄死亡后,就不能切换到其他四种状态了。
创建BaseSprite类,作为精灵的基类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
BaseSprite.h
typedef enum {
  ACTION_STATE_NONE = 0,
  ACTION_STATE_IDLE,
  ACTION_STATE_WALK,
  ACTION_STATE_ATTACK,
  ACTION_STATE_HURT,
  ACTION_STATE_DEAD
}ActionState;
class BaseSprite : public cocos2d::Sprite
{
public :
  BaseSprite();
  ~BaseSprite();
  void runIdleAction();
  void runWalkAction();
  void runAttackAction();
  void runHurtAction();
  void runDeadAction();
  CC_SYNTHESIZE_RETAIN(cocos2d::Action*, m_pIdleAction, IdleAction);
  CC_SYNTHESIZE_RETAIN(cocos2d::Action*, m_pWalkAction, WalkAction);
  CC_SYNTHESIZE_RETAIN(cocos2d::Action*, m_pAttackAction, AttackAction);
  CC_SYNTHESIZE_RETAIN(cocos2d::Action*, m_pHurtAction, HurtAction);
  CC_SYNTHESIZE_RETAIN(cocos2d::Action*, m_pDeadAction, DeadAction);
  CC_SYNTHESIZE(ActionState, m_currActionState, CurrActionState);
  cocos2d::CallFunc* createIdleCallbackFunc();
protected :
  static cocos2d::Animation* createAnimation( const char * formatStr, int frameCount, int fps);
private :
  bool changeState(ActionState actionState);
};
BaseSprite.cpp
BaseSprite::BaseSprite():
  m_pIdleAction(NULL),
  m_pWalkAction(NULL),
  m_pAttackAction(NULL),
  m_pHurtAction(NULL),
  m_pDeadAction(NULL),
  m_currActionState(ACTION_STATE_NONE)
{
}
BaseSprite::~BaseSprite()
{
  CC_SAFE_RELEASE_NULL(m_pIdleAction);
  CC_SAFE_RELEASE_NULL(m_pWalkAction);
  CC_SAFE_RELEASE_NULL(m_pAttackAction);
  CC_SAFE_RELEASE_NULL(m_pHurtAction);
  CC_SAFE_RELEASE_NULL(m_pDeadAction);
}
void BaseSprite::runIdleAction()
{
  if (changeState(ACTION_STATE_IDLE))
  {
   this ->runAction(m_pIdleAction);
  }
}
void BaseSprite::runWalkAction()
{
  if (changeState(ACTION_STATE_WALK))
  {
   this ->runAction(m_pWalkAction);
  }
}
void BaseSprite::runAttackAction()
{
  if (changeState(ACTION_STATE_ATTACK))
  {
   this ->runAction(m_pAttackAction);
  }
}
void BaseSprite::runHurtAction()
{
  if (changeState(ACTION_STATE_HURT))
  {
   this ->runAction(m_pHurtAction);
  }
}
void BaseSprite::runDeadAction()
{
  if (changeState(ACTION_STATE_DEAD))
  {
   this ->runAction(m_pDeadAction);
  }
}
Animation* BaseSprite::createAnimation( const char * formatStr, int frameCount, int fps)
{
  Array *pFrames = Array::createWithCapacity(frameCount);
  for ( int i = 0; i < frameCount; ++ i)
  {
   const char * imgName = String::createWithFormat(formatStr, i)->getCString();
   SpriteFrame *pFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName(imgName);
   pFrames->addObject(pFrame);
  }
  return Animation::createWithSpriteFrames(pFrames, 1.0f / fps);
}
bool BaseSprite::changeState(ActionState actionState)
{
  if (m_currActionState == ACTION_STATE_DEAD || m_currActionState == actionState)
  {
   return false ;
  }
  this ->stopAllActions();
  this ->m_currActionState = actionState;
  return true ;
}
CallFunc* BaseSprite::createIdleCallbackFunc()
{
  return CallFunc::create(CC_CALLBACK_0(BaseSprite::runIdleAction, this ));
}

ActionState枚举表示精灵的各种状态,runXXXAction表示切换状态以及播放各状态对应的动画。变量m_currActionState表示当前精灵的状态。createIdleCallbackFunc函数后面需要用到,表示当精灵切换到攻击或者受伤状态后立即回到空闲状态。createAnimation函数是一个工具函数,根据图片路径、帧数、每秒显示的帧数来创建动画。changeState函数就是状态切换函数,当精灵死亡的时候就GameOver了。
现在该创建咱们的英雄类Hero了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Hero.h
class Hero : public BaseSprite
{
public :
  Hero();
  ~Hero();
  bool init();
  CREATE_FUNC(Hero);
};
Hero.cpp
Hero::Hero()
{}
Hero::~Hero()
{}
bool Hero::init()
{
  bool ret = false ;
  do {
   CC_BREAK_IF( ! this ->initWithSpriteFrameName( "hero_idle_00.png" ) );
   Animation *pIdleAnim = this ->createAnimation( "hero_idle_%02d.png" , 6, 12);
   this ->setIdleAction(RepeatForever::create(Animate::create(pIdleAnim)));
   Animation *pWalkAnim = this ->createAnimation( "hero_walk_%02d.png" , 7, 14);
   this ->setWalkAction(RepeatForever::create(Animate::create(pWalkAnim)));
   Animation *pAttackAnim = this ->createAnimation( "hero_attack_00_%02d.png" , 3, 20);
   this ->setAttackAction(Sequence::create(Animate::create(pAttackAnim), BaseSprite::createIdleCallbackFunc(), NULL));
   Animation *pHurtAnim = this ->createAnimation( "hero_hurt_%02d.png" , 3, 12);
   this ->setHurtAction(Sequence::create(Animate::create(pHurtAnim), BaseSprite::createIdleCallbackFunc(), NULL));
   Animation *pDeadAnim = this ->createAnimation( "hero_knockout_%02d.png" , 5, 12);
   this ->setDeadAction(Sequence::create(Animate::create(pDeadAnim), Blink::create(3, 9), NULL));
   ret = true ;
  } while (0);
  return ret;
}

Hero类比较简单,就是初始化各种动作。
我们来修改GameLayer类,加载精灵图片所需的资源。
在GameLayer.h中添加:

1
2
3
4
5
6
CC_SYNTHESIZE_READONLY(Hero*, m_pHero, Hero);
  float m_fScreenWidth;
  float m_fScreenHeight;
  cocos2d::Point m_origin;
  cocos2d::SpriteBatchNode *m_pSpriteNodes;

在GameLayer.cpp的init函数中添加:

1
2
3
4
5
6
7
8
9
10
11
12
auto visibleSize = Director::getInstance()->getVisibleSize();
   this ->m_origin = Director::getInstance()->getVisibleOrigin();
   this ->m_fScreenWidth = visibleSize.width;
   this ->m_fScreenHeight = visibleSize.height;
   SpriteFrameCache::getInstance()->addSpriteFramesWithFile( "pd_sprites.plist" );
   m_pSpriteNodes = SpriteBatchNode::create( "pd_sprites.pvr.ccz" );
   this ->addChild(m_pSpriteNodes);
   m_pHero = Hero::create();
   m_pHero->setPosition( m_origin + Point(100, 100) );
   m_pHero->runIdleAction();
   m_pHero->setZOrder(m_fScreenHeight - m_pHero->getPositionY());
   m_pSpriteNodes->addChild(m_pHero);

这里添加了一个英雄,然后切换到空闲状态,设置ZOrder值跟Y坐标相关,这样后期可以解决英雄和怪物的遮挡问题,关于SpriteFrameCache和SpriteBatchNode这里就不介绍了,不明白的可以查看http://codingnow.cn/cocos2d-x/795.html
现在编译运行项目,就可以看到一个骚包在屏幕上晃来晃去了:

ok,这篇就到此为止吧,文章太长会让人看着累。下一篇来实现控制英雄,让英雄动起来。

 

参考资料:

http://www.raywenderlich.com/24452/how-to-make-a-side-scrolling-beat-em-up-game-like-scott-pilgrim-with-cocos2d-part-2

http://www.raywenderlich.com/24155/how-to-make-a-side-scrolling-beat-em-up-game-like-scott-pilgrim-with-cocos2d-part-1

http://philon.cn/post/cocos2d-x-3.0-zhi-zuo-heng-ban-ge-dou-you-xi


这篇关于cocos2d-x 3.0制作2D横版格斗游戏-part1的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/380327

相关文章

4B参数秒杀GPT-3.5:MiniCPM 3.0惊艳登场!

​ 面壁智能 在 AI 的世界里,总有那么几个时刻让人惊叹不已。面壁智能推出的 MiniCPM 3.0,这个仅有4B参数的"小钢炮",正在以惊人的实力挑战着 GPT-3.5 这个曾经的AI巨人。 MiniCPM 3.0 MiniCPM 3.0 MiniCPM 3.0 目前的主要功能有: 长上下文功能:原生支持 32k 上下文长度,性能完美。我们引入了

用Unity2D制作一个人物,实现移动、跳起、人物静止和动起来时的动画:中(人物移动、跳起、静止动作)

上回我们学到创建一个地形和一个人物,今天我们实现一下人物实现移动和跳起,依次点击,我们准备创建一个C#文件 创建好我们点击进去,就会跳转到我们的Vision Studio,然后输入这些代码 using UnityEngine;public class Move : MonoBehaviour // 定义一个名为Move的类,继承自MonoBehaviour{private Rigidbo

OpenStack离线Train版安装系列—0制作yum源

本系列文章包含从OpenStack离线源制作到完成OpenStack安装的全部过程。 在本系列教程中使用的OpenStack的安装版本为第20个版本Train(简称T版本),2020年5月13日,OpenStack社区发布了第21个版本Ussuri(简称U版本)。 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版

OpenStack镜像制作系列5—Linux镜像

本系列文章主要对如何制作OpenStack镜像的过程进行描述记录 CSDN:OpenStack镜像制作教程指导(全) OpenStack镜像制作系列1—环境准备 OpenStack镜像制作系列2—Windows7镜像 OpenStack镜像制作系列3—Windows10镜像 OpenStack镜像制作系列4—Windows Server2019镜像 OpenStack镜像制作

OpenStack镜像制作系列4—Windows Server2019镜像

本系列文章主要对如何制作OpenStack镜像的过程进行描述记录  CSDN:OpenStack镜像制作教程指导(全) OpenStack镜像制作系列1—环境准备 OpenStack镜像制作系列2—Windows7镜像 OpenStack镜像制作系列3—Windows10镜像 OpenStack镜像制作系列4—Windows Server2019镜像 OpenStack镜像制作系

OpenStack镜像制作系列2—Windows7镜像

本系列文章主要对如何制作OpenStack镜像的过程进行描述记录 CSDN:OpenStack镜像制作教程指导(全) OpenStack镜像制作系列1—环境准备 OpenStack镜像制作系列2—Windows7镜像 OpenStack镜像制作系列3—Windows10镜像 OpenStack镜像制作系列4—Windows Server2019镜像 OpenStack镜像制作系列

OpenStack镜像制作系列1—环境准备

本系列文章主要对如何制作OpenStack镜像的过程进行描述记录 CSDN:OpenStack镜像制作教程指导(全) OpenStack镜像制作系列1—环境准备 OpenStack镜像制作系列2—Windows7镜像 OpenStack镜像制作系列3—Windows10镜像 OpenStack镜像制作系列4—Windows Server2019镜像 OpenStack镜像制作

CSDN:OpenStack镜像制作教程指导(全)

本系列文章主要对如何制作OpenStack镜像的过程进行描述记录,涉及基本环境准备、常见类型操作系统的镜像制作。 让你可以从零开始安装一个操作系统,并支持个性化制作OpenStack镜像。 CSDN:OpenStack镜像制作教程指导(全) OpenStack镜像制作系列1—环境准备 OpenStack镜像制作系列2—Windows7镜像 OpenStack镜像制作系列3—Windows

Cmake之3.0版本重要特性及用法实例(十三)

简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏: 多媒体系统工程师系列【原创干货持续更新中……】🚀 优质视频课程:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧

docker学习系列(四)制作基础的base项目镜像--jdk+tomcat

前面已经完成了docker的安装以及使用,现在我们要将自己的javaweb项目与docker结合 1.1准备jdk+tomcat软件 ​​我下载了apache-tomcat-7.0.68.tar.gz和jdk-7u79-linux-x64.tar.gz,存储于Linux机器的本地目录/usr/ect/wt/下(利用xshell上传)。利用linux命令 tar -zxvf apache-tom