怎样制作一个横版格斗过关游戏 Cocos2d-x 2.0.4
本文实践自 Allen Tan 的文章《How To Make A Side-Scrolling
Beat ‘Em Up Game Like Scott Pilgrim with Cocos2D – Part 1》,文中使用Cocos2D,我在这里使用Cocos2D-x 2.0.4进行学习和移植。
在这篇文章。将会学习到怎样制作一个简单的横版格斗过关游戏。在这其中,学习怎样跟踪动画状态、碰撞盒、加入方向键、加入简单敌人AI和很多其他其他的。
过程例如以下:
1.新建Cocos2d-win32project,project名为"PompaDroid",去除"Box2D"选项,勾选"Simple Audio Engine in Cocos Denshion"选项。
2.加入游戏场景类GameScene,派生自CCScene类。加入GameLayer类和HudLayer类,派生自CCLayer类。
删除HelloWorldScene.h和HelloWorldScene.cpp文件。
3.文件GameScene.h代码例如以下:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#pragma once
#include "cocos2d.h" #include "GameLayer.h" #include "HudLayer.h" class GameScene : public cocos2d::CCScene { public: GameScene(void); ~GameScene(void); virtual bool init(); CREATE_FUNC(GameScene); CC_SYNTHESIZE(GameLayer*, _gameLayer, GameLayer); CC_SYNTHESIZE(HudLayer*, _hudLayer, HudLayer); }; |
文件GameScene.cpp代码例如以下:
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 |
#include "GameScene.h"
using namespace cocos2d; GameScene::GameScene(void) { _gameLayer = NULL; _hudLayer = NULL; } GameScene::~GameScene(void) { } bool GameScene::init() { bool bRet = false; do { CC_BREAK_IF(!CCScene::init()); _gameLayer = GameLayer::create(); ); _hudLayer = HudLayer::create(); ); bRet = true; } ); return bRet; } |
4.HudLayer类添加一个方法:
1
|
CREATE_FUNC(HudLayer);
|
和GameLayer类添加一个方法:
1
|
CREATE_FUNC(GameLayer);
|
5.改动AppDelegate.cpp文件。代码例如以下:
1
2 3 4 5 6 7 8 9 10 11 12 13 |
//#include "HelloWorldScene.h"
#include "GameScene.h" bool AppDelegate::applicationDidFinishLaunching() { //... // create a scene. it's an autorelease object //CCScene *pScene = HelloWorld::scene(); CCScene *pScene = GameScene::create(); //... } |
6.编译执行,此时仅仅是空空的界面。
7.下载本游戏所需资源。将资源放置"Resources"文件夹下;
8.用Tiled工具打开pd_tilemap.tmx。就能够看到游戏的整个地图:
地图上有两个图层:Wall和Floor,即墙和地板。去掉每一个图层前的打钩,能够查看层的组成。你会发现下数第四行是由两个图层一起组成的。每一个tile都是32x32大小。可行走的地板tile位于下数三行。
9.打开GameLayer.h文件,加入例如以下代码:
1
2 3 4 |
bool init();
void initTileMap(); cocos2d::CCTMXTiledMap *_tileMap; |
打开GameLayer.cpp,在构造函数,加入例如以下代码:
1
|
_tileMap = NULL;
|
加入例如以下代码:
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 |
bool GameLayer::init()
{ bool bRet = false; do { CC_BREAK_IF(!CCLayer::init()); this->initTileMap(); bRet = true; } ); return bRet; } void GameLayer::initTileMap() { _tileMap = CCTMXTiledMap::create("pd_tilemap.tmx"); CCObject *pObject = NULL; CCARRAY_FOREACH(_tileMap->getChildren(), pObject) { CCTMXLayer *child = (CCTMXLayer*)pObject; child->getTexture()->setAliasTexParameters(); } ); } |
对全部图层进行setAliasTexParameters设置,该方法是关闭抗锯齿功能,这样就能保持像素风格。
10.编译执行,能够看到地图显示在屏幕上。例如以下图所看到的:
11.创建英雄。
在大多数2D横版游戏中,角色有不同的动画代表不同类型的动作。
我们须要知道什么时候播放哪个动画。
这里採用状态机来解决问题。状态机就是某种通过切换状态来改变行为的东西。单一状态机在同一时间仅仅能有一个状态,但能够从一种状态过渡到还有一种状态。在这个游戏中。角色共同拥有五种状态,空暇、行走、出拳、受伤、死亡,例如以下图所看到的:
为了有一个完整的状态流,每一个状态应该有一个必要条件和结果。
比如:行走状态不能突然转变到死亡状态,由于你的英雄在死亡前必须先受伤。
12.加入ActionSprite类,派生自CCSprite类,ActionSprite.h文件代码例如以下:
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 |
#pragma once
#include "cocos2d.h" #include "Defines.h" class ActionSprite : public cocos2d::CCSprite { public: ActionSprite(void); ~ActionSprite(void); //action methods void idle(); void attack(); void hurtWithDamage(float damage); void knockout(); void walkWithDirection(cocos2d::CCPoint direction); //scheduled methods void update(float dt); //actions CC_SYNTHESIZE_RETAIN(cocos2d::CCAction*, _idleAction, IdleAction); CC_SYNTHESIZE_RETAIN(cocos2d::CCAction*, _attackAction, AttackAction); CC_SYNTHESIZE_RETAIN(cocos2d::CCAction*, _walkAction, WalkAction); CC_SYNTHESIZE_RETAIN(cocos2d::CCAction*, _hurtAction, HurtAction); CC_SYNTHESIZE_RETAIN(cocos2d::CCAction*, _knockedOutAction, KnockedOutAction); //states CC_SYNTHESIZE(ActionState, _actionState, ActionState); //attributes CC_SYNTHESIZE(float, _walkSpeed, WalkSpeed); CC_SYNTHESIZE(float, _hitPoints, HitPoints); CC_SYNTHESIZE(float, _damage, Damage); //movement CC_SYNTHESIZE(cocos2d::CCPoint, _velocity, Velocity); CC_SYNTHESIZE(cocos2d::CCPoint, _desiredPosition, DesiredPosition); //measurements CC_SYNTHESIZE(float, _centerToSides, CenterToSides); CC_SYNTHESIZE(float, _centerToBottom, CenterToBottom); }; |
打开ActionSprite.cpp文件,构造函数例如以下:
1
2 3 4 5 6 7 8 |
ActionSprite::ActionSprite(void)
{ _idleAction = NULL; _attackAction = NULL; _walkAction = NULL; _hurtAction = NULL; _knockedOutAction = NULL; } |
各个方法实现临时为空。以上代码声明了基本变量和方法,能够分为下面几类:
- Actions:这些是每种状态要运行的动作。
这些动作是当角色切换状态时,运行精灵动画和其它触发的事件。
States:保存精灵的当前动作/状态。使用ActionState类型。这个类型待会我们将会进行定义。
Attributes:包括精灵行走速度值,受伤时降低生命点值。攻击伤害值。
Movement:用于计算精灵怎样沿着地图移动。
Measurements:保存对精灵的实际图像实用的測量值。须要这些值,是由于你将要使用的这些精灵画布大小是远远大于内部包括的图像。Action methods:不直接调用动作。而是使用这些方法触发每种状态。
Scheduled methods:不论什么事须要在一定的时间间隔进行执行,比方精灵位置和速度的更新,等等。
新建一个头文件Defines.h。代码例如以下:
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 |
#pragma once
#include "cocos2d.h" // 1 - convenience measurements #define SCREEN CCDirector::sharedDirector()->getWinSize() , SCREEN.height / ) #define CURTIME do { \ timeval time; \ gettimeofday(&time, NULL); \ ) + (time.tv_usec / ); \ return (float)millisecs; \ } ) // 2 - convenience functions )) + low #define frandom (float)rand() / UINT64_C(0x100000000) #define frandom_range(low, high) ((high - low) * frandom) + low // 3 - enumerations typedef enum _ActionState { kActionStateNone = , kActionStateIdle, kActionStateAttack, kActionStateWalk, kActionStateHurt, kActionStateKnockedOut } ActionState; // 4 - structures typedef struct _BoundingBox { cocos2d::CCRect actual; cocos2d::CCRect original; } BoundingBox; |
简要说明下:
①.定义了一些便利的宏,如直接使用SCREEN获取屏幕大小;
②.定义了一些便利的函数,随机返回整型或者浮点型;
③.定义ActionState类型,这个是ActionSprite可能处在不同状态的类型枚举;
④.定义BoundingBox结构体。将用于碰撞检測。
打开GameLayer.h文件。加入例如以下代码:
1
|
cocos2d::CCSpriteBatchNode *_actors;
|
打开GameLayer.cpp文件。在init函数里面加入例如以下代码:
1
2 3 4 |
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("pd_sprites.plist");
_actors = CCSpriteBatchNode::create("pd_sprites.pvr.ccz"); _actors->getTexture()->setAliasTexParameters(); ); |
载入精灵表单,创建一个CCSpriteBatchNode。这个精灵表单包括我们的全部精灵。它的z值高于CCTMXTiledMap对象。这样才干出如今地图前。
加入Hero类,派生自ActionSprite类,加入例如以下代码:
1
2 |
CREATE_FUNC(Hero);
bool init(); |
Hero类的init函数的实现例如以下所看到的:
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 |
bool Hero::init()
{ bool bRet = false; do { CC_BREAK_IF(!ActionSprite::initWithSpriteFrameName("hero_idle_00.png")); int i; //idle animation CCArray *idleFrames = CCArray::createWithCapacity(); ; i < ; i++) { CCSpriteFrame *frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(CCString::createWithFormat("hero_idle_%02d.png", i)->getCString()); idleFrames->addObject(frame); } CCAnimation *idleAnimation = CCAnimation::createWithSpriteFrames(idleFrames, . / .); this->setIdleAction(CCRepeatForever::create(CCAnimate::create(idleAnimation))); .); .); .); .); .); bRet = true; } ); return bRet; } |
我们用初始空暇精灵帧创建了英雄角色,配备了一个CCArray数组包括全部的属于空暇动画的精灵帧,然后创建一个CCAction动作播放来这个动画。以每秒12帧的速率进行播放。接下去,为英雄设置初始属性,包括精灵中心到边究竟部的值。例如以下图所看到的:
英雄的每一个精灵帧都在280x150像素大小的画布上创建,但实际上英雄精灵仅仅占领这个空间的一部分。所以须要两个測量值,以便更好的设置精灵的位置。须要额外的空间,是由于每一个动画精灵绘制的方式是不同的,而有些就须要很多其它的空间。
打开GameLayer.h文件,加入头文件声明:
1
|
#include "Hero.h"
|
GameLayer类加入例如以下代码:
1
|
Hero *_hero;
|
打开GameLayer.cpp文件,在构造函数加入例如以下代码:
1
|
_hero = NULL;
|
在init函数this->addChild(_actors,
-5);后面加入例如以下代码:
1
|
this->initHero();
|
加入initHero方法,代码例如以下:
1
2 3 4 5 6 7 8 |
void GameLayer::initHero()
{ _hero = Hero::create(); _actors->addChild(_hero); _hero->setPosition(ccp(_hero->getCenterToSides(), )); _hero->setDesiredPosition(_hero->getPosition()); _hero->idle(); } |
创建了一个英雄实例,加入到了精灵表单,并设置了设置。调用idle方法。让其处于空暇状态,执行空暇动画。返回到ActionSprite.cpp文件,实现idle方法。代码例如以下:
1
2 3 4 5 6 7 8 9 10 |
void ActionSprite::idle()
{ if (_actionState != kActionStateIdle) { this->stopAllActions(); this->runAction(_idleAction); _actionState = kActionStateIdle; _velocity = CCPointZero; } } |
这个idle方法仅仅有当ActionSprite不处于空暇状态才干调用。当它触发时,它会运行空暇动作,改变当前状态到kActionStateIdle,而且把速度置零。
13.编译执行,能够看到英雄处于空暇状态。
例如以下图所看到的:
14.出拳动作。打开Hero.cpp文件,在init函数idle
animation后面,加入例如以下代码:
1
2 3 4 5 6 7 8 9 |
//attack animation
CCArray *attackFrames = CCArray::createWithCapacity(); ; i < ; i++) { CCSpriteFrame *frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(CCString::createWithFormat("hero_attack_00_%02d.png", i)->getCString()); attackFrames->addObject(frame); } CCAnimation *attackAnimation = CCAnimation::createWithSpriteFrames(attackFrames, . / .); this->setAttackAction(CCSequence::create(CCAnimate::create(attackAnimation), CCCallFunc::create(this, callfunc_selector(Hero::idle)), NULL)); |
打开ActionSprite.cpp文件,实现attack方法,代码例如以下:
1
2 3 4 5 6 7 8 9 |
void ActionSprite::attack()
{ if (_actionState == kActionStateIdle || _actionState == kActionStateAttack || _actionState == kActionStateWalk) { this->stopAllActions(); this->runAction(_attackAction); _actionState = kActionStateAttack; } } |
英雄仅仅有在空暇、攻击、行走状态才干进行出拳。确保英雄正在受伤时、或者死亡时不能进行攻击。为了触发attack方法,打开GameLayer.cpp文件,在init函数加入例如以下代码:
1
|
this->setTouchEnabled(true);
|
重载ccTouchesBegan方法,代码例如以下:
1
2 3 4 |
void GameLayer::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)
{ _hero->attack(); } |
15.编译执行。点击屏幕进行出拳。例如以下图所看到的:
16.创建8个方向的方向键。
我们须要创建虚拟的8个方向的方向键来让英雄在地图上进行移动。
加入SimpleDPad类,派生自CCSprite类,SimpleDPad.h文件代码例如以下:
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 |
#pragma once
#include "cocos2d.h" class SimpleDPad; class SimpleDPadDelegate { public: ; ; ; }; class SimpleDPad : public cocos2d::CCSprite, public cocos2d::CCTargetedTouchDelegate { public: SimpleDPad(void); ~SimpleDPad(void); static SimpleDPad* dPadWithFile(cocos2d::CCString *fileName, float radius); bool initWithFile(cocos2d::CCString *filename, float radius); void onEnterTransitionDidFinish(); void onExit(); void update(float dt); virtual bool ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent); virtual void ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent); virtual void ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent); void updateDirectionForTouchLocation(cocos2d::CCPoint location); CC_SYNTHESIZE(SimpleDPadDelegate*, _delegate, Delegate); CC_SYNTHESIZE(bool, _isHeld, IsHeld); protected: float _radius; cocos2d::CCPoint _direction; }; |
对以上的一些声明。解释例如以下:
- radius:圆形方向键的半径。
direction:当前所按下的方向。这是一个矢量。(-1.0, -1.0)是左下方向,(1.0, 1.0)是右上方向。
delegate:方向键的托付,兴许进行介绍。
isHeld:布尔值表示玩家触摸着方向键。
对于SimpleDPad类,使用了托付模式。意味着一个托付类(并不是SimpleDPad),将会处理由被托付类(SimpleDPad)启动的任务。在某些你指定的点上,主要是当涉及到处理不论什么游戏相关的东西。SimpleDPad将会将职责传递给托付类。这使得SimpleDPad无需知道不论什么游戏逻辑,从而同意你在开发不论什么其它游戏时,能够进行重用。
例如以下图所看到的:
当SimpleDPad检測到在方向键内的触摸,它会计算触摸的方向,然后发送消息到托付类指明方向。在这之后的不论什么事情都不是SimpleDPad所关心的了。为了实施这个模式。SimpleDPad须要至少了解其托付的有关信息。特别是将触摸方向传递给托付的方法。
这是还有一种设计模式:协议。
能够看到SimpleDPad的托付定义了所需的方法。在这样的方式中,SimpleDPad强制其托付有三个指定的方法,以便确保每当它想传递东西放到托付中时,它能调用这些方法中的不论什么一种。其实,SimpleDPad也遵循一种协议,即CCTargetedTouchDelegate。当SimpleDPad被触摸时,进行处理触摸事件,而GameLayer将不会得到触摸。
否则的话,在触摸方向键的时候,英雄就会出拳攻击,显然。这不是希望看到的。打开SimpleDPad.cpp文件。加入例如以下代码:
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 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
#include "SimpleDPad.h"
using namespace cocos2d; SimpleDPad::SimpleDPad(void) { _delegate = NULL; } SimpleDPad::~SimpleDPad(void) { } SimpleDPad* SimpleDPad::dPadWithFile(CCString *fileName, float radius) { SimpleDPad *pRet = new SimpleDPad(); if (pRet && pRet->initWithFile(fileName, radius)) { return pRet; } else { delete pRet; pRet = NULL; return NULL; } } bool SimpleDPad::initWithFile(CCString *filename, float radius) { bool bRet = false; do { CC_BREAK_IF(!CCSprite::initWithFile(filename->getCString())); _radius = radius; _direction = CCPointZero; _isHeld = false; this->scheduleUpdate(); bRet = true; } ); return bRet; } void SimpleDPad::onEnterTransitionDidFinish() { CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(, true); } void SimpleDPad::onExit() { CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this); } void SimpleDPad::update(float dt) { if (_isHeld) { _delegate->isHoldingDirection(this, _direction); } } bool SimpleDPad::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) { CCPoint location = pTouch->getLocation(); float distanceSQ = ccpDistanceSQ(location, this->getPosition()); if (distanceSQ <= _radius * _radius) { this->updateDirectionForTouchLocation(location); _isHeld = true; return true; } return false; } void SimpleDPad::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) { CCPoint location = pTouch->getLocation(); this->updateDirectionForTouchLocation(location); } void SimpleDPad::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) { _direction = CCPointZero; _isHeld = false; _delegate->simpleDPadTouchEnded(this); } void SimpleDPad::updateDirectionForTouchLocation(CCPoint location) { float radians = ccpToAngle(ccpSub(location, this->getPosition())); * CC_RADIANS_TO_DEGREES(radians); . && degrees >= -.) { //right _direction = ccp(., .); } . && degrees < .) { //bottomright _direction = ccp(., -.); } . && degrees <= .) { //bottom _direction = ccp(., -.); } . && degrees < .) { //bottomleft _direction = ccp(-., -.); } . || degrees <= -.) { //left _direction = ccp(-., .); } . && degrees > -.) { //topright _direction = ccp(., .); } . && degrees >= -.) { //top _direction = ccp(., .); } . && degrees > -.) { //topleft _direction = ccp(-., .); } _delegate->didChangeDirectionTo(this, _direction); } |
以上方法中,onEnterTransitionDidFinish注冊SimpleDPad托付类,onExit移除SimpleDPad托付类,update方法是当方向键被触摸时,传递方向值到托付类。ccTouchBegan方法检測触摸位置是否在方向键圆内。假设是,则将isHeld置为true。并更新方向值。返回true以拥有触摸事件优先权。ccTouchMoved当触摸点移动时。更新方向值。
ccTouchEnded将isHeld置为false。重置方向,并通知托付触摸结束。
updateDirectionForTouchLocation方法计算触摸点到方向键中心距离值,转换成角度,得到正确的方向值,然后传递值到托付。
打开HudLayer.h文件。加入头文件声明:
1
|
#include "SimpleDPad.h"
|
加入例如以下代码:
1
2 |
bool init();
CC_SYNTHESIZE(SimpleDPad*, _dPad, DPad); |
打开HudLayer.cpp文件,加入例如以下代码:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
HudLayer::HudLayer(void)
{ _dPad = NULL; } bool HudLayer::init() { bool bRet = false; do { CC_BREAK_IF(!CCLayer::init()); _dPad = SimpleDPad::dPadWithFile(CCString::create(); _dPad->setPosition(ccp(., .)); _dPad->setOpacity(); this->addChild(_dPad); bRet = true; } ); return bRet; } |
以上代码实例化SimpleDPad,而且加入到HudLayer上。如今GameScene同一时候控制GameLayer和HudLayer,但有时候想直接通过HudLayer訪问GameLayer。打开GameLayer.h文件,加入头文件声明:
1
2 |
#include "SimpleDPad.h"
#include "HudLayer.h" |
将GameLayer类声明改动成例如以下:
1
|
class GameLayer : public cocos2d::CCLayer, public SimpleDPadDelegate
|
并加入下面声明:
1
2 3 4 5 |
virtual void didChangeDirectionTo(SimpleDPad *simpleDPad, cocos2d::CCPoint direction);
virtual void isHoldingDirection(SimpleDPad *simpleDPad, cocos2d::CCPoint direction); virtual void simpleDPadTouchEnded(SimpleDPad *simpleDPad); CC_SYNTHESIZE(HudLayer*, _hud, Hud); |
以上方法的实现临时为空。
这样我们就在GameLayer中加入了HudLayer的引用,同一时候还让GameLayer遵循SimpleDPad所创建的协议。打开GameScene.cpp文件,在init函数this->addChild(_hudLayer,
1);后面,加入例如以下代码:
1
2 |
_hudLayer->getDPad()->setDelegate(_gameLayer);
_gameLayer->setHud(_hudLayer); |
17.编译执行,能够看到左下角的虚拟方向键,例如以下图所看到的:
别试着压下方向键,英雄不会有不论什么反应。由于还未实现协议方法,这在第二部分将完毕。
參考资料:
1.How To Make A Side-Scrolling Beat ‘Em Up Game Like Scott Pilgrim with Cocos2D – Part 1http://www.raywenderlich.com/24155/how-to-make-a-side-scrolling
2.怎样使用cocos2d制作类似Scott Pilgrim的2D横版格斗过关游戏part1(翻译) http://blog.sina.com.cn/s/blog_4b55f6860101a9b7.html
3.怎样使用Cocos2d-x做一DNF类的游戏-part1 http://blog.csdn.net/jyzgo/article/details/8471306
很感谢以上资料,本样例源码附加资源下载地址:http://download.csdn.net/detail/akof1314/5038013
如文章存在错误之处。欢迎指出,以便改正。
怎样制作一个横版格斗过关游戏 Cocos2d-x 2.0.4的更多相关文章
- 《Genesis-3D开源游戏引擎--横版格斗游戏制作教程:简介及目录》(附上完整工程文件)
介绍:讲述如何使用Genesis-3D来制作一个横版格斗游戏,涉及如何制作连招系统,如何使用包围盒实现碰撞检测,软键盘的制作,场景切换,技能读表,简单怪物AI等等,并为您提供这个框架的全套资源,源码以 ...
- Beat 'Em Up Game Starter Kit (横版格斗游戏) cocos2d-x游戏源代码
浓缩精华.专注战斗! 游戏的本质是什么?界面?养成?NoNo! 游戏来源于对实战和比赛的模拟,所以它的本源就是对抗.就是战斗! 是挥洒热血的一种方式! 一个游戏最复杂最难做的是什么?UI?商城? ...
- 如何制作一个类似Tiny Wings的游戏(2) Cocos2d-x 2.1.4
在第二篇<如何制作一个类似Tiny Wings的游戏>基础上,增加添加主角,并且使用Box2D来模拟主角移动,原文<How To Create A Game Like Tiny Wi ...
- 怎样制作一个相似Tiny Wings的游戏 Cocos2d-x 2.1.4
在第一篇<怎样使用CCRenderTexture创建动态纹理>基础上,添加�创建动态山丘,原文<How To Create A Game Like Tiny Wings with C ...
- 如何制作一个类似Tiny Wings的游戏 Cocos2d-x 2.1.4
在第一篇<如何使用CCRenderTexture创建动态纹理>基础上,增加创建动态山丘,原文<How To Create A Game Like Tiny Wings with Co ...
- [0]尝试用Unity3d制作一个王者荣耀(持续更新)->游戏规划
太得闲了于是想写个农药,虽然可能会失败但是还是要试一试. 因为是自学的不是Unity专业的可能表达语言会有些不标准!望见谅! 结构: 以组件式(比如说摇杆控制和玩家部分的编写是分离的,可以自由拼装)作 ...
- Cocos2dx游戏开发系列笔记13:一个横版拳击游戏Demo完结篇
懒骨头(http://blog.csdn.net/iamlazybone QQ:124774397 ) 写下这些东西的同时 旁边放了两部电影 周星驰的<还魂夜> 甄子丹的<特殊身份& ...
- three.js 制作一个三维的推箱子游戏
今天郭先生发现大家更喜欢看我发的three.js小作品,今天我就发一个3d版本推箱子的游戏,其实webGL有很多框架,three.js并不合适做游戏引擎,但是可以尝试一些小游戏.在线案例请点击博客原文 ...
- 《Genesis-3D开源游戏引擎--横版格斗游戏制作教程07:UI》
概述: UI即User Interface(用户界面)的简称.UI设计是指对软件的燃机交互.操作逻辑.界面美观的整体设计.好的UI设计不仅可以让游戏变得更有品位,更吸引玩家,还能充分体现开发者对游戏整 ...
随机推荐
- IPython Notebook error: Error loading notebook
打开jupyter突然报错: An unknown error occurred while loading this notebook. This version can load notebook ...
- ZJOI2006书架
追yql做题记录的时候做到的……一道Splay模版题…… 啊LCT写久了都有点忘了Splay了(什么奇怪的逻辑?) 其实说白了五个操作: 1. 将某元素置顶:将元素旋到根,然后将左子树合并到该元素的后 ...
- 【SQL】数据库更新
1.插入 INSERT INTO R(A1,A2,...An) VALUES(v1, v2, ...,vn) 如果插入了所有属性,并且按照定义的顺序给出,可以省略(A1,A2,...An) 可以只插入 ...
- 学习apache commons lang3的源代码 (1):前言和R
本系列主要是针对lang3的3.7版本的源代码进行学习,并适当举例.一共大概150多个java文件,争取30天内学习完毕. 26个英文字母 争取每天学习1个字母开头的类们. 今天,就学习R开头的吧. ...
- ubuntu 16.04 qtcreator 闪退
当用QtCreator 进行代码自动补全时,比如编写ros代码,ROS_INFO时候就会出现闪退,后面按照 http://doc.qt.io/qtcreator/creator-clang-codem ...
- Android InputStream转Bitmap
android socket服务端 接收Delphi socket客户端发来的图片,保存到bitmap中,代码如下: public static Bitmap readInputStreamToBit ...
- .NET Core on Raspberry Pi
原文地址:传送门 .NET Core on Raspberry Pi Arm32 builds are available as community supported builds for .NET ...
- MySQL InnoDB MVCC深度分析
关于MySQL的InnoDB的MVCC原理,很多朋友都能说个大概: 每行记录都含有两个隐藏列,分别是记录的创建时间与删除时间 每次开启事务都会产生一个全局自增ID 在RR隔离级别下 INSERT -& ...
- C3P0连接池一些基本配置
C3P0连接池配置 数据库连接是一个耗费大量资源且相当慢的操作,所以为了提高性能和连接速度,诞生了连接池这样的概念. 在多用户并发操作过程中,连接池尤为重要. 它是将那些已连接的数据库连接存放在一个容 ...
- Unity防破解 —— 重新编译mono
Unity4.x版本导出android包时,只能选择mono,无法使用il2cpp,这就造成了我们的程序集很容易被修改--很多朋友在发布项目时觉得即使代码暴露出去也没什么关系,只有项目火了才有 ...