iPad: Comment déplacer un sprite en le glissant et continuer à aller en fonction de la vitesse de glissement

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

Question

J'ai un sprite (image d'une balle), je peux le déplacer à l'aide de toucher et de déplacer.J'ai également identifié le taux de changement d'emplacement (axe x, axe de Y) de ce sprite en fonction de la période de glissement.

Maintenant, j'ai besoin de continuer ce sprite à aller en fonction de sa vitesse et de sa direction.Voici mon code -

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

Cependant, j'utilise actuellement une technique de réglage de vitesse statique, mais j'espère le rendre dynamique en fonction de la vitesse initiale (j'apprécie toute idée)

Était-ce utile?

La solution 2

merci@all. J'ai ma solution comme ci-dessous -

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

  }

Autres conseils

On dirait que vous l'avez assez proche. Vous planifiez un sélecteur à l'extrémité tactile, calculant la vitesse et déplacez le sprite en fonction de cette vitesse jusqu'à ce qu'il soit imbibé, de sorte que toutes les pièces mécaniques sont là.

Quel est l'air sify est la physique. Par exemple, vous faites des choses étranges avec la vitesse pour ralentir la balle qui ne va pas regarder réaliste du tout.

Ce que vous voulez faire est de trouver le "vecteur de vitesse" pour le sprite lorsque le doigt est levé. Bien que vous puissiez tenter de faire une vitesse instantanée pour cela, j'ai constaté que cela fonctionne mieux pour échantillonner quelques cycles et la moyenne sur eux pour obtenir une vitesse finale.

Puis, une fois que vous avez ce vecteur (cela ressemblera à une vitesse de X et Y, comme vous l'avez maintenant), vous souhaitez atténuer la vitesse en faisant quelque chose comme ceci (pseudocode non testé):

 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

Cela gardera la balle dans la même direction que lorsqu'elle a été libérée, ralentissement progressivement jusqu'à ce qu'il s'arrête. Pour plus d'informations, surtout si vous voulez faire un rebond ou quelque chose, Google pour une introduction à l'algèbre de vecteur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top