Reputation: 1319
I am trying to build a simple iOS game. When my main menu loads and appears on screen, I wanna have the buttons move in from the sides. My only idea is to apply some SKActions to SKSpriteNodes. But so I have to create my own button-class. Is there a simpler method to accomplish this? Are there already classes like CCMenuItem/CCMenu from cocos2d? Or is there a way with UIButtons?
Thanks
Upvotes: 2
Views: 4498
Reputation: 313
I created a button class that has a SKSpriteNode property, a CGRect property and a Radius property (for round buttons). When you initialise the button with an image it set's it's CGRect and Radius property based on the image size. You can then just check if a player's hitting the button by calling to it's -collisionRect method which return's a CGRect and check if the "touch" location is within that rect. This way the button's can move around and still receive input. Here's the code...
////////////////////// HEADER FILE //////////////////////
//
// ZSButton.h
// PEGO
//
// Created by Zion Siton on 07/09/2013.
// Copyright (c) 2013 zillustrator. All rights reserved.
//
#import <SpriteKit/SpriteKit.h>
@interface ZSButton : SKNode {
SKSpriteNode *mySprite;
CGRect myRect;
CGFloat myRadius;
}
@property (nonatomic, strong)SKSpriteNode *mySprite;
@property (nonatomic, assign)CGRect myRect;
@property (nonatomic, assign)CGFloat myRadius;
- (id)initWithTexture:(SKTexture *)texture;
- (BOOL)didRadialCollideWith:(CGPoint)aPoint;
@end
/////////////////// IMPLEMENTATION FILE //////////////////////
//
// ZSButtonA.m
// PEGO
//
// Created by Zion Siton on 07/09/2013.
// Copyright (c) 2013 zillustrator. All rights reserved.
//
#import "ZSButton.h"
@implementation ZSButton
@synthesize mySprite, myRect, myRadius;
- (id)init {
// Use a default button image
return [self initWithTexture:[SKTexture textureWithImageNamed:@"ButtonDefault.png"]];
}
- (id)initWithTexture:(SKTexture *)texture {
self = [super init];
if (self) {
// Assumes there is a texture
mySprite = [SKSpriteNode spriteNodeWithTexture:texture];
[self addChild:mySprite];
// Assumes the collision area is the size of the texture frame
myRect = [mySprite frame];
// Assumes the texture is square
myRadius = myRect.size.width * 0.5;
}
return self;
}
- (CGRect)myRect {
CGPoint pos = [self position];
CGFloat originX = pos.x - (mySprite.frame.width * 0.5);
CGFloat originY = pos.y - (mySprite.frame.height * 0.5);
CGFloat width = mySprite.frame.width;
CGFloat height = mySprite.frame.height;
myRect = CGRectMake(originX, originY, width, height);
return myRect;
}
- (BOOL)didRadialCollideWith:(CGPoint)aPoint {
// Get the distance between the button centre and the touch
// ZSMath is a class I wrote that mainly performs trigonometric functions
CGFloat distance = [ZSMath distanceFromA:[self position] toB:aPoint];
// Perform a radial collision check
if (distance < [self myRadius]) {
// HIT!!!
return YES;
}
// MISS!!!
return NO;
}
@end
////////////////// TO INITIALISE A BUTTON...
// Initialize BACK BUTTON
backButton = [[ZSButton alloc] initWithTexture:
[[ZSGraphicLoader sharedGraphicLoader] frameByName:kBACK_BUTTON]];
[self addChild:backButton];
////////////////// TO TEST FOR A COLLISION/USER PRESS
for (UITouch *touch in touches) {
// Get the user's touch location
CGPoint location = [touch locationInNode:self];
// If the user taps on BACK Button Rectangle
if (CGRectContainsPoint(backButton.myRect, location))
{
// DO A RADIAL CHECK
if ([backButton didRadialCollideWith:location])
{
// DO BACK BUTTON STUFF
}
}
}
Upvotes: 1
Reputation: 1284
Creating your own button class inheriting from SKSpriteNode and adding actions takes mere minutes and works really well. UIButton and SKScene don't seem to play well together with respect to touches and really there's no need considering the approach described works really well. You can add your own textures and colors to the button using the inherited SKSpriteNode members.
Upvotes: 0