project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m
branchhedgeroid
changeset 6344 cba81e10235c
parent 6328 d14adf1c7721
child 6415 af2047bb4f70
equal deleted inserted replaced
6341:ccc0a58e123d 6344:cba81e10235c
    18  * File created on 18/04/2011.
    18  * File created on 18/04/2011.
    19  */
    19  */
    20 
    20 
    21 
    21 
    22 #import "GameInterfaceBridge.h"
    22 #import "GameInterfaceBridge.h"
    23 #import "ServerSetup.h"
       
    24 #import "EngineProtocolNetwork.h"
    23 #import "EngineProtocolNetwork.h"
    25 #import "OverlayViewController.h"
    24 #import "OverlayViewController.h"
    26 #import "StatsPageViewController.h"
    25 #import "StatsPageViewController.h"
    27 #import "AudioManagerController.h"
    26 #import "AudioManagerController.h"
    28 #import "ObjcExports.h"
    27 #import "ObjcExports.h"
    29 
    28 
    30 @implementation GameInterfaceBridge
    29 @implementation GameInterfaceBridge
    31 @synthesize parentController, savePath, overlayController, engineProtocol, ipcPort, gameType;
    30 @synthesize blackView;
    32 
       
    33 -(id) initWithController:(id) viewController {
       
    34     if (self = [super init]) {
       
    35         self.ipcPort = [ServerSetup randomPort];
       
    36         self.gameType = gtNone;
       
    37         self.savePath = nil;
       
    38 
       
    39         self.parentController = (UIViewController *)viewController;
       
    40         self.engineProtocol = [[EngineProtocolNetwork alloc] initOnPort:self.ipcPort];
       
    41         self.engineProtocol.delegate = self;
       
    42 
       
    43         self.overlayController = [[OverlayViewController alloc] initWithNibName:@"OverlayViewController" bundle:nil];
       
    44     }
       
    45     return self;
       
    46 }
       
    47 
       
    48 -(void) dealloc {
       
    49     releaseAndNil(engineProtocol);
       
    50     releaseAndNil(savePath);
       
    51     releaseAndNil(overlayController);
       
    52     [super dealloc];
       
    53 }
       
    54 
    31 
    55 #pragma mark -
    32 #pragma mark -
    56 // overlay with controls, become visible later, with a transparency effect since the sdlwindow is not yet created
    33 #pragma mark Instance methods for engine interaction
    57 -(void) displayOverlayLater:(id) object {
    34 // prepares the controllers for hosting a game
    58     // in order to get rotation events we have to insert the view inside the first view of the second window
    35 -(void) earlyEngineLaunch:(NSString *)pathOrNil withOptions:(NSDictionary *)optionsOrNil {
    59     // when multihead we have to make sure that overlay is displayed in the touch-enabled window
    36     [self retain];
    60     UIView *injected = (IS_DUALHEAD() ? self.parentController.view : UIVIEW_HW_SDLVIEW);
    37     [AudioManagerController stopBackgroundMusic];
    61     [injected addSubview:self.overlayController.view];
    38     [EngineProtocolNetwork spawnThread:pathOrNil withOptions:optionsOrNil];
       
    39 
       
    40     // add a black view hiding the background
       
    41     CGRect theFrame = [[UIScreen mainScreen] bounds];
       
    42     UIWindow *thisWindow = [[HedgewarsAppDelegate sharedAppDelegate] uiwindow];
       
    43     self.blackView = [[UIView alloc] initWithFrame:theFrame];
       
    44     self.blackView.opaque = YES;
       
    45     self.blackView.backgroundColor = [UIColor blackColor];
       
    46     self.blackView.alpha = 0;
       
    47     [UIView beginAnimations:@"fade out" context:NULL];
       
    48     [UIView setAnimationDuration:1];
       
    49     self.blackView.alpha = 1;
       
    50     [UIView commitAnimations];
       
    51     [thisWindow addSubview:self.blackView];
       
    52     [self.blackView release];
       
    53 
       
    54     // keep track of uncompleted games
       
    55     NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
       
    56     [userDefaults setObject:pathOrNil forKey:@"savedGamePath"];
       
    57     [userDefaults synchronize];
       
    58 
       
    59     // let's launch the engine using this -perfomSelector so that the runloop can deal with queued messages first
       
    60     [self performSelector:@selector(engineLaunch:) withObject:pathOrNil afterDelay:0.1f];
       
    61 }
       
    62 
       
    63 // cleans up everything
       
    64 -(void) lateEngineLaunch {
       
    65     // remove completed games notification
       
    66     NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
       
    67     [userDefaults setObject:@"" forKey:@"savedGamePath"];
       
    68     [userDefaults synchronize];
       
    69 
       
    70     // remove the cover view with a transition
       
    71     self.blackView.alpha = 1;
       
    72     [UIView beginAnimations:@"fade in" context:NULL];
       
    73     [UIView setAnimationDuration:1];
       
    74     self.blackView.alpha = 0;
       
    75     [UIView commitAnimations];
       
    76     [self.blackView performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:1];
       
    77 
       
    78     // the overlay is not needed any more and can be removed
       
    79     [[OverlayViewController mainOverlay] removeOverlay];
       
    80 
       
    81     // restart music and we're done
       
    82     [AudioManagerController playBackgroundMusic];
       
    83     [self release];
    62 }
    84 }
    63 
    85 
    64 // main routine for calling the actual game engine
    86 // main routine for calling the actual game engine
    65 -(void) engineLaunch {
    87 -(void) engineLaunch:(NSString *)pathOrNil {
    66     const char *gameArgs[11];
    88     const char *gameArgs[11];
    67     CGFloat width, height;
    89     CGFloat width, height;
       
    90     NSInteger enginePort = [EngineProtocolNetwork activeEnginePort];
    68     CGFloat screenScale = [[UIScreen mainScreen] safeScale];
    91     CGFloat screenScale = [[UIScreen mainScreen] safeScale];
    69     NSString *ipcString = [[NSString alloc] initWithFormat:@"%d", self.ipcPort];
    92     NSString *ipcString = [[NSString alloc] initWithFormat:@"%d",enginePort];
    70     NSString *localeString = [[NSString alloc] initWithFormat:@"%@.txt", [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]];
    93     NSString *localeString = [[NSString alloc] initWithFormat:@"%@.txt",[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]];
    71     NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
    94     NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
    72 
    95 
    73     if (IS_DUALHEAD()) {
    96     if (IS_DUALHEAD()) {
    74         CGRect screenBounds = [[[UIScreen screens] objectAtIndex:1] bounds];
    97         CGRect screenBounds = [[[UIScreen screens] objectAtIndex:1] bounds];
    75         width = screenBounds.size.width;
    98         width = screenBounds.size.width;
    80         height = screenBounds.size.width;
   103         height = screenBounds.size.width;
    81     }
   104     }
    82 
   105 
    83     NSString *horizontalSize = [[NSString alloc] initWithFormat:@"%d", (int)(width * screenScale)];
   106     NSString *horizontalSize = [[NSString alloc] initWithFormat:@"%d", (int)(width * screenScale)];
    84     NSString *verticalSize = [[NSString alloc] initWithFormat:@"%d", (int)(height * screenScale)];
   107     NSString *verticalSize = [[NSString alloc] initWithFormat:@"%d", (int)(height * screenScale)];
       
   108     NSString *resourcePath = [[NSString alloc] initWithFormat:@"%@/Data", [[NSBundle mainBundle] resourcePath]];
    85 
   109 
    86     NSString *modelId = [HWUtils modelType];
   110     NSString *modelId = [HWUtils modelType];
    87     NSInteger tmpQuality;
   111     NSInteger tmpQuality;
    88     if ([modelId hasPrefix:@"iPhone1"] || [modelId hasPrefix:@"iPod1,1"] || [modelId hasPrefix:@"iPod2,1"])     // = iPhone and iPhone 3G or iPod Touch or iPod Touch 2G
   112     if ([modelId hasPrefix:@"iPhone1"] || [modelId hasPrefix:@"iPod1,1"] || [modelId hasPrefix:@"iPod2,1"])     // = iPhone and iPhone 3G or iPod Touch or iPod Touch 2G
    89         tmpQuality = 0x00000001 | 0x00000002 | 0x00000008 | 0x00000040;                 // rqLowRes | rqBlurryLand | rqSimpleRope | rqKillFlakes
   113         tmpQuality = 0x00000001 | 0x00000002 | 0x00000008 | 0x00000040;                 // rqLowRes | rqBlurryLand | rqSimpleRope | rqKillFlakes
    92     else if ([modelId hasPrefix:@"iPad1"] || [modelId hasPrefix:@"iPod4"])                                      // = iPad 1G or iPod Touch 4G
   116     else if ([modelId hasPrefix:@"iPad1"] || [modelId hasPrefix:@"iPod4"])                                      // = iPad 1G or iPod Touch 4G
    93         tmpQuality = 0x00000002;                                                        // rqBlurryLand
   117         tmpQuality = 0x00000002;                                                        // rqBlurryLand
    94     else                                                                                                        // = everything else
   118     else                                                                                                        // = everything else
    95         tmpQuality = 0;                                                                 // full quality
   119         tmpQuality = 0;                                                                 // full quality
    96 
   120 
       
   121     // disable ammomenu animation
       
   122     tmpQuality = tmpQuality | 0x00000080;
    97     // disable tooltips on iPhone
   123     // disable tooltips on iPhone
    98     if (IS_IPAD() == NO)
   124     if (IS_IPAD() == NO)
    99         tmpQuality = tmpQuality | 0x00000400;
   125         tmpQuality = tmpQuality | 0x00000400;
   100 
   126 
   101     // prevents using an empty nickname
   127     // prevents using an empty nickname
   110     gameArgs[ 4] = "en.txt";//[localeString UTF8String];                                        //cLocaleFName
   136     gameArgs[ 4] = "en.txt";//[localeString UTF8String];                                        //cLocaleFName
   111     gameArgs[ 5] = [username UTF8String];                                                       //UserNick
   137     gameArgs[ 5] = [username UTF8String];                                                       //UserNick
   112     gameArgs[ 6] = [[[settings objectForKey:@"sound"] stringValue] UTF8String];                 //isSoundEnabled
   138     gameArgs[ 6] = [[[settings objectForKey:@"sound"] stringValue] UTF8String];                 //isSoundEnabled
   113     gameArgs[ 7] = [[[settings objectForKey:@"music"] stringValue] UTF8String];                 //isMusicEnabled
   139     gameArgs[ 7] = [[[settings objectForKey:@"music"] stringValue] UTF8String];                 //isMusicEnabled
   114     gameArgs[ 8] = [[[settings objectForKey:@"alternate"] stringValue] UTF8String];             //cAltDamage
   140     gameArgs[ 8] = [[[settings objectForKey:@"alternate"] stringValue] UTF8String];             //cAltDamage
   115     gameArgs[ 9] = [[[NSBundle mainBundle] resourcePath] UTF8String];                           //PathPrefix
   141     gameArgs[ 9] = [resourcePath UTF8String];                                                   //PathPrefix
   116     gameArgs[10] = (self.gameType == gtSave) ? [self.savePath UTF8String] : NULL;               //recordFileName
   142     gameArgs[10] = ([HWUtils gameType] == gtSave) ? [pathOrNil UTF8String] : NULL;              //recordFileName
   117 
   143 
   118     [verticalSize release];
   144     [verticalSize release];
   119     [horizontalSize release];
   145     [horizontalSize release];
       
   146     [resourcePath release];
   120     [localeString release];
   147     [localeString release];
   121     [ipcString release];
   148     [ipcString release];
   122 
   149 
   123     [ObjcExports initialize];
   150     [HWUtils setGameStatus:gsLoading];
   124 
   151 
   125     // this is the pascal fuction that starts the game, wrapped around isInGame
   152     // this is the pascal function that starts the game
   126     [HedgewarsAppDelegate sharedAppDelegate].isInGame = YES;
       
   127     Game(gameArgs);
   153     Game(gameArgs);
   128     [HedgewarsAppDelegate sharedAppDelegate].isInGame = NO;
   154     [self lateEngineLaunch];
   129 }
   155 }
   130 
   156 
   131 // prepares the controllers for hosting a game
   157 #pragma mark -
   132 -(void) prepareEngineLaunch {
   158 #pragma mark Class methods for setting up the engine from outsite
   133     // we add a black view hiding the background
   159 +(void) startGame:(TGameType) type atPath:(NSString *)path withOptions:(NSDictionary *)config {
   134     CGRect theFrame = CGRectMake(0, 0, self.parentController.view.frame.size.height, self.parentController.view.frame.size.width);
   160     [HWUtils setGameType:type];
   135     UIView *blackView = [[UIView alloc] initWithFrame:theFrame];
   161     GameInterfaceBridge *bridge = [[GameInterfaceBridge alloc] init];
   136     [self.parentController.view addSubview:blackView];
   162     [bridge earlyEngineLaunch:path withOptions:config];
   137     blackView.opaque = YES;
   163     [bridge release];
   138     blackView.backgroundColor = [UIColor blackColor];
   164 }
   139     blackView.alpha = 0;
   165 
   140     // when dual screen we apply a little transition
   166 +(void) startLocalGame:(NSDictionary *)withOptions {
   141     if (IS_DUALHEAD()) {
       
   142         [UIView beginAnimations:@"fade out" context:NULL];
       
   143         [UIView setAnimationDuration:1];
       
   144         blackView.alpha = 1;
       
   145         [UIView commitAnimations];
       
   146     } else
       
   147         blackView.alpha = 1;
       
   148 
       
   149     // prepare options for overlay and add it to the future sdl uiwindow
       
   150     [self performSelector:@selector(displayOverlayLater:) withObject:nil afterDelay:3];
       
   151 
       
   152     // keep track of uncompleted games
       
   153     NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
       
   154     [userDefaults setObject:self.savePath forKey:@"savedGamePath"];
       
   155     [userDefaults synchronize];
       
   156 
       
   157     [AudioManagerController pauseBackgroundMusic];
       
   158 
       
   159     // SYSTEMS ARE GO!!
       
   160     [self engineLaunch];
       
   161     
       
   162     // remove completed games notification
       
   163     [userDefaults setObject:@"" forKey:@"savedGamePath"];
       
   164     [userDefaults synchronize];
       
   165 
       
   166     // now we can remove the cover with a transition
       
   167     blackView.frame = theFrame;
       
   168     blackView.alpha = 1;
       
   169     [UIView beginAnimations:@"fade in" context:NULL];
       
   170     [UIView setAnimationDuration:1];
       
   171     blackView.alpha = 0;
       
   172     [UIView commitAnimations];
       
   173     [blackView performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:1];
       
   174     [blackView release];
       
   175 
       
   176     // the overlay is not needed any more and can be removed
       
   177     [self.overlayController removeOverlay];
       
   178 
       
   179     // warn our host that it's going to be visible again
       
   180     [self.parentController viewWillAppear:YES];
       
   181 
       
   182     [AudioManagerController playBackgroundMusic];
       
   183 }
       
   184 
       
   185 // set up variables for a local game
       
   186 -(void) startLocalGame:(NSDictionary *)withOptions {
       
   187     self.gameType = gtLocal;
       
   188 
       
   189     NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
   167     NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
   190     [outputFormatter setDateFormat:@"yyyy-MM-dd '@' HH.mm"];
   168     [outputFormatter setDateFormat:@"yyyy-MM-dd '@' HH.mm"];
   191     NSString *path = [[NSString alloc] initWithFormat:@"%@%@.hws",SAVES_DIRECTORY(),[outputFormatter stringFromDate:[NSDate date]]];
   169     NSString *savePath = [[NSString alloc] initWithFormat:@"%@%@.hws",SAVES_DIRECTORY(),[outputFormatter stringFromDate:[NSDate date]]];
   192     [outputFormatter release];
   170     [outputFormatter release];
   193     self.savePath = path;
   171 
   194     [path release];
   172     // in the rare case in which a savefile with the same name exists the older one must be removed (otherwise it gets corrupted)
   195 
   173     if ([[NSFileManager defaultManager] fileExistsAtPath:savePath])
   196     // in the rare case in which a savefile with the same name exists the older one must be removed (or it gets corrupted)
   174         [[NSFileManager defaultManager] removeItemAtPath:savePath error:nil];
   197     if ([[NSFileManager defaultManager] fileExistsAtPath:self.savePath])
   175 
   198         [[NSFileManager defaultManager] removeItemAtPath:self.savePath error:nil];
   176     [self startGame:gtLocal atPath:savePath withOptions:withOptions];
   199 
   177     [savePath release];
   200     [self.engineProtocol spawnThread:self.savePath withOptions:withOptions];
   178 }
   201     [self prepareEngineLaunch];
   179 
   202 }
   180 +(void) startSaveGame:(NSString *)atPath {
   203 
   181     [self startGame:gtSave atPath:atPath withOptions:nil];
   204 // set up variables for a save game
   182 }
   205 -(void) startSaveGame:(NSString *)atPath {
   183 
   206     self.gameType = gtSave;
   184 +(void) startMissionGame:(NSString *)withScript {
   207     self.savePath = atPath;
       
   208 
       
   209     [self.engineProtocol spawnThread:self.savePath];
       
   210     [self prepareEngineLaunch];
       
   211 }
       
   212 
       
   213 -(void) startMissionGame:(NSString *)withScript {
       
   214     self.gameType = gtMission;
       
   215     self.savePath = nil;
       
   216 
       
   217     NSString *missionPath = [[NSString alloc] initWithFormat:@"escript Missions/Training/%@.lua",withScript];
   185     NSString *missionPath = [[NSString alloc] initWithFormat:@"escript Missions/Training/%@.lua",withScript];
   218     NSDictionary *config = [NSDictionary dictionaryWithObject:missionPath forKey:@"mission_command"];
   186     NSDictionary *missionLine = [[NSDictionary alloc] initWithObjectsAndKeys:missionPath,@"mission_command",nil];
   219     [missionPath release];
   187     [missionPath release];
   220     [self.engineProtocol spawnThread:nil withOptions:config];
   188 
   221     [self prepareEngineLaunch];
   189     [self startGame:gtMission atPath:nil withOptions:missionLine];
   222 }
   190     [missionLine release];
   223 
   191 }
       
   192 
       
   193 /*
   224 -(void) gameHasEndedWithStats:(NSArray *)stats {
   194 -(void) gameHasEndedWithStats:(NSArray *)stats {
   225     // wrap this around a retain/realse to prevent being deallocated too soon
   195     // wrap this around a retain/realse to prevent being deallocated too soon
   226     [self retain];
   196     [self retain];
   227     // display stats page if there is something to display
   197     // display stats page if there is something to display
   228     if (stats != nil) {
   198     if (stats != nil) {
   235         [self.parentController presentModalViewController:statsPage animated:YES];
   205         [self.parentController presentModalViewController:statsPage animated:YES];
   236         [statsPage release];
   206         [statsPage release];
   237     }
   207     }
   238 
   208 
   239     // can remove the savefile if the replay has ended
   209     // can remove the savefile if the replay has ended
   240     if (self.gameType == gtSave)
   210     if ([HWUtils gameType] == gtSave)
   241         [[NSFileManager defaultManager] removeItemAtPath:self.savePath error:nil];
   211         [[NSFileManager defaultManager] removeItemAtPath:self.savePath error:nil];
   242     [self release];
   212     [self release];
   243 }
   213 }
       
   214 */
   244 
   215 
   245 @end
   216 @end