Hey everyone,
I'm new to cocos2d and Objective-C so I apologize if there is a simple solution.
I am working on some code for a game I am developing. In this game I have a sprite on screen, and I would like this sprite to move opposite of the touch location.
Example:
Picture Example
So far my code looks like this:
-(void) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
//Determine location of the tap/touch
CGPoint touchLocation = [touch locationInView: [touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];
touchLocation = [self convertToNodeSpace:touchLocation];
I add my sprite to the scene in the init method like so:
CGSize screenSize = [[CCDirector sharedDirector] winSize];
Ball* ball = [Ball ball];
ball.position = CGPointMake(ball.contentSize.width / 2, screenSize.height / 2);
[self addChild:ball z:2];
I would like it so that wherever I touch on the screen, the sprite will move 20pixels opposite of that touch location. So if I touch to the left of the sprite, the sprite moves right, if I touch to the top, the sprite will move down..etc.
Thanks for the help!
Use actions. In your touch began method create an action:
CGPoint vector;
vector.x = ball.position.x - touchLocation.x;
vector.y = ball.position.y - touchLocation.y;
float vectorLength = sqrt(vector.x*vector.x + vector.y*vector.y);
if (fabs(vectorLength) < 0.1) return; //tapped directly to the center of sprite
vector.x *= 20 / vectorLength;
vector.y *= 20 / vectorLength;
id action = [CCMoveBy actionWithDuration: 0.5 position: vector];
[ball runAction: action];
Related
I'm new in cocos2d and I'm working in a coloring app, I'm Using CCRenderTexture for drawing:
target = [[CCRenderTexture alloc] initWithWidth:size.width height:size.height pixelFormat:kCCTexture2DPixelFormat_RGBA8888];
[target setPosition:ccp(size.width/2, size.height/2)];
[target clear:255 g:255 b:255 a:1];
[self addChild:target];
but I need to move the position of the drawing area (CCRenderTexture) a little up to show a submenu that hides in the bottom of the screen, so im using CCMove:
[CCMoveTo actionWithDuration:0.2 position:ccp(self.position.x, self.position.y+menuOffset)]
the rendertexture moves up as expected, but the "touchable area" stays in the same place, so when im touching the submenu area(outside the rendertexture frame) im still drawing inside the rendertexture.
this is the method for drawing
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint start = [touch locationInView: [touch view]];
start = [[CCDirector sharedDirector] convertToGL: start];
CGPoint end = [touch previousLocationInView:[touch view]];
end = [[CCDirector sharedDirector] convertToGL:end];
// begin drawing to the render texture
[target begin];
// scale/rotation/offset
float distance = ccpDistance(start, end);
if (distance > 1)
{
int d = (int)distance;
for (int i = 0; i < d; i++)
{
float difx = end.x - start.x;
float dify = end.y - start.y;
float delta = (float)i / distance;
[brush setPosition:ccp(start.x + (difx * delta), start.y + (dify * delta))];
[brush setRotation:rand()%360];
[brush setScale:drawratio];
[brush setColor:brush.color];
[brush visit];
}
}
[target end];
}
so, how can I change the position of CCRendertexture in a proper way?
Thanks in advance.
You just need to convert the GL coordinates to your target object's node space
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint start = [touch locationInView: [touch view]];
start = [[CCDirector sharedDirector] convertToGL: start];
start = [target convertToNodeSpace: start];
CGPoint end = [touch previousLocationInView:[touch view]];
end = [[CCDirector sharedDirector] convertToGL:end];
end = [target convertToNodeSpace: end];
// begin drawing to the render texture
[target begin];
// scale/rotation/offset
float distance = ccpDistance(start, end);
if (distance > 1)
{
int d = (int)distance;
for (int i = 0; i < d; i++)
{
float difx = end.x - start.x;
float dify = end.y - start.y;
float delta = (float)i / distance;
[brush setPosition:ccp(start.x + (difx * delta), start.y + (dify * delta))];
[brush setRotation:rand()%360];
[brush setScale:drawratio];
[brush setColor:brush.color];
[brush visit];
}
}
[target end];
}
Im working with cocos2d v1.0.1 & the respective Box2d version. In the simulator it all works. Its just a body created at a touch location that drops down to the ground. But I ran it on the device, iphone4, and the objects float upwards.
Why would this happen?
Gravity is set to -0.3f. I have another dynamic body in the scene and it appears on the bottom of the ground as it should. Its just the touch objects that float up. Sleep is True.
I just set sleep to false and now the rover also floats up. But it should not float up. here is my world creation method:
- (void)setupWorld {
b2Vec2 gravity = b2Vec2(0.0f, -0.3f);
bool doSleep = false;
world = new b2World(gravity, doSleep);
}
and here is my body creation from init:
Box2DSprite *roverSprite = [Box2DSprite spriteWithSpriteFrameName:#"rover.png"];
[self createBoxAtLocation:ccp(100,15) withSize:CGSizeMake(50, 50) forSprite:roverSprite isBox:TRUE];
[sceneSpriteBatchNode addChild:roverSprite];
and here is the createBox method:
- (void)createBoxAtLocation:(CGPoint)location withSize:(CGSize)size forSprite:(Box2DSprite *)sprite isBox:(BOOL)isBox{
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
b2Body *body = world->CreateBody(&bodyDef);
//
body->SetUserData(sprite);
sprite.body = body;
b2FixtureDef fixtureDef;
//
if (isBox) {
b2PolygonShape shape;
shape.SetAsBox(sprite.contentSize.width/3/PTM_RATIO,
sprite.contentSize.height/3/PTM_RATIO);
fixtureDef.shape = &shape;
} else {
b2CircleShape shape;
shape.m_radius = sprite.contentSize.width/2/PTM_RATIO;
fixtureDef.shape = &shape;
}
fixtureDef.density = 1.0;
fixtureDef.friction = 1.0;
fixtureDef.restitution = 0.5;
body->CreateFixture(&fixtureDef);
}
The same method is also used for the touch created objects which are created from these lines:
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchLocation = [touch locationInView:[touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
touchLocation = [self convertToNodeSpace:touchLocation];
//b2Vec2 locationWorld = b2Vec2(touchLocation.x/PTM_RATIO, touchLocation.y/PTM_RATIO);
Box2DSprite *sprite = [Box2DSprite spriteWithSpriteFrameName:#"koko1.png"];
[self createBoxAtLocation:touchLocation withSize:CGSizeMake(50, 50) forSprite:sprite isBox:TRUE];
[sceneSpriteBatchNode addChild:sprite];
return TRUE;
}
Are you in portrait or landscape mode? If in landscape, perhaps you have the device rotated left instead of right. The device orientation can swap the y-values of the accelerometer on you. Not sure if this is related to your issue.
Turns out I had the Target Settings Rotation to Right instead of Left.
I have a problem that I can't seem to solve.
I would like to move a sprite on the screen based on finger movements, but instead of making the sprite move towards the touch position I would like the sprite to move in the same way the finger moves on the screen.
Example:
User puts his/her finger on the screen (any position) and then drags the finger on the screen by 200 pixel to the left, the sprite should also move of 200 pixels to the left.
My approach was to store the position of the player at the start and then calculating the difference between the start position and the current position of the finger to add to the starting position of the sprite itself.
Here is my code
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
if([touches count] == 1){
UITouch *touch = [touches anyObject];
CGPoint startPos = [touch locationInView:[touch view]];
startPosition = startPos;
}
}
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
if([touches count] == 1){
UITouch *touch = [touches anyObject];
CGPoint touchPos = [touch locationInView:[touch view]];
CGPoint playerPos = player.position;
float yDifference = startPosition.y - touchPos.y;
playerPos.y = playerPos.y - yDifference;
// just to change to GL coordinates instead of the ones used by Cocos2D
// still doesn't work even if I remove this...
CGPoint convertedPoint = [[CCDirector sharedDirector] convertToGL:playerPos];
[player setPosition:convertedPoint];
}
}
I hope the problem I have is clear but if it is not don't hesitate do ask questions or further explaining. I've been stuck on this for quite a while :'(
Also, if you want it to move "relative" to where it started as opposed to exactly where the touch is:
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
if([touches count] == 1){
UITouch *touch = [touches anyObject];
CGPoint startPos = [touch locationInView:[touch view]];
startPosition = startPos;
playerStartPos = playerPos;
}
}
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
if([touches count] == 1){
UITouch *touch = [touches anyObject];
CGPoint touchPos = [touch locationInView:[touch view]];
CGPoint newPlayerPos;
newPlayerPos.x = playerStartPos.x + (touchPos.x - startPosition.x);
newPlayerPos.y = playerStartPos.y + (touchPos.y - startPosition.y);
// just to change to GL coordinates instead of the ones used by Cocos2D
// still doesn't work even if I remove this...
CGPoint convertedPoint = [[CCDirector sharedDirector] convertToGL:newPlayerPos];
[player setPosition:convertedPoint];
}
Your code is looking like it's "feeding back" onto itself by continually adding the difference to the playerPos.y
So just don't use the difference, use the current touch position :
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
if([touches count] == 1){
UITouch *touch = [touches anyObject];
CGPoint playerPos = [touch locationInView:[touch view]];
// just to change to GL coordinates instead of the ones used by Cocos2D
// still doesn't work even if I remove this...
CGPoint convertedPoint = [[CCDirector sharedDirector] convertToGL:playerPos];
[player setPosition:convertedPoint];
}
I have a problem in the Touch Event.
I have 5 sprites and I want to move a single sprite and only the selected sprite. But in this when i move touch then only one Sprite is move How move only select Sprite..
in .h file
CCSprite *puzzButton1,*puzzButton2,*puzzButton3;
in .m file
// create and initialize our seeker sprite, and add it to this layer
puzzButton1 = [CCSprite spriteWithFile: #"ingame_button_idal.png"];
puzzButton1.position = ccp( 480/2, 320/2 );
[self addChild:puzzButton1];
// create and initialize our seeker sprite, and add it to this layer
puzzButton2 = [CCSprite spriteWithFile: #"ingame_button_idal.png"];
puzzButton2.position = ccp( 100, 200 );
[self addChild:puzzButton2];
// create and initialize our seeker sprite, and add it to this layer
puzzButton3 = [CCSprite spriteWithFile: #"ingame_button_idal.png"];
puzzButton3.position = ccp( 100, 300 );
[self addChild:puzzButton3];
and in
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
return TRUE;
}
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint location = [self convertTouchToNodeSpace: touch];
[puzzButton1 stopAllActions];
[puzzButton1 runAction: [CCMoveTo actionWithDuration:0.1 position:location]];
}
Try this:
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
CGRect touchpoint = CGRectMake(160, 66, 564, 220); // your sprite position
if(CGRectContainsPoint(touchpoint, location))
{
yoursprite.position = ccp(location.x,location.y);// write move code
//here and check same
//condition for all
//your sprite.
}
}
or assign tags for your sprits and check them.
Forgive my elementary question as I'm pretty new to cocos2d, but I'm having an issue moving a sprite around. The method seems to do what I want...as long as it's moving in a positive x and positive y direction (top right corner). If I try to move it down or left, it doesn't work.
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *myTouch = [touches anyObject];
CGPoint point = [myTouch locationInView:[myTouch view]];
point = [[CCDirector sharedDirector] convertToGL:point]; //create point location
CCNode *sprite = [self getChildByTag:kTagSprite]; //set sprite
CGRect spriteRect = CGRectMake(sprite.position.x, sprite.position.y, sprite.contentSize.width, sprite.contentSize.height); //create box around sprite and get position
if(CGRectContainsPoint(spriteRect, point)){
[sprite setPosition:point]; //if my pointer is inside of the sprite box, move the sprite
}
}
Thank you.
edit: adding my init and tag reference
-(id) init{
if((self = [super init])){
self.isTouchEnabled = YES;
CCSprite *mySprite = [CCSprite spriteWithFile:#"sprite.png"];
mySprite.position = ccp(240, 40);
[self addChild:mySprite z:0 tag:kTagSprite];
}
return self;
}
and i declared the kTagSprite in:
enum{
kTagSprite
};
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *myTouch = [touches anyObject];
CGPoint point = [myTouch locationInView:[myTouch view]];
point = [[CCDirector sharedDirector] convertToGL:point]; //create point location
CCSprite *sprite = [self getChildByTag:kTagSprite]; //set sprite
if(CGRectContainsPoint([sprite boundingBox], point)){
[sprite setPosition:point]; //if my pointer is inside of the sprite box, move the sprite CCLOG(#"THIS WILL BE CALLED");
}
}
run the code and look at the console to see if the log will be called..