I want to set this game up so that when the user taps a specific point on the screen it dispenses a SKSpriteNode from the location. So what I've set up is this inside the touches began method:
for (UITouch *touch in touches) {
score = score + 1;
cat = [SKSpriteNode spriteNodeWithTexture:[SKTexture textureWithImageNamed:#"cat.png"] size:CGSizeMake(35, 35)];
cat.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)+120);
[self addChild:cat];
}
Which works fine and adds the node to any where the touch occurred.
I want it only to be added when the user touches a specific location, so I tried setting this up:
for (touch locationInNode:CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) {
score = score + 1;
cat = [SKSpriteNode spriteNodeWithTexture:[SKTexture textureWithImageNamed:#"cat.png"] size:CGSizeMake(35, 35)];
cat.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)+120);
[self addChild:cat];
}
But it didn't work and told me I needed a square bracket ] for some reason.
How can I set it up so it only spawns if the user touches the middle of the screen?
I think you can use
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch* touch = [touches anyObject];
CGPoint positionInScene = [touch locationInNode:self];
// Add your logic to check the specific location
// if( CGPointEqualToPoint (positionInScene, yourSpecificPosition)
// Render Cat
}
Hope it will help
Figured it out:
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
if (CGRectContainsPoint(crate.frame, location)) {
score = score + 1;
cat = [SKSpriteNode spriteNodeWithTexture:[SKTexture textureWithImageNamed:#"cat.png"] size:CGSizeMake(35, 35)];
cat.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)+120);
[self addChild:cat];
}
}
Related
So far, I have made my CCSprite move to the location of the user's touch on the screen using CCActionMoveTo, however I have only got it to work when the user simply taps.
I would like the CCSprite to move when the user drags their finger, instead of just tapping and moving along with the ability to change direction as the user drags changes direction - I am fairly new to cocos2d and have search for similar questions but have been unable to find any. I have posted my code below:
- (id)init
{
self = [super init];
if (!self) return(nil);
self.userInteractionEnabled = YES;
// Player sprite
_playerSprite = [CCSprite spriteWithImageNamed:#"PlayerSprite.png"];
_playerSprite.scale = 0.5;
_playerSprite.position = ccp(self.contentSize.width/2, 150);
[self addChild:_playerSprite];
return self;
}
-(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchLoc = [touch locationInNode:self];
CCActionMoveTo *actionMove = [CCActionMoveTo actionWithDuration:0.2f position:ccp(touchLoc.x, 150)];
[_playerSprite runAction:actionMove];
}
You will need to implement the touchMoved method and set your sprite position in there. Something like this:
- (void)touchMoved:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchLocation = [touch locationInNode:self];
_playerSprite.position = touchLocation;
}
Try this (add a CGPoint property called previousTouchPos):
-(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchLoc = [touch locationInNode:self];
self.previousTouchPos = touchLoc;
CCActionMoveTo *actionMove = [CCActionMoveTo actionWithDuration:1.0f position:touchLoc];
[_playerSprite runAction:actionMove];
}
-(void) touchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchLoc = [touch locationInNode:self];
CGPoint delta = ccpSub(touchLoc, self.previousTouchPos);
_playerSprite.position = ccpAdd(_playerSprite.position, delta);
self.previousTouchPos = touchLoc;
}
This sounds like an ideal use case for CCActionFollow:
https://www.makegameswith.us/gamernews/365/make-two-nodes-follow-each-other-in-cocos2d-30
If you use the variation where you provide the target position through a block you can use the latest touch position as target position.
I am loading a menu in which i have 7 layers through which i swipe. On first load the swiping is smooth at 60fps, but i then pop the scene and push it again, the swiping is very slow, though the app displays 60fps, and the ccTouchesMoved is called roughly at the same interval as on the first load.
On each layer, i add some statical CCSprites and a CCMenu.
All items are deallocated, and i am testing the app on ipad 3 (so speed isn't quite an issue).
I presume that the cause is more on the settings part and would like to find a solution for it. Here are my touch methods, if it helps:
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
//Swipe Detection Part 1
firstTouch = location;
}
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSSet *allTouches = [event allTouches];
UITouch * touch = [[allTouches allObjects] objectAtIndex:0];
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
CGSize winSize = [[CCDirector sharedDirector] winSize];
for(int i=0;i<[layerList count];i++)
{
[[layerList objectAtIndex:i] setPosition:CGPointMake((i-currentLayer)*winSize.width + (location.x - firstTouch.x),0) ];
}
}
-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
NSSet *allTouches = [event allTouches];
UITouch * touch = [[allTouches allObjects] objectAtIndex:0];
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
//Swipe Detection Part 2
lastTouch = location;
//Swipe Detection Part 2
lastTouch = location;
//Minimum length of the swipe
float swipeLength = ccpDistance(firstTouch, lastTouch);
//Check if the swipe is a left swipe and long enough
if (firstTouch.x > lastTouch.x && swipeLength > 60) {
[self doStuffLeft];
}
else if (firstTouch.x < lastTouch.x && abs(swipeLength) > 60) {
[self doStuffRight];
}
}
Figured it out, [CCDirector sharedInstance] was paused.
I have a UIView and on the top of him I've got UIButton, UITableView and UINavigationBar. what I want to do is, when you click on the UIButton and drag it, all the view will move to the left side only, until the screen ends. I mean that you can drag the view to the left and when you stop touching, the view will stop where your finger stopped touching the screen.
I can't do it, he shows me only the "Touches Began 1" and thats it. what seems to be my problem here?
Thanks alot everyone!
float oldX, oldY;
BOOL dragging;
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
NSLog("Touches Began 1");
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
if (CGRectContainsPoint(btnOpen.frame, touchLocation))
{
NSLog("Touches Began 2");
dragging = YES;
oldX = touchLocation.x;
oldY = touchLocation.y;
}
}
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
if (dragging)
{
NSLog("Dragging!");
CGRect frame = mainView.frame;
frame.origin.x = mainView.frame.origin.x + touchLocation.x - oldX;
frame.origin.y = mainView.frame.origin.y + touchLocation.y - oldY;
mainView.frame = frame;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog("Touches Ended!");
dragging = NO;
}
- (void)viewDidLoad
{
[btnOpen addTarget:self action:#selector(touchesBegan:withEvent:) forControlEvents: UIControlEventTouchDown];
[btnOpen addTarget:self action:#selector(touchesMoved:withEvent:) forControlEvents: UIControlEventTouchDragInside];
[btnOpen addTarget:self action:#selector(touchesEnded:withEvent:) forControlEvents: UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
}
You are asking for the coordinates of the touch in relation to the frame of main view
CGPoint touchLocation = [touch locationInView:self.view];
And then you ask if the location of the touchLocation is within the frame of the buttons frame
if (CGRectContainsPoint(btnOpen.frame, touchLocation))
In another words. You are checking if the touch was within the bounds of the button but you check by the coordinates of the touch made on the main view instead of the button.
So this is what you should do:
CGPoint touchLocation = [touch locationInView:btnOpen];
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
NSLog("Touches Began 1");
for (UITouch *touch in touches) {
//UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
if (CGRectContainsPoint(btnOpen.frame, touchLocation))
{
NSLog("Touches Began 2");
//dragging = YES;
oldX = touchLocation.x;
oldY = touchLocation.y;
}
}
}
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
// UITouch *touch = [[event allTouches] anyObject];
for (UITouch *touch in touches) {
CGPoint touchLocation = [touch locationInView:self.view];
if (CGRectContainsPoint(btnOpen.frame, touchLocation))
{
NSLog("Dragging!");
CGRect frame = mainView.frame;
frame.origin.x = mainView.frame.origin.x + touchLocation.x - oldX;
frame.origin.y = mainView.frame.origin.y + touchLocation.y - oldY;
mainView.frame = frame;
}
}
}
Try like this i think it will be helpful to you.
my code:
-(void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
//Add a new body/atlas sprite at the touched location
for( UITouch *touch in touches ) {
CGPoint touchLocation = [touch locationInView: [touch view]];
CGPoint prevLocation = [touch previousLocationInView: [touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];
prevLocation = [[CCDirector sharedDirector] convertToGL: prevLocation];
CGPoint diff = ccpSub(touchLocation,prevLocation);
[self setPosition: ccpAdd(self.position, diff)];
}
}
This code lets me move the layer with my fingers. That works fine. But now I want to let the user only move the layer within a predefined CGRect. How to do that?
For example:
CGRect rect = CGRectMake(0,0,600,320);
Now the player should be only allowed to move the layer within this rect. In that example he could only move it (on an ipod touch) to the left and right. (till 600px).
What do I need to change to achieve that?
Thank you for any help.
Have a nice day :)
Keep a variable to check.. eg..
distmoved = distmoved + touchlocation.x - prevlocation.x;
if(distmoved<600)
//move code
note that distmoved is a float..
You should make your own check. It's not hard in your case:
[self setPosition: ccpAdd(self.position, diff)];
if (self.position.x < minX)
{
//correct x position
}
if (...)
// ...
// ans so on
I have a small image on a view. The view is the object process multi-touch actions. If a finger drag on the view, the image will translate its position. And if user use 2 fingers to make pinch gesture, the image will scale its size. And I do work as section code below:
//touch detect methods
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"Touch began");
//Devide into 2 cases: 1 touch and 2 touches.
if ([touches count] == 1) {
NSLog(#"Touch began cout = 1");
currentImageCenter = focusImage.center;
UITouch *touch = [[touches allObjects] objectAtIndex:0];
previousPoint = [touch locationInView:self];
isTwoFingerTouching = FALSE;
}
else if([touches count] == 2){
NSLog(#"Touch began cout = 2");
UITouch *touch = [[touches allObjects] objectAtIndex:0];
beginFirstPoint = [touch locationInView:self];
touch = [[touches allObjects] objectAtIndex:1];
beginSecondPoint = [touch locationInView:self];
isTwoFingerTouching = TRUE;
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if ([touches count] == 1 && isTwoFingerTouching == FALSE) {
UITouch *touch = [touches anyObject];
CGPoint currentPosition = [touch locationInView:self];
//Calculate distance
double deltaX = currentPosition.x - previousPoint.x;
double deltaY = currentPosition.y - previousPoint.y;
NSLog(#"Touch move detect 1 touch ");
focusImage.center = CGPointMake(currentImageCenter.x+deltaX, currentImageCenter.y+deltaY);
}
else if([touches count] == 2){
NSLog(#"Touch move detect 2 touches");
CGPoint currentFirstPoint;
CGPoint currentSecondPoint;
UITouch *touch = [[touches allObjects] objectAtIndex:0];
currentFirstPoint = [touch locationInView:self];
CGPoint previousFirstPoint = [touch previousLocationInView:self];
touch = [[touches allObjects] objectAtIndex:1];
currentSecondPoint = [touch locationInView:self];
CGPoint previousSecondPoint = [touch previousLocationInView:self];
//Compare previous points with current points.
//Pinch gesture
CGFloat beginDistance = distanceBetweenPoints(previousFirstPoint, previousSecondPoint);
CGFloat currentDistance = distanceBetweenPoints(currentFirstPoint, currentSecondPoint);
if (currentDistance > 0 && beginDistance > 0) {
double scale = currentDistance/beginDistance;
NSLog(#"%f", scale);
//Rotation
CGPoint vector1 = CGPointMake(previousFirstPoint.x - previousSecondPoint.x, previousFirstPoint.y - previousSecondPoint.y);
CGPoint vector2 = CGPointMake(currentFirstPoint.x - currentSecondPoint.x, currentFirstPoint.y - currentSecondPoint.y);
//[vector1, vector2].
double zValue = vector1.x*vector2.y - vector1.y*vector2.x;
CGFloat rotateAngle = angleBetweenLines(previousFirstPoint, previousSecondPoint, currentFirstPoint, currentSecondPoint);
//zValue < 0, vector1 rotate counter-clockwise, so the angle should be negative.
if (zValue < 0) {
rotateAngle = -rotateAngle;
}
//Don't allow to zoom out if the image is too small
if (scale > 1 || focusImage.frame.size.width > 30) {
CGAffineTransform previousTransform = focusImage.transform;
CGAffineTransform mixTransform = CGAffineTransformConcat(CGAffineTransformMakeScale(scale, scale), CGAffineTransformMakeRotation(rotateAngle));
focusImage.transform = CGAffineTransformConcat(previousTransform, mixTransform);
}
}
}
}
But the problem is: I can't identify whether 1 finger or 2 fingers on screen. When I touch 2 fingers, and I move (for rotate and scale) those fingers, [touches count] in touchesMoved: method still equal 1 occasionally. Any one experienced this, please tell me how to solve my problem?
Any reason why you are not using UIGestureRecognizers? It will save you a lot of work if you just use a UIPanGestureRecognizer and a UIPinchGestureRecognizer.
In any case, iOS has always behaved like that. Unless you touch with both fingers at the exact same millisecond, you will detect a one finger touch first then detect two finger touch. You need to employ some sort of a cancelling mechanism in your code if you still want to go the -touchesBegan..., -touchesMoved..., etc., method.