定时器调节人物动作协同问题

Hero.h类

#ifndef __HERO_SCENE_H__
#define __HERO_SCENE_H__
#include "cocos2d.h"
USING_NS_CC;

class Hero : public Layer
{
public:
	int direction;
	Point position;
	Sprite* sprite;
	static Hero* createHeroSprite(Point position, int direction, const char* action);
	void heroInit(Point position, int direction, const char* action);
	virtual bool init();
	void runAttack(Hero* enemy);
	void doAttack();
	void runBack();
	void doStand();
	void beAttacked(float dt);
	void waiting();
	void waitingAttack();
	void waitingUpdate(float dt);
	Animate* createAnimate(int direction, const char *action, int num,int time);
	//void setAction(int direction, const char *action, int num);
	CREATE_FUNC(Hero);
};
#endif

Hero.cpp

`#include "Hero.h"`
`USING_NS_CC;`
Hero* Hero::createHeroSprite(Point position, int direction, const char* action)
{
	Hero* hero = new Hero();
	if (hero && hero->init())
	{
		hero->autorelease();
		hero->heroInit(position, direction, action);
		return hero;
	}
	CC_SAFE_DELETE(hero);
	return NULL;
}
bool Hero::init()
{
	if (!Layer::init())
	{
		return false;
	}
	return true;
}
void Hero::heroInit(Point position, int direction, const char* action)
{
	this->position = position;
	this->direction = direction;
	auto* m_frameCache = SpriteFrameCache::getInstance();
	m_frameCache->addSpriteFramesWithFile("hero.plist", "hero.png");
	sprite = Sprite::createWithSpriteFrameName(String::createWithFormat("%s%d1.png",action,direction)->getCString());
	sprite->setPosition(position);
	addChild(sprite);
	auto* animate = createAnimate(direction, action, 8,-1);
	sprite->runAction(animate);
}
Animate* Hero::createAnimate(int direction, const char *action, int num,int time)
{
	auto* m_frameCache = SpriteFrameCache::getInstance();
	m_frameCache->addSpriteFramesWithFile("hero.plist", "hero.png");
	Vector<SpriteFrame*> frameArray;
	for (int i = 1; i <= num; i++)
	{
		auto* frame = m_frameCache->getSpriteFrameByName(String::createWithFormat("%s%d%d.png", action, direction, i)->getCString());
		frameArray.pushBack(frame);
	}
	Animation* animation = Animation::createWithSpriteFrames(frameArray);
	animation->setLoops(time);//表示无限循环播放
	animation->setDelayPerUnit(0.1f);//每两张图片的时间隔,图片数目越少,间隔最小就越小
	//将动画包装成一个动作
	return Animate::create(animation);
}
void Hero::runAttack(Hero* enemy)
{
	sprite->stopAllActions();
	Point target;
	if (enemy->direction == 1)
	{
		target = Vec2(enemy->position.x - 20, enemy->position.y + 30);
	}
	else
	{
		target = Vec2(enemy->position.x + 20, enemy->position.y+10);
	}
	auto* moveto = MoveTo::create(0.5f, target);
	auto* run = createAnimate(direction, "run", 5,1);
	auto* spawn = Spawn::create(moveto, run, NULL);
	auto* callFunc = CallFunc::create(CC_CALLBACK_0(Hero::doAttack, this));
	auto* sequence = Sequence::create(spawn, callFunc, NULL);
	sprite->runAction(sequence);
}
void Hero::doAttack()
{
	auto* animate = createAnimate(direction, "attack", 14, 1);
	auto* callFunc = CallFunc::create(CC_CALLBACK_0(Hero::runBack, this));
	auto* sequence = Sequence::create(animate, callFunc, NULL);
	sprite->runAction(sequence);
}
void Hero::runBack()
{
	sprite->stopAllActions();
	auto* back = createAnimate(direction, "back", 5, 1);
	auto* moveto = MoveTo::create(0.5f, position);
	auto* spawn = Spawn::create(back, moveto, NULL);
	auto* callFunc = CallFunc::create(CC_CALLBACK_0(Hero::doStand, this));
	auto* sequence = Sequence::create(spawn, callFunc, NULL);
	sprite->runAction(sequence);
}
void Hero::doStand()
{
	sprite->stopAllActions();
	auto* animate = createAnimate(direction, "stand", 8, -1);
	sprite->runAction(animate);
}
void Hero::waitingAttack()
{
	scheduleOnce(schedule_selector(Hero::beAttacked), 1.1f);
}
void Hero::beAttacked(float dt)
{
	sprite->stopAllActions();
	auto* animate = createAnimate(direction, "underatt", 2, 1);
	auto* callFunc = CallFunc::create(CC_CALLBACK_0(Hero::waiting, this));
	auto* sequence = Sequence::create(animate, callFunc, NULL);
	sprite->runAction(sequence);
}
void Hero::waiting()
{
	scheduleOnce(schedule_selector(Hero::waitingUpdate), 0.5f);
}
void Hero::waitingUpdate(float dt)
{
	doStand();
}

HelloWorld.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"
#include "Hero.h"
class HelloWorld : public cocos2d::Layer
{
public:
	int i;
	Hero* hero[2];
    static cocos2d::Scene* createScene();
    virtual bool init();
	void myUpdate(float dt);
	void waiting(float dt);
    CREATE_FUNC(HelloWorld);
};

#endif // __HELLOWORLD_SCENE_H__

HelloWorld.cpp

    #include "cocos2d.h"
    #include "HelloWorldScene.h"

 Scene* HelloWorld::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::create();
    
    // 'layer' is an autorelease object
    auto layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
	auto* background = LayerColor::create(Color4B(255, 255, 255, 255));
	addChild(background);
	i = 0;
	hero[0] = Hero::createHeroSprite(Vec2(540, 100), 1, "stand");
	addChild(hero[0]);
	hero[1] = Hero::createHeroSprite(Vec2(100, 260), 2, "stand");
	addChild(hero[1]);
	schedule(schedule_selector(HelloWorld::myUpdate), 2.5f);
    return true;
}
void HelloWorld::myUpdate(float dt)
{
	i++;
	if ((i % 2) == 0)
	{
		hero[0]->runAttack(hero[1]);
		hero[1]->waitingAttack();
	}
	else
	{
		hero[1]->runAttack(hero[0]);
		hero[0]->waitingAttack();
	}
}

有两个问题:

  1. 编译好执行程序的时候,为什么HelloWorld.cpp的myUpdate函数中hero[0]->runAttack(hero[1]);hero[1]->waitingAttack();这两个语句是同时运行的?
  2. Hero.cpp的waitingAttack函数中1.1S以及waiting函数中0.5S等等这些时间是怎么确定的?如何做到攻击者和受到攻击者动作同步的?我怎么算这些时间都觉得不对

自顶!

给的代码,HelloWorld.cpp 中都没有实现 myUpdate 函数,补充一下吧。方便的话,直接把工程传上来

另外 auto* 这种写法,auto都自动推倒类型了,加不加 * ,没关系,不加看起来更简洁

[quote=“2627993092, post:3, topic:55760”]
给的代码,HelloWorld.cpp 中都没有实现 myUpdate 函数,补充一下吧。方便的话,直接把工程传上来
[/quote]改过了,麻烦再帮忙看一下,谢谢!

为什么不是同时运行的?代码运行到if else当然符合条件就会跳转到相应代码块。

不建议新手就去做状态机相关的,建议在网上看看源码。

新手总会认为执行一个动作的时候,进程会阻塞,等这个动作执行完成,才执行下一个动作(这是符合直觉的,但是不符合渲染的逻辑)。

实际上执行动作,只是做接下来的计划,所有的计划做完后,开始一帧一帧的渲染,动作才真正的在直觉上执行

[quote=“2627993092, post:6, topic:55760”]
新手总会认为执行一个动作的时候,进程会阻塞,等这个动作执行完成,才执行下一个动作(这是符合直觉的,但是不符合渲染的逻辑)。

实际上执行动作,只是做接下来的计划,所有的计划做完后,开始一帧一帧的渲染,动作才真正的在直觉上执行
[/quote]那像1.1,0.5这些等待时间是怎么确定的呢?

上面有大佬,回答[quote=“1111934, post:5, topic:55760”]
不建议新手就去做状态机相关的,建议在网上看看源码。
[/quote]

怎么确定这些时间,我不太懂,你可以@楼上的大佬问问,看什么资料学习

act = DelayTime::create(0.5),就是一个普通动作,然后加入Sequence,没必要用schedule自己实现。