Move A Sprite By Touching And Dragging It?

As the title says, i’m not too familiar with the capabilities and the way Touch methods work, so i would like to ask for an example of moving a sprite by dragging it. thank you in advance

Algorithm:

  1. save a pointer to the sprite or have a known tag to it so you retrieve it
  2. have a member variable called “lastTouchPos” in your layer class
  3. in onTouchBegan check if the touch point is within the sprite’s bounding box - if so, save lastTouchPos and return true
  4. in onTouchMoved, calculate a delta point between touch point and lastTouchPos; update sprite’s position by the delta; store touch point in lastTouchPos

If you would like more concrete code, I can post an example when I’m in front of my computer

if you could post your code i would be grateful, as i seem to have misinterpreted your algorithm.

Certainly. I’ll post the relevant parts:

MyLayer.h

class MyLayer : cocos2d::Layer
{
private:
    cocos2d::Sprite *_spriteToMove;

public:
    virtual bool init();
    
    CREATE_FUNC(MyLayer);

    bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *event);
    void onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *event);
};

MyLayer.cpp

USING_NS_CC;

bool MyLayer::init()
{
    if (!Layer::init())
    {
        return false;
    }

    // setup sprite to be moved
    _spriteToMove = ...
    _spriteToMove->setPosition...
    this->addChild(_spriteToMove)

    EventListenerTouchOneByOne *listener = EventListenerTouchOneByOne::create();    
    listener->onTouchBegan = CC_CALLBACK_2(MyLayer::onTouchBegan, this);
    listener->onTouchMoved = CC_CALLBACK_2(MyLayer::onTouchMoved, this);
    
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

    return true;
}

bool MyLayer::onTouchBegan(Touch *touch, Event *event)
{
    Point touchLoc = touch->getLocationInView();
    
    if (_spriteToMove->getBoundingBox().containsPoint(touchLoc))
    {
        return true;
    }
    
    return false;
}

void MyLayer::onTouchMoved(Touch *touch, Event *event)
{
    _spriteToMove->setPosition(_spriteToMove->getPosition() + touch->getDelta());
}

This should be roughly right.

1 Like

Thank you very much, i will elaborate on the code and post back. In the meantime i stumbled upon another issue i can’t seem to be able to resolve, and i wonder if you could answer me that too and be my hero for the night :stuck_out_tongue:.How am i supposed to sequence two actions to repeat forever?

Sure no, problem:

// example actions
auto action1 = MoveTo::create...
auto action2 = RotateBy::create...

auto actionSeq = Sequence::create(action1, action2, NULL);
auto repeatActions = RepeatForever::create(actionSeq);

// mySprite could be a Sprite or a Layer or almost any Node
mySprite->runAction(repeatActions);

Thank you for taking the time to help me, but i’ve already tried this way and it seems you cannot use repeatForever with sequence for some reason…You can try it yourself and see it doesn’t work, so i was thinking of trying to schedule it somehow but i don’t really understand the schedule mechanics yet.

You absolutely can create a RepeatForever from a Sequence. I’ve done it :slight_smile: Can you post your code snippet and maybe we can see why it’s not working?

certainly. here it is:

auto actionUp = MoveBy::create(2, Vec2(0, visibleSize.height / 3));

auto actionDown = MoveBy::create(2, Vec2(0, -visibleSize.height / 3));

auto sequence = Sequence::create(actionUp, actionDown, NULL);

auto repeat = RepeatForever::create(sequence);

gasTank->runAction(repeat);

I copied your code verbatim into a test app and ran it and it seems to work. Are you getting a compiler error? Or is gasTank not moving? Or is it only moving once? Or do you not see gasTank at all?

BTW, I updated my sample code for the sprite dragging, because when I was looking at my test app, I realized that Touch has a getDelta() method that calculates the delta to the last touch position. This means you don’t need to store the last touch position at all. even simpler!

1 Like

It worked and i have no idea what i did wrong before, bit nevermind :stuck_out_tongue: . You’ve been extremely helpful thank you very much, keep up the good work helping us newbies :stuck_out_tongue:

My pleasure!

Hi there, I have done this above example of code into my project. When I end the movement of my sprite it completely stops and I can’t move it again. Is there anyway to solve this?

Hi,

Did you make some changes to the example code posted? Can you post some of the relevant code?

1 Like

Hi, Mr,
i have done this above example of code into my project and success, can you help me,
after Sprite is moved to new position, how to move it again to other position?
thank you very much, im still newbie :persevere: ,

@eOzdemir, @nevermore_dev – There is a small mistake in the sample code.

This line:

Point touchLoc = touch->getLocationInView();

Should be:

Point touchLoc = touch->getLocation();

The difference is coordinate system that the functions return. The first is with the origin at the upper left (like most phones’ UIs) and the second is with the origin at the lower left (like cocos2d-x and OpenGL).

2 Likes

thank you very much mastah @toojuice , i have done and the project running smoothly hehe :smile: :smile:
really, you like angel for newbie … btw, im looking for reference in google and other but nothing solution, but here im found great, :blush:

My code is writen as you posted. But the touchLoc in the sprite’s boundingbox is strange weird. it is not in sprite as I see.
mSprite->setPosition(Vec2(
Director::getInstance()->getVisibleSize().width / 2,
Director::getInstance()->getVisibleSize().height / 2));
this is my code for sprite’s position.I have no idea why.Could you help me check

Did you make the change referenced in this post?

yes of course
my code:
bool TouchScene::onTouchBegan(Touch* touch, Event* event)
{
labelTouchInfo->setPosition(touch->getLocation());
labelTouchInfo->setString(“You Touched Here”);
return true;
}
and I print the touch position at lower left, upper right and win size.
lower left: x:4.781072, y:168.248871
upper right: x:632.747925, y:635.480408
win size:height:640.000000, width:960.000000
why is lower left y coordinate start from 168?
thanks :slight_smile: