From ad72c0ddc3fea12475e1e14cb42f3a62702fcc58 Mon Sep 17 00:00:00 2001 From: "techdragon.nguyen@gmail.com" Date: Sun, 4 Sep 2011 08:31:36 +0000 Subject: [PATCH] adjusted controls for Touch interface on iOS. * Single Tap now implemented * Touch and Hold (2 secs) to pop up menu * added a pan gesture to simulate flicking up/down and left/right * removed dependency on binding keys to game for iOS devices. (perhaps extend this to all touch devices.) * flicking motion needs to be expanded to allow for smooth scrolling. Right now every flick is equivalent to going one slot up/down/left/right. --- JGE/src/iOS/EAGLView.m | 304 +++++++++++++++++++++--------- JGE/src/iOS/wagicAppDelegate.m | 17 +- projects/mtg/src/CardSelector.cpp | 2 +- projects/mtg/src/WGui.cpp | 4 +- projects/mtg/wagic-Info.plist | 10 +- 5 files changed, 239 insertions(+), 98 deletions(-) diff --git a/JGE/src/iOS/EAGLView.m b/JGE/src/iOS/EAGLView.m index 72c64f24f..54b6fbfcf 100755 --- a/JGE/src/iOS/EAGLView.m +++ b/JGE/src/iOS/EAGLView.m @@ -10,11 +10,16 @@ #include "JRenderer.h" #include "JGameLauncher.h" - uint64_t lastTickCount; JGE* g_engine = NULL; static JApp* g_app = NULL; static JGameLauncher* g_launcher = NULL; +CGFloat lastScale; +CGFloat lastRotation; + +CGFloat firstX; +CGFloat firstY; + void JGECreateDefaultBindings() { @@ -75,30 +80,6 @@ void DestroyGame(void) [super dealloc]; } --(id)initWithFrame:(CGRect)frame { - - NSLog(@"EAGL View - init With Frame: origin(%f %f) size(%f %f)", - frame.origin.x, frame.origin.y, frame.size.width, frame.size.height); - - if ((self = [super initWithFrame:frame])) { - - self = [self initialize]; - - } // if ((self = [super initWithFrame:frame])) - - return self; -} - -//The EAGL view is stored in the nib file. When it's unarchived it's sent -initWithCoder: -- (id)initWithCoder:(NSCoder*)coder -{ - if ((self = [super initWithCoder:coder])) - { - self = [self initialize]; - } - - return self; -} - (id)initialize { @@ -128,25 +109,8 @@ void DestroyGame(void) started = FALSE; animationFrameInterval = 1; displayLink = nil; - - UIGestureRecognizer *recognizer; - /* - Create a double tap recognizer to handle OK. - */ - recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleOK:)]; - [self addGestureRecognizer:recognizer]; - ((UITapGestureRecognizer*)recognizer).numberOfTapsRequired = 2; - [recognizer release]; - - /* - Create a 2 fingers right swipe gesture recognizer to handle next phase. - */ - recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleNextPhase:)]; - ((UISwipeGestureRecognizer*)recognizer).direction = UISwipeGestureRecognizerDirectionRight; - ((UISwipeGestureRecognizer*)recognizer).numberOfTouchesRequired = 2; - [self addGestureRecognizer:recognizer]; - [recognizer release]; + UIGestureRecognizer *recognizer; /* Create a 2 fingers left swipe gesture recognizer to handle interruption. @@ -156,30 +120,162 @@ void DestroyGame(void) ((UISwipeGestureRecognizer*)recognizer).numberOfTouchesRequired = 2; [self addGestureRecognizer:recognizer]; [recognizer release]; - + + /* + Create a touch and hold to handle opening up the menu + */ + UILongPressGestureRecognizer *menuKeyRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleMenuWithLongPress:)]; + menuKeyRecognizer.minimumPressDuration =2; + menuKeyRecognizer.numberOfTouchesRequired = 1; + menuKeyRecognizer.delaysTouchesBegan = YES; + [self addGestureRecognizer:menuKeyRecognizer]; + + /* - Create a 3 fingers up swipe gesture recognizer to handle menu. + Create a single tap recognizer to handle OK. */ - recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleMenu:)]; - ((UISwipeGestureRecognizer*)recognizer).direction = UISwipeGestureRecognizerDirectionUp; - ((UISwipeGestureRecognizer*)recognizer).numberOfTouchesRequired = 3; - [self addGestureRecognizer:recognizer]; - [recognizer release]; - - /* - Create a 2 fingers long press gesture recognizer to handle hand display. + UITapGestureRecognizer *singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleOK:)]; + singleTapRecognizer.numberOfTapsRequired = 1; + singleTapRecognizer.numberOfTouchesRequired = 1; + [singleTapRecognizer requireGestureRecognizerToFail: menuKeyRecognizer]; + [singleTapRecognizer setDelaysTouchesBegan: YES]; + + [self addGestureRecognizer: singleTapRecognizer]; + + + /* + Create a Pan recognizer */ - recognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleHand:)]; - ((UILongPressGestureRecognizer*)recognizer).minimumPressDuration = 1; - ((UILongPressGestureRecognizer*)recognizer).numberOfTouchesRequired = 2; - + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget: self action: @selector(handlePan:)]; + panRecognizer.minimumNumberOfTouches = 1; + panRecognizer.maximumNumberOfTouches = 1; + [recognizer requireGestureRecognizerToFail: singleTapRecognizer]; + [self addGestureRecognizer: panRecognizer]; + + /* + Create a 2 fingers right swipe gesture recognizer to handle opening and closing of hand + */ + recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleHand:)]; + ((UISwipeGestureRecognizer*)recognizer).direction = UISwipeGestureRecognizerDirectionRight; + ((UISwipeGestureRecognizer*)recognizer).numberOfTouchesRequired = 2; + [self addGestureRecognizer:recognizer]; [recognizer release]; - + + [panRecognizer release]; + [menuKeyRecognizer release]; + [singleTapRecognizer release]; + return self; } -- (void)handleHand:(UILongPressGestureRecognizer *)recognizer { + +-(id)initWithFrame:(CGRect)frame { + + NSLog(@"EAGL View - init With Frame: origin(%f %f) size(%f %f)", + frame.origin.x, frame.origin.y, frame.size.width, frame.size.height); + + if ((self = [super initWithFrame:frame])) { + + self = [self initialize]; + + } + + return self; +} + + +//The EAGL view is stored in the nib file. When it's unarchived it's sent -initWithCoder: +- (id)initWithCoder:(NSCoder*)coder +{ + if ((self = [super initWithCoder:coder])) + { + self = [self initialize]; + } + + return self; +} + + +- (void)handlePan: (UIPanGestureRecognizer *)recognizer { + + [[[(UITapGestureRecognizer*)recognizer view] layer] removeAllAnimations]; + + [self bringSubviewToFront:[(UIPanGestureRecognizer*)recognizer view]]; + CGPoint translatedPoint = [(UIPanGestureRecognizer*)recognizer translationInView: self]; + + if([(UIPanGestureRecognizer*)recognizer state] == UIGestureRecognizerStateBegan) { + + firstX = [[recognizer view] center].x; + firstY = [[recognizer view] center].y; + } + + translatedPoint = CGPointMake(firstX+translatedPoint.x, firstY+translatedPoint.y); + + // [[recognizer view] setCenter:translatedPoint]; + + if([(UIPanGestureRecognizer*)recognizer state] == UIGestureRecognizerStateEnded) { + + CGFloat xVelocity = [(UIPanGestureRecognizer*)recognizer velocityInView: self].x; + CGFloat yVelocity = [(UIPanGestureRecognizer*)recognizer velocityInView: self].y; + CGFloat finalX = translatedPoint.x + (.35 * xVelocity); + CGFloat finalY = translatedPoint.y + (.35 * yVelocity); + + if(UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation])) { + if(finalX < 0) + { + finalX = 0; + } + else if(finalX > 768) { + finalX = 768; + } + + if(finalY < 0) { + finalY = 0; + } + else if(finalY > 1024) { + finalY = 1024; + } + } + + else { + + if(finalX < 0) + { + finalX = 0; + } + else if(finalX > 1024) { + + finalX = 768; + } + + if(finalY < 0) { + finalY = 0; + } + else if(finalY > 768) { + finalY = 1024; + } + } + + int xVelocityAbs = abs(static_cast(xVelocity)); + int yVelocityAbs = abs(static_cast(yVelocity)); + + + if (yVelocityAbs > 300 && (xVelocityAbs < yVelocityAbs)) + { + bool flickUpwards = yVelocity < 0; + g_engine->HoldKey_NoRepeat(flickUpwards ? JGE_BTN_UP : JGE_BTN_DOWN); + } + else if (xVelocityAbs > 300 && (xVelocityAbs > yVelocityAbs)) + { + bool flickRight = xVelocity > 0; + g_engine->HoldKey_NoRepeat( flickRight ? JGE_BTN_RIGHT : JGE_BTN_LEFT); + } + } + +} + +- (void)handleHand:(UITapGestureRecognizer *)recognizer { g_engine->HoldKey_NoRepeat(JGE_BTN_NEXT); } @@ -187,8 +283,20 @@ void DestroyGame(void) g_engine->HoldKey_NoRepeat(JGE_BTN_MENU); } + +- (void)handleMenuWithLongPress:(UILongPressGestureRecognizer *)recognizer { + if (recognizer.state == UIGestureRecognizerStateEnded) { + NSLog(@"Long press Ended"); + g_engine->HoldKey_NoRepeat(JGE_BTN_MENU); + } + else { + NSLog(@"Long press detected."); + } +} + - (void)handleInterrupt:(UISwipeGestureRecognizer *)recognizer { g_engine->HoldKey_NoRepeat(JGE_BTN_SEC); + } - (void)handleNextPhase:(UISwipeGestureRecognizer *)recognizer { @@ -209,7 +317,7 @@ void DestroyGame(void) [self stopAnimation]; [renderer resizeFromLayer:(CAEAGLLayer*)self.layer]; [self startAnimation]; - + [self drawView:nil]; } @@ -229,7 +337,7 @@ void DestroyGame(void) if (frameInterval >= 1) { animationFrameInterval = frameInterval; - + if (animating) { [self stopAnimation]; @@ -249,7 +357,7 @@ void DestroyGame(void) displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(drawView:)]; [displayLink setFrameInterval:animationFrameInterval]; [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; - + animating = TRUE; } @@ -266,7 +374,7 @@ void DestroyGame(void) } JGECreateDefaultBindings(); - + if (!InitGame()) { //return 1; @@ -288,8 +396,8 @@ void DestroyGame(void) } } -// Handles the start of a touch -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event + +- (void) handleTouchEvent: (NSSet *) touches withEvent: (UIEvent *) event { UITouch* touch = [[event touchesForView:self] anyObject]; @@ -299,43 +407,51 @@ void DestroyGame(void) int actualWidth = (int) JRenderer::GetInstance()->GetActualWidth(); int actualHeight = (int) JRenderer::GetInstance()->GetActualHeight(); - if (currentLocation.y >= es2renderer.viewPort.top && - currentLocation.y <= es2renderer.viewPort.bottom && - currentLocation.x <= es2renderer.viewPort.right && - currentLocation.x >= es2renderer.viewPort.left) { - g_engine->LeftClicked( - ((currentLocation.x-es2renderer.viewPort.left)*SCREEN_WIDTH)/actualWidth, - ((currentLocation.y-es2renderer.viewPort.top)*SCREEN_HEIGHT)/actualHeight); - } else if(currentLocation.y es2renderer.viewPort.top && + currentLocation.y < es2renderer.viewPort.bottom && + currentLocation.x < es2renderer.viewPort.right && + currentLocation.x > es2renderer.viewPort.left) + { + int xOffset = ((currentLocation.x-es2renderer.viewPort.left)*SCREEN_WIDTH)/actualWidth; + int yOffset = ((currentLocation.y-es2renderer.viewPort.top)*SCREEN_HEIGHT)/actualHeight; + NSLog( @"clicked %d, %d: tapCount: %d", xOffset, yOffset, touch.tapCount); + + if (touch.tapCount == 1) + { + g_engine->LeftClicked(xOffset, yOffset); + } + + } + + else if(currentLocation.y < es2renderer.viewPort.top) { + NSLog(@"Menu Button"); g_engine->HoldKey_NoRepeat(JGE_BTN_MENU); - } else if(currentLocation.y>es2renderer.viewPort.bottom) { + } + + else if(currentLocation.y > es2renderer.viewPort.bottom) { + NSLog( @"Right Trigger"); g_engine->HoldKey_NoRepeat(JGE_BTN_NEXT); } + } +// Handles the start of a touch +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + [self handleTouchEvent: touches withEvent: event]; +} + + // Handles the continuation of a touch. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - UITouch* touch = [[event touchesForView:self] anyObject]; - - // Convert touch point from UIView referential to OpenGL one (upside-down flip) - currentLocation = [touch previousLocationInView:self]; - ES2Renderer* es2renderer = (ES2Renderer*)renderer; - - int actualWidth = (int) JRenderer::GetInstance()->GetActualWidth(); - int actualHeight = (int) JRenderer::GetInstance()->GetActualHeight(); - if (currentLocation.y >= es2renderer.viewPort.top && - currentLocation.y <= es2renderer.viewPort.bottom && - currentLocation.x <= es2renderer.viewPort.right && - currentLocation.x >= es2renderer.viewPort.left) { - g_engine->LeftClicked( - ((currentLocation.x-es2renderer.viewPort.left)*SCREEN_WIDTH)/actualWidth, - ((currentLocation.y-es2renderer.viewPort.top)*SCREEN_HEIGHT)/actualHeight); - } else if(currentLocation.yHoldKey_NoRepeat(JGE_BTN_MENU); - } else if(currentLocation.y>es2renderer.viewPort.bottom) { - g_engine->HoldKey_NoRepeat(JGE_BTN_NEXT); - } + [self handleTouchEvent: touches withEvent: event]; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + //[self handleTouchEvent:touches withEvent:event]; } // Handles the end of a touch event. diff --git a/JGE/src/iOS/wagicAppDelegate.m b/JGE/src/iOS/wagicAppDelegate.m index 5dc7eb4ce..982226a00 100755 --- a/JGE/src/iOS/wagicAppDelegate.m +++ b/JGE/src/iOS/wagicAppDelegate.m @@ -23,9 +23,24 @@ - (void)applicationDidBecomeActive:(UIApplication *)application { -// [glView startAnimation]; + EAGLView *eaglView = (EAGLView *)self.glViewController.view; + [eaglView startAnimation]; } + +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + EAGLView *eaglView = (EAGLView *)self.glViewController.view; + [eaglView startAnimation]; +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + EAGLView *eaglView = (EAGLView *)self.glViewController.view; + [eaglView stopAnimation]; +} + + - (void)applicationWillTerminate:(UIApplication *)application { EAGLView *eaglView = (EAGLView *)self.glViewController.view; diff --git a/projects/mtg/src/CardSelector.cpp b/projects/mtg/src/CardSelector.cpp index cf347a4b9..f41322f3e 100644 --- a/projects/mtg/src/CardSelector.cpp +++ b/projects/mtg/src/CardSelector.cpp @@ -189,7 +189,7 @@ bool CardSelector::CheckUserInput(JButton key) int x,y; if(JGE::GetInstance()->GetLeftClickCoordinates(x, y)) { - active = closest (cards, limitor, static_cast (x), static_cast (y)); + active = closest (cards, limitor, static_cast (x), static_cast (y)); } switch (key) diff --git a/projects/mtg/src/WGui.cpp b/projects/mtg/src/WGui.cpp index 85bb865c7..04a2e5bcd 100644 --- a/projects/mtg/src/WGui.cpp +++ b/projects/mtg/src/WGui.cpp @@ -2302,6 +2302,7 @@ WGuiBase::CONFIRM_TYPE WGuiKeyBinder::needsConfirm() } // Check whether any button has no key associated to it. +#if (!defined IOS) confirmingButton = JGE_BTN_NONE; for (signed int i = (sizeof(btnToCheck) / sizeof(btnToCheck[0])) - 1; i >= 0; --i) { @@ -2326,7 +2327,8 @@ WGuiBase::CONFIRM_TYPE WGuiKeyBinder::needsConfirm() confirmMenu->Add(2, _("This is okay, validate and save").c_str()); return CONFIRM_NEED; } - +#endif // IOS + return CONFIRM_OK; } diff --git a/projects/mtg/wagic-Info.plist b/projects/mtg/wagic-Info.plist index 0ef8b778c..6de833935 100755 --- a/projects/mtg/wagic-Info.plist +++ b/projects/mtg/wagic-Info.plist @@ -6,6 +6,8 @@ English CFBundleDisplayName ${PRODUCT_NAME} + CFBundleDocumentTypes + CFBundleExecutable ${EXECUTABLE_NAME} CFBundleGetInfoString @@ -13,7 +15,7 @@ CFBundleIconFile wagic-64x64.png CFBundleIdentifier - somethingsmart.com.${PRODUCT_NAME:rfc1034identifier} + net.wagic.game.app CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -24,6 +26,8 @@ CFBundleSignature ???? + CFBundleURLTypes + CFBundleVersion 1.0 LSRequiresIPhoneOS @@ -46,5 +50,9 @@ UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown + UTExportedTypeDeclarations + + UTImportedTypeDeclarations +