didBeginContact not being called after xcode 6 - sprite-kit

I've been having problems with xcode in general. Example, NSLog not printing, case statements not working, etc. I did created this project before xcode 6 came out and thought if i switched it to a new file made in xcode 6 that these things would have been fixed. So far, they have been fixed. However, more problems have happened. One major one is that the didBeginContact method is not being called now. I've tried doing everything to fix it. I changed the category masks, their values, the collisionBitMask, contactBitMask, put different foundations in, but nothing has worked yet. It works in the file made before xcode 6 came out, but not in xcode 6.
There is supposed to be contact detected between the player and the opponent, but it doesn't work anymore.
I put breakpoints at the didBeginContact method and at the method it is supposed to call when there is contact between the player and opponent, but program didn't exit.
Thanks in advance!
GameScene.m:
#import "GameScene.h"
#interface GameScene ()
#end
#implementation GameScene
- (void)didMoveToView:(SKView *)view
{
if (!self.contentCreated)
{
[self createSceneContents];
self.contentCreated = YES;
[self addplatform];
[self addPlayer];
[self addButtons];
[self addOpponent];
}
}
typedef NS_OPTIONS(uint32_t, CollisionCategory) {
CollisionCategoryPlayer = 1 << 0,
CollisionCategoryOpponent = 1 << 1,
CollisionCategoryPlatform = 1 << 2,
CollisionCategoryPlatformBorder = 1 << 3,
};
//static inline CGFloat skRandf() {
// return rand() / (CGFloat) RAND_MAX;
//}
- (void)createSceneContents
{
self.backgroundColor = [SKColor purpleColor];
self.scaleMode = SKSceneScaleModeAspectFit;
self.multipleTouchEnabled = YES;
}
-(id)initWithSize:(CGSize)size
{
if (self = [super initWithSize:size])
{
self.physicsWorld.contactDelegate = self;
}
return self;
}
- (SKSpriteNode *)addPlayer {
self._player = [SKSpriteNode spriteNodeWithTexture: [SKTexture textureWithImageNamed:#"TurnipSmall"]];
self._player.position = CGPointMake(100,450);
self._player.anchorPoint = CGPointMake(0.5,0.5);
self._player.physicsBody = [SKPhysicsBody bodyWithTexture:self._player.texture size:self._player.texture.size];
self._player.name = #"player";
self._player.physicsBody.dynamic = YES;
self._player.physicsBody.allowsRotation = FALSE;
self._player.physicsBody.affectedByGravity = TRUE;
self._player.physicsBody.friction = 5;
self._player.physicsBody.mass = 10;
self._player.physicsBody.usesPreciseCollisionDetection = YES;
self._player.physicsBody.restitution = 0.0;
self._player.physicsBody.categoryBitMask = CollisionCategoryPlayer;
self._player.physicsBody.collisionBitMask = CollisionCategoryPlayer | CollisionCategoryOpponent | CollisionCategoryPlatform;
self._player.physicsBody.contactTestBitMask = CollisionCategoryPlayer | CollisionCategoryOpponent | CollisionCategoryPlatform;
self.playerPunching = false;
[self addChild:self._player];
return self._player;
}
- (SKSpriteNode *)addOpponent {
self._opponent = [SKSpriteNode spriteNodeWithTexture: [SKTexture textureWithImageNamed:#"Tomato"]];
self._opponent.position = CGPointMake(300, 450);
self._opponent.anchorPoint = CGPointMake(0.5, 0.5);
self._opponent.physicsBody = [SKPhysicsBody bodyWithTexture:self._opponent.texture size:self._opponent.texture.size];
self._opponent.name = #"opponent";
self._opponent.physicsBody.dynamic = YES;
self._opponent.physicsBody.allowsRotation = NO;
self._opponent.physicsBody.affectedByGravity = YES;
self._opponent.physicsBody.friction = 5;
self._opponent.physicsBody.mass = 10;
self._opponent.physicsBody.density = 5;
self._opponent.physicsBody.usesPreciseCollisionDetection = YES;
self._opponent.physicsBody.restitution = 0;
self._opponent.physicsBody.velocity = CGVectorMake(0, 0);
self._opponent.physicsBody.categoryBitMask = CollisionCategoryOpponent;
self._opponent.physicsBody.collisionBitMask = CollisionCategoryPlatform| CollisionCategoryPlayer;
self._opponent.physicsBody.contactTestBitMask = CollisionCategoryPlayer | CollisionCategoryPlatform;
[self addChild:self._opponent];
return self._opponent;
}
- (void)didBeginContact:(SKPhysicsContact *)contact
{
SKPhysicsBody *firstBody, *secondBody;
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
{
firstBody = contact.bodyA;
secondBody = contact.bodyB;
}
else
{
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
if ((firstBody.categoryBitMask & CollisionCategoryPlayer) != 0 && (secondBody.categoryBitMask & CollisionCategoryOpponent))
{
[self playerTouchingOpponent];
}
}
GameScene.h:
//
// GameScene.h
// TEST
//
// Copyright (c) 2014 G Hui. All rights reserved.
//
#import <SpriteKit/SpriteKit.h>
#interface GameScene : SKScene <SKPhysicsContactDelegate>
#property bool multipleTouchEnabled;
#property BOOL contentCreated;
#property SKSpriteNode * _donut;
#property SKSpriteNode * _player;
#property SKSpriteNode * _opponent;
#property SKSpriteNode *platform1Scene1;
#property BOOL movementBegins;
#property NSArray *level1;
#property BOOL playerPunching;
#property bool alreadyPunching;
#property float characterNumber;
#property SKSpriteNode *platform2Scene1;
#property SKSpriteNode *platform3Scene1;
#property float playerHealth;
#property SKSpriteNode *_healthBar;
#property SKSpriteNode *rightplatformBorder;
#property SKSpriteNode *mask;
#property SKNode *_playerHealthBar;
#property SKNode *_opponentHealthBar;
#property SKNode *_playerPowerUpBar;
#property SKNode *_opponentPowerUpBar;
#property int _playerHP;
#property int _opponentHP;
#property const int MaxHP;
#property int _playerPowerUp;
#property int _opponentPowerUp;
#property const int MaxPowerUp;
#property const float healthBarWidth;
#property const float healthBarHeight;
#property const float powerBarWidth;
#property const float powerBarHeight;
#property bool touchingPlatform;
#property SKSpriteNode *sideBorder;
#property SKSpriteNode *frontBorder;
#property BOOL playerOpponentContact;
#property float distanceBetweenPlayerAndOpponent;
#property float distanceBetweenOpponentAndPlayer;
#end

Fixed!
It was because the contact delegate was in initWithSize, which wasn't being called for some reason...

Related

sprite kit frame rate dip at start and only once

I have a sprite that runs and jumps (like Mario), I am using a state machine to help with running the animation actions, I am using a texture atlas, and everything works fine.
- (void)jumpingphysics {
if (_JumpBool && self.onGround) {
_doubleJumpBool = YES;
_JumpBool = NO;
[self catJump];
self.physicsBody.velocity = CGVectorMake(0.0, 600);
}
// double jump
if (_JumpBool && _doubleJumpBool) {
self.physicsBody.velocity = CGVectorMake(0.0, 600);
[self catDoubleJump];
_doubleJumpBool = NO;
_JumpBool = NO;
}
}
this is the method thats called.
- (void)catJump {
if (_actionState == kActionStateIdle || _actionState == kActionStateWalk || _actionState == kActionStateJump) {
[self removeAllActions];
[self runAction:_jumpAction];
SKAction *jumpFx = [SKAction playSoundFileNamed:#"jump.wav" waitForCompletion:NO];
[self runAction:jumpFx];
_actionState = kActionStateJump;
}
}
this is where I created the frames array animation.
- (void)catJumpAnimation {
int i;
NSMutableArray *jumpFrames = [NSMutableArray arrayWithCapacity:9];
for (i = 1 ; i < 9; ++i) {
NSString *frames = [NSString stringWithFormat:#"jump%d.png",i];
SKTexture *temp = [catAtlas textureNamed:frames];
[jumpFrames addObject:temp];
self.jumpAction = [SKAction animateWithTextures:jumpFrames timePerFrame:1.0 / 16.0 resize:YES restore:NO];
}
}
The problem is when running on an iPad mini, when I jump the first time, my frame rate dips to 40, only that first time, and only on my iPad mini, not my iPhone 5 c.
I know its the [self catJump] call that causes the frame rate dip, but I'm confused why only that call causes a dip, I have other animations which do more work yet don't cause a dip.
Any ideas would be greatly appreciated. :D
In my ActionSprite.h class which handles the the methods that controls the animations and sounds.
#interface ActionSprite : SKSpriteNode
#property (nonatomic,strong)SKAction *jumpFx;
#property (nonatomic,strong)SKAction *DjumpFx;
#property (nonatomic,strong)SKAction *hurtFx;
#property (nonatomic,strong)SKAction *dashFx;
#property (nonatomic,strong)SKAction *defeatFx;
#property (nonatomic,strong)SKAction *powerFx;
#property (nonatomic,strong)SKAction *bounceFx;
#property (nonatomic,strong)SKAction *rocketFx;
In my ActionSprite.m
#implementation ActionSprite
- (id)init {
if (self = [super init]) {
}
return self;
}
- (void)preLoadSound {
_jumpFx = [SKAction playSoundFileNamed:#"jump.wav" waitForCompletion:NO];
_DjumpFx = [SKAction playSoundFileNamed:#"dJump.wav" waitForCompletion:NO];
_hurtFx = [SKAction playSoundFileNamed:#"cat hurt.wav" waitForCompletion:NO];
_defeatFx = [SKAction playSoundFileNamed:#"defeat.wav" waitForCompletion:NO];
_bounceFx = [SKAction playSoundFileNamed:#"bounce.wav" waitForCompletion:NO];
_powerFx = [SKAction playSoundFileNamed:#"power.mp3" waitForCompletion:NO];
_rocketFx = [SKAction playSoundFileNamed:#"rocketFx.wav" waitForCompletion:NO];
}
preload sounds in the cat class
#implementation Cat
SKTextureAtlas *catAtlas;
- (id)init {
if (self = [super initWithImageNamed:#"idle.png"]) {
catAtlas = [SKTextureAtlas atlasNamed:#"idle.plist"];
[self preLoadSound];
}
return self;
}
no more lag! :D

Segmented Controllers

Trying to set an int value using a Segmented Controller. I've seen several tuts on how to change labels, but I need to set an int value.
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
#synthesize caseCost;
#synthesize dilution;
#synthesize returnMsg;
#synthesize opcValue;
//synthesize opc; < -- Tried
//int opc; <--- tried
- (IBAction)opcView:(id)sender {
if (opcValue.selectedSegmentIndex == 0) {
int opc = 320;
}
if (opcValue.selectedSegmentIndex == 1) {
int opc = 128;
}
if (opcValue.selectedSegmentIndex == 2) {
int opc = 135;
}
if (opcValue.selectedSegmentIndex == 3) {
int opc = 88;
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//int opc; <--- tried
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)finishBtn:(id)sender {
//int opc = 320;
float case_cost = ([caseCost.text floatValue]);
float dilutionValue = ([dilution.text floatValue]);
float gpc = (opc / dilutionValue);
float gCost = (case_cost / gpc);
float bCost = (gCost / 4);
float bpc = (gpc * 4);
NSNumberFormatter *formatterCur = [[NSNumberFormatter alloc] init];
NSNumberFormatter *formatterInt = [[NSNumberFormatter alloc] init];
[formatterCur setNumberStyle:NSNumberFormatterCurrencyStyle];
[formatterInt setNumberStyle:NSNumberFormatterDecimalStyle];
NSString *bottlesCost = [formatterCur stringFromNumber:[NSNumber numberWithFloat:bCost]];
NSString *gallons = [formatterInt stringFromNumber:[NSNumber numberWithInt:gpc]];
NSString *gallonsCost = [formatterCur stringFromNumber:[NSNumber numberWithFloat:gCost]];
NSString *bottles = [formatterInt stringFromNumber:[NSNumber numberWithInt:bpc]];
returnMsg.text = [NSString stringWithFormat:#"%# gallons per case at %# per gallon and %# - 32 oz bottles at %# per bottle.", gallons, gallonsCost, bottles, bottlesCost];
}
- (IBAction)opcView:(id)sender {
}
#end
in the line "float gpc = (opc / dilutionValue);" is shows as an unknown value of opc, even though I think it should from the segmented controller. I'm using the segmented controller instead of Radio Buttons i've used in Java. I used the "//int opc=320" to make sure the rest of the code worked.
In each of the if blocks in your method - (IBAction)opcView:(id)sender you are creating a local int variable named opc. So when execution leaves the if block, the local variable disappears. Thus, in - (IBAction)finishBtn:(id)sender there is no variable named opc in scope.
You should declare opc to be a property as well. You will set this property when the segment control changes selection. Later, you can read the property's value in your finish button's handler.
#import "SecondViewController.h"
#interface SecondViewController()
#property (nonatomic) int opc;
#end
#implementation SecondViewController
// this method is wired to the segment control's UIControlEventValueChanged event
- (IBAction)opcView:(id)sender
{
if (opcValue.selectedSegmentIndex == 0) {
self.opc = 320;
}
if (opcValue.selectedSegmentIndex == 1) {
self.opc = 128;
}
if (opcValue.selectedSegmentIndex == 2) {
self.opc = 135;
}
if (opcValue.selectedSegmentIndex == 3) {
self.opc = 88;
}
}
- (IBAction)finishBtn:(id)sender
{
float case_cost = ([caseCost.text floatValue]);
float dilutionValue = ([dilution.text floatValue]);
float gpc = (self.opc / dilutionValue);
// lots more code
}

How to extend my method that checking if 2 cards are matched to 3 cards that are matched?

I'm following the Stanford course, and we had to build a method for the app that checks for 2 cards matching, this is how the model that have the logic looks like (the method to look there is flipCardAtIndex):
#import "CardMatchingGame.h"
#import "PlayingCardsDeck.h"
#interface CardMatchingGame()
#property (readwrite, nonatomic) int score;
#property (strong, nonatomic) NSMutableArray *cards;
#property (strong, nonatomic) NSString *notification;
#end
#implementation CardMatchingGame
-(NSMutableArray *) cards {
if (!_cards) _cards = [[NSMutableArray alloc] init];
return _cards;
}
-(id)initWithCardCount:(NSUInteger)count usingDeck:(Deck *)deck {
self = [super init];
if (self) {
for (int i = 0; i < count; i++) {
Card *card = [deck drawRandonCard];
if (!card) {
self = nil;
} else {
self.cards[i] = card;
}
}
}
return self;
}
-(Card *) cardAtIndex:(NSUInteger)index {
return (index < self.cards.count) ? self.cards[index] : nil;
}
#define FLIP_COST 1
#define MISMATCH_PENALTY 2
#define BONUS 4
-(void) flipCardAtIndex:(NSUInteger)index {
Card *card = [self cardAtIndex:index];
if (!card.isUnplayable) {
if (!card.isFaceUp) {
for (Card *otherCard in self.cards) {
if (otherCard.isFaceUp && !otherCard.isUnplayable) {
int matchScore = [card match:#[otherCard]];
if (matchScore) {
otherCard.unplayble = YES;
card.unplayble = YES;
self.notification = [NSString stringWithFormat:#"%# & %# match!", card.contents, otherCard.contents];
self.score += matchScore * BONUS;
} else {
otherCard.faceUp = NO;
self.score -= MISMATCH_PENALTY;
self.notification = [NSString stringWithFormat:#"%# did not matched to %#", card.contents, otherCard.contents];
}
break;
}
}
self.score -= FLIP_COST;
}
card.faceUp = !card.isFaceUp;
}
}
#end
And this is the class model of the whole game, that got the actual matching method:
#import "PlayingCards.h"
#implementation PlayingCards
#synthesize suit = _suit;
//overriding the :match method of cards to give different acore if its only a suit match or a number match
-(int)match:(NSArray *)cardToMatch {
int score = 0;
if (cardToMatch.count == 1) {
PlayingCards *aCard = [cardToMatch lastObject];
if ([aCard.suit isEqualToString: self.suit]) {
score = 1;
} else if (aCard.rank == self.rank) {
score = 4;
}
}
return score;
}
//more stuff...
W already created it with an array so we will be able to extend it for more objects, but now i'm trying to figure out how do I extend it :/
This is my github for the project https://github.com/NirOhayon/Matchismo
i'm new to objective C and would appreciate it munch if you could help me to figure it out.
Thanks a bunch
You can chain these with a loop to check them all. Very basic way of doing it. Just loop through each card and check it against the "self" card that you have and increment the score instead of setting it.
-(int)match:(NSArray *)cardToMatch {
int score = 0;
for(int i = 0; i < cardToMatch.count; i++) {
PlayingCards *aCard = cardToMatch[i];
if ([aCard.suit isEqualToString: self.suit]) {
score += 1;
} else if (aCard.rank == self.rank) {
score += 4;
}
}
return score;
}
For flipCardAtIndex: , I would change it to flipCardsAtIndexes:(NSArray*)indexes, where indexes is an NSArray of NSNumbers. Then I would run a for loop checking and removing any cards that are unplayable or faceup, and pass through the remaining cards at those indexes to check match, and retrieve the match score.
To tell your view controller to add another card depends on how you have your view controller set up. You could do a protocol in a method that your view controller becomes the delegate of, and through a protocol method, tell it to switch. It could also be simpler than that, depending on how it checks your model of cards to decide what to show, if it sees three cards available instead of two, it could switch.
As the point of this exercise is to learn iOS programming, I want to give you a good head start and you should tweak and figure some stuff out on your own. I have a feeling you're a novice at programming, and if you are, you'll be surprised how much programming at your stage is trial and error. Eventually it will become second nature.

CCLabelTTF value is not updating (cocos2d)

i have two layers control layer which contains CCLabelTTF for score, and first layer in which i detect collision btwn my objects. i want to update score (i.e CCLabelTTF value) in control layer from my first layer.
here is my code...
my scene.m
-(id)init{
self=[super init];
FirstLayer *fl=[FirstLayer node];
[self addChild:fl];
controlLayer *cl=[controlLayer node];
[self addChild:cl z:3 tag:1];
return self;
}
control layer.h
#interface controlLayer : CCLayer{
CCLabelTTF * score ;
int score_value;
}
#property(nonatomic,retain)CCLabelTTF * score ;
#property int score_value;
-(void)displayScore;
#end
controlLayer.m
-(id)init{
// my code..
[self displayScore];
}
return self;
}
-(void)displayScore{
CGSize screenSize=[[CCDirector sharedDirector]winSize];
CCLabelTTF * score_lbl = [CCLabelTTF labelWithString:#"Score" fontName:#"Arial" fontSize:16.0];
score_lbl.position=ccp(screenSize.width*0.10,screenSize.height*0.90);
[self addChild:score_lbl z:99];
score =[CCLabelTTF labelWithString:[NSString stringWithFormat:#"test:%d",score_value] fontName:#"Arial" fontSize:16.0] ;
NSString *str = [score string];
NSLog(#"SCORE control:%#",str);
score.position=ccp(screenSize.width*0.20,screenSize.height*0.90);
[self addChild:score];
}
firstLayer.h
#interface FirstLayer : CCLayer
{
controlLayer *cl;
}
#property(nonatomic,retain)controlLayer *cl;
#end
firstLayer.m
#implementation FirstLayer
#synthesize cl;
-(id)init{
---
cl=[controlLayer new];
[self schedule:#selector(tick:)];
return self;
}
-(void)tick:(ccTime)dt{
bool blockFound=false;
world->Step(dt, 10, 10);
std::vector<MyContact>::iterator pos;
for(pos = _contactListener->_contacts.begin();
pos != _contactListener->_contacts.end(); ++pos) {
MyContact contact = *pos;
b2Body *bodyA = contact.fixtureA->GetBody();
b2Body *bodyB = contact.fixtureB->GetBody();
if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL) {
CCSprite *spriteA = (CCSprite *) bodyA->GetUserData();
CCSprite *spriteB = (CCSprite *) bodyB->GetUserData();
// Sprite A = ball, Sprite B = Block
if (spriteA.tag == 1 && spriteB.tag == 2) {
cl.score_value=cl.score_value+5;
[cl.score setString:[NSString stringWithFormat:#"%d",cl.score_value]];
NSString *str = [cl.score string];
NSLog(#"SCORE in GAME:%#",str);
// [cl displayScore];
if (std::find(toDestroy.begin(), toDestroy.end(), bodyB)
== toDestroy.end()) {
toDestroy.push_back(bodyB);
}
}
// Sprite B = block, Sprite A = ball
else if (spriteA.tag == 2 && spriteB.tag == 1) {
cl.score_value=cl.score_value+5;
[cl.score setString:[NSString stringWithFormat:#"%d",cl.score_value]];
NSString *str = [cl.score string];
NSLog(#"SCORE in GAME:%#",str);
// [cl displayScore];
}
}
}
What is going Wrong? , i'm always getting score:test 0 !:(
Your statement cl=[controlLayer new]; is not getting the reference of the controlLayer that was added to your game scene. As your game scene.m code indicates, both FirstLayer and controlLayer instances are initalized and added as children to the CCScene. To get a proper reference to your controlLayer from inside FirstLayer, do it like this:
FirstLayer.m
-(void) onEnter {
[super onEnter];
cl = (controlLayer*)[self.parent getChildByTag:1];
}
The reason you have to put this in onEnter is because self.parent will not be valid within the FirstLayer's init method. onEnter is called after initialization is complete. This should give you the reference to the actual controlLayer that was added to your game scene.
I think by the looks of it, you are sending a new score value to your control layer, but you are not updating the label, as you only set it once. It won't automatically update if score_value changes. I think you need to schedule an update method in your control layer that will update the score label.

iphone slider with constum steps

i am not really familiar with objC and looking for a solution to build a slider that slides with "steps". on moving the slider the value increases like value+=10 or maybe value+=100. how do i do that?
I modified the code above for a custom Cocos2D slider http://yannickloriot.com/library/ios/cccontrolextension/Classes/CCControlSlider.html
It has properties:
#property (nonatomic, readwrite) float value;
#property (nonatomic, readwrite) minimumValue;
#property (nonatomic, readwrite) maximumValue;
#property (nonatomic, readwrite) int steps;
the recalculation:
- (void)recalcuateValue
{
float stepValues[self.steps];
stepValues[0] = self.minimumValue;
stepValues[self.steps - 1] = self.maximumValue;
for(int i = 1; i < self.steps; i++){
stepValues[i] = i * (self.maximumValue - self.minimumValue) / (self.steps - 1);
if (self.value < stepValues[i] && self.value > stepValues[i-1]){
self.value = (self.value > (stepValues[i] - stepValues[i-1]) / 2 + stepValues[i-1])?stepValues[i]:stepValues[i-1];
}
}
}
And the ccTouchesEnded: I added if(self.steps != 0), for the case steps is set to 0, the slider could work in usual mode
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
if ([self isSelected]){
self.value = [self valueForLocation:_thumbSprite.position];
if(self.steps != 0) {
[self recalcuateValue];
[_thumbSprite setPosition:[self locationFromValue:self.value]];
}
}
self.thumbSprite.color = ccWHITE;
self.selected = NO;
}
It calls valueForLocation and locationFromValue methods:
- (float)valueForLocation:(CGPoint)location
{
float percent = location.x / _backgroundSprite.contentSize.width;
return _minimumValue + percent * (_maximumValue - _minimumValue);
}
- (CGPoint)locationFromValue:(float)value{
float percent = self.value / self.maximumValue;
return ccp(percent * _backgroundSprite.contentSize.width, _backgroundSprite.position.y);
}
So an example of usage. I needed a slider with 3 steps and values 0, 1 and 2 on each step:
self.Slider = [CCControlSlider sliderWithBackgroundFile:#"sliderTrack.png"
progressFile:#"sliderProgress.png"
thumbFile:#"sliderThumb-hd.png"]; progressFile:#"sliderProgress.png" thumbFile:#"sliderThumb-hd.png"];
self.Slider.minimumValue = 0.0f;
self.Slider.maximumValue = 2.0f;
self.Slider.steps = 3;
self.Slider.value = [[GameSettings sharedSettings] defaultAILevel];
[self.Slider addTarget:self action:#selector(onSliderValueChanged:) forControlEvents:CCControlEventValueChanged];
Hope it may be useful
I created my discrete slider this way:
#import <UIKit/UIKit.h>
#interface DiscreteSlider : UISlider {
int step;
}
#property (nonatomic) int step;
#end
which that implementation:
#import "DiscreteSlider.h"
#implementation DiscreteSlider
#synthesize step;
- (void) recalcuateStep
{
float lValue = self.value;
int lLowerValue = (int) ( lValue / self.step );
float lDifference = lValue - ( lLowerValue * step );
float lHalfStep = ((float) step) / 2;
if( lDifference < lHalfStep ) {
} else {
self.value = (float) ( lLowerValue + step );
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
}
- (void) touchesMoved:(NSSet *) touches
withEvent:(UIEvent *) event
{
[super touchesMoved:touches withEvent:event];
NSLog( #"DS.touchesMoved(), event: %#", event );
[self recalcuateStep];
}
- (void) endTrackingWithTouch:(UITouch *) touch
withEvent:(UIEvent *) event
{
[super endTrackingWithTouch:touch withEvent:event];
NSLog( #"DS.endTrackingWithTouch(), event: %#", event );
[self recalcuateStep];
}
- (int) step {
return ( step ? step : 1 );
}
#end