Touch Move Method issue in cocos2d for iphon4 - objective-c

I am developing one universal puzzle game, in which i have used separate image for iphone4 and for iphone3, iphone4 image is double in size of iphone3 image. My issue is for iphone4, touch area of image for iphone4 image is taking double size, suppose i have an image size for iphone4 is 20*40 and for iphone3 is 10*20, issue is touch area for iphone4 image is 40*80 i don't know how its happening i worked out in my code but i didnt get any solution of this issue, touching is working fine in iphone3, taking with in sprite rectangle.
can you one help me to solve this issue or tell me what i am forgetting to code for iphone4 touching so that its take touch with in sprite (image) rectangle
Thank in advance.
Here is my code:
`-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
touchLocation = [touch locationInView: [touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
touchLocation = [self convertTouchToNodeSpace:touch];
NSLog(#"touch location x = %f , y =%f",touchLocation.x,touchLocation.y);
CCSprite * sp= [CCSprite spriteWithFile:#"1.png"];
sp.position = ccp(touchLocation.x ,touchLocation.y);
// [self addChild:sp z:100];
CGRect myrec = [invisible[0] boundingBox];
if (CGRectContainsPoint(myrec, touchLocation) ) {
NSLog(#"oneeeeeeee");
}
[self selectSpriteForTouch:touchLocation];
// return TRUE;
}
- (void)panForTranslation:(CGPoint)translation {
if (selSprite) {
CGPoint newPos = ccpAdd(selSprite.position, translation);
selSprite.position = newPos;
}
}
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
Location = [touch locationInView: [touch view]];
Location = [[CCDirector sharedDirector] convertToGL:Location];
Location = [self convertTouchToNodeSpace:touch];
NSLog(#"touch moved location x = %f , y =%f",Location.x,Location.y);
//touchLocation = [self convertTouchToNodeSpace:touch];
CGPoint oldTouchLocation = [touch previousLocationInView:touch.view];
oldTouchLocation = [[CCDirector sharedDirector] convertToGL:oldTouchLocation];
oldTouchLocation = [self convertToNodeSpace:oldTouchLocation];
CGPoint translation = ccpSub(Location, oldTouchLocation);
if (CGRectContainsPoint(selspriterect,Location))
{
[self panForTranslation:translation];
}
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)])
{
NSLog(#"respond to selector");
CGFloat scale = [[UIScreen mainScreen] scale];
if (scale > 1.0)
{
NSLog(#"iphone 4s");
CGPoint mypoint = CGPointMake(80, 357);
CGPoint mypoint1 = CGPointMake(237, 360);
CGPoint mypoint2 = CGPointMake(79, 255);
CGPoint mypoint3 = CGPointMake(237, 247);
CGPoint mypoint4 = CGPointMake(78, 153);
CGPoint mypoint5 = CGPointMake(239, 140);
CCSprite *disablesprite=nil;
switch (selSprite.tag) {
case 0:
if (CGRectContainsPoint( [dest[0] boundingBox] , mypoint ) ) {
NSLog(#"oneeeeee collided");
dest[0].position = ccp(192,380);
// selSprite = disablesprite;
}
break;
case 1:
if (CGRectContainsPoint( [dest[1] boundingBox] , mypoint1 ) ) {
NSLog(#"two collided");
dest[1].position = ccp(258,379);
}
break;
case 2:
if (CGRectContainsPoint( [dest[2] boundingBox] , mypoint2 ) ) {
NSLog(#"three collided");
dest[2].position = ccp(173,281);
}
break;
case 3:
if (CGRectContainsPoint( [dest[3] boundingBox] , mypoint3 ) ) {
NSLog(#"four collided");
dest[3].position = ccp(258,281);
}
break;
case 4:
if (CGRectContainsPoint( [dest[4] boundingBox] , mypoint4 ) ) {
NSLog(#"five collided");
dest[4].position = ccp(166,181);
}
break;
case 5:
if (CGRectContainsPoint( [dest[5] boundingBox] , mypoint5 ) ) {
NSLog(#"six collided");
dest[5].position = ccp(258,176);
}
break;
default:
break;
}
}
else {
CGPoint mypoint = CGPointMake(106, 329);
CGPoint mypoint1 = CGPointMake(208, 329);
CGPoint mypoint2 = CGPointMake(97, 220);
CGPoint mypoint3 = CGPointMake(217, 220);
CGPoint mypoint4 = CGPointMake(92, 124);
CGPoint mypoint5 = CGPointMake(212, 124);
CCSprite *disablesprite=nil;
switch (selSprite.tag) {
case 0:
if (CGRectContainsPoint( [dest[0] boundingBox] , mypoint ) ) {
NSLog(#"oneeeeee collided");
dest[0].position = ccp(125,320);
// selSprite = disablesprite;
}
break;
case 1:
if (CGRectContainsPoint( [dest[1] boundingBox] , mypoint1 ) ) {
NSLog(#"two collided");
dest[1].position = ccp(200,312);
}
break;
case 2:
if (CGRectContainsPoint( [dest[2] boundingBox] , mypoint2 ) ) {
NSLog(#"three collided");
dest[2].position = ccp(117,209);
}
break;
case 3:
if (CGRectContainsPoint( [dest[3] boundingBox] , mypoint3 ) ) {
NSLog(#"four collided");
dest[3].position = ccp(200,208);
}
break;
case 4:
if (CGRectContainsPoint( [dest[4] boundingBox] , mypoint4 ) ) {
NSLog(#"five collided");
dest[4].position = ccp(113,127);
}
break;
case 5:
if (CGRectContainsPoint( [dest[5] boundingBox] , mypoint5 ) ) {
NSLog(#"six collided");
dest[5].position = ccp(207,126);
}
break;
default:
break;
}
}
}
}
-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
CGPoint mypoint = CGPointMake(106, 329);
CGPoint mypoint1 = CGPointMake(208, 329);
CGPoint mypoint2 = CGPointMake(97, 220);
CGPoint mypoint3 = CGPointMake(217, 220);
CGPoint mypoint4 = CGPointMake(92, 124);
CGPoint mypoint5 = CGPointMake(212, 124);
switch (selSprite.tag) {
case 0:
if (CGRectContainsPoint( [dest[0] boundingBox] , mypoint ) ) {
NSLog(#"oneeeeee collided");
if (corsprite == TRUE) {
correctplace++;
corsprite = FALSE;
}
}else {
selSprite.position = ccp(110,50);
}
break;
case 1:
if (CGRectContainsPoint( [dest[1] boundingBox] , mypoint1 ) ) {
NSLog(#"two collided");
if (corsprite2 == TRUE) {
correctplace++;
corsprite2 = FALSE;
}
}else {
selSprite.position = ccp(110, 65);
}
break;
case 2:
if (CGRectContainsPoint( [dest[2] boundingBox] , mypoint2 ) ) {
NSLog(#"three collided");
if (corsprite3 == TRUE) {
correctplace++;
corsprite3 = FALSE;
}
}else {
selSprite.position =ccp(130, 10);
}
break;
case 3:
if (CGRectContainsPoint( [dest[3] boundingBox] , mypoint3 ) ) {
NSLog(#"four collided");
if (corsprite4 == TRUE) {
correctplace++;
corsprite4 = FALSE;
}
}else {
selSprite.position = ccp(215, 10);
}
break;
case 4:
if (CGRectContainsPoint( [dest[4] boundingBox] , mypoint4 ) ) {
NSLog(#"five collided");
if (corsprite5 == TRUE) {
correctplace++;
corsprite5 = FALSE;
}
}else {
selSprite.position = ccp(220,70);
}
break;
case 5:
if (CGRectContainsPoint( [dest[5] boundingBox] , mypoint5 ) ) {
NSLog(#"six collided");
if (corsprite6 == TRUE) {
correctplace++;
corsprite6 = FALSE;
}
}else {
selSprite.position = ccp(220,70);
}
break;
default:
break;
}
`

Do this in your app delegate
[director enableRetinaDisplay:YES];
and make sure your images follows the convention.
e.g. for iPhone3 suppose you have image as image.png then your retina image must be image-hd.png

Well, everything should be in points e.g. i dont think you need the logic around the UIScreen scale property, and your logic for scale=1 should work identically on a retina and non-retina display.
Quick try : change scale > 1.0 to scale > 3.0 (the if should always branch to the else part, which you state 'works' on iPhone 3), just to see if this is correct. If it is, remove the logic around scale altogether and cleanup :) ... In my code, i have not had one legitimate case of figuring out whether the scale is 1.0 or otherwise.

Related

CAShapeLayer Shadow with UIBezierPath

This question continues from a previous answer.
I have the following CAShapeLayer:
- (CAShapeLayer *)gaugeCircleLayer {
if (_gaugeCircleLayer == nil) {
_gaugeCircleLayer = [CAShapeLayer layer];
_gaugeCircleLayer.lineWidth = self.gaugeWidth;
_gaugeCircleLayer.fillColor = [UIColor clearColor].CGColor;
_gaugeCircleLayer.strokeColor = self.gaugeTintColor.CGColor;
_gaugeCircleLayer.strokeStart = 0.0f;
_gaugeCircleLayer.strokeEnd = self.value;
_gaugeCircleLayer.lineCap = kCALineCapRound;
_gaugeCircleLayer.path = [self insideCirclePath].CGPath;
CAShapeLayer *cap = [CAShapeLayer layer];
cap.shadowColor = [UIColor blackColor].CGColor;
cap.shadowRadius = 8.0;
cap.shadowOpacity = 0.9;
cap.shadowOffset = CGSizeMake(0, 0);
cap.fillColor = [UIColor grayColor].CGColor;
[_gaugeCircleLayer addSublayer:cap];
}
return _gaugeCircleLayer;
}
Then I have the following UIBezierPath:
- (UIBezierPath *)insideCirclePath {
CGPoint arcCenter = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:arcCenter
radius:CGRectGetWidth(self.bounds) / 2.0f
startAngle:(3.0f * M_PI_2)
endAngle:(3.0f * M_PI_2) + (2.0f * M_PI)
clockwise:YES];
return path;
}
This produces something like the following:
What I am trying to produce with the cap sublayer is the drop shadow at the end and I'd also be interested to know how to get a GradientLayer working similar to the image below:
The problem is that the sublayer is not appearing anywhere and I'm not quite sure why. I'm also not 100% sure on whether or not this is the best way to produce the desired effect.
UPDATE:
The following bit of code creates a cap, though I'm not quite sure how to add it to my UIBezierPath properly:
let cap = CAShapeLayer()
cap.shadowColor = UIColor.blackColor().CGColor
cap.shadowRadius = 8.0
cap.shadowOpacity = 0.9
cap.shadowOffset = CGSize(width: 0, height: 0)
cap.path = UIBezierPath(ovalInRect: CGRectMake(0, 40, 20, 20)).CGPath
cap.fillColor = UIColor.grayColor().CGColor
layer.addSublayer(cap)
I don't know if this will be useful to you, since it doesn't use the CHCircleGaugeView. I was working on several projects related to this question, so I mashed them together and made some changes to produce a progress view that has a color gradient background with a tip that overlaps the end at 100%. I haven't gotten to the point where I make the rounded tip disappear at 0%, but I'll get there eventually. Here are a couple of views of it at 2 different progress levels,
The view is created with a polar gradient drawn in drawRect, masked by an annulus. The rounded tip is a separate layer that's a half circle on the end of a line connected to the center of the circle that's revolved around its center with a transform based on the progress level. Here's the code,
#implementation AnnulusProgressView{ // subclass of UIView
int slices;
CGFloat circleRadius;
CAShapeLayer *maskLayer;
CGFloat segmentAngle;
CGFloat startAngle;
CAShapeLayer *tipView;
NSMutableArray *colors;
int sign;
}
-(instancetype)initWithFrame:(CGRect)frame wantsBackgroundRing:(BOOL)wantsBackground backgroundRingColor:(UIColor *)ringColor {
if (self = [super initWithFrame:frame]) {
slices = 360;
_ringThickness = 12;
circleRadius = self.bounds.size.width/2;
_startColor = [UIColor colorWithHue:0.24 saturation:1 brightness:0.8 alpha:1];
_endColor = [UIColor colorWithHue:0.03 saturation:1 brightness:1 alpha:1];
[self setupColorArray];
_backgroundRing = wantsBackground? [self createBackgroundRingWithColor:ringColor] : nil;
self.layer.mask = [self createAnnulusMask];
}
return self;
}
-(void)setStartColor:(UIColor *)startColor {
_startColor = startColor;
[self setupColorArray];
}
-(void)setEndColor:(UIColor *)endColor {
_endColor = endColor;
[self setupColorArray];
}
-(void)setupColorArray {
colors = [NSMutableArray new];
CGFloat startHue, startSaturation, startBrightness, startAlpha, endHue, endSaturation, endBrightness, endAlpha;
[self.startColor getHue:&startHue saturation:&startSaturation brightness:&startBrightness alpha:&startAlpha];
[self.endColor getHue:&endHue saturation:&endSaturation brightness:&endBrightness alpha:&endAlpha];
for(int i=0;i<slices;i++){
CGFloat hue = startHue + (endHue - startHue)*i/slices;
CGFloat brightness = startBrightness + (endBrightness - startBrightness)*i/slices;
CGFloat saturation = startSaturation + (endSaturation - startSaturation)*i/slices;
CGFloat alpha = startAlpha + (endAlpha - startAlpha)*i/slices;
UIColor *color = [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:alpha];
[colors addObject:color];
}
self.progress = _progress;
}
-(UIView *)createBackgroundRingWithColor:(UIColor *) color {
UIView *bgRing = [[UIView alloc] initWithFrame:self.frame];
bgRing.backgroundColor = color;
bgRing.layer.mask = [self createAnnulusMask];
[(CAShapeLayer *)bgRing.layer.mask setStrokeEnd:startAngle + 2*M_PI ];
return bgRing;
}
-(void)didMoveToSuperview {
if (self.backgroundRing) [self.superview insertSubview:self.backgroundRing belowSubview:self];
tipView = [self tipView];
[self.superview.layer addSublayer:tipView];
}
-(CAShapeLayer *)tipView {
CAShapeLayer *tip = [CAShapeLayer layer];
tip.frame = self.frame;
tip.fillColor = [UIColor redColor].CGColor;
UIBezierPath *shape = [UIBezierPath bezierPath];
CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
[shape moveToPoint:center];
CGPoint bottomPoint = CGPointMake(center.x, center.y + circleRadius - self.ringThickness*2);
CGFloat tipCenterY = bottomPoint.y + self.ringThickness - 1;
[shape addLineToPoint: bottomPoint];
[shape addLineToPoint:CGPointMake(bottomPoint.x+2, bottomPoint.y)];
double fractionAlongTangent = self.ringThickness;
[shape addCurveToPoint:CGPointMake(center.x, center.y + circleRadius) controlPoint1:CGPointMake(center.x - self.ringThickness*1.5, tipCenterY - fractionAlongTangent) controlPoint2:CGPointMake(center.x - self.ringThickness*1.5, tipCenterY + fractionAlongTangent)];
[shape closePath];
tip.path = shape.CGPath;
tip.shadowColor = [UIColor darkGrayColor].CGColor;
tip.shadowOpacity = 0.8;
tip.shadowOffset = CGSizeMake(-6, 0);
tip.shadowRadius = 2;
return tip;
}
- (void)setProgress:(CGFloat)progress{
sign = (progress >= _progress)? 1 : -1;
[self animateProgressTo:#(progress)];
}
-(void)animateProgressTo:(NSNumber *) newValueNumber{
float newValue = newValueNumber.floatValue;
_progress = (_progress + (sign * 0.1) > 1)? 1 : _progress + (sign * 0.1);
if ((_progress > newValue && sign == 1) || (_progress < newValue && sign == -1)) {
_progress = newValue;
}
maskLayer.strokeEnd = _progress;
tipView.transform = CATransform3DMakeRotation(-(1 - _progress + 0.002) * M_PI*2, 0, 0, 1); //the 0.002 closes a small gap between the tip and the annulus strokeEnd
int i = (int)(_progress*(slices - 1));
tipView.fillColor = ((UIColor *)colors[i]).CGColor;
if (sign == 1) {
if (_progress < newValue) {
[self performSelector:#selector(animateProgressTo:) withObject:#(newValue) afterDelay:0.05];
}
}else{
if (_progress > newValue) {
[self performSelector:#selector(animateProgressTo:) withObject:#(newValue) afterDelay:0.05];
}
}
NSLog(#"%f",_progress);
}
- (CAShapeLayer *)createAnnulusMask {
maskLayer = [CAShapeLayer layer];
maskLayer.frame = self.bounds;
segmentAngle = 2*M_PI/(slices);
startAngle = M_PI_2;
CGFloat endAngle = startAngle + 2*M_PI;
maskLayer.path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)) radius:circleRadius - self.ringThickness startAngle:startAngle endAngle:endAngle clockwise:YES].CGPath;
maskLayer.fillColor = [UIColor clearColor].CGColor;
maskLayer.strokeColor = [UIColor blackColor].CGColor;
maskLayer.lineWidth = self.ringThickness * 2;
maskLayer.strokeEnd = self.progress;
return maskLayer;
}
-(void)drawRect:(CGRect)rect{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetAllowsAntialiasing(ctx, NO);
CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
for(int i=0;i<slices;i++){
CGContextSaveGState(ctx);
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:center];
[path addArcWithCenter:center radius:circleRadius startAngle:startAngle endAngle:startAngle+segmentAngle clockwise:YES];
[path addClip];
[colors[i] setFill];
[path fill];
CGContextRestoreGState(ctx);
startAngle += segmentAngle;
}
}
This should resolve the problem.
Only remaining issue is the animation, whereby the cap is not animated.
The trick was to add the cap to the end of the gauge, and update it when the value of the gauge changed. To calculate the location, a little math magic was used. It needs to be under the gauge, so the cap is added in the trackCircleLayer
//
// CHCircleGaugeView.m
//
// Copyright (c) 2014 ChaiOne <http://www.chaione.com/>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "CHCircleGaugeView.h"
#import "CHCircleGaugeViewDebugMacros.h"
#import <CoreText/CoreText.h>
#import <QuartzCore/QuartzCore.h>
static CGFloat const CHKeyAnimationDuration = 0.5f;
static CGFloat const CHKeyDefaultValue = 0.0f;
static CGFloat const CHKeyDefaultFontSize = 32.0f;
static CGFloat const CHKeyDefaultTrackWidth = 0.5f;
static CGFloat const CHKeyDefaultGaugeWidth = 2.0f;
static NSString * const CHKeyDefaultNAText = #"n/a";
static NSString * const CHKeyDefaultNoAnswersText = #"%";
#define CHKeyDefaultTrackTintColor [UIColor blackColor]
#define CHKeyDefaultGaugeTintColor [UIColor blackColor]
#define CHKeyDefaultTextColor [UIColor blackColor]
#interface CHCircleGaugeView ()
#property (nonatomic, strong) CAShapeLayer *trackCircleLayer;
#property (nonatomic, strong) CAShapeLayer *gaugeCircleLayer;
// ADDED
#property (nonatomic, strong) CAShapeLayer *capLayer;
// END ADDED
#property (nonatomic, strong) UILabel *valueTextLabel;
#end
#implementation CHCircleGaugeView
#pragma mark - View Initialization
- (instancetype)init {
return [self initWithFrame:CGRectZero];
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self initSetup];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self initSetup];
}
return self;
}
- (void)initSetup {
_state = CHCircleGaugeViewStateNA;
_value = CHKeyDefaultValue;
_trackTintColor = CHKeyDefaultTrackTintColor;
_gaugeTintColor = CHKeyDefaultGaugeTintColor;
_textColor = CHKeyDefaultTextColor;
_font = [UIFont systemFontOfSize:CHKeyDefaultFontSize];
_trackWidth = CHKeyDefaultTrackWidth;
_gaugeWidth = CHKeyDefaultGaugeWidth;
_notApplicableString = CHKeyDefaultNAText;
_noDataString = CHKeyDefaultNoAnswersText;
[self createGauge];
}
- (void)createGauge {
[self.layer addSublayer:self.trackCircleLayer];
[self.layer addSublayer:self.gaugeCircleLayer];
[self addSubview:self.valueTextLabel];
[self setupConstraints];
}
- (void)setupConstraints {
NSDictionary *viewDictionary = #{#"valueText" : self.valueTextLabel};
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[valueText]|" options:0 metrics:nil views:viewDictionary]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[valueText]|" options:0 metrics:nil views:viewDictionary]];
}
#pragma mark - Property Setters
- (void)setState:(CHCircleGaugeViewState)state {
if (_state != state) {
_state = state;
switch (state) {
case CHCircleGaugeViewStateNA: {
[self updateGaugeWithValue:0 animated:NO];
break;
}
case CHCircleGaugeViewStatePercentSign: {
[self updateGaugeWithValue:0 animated:NO];
break;
}
case CHCircleGaugeViewStateScore: {
[self updateGaugeWithValue:self.value animated:NO];
break;
}
default: {
ALog(#"Missing gauge state.");
break;
}
}
}
}
- (void)setValue:(CGFloat)value {
[self setValue:value animated:NO];
}
- (void)setValue:(CGFloat)value animated:(BOOL)animated {
self.state = CHCircleGaugeViewStateScore;
if (value != _value) {
[self willChangeValueForKey:NSStringFromSelector(#selector(value))];
value = MIN(1.0f, MAX(0.0f, value));
[self updateGaugeWithValue:value animated:animated];
_value = value;
[self didChangeValueForKey:NSStringFromSelector(#selector(value))];
}
}
- (void)setUnitsString:(NSString *)unitsString {
if ([_unitsString isEqualToString:unitsString] == NO) {
_unitsString = [unitsString copy];
self.valueTextLabel.attributedText = [self formattedStringForValue:self.value];
}
}
- (void)updateGaugeWithValue:(CGFloat)value animated:(BOOL)animated {
self.valueTextLabel.attributedText = [self formattedStringForValue:value];
BOOL previousDisableActionsValue = [CATransaction disableActions];
[CATransaction setDisableActions:YES];
self.gaugeCircleLayer.strokeEnd = value;
// ADDED
_capLayer.path = [self capPathForValue:value].CGPath;
// END ADDED
if (animated) {
self.gaugeCircleLayer.strokeEnd = value;
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
pathAnimation.duration = CHKeyAnimationDuration;
pathAnimation.fromValue = [NSNumber numberWithFloat:self.value];
pathAnimation.toValue = [NSNumber numberWithFloat:value];
pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.gaugeCircleLayer addAnimation:pathAnimation forKey:#"strokeEndAnimation"];
}
[CATransaction setDisableActions:previousDisableActionsValue];
}
- (void)setTrackTintColor:(UIColor *)trackTintColor {
if (_trackTintColor != trackTintColor) {
_trackTintColor = trackTintColor;
self.trackCircleLayer.strokeColor = trackTintColor.CGColor;
}
}
- (void)setGaugeTintColor:(UIColor *)gaugeTintColor {
if (_gaugeTintColor != gaugeTintColor) {
_gaugeTintColor = gaugeTintColor;
self.gaugeCircleLayer.strokeColor = gaugeTintColor.CGColor;
// ADDED
self.capLayer.fillColor = gaugeTintColor.CGColor;
// END ADDED
}
}
- (void)setTrackWidth:(CGFloat)trackWidth {
if (_trackWidth != trackWidth) {
_trackWidth = trackWidth;
self.trackCircleLayer.lineWidth = trackWidth;
[self.layer layoutSublayers];
}
}
- (void)setGaugeWidth:(CGFloat)gaugeWidth {
if (_gaugeWidth != gaugeWidth) {
_gaugeWidth = gaugeWidth;
self.gaugeCircleLayer.lineWidth = gaugeWidth;
[self.layer layoutSublayers];
}
}
- (void)setTextColor:(UIColor *)textColor {
if (_textColor != textColor) {
_textColor = textColor;
self.valueTextLabel.textColor = textColor;
}
}
- (void)setFont:(UIFont *)font {
if (_font != font) {
_font = font;
self.valueTextLabel.font = font;
}
}
- (void)setGaugeStyle:(CHCircleGaugeStyle)gaugeStyle {
if (_gaugeStyle != gaugeStyle) {
_gaugeStyle = gaugeStyle;
[self.layer layoutSublayers];
}
}
#pragma mark - Circle Shapes
- (CAShapeLayer *)trackCircleLayer {
if (_trackCircleLayer == nil) {
_trackCircleLayer = [CAShapeLayer layer];
_trackCircleLayer.lineWidth = self.trackWidth;
_trackCircleLayer.fillColor = [UIColor clearColor].CGColor;
_trackCircleLayer.strokeColor = self.trackTintColor.CGColor;
_trackCircleLayer.path = [self insideCirclePath].CGPath;
// ADDED
_capLayer = [CAShapeLayer layer];
_capLayer.shadowColor = [UIColor blackColor].CGColor;
_capLayer.shadowRadius = 8.0;
_capLayer.shadowOpacity = 0.9;
_capLayer.shadowOffset = CGSizeMake(0, 0);
_capLayer.fillColor = self.gaugeTintColor.CGColor;
_capLayer.path = [self capPathForValue:self.value].CGPath;
[_trackCircleLayer addSublayer:_capLayer];
// END ADDED
}
return _trackCircleLayer;
}
- (CAShapeLayer *)gaugeCircleLayer {
if (_gaugeCircleLayer == nil) {
_gaugeCircleLayer = [CAShapeLayer layer];
_gaugeCircleLayer.lineWidth = self.gaugeWidth;
_gaugeCircleLayer.fillColor = [UIColor clearColor].CGColor;
_gaugeCircleLayer.strokeColor = self.gaugeTintColor.CGColor;
_gaugeCircleLayer.strokeStart = 0.0f;
_gaugeCircleLayer.strokeEnd = self.value;
_gaugeCircleLayer.path = [self circlPathForCurrentGaugeStyle].CGPath;
}
return _gaugeCircleLayer;
}
// ADDED
- (UIBezierPath *)capPathForValue:(float)value {
CGPoint arcCenter = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
CGFloat radius = CGRectGetWidth(self.bounds) / 2.0f;
float angle = value * 360.0;
float x = radius * sin(angle*M_PI/180.0);
float y = radius * cos(angle*M_PI/180.0);
CGPoint capArcCenter = CGPointMake(arcCenter.x + x, arcCenter.y - y);
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:capArcCenter
radius:self.gaugeWidth*_capLayer.shadowRadius / 2.0f
startAngle:(3.0f * M_PI_2)
endAngle:(3.0f * M_PI_2) + (2.0f * M_PI)
clockwise:YES];
return path;
}
// END ADDED
- (UIBezierPath *)circlPathForCurrentGaugeStyle {
switch (self.gaugeStyle) {
case CHCircleGaugeStyleInside: {
return [self insideCirclePath];
}
case CHCircleGaugeStyleOutside: {
return [self outsideCirclePath];
}
default: {
return nil;
}
}
}
- (UIBezierPath *)insideCirclePath {
CGPoint arcCenter = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:arcCenter
radius:CGRectGetWidth(self.bounds) / 2.0f
startAngle:(3.0f * M_PI_2)
endAngle:(3.0f * M_PI_2) + (2.0f * M_PI)
clockwise:YES];
return path;
}
- (UIBezierPath *)outsideCirclePath {
CGPoint arcCenter = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
CGFloat radius = (CGRectGetWidth(self.bounds) / 2.0f) + (self.trackWidth / 2.0f) + (self.gaugeWidth / 2.0f);
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:arcCenter
radius:radius
startAngle:(3.0f * M_PI_2)
endAngle:(3.0f * M_PI_2) + (2.0f * M_PI)
clockwise:YES];
return path;
}
#pragma mark - Text Label
- (UILabel *)valueTextLabel {
if (_valueTextLabel == nil) {
_valueTextLabel = [[UILabel alloc] init];
[_valueTextLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
_valueTextLabel.textAlignment = NSTextAlignmentCenter;
_valueTextLabel.attributedText = [self formattedStringForValue:self.value];
}
return _valueTextLabel;
}
- (NSAttributedString *)formattedStringForValue:(CGFloat)value {
NSAttributedString *valueString;
NSDictionary *stringAttributes = #{
NSForegroundColorAttributeName : self.textColor,
NSFontAttributeName : self.font
};
switch (self.state) {
case CHCircleGaugeViewStateNA: {
valueString = [[NSAttributedString alloc] initWithString:self.notApplicableString attributes:stringAttributes];
break;
}
case CHCircleGaugeViewStatePercentSign: {
valueString = [[NSAttributedString alloc] initWithString:self.noDataString attributes:stringAttributes];
break;
}
case CHCircleGaugeViewStateScore: {
NSString *suffix = self.unitsString ? self.unitsString : #"";
valueString = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:#"%.0f %#", value * 100.0f, suffix]
attributes:stringAttributes];
break;
}
default: {
ALog(#"Missing gauge state.");
break;
}
}
return valueString;
}
#pragma mark - KVO
// Handling KVO notifications for the value property, since
// we're proxying with the setValue:animated: method.
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
if ([key isEqualToString:NSStringFromSelector(#selector(value))]) {
return NO;
} else {
return [super automaticallyNotifiesObserversForKey:key];
}
}
#pragma mark - CALayerDelegate
- (void)layoutSublayersOfLayer:(CALayer *)layer {
[super layoutSublayersOfLayer:layer];
if (layer == self.layer) {
self.trackCircleLayer.path = [self insideCirclePath].CGPath;
self.gaugeCircleLayer.path = [self circlPathForCurrentGaugeStyle].CGPath;
}
}
#end

UIPinchGestureRecognizer trouble

Ok, i've read a few posts on this one (ex. UIImageView Gestures (Zoom, Rotate) Question) but I can't seem to fix my problem.
I have the following setup: an SKScene, an SKNode _backgroundLayer and 9 SKSpriteNodes that are tiles that make up the background and are attached to the _backgroundLayer.
Since these 9 tiles make a 3x3 square and they are quite large, I need to be able to zoom in and look at other SKSpriteNodes that will be on top of these 9 background images.
There are two problems:
1) When I pinch to zoom in or zoom out it seems like it is zooming in/out from location (0,0) of the _backgroundLayer and not from the touch location.
2) I have added some bounds so that the user can not scroll out of the 9 background images. In general it works. However, if I zoom in then move towards the top of the 9 background images and then zoom out the bounding conditions go berserk and the user can see the black space outside the background images. I need a way to limit the amount of zooming out that the user can do depending on where he's at.
Any ideas? Thanks!
I include my code below:
#import "LevelSelectScene.h"
#import "TurtleWorldSubScene.h"
#interface LevelSelectScene ()
#property (nonatomic, strong) SKNode *selectedNode;
#end
#implementation LevelSelectScene
{
SKNode *_backgroundLayer;
}
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */
_backgroundLayer = [SKNode node];
_backgroundLayer.name = #"backgroundLayer";
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[_backgroundLayer setScale:0.76];
} else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && IS_WIDESCREEN) {
} else {
[_backgroundLayer setScale:0.36];
}
[self addChild:_backgroundLayer];
SKTexture *backgroundTexture = [SKTexture textureWithImageNamed:#"levelSelect"];
int textureID = 0;
for (int i = 0; i<3; i++) {
for (int j = 0; j<3; j++) {
SKSpriteNode *background = [SKSpriteNode spriteNodeWithTexture:backgroundTexture];
background.anchorPoint = CGPointZero;
background.position = CGPointMake((background.size.width)*i, (background.size.height)*j);
background.zPosition = 0;
background.name = [NSString stringWithFormat:#"background%d", textureID];
textureID++;
[_backgroundLayer addChild:background];
}
}
[TurtleWorldSubScene displayTurtleWorld:self];
}
return self;
}
- (void)didMoveToView:(SKView *)view {
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanFrom:)];
[[self view] addGestureRecognizer:panGestureRecognizer];
//UITapGestureRecognizer * tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
// [self.view addGestureRecognizer:tapRecognizer];
UIPinchGestureRecognizer *pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(handlePinch:)];
[[self view] addGestureRecognizer:pinchGestureRecognizer];
}
- (void)handlePanFrom:(UIPanGestureRecognizer *)recognizer {
if (recognizer.state == UIGestureRecognizerStateBegan) {
CGPoint touchLocation = [recognizer locationInView:recognizer.view];
touchLocation = [self convertPointFromView:touchLocation];
SKNode *node = [self nodeAtPoint:touchLocation];
_selectedNode = node;
} else if (recognizer.state == UIGestureRecognizerStateChanged) {
CGPoint translation = [recognizer translationInView:recognizer.view];
translation = CGPointMake(translation.x, -translation.y);
CGPoint initialPosition = CGPointAdd(_backgroundLayer.position, translation);
_backgroundLayer.position = [self boundLayerPos:initialPosition];
[recognizer setTranslation:CGPointZero inView:recognizer.view];
} else if (recognizer.state == UIGestureRecognizerStateEnded) {
float scrollDuration = 0.2;
CGPoint velocity = [recognizer velocityInView:recognizer.view];
CGPoint pos = [_backgroundLayer position];
CGPoint p = CGPointMultiplyScalar(velocity, scrollDuration);
CGPoint newPos = CGPointMake(pos.x + p.x, pos.y - p.y);
newPos = [self boundLayerPos:newPos];
[_backgroundLayer removeAllActions];
SKAction *moveTo = [SKAction moveTo:newPos duration:scrollDuration];
[moveTo setTimingMode:SKActionTimingEaseOut];
[_backgroundLayer runAction:moveTo];
}
}
- (void)handlePinch:(UIPinchGestureRecognizer *) recognizer
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
if(_backgroundLayer.xScale*recognizer.scale < 0.76) {
//SKSpriteNode *backgroundTile = (SKSpriteNode *)[_backgroundLayer childNodeWithName:#"background0"];
[_backgroundLayer setScale:0.76];
} else if(_backgroundLayer.xScale*recognizer.scale > 2) {
[_backgroundLayer setScale:2.0];
} else {
[_backgroundLayer runAction:[SKAction scaleBy:recognizer.scale duration:0]];
}
} else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && IS_WIDESCREEN) {
} else {
if(_backgroundLayer.xScale*recognizer.scale < 0.36) {
[_backgroundLayer setScale:0.36];
} else if(_backgroundLayer.xScale*recognizer.scale > 2) {
[_backgroundLayer setScale:2.0];
} else {
[_backgroundLayer runAction:[SKAction scaleBy:recognizer.scale duration:0]];
}
}
recognizer.scale = 1;
}
- (CGPoint)boundLayerPos:(CGPoint)newPos {
SKSpriteNode *backgroundTile = (SKSpriteNode *)[_backgroundLayer childNodeWithName:#"background0"];
CGPoint retval = newPos;
retval.x = MIN(retval.x, 0);
retval.x = MAX(retval.x, -(backgroundTile.size.width*_backgroundLayer.xScale*3)+self.size.width);
retval.y = MIN(retval.y, 0);
retval.y = MAX(retval.y, -(backgroundTile.size.height*_backgroundLayer.xScale*3)+self.size.height);
return retval;
}

SKSpriteNode rotation not working properly

I'm trying to rotate a SKSpriteNode by using UIRrotationGestureRecognizer. I've implemented a code but sometimes, when I rotate the node it jumps to a rotation that isn't the one it should be. Here you have the code:
- (void) handleRotation:(UIRotationGestureRecognizer *) rotationrecognizer{
CGFloat initialrotation = 0.0;
if (rotationrecognizer.state == UIGestureRecognizerStateBegan) {
CGPoint touchLocation = [rotationrecognizer locationInView:rotationrecognizer.view];
touchLocation = [self convertPointFromView:touchLocation];
[self selectNodeForTouch:touchLocation];
initialrotation = selected.zRotation;
}
else if (rotationrecognizer.state == UIGestureRecognizerStateChanged) {
CGFloat angle = initialrotation + rotationrecognizer.rotation;
selected.zRotation = angle;
}
}
You are resetting initial rotation to 0 on every call... you should move this to be an ivar of your view if you need it to stay resident.
The way you have it written now, the line that sets 'angle' is effectively equal to this:
CGFloat angle = 0 + rotationrecognizer.rotation;
Instead, you should do the following (where initialRotation is defined as a private ivar):
- (void) handleRotation:(UIRotationGestureRecognizer *) rotationrecognizer{
if (rotationrecognizer.state == UIGestureRecognizerStateBegan) {
CGPoint touchLocation = [rotationrecognizer locationInView:rotationrecognizer.view];
touchLocation = [self convertPointFromView:touchLocation];
[self selectNodeForTouch:touchLocation];
_initialrotation = selected.zRotation;
}
else if (rotationrecognizer.state == UIGestureRecognizerStateChanged) {
CGFloat angle = _initialrotation + rotationrecognizer.rotation;
selected.zRotation = angle;
}
}

Scrabble drag technique

I had created an puzzle game which was like Scrabble.
Here is the layout:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
What is my problem?
My problem was when I start touch from 1 and direction to 12, If touch and drag in slow then no problem but when drag in fast, I manage to 1, 6, 12 or 1, 7, 12 only. There is missing a number.
How to make sure the path numbers all be selected?
I am using touch began, touch moved and touch ended and check with coordinate to locate which number is being touched.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
UITouch *touch = [touches anyObject];
CGPoint currentTouchLocation = [touch locationInView:self.numberview];
if(!ispause && [time.text intValue] > 0){
if(!isbegan && !isended){
for(int i = 1; i <= 16; i++)
{
UIView *imageview = [self.numberview viewWithTag:i];
if (CGRectContainsPoint(imageview.frame, currentTouchLocation))
{
isbegan = YES;
isreverse = NO;
if([[ischose objectAtIndex:i-1] boolValue] == 0)
{
currentposition = imageview.tag;
positionvalue += pow(i, 3);
currentanswer += [self converter:[NSString stringWithFormat:#"%#", [allimagenumbers substringWithRange:NSMakeRange(i-1, 1)]]];
[ischose replaceObjectAtIndex:i-1 withObject:[NSNumber numberWithBool:YES]];
[self changeimage:#"selected"];
}
break;
}
}
}
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
[super touchesMoved:touches withEvent:event];
UITouch *touch = [touches anyObject];
CGPoint currentTouchLocation = [touch locationInView:self.numberview];
float gapX = image1.frame.size.width / 8;
float gapY = image1.frame.size.height / 8;
if(isbegan && !isended)
{
if(currentTouchLocation.x >= 0 && currentTouchLocation.x <= self.numberview.frame.size.width && currentTouchLocation.y >= 0 && currentTouchLocation.y <= self.numberview.frame.size.height)
{
for(int i = 1; i <= 16; i++)
{
UIView *imageview = [self.numberview viewWithTag:i];
if (CGRectContainsPoint(imageview.frame, currentTouchLocation))
{
if((currentTouchLocation.x >= imageview.frame.origin.x + gapX && currentTouchLocation.x < imageview.frame.origin.x + imageview.frame.size.width - gapX) && (currentTouchLocation.y >= imageview.frame.origin.y + gapY && currentTouchLocation.y < imageview.frame.origin.y + imageview.frame.size.height - gapY ))
{
if([[ischose objectAtIndex:i-1] boolValue] == 0 && !isreverse)
{
currentposition = imageview.tag;
positionvalue += pow(i, 3);
currentanswer += [self converter:[NSString stringWithFormat:#"%#", [allimagenumbers substringWithRange:NSMakeRange(i-1, 1)]]];
[ischose replaceObjectAtIndex:i-1 withObject:[NSNumber numberWithBool:YES]];
[self changeimage:#"selected"];
}
else
{
if(currentposition != imageview.tag)
{
isreverse = YES;
}
else
{
isreverse = NO;
}
}
break;
}
}
}
}
else
{
isended = YES;
isoutofbound = YES;
if(isbegan && isoutofbound)
[self countinganswer];
}
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
if(!isoutofbound)
{
isended = YES;
[self countinganswer];
}
else
isoutofbound = NO;
}
-(void)changeimage:(NSString *)status{
if([status isEqualToString:#"default"])
{
for(int i = 1; i <=16;i++)
{
UIImageView *imageview = (UIImageView*)[self.numberview viewWithTag:i];
imageview.image = [UIImage imageNamed:[NSString stringWithFormat:#"stone%#", [allimagenumbers substringWithRange:NSMakeRange(i-1, 1)]]];
[image1 setUserInteractionEnabled:YES];
}
}
else if([status isEqualToString:#"correct"] || [status isEqualToString:#"selected"])
{
for(int i = 1; i<= ischose.count; i++)
{
if([[ischose objectAtIndex:i-1] boolValue] == 1)
{
UIImageView *imageview = (UIImageView*)[self.numberview viewWithTag:i];
imageview.image = [UIImage imageNamed:[NSString stringWithFormat:#"stone%#_correct", [allimagenumbers substringWithRange:NSMakeRange(i-1, 1)]]];
}
}
}
else if([status isEqualToString:#"wrong"] || [status isEqualToString:#"repeat"])
{
for(int i = 1; i<= ischose.count; i++)
{
if([[ischose objectAtIndex:i-1] boolValue] == 1)
{
UIImageView *imageview = (UIImageView*)[self.numberview viewWithTag:i];
imageview.image = [UIImage imageNamed:[NSString stringWithFormat:#"stone%#_wrong_repeat", [allimagenumbers substringWithRange:NSMakeRange(i-1, 1)]]];
}
}
}
}
Update:
Chatting with you, it appears that you have solved your problem (where a swipe over one of your UIImageView objects was not being detected). It looks like the solution was a unique issue (i.e. highly "localized" in Stack Overflow language) associated with your code to create reduced size "hit zones" that you constructed with your gap variables. It doesn't look like the solution was anything really associated with touchesMoved, iOS API, or iOS system performance. Regardless, I'm glad you solved the problem.
My original answer below was predicated on the original source code posted, which had the same logic repeated for each of the 16 UIImageView objects. I was just demonstrating how you can use a UIArray to significantly simplify that logic. I also use UIPanGestureRecognizer, which I think unifies the code, and with <UIKit/UIGestureRecognizerSubclass.h> you can cancel the gesture, in case the user's gesture went "out of bounds."
Original answer:
I'm assuming that you simply want to build an array of image numbers as the user drags their finger over the numbers. So the ARC code might look something like:
// NumberGameViewController.m
#import "NumberGameViewController.h"
#import <UIKit/UIGestureRecognizerSubclass.h>
#interface NumberGameViewController ()
{
NSArray *images;
NSMutableArray *results;
}
#end
#implementation NumberGameViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// if you build an array of your images, the logic to determine which image you're over is much easier
images = #[self.image1, self.image2, self.image3, self.image4, self.image5, self.image6, self.image7, self.image8, self.image9, self.image10, self.image11, self.image12, self.image13, self.image14, self.image15, self.image16];
// I know you used `touchesMoved` and the like, but I think gesture recognizers are a little easier
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
[self.numberview addGestureRecognizer:pan];
}
- (NSInteger)determineImageNumber:(CGPoint)point
{
for (NSInteger i = 0; i < [images count]; i++)
{
UIImageView *imageview = images[i];
// I'm just going to see if the user's finger was over the number in question.
// If you wanted more restrictive logic (e.g. 3/4ths of the frame), just adjust
// adjust the frame variable here.
CGRect frame = imageview.frame;
if (CGRectContainsPoint(frame, point))
return i;
}
return -1;
}
- (void)handlePan:(UIGestureRecognizer *)gesture
{
CGPoint location = [gesture locationInView:self.numberview];
NSInteger imageNumber = [self determineImageNumber:location];
static NSInteger lastImageNumber;
if (gesture.state == UIGestureRecognizerStateBegan)
{
results = [[NSMutableArray alloc] init];
if (imageNumber >= 0)
{
[results addObject:#(imageNumber)];
}
}
else if (gesture.state == UIGestureRecognizerStateChanged)
{
if (imageNumber >= 0)
{
if (imageNumber != lastImageNumber)
{
// If you want to do some visual adjustment of the image you're over, do it
// here.
// add the image to our array of results
[results addObject:#(imageNumber)];
// if you want to do some additional validation (e.g. do you have 16 points,
// has the user hit the same number twice, etc.), do that here
}
}
// by the way, let's check to see if we're still within the numberview subview, and if
// not, let's cancel the gesture
if (!CGRectContainsPoint(self.numberview.bounds, location))
{
gesture.state = UIGestureRecognizerStateCancelled;
return;
}
}
else if ((gesture.state == UIGestureRecognizerStateEnded) || (gesture.state == UIGestureRecognizerStateCancelled) || (gesture.state == UIGestureRecognizerStateFailed))
{
// At this point you'd do any final validation of the user's response, to see if they
// succeeded or not. I'm just displaying the results in the console
NSLog(#"%#", results);
}
if (imageNumber >= 0)
lastImageNumber = imageNumber;
}
#end
float gapX = image1.frame.size.width / 8;
float gapY = image1.frame.size.height / 8;
Here is the problem, there is a gap within all images so when fast drag it will be outer part of images

How to make tile set colliders with player movement by accelerometer iOS, cocos2d

I am trying to make iPhone game, using cocos2d, where you roll a ball down a given path and you cannot touch certain objects.
I did an RPG tutorial which taught me how to make the tile colliders and it works when I move the ball by using isTouchEnabled, but when I apply the same logic to accelerometer it doesn't seem to register.
THis is the touch player movement method, just so you can see how it is suppose to work.
-(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchLocation = [touch locationInView:[touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
touchLocation = [self convertToNodeSpace:touchLocation];
CGPoint playerPos = ball.position;
CGPoint diff = ccpSub(touchLocation, playerPos);
//move horizontal or vertical?
if(abs(diff.x) > abs(diff.y)){
if(diff.x > 0)
{
playerPos.x += theMap.tileSize.width;
}else{
playerPos.x -= theMap.tileSize.width;
}
}else{
if(diff.y > 0){
playerPos.y += theMap.tileSize.height;
}else{
playerPos.y -= theMap.tileSize.height;
}
}
//make sure the player isnt off the map
if(playerPos.x <= (theMap.mapSize.width * theMap.tileSize.width) &&
playerPos.y <= (theMap.mapSize.height * theMap.tileSize.height) &&
playerPos.x >=0 &&
playerPos.y >=0)
{
[self setPlayerPostion:playerPos];
}
[self setCenterOfScreen:ball.position];
}
Below is how it get the position of the ball and move it using the accelerometer
-(void)updateBall:(ccTime)delta{
//ball.position = ccp(ball.position.x, ball.position.y + tiltVertical);
//ball.position = ccp(ball.position.x + tiltHorizontal, ball.position.y);
CGPoint playerPos = ball.position;
playerPos.x += tiltHorizontal;
playerPos.y += tiltVertical;
ball.position = playerPos;
//make sure the player isnt off the map
if(playerPos.x <= (theMap.mapSize.width * theMap.tileSize.width) &&
playerPos.y <= (theMap.mapSize.height * theMap.tileSize.height) &&
playerPos.x >=0 &&
playerPos.y >=0)
{
ball.position = playerPos;
CCLOG(#"testing for off screen");
[self setPlayerPostion:playerPos];
ball.position = playerPos;
}
ball.position = playerPos;
[self setCenterOfScreen:ball.position];
}
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration{
tiltHorizontal = (acceleration.y* (-20));
tiltVertical = (acceleration.x) * 20;
}
Here are the two methods that are used for getting the tile position and seeing if the properties of tile are Collidable and true (this is set in tiled when I created my map).
-(void)setPlayerPostion:(CGPoint)position{
CGPoint tileCoord = [self tileCoordForPosition:position];
int tileGid = [stLayer tileGIDAt:tileCoord];
if(tileGid)
{
NSDictionary *properties = [theMap propertiesForGID:tileGid];
if(properties){
NSString *collision = [properties valueForKey:#"Collidable"];
if(collision && [collision compare:#"True"] ==NSOrderedSame){
return;
}
}
}
ball.position = position;
}
-(CGPoint)tileCoordForPosition:(CGPoint)position{
int x = position.x/theMap.tileSize.width;
int y = ((theMap.mapSize.height * theMap.tileSize.height)- position.y)/theMap.tileSize.height;
return ccp(x,y);
}
Is there something wrong with my logic? or any suggestion would be appreciated.
Thanks
Make sure you have the line self.isAccelerometerEnabled = YES in your init method.