How to invert Y axis in UIGestureRecogniser Cocos2d - cocos2d-iphone

I have following code:
- (void)panning:(UIPanGestureRecognizer *)recognizer {
CGPoint position;
//CGPoint velocity;
//velocity = [recognizer velocityInView:[CCDirector sharedDirector].view];
switch( recognizer.state ) {
case UIGestureRecognizerStatePossible:
break;
case UIGestureRecognizerStateBegan:
{
position = [recognizer locationInView:[CCDirector sharedDirector].view];
for (CCSprite *sprite in movableSprites) {
if (CGRectContainsPoint(sprite.boundingBox, position)) {
selSprite = sprite;
break;
}
}
break;
}
case UIGestureRecognizerStateChanged:
{
position = [recognizer locationInView:[CCDirector sharedDirector].view];
CGPoint yInvertedPosition = CGPointMake(position.x, -position.y);
[selSprite setPosition:position];
break;
}
case UIGestureRecognizerStateFailed:
break;
case UIGestureRecognizerStateEnded:
break;
case UIGestureRecognizerStateCancelled:
break;
}
}
When I drag a sprite it moves ok on X axis, but it's inverted on Y axis.
How can I convert it?
CGPoint yInvertedPosition = CGPointMake(position.x, -position.y);
this doesnt work

You just need to convert your position to GL Coordinates.
case UIGestureRecognizerStateBegan:
{
position = [recognizer locationInView:[CCDirector sharedDirector].view];
position = [[CCDirector sharedDirector] convertToGL:position];
for (CCSprite *sprite in movableSprites) {
if (CGRectContainsPoint(sprite.boundingBox, position)) {
selSprite = sprite;
break;
}
}
break;
}
case UIGestureRecognizerStateChanged:
{
position = [recognizer locationInView:[CCDirector sharedDirector].view];
position = [[CCDirector sharedDirector] convertToGL:position];
[selSprite setPosition:position];
break;
}

Related

Trying to get user input to move sprite in Cocos2D-X

I'm trying to make user input of WASD move a sprite around in Cocos2D-X. I'm pretty sure I'm doing everything correct but it gives me this error:
expression must be a modifiable lvalue.
Here is my code (Note: I'm new to Cocos2D-X, so it might be a bit messy)
float playerX = visibleSize.width / 2 + origin.x;
float playerY = visibleSize.height / 2 + origin.y;
auto player = Sprite::create("sprites/player.png");
if (player == nullptr)
{
problemLoading("'sprites/player.png'");
}
else
{
// position the sprite on the center of the screen
player->setPosition(Vec2(playerX, playerY));
// add the sprite as a child to this layer
this->addChild(player, 0);
}
// Keyboard events
auto keyboardListener = EventListenerKeyboard::create();
keyboardListener->onKeyPressed = [playerX, playerY](EventKeyboard::KeyCode keyCode, Event* event)
{
switch (keyCode)
{
case EventKeyboard::KeyCode::KEY_W:
playerY += 5.0f;
break;
case EventKeyboard::KeyCode::KEY_A:
playerX -= 5.0f;
break;
case EventKeyboard::KeyCode::KEY_S:
playerY -= 5.0f;
break;
case EventKeyboard::KeyCode::KEY_D:
playerX += 5.0f;
break;
case EventKeyboard::KeyCode::KEY_ESCAPE:
Director::getInstance()->end();
break;
}
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(keyboardListener, this);
There is four of the error and they all point to a different playerX/Y +=/-= 5.0f
Try to use mutable specifier(which allows lambdas body to modify the objects captured by copy, and to call their non-const member functions):
float playerX = visibleSize.width / 2 + origin.x;
float playerY = visibleSize.height / 2 + origin.y;
auto player = Sprite::create("sprites/player.png");
if (player == nullptr)
{
problemLoading("'sprites/player.png'");
}
else
{
// position the sprite on the center of the screen
player->setPosition(Vec2(playerX, playerY));
// add the sprite as a child to this layer
this->addChild(player, 0);
}
// Keyboard events
auto keyboardListener = EventListenerKeyboard::create();
// add mutable specifier
keyboardListener->onKeyPressed = [playerX, playerY, player](EventKeyboard::KeyCode keyCode, Event* event) mutable
{
switch (keyCode)
{
case EventKeyboard::KeyCode::KEY_W:
playerY += 5.0f;
break;
case EventKeyboard::KeyCode::KEY_A:
playerX -= 5.0f;
break;
case EventKeyboard::KeyCode::KEY_S:
playerY -= 5.0f;
break;
case EventKeyboard::KeyCode::KEY_D:
playerX += 5.0f;
break;
case EventKeyboard::KeyCode::KEY_ESCAPE:
Director::getInstance()->end();
break;
}
player->setPosition(playerX, playerY);
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(keyboardListener, this);

How to detect touch outside (empty space) - cocos2d

This is my code for detect that if touch on a specific sprite
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
for(CCSprite *sprite in shapeArray)
{
if(CGRectContainsPoint(sprite.boundingBox, location))
{
//There is a sprite that is touched
mSpriteOnHand = sprite;
currentPoint = mSpriteOnHand.position;
break;
}
//This part didn't work
else
{
NSLog(#"Touch outside);
}
}
}
Now I want to detect if touch is outside(not on any sprite or empty space) but I don't know how to do it.
If your touches are working, than I think adding a BOOL and then an if statement outside the for loop, like this will work.
BOOL itemFound = NO;
for(CCSprite *sprite in shapeArray)
{
if(CGRectContainsPoint(sprite.boundingBox, location))
{
//There is a sprite that is touched
mSpriteOnHand = sprite;
currentPoint = mSpriteOnHand.position;
NSLog(#"item TOUCHED");
itemFound = YES;
break;
}
}
if (itemFound == NO)
{
NSLog(#"Touch outside");
}

Cocos2d Sprites Collision

I have multiple sprites placed onto a background sprite like this:
//my background
CCSprite *bg = [CCSprite spriteWithFile:#"imageName.png"];
[self addchild:bg];
And then I add my items onto bg
//this is how i add my items
CCSprite *items = [CCSprite spriteWithFile:#"itemName.png"];
[bg addchild:items];
Oh and not forgetting my car sprite
//my car
CCSprite *car = [CCSprite spriteWithFile:#"car.png"];
[self addchild:car];
I use a loop to add multiple sprites onto the bg.
Now the question is how do I detect whether the car collided with the multiple sprites that I have placed onto the bg?
I've tried using CGRectIntersectsRect and it doesn't work.
I've tried using the pythagoras theorem method and once again it doesn't work.
There was a method which involved adding the items sprites into a NSMutableArray and it doesn't work either.
Can anyone suggest a method whereby I can try?
Additional code:
-(void) initializeCarAndItems
{
car = [CCSprite spriteWithFile:#"android.png"];
car.position = ccp(screenSize.width/2, screenSize.height * 0.30);
[self addChild:car z:1];
carRect = [car boundingBox];
}
-(void) initializeMap
{
bg1 = [CCSprite spriteWithFile:#"racingBG.png"];
bg1.anchorPoint = ccp(0, 0);
bg1.position = ccp(0, 0);
[self addChild:bg1 z:-1];
bg2 = [CCSprite spriteWithFile:#"racingBG2.png"];
bg2.anchorPoint = ccp(0,0);
bg2.position = ccp(0, bg1.boundingBox.size.height - 1);
[self addChild:bg2 z:-1];
convertedWidth = (int)bg1.boundingBox.size.width;
convertedHeight = (int)bg1.boundingBox.size.height;
for (y = 0; y < 15; y++)
{
positionX = arc4random()%convertedWidth;
positionY = arc4random()%convertedHeight;
items = [CCSprite spriteWithFile:#"item.png"];
items.position = ccp(positionX, positionY + 300);
[bg1 addChild:items z:100];
[itemsArray addObject:items];
}
for (y = 0; y < 15; y++)
{
positionX = arc4random()%convertedWidth;
positionY = arc4random()%convertedHeight;
items = [CCSprite spriteWithFile:#"item.png"];
items.position = ccp(positionX, positionY);
[bg2 addChild:items z:100];
[itemsArray addObject:items];
}
}
-(void) accelerate
{
bg1.position = ccp(0, bg1.position.y - accelerateNumber);
bg2.position = ccp(0, bg2.position.y - accelerateNumber);
if (bg1.position.y < -bg1.boundingBox.size.height)
{
questionCount++;
bg1.position = ccp(0, bg2.position.y + bg2.boundingBox.size.height - 1);
[self question];
[bg1 removeAllChildrenWithCleanup:YES];
for (y = 0; y < 15; y++)
{
positionY = arc4random()%convertedHeight;
positionX = arc4random()%convertedWidth;
items.position = ccp(positionX, positionY);
items = [CCSprite spriteWithFile:#"item.png"];
[bg1 addChild:items z:100];
[itemsArray addObject:items];
}
}
else if (bg2.position.y < -bg2.boundingBox.size.height)
{
questionCount++;
bg2.position = ccp(0, bg1.position.y + bg1.boundingBox.size.height - 1);
[self question];
[bg2 removeAllChildrenWithCleanup:YES];
for (y = 0; y < 15; y++)
{
positionY = arc4random()%convertedHeight;
positionX = arc4random()%convertedWidth;
items.position = ccp(positionX, positionY);
items = [CCSprite spriteWithFile:#"item.png"];
[bg2 addChild:items z:100];
[itemsArray addObject:items];
}
}
}
-(void) update:(ccTime)deltaTime
{
[self ifEdgeOfScreen];
[self accelerate];
for (CCSprite *itemFromArray in itemsArray)
{
CGRect itemRect = [itemFromArray boundingBox];
if (CGRectIntersectsRect(carRect, itemRect))
{
NSLog(#"Collision!");
}
}
if (leftButton.active == TRUE)
{
[self moveLeftRight:1];
}
else if (rightButton.active == TRUE)
{
[self moveLeftRight:2];
}
}
UPDATE:
It's fixed :)
-(void) update:(ccTime)deltaTime
{
car = [car boundingbox];
[self ifEdgeOfScreen];
[self accelerate];
for (CCSprite *itemFromArray in itemsArray)
{
if (CGRectIntersectsRect(carRect, [itemFromArray boundingbox]))
{
NSLog(#"Collision!");
}
}
if (leftButton.active == TRUE)
{
[self moveLeftRight:1];
}
else if (rightButton.active == TRUE)
{
[self moveLeftRight:2];
}
}
I found so many problems with the code....
When you call removeAllChildren.. Make sure you also remove objects from array.. Removing sprite from parents does not remove it from array.
update the car rect in update Method. So in your update method
-(void) update:(ccTime)deltaTime
{
[self ifEdgeOfScreen];
[self accelerate];
carRect = [car boundingBox];
...........
}
Hope this helps.. :)

box2d collision detection, code

im new to programming, i have tried the ray wenderlich tutorial but im still confused.
i have a sprite called rock, and a sprite called player, im trying to detect collision between them. but im extremely confused. in need of some help.
-(void)addRock {
CCSprite *rock = [CCSprite spriteWithFile:#"rock.png"
rect:CGRectMake(0, 0, 27, 40)];
// Determine where to spawn the target along the X axis
CGSize winSize = [[CCDirector sharedDirector] winSize];
int minX = rock.contentSize.width/2;
int maxX = winSize.width - rock.contentSize.width/2;
int rangeX = maxX - minX;
int actualX = (arc4random() % rangeX) + minX;
// Create the target slightly off-screen along the right edge,
// and along a random position along the X axis as calculated above
rock.position = ccp(actualX, 500);
[self addChild:rock];
// Determine speed of the sprite
int actualDuration = 5;//speed of sprite
}
- (id)init {
if ((self=[super init])) {
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCSprite *player = [CCSprite spriteWithFile:#"Player.png"
rect:CGRectMake(0, 0, 27, 40)];
player.position = ccp(winSize.width/2, winSize.height/4+15);
[self addChild:player];
[self schedule:#selector(gameLogicRock:) interval:0.2];
they are the two sprites, they spawn and position correctly, i only need to detect collision
You have to implement a new class for the collision or say contact listener based on some criteria as tag no. i have an example for you.
// ContactListener.h
#import "Box2D.h"
class ContactListener : public b2ContactListener
{
private:
void BeginContact(b2Contact* contact);
void EndContact(b2Contact* contact);
};
// ContactListener.mm
#import "ContactListener.h"
#import "cocos2d.h"
#import "BodyNode.h"
#import "GameScene.h"
void ContactListener::BeginContact(b2Contact* contact)
{
b2Body* bodyA = contact->GetFixtureA()->GetBody();
b2Body* bodyB = contact->GetFixtureB()->GetBody();
if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL)
{
BodyNode* bNodeA = (BodyNode*)bodyA->GetUserData();
BodyNode* bNodeB = (BodyNode*)bodyB->GetUserData();
if ((bNodeA.tag == GameSceneNodeTagBall && bNodeB.tag == GameSceneNodeTagHole) ||
(bNodeA.tag == GameSceneNodeTagHole && bNodeB.tag == GameSceneNodeTagBall))
{
switch (bNodeA.tag) {
case GameSceneNodeTagBall:
if ([bNodeA isKindOfClass:[Ball class]]) {
Ball* ball = (Ball*)bNodeA;
ball.sprite.visible = NO;
[[GameScene sharedGameScene] gameOver];
}
break;
case GameSceneNodeTagHole:
if ([bNodeB isKindOfClass:[Ball class]]) {
Ball* ball = (Ball*)bNodeB;
ball.sprite.visible = NO;
[[GameScene sharedGameScene] gameOver];
}
break;
default:
break;
}
}
}
}
This is an example of ball and hole collision. You can use this as per your requirement.
Hope this will help you.
Thanks!

Animating sprite while jumping

How to animate a sprite while jumping?
i.e, moving the eyes or animating the sprite using CCAnimate
CCSpriteFrameCache.sharedSpriteFrameCache().addSpriteFrames("AnimBear.plist");
this._bear = CCSprite.sprite("bear1.png", true);
spritesheet1 = CCSpriteSheet.spriteSheet("AnimBear.png");
spritesheet1.addChild(_bear, 1);
addChild(spritesheet1, 1);
ArrayList<CCSpriteFrame> animFrames = new ArrayList<CCSpriteFrame>();
CCSpriteFrameCache.sharedSpriteFrameCache();
for (int i = 1; i <= 8; i++) {
CCSpriteFrame frame = CCSpriteFrameCache
.spriteFrameByName(
"bear" + i + ".png");
animFrames.add(frame);
}
CCAnimation anim = CCAnimation.animation("AnimBear", .175f,
animFrames);
_bear.setPosition(CGPoint.make(_bear.getContentSize().width, 50));
CCIntervalAction action=CCAnimate.action(0.1f, anim, false);
this.walkAction = CCRepeatForever.action(action);
_bear.runAction(walkAction);
and moving on touch
public boolean ccTouchesEnded(MotionEvent event) {
CGPoint touchLocation = CCDirector.sharedDirector().convertToGL(
CGPoint.make(event.getX(), event.getY()));
float bearVelocity = 480.0f/3.0f;
CGPoint moveDifference = CGPoint.ccpSub(touchLocation, _bear.getPosition());
float distanceToMove = CGPoint.ccpLength(moveDifference);
float moveDuration = distanceToMove / bearVelocity;
if (moveDifference.x < 0) {
_bear.flipX_= false;
} else {
_bear.flipX_ = true;
}
_bear.stopAction(moveAction);
if (!_moving) {
_bear.runAction(walkAction);
}
CCMoveTo actionMove=CCMoveTo.action(moveDuration, touchLocation);
CCCallFuncN actionMoveDone1 = CCCallFuncN.action(this, "bearMoveEnded");
CCSequence actions = CCSequence.actions(actionMove, actionMoveDone1);
_bear.stopAllActions();
this.moveAction = actions;
_bear.runAction(moveAction);
_moving = true;
return CCTouchDispatcher.kEventHandled;
}
In this animation complete first and after this if you touch on the screen then the activity you want it'll happen.....
If you want the animation n move the sprite simultaneously, complete your all code in the
public boolean ccTouchesEnded(MotionEvent event) {
}