`
totoxian
  • 浏览: 1080134 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

把AndEngine例子中贪吃蛇游戏使用Cocos2d-x实现

 
阅读更多

用AE做了个项目后,还是决定转到cocos2d-x上来做2D,因为跨平台确实吸引人。个人觉得AE还是个很不错的2D引擎,有着JAVA一贯的简单易用。而且AE中许多概念和cocos2d-x相通,比如Entity 对应CCNode,Modifier 对应Action, Scene, Layer,都有粒子系统和物理引擎支持等。

AE自带例子中有一个贪吃蛇的例子,使用的图片资源也少,学习cocos2d-x过程中新手实践一番

一、准备:

AE 游戏例子,AndEngineExamples中位于org.andengine.examples.game.snake包中的游戏,cocos2d-x, 我下载的是cocos2d-2.1rc0-x-2.1.

二、操作:

  1. 用ccx VS的win32模板添加一个项目Snake, 这是一个HelloWorld的程序,注意:如果这个工程没有放在CCX的目录下,要自己配置包含目录,因为模板使用了$(SolutionDir)这样的路径。

2. 将AndEngineExamples\assets\mfx下的两个声音文件,game_over.ogg,munch.ogg; font下的Plok.ttf;AndEngineExamples\assets\gfx下的snake*.png, frog.png拷到resource目录下。

3. 观察原游戏目录,依次实现对应类。


首先是常量定义,这个不用说了,添加一个头文件SnakeConstants.h,如:

 
#ifndef SNAKECONSTANTS_H_
#define SNAKECONSTANTS_H_

class SnakeConstants
{
public:
	static const int CELLS_HORIZON = 16;
	static const int CELLS_VERTICAL = 12;
	static const int CELL_WIDTH = 32;
	static const int CELL_HEIGHT = CELL_WIDTH;
	static const int CAMERA_WIDTH = CELLS_HORIZON * CELL_WIDTH; 
	static const int CAMERA_HEIGHT = CELLS_VERTICAL * CELL_HEIGHT;

	static const int LAYER_COUNT = 4;

	static const int LAYER_BACKGROUND = 0;
	static const int LAYER_FOOD = 1;
	static const int LAYER_SNAKE = 2;
	static const int LAYER_UI = 3;
};
#endif  
接口ICellEntity, 添加一个ICellEntity.h
#define ICELL_ENTITY_H_
#ifndef ICELL_ENTITY_H_
class ICellEntity
{
public:
	virtual const int GetCellX() const= 0;
	virtual const int GetCellY() const= 0;

	virtual void SetCell(const ICellEntity& cell) = 0;
	virtual void SetCell(const int cellX, const int cellY) = 0;

	virtual bool IsInSameCell(const ICellEntity& cell) const = 0;

};

#endif


Direction枚举定义了方向,和方向上的移动,添加Direction.h, 注意:由于这两个引擎的坐标第y方向是相反的,所以AddToY上下方向的符号变了。

#ifndef DIRECTION_H_
#define DIRECTION_H_

#include "SnakeConstants.h"

enum Direction
{
	DIR_NULL,
	UP = 1,
	DOWN,
	LEFT,
	RIGHT
};

static int AddtoX(const Direction direction, const int dx)
{
	switch(direction)
	{
	case UP:
	case DOWN:
		return dx;
	case LEFT:
		return dx - 1;
	case RIGHT:
		return dx + 1;
	}

	return dx;
}

static int AddtoY(const Direction direction, const int dy)
{
	switch(direction) 
	{
	case LEFT:
	case RIGHT:
		return dy;
	case UP:
		return dy + 1;
	case DOWN:
		return dy - 1;
	}

	return dy;
}

static Direction Opposite(const Direction direction) 
{
	switch(direction) {
	case UP:
		return DOWN;
	case DOWN:
		return UP;
	case LEFT:
		return RIGHT;
	case RIGHT:
		return LEFT;
	default:
		return DIR_NULL;
	}
}

#endif
用ICellEntity.h接口实现CellEntity类,这个类是没有动画的,用于主角的尾巴。这里使用了继承CCSprite的方式,
class CellEntity : public ICellEntity, public CCSprite

因为ccx默认的锚点在中心,所以把位置加上格子一半,定义在中心

this->setPosition(ccp(mCellX*SnakeConstants::CELL_WIDTH+16, mCellY*SnakeConstants::CELL_HEIGHT+16));

实现一个简单帧动画的类,AnimatedCellEntity, 构造函数中显示了一种使用帧动画的方式:

	mCellX = cellx;
	mCellY = celly;

	animation = CCAnimation::create();
	CCImage* image = new CCImage();
	image->autorelease();
	image->initWithImageFile(filename);
	CCTexture2D* texture = new CCTexture2D();
	texture->initWithImage(image);
	mTileW = texture->getPixelsWide() / col;
	mTileH = texture->getPixelsHigh();

	for (int i = 0; i < col; ++i)
	{
		animation->addSpriteFrameWithTexture(texture, CCRectMake(i*mTileW, 0, mTileW, mTileH));
	}
	CCSpriteFrame* frm = ((CCAnimationFrame*)(animation->getFrames()->objectAtIndex(0)))->getSpriteFrame();

	this->initWithSpriteFrame(frm);
	animation->setDelayPerUnit(0.5f);

	mAni = CCRepeatForever::create(CCAnimate::create(animation));

	this->SetCell(cellx, celly);
void AnimatedCellEntity::Animate( const float interval )
{
	animation->setDelayPerUnit(interval);
	this->runAction(mAni);
}

用上面的两个类实现SnakeHead,SnakeTailPart

蛇头应当占两个格子,而且旋转的中心在头部的1/4处,所以要更改锚点,并放大,这点和AE还是有些不同的

	this->setAnchorPoint(ccp(0.5f, 0.75f));
	this->setScale(2.0f);
最后新建一个类,Snake继承自CCNode,其中包含一个头和一个CCArray表示尾部。
#include "cocos2d.h"
#include "Direction.h"
#include "Snake.h"
#include "SnakeTailPart.h"


Snake::Snake( const Direction dir, int cellx, int celly )
{
	m_pSnakeHead = new SnakeHead(cellx, celly);
	m_pSnakeHead->autorelease();

	this->addChild(m_pSnakeHead);
	this->SetDirection(dir);
}

void Snake::SetDirection( const Direction dirction )
{
	if(mLastMoveDirection != Opposite(dirction)) 
	{
		mDirection = dirction;
		m_pSnakeHead->SetRotation(dirction);
	}
}

Snake::~Snake()
{
//	CC_SAFE_DELETE(m_pSnakeHead);

	////释放数组内的元素!, NO NEED!
	//CCObject* object;
	//CCARRAY_FOREACH(&marrTail, object)
	//{
	//	CC_SAFE_DELETE(object);
	//}

	//marrTail.removeAllObjects();
}

int Snake::GetNextX()
{
	return AddtoX(mDirection, m_pSnakeHead->GetCellX());
}

int Snake::GetNextY()
{
	return AddtoY(mDirection, m_pSnakeHead->GetCellY());
}

boolean Snake::Move()
{
	mLastMoveDirection = mDirection;

	if(m_bGrow) 
	{
		m_bGrow = false;
		/* If the snake should grow,
		* simply add a new part in the front of the tail,
		* where the head currently is. */
		SnakeTailPart* newTailPart = new SnakeTailPart(m_pSnakeHead);
		this->addChild(newTailPart);
		marrTail.insertObject(newTailPart, 0);
	} 
	else 
	{
		if(marrTail.count() > 0)
		{
			/* First move the end of the tail to where the head currently is. */
			SnakeTailPart* tailEnd = (SnakeTailPart*)marrTail.lastObject();
			marrTail.removeLastObject(false);
			tailEnd->SetCell(*m_pSnakeHead);

			marrTail.insertObject(tailEnd, 0);
		}
	}

	/* The move the head into the direction of the snake. */
	m_pSnakeHead->SetCell(GetNextX(), GetNextY());

	/* Check if head collides with tail. */
	for(int i = marrTail.count() - 1; i >= 0; i--) 
	{
		if(m_pSnakeHead->IsInSameCell(*(SnakeTailPart*)marrTail.objectAtIndex(i)))
		{
			return false;
		}
	}

	return true;
}
逻辑部分就完了。

把模板中的HelloWorldScene改为自己的SnakeScene,实现显示和触摸控制

#ifndef SNAKESCENE_H__
#define SNAKESCENE_H__

#include "cocos2d.h"
#include "SimpleAudioEngine.h"
#include "Direction.h"
#include "Snake.h"
#include "Frog.h"

class SnakeScene : public cocos2d::CCLayer
{
public:
    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  

    // there's no 'id' in cpp, so we recommand to return the exactly class pointer
    static cocos2d::CCScene* scene();
    
    // a selector callback
    void menuCloseCallback(CCObject* pSender);

	//四个方向
	void upCallBack(CCObject* sender);
	void downCallBack(CCObject* sender);
	void leftCallBack(CCObject* sender);
	void rightCallBack(CCObject* sender);

	//schedule
	void ScheduleTick1(float dt);
	void GameCircle(float dt);

    // implement the "static node()" method manually
    CREATE_FUNC(SnakeScene);
private:
	void SetFrogToRandomCell();
	void OnGameOver();

	void HandleNewSnakePosition();

	//声音的使用非常简洁!
	void PlayMunchSound();
	void PlayGameOverSound();
private:
	int m_nScore;
	bool m_bGameRunning;

	//分数
	CCLabelTTF* mScoreText;
	//游戏结束 
	CCLabelTTF* mGameOverText;
	//游戏开始前的文字 
	CCLabelTTF* mTitleText;
	Snake* mSnake;
	Frog* mFrog;
};

#endif 
在init中:

依照原游戏,分四层:

for(int i = 0; i < SnakeConstants::LAYER_COUNT; ++i)
{
this->addChild(CCLayer::create());
}

四个方向键:

		//4个方向键:
		CCMenuItemImage* pUpImage = CCMenuItemImage::create("u1.png", "u2.png", this, menu_selector(SnakeScene::upCallBack));
		pUpImage->setAnchorPoint(ccp(0.5, 0));
		pUpImage->setPositionY(6.0f);

		CCMenuItemImage* pDownImage = CCMenuItemImage::create("d1.png", "d2.png", this, menu_selector(SnakeScene::downCallBack));
		pDownImage->setAnchorPoint(ccp(0.5, 1));
		pDownImage->setPositionY(-6.0f);

		CCMenuItemImage* pLeftImage = CCMenuItemImage::create("b1.png", "b2.png", this, menu_selector(SnakeScene::leftCallBack));
		pLeftImage->setAnchorPoint(ccp(1, 0.5));
		pLeftImage->setPositionX(-6.0f);

		CCMenuItemImage* pRightImage = CCMenuItemImage::create("f1.png", "f2.png", this, menu_selector(SnakeScene::rightCallBack));
		pRightImage->setAnchorPoint(ccp(0, 0.5));
		pRightImage->setPositionX(6.0f);

		CCMenu* ArrowMenu = CCMenu::create(pUpImage, pDownImage, pLeftImage, pRightImage, NULL);
		ArrowMenu->setPosition(100, 100);
		layer->addChild(ArrowMenu);
游戏主循环:

schedule(schedule_selector(SnakeScene::GameCircle), 0.5f);
声音播放:

void SnakeScene::PlayMunchSound()
{
CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect("munch.ogg");
}

运行后:



最后 附上源码:

src-of-demo








  


  
分享到:
评论

相关推荐

    andengine 安卓游戏2d引擎

    在使用AndEngine-GLES2压缩包时,你需要包含必要的库文件,并按照官方文档或者社区教程进行项目设置。通常,开发流程包括创建游戏场景、添加精灵、定义动画、实现碰撞检测以及添加音效和音乐等。 总的来说,...

    Java可以同时开发安卓和iOS_.docx

    另一方面,Cocos2d-x是一个源自Cocos2d-iphone的跨平台游戏引擎,它主要使用C++进行开发。C++提供了更底层的控制和性能优化,但学习曲线相对较陡峭。Cocos2d-x支持多种平台,包括iOS、Android和Windows等。然而,...

    AndEngine游戏-DeliveryBoy-源代码

    《AndEngine游戏-DeliveryBoy-源代码》是一个用于学习AndEngine游戏开发的示例项目,其主要内容涵盖了AndEngine的基本使用、游戏逻辑构建以及资源管理等多个方面。AndEngine是一款流行的开源Android游戏开发引擎,它...

    andengine 最新源码(具有box2D)

    了解并掌握这些知识点,开发者可以利用AndEngine高效地开发出丰富的2D游戏,同时,结合Box2D的物理引擎,能够实现更加逼真的游戏体验。无论是初学者还是经验丰富的开发者,都能从中受益,提升游戏开发的效率和质量。

    一个关于andengine中精灵 动作的简单例子

    在Android游戏开发中,AndEngine是一个非常受欢迎的2D游戏引擎,它允许开发者轻松地创建出高质量的2D游戏。本篇文章将详细讲解AndEngine中精灵(Sprite)及其动作(Animations)的应用,以一个简单的例子为基础,...

    AndEngine例子控制手柄

    本示例“AndEngine例子控制手柄”是针对AndEngine中如何实现虚拟控制器(如游戏手柄)的一个实践教程,旨在帮助开发者构建具有移动、旋转等操作的游戏。 在AndEngine中,控制手柄通常由两个主要部分组成:一个用于...

    AndEngine_分析之二-----BaseGameActivity. 中文

    AndEngine 中的 BaseGameActivity 详解 BaseGameActivity 是 AndEngine 框架中一个...BaseGameActivity 是 AndEngine 框架中一个非常重要的组件,它负责管理游戏引擎和SurfaceView,并提供了一个接口来实现游戏逻辑。

    AndEngine_分析之三-----AsyncTask_BaseActivity备忘

    通过对`AsyncTask`的详细介绍和`BaseActivity`中的应用案例,我们可以了解到如何在AndEngine中使用`AsyncTask`来进行后台处理和更新UI的操作。这种方法不仅能够提高用户体验,还简化了代码的编写过程。开发者可以...

    andorid简单计算器java源码-AndroidArsenal:安卓兵工厂,强大!

    cocos2d-x 项目描述: An open source software framework. It can be used to build games, apps and other cross platform GUI based interactive programs. 项目地址: http://cocos2d-x.org PlayN 项目描述: ...

    AndEngine_分析之一----载入资源 这个是英文的

    在Android游戏开发中,AndEngine是一个非常流行的2D游戏引擎,它允许开发者创建高质量的图形和交互式体验。本文将探讨如何在AndEngine中实现后台加载资源,同时展示一个使用AsyncTask来处理加载过程的示例。 在...

    AndEngine游戏开发示例

    在AndEngine中,你可以使用TextureRegion来指定精灵的图像区域,并通过Animation类实现精灵的帧动画。 物理引擎在AndEngine中扮演着重要角色,特别是对于需要动态模拟的游戏。AndEngine支持Box2D物理引擎的集成,...

    AndEngine游戏引擎JAR文件

    Box2D是一个著名的2D物理引擎,它被集成到AndEngine中,为游戏提供真实的物理模拟,如重力、碰撞检测和刚体动力学等。开发者可以通过Box2D轻松实现物体的运动和交互,创造出更具真实感的游戏环境。例如,你可以创建...

    andengine_box2d

    它包含了所有必要的类和方法,用于在AndEngine游戏中实现Box2D物理效果。例如,你可以创建刚体、关节、碰撞形状等,并设置物理参数,如密度、摩擦力和弹力。 2. `armeabi-v7a`、`armeabi`、`x86`:这些是针对不同...

    andengine2.0开发的小游戏

    在这个Jumper Game Tutorial中,开发者可能详细介绍了如何使用AndEngine 2.0创建游戏背景、主角角色、跳跃动作、碰撞检测以及得分系统。通过分析源代码和阅读教程,学习者可以掌握AndEngine的基本用法,例如设置场景...

    TheHardestGame for andengine完整游戏例子。

    在这个完整的游戏例子中,我们可以深入学习到AndEngine的多个核心技术和游戏开发流程。 1. AndEngine基础知识:AndEngine提供了丰富的图形渲染、物理引擎、动画处理等功能,开发者可以快速构建游戏场景。了解...

    Android 2D游戏引擎AndEngine快速入门教程

    AndEngine是一款专为Android平台设计的2D游戏开发引擎,它简化了2D游戏的创建过程,让开发者能够更专注于游戏的设计和逻辑,而非底层图形处理。本教程将引导你快速掌握AndEngine的基础知识和核心功能,助你开启...

    指向对象的C++指针、对象的大小

    三、Android4.3游戏开发基础、Cocos2D-X,Unity2D,Unity3D一个都不能少 四、课程首次涉及跨平台游戏引擎技术,国内独家(AndEngine引擎、libGDX引擎) 五、跨平台技术(HTML5技术) 六、经典游戏重现(捕鱼达人...

    MoVeBall Andengine例子

    【MoVeBall Andengine例子】是一个基于Andengine游戏开发框架的示例项目,它展示了如何使用Andengine来创建一个简单的移动球体的游戏。Andengine是一款流行的开源Android游戏开发库,它提供了一系列强大的2D游戏开发...

    游戏开发入门

    苹果ios平台上流行的游戏引擎有Unity3D、cocos2d-ObjC、Unreal、sparrow、sprite kit,安卓平台上流行的游戏引擎有Unity3d、cocos2d-x、Unreal、AndEngine、libgdx。 不同的游戏引擎有不同的特点,例如Unity3d 胜在...

    andengine 中文

    AndEngine是一款专为Android平台设计的游戏开发框架,它基于OpenGL ES 1.1或2.0,提供了一套高效、易用的2D游戏...通过阅读这份中文文档,开发者可以更好地理解和掌握AndEngine的使用,从而提升游戏开发的效率和质量。

Global site tag (gtag.js) - Google Analytics