简体   繁体   中英

Enable touches on an sprite (spritekit)

I'm having a problem with touches on sprites, within SpriteKit.

Here is my code.

#define kRowCount 8
#define kColCount 6
#define kDotGridSpacing CGSizeMake (50,-50)
#import "BBMyScene.h"

@implementation BBMyScene

@synthesize dot;
@synthesize htoucharea;
@synthesize vtoucharea;
@synthesize hFrame;
@synthesize vFrame;



-(id)initWithSize:(CGSize)size {    
if (self = [super initWithSize:size]) {
    /* Setup your scene here */

    self.userInteractionEnabled = YES;

    //  Set up Background
    self.backgroundColor = [SKColor colorWithRed:0.957 green:0.957 blue:0.957 alpha:1]; /*#f4f4f4*/


    // Set up Lattice of Dots
    CGPoint baseOrigin = CGPointMake(35, 385);
    for (NSUInteger row = 0; row < kRowCount; ++row) {


        CGPoint dotPosition = CGPointMake(baseOrigin.x, row * (kDotGridSpacing.height) + baseOrigin.y);


        for (NSUInteger col = 0; col < kColCount; ++col) {

            dot = [SKSpriteNode spriteNodeWithImageNamed:@"dot"];
            dot.position = dotPosition;
            NSString *dotName = [NSString stringWithFormat:@"dot_%d_%d", row, col];
            dot.name = dotName;
            [self addChild:dot];
            dotPosition.x += kDotGridSpacing.width;



        }

    }


    //Set up horizontal touch areas
    for (NSUInteger row = 0; row < kRowCount; ++row) {

        CGPoint htouchareaPosition = CGPointMake(baseOrigin.x + 0.5*(kDotGridSpacing.width), row * (kDotGridSpacing.height) + baseOrigin.y);

        for (NSUInteger col = 0; col < kColCount-1; ++col) {

            htoucharea = [SKSpriteNode spriteNodeWithColor:[SKColor colorWithRed:0.18 green:0.702 blue:0.91 alpha:0.5] size:CGSizeMake(35,25)];
            htoucharea.position = htouchareaPosition;
            NSString *htouchareaName = [NSString stringWithFormat:@"htoucharea_%d_%d", row, col];
            htoucharea.name = htouchareaName;
            htoucharea.userInteractionEnabled = YES;

            htouchareaPosition.x += kDotGridSpacing.width;

            [self addChild:htoucharea];


        }

    }







    // Set up vertical touch areas
    for (NSUInteger row = 0; row < kRowCount-1; ++row) {

        CGPoint vtouchareaPosition = CGPointMake(baseOrigin.x, row * (kDotGridSpacing.height) + baseOrigin.y + 0.5*(kDotGridSpacing.height));

        for (NSUInteger col = 0; col < kColCount; ++col) {

            vtoucharea = [SKSpriteNode spriteNodeWithColor:[SKColor colorWithRed:1 green:0.478 blue:0.478 alpha:0.5] size:CGSizeMake(25,35)];
            vtoucharea.position = vtouchareaPosition;
            NSString *vtouchareaName = [NSString stringWithFormat:@"vtoucharea_%d_%d", row, col];
            vtoucharea.name = vtouchareaName;
            vtoucharea.userInteractionEnabled = YES;
            [self addChild:vtoucharea];
            vtouchareaPosition.x += kDotGridSpacing.width;


        }

    }








}

return self;
}





-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */



UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.view];

if (CGRectContainsPoint(vtoucharea.frame, location)) {
    NSLog(@"Hello");;
}
















}

-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */
}

@end

I'm having trouble. When I touch one of the sprites, I want to do something (at the moment that is just log to the console). Why aren't my touches being recognised?

That function is only called when you userInteractionEnabled = YES , which you are trying to do inside that same function, so it will never be called. Place that code into your sprite's init method instead.

I tried your code and the touches are registered just fine. However, there are few other problems in the code:

  • In your for-loops in the init, you set only the last created node to your ivars (dot, hTouchArea, vTouchArea). And later, in touchesEnded -method, you try to use this ivar to detect if the touch was inside this node's frame. Of course this doesn't work as you only have the last node cached. (I used different approach here - see the touchesBegan method)

  • If you want to register touches only in the scene node, you must disable user interaction from the other nodes you add on it. Otherwise, you other nodes will block your scene from getting the touches. (use userInteractionEnabled = NO).

  • [touch locationInView:self.view] gives you the location in the view. Instead, you want to have to location in the node itself. You must use [touch locationInNode:self] instead.

Here, I fixed the code for you (I also tested it so it should work):

#import "Test scene"
#define kRowCount 8
#define kColCount 6
#define kDotGridSpacing CGSizeMake (50,-50)

@implementation TestScene

-(id)initWithSize:(CGSize)size
{
    if (self = [super initWithSize:size])
    {
        self.userInteractionEnabled = YES;
        self.backgroundColor = [SKColor colorWithRed:0.957 green:0.957 blue:0.957 alpha:1];

        CGPoint baseOrigin = CGPointMake(35, 385);
        for (NSUInteger row = 0; row < kRowCount; ++row)
        {
            CGPoint dotPosition = CGPointMake(baseOrigin.x, row * (kDotGridSpacing.height) + baseOrigin.y);

            for (NSUInteger col = 0; col < kColCount; ++col)
            {
                SKSpriteNode* dot = [SKSpriteNode spriteNodeWithColor:[UIColor redColor] size:CGSizeMake(10, 10)];
                dot.position = dotPosition;
                dot.name = [NSString stringWithFormat:@"dot_%d_%d", row, col];

                dotPosition.x += kDotGridSpacing.width;

                [self addChild:dot];
                dot.userInteractionEnabled = NO;
            }
        }

        for (NSUInteger row = 0; row < kRowCount; ++row)
        {
            CGPoint htouchareaPosition = CGPointMake(baseOrigin.x + 0.5*(kDotGridSpacing.width), row * (kDotGridSpacing.height) + baseOrigin.y);

            for (NSUInteger col = 0; col < kColCount-1; ++col)
            {
                SKSpriteNode* htoucharea = [SKSpriteNode spriteNodeWithColor:[SKColor colorWithRed:0.18 green:0.702 blue:0.91 alpha:0.5] size:CGSizeMake(35,25)];
                htoucharea.position = htouchareaPosition;
                NSString *htouchareaName = [NSString stringWithFormat:@"htoucharea_%d_%d", row, col];
                htoucharea.name = htouchareaName;
                htoucharea.userInteractionEnabled = YES;

                htouchareaPosition.x += kDotGridSpacing.width;

                [self addChild:htoucharea];
                htoucharea.userInteractionEnabled = NO;
            }
        }

        for (NSUInteger row = 0; row < kRowCount-1; ++row)
        {
            CGPoint vtouchareaPosition = CGPointMake(baseOrigin.x, row * (kDotGridSpacing.height) + baseOrigin.y + 0.5*(kDotGridSpacing.height));

            for (NSUInteger col = 0; col < kColCount; ++col)
            {
                SKSpriteNode* vtoucharea = [SKSpriteNode spriteNodeWithColor:[SKColor colorWithRed:1 green:0.478 blue:0.478 alpha:0.5] size:CGSizeMake(25,35)];
                vtoucharea.position = vtouchareaPosition;
                vtoucharea.name = [NSString stringWithFormat:@"vtoucharea_%d_%d", row, col];
                vtoucharea.userInteractionEnabled = YES;

                vtouchareaPosition.x += kDotGridSpacing.width;

                [self addChild:vtoucharea];
                vtoucharea.userInteractionEnabled = NO;
            }
        }
    }

    return self;
}


- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch* touch = [touches anyObject];
    CGPoint touchLocation = [touch locationInNode:self];

    for (SKNode* node in [self nodesAtPoint:touchLocation])
    {
        NSLog(@"Node was touched: %@", node.name);
    }
}

@end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM