ipad:如何通过滑动来移动精灵并根据滑动速度继续前进

发布于 2024-09-09 04:56:46 字数 3035 浏览 2 评论 0原文

我有一个精灵(球的图像),我可以使用触摸和移动来移动它。我还确定了该精灵的位置(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;
}

虽然,目前我正在使用静态速度调整技术,但我希望根据初始速度使其动态(我很欣赏任何想法)

I have a sprite(image of a ball) I can move it using touch and move. I have also identified the rate of change of location(x-axis,y-axis) of that sprite depending on sliding period.

Now I need to continue that sprite to go according to its speed and direction. Here is my 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;
}

Though, currently I am using static speed adjusting technique, but I hope to make it dynamic depending on initial speed( I appreciate any idea)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

七禾 2024-09-16 04:56:46

看起来你已经很接近了。您在触摸端安排一个选择器,计算速度,并根据该速度移动精灵,直到它减弱,因此所有机械部件都在那里。

看起来可疑的是物理原理。例如,你正在做一些奇怪的事情,以减慢球的速度,这看起来根本不现实。

您想要做的是找到手指抬起时精灵的“速度矢量”。虽然您可以尝试为此执行瞬时速度,但我发现最好对几个周期进行采样并对其进行平均以获得最终速度。

然后,一旦你得到了这个向量(它看起来像 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

这将使球继续前进与释放时的方向相同,逐渐减速直至停止。有关更多信息,特别是如果您想做一些弹跳或其他任何操作,请搜索向量代数简介。

It looks like you have it pretty close. You're scheduling a selector on the touch end, computing the velocity, and moving the sprite according to that velocity until it damps out, so all the mechanical pieces are there.

What looks iffy is the physics. For instance, you're doing some odd things with the speed to slow the ball down which aren't going to look realistic at all.

What you want to do is find the "velocity vector" for the sprite when the finger is lifted. While you can attempt to do an instantaneous velocity for this, I've found that it works better to sample a few cycles back and average over them to get a final speed.

Then, once you've got that vector (it will look like an x and y speed, like you have now), you want to dampen the speed by doing something like this (untested pseudocode ahead):

 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

This will keep the ball going in the same direction as when it was released, slowing down gradually until it stops. For more information, especially if you want to do some bouncing or anything, google for an introduction to vector algebra.

堇年纸鸢 2024-09-16 04:56:46

谢谢@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];

  }

thanks @all.
I have got my solution as below-

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

  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文