In the game I am working on you can move a character from left to right by touching the left/right sides of the screen. What I'm trying to do is to make it that if you're touching the left side and then touch the right side, the character starts moving right instead of left; the action to move left is overridden. I have currently made it so that the game is single-touch but the method of overriding the previous touch is where I'm stuck at. My code:
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
if (location.x < screenWidth/2){
leftMovement = YES;
[player runLeft];
}
else {
rightMovement = YES;
[player runRight];
}
self.userInteractionEnabled = NO;
}
- (void) touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self playerStop];
self.userInteractionEnabled = YES;
}
- (void) update:(NSTimeInterval)currentTime {
if (isTouched && leftMovement){
player.physicsBody.velocity=CGVectorMake(-PLAYERSPEED,
player.physicsBody.velocity.dy);
}
else if (isTouched && rightMovement){
player.physicsBody.velocity=CGVectorMake(PLAYERSPEED,
player.physicsBody.velocity.dy);
}
}
One thing you should consider is to change the value of both leftMovement and rightMovement when the user touches the other side of the screen, otherwise, the right movement in update method will never be invoked.
if (location.x < screenWidth/2){
leftMovement = YES;
rightMovement = NO;
[player runLeft];
}
else {
rightMovement = YES;
leftMovement = NO;
[player runRight];
}
Related
I have a character in my game that I can move left/right and jump. I am using touchesBegan to do that. But when I move left ( keep touching the screen -> makes character faster and faster ), it only jumps when i release it. I would like to jump and move left at the same time.
Here is some of my code :
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.view];
if((point.x < moveLeftButton.frame.size.width))
{
if((point.y > JumpButton.frame.size.height))
{
leftSide = YES;
sanchez.image = [UIImage imageNamed:#"characterL2"];
}
}
if((point.x) > (backGround.frame.size.width - moveRightButton.frame.size.width))
{
if((point.y > JumpButton.frame.size.height))
{
rightSide = YES;
sanchez.image = [UIImage imageNamed:#"characterR2"];
}
}
if( notJumping && (point.y < JumpButton.frame.size.height) && (sanchezStopAll == NO))
{
AudioServicesPlaySystemSound(jump);
sanchezJumping = 5.5;
notJumping = NO;
}
[self animation];
}
I am not using buttonPressed because they are hidden and I think you can't click hidden buttons.
This is how it looks like if its not hidden:
Thanks for any Help.
You'll only get a single touch by default unless you set multipleTouchEnabled = YES. Then your code should work as expected.
For example:
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.multipleTouchEnabled = YES;
}
How do I constantly get the location of the user's touch? I'm working on controllers for a game, and as it stands I must lift and individually place my finger on the new control in order to make it work. It seems that the touchLocation variable only updates upon each tap, and I want it to update constantly, so that even if I slide my finger around it will know the location and update it accordingly. Here is the relevant code. Thank you!
-(void)update:(CCTime)delta{
if([playerDirection isEqual:#"left"]){
_player.position = ccp(_player.position.x - 2, _player.position.y);
}
if([playerDirection isEqual:#"right"]){
_player.position = ccp(_player.position.x + 2, _player.position.y);
}
if([direction isEqual:#"up"]){
_enemy.position = ccp(_enemy.position.x, _enemy.position.y + 2);
}
if([direction isEqual:#"down"]){
_enemy.position = ccp(_enemy.position.x, _enemy.position.y - 2);
}
if(_enemy.position.y >= self.contentSize.height){
direction = #"down";
}
if(_enemy.position.y <= 2){
direction = #"up";
}
if(isTouching){
_player.position = ccp(_player.position.x + 2, _player.position.y);
}
}
// -----------------------------------------------------------------------
#pragma mark - Touch Handler
// -----------------------------------------------------------------------
-(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchLocation = [touch locationInView:[touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
if(touchLocation.x > 400){
playerDirection = #"right";
}
if(touchLocation.x < 200){
playerDirection = #"left";
}
CGPoint touchLoc = [touch locationInNode:self];
//isTouching = true;
// Log touch location
CCLOG(#"Move sprite to # %#",NSStringFromCGPoint(touchLoc));
// Move our sprite to touch location
//CCActionMoveTo *actionMove = [CCActionMoveTo actionWithDuration:1.0f position:touchLoc];
//[_sprite runAction:actionMove];
}
- (void)touchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
playerDirection = #"none";
}
i see you've got a touchesBegan and touchesEnded... but you're missing touchesMoved.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
for(UITouch *touch in touches) {
//do whatever you want
}
}
Hope that helps, good luck!
To get Touch you have to enable touch in -(id) init() method.
you can enable touch by
self.IsTouchEnable = YES
and after this you can get touch in following touch handling methods
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
hope This will help you
I am using ccTouchesBegan and ccTouchesEnded methods to register touches. Everything was ok until I placed some buttons(ccmenuitems) on my node. now when i place my finger down on a button and then move it to any other place of screen ccTouchesEnded method does not calls. What am I doing wrong? How can I detect touches on a button?
some code:
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint location = [self convertTouchToNodeSpace: [touches anyObject]];
// here i check if touch is in the right place
if ([self ptInRect:location :CGRectMake(0, center.y - 160, winSize.width, 40)]) {
dragBeginLocation = location;
}
}
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint location = [self convertTouchToNodeSpace: [touches anyObject]];
if (ABS(location.x - dragBeginLocation.x) < 8) {
NSLog(#"TAP");
} else {
NSLog(#"SWIPE");
}
}
So, when I begin touch on a sprite and release on background I get nothing in console.
Buttons are in CCMenu, which is higher than background.
I found this code on a tutorial which pretty much sets a left or right side BOOL to YES if the touch started on a specific side of the screen and then checks when the touch moves to see if it changes sides on the screen in order to make the other BOOL yes.
So I am now trying to implement multi-touch but I am not sure how it would work with the following code? Does anyone have any idea how I would go upon it?
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
touchStartPoint = [touch locationInView:self.view];
if (touchStartPoint.x < 160.0) {
touchLeftDown = TRUE;
}
else if (touchStartPoint.x > 160.0) {
touchRightDown = TRUE;
}
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint currentTouchPoint = [touch locationInView:self.view];
if (touchStartPoint.x < 160.0 && currentTouchPoint.x < 160.0) {
touchLeftDown = TRUE;
}
else if (touchStartPoint.x > 160.0 && currentTouchPoint.x > 160.0)
{
touchRightDown = TRUE;
}
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
touchLeftDown = touchRightDown = FALSE;
}
Thanks!
Edit1:
These are what the bools are doing in the game loop, pretty much what I am trying to achieve is that if there is a touch on both sides at the same time, the TOUCH_INCREMENT will be 0 since the touches on each side will cancel each other out. How would I achieve that? Anyway this is the code I am talking about:
if (touchLeftDown == TRUE) {
touchStep -= TOUCH_INCREMENT;
}
else if (touchRightDown == TRUE) {
touchStep += TOUCH_INCREMENT;
}
else {
touchStep = SLOWDOWN_FACTOR * touchStep;
}
touchStep = MIN(MAX(touchStep, -MAX_ABS_X_STEP), MAX_ABS_X_STEP);
pos.x += touchStep;
You can probably make this work without the touchStartPoint (i)var. The important thing is to not use -anyObject and instead to inspect each touch. The following code modifications might work for you:
-(void) countTouches:(NSSet *)touches withEvent:(UIEvent *)event{
int leftTouches=0;
int rightTouches=0;
for (UITouch *touch in touches)
{
CGPoint location = [touch locationInView:touch.view];
//just in case some code uses touchStartPoint
touchStartPoint=location;
if (location.x < 160.0) {
leftTouches++;
}
else if (location.x > 160.0) {
rightTouches++;
}
}
//reset touch state
touchLeftDown=FALSE;
//set touch state if touch found
if(leftTouches>0){
touchLeftDown=TRUE;
}
touchRightDown=FALSE;
if(rightTouches>0){
touchRightDown=TRUE;
}
}
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self countTouches:touches withEvent:event];
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[self countTouches:touches withEvent:event];
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
touchLeftDown = touchRightDown = FALSE;
}
Here I have created a function that is called by touchesBegan and touchesMoved because they need to implement the same logic. You may see some unintended side effects if touchStartPoint is being used in the code somehow.
I have a UIView on where i add balls with a ID. When i touch the ball with the ID 1 i draw a dashed line follows my finger.
The problem if when i move the finger to the other balls, i don't know how to detect these balls and check the ID they have. The what i need to happen is when i touch the next ball with the ID 2, the line finish draw and stay from ball 1 to ball 2, and create new one from 2 to finger, next.. 3 etc...
The code:
#import "DrawView.h"
#implementation DrawView
- (id)init
{
self = [super initWithFrame:CGRectMake(0, 0, 1024, 768)];
if (self) {
self.backgroundColor = [UIColor clearColor];
self.opaque = YES;
checkPointCircle = [[CheckPointCircle alloc] initWithPosX:315 posY:138 andNumber:1];
checkPointCircle.userInteractionEnabled = YES;
[self addSubview:checkPointCircle];
checkPointCircle = [[CheckPointCircle alloc] initWithPosX:706 posY:138 andNumber:2];
checkPointCircle.userInteractionEnabled = YES;
[self addSubview:checkPointCircle];
checkPointCircle = [[CheckPointCircle alloc] initWithPosX:315 posY:526 andNumber:3];
checkPointCircle.userInteractionEnabled = YES;
[self addSubview:checkPointCircle];
checkPointCircle = [[CheckPointCircle alloc] initWithPosX:706 posY:526 andNumber:4];
checkPointCircle.userInteractionEnabled = YES;
[self addSubview:checkPointCircle];
}
return self;
}
- (Line *)drawLine {
return drawLine;
}
- (void)setDrawLine:(Line *)line
{
drawLine = line;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CheckPointCircle * checkTouch = (CheckPointCircle *)touch.view;
if (touch.view.class == checkPointCircle.class) {
if ([checkTouch getObjectID] == 1) {
startTouchPoint = CGPointMake([checkTouch center].x, [checkTouch center].y);
endTouchPoint = [touch locationInView:self];
}
}
self.drawLine = [[Line alloc] initWithPoint:[touch locationInView:self]];
[self setNeedsDisplay];
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"Cancelado");
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
UITouch *secondaryTouch = (UITouch *)[[[event touchesForView:checkPointCircle] allObjects] objectAtIndex: 0];
NSLog(#"Que toco: %# ", secondaryTouch.view);
if (touch.view.class == checkPointCircle.class) {
CheckPointCircle * checkTouch = (CheckPointCircle *)touch.view;
if ([checkTouch getObjectID] == 1) {
endTouchPoint = [touch locationInView:self];
}
}
[self setNeedsDisplay];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CheckPointCircle * checkTouch = (CheckPointCircle *)touch.view;
if (touch.view.class == checkPointCircle.class) {
if ([checkTouch getObjectID] == 1) {
endTouchPoint = [touch locationInView:self];
}
}
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
[drawLine drawLineFrom:startTouchPoint to:endTouchPoint];
}
#end
How to detect the other balls to get the ID.
Can anybody help me?
Thanks!
The Apple documentation of class UIView (https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/UIView/UIView.html#//apple_ref/occ/instm/UIView/hitTest:withEvent:) lists two methods which will determine which view contains a hit/point:
– hitTest:withEvent:
– pointInside:withEvent:
Probably hitTest will help most: Its description reads "Returns the farthest descendant of the receiver in the view hierarchy (including itself) that contains a specified point.", so it even converts coordinates as needed.
If you check [self hitTest: [touch.locationInView self] withEvent: event] (or similar, no code completion here ;-)= in your touchesMoved: method, you should be able to detect when the finger is over any of the other circles.
Hope this helps, nobi