I have a game where a fireball UIImage falls from the screen, and the user moves the player object with the touch screen to avoid them. After 8 points, the playAgainButton pops up. However, this playAgainButton button isn't working. It doesn't execute any of the code in the ResetGame method, and it actually resets the position of my character object "Dustin", which I don't want to happen. I have a referencing outlet attached to the button. How can I get the code in ResetGame to work? My ViewController code is below.
int theScore;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self initializeTimer];
}
- (IBAction)ResetGame:(id)sender { //only thing that actually happens right now is that Dustin resets for some reason.
theScore = 0;
[self updateScore];
_Fireball.center = CGPointMake(64, 64);
_endLabel.hidden = true;
_playAgainButton.hidden = true;
[self gameLogic:theTimer];
}
- (void)updateScore {
_score.text = [[NSString alloc] initWithFormat:#"%d",theScore];
}
- (void) initializeTimer {
if(theTimer == nil)
{
theTimer = [CADisplayLink displayLinkWithTarget:self selector:#selector(gameLogic:)];
}
theTimer.frameInterval = 1;
[theTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void) gameLogic:(CADisplayLink *) theTimer {
if((!CGRectIntersectsRect(_Fireball.frame, _Dustin.frame)) && (theScore < 8)){
if(_Fireball.center.y >600){
int num = arc4random() % 3;
if(num == 0){
_Fireball.center = CGPointMake(64, 64);
}
else if(num == 1){
_Fireball.center = CGPointMake(192, 64);
}
else if(num == 2){
_Fireball.center = CGPointMake(320, 64);
}
theScore = theScore + 1;
[self updateScore];
}
_Fireball.center = CGPointMake(_Fireball.center.x, _Fireball.center.y+12); }
else if(theScore == 8){
_Fireball.center = CGPointMake(_Fireball.center.x, _Fireball.center.y);
_endLabel.text = #"You Win!";
_endLabel.hidden = false;
_playAgainButton.hidden = false;
}
}
- (void) touchesBegan:(NSSet *) touches withEvent:(UIEvent *) event {
UITouch *touch = [touches anyObject];
_firstTouch = [touch locationInView:self.view];
_lastTouch = [touch locationInView:self.view];
_Dustin.center = CGPointMake(_firstTouch.x, _Dustin.center.y);
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
_firstTouch = [touch locationInView:self.view];
_lastTouch = [touch locationInView:self.view];
_Dustin.center = CGPointMake(_firstTouch.x, _Dustin.center.y);
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
_firstTouch = [touch locationInView:self.view];
_lastTouch = [touch locationInView:self.view];
_Dustin.center = CGPointMake(_firstTouch.x, _Dustin.center.y);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
Your touchesBegan etc. methods are not calling super and thus all touches are being captured by your app and cannot get through to your button.
Add a call to super to each of these methods.
Related
The game I'm trying to make is simple enough. A UIImageView fireball falls from the top of the screen, and the touch screen is used to move the other UIImageView Dustin to avoid it.
Once the fireball reaches the bottom of the screen, it resets back to the top, and the user's score increases by 1. The problem is that after I added the scoring functions, the Dustin UIImage resets to its original position after the fireball reaches the bottom. Without the scoring method, Dustin's image doesn't reset. How does the scoring cause my imageview's position to reset? Most of my code from the ViewController is below.
int theScore;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self initializeTimer];
}
- (void)updateScore {
theScore = theScore + 1;
_score.text = [[NSString alloc] initWithFormat:#"%d",theScore];
}
- (void) initializeTimer {
if(theTimer == nil)
{
theTimer = [CADisplayLink displayLinkWithTarget:self selector:#selector(gameLogic:)];
}
theTimer.frameInterval = 1;
[theTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void) gameLogic:(CADisplayLink *) theTimer {
if(!CGRectIntersectsRect(_fireball.frame, _Dustin.frame)){
if(_fireball.center.y >600){
_fireball.center = CGPointMake(0, 0);
[self updateScore];
}
_fireball.center = CGPointMake(_fireball.center.x, _fireball.center.y+4);
}
else{
}
}
- (void) touchesBegan:(NSSet *) touches withEvent:(UIEvent *) event {
UITouch *touch = [touches anyObject];
_firstTouch = [touch locationInView:self.view];
_lastTouch = [touch locationInView:self.view];
_Dustin.center = CGPointMake(_firstTouch.x, _Dustin.center.y);
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
_firstTouch = [touch locationInView:self.view];
_lastTouch = [touch locationInView:self.view];
_Dustin.center = CGPointMake(_firstTouch.x, _Dustin.center.y);
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
_firstTouch = [touch locationInView:self.view];
_lastTouch = [touch locationInView:self.view];
_Dustin.center = CGPointMake(_firstTouch.x, _Dustin.center.y);
}
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
In my app i want to create a custom gesture recognizer that recognizes a long press followed by a swipe.
I need to measure if the length of the long press is more than 1 second. If it is, then call a function and wait for the swipe action to begin.
My problem is that I the only way i know now how long the press was is by extracting the timestamp of touchesBegan from touchesMoved. However i want to know that elapsed time before touchesMoved gets called.
Is there a way to know the length of the tap before the touchesMoved is called?
Thanks in advance!
you can use may code, it can use, but maybe you should deal with some details
in the .h file you should add these ivar:
TestView *aView ;//the view which you press
NSThread *timerThread;
NSTimer *touchTimer;
NSDate *touchStartTime;
CGPoint touchStartPoint;
CGPoint lastTouchPoint;
in the .m file you should add these method:
- (void)doSomething
{
NSLog(#"Long press!!!");
}
- (void)startTimerThead{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
touchTimer = [NSTimer scheduledTimerWithTimeInterval:0.2
target:self
selector:#selector(checkTouchTime:)
userInfo:nil repeats:YES];
[runLoop run];
[pool release];
}
- (void)stopTouchTimer{
if (touchTimer != nil) {
[touchTimer invalidate];
touchTimer = nil;
}
if (timerThread != nil) {
[timerThread cancel];
[timerThread release];
timerThread = nil;
}
}
#define DELETE_ACTIVING_TIME 1.0
- (void)checkTouchTime:(NSTimer*)timer{
NSDate *nowDate = [NSDate date];
NSTimeInterval didTouchTime = [nowDate timeIntervalSinceDate:touchStartTime];
if (didTouchTime > DELETE_ACTIVING_TIME){
[self stopTouchTimer];
[self doSomething];
}
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
UIView *touchView = [touch view];
if ([touchView isKindOfClass:[TestView class]]) {
touchStartTime = [[NSDate date] retain];
if (nil == timerThread) {
timerThread = [[NSThread alloc] initWithTarget:self selector:#selector(startTimerThead) object:nil];
[timerThread start];
}
}
touchStartPoint = [touch locationInView:self.view];
lastTouchPoint = touchStartPoint;
}
#define TOUCH_MOVE_EFFECT_DIST 10.0f
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint movedPoint = [touch locationInView:self.view];
CGPoint deltaVector = CGPointMake(movedPoint.x - touchStartPoint.x, movedPoint.y - touchStartPoint.y);
if (fabsf(deltaVector.x) > TOUCH_MOVE_EFFECT_DIST
|| fabsf(deltaVector.y) > TOUCH_MOVE_EFFECT_DIST)
{
[self stopTouchTimer];
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
UIView *touchView = [touch view];
CGPoint movedPoint = [touch locationInView:self.view];
CGPoint deltaVector = CGPointMake(movedPoint.x - touchStartPoint.x, movedPoint.y - touchStartPoint.y);
if ([touchView isKindOfClass:[TestView class]]) {
if (fabsf(deltaVector.x) < TOUCH_MOVE_EFFECT_DIST
&& fabsf(deltaVector.y) < TOUCH_MOVE_EFFECT_DIST) {
[self stopTouchTimer];
}
}
}
In this cocos2d app the nslog is not firing when I press the ccsprite. Could someone help me?
-(BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
NSMutableArray *targetsToDelete = [[NSMutableArray alloc] init];
for (CCSprite *target in _targets) {
CGRect targetRect = CGRectMake(target.position.x - (target.contentSize.width/2),
target.position.y - (target.contentSize.height/2),
27,
40);
CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
if (CGRectContainsPoint(targetRect, touchLocation)) {
NSLog(#"Moo cheese!");
}
}
return YES;
}
First of all be sure that you register the sprite for touches into the onEnter method for example:
- (void)onEnter
{
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:defaultTouchPriority_ swallowsTouches:YES];
[super onEnter];
}
This will make your sprite touchable and so fire the event to the sprite when a user will press it.
Then refactor your code to make it more readable and test something like that:
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
NSArray *targetsToDelete = [self touchedSpritesAtLocation:touchLocation];
// Put your code here
// ...
return YES;
}
- (NSArray *)touchedSpritesAtLocation:(CGPoint)location
{
NSMutableArray *touchedSprites = [[NSMutableArray alloc] init];
for (CCSprite *target in _targets)
if (CGRectContainsPoint(target.boundingBox, location))
[touchedSprites addObject:target];
return [touchedSprites autorelease];
}
It should return the targets that have been touched.
In layer init method add this
self.isTouchEnabled = true;
Use this code for touch detection
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
CGRect rect = [self getSpriteRect:yourSprite];
if (CGRectContainsPoint(rect, location))
{
NSLog(#"Sprite touched\n");
}
}
To get sprite rect:
-(CGRect)getSpriteRect:(CCNode *)inSprite
{
CGRect sprRect = CGRectMake(
inSprite.position.x - inSprite.contentSize.width*inSprite.anchorPoint.x,
inSprite.position.y - inSprite.contentSize.height*inSprite.anchorPoint.y,
inSprite.contentSize.width,
inSprite.contentSize.height
);
return sprRect;
}
I want to draw line on finger touch in cocos 2d.
-(void) ccTouchesMoved:(NSSet *)inappropriateTouches withEvent:(UIEvent *)event
{
UITouch *touch = [inappropriateTouches anyObject];
CGPoint currentTouchArea = [touch locationInView:[touch view] ];
CGPoint lastTouchArea = [touch previousLocationInView:[touch view]];
currentTouchArea = [[CCDirector sharedDirector] convertToGL:currentTouchArea];
lastTouchArea = [[CCDirector sharedDirector] convertToGL:lastTouchArea];
// throw to console my inappropriate touches
NSLog(#"current x=%2f,y=%2f",currentTouchArea.x, currentTouchArea.y);
NSLog(#"last x=%2f,y=%2f",lastTouchArea.x, lastTouchArea.y);
glColor4f(0.8, 1.0, 0.76, 1.0);
glLineWidth(6.0f);
ccDrawLine(currentTouchArea, lastTouchArea);
}
I use this code but nothing is drawn on the screen. What is wrong in my code?
All OpenGL drawing you want to do in the draw method. Like this:
-(void)draw
{
if(lastTouchArea != 0)
{
glColor4f(0.8, 1.0, 0.76, 1.0);
glLineWidth(6.0f);
ccDrawLine(currentTouchArea, lastTouchArea);
lastTouchArea = 0;
}
}
Try this : to save a line in a NSMutableArray
-(void) ccTouchesMoved:(NSSet *)inappropriateTouches withEvent:(UIEvent *)event
{
UITouch *touchMyMinge = [inappropriateTouches anyObject];
CGPoint currentTouchArea = [touchMyMinge locationInView:[touchMyminge view] ];
CGPoint lastTouchArea = [touchMyMinge previousLocationInView:[touchMyMinge view]];
// flip belly up. no one likes being entered from behind.
currentTouchArea = [[CCDirector sharedDirector] convertToGL:currentTouchArea];
lastTouchArea = [[CCDirector sharedDirector] convertToGL:lastTouchArea];
// throw to console my inappropriate touches
NSLog(#"current x=%2f,y=%2f",currentTouchArea.x, currentTouchArea.y);
NSLog(#"last x=%2f,y=%2f",lastTouchArea.x, lastTouchArea.y);
// add my touches to the naughty touch array
naughtyTouchArray addObject:NSStringFromCGPoint(currentTouchArea)];
naughtyTouchArray addObject:NSStringFromCGPoint(lastTouchArea)];
}
#implementation DrawMyTouch
-(id) init
{
if( (self=[super init]))
{ }
return self;
}
-(void)draw
{
glEnable(GL_LINE_SMOOTH);
for(int i = 0; i < [naughtyTouchArray count]; i+=2)
{
start = CGPointFromString([naughtyTouchArray objectAtIndex:i]);
end = CGPointFromString([naughtyTouchArray objectAtIndex:i+1]);
ccDrawLine(start, end);
}
}
-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
DrawMyTouch *line = [DrawMyTouch node];
[self addChild: line];
}
Hope this help