iPad: Как переместить спрайт, скользив его и продолжайте идти по скорости скольжения

StackOverflow https://stackoverflow.com/questions/3235428

Вопрос

У меня есть спрайт (изображение мяча), я могу переместить его, используя прикосновение и двигаться.Я также определил скорость изменения местоположения (ось 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

Спасибо @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];

  }
.

Другие советы

Похоже, у вас есть довольно близко. Вы планируете селектор на концепцию сенсорных, вычисляющих скорость и перемещая спрайт в соответствии с этой скоростью, пока она не затухает, поэтому все механические части есть.

Что выглядит IFFY, является физикой. Например, вы делаете несколько странных вещей со скоростью, чтобы замедлить мяч, который вообще не будет выглядеть реалистично.

Что вы хотите сделать, это найти «вектор скорости» для спрайта, когда палец поднят. Хотя вы можете попытаться сделать мгновенную скорость для этого, я обнаружил, что работает лучше, чтобы попробовать несколько циклов назад и в среднем над ними, чтобы получить окончательную скорость.

Тогда, как только у вас есть этот вектор (он будет выглядеть как скорость 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 для введения в векторную алгебру.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top