学习cocos2dx有一段时间了,试着做了2048游戏,最近又发现个经典游戏,啥也不说果断开工做自己的游戏——TimberMan!

  首先说明:游戏资源摘自同类游戏,感谢这些游戏的资源让我完成自己的开发。

一、TimberMan玩法--根本停不下来!

    这款游戏的玩法比较简单,通过手指点击左右屏幕来决定砍树站立的方向,不能让树枝碰触Hero,同时有时间限制(时间通过砍树增加),如果停止砍树时间结束=游戏结束。

  让我们看看成品的效果吧!(ps:录像失帧,看到的不直观,可以下载已打包好的apk 在最下方)

二、代码结构

  HelloWorldScene 主场景

  TreeModel  树木(由树节点组合而成)

  Timber 伐木Hero

  TreeNode 树木节点

  GameScore 场景生命和得分

  GameOver 游戏结束

  当然由小到大,一颗大树是由无数的树节点组成的,因此先写树结类,然后才是大树类,最后才是场景。这样拆分之后就很简单的做出了demo。

三、树节点TreeNode

  树节点是一颗树的基础,包括树枝。当然,有没有树枝、树枝的方向是由 大树控制的。因此有如下枚举贯穿游戏

  

enum TreeBranchDirection
{
DEFINE,//无节点
LEFT,//左
RIGHT//右
};

  节点的基本功能:1、设置树枝2、获取树枝类型(返回TreeBranchDirection)

void TreeNode::setBranch(TreeBranchDirection enums)
{
enumBranch = enums;
auto branch = this->getChildByName("branch");
auto body = this->getChildByName("body");
branch->setVisible(enums!=DEFINE);
if(enums==DEFINE)return;
if(enums == RIGHT)
{
branch->setScaleX();
branch->setPositionX(body->getContentSize().width);
}
else
{
branch->setScaleX(-);
branch->setPositionX(-body->getContentSize().width);
}
} TreeBranchDirection TreeNode::getHasBranch()
{
return enumBranch;
}

四、大树TreeModel

  大树是树节点的集合,由一个一个的节点依次排列组成。最基本的功能如下

  TreeNode* getTreeHeadNode();获得头节点

  TreeNode* deleteTreeHeadNode();删除头节点

  void initTree();初始化

  TreeBranchDirection getFirstBranch();获得头节点的树枝方向

  void onReset();重置整个树

  Vector<TreeNode*> treeQueue;树节点列表

  Vector<TreeNode*> treeCache;树节点缓存列表

  优化:这个游戏一直在变化的是树节点,如果不停的删除和new节点 将会使程序不健康!为此除了要有树列表treeQueue外要有一个缓存队列treeCache,缓存队列的工作就是避免重复的new节点,同时回收砍掉的节点等待下次使用。

  当然,作为大树的类是整个游戏的重点逻辑:生成什么样节点?

    1、通过玩法得知必须在不同方向的树枝之间存在一个没有树枝的节点,使hero能生存。

    2、如果前一个是有树枝的,那么以什么概率来产生下一个节点是否要有树枝(有树枝必须是同方向的 or 无树枝),使hero生存。

    3、如果前一个树节点是无树枝的,那么再向前一个的树节点是否有树枝?根据难度来调节是否要产生树枝,增加难度。

  围绕着这三个问题要有一个得到树枝的逻辑函数TreeModel::getBranch()

TreeBranchDirection TreeModel::getBranch()
{
auto isBranch = CCRANDOM_0_1()* < ;
if( treeQueue.size() == )
return DEFINE;
if( !isBranch ) return DEFINE;
auto protree = treeQueue.at(treeQueue.size()-);
switch (protree->getHasBranch())
{
case LEFT:
return (CCRANDOM_0_1()* < ) ? DEFINE : LEFT;
break;
case RIGHT:
return (CCRANDOM_0_1()* < ) ? DEFINE : RIGHT;
break;
case DEFINE:
return getAgainBranch();
break;
default:
return DEFINE;
break;
}
} TreeBranchDirection TreeModel::getAgainBranch()
{
if( treeQueue.size() < )
return DEFINE;
auto protree = treeQueue.at(treeQueue.size()-);
switch (protree->getHasBranch())
{
case LEFT:
return (CCRANDOM_0_1()* < ) ? RIGHT : LEFT;
break;
case RIGHT:
return (CCRANDOM_0_1()* < ) ? LEFT : RIGHT;
break;
case DEFINE:
return (CCRANDOM_0_1()* < ) ? LEFT : RIGHT;
break;
default:
return DEFINE;
break;
}
}

  这其中的 概率随机数是可以调整的,如果你想增加难度 那就调整吧!

五、时间线GameScore

  游戏结束有两个点1、碰到树枝2、时间终止

  时间进度我用的ProgressTimer 进度表示时间百分比。

  我想到了两种逻辑:

    1、speed 法, 通过分数来决定速度,分数越高时间越少,不断的砍树来维持时间平衡。

    2、addProgress 增量法, 通过分数来决定砍树获得每次增加的量,分数越高增量越低,最后维持在一个平衡点,在这个平衡点上保持速度均衡。

  我最后选得增量,这两种方法相对都很不错。

六、数据存储UserDefault

  整个游戏不需要大量的存储数据,因为只是记录最高分数,在设置游戏结束分数的时候进行读写

void GameOver::setScore(int score)
{
int maxScore = score;
char string[] = {};
sprintf(string, "Score %d", score);
_newScore->setString(string); maxScore = UserDefault::getInstance()->getIntegerForKey("maxScore");
if( maxScore < score )
{
UserDefault::getInstance()->setIntegerForKey("maxScore",score);
}
newScore->setVisible(( maxScore < score ));
char str2[] = {};
sprintf(str2, "Max Score %d", ( maxScore < score ) ? score : maxScore);
_highestScore->setString(str2); UserDefault::getInstance()->flush();
}

七、主场景 HelloWorldScene

  主场景控制游戏的开始与结束。逻辑判断并不多。

  点击判断:

bool HelloWorld::onTouchBegans(Touch *touch, Event *event)
{
auto pos = touch->getLocation();
Size visibleSize = Director::getInstance()->getVisibleSize();
auto model = TreeModel::getInstance(); auto isRight = pos.x > visibleSize.width/;
timber->playAction(isRight ? RIGHT : LEFT);
if(isRight)
{
timber->setPosition(visibleSize.width/+timber->getContentSize().width/+,);
}
else
{
timber->setPosition(visibleSize.width/-timber->getContentSize().width/-,);
} if(getIsOver())
{
timber->setTimberDie();
gameOver();
return false;
} auto dic = visibleSize.width*;
auto time = 0.5;
auto tree = model->deleteTreeHeadNode();
if( isRight )
{
tree->runAction(Spawn::create(RotateBy::create(time,-),MoveBy::create(time,Vec2(-dic,)),nullptr));
}
else
{
tree->runAction(Spawn::create(RotateBy::create(time,),MoveBy::create(time,Vec2(dic,)),nullptr));
} _score++;
score->setScore(_score);
if(getIsOver())
{
timber->setTimberDie();
gameOver();
} return true;
}

  是否游戏结束:

bool HelloWorld::getIsOver()
{
auto model = TreeModel::getInstance(); if(model->getFirstBranch() == timber->getTimberDir()) return true;
return false;
}

  重置游戏,从新开始:

void HelloWorld::onRest()
{
_score = ;
TreeModel::getInstance()->onReset();
score->onReset();
timber->onReset();
list->setEnabled(true);
auto isBgShow = (CCRANDOM_0_1()* < );
bg1->setVisible(isBgShow);
bg2->setVisible(!isBgShow);
Size visibleSize = Director::getInstance()->getVisibleSize();
timber->setPosition(visibleSize.width/-timber->getContentSize().width/-,);
}

  当然coco2dx的粒子系统也很不错 我加入了 雪花特效以及声音特效:

ParticleSystem* pl = ParticleSnow::create();
pl->setTexture(Director::getInstance()->getTextureCache()->addImage("particle.png"));
pl->setPosition(visibleSize.width/,visibleSize.height);
this->addChild(pl);

八、总结

  这个游戏算是我做的比较全的demo了,加入了屏幕适配、桌面图片icon、声音、粒子、数据。虽然比较简单,但能学习、做好、完善其实还是比较不错的,因为工作比较忙所以抽空能敲一敲代码,不过总算没有半途而废。

  TimberMan.apk

  链接:http://pan.baidu.com/s/1o6A0Dce 密码:29mz

  TimberMan代码

  链接: http://pan.baidu.com/s/1pJynvdT 密码: bt1v

Cocos2d-x 3.2 学习笔记(十二)TimberMan!疯狂伐木工!的更多相关文章

  1. python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL

    python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL实战例子:使用pyspider匹配输出带.html结尾的URL:@config(a ...

  2. Go语言学习笔记十二: 范围(Range)

    Go语言学习笔记十二: 范围(Range) rang这个关键字主要用来遍历数组,切片,通道或Map.在数组和切片中返回索引值,在Map中返回key. 这个特别像python的方式.不过写法上比较怪异使 ...

  3. java jvm学习笔记十二(访问控制器的栈校验机制)

    欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 本节源码:http://download.csdn.net/detail/yfqnihao/4863854 这一节,我们 ...

  4. (C/C++学习笔记) 十二. 指针

    十二. 指针 ● 基本概念 位系统下为4字节(8位十六进制数),在64位系统下为8字节(16位十六进制数) 进制表示的, 内存地址不占用内存空间 指针本身是一种数据类型, 它可以指向int, char ...

  5. Python学习笔记(十二)—Python3中pip包管理工具的安装【转】

    本文转载自:https://blog.csdn.net/sinat_14849739/article/details/79101529 版权声明:本文为博主原创文章,未经博主允许不得转载. https ...

  6. ROS学习笔记十二:使用gazebo在ROS中仿真

    想要在ROS系统中对我们的机器人进行仿真,需要使用gazebo. gazebo是一种适用于复杂室内多机器人和室外环境的仿真环境.它能够在三维环境中对多个机器人.传感器及物体进行仿真,产生实际传感器反馈 ...

  7. JavaScript权威设计--命名空间,函数,闭包(简要学习笔记十二)

    1.作为命名空间的函数 有时候我们需要声明很多变量.这样的变量会污染全局变量并且可能与别人声明的变量产生冲突. 这时.解决办法是将代码放入一个函数中,然后调用这个函数.这样全局变量就变成了 局部变量. ...

  8. MySQL学习笔记十二:数据备份与恢复

    数据备份 1.物理备份与逻辑备份 物理备份 物理备份就是将数据库的数据文件,配置文件,日志文件等复制一份到其他路径上,这种备份速度一般较快,因为只有I/O操作.进行物理备份时,一般都需要关闭mysql ...

  9. Java基础学习笔记十二 类、抽象类、接口作为方法参数和返回值以及常用API

    不同修饰符使用细节 常用来修饰类.方法.变量的修饰符 public 权限修饰符,公共访问, 类,方法,成员变量 protected 权限修饰符,受保护访问, 方法,成员变量 默认什么也不写 也是一种权 ...

  10. Python学习笔记十二

    HTML全称:Hyper Text Markup Language超文本标记语言 不是编程语言 HTML使用标记标签来描述网页 2.  HTML标签 开始标签,结束标签.  例如:<html&g ...

随机推荐

  1. pc端和android端应用程序测试有什么区别?(ps面试题)

    pc端和android端应用程序测试有什么区别?(ps面试题) [VIP7]大连-凭海临风(215687736) 2014/4/10 8:56:171.测试环境不同PC平台一般都是windows an ...

  2. java异常处理机制

    本文从Java异常最基本的概念.语法开始讲述了Java异常处理的基本知识,分析了Java异常体系结构,对比Spring的异常处理框 架,阐述了异常处理的基本原则.并且作者提出了自己处理一个大型应用系统 ...

  3. Linux命令行小插曲

    当命令行出错活出现<时,可使用 ctrl+c强制退出

  4. spring 3.1 配置 JCR 303 Bean Validation

    A) 导入Hibernate-Validator  要使用JSR303 校验框架, 需要加入框架的具体实现Hibernate-Validator, 在soureforge上下载最新的Hibernate ...

  5. codeblocks配置GLUT

    codeblocks配置OPENGL GLUT 作者 He YiJun – storysnail<at>gmail.com 团队 ls 版权 转载请保留本声明! 本文档包含的原创代码根据G ...

  6. DownloadManager

    在androi中,volley适合小文件的获取和大并发,如果支持大文件的下载可以用Android原生的DownloadManager.DownloadManager默认支持多线程下载.断点续传等. 基 ...

  7. note of introduction of Algorithms(Lecture 3 - Part1)

    Lecture 3(part 1) Divide and conquer 1. the general paradim of algrithm as bellow: 1. divide the pro ...

  8. 自己写一个java.lang.reflect.Proxy代理的实现

    前言 Java设计模式9:代理模式一文中,讲到了动态代理,动态代理里面用到了一个类就是java.lang.reflect.Proxy,这个类是根据代理内容为传入的接口生成代理用的.本文就自己写一个Pr ...

  9. java 锁!

    问题:如何实现死锁. 关键: 1 两个线程ta.tb 2 两个对象a.b 3 ta拥有a的锁,同时在这个锁定的过程中,需要b的锁:tb拥有b的锁,同时在这个锁定的过程中,需要a的锁: 关键的实现难点是 ...

  10. telnet小结

    几百年前就开始听说telnet了,却直到最近才真正完全搞懂!... http://www.cnblogs.com/wusthjp/archive/2012/01/05/2312975.html 可能要 ...