ipad:如何通过滑动精灵移动精灵并继续按照滑动速度移动精灵

时间:2010-07-13 08:36:32

标签: ipad cocos2d-iphone iphone-sdk-3.2

我有一个精灵(球的形象)我可以用触摸和移动来移动它。我还根据滑动周期确定了该精灵的位置变化率(x轴,y轴)。

现在我需要继续根据它的速度和方向去精灵。这是我的代码 -

Touch Event

- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {

  CGPoint location = [touch locationInView: [touch view]];
  CGPoint convertedLocation = [[CCDirector sharedDirector] convertToGL:location];

  self.touchStartTime = [event timestamp];
  self.touchStartPosition = location;

  if (YES == [self isItTouched:self.striker touchedAt:convertedLocation]) {
    self.striker.isInTouch = YES;
  }

  return YES;
}

- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event {

  CGPoint location = [touch locationInView: [touch view]];
  CGPoint convertedLocation = [[CCDirector sharedDirector] convertToGL:location];

  self.touchLastMovedTime = [event timestamp];
  self.touchMovedPosition = convertedLocation;


  if(self.striker.isInTouch == YES){
    self.striker.position = self.touchMovedPosition;
  }

}
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event {

  CGPoint location = [touch locationInView: [touch view]];
  CGPoint convertedLocation = [[CCDirector sharedDirector] convertToGL:location];

  self.touchEndTime = [event timestamp];
  self.touchEndPosition = location;

  if( self.striker.isInTouch == YES 
    && ( self.touchEndTime - self.touchLastMovedTime ) <= MAX_TOUCH_HOLD_DURATION )
  {
    float c = sqrt( pow( self.touchStartPosition.x - self.touchEndPosition.x, 2 ) 
        + pow( self.touchStartPosition.y - self.touchEndPosition.y, 2 ) );

    self.striker.speedx =  ( c - ( self.touchStartPosition.y - self.touchEndPosition.y ) ) 
                         / ( ( self.touchEndTime - self.touchStartTime ) * 1000 );

    self.striker.speedy =  ( c - ( self.touchStartPosition.x - self.touchEndPosition.x ) ) 
             / ( ( self.touchEndTime -   self.touchStartTime ) * 1000 );

    self.striker.speedx *= 4;
    self.striker.speedy *= 4;

    self.striker.isInTouch = NO;
    [self schedule:@selector( nextFrame ) interval:0.001];

  }

}

Scheduled Method to move Sprite

- (void) nextFrame {

  [self setPieceNextPosition:self.striker];
  [self adjustPieceSpeed:self.striker];

  if( abs( self.striker.speedx ) <= 1 && abs( self.striker.speedy ) <= 1 ){
    [self unschedule:@selector( nextFrame )];
  }
}

SET next Position

- (void) setPieceNextPosition:(Piece *) piece{

  CGPoint nextPosition;
  float tempMod;
  tempMod = ( piece.position.x + piece.speedx ) / SCREEN_WIDTH;
  tempMod = (tempMod - (int)tempMod)*SCREEN_WIDTH;
  nextPosition.x = tempMod;

  tempMod = ( piece.position.y + piece.speedy ) / SCREEN_HEIGHT;
  tempMod = (tempMod - (int)tempMod)*SCREEN_HEIGHT;
  nextPosition.y = tempMod;

  piece.position = nextPosition;
}

Set new Speed

- (void) adjustPieceSpeed:(Piece *) piece{

  piece.speedx =(piece.speedx>0)? piece.speedx-0.05:piece.speedx+0.05;
  piece.speedy =(piece.speedy>0)? piece.speedy-0.05:piece.speedy+0.05;
}

虽然,目前我正在使用静态速度调整技术,但我希望根据初始速度使其动态(我欣赏任何想法)

2 个答案:

答案 0 :(得分:0)

看起来你已经非常接近了。你在触摸端安排一个选择器,计算速度,并根据速度移动精灵直到它衰减,所以所有的机械部件都在那里。

看起来物理是什么。例如,你正在做一些奇怪的事情,以减慢球的速度,这看起来并不真实。

你想要做的是在手指抬起时找到精灵的“速度矢量”。虽然你可以尝试为此做一个瞬时速度,但我发现它可以更好地采样几个周期并对其进行平均以获得最终速度。

然后,一旦你有了这个向量(它看起来像x和y的速度,就像你现在一样),你想通过做这样的事情来抑制速度(未经测试的伪代码):

 float speed = sqrt( speedx * speedx + speedy * speedy );
 if (speed == 0) {
     // kill motion here, unschedule or do whatever you need to
 }
 // Dampen the speed.
 float newSpeed = speed * .9;
 if (newSpeed < SOME_THRESHOLD) newSpeed = 0;
 speedx = speedx * newSpeed / speed;
 speedy = speedy * newSpeed / speed;
 //  Move sprite according to the new speed

这将使球保持与释放时相同的方向,逐渐减速直至停止。有关更多信息,特别是如果您想要进行一些弹跳或其他任何操作,请参阅Google以获取向量代数的介绍。

答案 1 :(得分:0)

谢谢@all。 我的解决方案如下 -

//in adjustSpeed method
  piece.speedx -= piece.speedx * DEACCLERATION_FACTOR;
  piece.speedy -= piece.speedy * DEACCLERATION_FACTOR;

//and simply, free the sprite to move from ccTouchMoved method not ccTouchEnd
  if(self.striker.isInTouch == YES && distance_passed_from_touch_start>=a_threashold){
    //calculate speed and position here as it was in ccTouchEnd method
    self.striker.isInTouch = NO;
    [self schedule:@selector( nextFrame ) interval:0.001];

  }