In my Box2d game i try to use uiswipegesture to get the swipe gesture up and when i do in test project it works fine but when i implement in box2d game it does not called swipe action here is the code
{UISwipeGestureRecognizer *swipeGestureup = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(oneFingerSwipeUp)];
[swipeGestureup setDirection: UISwipeGestureRecognizerDirectionUp ];
[[[CCDirector sharedDirector] openGLView] addGestureRecognizer:swipeGestureup];
[swipeGestureup release];}
and method is
-(void)oneFingerSwipeUp:(id)sender{
NSLog(#"swipe auction called");
[player jump];
}
{
UISwipeGestureRecognizer *swipeGestureup = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(oneFingerSwipeUp:)];
[swipeGestureup setDirection: UISwipeGestureRecognizerDirectionUp ];
[[[CCDirector sharedDirector] openGLView] addGestureRecognizer:swipeGestureup];
[swipeGestureup release];
}
- (void)oneFingerSwipeUp:(UISwipeGestureRecognizer *)recognizer{
NSLog(#"swipe auction called");
}
Related
I am using mpmovieplayercontroller to play a movie in my game. When the user taps the screen I run a method that replaces the current layer containing the movie with the game main menu. It works fine the first time, but when I try to play the video the second time from the main menu I get an EXC_BAD_ACCESS error on the line
int retVal = UIApplicationMain(argc, argv, nil, #"AppController");
in the main.m.
Please find the relevant code below.
-(void)playVideo {
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"movie" ofType:#"mp4"]];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];
moviePlayer.repeatMode = MPMovieRepeatModeOne;
// Register to receive a notification when the movie has finished playing.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
if ([moviePlayer respondsToSelector:#selector(setFullscreen:animated:)]) {
// Use the new 3.2 style API
moviePlayer.controlStyle = MPMovieControlStyleNone;
moviePlayer.shouldAutoplay = YES;
// This does blows up in cocos2d, so we'll resize manually
[moviePlayer setFullscreen:YES animated:YES];
CGSize winSize = [[CCDirector sharedDirector] winSize];
moviePlayer.view.frame = CGRectMake(0, 0, winSize.width, winSize.height); //width and height are swapped after rotation
[[[CCDirector sharedDirector] view] addSubview:moviePlayer.view ];
[moviePlayer play];
UITapGestureRecognizer * tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
tapGestureRecognizer.delegate = (id)self;
tapGestureRecognizer.numberOfTapsRequired = 1;
[[[CCDirector sharedDirector] view] addGestureRecognizer:tapGestureRecognizer];
[tapGestureRecognizer release];
} else {
// Use the old 2.0 style API
moviePlayer.controlStyle = MPMovieControlStyleNone;
[moviePlayer play];
}
}
- (void)handleTap:(UITapGestureRecognizer *)gesture {
[moviePlayer stop];
[[MenuManager sharedMenuManager] runMenu:kMMenuLayer];
}
// this enables you to handle multiple recognizers on single view
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
-(void)moviePlayBackDidFinish:(NSNotification*)notification {
moviePlayer = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
// If the moviePlayer.view was added to the openGL view, it needs to be removed
if ([moviePlayer respondsToSelector:#selector(setFullscreen:animated:)]) {
[moviePlayer.view removeFromSuperview];
CCLOG(#"this block is okay");
}
[moviePlayer release];
}
Please help.
The reason why you're getting the message is sent to a deallocated instance is because you've not removed the tapGestureRecognizer from the view. I believe your MenuManager singleton replaces the current layer with another, but since the tapGestureRecognizer is still part of the view it will try to access the handleTap, which by this time is deallocated. Add the following line before singleton call in handleTap.
[[[CCDirector sharedDirector] view] removeGestureRecognizer:tapGestureRecognizer];
I have 10 UIImageViews in the same ViewController, and each one of these images need to be controlled with a Gesture Recognizer; this is my simple code:
- (void)viewDidLoad {
UIImageView *image1 = // image init
UIImageView *image2 = // image init
...
UIRotationGestureRecognizer *rotationGesture1 = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotatePiece:)];
UIRotationGestureRecognizer *rotationGesture2 = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotatePiece:)];
...
...
UIRotationGestureRecognizer *rotationGesture10 = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotatePiece:)];
[image1 addGestureRecognizer:rotationGesture1];
[image2 addGestureRecognizer:rotationGesture2];
...
...
[image10 addGestureRecognizer:rotationGesture10];
}
- (void)rotatePiece:(UIRotationGestureRecognizer *)gestureRecognizer {
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
[gestureRecognizer view].transform = CGAffineTransformRotate([[gestureRecognizer view] transform], [gestureRecognizer rotation]);
[gestureRecognizer setRotation:0];
}
}
Ok, all right, each image rotates, but I need to write similar code also for UIPanGestureRecognizer and UIPinchGestureRecognizer, obv for each UIImageView: is this the correct way, or there is a simpler method to avoid "redundant" code like this? Thanks!
Here's a possible solution. Make a method like so:
- (void)addRotationGestureForImage:(UIImageView *)image
{
UIRotationGestureRecognizer *gesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotatePiece:)];
gesture.delegate = self;
[image addGestureRecognizer:gesture];
}
Then in your viewDidLoad method create an array of image views and loop through them calling this method like so:
NSArray *imageViewArray = [NSArray arrayWithObjects:image1,image2,image3,nil];
for(UIImageView *img in imageViewArray) {
[self addRotationGestureForImage:img];
}
I have a class called PhotoBoothController that I use to manipulate an image using gestures. It works fine when I run it on iPhone. However when I run it on iPad, I display the PhotoBoothController inside a UIPopoverController. The image appears fine, however I can't manipulate it as my gestures don't appear to be recognized. I'm not sure how to make the UIPopoverController take control of the gestures.
I present the popovercontroller and configure the view thus:
- (void)presentPhotoBoothForPhoto:(UIImage *)photo button:(UIButton *)button {
//Create a photoBooth and set its contents
PhotoBoothController *photoBoothController = [[PhotoBoothController alloc] init];
photoBoothController.photoImage.image = [button backgroundImageForState:UIControlStateNormal];
//set up all the elements programmatically.
photoBoothController.view.backgroundColor = [UIColor whiteColor];
//Add frame (static)
UIImage *frame = [[UIImage imageNamed:#"HumptyLine1Frame.png"] adjustForResolution];
UIImageView *frameView = [[UIImageView alloc] initWithImage:frame];
frameView.frame = CGRectMake(50, 50, frame.size.width, frame.size.height);
[photoBoothController.view addSubview:frameView];
//Configure image
UIImageView *photoView = [[UIImageView alloc] initWithImage:photo];
photoView.frame = CGRectMake(50, 50, photo.size.width, photo.size.height);
photoBoothController.photoImage = photoView;
//Add canvas
UIView *canvas = [[UIView alloc] initWithFrame:frameView.frame];
photoBoothController.canvas = canvas;
[canvas addSubview:photoView];
[canvas becomeFirstResponder];
[photoBoothController.view addSubview:canvas];
[photoBoothController.view bringSubviewToFront:frameView];
//resize the popover view shown in the current view to the view's size
photoBoothController.contentSizeForViewInPopover = CGSizeMake(frameView.frame.size.width+100, frameView.frame.size.height+400);
self.photoBooth = [[UIPopoverController alloc] initWithContentViewController:photoBoothController];
[self.photoBooth presentPopoverFromRect:button.frame
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
I thought [canvas becomeFirstResponder] might do it but it doesn't appear to make a difference.
Any advice much appreciate, thank you.
UPDATE: adding code as per comment
- (void)viewDidLoad {
[super viewDidLoad];
if (!_marque) {
_marque = [CAShapeLayer layer];
_marque.fillColor = [[UIColor clearColor] CGColor];
_marque.strokeColor = [[UIColor grayColor] CGColor];
_marque.lineWidth = 1.0f;
_marque.lineJoin = kCALineJoinRound;
_marque.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:10],[NSNumber numberWithInt:5], nil];
_marque.bounds = CGRectMake(photoImage.frame.origin.x, photoImage.frame.origin.y, 0, 0);
_marque.position = CGPointMake(photoImage.frame.origin.x + canvas.frame.origin.x, photoImage.frame.origin.y + canvas.frame.origin.y);
}
[[self.view layer] addSublayer:_marque];
UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(scale:)];
[pinchRecognizer setDelegate:self];
[self.view addGestureRecognizer:pinchRecognizer];
UIRotationGestureRecognizer *rotationRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotate:)];
[rotationRecognizer setDelegate:self];
[self.view addGestureRecognizer:rotationRecognizer];
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(move:)];
[panRecognizer setMinimumNumberOfTouches:1];
[panRecognizer setMaximumNumberOfTouches:1];
[panRecognizer setDelegate:self];
[canvas addGestureRecognizer:panRecognizer];
UITapGestureRecognizer *tapProfileImageRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped:)];
[tapProfileImageRecognizer setNumberOfTapsRequired:1];
[tapProfileImageRecognizer setDelegate:self];
[canvas addGestureRecognizer:tapProfileImageRecognizer];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return ![gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && ![gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]];
}
I am working on a similar application, and i can easily manipulate images on the canvas.
1) Check if the userInteractionEnabled property of the canvas is set to YES.
2) You can try adding the gestures to the ImageView's rather than the canvas. (I am guessing u want to zoom , rotate n swipe the images).
some guesses:
is this because viewDidLoad method have been called before cavas property been set? In this case, you could try to add recognizers after present popover in another method such as viewDidAppear.
I also agree that the key may be that UIPopoverController allows interaction to other views outside of the popover. So i suggest to move [canvas becomeFirstResponder]; to the end of the viewDidLoad method in PhotoBoothController and try self.view becomeFirstResponder here because you actually add recognizers to self.view.
I'm having a problem getting leaderboards to show. I think I have it right but I get this error in the log
Unbalanced calls to begin/end appearance transitions for <UIViewController: 0x105e39c0>.
here's my code to show and hide the view
- (void)showLeaderboard
{
GKLeaderboardViewController *leaderboardController = [[GKLeaderboardViewController alloc] init];
if (leaderboardController != NULL)
{ CCLOG( #" leaderboardController ok...");
tempVC = [[UIViewController alloc] init];
leaderboardController.leaderboardDelegate = self;
[[[CCDirector sharedDirector] openGLView] addSubview:tempVC.view];
leaderboardController.category = #"com.bluemesasoftware.housedefender.hightestscore";
leaderboardController.timeScope = GKLeaderboardTimeScopeAllTime;
leaderboardController.leaderboardDelegate = self;
[tempVC presentModalViewController: leaderboardController animated: YES];
}
}
- (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
{
[tempVC dismissModalViewControllerAnimated:YES];
[tempVC.view.superview removeFromSuperview];
[tempVC release];
}
[tempVC presentModalViewController: leaderboardController animated: NO];
[tempVC dismissModalViewControllerAnimated:YES];
This should work.
don't add the view to CCDirector's openglview
i assume you have this code in your AppDelegate...if so do this:
[window.rootViewControler.view addSubview:tempVC.view];
instead of
[[[CCDirector sharedDirector] openGLView] addSubview:tempVC.view];
also..move this code before presentModalViewController
I have a CCLayer which I need to add a camera to, on top of that I need a custom button to close the camera overlayed onto of the camera. I eventually need to display CCSprites on top of it all, but first need to be able to dismiss the camera.
But when I click on the button, I get SIGABRT or BAD EXE errors depending on whether I use [[[CCDirector sharedDirector] openGLView] sendSubviewToBack:uip.view]; or [uip.view removeFromSuperview];
-(void) displayCamera
{
uip = [[[UIImagePickerController alloc] init] autorelease];
uip.sourceType = UIImagePickerControllerSourceTypeCamera;
uip.showsCameraControls = NO;
uip.toolbarHidden = YES;
uip.navigationBarHidden = YES;
uip.wantsFullScreenLayout = YES;
[[[CCDirector sharedDirector] openGLView] addSubview:uip.view];
UIButton *arrowButton = [UIButton buttonWithType:UIButtonTypeCustom];
[arrowButton addTarget:self
action:#selector(arrowButtonClicked:)
forControlEvents:UIControlEventTouchUpInside];
UIImage *imgNormal = [UIImage imageNamed:#"btn_next_norm.png"];
[arrowButton setImage:imgNormal forState:UIControlStateNormal];
UIImage *imgPressed = [UIImage imageNamed:#"btn_next_pressed.png"];
[arrowButton setImage:imgPressed forState:UIControlStateHighlighted];
arrowButton.frame = CGRectMake(screenSize.width - 48.0, screenSize.height - 37.0, 48.0, 37.0);
[[[CCDirector sharedDirector] openGLView] addSubview:arrowButton];
}
-(void)arrowButtonClicked:(id)sender
{
// close / hide camera
[[[CCDirector sharedDirector] openGLView] sendSubviewToBack:uip.view];
// or maybe [uip.view removeFromSuperview];
// and then go to another scene
LoadingScene* scene = [LoadingScene sceneWithTargetScene:TargetSceneEndExperienceScene];
[[CCDirector sharedDirector] replaceScene:scene];
}
I believe the issue is this line:
uip = [[[UIImagePickerController alloc] init] autorelease];
Using autorelease in this case doesn't work because the UIImagePickerController is not retained by it's view, so you need to make sure that you retain it yourself. Instead of autoreleasing it, I would hold onto the reference to it, and then after you remove it from the view, I would release it then. I've changed your code to show what I mean:
-(void) displayCamera
{
uip = [[UIImagePickerController alloc] init]; // Don't autorelease it here
uip.sourceType = UIImagePickerControllerSourceTypeCamera;
uip.showsCameraControls = NO;
uip.toolbarHidden = YES;
uip.navigationBarHidden = YES;
uip.wantsFullScreenLayout = YES;
[[[CCDirector sharedDirector] openGLView] addSubview:uip.view];
UIButton *arrowButton = [UIButton buttonWithType:UIButtonTypeCustom];
[arrowButton addTarget:self
action:#selector(arrowButtonClicked:)
forControlEvents:UIControlEventTouchUpInside];
UIImage *imgNormal = [UIImage imageNamed:#"btn_next_norm.png"];
[arrowButton setImage:imgNormal forState:UIControlStateNormal];
UIImage *imgPressed = [UIImage imageNamed:#"btn_next_pressed.png"];
[arrowButton setImage:imgPressed forState:UIControlStateHighlighted];
arrowButton.frame = CGRectMake(screenSize.width - 48.0, screenSize.height - 37.0, 48.0, 37.0);
[[[CCDirector sharedDirector] openGLView] addSubview:arrowButton];
}
-(void)arrowButtonClicked:(id)sender
{
// close / hide camera
[uip.view removeFromSuperview];
[uip release]; // Release here
uip = nil;
// and then go to another scene
LoadingScene* scene = [LoadingScene sceneWithTargetScene:TargetSceneEndExperienceScene];
[[CCDirector sharedDirector] replaceScene:scene];
}