cocos2dx3.0游戏编程2-动作游戏之自定义精灵类

上一节我们做了点准备工作, 本节我们将定义自己的sprite类,以便于后续的开发。Coco2dx提供的默认sprite类只提供了最基础的功能,我们要做动作游戏,仅仅只用cocos2dx的sprite类的功能是不够的,所以我们要继承sprite类,来实现自己的精灵类。

1.实现思路

动作游戏角色就是各种各样的动作,所以我们自定义的类会围绕这个功能来写,落羽这里只实现有代表性的几个动作,主要就是待机,走,攻击,受伤,死亡。动作游戏还要有数据,但是本节落羽不讲数据,只讲动画,数据以后再讲。效果如下

cocos2dx3.0游戏编程2-动作游戏之自定义精灵类_第1张图片

2.程序

定义枚举

enum class SpriteType	//精灵类型
{
	PLAYER = 1,
	ENEMY = 2
};

enum class SpriteState	//精灵状态
{
	NONE = 0,
	IDLE = 1,
	WALK = 2,
	ATTACK = 3,
	HURT = 4,
	KNOCKEDOUT = 5
};


头文件

#ifndef GAME_SPRITE_H
#define GAME_SPRITE_H

#include "cocos2d.h"
#include "Define.h"
USING_NS_CC;

class GameSprite : public Sprite
{
public:
	~GameSprite();
	void init(Point point, SpriteType type, float walkSpeed);//位置,精灵类型,移动速度
	void update(float dt);

	virtual void idle();					//待机
	virtual void walkWithDirection(Point direction);//移动
	virtual void attack();	//攻击
	virtual void hurtWithDamage(int damage);	//受伤
	virtual void knockedout();	//死亡

	void loadAnimation(SpriteType type);
protected:
	Action *idleAction;		//动画
	Action *walkAction;
	Animate *attackAction;
	Animate *hurtAction;
	Animate *knockedoutAction;

	Point moveDirection;	//移动方向
	float walkSpeed;	//移动速度
	Point velocity;		//移动向量
	SpriteType type;	//精灵类型
	SpriteState state;	//精灵状态
};

#endif


析构

GameSprite::~GameSprite()	//释放动画
{
	if(idleAction != NULL)
	{
		idleAction->release();
		idleAction = NULL;
	}
	if(walkAction != NULL)
	{
		walkAction->release();
		walkAction = NULL;
	}
	if(attackAction != NULL)
	{
		attackAction->release();
		attackAction = NULL;
	}
	if(hurtAction != NULL)
	{
		hurtAction->release();
		hurtAction = NULL;
	}
	if(knockedoutAction != NULL)
	{
		knockedoutAction->release();
		knockedoutAction = NULL;
	}
}


初始化

void GameSprite::init(Point point, SpriteType type, float walkSpeed)
{
	Sprite::init();
	this->setPosition(point);
	this->type = type;
	this->walkSpeed = walkSpeed;
	moveDirection = Point::ZERO;
	velocity = Point::ZERO;
	state = SpriteState::NONE;
	loadAnimation(type);
	this->scheduleUpdate();
	idle();
}


更新

void GameSprite::update(float dt)
{
	Point distance = velocity * dt;			//根据向量移动
	setPosition(getPosition() + distance);
}


待机

void GameSprite::idle()
{
	if(state != SpriteState::IDLE)
	{
		state = SpriteState::IDLE;
		this->stopAllActions();
		this->runAction(idleAction);
	}
}


走路


void GameSprite::walkWithDirection(Point direction)
{
	if(state != SpriteState::WALK)
	{
		state = SpriteState::WALK;
		this->stopAllActions();
		this->runAction(walkAction);
	}
}


攻击

void GameSprite::attack()
{
	if(state != SpriteState::ATTACK)
	{
		state = SpriteState::ATTACK;
		this->stopAllActions();
		auto *atta = Sequence::create(attackAction,
			CallFunc::create(CC_CALLBACK_0(GameSprite::idle, this)), NULL);
		this->runAction(atta);
	}
}


受伤

void GameSprite::hurtWithDamage(int damage)
{
	if(state != SpriteState::HURT)
	{
		state = SpriteState::HURT;
		this->stopAllActions();
		auto *hurt = Sequence::create(hurtAction,
			CallFunc::create(CC_CALLBACK_0(GameSprite::idle, this)), NULL);
		this->runAction(hurt);
	}
}


死亡

void GameSprite::knockedout()
{
	if(state != SpriteState::KNOCKEDOUT)
	{
		state = SpriteState::KNOCKEDOUT;
		this->stopAllActions();
		this->runAction(knockedoutAction);
	}
}


加载动画

Animation* findAnimation(const char* animName, const char* fileName, int fileStartNum, int fileEndNum, float dur, Rect rect)
{
	Animation *animation;
	animation = AnimationCache::getInstance()->getAnimation(animName);
	if(animation != NULL)
	{
		return animation;
	}
	else
	{
		Vector<SpriteFrame*> arr;
		char str[50];
		for(int i = fileStartNum; i <= fileEndNum; ++i)
		{
			sprintf(str, "%s_%02d.png", fileName, i);
			arr.pushBack(SpriteFrame::create(str, rect));
		}
		animation = Animation::createWithSpriteFrames(arr, dur);
		animation->setRestoreOriginalFrame(false);
		AnimationCache::getInstance()->addAnimation(animation, animName);
		return animation;
	}
}


void GameSprite::loadAnimation(SpriteType type)
{
	if(type == SpriteType::PLAYER || type == SpriteType::ENEMY)
	{
		Animation *animation;
		Animate *animate;
	//idle
		animation = findAnimation("playerNormalIdle", "player_brother_idle", 1, 1, 0.2, Rect(0, 0, 200, 300));
		animate = Animate::create(animation);
		idleAction = RepeatForever::create(animate);
		idleAction->retain();

	//walk
		animation = findAnimation("playerNormalWalk", "player_brother_move", 1, 4, 0.2, Rect(0, 0, 200, 300));
		animate = Animate::create(animation);
		walkAction = RepeatForever::create(animate);
		walkAction->retain();

	//attack
		animation = findAnimation("playerNormalAttack", "player_brother_attack", 1, 2, 0.4, Rect(0, 0, 200, 300));
		animate = Animate::create(animation);
		attackAction = animate;
		attackAction->retain();
	//hurt
		animation = findAnimation("playerNormalHurt", "player_brother_hurt", 1, 2, 0.2, Rect(0, 0, 200, 300));
		animate = Animate::create(animation);
		hurtAction = animate;
		hurtAction->retain();
	//knockedout
		animation = findAnimation("playerNormalKnockedout", "player_brother_die", 1, 2, 0.2, Rect(0, 0, 200, 300));
		animate = Animate::create(animation);
		knockedoutAction = animate;
		knockedoutAction->retain();
	}
}


使用精灵类

	auto *sprite = new GameSprite();
	sprite->init(Point(400, 400), SpriteType::PLAYER, 100);
	sprite->walkWithDirection(Point::ZERO);
	this->addChild(sprite);
	sprite->release();

	sprite = new GameSprite();
	sprite->init(Point(600, 400), SpriteType::ENEMY, 100);
	sprite->attack();
	this->addChild(sprite);
	sprite->release();

	sprite = new GameSprite();
	sprite->init(Point(800, 400), SpriteType::PLAYER, 100);
	sprite->hurtWithDamage(0);
	this->addChild(sprite);
	sprite->release();

	sprite = new GameSprite();
	sprite->init(Point(1000, 400), SpriteType::PLAYER, 100);
	sprite->knockedout();
	this->addChild(sprite);
	sprite->release();


3.总结

本节落羽一步步实现了一个自定义精灵类,实现了各种动作,下一节我们讲类之间的交互。

本节源代码和图片资源

你可能感兴趣的:(游戏,游戏编程,cocos2dx3.0游戏编程,cocos2dx地图,cocos2dx动作游戏)