精灵跟踪触摸

Mak*_*ele 5 c++ cocos2d-x

我想在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);
Run Code Online (Sandbox Code Playgroud)

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

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

offsetPoint = Point(touchPoint.x - draggedItem->getPositionX(), touchPoint.y - draggedItem->getPositionY());
offsetRotation = atan2(offsetPoint.y, offsetPoint.x);
Run Code Online (Sandbox Code Playgroud)

我还在触摸移动中添加了这些线条(在顶部):

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;
Run Code Online (Sandbox Code Playgroud)

所以目的地是:

_destinationX = touchPoint.x + ax;
_destinationY = touchPoint.y + ay;
Run Code Online (Sandbox Code Playgroud)

但它不起作用,哪里出了问题?雪碧四处跳跃.

Otá*_*udo 2

由于我对 Obj-C 或 C++ 完全不熟悉,所以我将用 Swift 给你答案。然后,您将能够将其插入到您的项目中或“转换”为 Obj-C/C++。反正:

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

var touchingScreen:Bool = false // needs 'false' as initial value.
weak var sprite:CCSprite!; // represents a connection to the sprite.
Run Code Online (Sandbox Code Playgroud)

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

var diffTouchSpriteX:CGFloat!; // not necessary to initialize it with any default value.
var diffTouchSpriteY:CGFloat!; // same.
Run Code Online (Sandbox Code Playgroud)

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

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

现在是时候利用提供的触摸方法来处理特定时刻的触摸输入了。diffTouchSpriteX让我们为和diffTouchSpriteY变量赋值,并设置touchingScreentrue当用户触摸屏幕时,当用户在屏幕上移动手指时更新diffTouchSpriteX和值,最后设置为一旦触摸中断:diffTouchSpriteYtouchingScreenfalse

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;
}
Run Code Online (Sandbox Code Playgroud)

终于,最后一步了。在 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)));
  }
}
Run Code Online (Sandbox Code Playgroud)

cocos2dfixedUpdate()方法以恒定速率运行(每秒 1 次,如果我没记错的话)。这里的方法runAction()将通过将“x”添加到其当前位置的“x”值并将“y”添加到其当前位置的“y”值来更新精灵位置。因此,按照这个速度,精灵需要一秒钟才能到达当前触摸位置,但这当然是您可以轻松操纵的东西。