I am trying to develop a simple cross-platform game, and trying to move a PhysicsSprite with a Body to the position I touched/clicked, using Cocos2D-JS.
Here is the code that I have:
var TAG_SPRITE = 1;
var AnimationLayer = cc.Layer.extend({
space:null,
ctor:function (space) {
this._super();
this.space = space;
this.init();
},
init:function () {
this._super();
var winsize = cc.director.getWinSize();
//init physics sprite
var spriteHead = new cc.PhysicsSprite(res.Head_png);
var headContentSize = spriteHead.getContentSize();
//init body
var headBody = new cp.Body(1, cp.momentForBox(1, headContentSize.width, headContentSize.height));
headBody.p = cc.p(winsize.width / 2, winsize.height / 3);
this.space.addBody(headBody);
//init shape
var headShape = new cp.CircleShape(headBody, headContentSize.width / 2, cp.v(0, 0));
headShape.setFriction(0.3);
headShape.setElasticity(0.8);
this.space.addShape(headShape);
spriteHead.setBody(headBody);
this.addChild(spriteHead, 0, TAG_SPRITE);
//for mobile
if('touches' in cc.sys.capabilities ){
cc.eventManager.addListener({
event: cc.EventListener.TOUCH_ONE_BY_ONE,
swallowTouches: true,
onTouchBegan:function (touch, event) {
cc.log('touch began');
event.getCurrentTarget().moveSprite(touch.getLocation());
return true;
},
onTouchMoved: function (touch, event) {
},
onTouchEnded: function (touch, event) {
},
onTouchCancelled: function (touch, event) {
}
}, this);
}
//for desktop
else if ('mouse' in cc.sys.capabilities ) {
cc.eventManager.addListener({
event: cc.EventListener.MOUSE,
onMouseUp: function (event) {
event.getCurrentTarget().moveSprite(event.getLocation());
}
}, this);
}
},
moveSprite:function(position) {
cc.log('move to: ' + position.x + ',' + position.y);
var sprite = this.getChildByTag(TAG_SPRITE);
var moveAction = new cc.moveTo(1, position);
sprite.runAction(moveAction);
}
});
As I see the logs from the logcat, it can handle touch events but cannot move the sprite. When I convert the PhysicsSprite to just Sprite object and remove all other Body and Shape stuff, it can be moved to the location that I touch. The problem is that I can move the PhysicsSprite in the browser whereas I cannot do that in my Android phone.
Note: I use Chipmunk physics engine
I don't know this is the real solution or should be considered as a workaround but the code below works fine for both web and Android. But still don't know why the code in the question doesn't work for Android while it does for the web. (It would make more sense if it didn't work for both...)
I tried to move body of the sprite instead of itself. The new moveSprite
method is like that:
moveSprite: function(sprite){
cc.log('move to: ' + position.x + ',' + position.y);
var sprite = this.getChildByTag(TAG_SPRITE);
var body = sprite.getBody();
var velocity = 300;
this.moveWithVelocity(body, position, velocitiy);
}
moveWithVelocity
is the custom function that I created in the same Layer, moving the Body to the destination point with a particular velocity:
moveWithVelocity: function(body, destination, velocity){
var deltaX = destination.x - body.p.x;
var deltaY = destination.y - body.p.y;
var distance = Math.sqrt(Math.pow(deltaX,2) + Math.pow(deltaY,2));
var time = distance / velocity;
var velocityX = deltaX / time;
var velocityY = deltaY / time;
//start the action with the calculated velocity in the calculated direction
body.applyImpulse(cc.v(velocityX, velocityY), cc.v(0,0));
//stop the sprite (or body here) when duration of movement is time out (or when the sprite/body arrives its destination)
setTimeout(function(){
body.setVel(cc.v(0,0));
}, time*1000);
}
Hope this helps anyone encountered the same problem.