iPad: Cómo mover un sprite deslizándolo y continúa adelante de acuerdo con la velocidad deslizante

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

Pregunta

Tengo un sprite (imagen de una pelota) Puedo moverlo usando toque y mover.También he identificado la tasa de cambio de ubicación (eje X, eje y) de ese sprite, dependiendo del período de deslizamiento.

Ahora necesito continuar ese sprite para ir de acuerdo a su velocidad y dirección.Aquí está mi código -

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;
}

, sin embargo, actualmente estoy usando la técnica de ajuste de velocidad estática, pero espero que sea dinámica según la velocidad inicial (aprecio cualquier idea)

¿Fue útil?

Solución 2

gracias @all. Tengo mi solución por debajo -

//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];

  }

Otros consejos

Parece que lo tienes bastante cerca. Está programando un selector en el extremo táctil, calculando la velocidad y moviendo el sprite de acuerdo con esa velocidad hasta que se calme, por lo que todas las piezas mecánicas están ahí.

Lo que parece IFFY es la física. Por ejemplo, estás haciendo algunas cosas extrañas con la velocidad para retardar la pelota que no van a lucir realistas en absoluto.

Lo que quiere hacer es encontrar el "Vector de velocidad" para el sprite cuando se levanta el dedo. Si bien puede intentar hacer una velocidad instantánea para esto, he encontrado que funciona mejor para probar algunos ciclos hacia atrás y promediar sobre ellos para obtener una velocidad final.

Entonces, una vez que tengas ese vector (se verá como una velocidad X e Y, como lo tiene ahora), desea humedecer la velocidad haciendo algo como este (Pseudocódigo no probado por delante):

 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

Esto mantendrá la pelota en la misma dirección que cuando se liberó, disminuyendo gradualmente hasta que se detenga. Para obtener más información, especialmente si desea hacer algo de rebote o cualquier cosa, Google para obtener una introducción a vector Álgebra.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top