2010-07-13 3 views
0

J'ai un sprite (image d'une balle) Je peux le déplacer en utilisant le toucher et le mouvement. J'ai également identifié le taux de changement de position (axe des abscisses, axe des y) de ce sprite en fonction de la période de glissement.ipad: comment déplacer un sprite en le faisant glisser et continuer à aller en fonction de la vitesse de glissement

Maintenant, j'ai besoin de continuer ce sprite pour aller selon sa vitesse et 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; 
} 

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

+0

des informations plus loin, s'il vous plaît laissez-moi savoir – Sadat

Répondre

0

merci @all. J'ai obtenu ma solution comme 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]; 

    } 
0

Il semble que vous avez assez proche. Vous planifiez un sélecteur sur l'extrémité tactile, calculez la vélocité et déplacez le sprite en fonction de cette vélocité jusqu'à ce qu'il s'évapore, de sorte que toutes les pièces mécaniques sont présentes.

À quoi ressemble la physique? Par exemple, vous faites des choses étranges avec la vitesse pour ralentir la balle qui ne va pas être réaliste du tout.

Ce que vous voulez faire est de trouver le "vecteur de vélocité" pour l'image-objet quand le doigt est levé. Alors que vous pouvez essayer de faire une vélocité instantanée pour cela, j'ai trouvé que cela fonctionne mieux pour échantillonner quelques cycles en arrière et moyenne sur eux pour obtenir une vitesse finale.

Ensuite, une fois que vous avez ce vecteur (il ressemblera à un x et la vitesse y, comme vous avez maintenant), vous voulez amortir la vitesse en faisant quelque chose comme ça (non testé avant pseudocode):

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 permettra de garder la balle dans le même sens que quand elle a été relâchée, ralentissant progressivement jusqu'à ce qu'elle s'arrête. Pour plus d'informations, surtout si vous voulez faire un peu de rebond ou quoi que ce soit, google pour une introduction à l'algèbre vectorielle.

+0

Merci @intsdq, je vais essayer bientôt et vous faire savoir. – Sadat

+0

@intsdq si je ne me trompe pas, ce qui est similaire à « SpeedX = SpeedX * 0,9; rapide = rapide * 0,9; » alors pourquoi devrais-je utiliser Newspeed ou les calculs? S'il vous plaît laissez-moi savoir si vous avez d'autres explications. – Sadat

+0

Ce n'est pas différent, sauf pour la partie où vous voulez connaître la vitesse actuelle afin d'amortir la vitesse à zéro explicitement. Généralement, vous voudrez faire quelque chose de spécial lorsque vous passerez de "vitesse non nulle" à "vitesse zéro", c'est donc le cadre que j'utilise toujours. Dans l'exemple ci-dessus, je ne fais que mettre la vitesse à zéro, mais il y a de fortes chances que vous vouliez désinscrire le sélecteur que vous appelez ou définir un autre drapeau "au repos". Bien sûr, vous pourriez juste le détecter avec une sorte de chose "si speedx

Questions connexes