这两周做了一个类似于男人下一百层和最近较火地心大冒险类型的卷轴游戏,也是最近才开始接触游戏开发的,前期做起来还是挺不容易的,很多东西都不太理解,只能自己去不断地摸索,说到底,无论做什么都是如此,需要不断的去尝试与学习,扯远了,言归正传。
最起初设计的时候我参考了 jeekun的博客 :http://www.cnblogs.com/jeekun/p/3448375.html ,说实话,他的已经写的挺好的了,比我的要强不少,所有我也借鉴了大神的很多方法。
说说我的思路吧,我设计了一个player类,一个block基类,一个blockFactory工厂类,一个background类,一个GameScene游戏主场景类,最后还有一个MainMenu开始菜单类。这个游戏没太大,所有我也没有添加loading界面了,人物自然情况向下运动,板子向上运动,只是速度远小于人物,当产生碰撞时,人物等于板子的速度一起向上运动,到顶就掉血,到底自然就Die了,分别在各个update函数中执行各自的动画。 游戏直接从MainMenu点击开始游戏进入GameScene主场景。主场景最后说。
1.Player要做的无非就是人物的一些初始化,添加动作什么的,当然越考虑周全就有越多东西,比如还可以加上人物状态之类的
<span style="font-size:18px;">// .h 创建一个玩家单例|
static Player* SharedPlayer();
//初始化玩家|
virtual bool init();
Layer * spriteLayer;
virtual void update(float dt);
CREATE_FUNC(Player);
//初始化动画|
void spriteCollision();</span>
<pre name="code" class="html"><span style="font-family: Arial, Helvetica, sans-serif;"><span style="font-size:18px;">// .m 创建一个玩家单例</span></span>
Player* Player::SharedPlayer() //创建一个玩家单例{ if(!g_sharedPlayer) { g_sharedPlayer = new Player(); g_sharedPlayer->init(); } return g_sharedPlayer;}<span style="font-size:18px;">//添加一个人物下落到板子上的动画效果,其实就是压缩一下然后回弹
void Player::spriteCollision(){
auto actionTo = ScaleBy::create(0.1f, 1.1f, 0.8f);
this->runAction( Sequence::create(actionTo, actionTo->reverse(),nullptr));
}
</span>
<span style="font-size:18px;">void Player::Hurt(float amount){
GameScene* father = (GameScene*)this->getParent();
int myCurBlood = father->m_background->UpdateBloodValue(amount);
if (myCurBlood <= 0) {
Die();
}
}
void Player::Die(){
gameStatus = GAME_OVER;
log("%d",gameStatus);
unscheduleUpdate();
}</span>
然后在update函数中根据手势执行一些相关的动画和移动等等。
2.block类
block即方块,作为基类我想就是几个基础的动作,一个向上运动,一个停止运动,一个update方法,update就是让不断产生的blocks不断向上运动。
<span style="font-size:18px;">void Block:: update(float dt){
float x = this->getPositionX();
float y = this->getPositionY() + m_movepy;
this->setPosition(Point(x,y));
if (gameStatus == GAME_OVER) {
StopMove();
return;
}<span style="font-family: Courier;">}</span></span>
比如有常规的板子,会miss的板子,会让人物跳跃的板子,会减速的板子等等。
我的办法是在父类中定义了2个纯虚函数,类似于oc中的协议,让子类去实现,分别是落在板子上和离开板子时,然后再这2个函数中添加上自己的动画和效果。
3.blockFactory用于随机产生板子。
大致意思是用一个queue或者vector或者数组装上一些个板子,然后从里面取,当板子到屏幕顶端即销毁。
<span style="font-size:18px;"> struct timeval tv;
gettimeofday(&tv, NULL);
unsigned long int rand_seed = tv.tv_sec *1000 + tv.tv_usec/1000;
srand(rand_seed);</span>
这个用于根据当前时间产生一个随机数。<span style="font-size:18px;">//根据产生的随机数对应生成随机的block|
void BlockFactory::CreateBlock()
{
Block* block = NULL;
int randomBlock = floor(CCRANDOM_0_1() * 100);
if(randomBlock <= 35)
{
block = NormalBlock::create();
}
else if(randomBlock <= 50)
{
block = MissBlock::create();
}
else if(randomBlock <= 70)
{
block = FlipBlock::create();
}
else if(randomBlock <= 85)
{
block = LeftRunBlock::create();
}
else if(randomBlock <= 90)
{
block = RightRunBlock::create();
}else{
block = RightRunBlock::create();
}
}
</span>
当然第一块板子可能需要固定产生个,因为你不可能一上来就不小心给摔死了了吧,坐标我设置为屏幕中央。
掉,同时从容器中pop掉。当板子超出屏幕时就将其remove掉,同时从容器中pop掉。
4.background中显示层数,有血量的话也可以添加上,init中加上pist,png什么的,主要是加上层数和血量的更新
<span style="font-size:18px;">int BackgroundLayer::UpdateBloodValue(int percent) //血量我用的是progressTimer
{
float progressFrom = bloodVol->getPercentage();
float progressTo;
progressTo = bloodVol->getPercentage() - percent;
if (progressTo <= 0) {
progressTo = 0;
}
ProgressFromTo *to2 = CCProgressFromTo::create(0.2, progressFrom, progressTo);
bloodVol->runAction(to2);
return progressTo;
}
void BackgroundLayer::UpdateFloorValue(int floor)
{
char des[20];
sprintf(des, "%d",floor);
floorFont->setString(des);
}</span>
5. 最后是主场景
<span style="font-size:18px;"> static Scene* createScene();
CREATE_FUNC(GameScene);
virtual bool init();
//根据每帧来更新游戏|
virtual void update(float dt);
//触屏响应重写这三个方法|
virtual bool onTouchBegan(Touch* touch, Event* event);//按下|
virtual void onTouchMoved(Touch* touch, Event* event);//拖动|
virtual void onTouchEnded(Touch* touch, Event* event);//松开|
Player * myPlayer;
public:
void StartGame();
void StartPlayer();
void StartBlock();
void GameOver();
//人物碰撞检测|
bool playerCollisionBlock();
BackgroundLayer* m_background;</span>
碰撞检测的实现我暂时用的
<span style="font-size:18px;"> if (player->getBoundingBox().intersectsRect(block->getBoundingBox())) {}</span>
好了,大概的思路如此,由于图片资源还没做而且项目还没完善,所有源代码暂时也无法提供,不过我们应该是通过开源的代码去学习他的思想,集思广益吧。今天周五了,好开心,明天又可以好好休息玩耍下了