iPad: come spostare uno sprite facendolo scorrere e continua ad andare in base alla velocità scorrevole

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

Domanda

Ho uno sprite (immagine di una palla) Posso spostarlo usando il tatto e muoversi.Ho anche identificato il tasso di cambio della posizione (asse X, asse Y) di tale sprite a seconda del periodo di scorrimento.

Ora ho bisogno di continuare quella sprite per andare in base alla sua velocità e direzione.Ecco il mio codice -

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

Tuttavia, attualmente sto usando la tecnica di regolazione della velocità statica, ma spero di renderlo dinamico a seconda della velocità iniziale (apprezzo qualsiasi idea)

È stato utile?

Soluzione 2

Grazie @all. Ho la mia soluzione come sotto -

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

  }
.

Altri suggerimenti

Sembra che tu lo abbia abbastanza vicino. Stai programmando un selettore sul tattile, calcolando la velocità e spostando lo sprite in base a quella velocità fino a quando non si smorza, quindi tutti i pezzi meccanici ci sono.

Cosa sembra IFFY è la fisica. Ad esempio, stai facendo alcune cose strane con la velocità per rallentare la palla che non sembrerà affatto realistico.

Cosa vuoi fare è trovare il "vettore di velocità" per lo sprite quando il dito viene sollevato. Mentre puoi tentare di fare una velocità istantanea per questo, ho scoperto che funziona meglio per eseguire il campione di alcuni cicli e nella media su di loro per ottenere una velocità finale.

Allora, una volta che hai quel vettore (sembrerà una velocità x e y, come se tu abbia ora), vuoi smorzare la velocità facendo qualcosa del genere come questo (pseudocode non testato in anticipo):

 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
.

Ciò manterrà la palla nella stessa direzione di quando è stato rilasciato, rallentando gradualmente fino a quando non si ferma. Per ulteriori informazioni, specialmente se si desidera eseguire il rimbalzo o qualsiasi cosa, Google per un'introduzione all'algebra vettoriale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top