精灵跟踪触摸

Sprite tracking touch

本文关键字:触摸 跟踪 精灵      更新时间:2023-10-16

我想在cocos2d-x中实现一个带有旋转的精灵的跟踪(跟随)触摸。你可以在这里看到这个效果:https://www.youtube.com/watch?v=RZouMyyNGG8(2:10)。

下面是我在touchMove中的代码:
_destinationX = touchPoint.x;
_destinationY = touchPoint.y;
_dx = _destinationX - draggedItem->getPositionX();
_dy = _destinationY - draggedItem->getPositionY();
_vx = _dx;
_vy = _dy;
float d = sqrtf((_dx*_dx)+(_dy*_dy));
//nice easing when near destination
if (d < 50 && d > 3){
    _vx *= d / 50.0f;
    _vy *= d / 50.0f;
}
else if(d <= 3){
    _vx = _vy = 0;
}
draggedItem->setPosition(draggedItem->getPosition() + Point(_vx, _vy));
float rad = atan2(_dy, _dx);
float rotateTo = CC_RADIANS_TO_DEGREES(-rad);
if (rotateTo > draggedItem->getRotation() + 180) rotateTo -= 360;
if (rotateTo < draggedItem->getRotation() - 180) rotateTo += 360;
draggedItem->setRotation(rotateTo);

它可以工作,但是精灵的目标点在它的中心,所以如果我on touchBegin不会从它的中心开始,它看起来不太好

所以我在计算触点开始和初始旋转的偏移量:

offsetPoint = Point(touchPoint.x - draggedItem->getPositionX(), touchPoint.y - draggedItem->getPositionY());
offsetRotation = atan2(offsetPoint.y, offsetPoint.x);

我还在touch move(在顶部)中添加了这些行:

float alfa = offsetRotation;
float beta = CC_DEGREES_TO_RADIANS(draggedItem->getRotation());
float gamma = alfa + beta;
float radius = offsetPoint.length();
float ax = cosf(gamma) * radius;
float ay = sinf(gamma) * radius;

所以目的地是:

_destinationX = touchPoint.x + ax;
_destinationY = touchPoint.y + ay;

但是它不工作,哪里有问题?

由于我对Obj-C或c++都不熟悉,我将在Swift中给您答案。然后,您将能够将其插入您的项目或"翻译"为Obj-C/c++。总之:

在代表游戏场景的文件中,声明一个变量来跟踪用户当前是否触摸屏幕。我还假设你想要跟随触摸的精灵是由某个变量表示的(这里名为"sprite"):

var touchingScreen:Bool = false // needs 'false' as initial value.
weak var sprite:CCSprite!; // represents a connection to the sprite.

然后,你还需要一个变量来表示当前被触摸的点的值与你的精灵在x轴和y轴上所处的点之间的差值:

var diffTouchSpriteX:CGFloat!; // not necessary to initialize it with any default value.
var diffTouchSpriteY:CGFloat!; // same.

下一步是在必要时更新这两个变量的值。让我们为此创建一个方法:

func updateDiff(touchX: CGFloat, touchY: CGFloat) {
  self.diffTouchSpriteX = touchX - self.sprite.position.x;
  self.diffTouchSpriteY = touchY - self.sprite.position.y;
}

现在是时候利用在特定时刻处理触摸输入提供的触摸方法了。让我们为diffTouchSpriteXdiffTouchSpriteY变量赋值,并在用户触摸屏幕时将touchingScreen设置为true,当用户在屏幕上移动手指时更新diffTouchSpriteXdiffTouchSpriteY值,最后在触摸中断时将touchingScreen设置为false:

override func touchBegan(touch: CCTouch!, withEvent event: CCTouchEvent!) {
  self.updateDiff(touch.locationInWorld().x, touch.locationInWorld().y);
  self.touchingScreen = true;
}
override func touchMoved(touch: CCTouch!, withEvent event: CCTouchEvent!) {
  self.updateDiff(touch.locationInWorld().x, touch.locationInWorld().y);
}
override func touchEnded(touch: CCTouch!, withEvent event: CCTouchEvent!) {
  self.touchingScreen = false;
}
override func touchCancelled(touch: CCTouch!, withEvent event: CCTouchEvent!) {
  self.touchingScreen = false;
}

最后一步。在Cocos2d方法fixedUpdate()中,添加一个条件,当屏幕当前被触摸时移动角色:

override func fixedUpdate(delta: CCTime) {
  if (self.touchingScreen) {
    self.sprite.runAction(CCActionMoveBy(duration: 1/ 60, position: CGPoint(x: self.diffTouchSpriteX / 60, y: self.diffTouchSpriteY / 60)));
  }
}

fixedUpdate() cocos2d方法以恒定速率运行(如果我没记错的话,每秒运行1次)。这里的runAction()方法将通过在当前位置的"x"值上添加"x",在当前位置的"y"值上添加"y"来更新精灵的位置。所以,在这个速度下,精灵需要一秒钟才能到达当前的触摸位置,但这当然是你可以轻松操作的东西。