Exemple #1
0
/******************************************************************************
 This function is meant as a wrapper for testConstraint. It controls setting 
 the done state for the constraint as well as implements the anti-constraint 
 behavior.
******************************************************************************/
bool SnapConstraint::applyConstraint(const hduVector3Dd &testPt,
                                     hduVector3Dd &proxyPt)
{
    double snapDist = testConstraint(testPt, proxyPt);

    if (snapDist < getSnapDistance())
    {
        if (isAntiConstraint())
        {
            /* Pretend we didn't have a successful constraint. */
            proxyPt = testPt;
        }

        /* Had collision. */
        return true;
    }
    else
    {
        setIsDone(true);

        /* didn't have collision. */
        return false;
    }

}
void RecordBufUGenInternal::processBlock(bool& shouldDelete, const unsigned int blockID, const int /*channel*/) throw()
{
	const int blockSize = uGenOutput.getBlockSize();
	
	int channelBufferPos = 0;
	
	for(int channel = 0; channel < getNumChannels(); channel++)
	{
		int numSamplesToProcess = blockSize;
		const int bufferSize = buffer_.size();
		channelBufferPos = bufferPos;
		float* outputSamples = proxies[channel]->getSampleData();
		float* inputSamples = inputs[Input].processBlock(shouldDelete, blockID, channel);
		float* preLevelSamples = inputs[PreLevel].processBlock(shouldDelete, blockID, channel);
		float* recLevelSamples = inputs[RecLevel].processBlock(shouldDelete, blockID, channel);
		float* loopSamples = inputs[Loop].processBlock(shouldDelete, blockID, 0);
		float* bufferSamples = buffer_.getData(channel);
		
		while(numSamplesToProcess) 
		{										
			if(*loopSamples++ >= 0.5f) 
			{
				if(channelBufferPos >= bufferSize)
					channelBufferPos = 0;
				
				float recLevel = *recLevelSamples++;
				float rec = *inputSamples++ * recLevel;
				float preLevel = *preLevelSamples++;
				float pre = bufferSamples[channelBufferPos] * preLevel;
				float out = pre + rec;
				*outputSamples++ = out;
				bufferSamples[channelBufferPos] = out;
				channelBufferPos++;
				
				if(channelBufferPos >= bufferSize)
					channelBufferPos = 0;
			}
			else
			{
				float rec = *inputSamples++ * *recLevelSamples++;
				float pre = bufferSamples[channelBufferPos] * *preLevelSamples++;
				float out = pre + rec;
				*outputSamples++ = out;
				bufferSamples[channelBufferPos] = out;
				channelBufferPos++;
			}
			
			--numSamplesToProcess;
		}		
	}
	
	bufferPos = channelBufferPos;
	
	if(bufferPos >= buffer_.size())
	{
		shouldDelete = shouldDelete ? true : shouldDeleteValue;
		setIsDone();
	}	
}
void MD2Object::digestFinal(
	void 		*digest)
{
	if(isDone()) {
		throw std::runtime_error("MD2 digestFinal after final");
	}
	CC_MD2_Final((unsigned char *)digest, &mCtx);
	setIsDone(true);
}
Exemple #4
0
void DiskInUGenInternal::changeListenerCallback (ChangeBroadcaster*)
{
	if(filePlayer.isPlaying() == false)
	{
		if(loopFlag_ == true)
		{
			filePlayer.setPosition(startTime_);
			filePlayer.start();
		}
		else
		{
			if(shouldDeleteValue)
				setIsDone();
		}
	}
	
}
void MD2Object::digestInit()
{
	setIsDone(false);
	CC_MD2_Init(&mCtx);
}
void LoopPointsUGenInternal::processBlock(bool& shouldDelete, const unsigned int blockID, const int /*channel*/) throw()
{
	const int numCuesPoints = metaData.getNumCuePoints();

	int numSamplesToProcess = uGenOutput.getBlockSize();
	float* outputSamples = uGenOutput.getSampleData();
	float* rateSamples = inputs[Rate].processBlock(shouldDelete, blockID, 0);
	float* startSamples = inputs[Start].processBlock(shouldDelete, blockID, 0);
	float* endSamples = inputs[End].processBlock(shouldDelete, blockID, 0);
	float* loopSamples = inputs[Loop].processBlock(shouldDelete, blockID, 0);
	float* startAtZeroSamples = inputs[StartAtZero].processBlock(shouldDelete, blockID, 0);
	float* playToEndSamples = inputs[PlayToEnd].processBlock(shouldDelete, blockID, 0);
		
	while(numSamplesToProcess--)
	{
		float rate = *rateSamples;
		float start = *startSamples * b.size();
		float end = *endSamples * b.size();
		bool loop = *loopSamples >= 0.5f;
		
		if(start > end)
		{
			float temp = start;
			start = end;
			end = temp;
			rate = -rate;
		}
		
		currentValue += rate;
		
		if(loop)
		{            
			if((rate > 0.f) && (currentValue >= end))
			{
				if(lastLoop == false)
				{
					bool fromZero = *startAtZeroSamples >= 0.5f;
					
					currentValue = fromZero ? 0.f : start;
				}
				else
				{
					currentValue -= (end - start);
				}
				
				prevValue = currentValue-1.f;
			}
			else if((rate < 0.f) && (currentValue < start))
			{
				if(lastLoop == false)
				{
					bool fromEnd = *startAtZeroSamples >= 0.5f;

					currentValue = fromEnd ? (b.size()-1) : end;
				}
				else
				{            
					currentValue += (end - start);
				}
				
				prevValue = currentValue+1.f;
			}
		}
		else if(*playToEndSamples < 0.5f)
		{
			if((rate > 0.f) && (currentValue >= end))
			{
				currentValue = (float)b.size();
				shouldDelete = shouldDelete ? true : shouldDeleteValue;
				setIsDone();
				
			}
			else if((rate < 0.f) && (currentValue < start))
			{
				currentValue = -1.f;
				shouldDelete = shouldDelete ? true : shouldDeleteValue;
				setIsDone();
			}			
		}
		else
		{
			if((rate > 0.f) && (currentValue >= (float)b.size()))
			{
				shouldDelete = shouldDelete ? true : shouldDeleteValue;
				setIsDone();
			}
			else if((rate < 0.f) && (currentValue < 0.f))
			{
				shouldDelete = shouldDelete ? true : shouldDeleteValue;
				setIsDone();
			}						
		}
		
		*outputSamples = currentValue;
		
		if(numCuesPoints) checkMetaDataCuePoints(currentValue, prevValue, numCuesPoints, rate >= 0.f);
		
		prevValue = currentValue;
		
		rateSamples++;
		startSamples++;
		endSamples++;
		loopSamples++;
		startAtZeroSamples++;
		playToEndSamples++;
		outputSamples++;
		
		lastLoop = loop;
	}
}
void PlayBufUGenInternal::processBlock(bool& shouldDelete, const unsigned int blockID, const int /*channel*/) throw()
{	
	const int numCuesPoints = metaData.getNumCuePoints();

	const int blockSize = uGenOutput.getBlockSize();
	const int bufferSize = buffer_.size();
	const double lastBufferPosition = bufferSize-1;
	
	double channelBufferPos = 0.0;
	
	for(int channel = 0; channel < getNumChannels(); channel++)
	{
		int numSamplesToProcess = blockSize;
		channelBufferPos = bufferPos;
		float* outputSamples = proxies[channel]->getSampleData();
		float* rateSamples = inputs[Rate].processBlock(shouldDelete, blockID, 0);
		float* trigSamples = inputs[Trig].processBlock(shouldDelete, blockID, 0);
		float* offsetSamples = inputs[Offset].processBlock(shouldDelete, blockID, 0);
		float* loopSamples = inputs[Loop].processBlock(shouldDelete, blockID, 0);
						
		double prevPos = prevPosArray[channel];
		
		while(numSamplesToProcess) 
		{				
			float thisTrig = *trigSamples++;
			
			if(thisTrig > 0.f && lastTrig <= 0.f)
				channelBufferPos = 0.0;
			
			double offset = *offsetSamples++;
			double position = offset + channelBufferPos;
			
			if(*loopSamples++ >= 0.5f) 
			{
				if(position >= bufferSize)
				{
					position -= bufferSize;
				} 
				else if(position < 0)
				{
					position += bufferSize;
				}
				
				*outputSamples++ = buffer_.getSample(channel, position);
				channelBufferPos += *rateSamples++;
			
				if(channelBufferPos >= bufferSize)
				{
					sendMetaData(buffer_, metaData, MetaData::ReachedEnd, channel);
					channelBufferPos -= bufferSize;
					sendMetaData(buffer_, metaData, MetaData::ReachedStart, channel);
					if(numCuesPoints > 0) checkMetaDataCuePoints(channelBufferPos, -1.0, channel, numCuesPoints, true);
					prevPos = channelBufferPos;
				}
				else if(channelBufferPos < 0)
				{
					sendMetaData(buffer_, metaData, MetaData::ReachedEnd, channel);
					channelBufferPos += bufferSize;
					sendMetaData(buffer_, metaData, MetaData::ReachedStart, channel);
					if(numCuesPoints > 0) checkMetaDataCuePoints(channelBufferPos, bufferSize, channel, numCuesPoints, false);
					prevPos = channelBufferPos;
				}
				else if(numCuesPoints > 0) 
				{
					checkMetaDataCuePoints(channelBufferPos, prevPos, channel, numCuesPoints, prevPos <= channelBufferPos);
					prevPos = channelBufferPos;
				}
			}
			else
			{
				if(numCuesPoints > 0) checkMetaDataCuePoints(channelBufferPos, prevPos, channel, numCuesPoints, prevPos <= channelBufferPos);
				prevPos = channelBufferPos;

				if((position <= 0.0) || (position > lastBufferPosition))
				{	
					*outputSamples++ = 0.0;
				}
				else
				{
					*outputSamples++ = buffer_.getSampleUnchecked(channel, position);
				}
				
				channelBufferPos += *rateSamples++;
			}
					
			--numSamplesToProcess;
			lastTrig = thisTrig;
		}		
		
		prevPosArray[channel] = prevPos;
	}
	
	bufferPos = channelBufferPos;
	
	if(bufferPos >= buffer_.size())
	{
		shouldDelete = shouldDelete ? true : shouldDeleteValue;
		setIsDone();
		sendMetaData(buffer_, metaData, MetaData::ReachedEnd);
	}
	else if(bufferPos < 0)
	{
		shouldDelete = shouldDelete ? true : shouldDeleteValue;
		setIsDone();
		sendMetaData(buffer_, metaData, MetaData::ReachedStart);		
	}
}
Exemple #8
0
void EnvGenUGenInternal::processBlock(bool& shouldDelete, const unsigned int blockID, const int channel) throw()
{
	int numSamplesToProcess = uGenOutput.getBlockSize();
	float* outputSamples = uGenOutput.getSampleData();
	
	if(isStealing() == false && shouldSteal() == true)
	{
		setIsStealing();
		const int numLevels = env_.getLevels().size();
		float stealValue = (float)currentValue;
		float targetValue = env_.getLevels().getSampleUnchecked(numLevels-1);
		float inc = (targetValue - stealValue) / (float)numSamplesToProcess;
		while(numSamplesToProcess)
		{
			*outputSamples++ = stealValue;
			stealValue += inc;
			--numSamplesToProcess;
		}
		shouldDelete = shouldDelete ? true : shouldDeleteValue;
		currentValue = targetValue;
		currentCurve = EnvCurve(EnvCurve::Empty);
		setIsDone();
	}
	else
	{
		if(isReleasing() == false && shouldRelease() == true)
		{
			int releaseNode = env_.getReleaseNode();

			if(releaseNode >= 0) // try this, - don't release if releaseNode is -1
			{
				setSegment(releaseNode, UGen::getSampleRate());
			}
		}		
		
		while(numSamplesToProcess && isDone() == false)
		{
			int samplesThisTime = min(stepsUntilTarget, numSamplesToProcess);
			numSamplesToProcess -= samplesThisTime;
			stepsUntilTarget -= samplesThisTime;
			
			// select from different curves here..., use a different loop
			
			switch(currentCurve.getType())
			{
				case EnvCurve::Numerical:
					while(samplesThisTime)
					{
						*outputSamples++ = (float)currentValue;
						b1 *= grow;
						currentValue = a2 - b1;
						--samplesThisTime;
					}
					break;
				case EnvCurve::Linear:
					while(samplesThisTime)
					{
						*outputSamples++ = (float)currentValue;
						currentValue += grow;
						--samplesThisTime;
					}
					break;
				case EnvCurve::Exponential:
					while(samplesThisTime)
					{
						*outputSamples++ = (float)currentValue;
						currentValue *= grow;
						--samplesThisTime;
					}
					break;
				case EnvCurve::Sine:
					while(samplesThisTime)
					{
						*outputSamples++ = (float)currentValue;
						double y0 = b1 * y1 - y2; 
						currentValue = a2 - y0;
						y2 = y1; 
						y1 = y0;
						--samplesThisTime;
					}
					break;
				case EnvCurve::Welch:
					while(samplesThisTime)
					{
						*outputSamples++ = (float)currentValue;
						double y0 = b1 * y1 - y2; 
						currentValue = a2 + y0;
						y2 = y1; 
						y1 = y0;
						--samplesThisTime;
					}
					break;
				case EnvCurve::Empty:
				case EnvCurve::Step:
				default:
					while(samplesThisTime)
					{
						*outputSamples++ = (float)currentValue;
						--samplesThisTime;
					}
			}
			
			if(stepsUntilTarget <= 0)
			{
				if(setSegment(currentSegment + 1, UGen::getSampleRate()) == true)
				{
					shouldDelete = shouldDelete ? true : shouldDeleteValue;
					const int numLevels = env_.getLevels().size();
					currentValue = env_.getLevels().getSampleUnchecked(numLevels-1);
					currentCurve = EnvCurve(EnvCurve::Empty);
					goto exit;
				}
			}
		}
	}
		
	while(numSamplesToProcess--)
	{
		*outputSamples++ = (float)currentValue;
	}
		
	return;
	
exit:
	while(numSamplesToProcess--)
	{
		*outputSamples++ = (float)currentValue;
	}
	setIsDone();
	
	sendDoneInternal();
}
Exemple #9
0
void EnvGenUGenInternalK::processBlock(bool& shouldDelete, const unsigned int blockID, const int channel) throw()
{
	const int krBlockSize = UGen::getControlRateBlockSize();
	unsigned int blockPosition = blockID % krBlockSize;
	int numSamplesToProcess = uGenOutput.getBlockSize();
	float* outputSamples = uGenOutput.getSampleData();
	
	int numKrSamples = blockPosition % krBlockSize;
	
	double prevValue = currentValue;
	
	if(isDone()) goto exit;

	while(numSamplesToProcess > 0)
	{
		prevValue = currentValue;
		if(numKrSamples == 0)
		{
			if(isStealing() == false && shouldSteal() == true)
			{
				setIsStealing();
				const int numLevels = env_.getLevels().size();
				float stealValue = (float)currentValue;
				float targetValue = env_.getLevels().getSampleUnchecked(numLevels-1);
				float inc = (targetValue - stealValue) / (float)numSamplesToProcess;
				while(numSamplesToProcess)
				{
					*outputSamples++ = stealValue;
					stealValue += inc;
					--numSamplesToProcess;
				}
				shouldDelete = shouldDelete ? true : shouldDeleteValue;
				currentValue = targetValue;
				currentCurve = EnvCurve(EnvCurve::Empty);
				setIsDone();
				return;
			}
			else
			{
				if(isReleasing() == false && shouldRelease() == true)
				{
					int releaseNode = env_.getReleaseNode();
//					if(releaseNode < 0)
//					{
//						releaseNode = env_.getTimes().size() - 1;
//					}
//					
//					setSegment(releaseNode, UGen::getSampleRate() / krBlockSize);
					
					if(releaseNode >= 0) // try this..
					{
						setSegment(releaseNode, UGen::getSampleRate() / krBlockSize);
					}
				}		
				
				--stepsUntilTarget;
									
				double y0;
				switch(currentCurve.getType())
				{
					case EnvCurve::Numerical:
						currentValue = a2 - b1;
						b1 *= grow;
						break;
					case EnvCurve::Linear:
						currentValue += grow;
						break;
					case EnvCurve::Exponential:
						currentValue *= grow;
						break;
					case EnvCurve::Sine:
						y0 = b1 * y1 - y2; 
						currentValue = a2 - y0;
						y2 = y1; y1 = y0;
						break;
					case EnvCurve::Welch:
						y0 = b1 * y1 - y2; 
						currentValue = a2 + y0;
						y2 = y1; y1 = y0;
						break;
					case EnvCurve::Empty:
					case EnvCurve::Step:
					default:
						;
				}
				
				if(stepsUntilTarget <= 0)
				{
					if(setSegment(currentSegment + 1, UGen::getSampleRate() / krBlockSize) == true)
					{
						shouldDelete = shouldDelete ? true : shouldDeleteValue;
						const int numLevels = env_.getLevels().size();
						currentValue = env_.getLevels().getSampleUnchecked(numLevels-1);
						currentCurve = EnvCurve(EnvCurve::Empty);
						goto exit;
					}
				}
				
			}
		}
		
		numKrSamples = krBlockSize - numKrSamples;
		blockPosition += numKrSamples;
		
		if(prevValue == currentValue)
		{
			while(numSamplesToProcess && numKrSamples)
			{
				*outputSamples++ = (float)prevValue;
				--numSamplesToProcess;
				--numKrSamples;
			}
		}
		else
		{
			double valueSlope = (currentValue - prevValue) / (double)UGen::getControlRateBlockSize();
			
			while(numSamplesToProcess && numKrSamples)
			{
				*outputSamples++ = (float)prevValue;
				prevValue += valueSlope;
				--numSamplesToProcess;
				--numKrSamples;
			}
		}
	}		
	
	return;

exit:
	
	if(prevValue == currentValue)
	{
		while(numSamplesToProcess > 0)
		{
			*outputSamples++ = (float)prevValue;
			--numSamplesToProcess;
		}
	}
	else
	{
		double valueSlope = (currentValue - prevValue) / (double)numSamplesToProcess;
		while(numSamplesToProcess > 0)
		{
			*outputSamples++ = (float)prevValue;
			prevValue += valueSlope;
			--numSamplesToProcess;
		}
	}
	
	setIsDone();
}
OSStatus DiskInUGenInternal::clearOutputsAndReadData(bool& shouldDelete) throw()
{
	const int outputBlockSize = uGenOutput.getBlockSize();
	const double sampeRateRatio = 1.0;//fileSampleRate * UGen::getReciprocalSampleRate();
	
	const int inputBlockSize = outputBlockSize * sampeRateRatio;
	
	if(inputBlockSize > allocatedBlockSize)
	{
		allocatedBlockSize = inputBlockSize;
		audioData = realloc(audioData, bytesPerFrame * allocatedBlockSize);
		if(!audioData)
		{
			printf("DiskIn: error: could not allocated memory for the new buffer size\n\n");
			AudioFileClose(audioFile_);
			audioFile_ = 0;
		}
	}
	
	for(int channel = 0; channel < numChannels_; channel++)
	{
		float *outputSamples = proxies[channel]->getSampleData();
		memset(outputSamples, 0, outputBlockSize * sizeof(float));
	}	
	
	if(!audioFile_)
	{
		numPackets = 0;
		return -1;
	}
	else
	{
		numPackets = inputBlockSize;
		UInt32 numBytesRead = -1;
		OSStatus result = AudioFileReadPackets(audioFile_, false,
											   &numBytesRead, NULL, 
											   currentPacket, &numPackets, audioData); 
		
		if(result == noErr)
		{  
			currentPacket += numPackets;
			
			if(numPackets < inputBlockSize)
			{
				if(loopFlag_)
				{
					// we hit the end of the file and looping is on, we need to pull 
					// a few samples from the start of the file
					
					const int remainingPackets = inputBlockSize - numPackets;
					
					unsigned char *remainingAudioData = (unsigned char*)audioData;
					remainingAudioData += remainingPackets * bytesPerFrame;
					
					numPackets = remainingPackets;
					result = AudioFileReadPackets(audioFile_, false, 
												  &numBytesRead, NULL, 
												  0, &numPackets, audioData);
					
					if(result == noErr)
					{ 
						currentPacket = remainingPackets;
					}
				}
				else
				{
					if(shouldDeleteValue)
						setIsDone();
					
					shouldDelete = shouldDelete ? true : shouldDeleteValue;
				}
			}
		}
		
		return result;
	}
	
}
Exemple #11
0
AttackObject* HeroBow::createAttackObject()
{
    std::string strAttID=getArmature()->getAnimation()->getCurrentMovementID();
    auto actionMode=getActionFileMode();
    //获取方向
    bool facing=getFacing();
    float attackDist=getHeroModel()->AttackDist;      //攻击距离

    //创建子弹
    auto bullet=BulletObject::create();
    bullet->setAttackType(1);
    bullet->setAttackObject(this);
    
    if (strAttID==actionMode->ActionAttackName1 || strAttID==actionMode->ActionAttackName2 || strAttID==actionMode->ActionAttackName3 || strAttID==actionMode->ActionAttackName4)
    {
        bullet->setRepelPower(8.0);
        float bulletX=GameBLL::instance()->getMaxMapWidth();
        if(!facing){
            bulletX*=-1;
        }
        auto b=Sprite::createWithSpriteFrameName("v_arrow_1.png");
        b->setFlippedX(!facing);
        bullet->setSprite(b);
        bullet->setPosition(getPosition()+vShootPos);
        bullet->setTargetPos(getPosition()+Vec2(bulletX,vShootPos.y), 3000);
        bullet->setAttack(getHeroModel()->Attack);
        BulletBLL::getInstance()->addBullet(bullet);
    }
    //技能1
    if (strAttID==actionMode->SkillName1) {
        bullet->setPenetrateAttack(true);
        bullet->setRepelPower(32);
        attackDist=skills[0].AttackDist;
        
        float width=1280.0;
        float rota=21.24;   //旋转角度
        if(!facing){
            attackDist*=-1;
            rota*=-1;
            width*=-1;
        }
        auto bulletStartPos=getPosition() + Vec2(0, 255);
        auto b=Sprite::createWithSpriteFrameName("v_arrow_2.png");
        b->setFlippedX(!facing);
        bullet->setSprite(b);
        bullet->setPosition(bulletStartPos);
        //bullet->setTargetPos(pos+Vec2(attackDist,0), 2000);
        bullet->setIsDone(true);
        bullet->setRotation(rota);
        int attack=skills[0].CurrAttack + getHeroModel()->Attack / 4;
        bullet->setAttack(attack);
        BulletBLL::getInstance()->addBullet(bullet);
        
        auto call=CallFunc::create(CC_CALLBACK_0(HeroBow::bulletCallback, this, bullet));
        ccBezierConfig bc;
        bc.endPosition=Vec2(bulletStartPos.x + width, bulletStartPos.y);
        
        if(!facing){
            bc.controlPoint_1 = Vec2(bulletStartPos.x - width * 0.2, bulletStartPos.y - 300);
            bc.controlPoint_2 = Vec2(bc.endPosition.x + width * 0.2, bulletStartPos.y - 300);
        }else{
            bc.controlPoint_1 = Vec2(bulletStartPos.x + width * 0.2, bulletStartPos.y - 300);
            bc.controlPoint_2 = Vec2(bc.endPosition.x - width * 0.2, bulletStartPos.y - 300);
        }
        //子弹动作
        auto bez=BezierTo::create(0.5, bc);
        auto seq=Sequence::create(bez,call, NULL);
        bullet->runAction(APRotateWithAction::create(seq));
        
    }else if (strAttID==actionMode->SkillName2){
        float bAngle=345;
        if(!facing){
            bAngle=215;
        }
        auto bulletPos=getPosition() + Vec2(0, 272);
        int attack=skills[1].CurrAttack + getHeroModel()->Attack / 4;
        for (int i=0; i<3; i++) {
            auto targetPos=APTools::getRoundPoint(bulletPos, bAngle - (i * 10), 1700);
            float rotation=APTools::getAngle(bulletPos, targetPos);
            auto b=Sprite::createWithSpriteFrameName("v_arrow_3.png");
            b->setFlippedX(!facing);
            
            //创建子弹
            auto newbullet=BulletObject::create();
            newbullet->setRepelPower(8.0);
            newbullet->setAttackType(1);
            newbullet->setPenetrateAttack(true);
            newbullet->setAttackObject(this);
            newbullet->setSprite(b);
            newbullet->setPosition(bulletPos);
            newbullet->setTargetPos(targetPos, 2000);
            newbullet->setRotation(rotation);
            newbullet->setAttack(attack);
            BulletBLL::getInstance()->addBullet(newbullet);

        }
    }else if (strAttID==actionMode->SkillName3){
        attackDist=skills[2].AttackDist;
        //创建攻击对象
        int attack=skills[2].CurrAttack + getHeroModel()->Attack / 4;
        auto att=AttackObject::create();
        att->setAttack(attack);
        att->setRepelPower(280);
        att->setAttackObject(this);
        //是否被击倒
        att->setIsHitDown(true);
        //攻击范围
        Vec2 pos=this->getPosition();
        float attStartPosX=getPositionX();
        if (!facing) {
            attStartPosX-=attackDist;
        }
        
        Rect attRect=Rect(attStartPosX,getPositionY(),attackDist, 100);
        att->setAttRange(attRect);
        return att;
        
    }else if (strAttID==actionMode->SkillName4){
        attackDist=skills[3].AttackDist;
        //创建攻击对象
        int attack=skills[3].CurrAttack + getHeroModel()->Attack / 4;
        auto att=AttackObject::create();
        att->setAttack(attack);
        att->setRepelPower(120);
        att->setAttackObject(this);
        //是否被击倒
        att->setIsHitDown(false);
        //攻击范围
        Vec2 pos=this->getPosition();
        auto worldPos=this->getParent()->convertToWorldSpace(pos);
        float attDist=1280-worldPos.x;
        float attStartPosX=pos.x;
        if (!facing) {
            attDist=worldPos.x;
            attStartPosX-=attDist;
        }
        
        Rect attRect=Rect(attStartPosX,getPositionY(),attDist, 100);
        att->setAttRange(attRect);
        
        return att;
    }
    
    return nullptr;
}