作者:孫東風 2009-11-14(請尊重作者勞動成果,轉載務必註明出處)
筆者在前面的系列文章中依次講解了iPhone多線程、iPhone數據持久化、iPhone網絡通訊BSD Socket等內容,接下來筆者會講解如何從頭搭建一個自己的遊戲引擎。
根據iPhone官方的統計,App Store中游戲類應用是最多的,大概是其它應用總和的1 .5倍,在排行前20的應用中,遊戲類應用超過14個。
iPhone窗口系統如下:
ü UIKit.framwork
² UIScreen
² UIWindow
² UIView
ü QuartzCore.framework
² CALayer
² CAEAGLLayer
本文主要講解UIKit.framework圖形框架,其中UIScreen提供了屏幕的基本系統,定義如下:
//
// UIScreen.h
// UIKit
//
// Copyright 2007-2009 Apple Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <UIKit/UIKitDefines.h>
UIKIT_EXTERN_CLASS @interface UIScreen : NSObject {
@private
CGRect _bounds;
}
+ (UIScreen *)mainScreen;
@property(nonatomic,readonly) CGRect bounds; // Bounds of entire screen in points
@property(nonatomic,readonly) CGRect applicationFrame; // Frame of application screen area in points (i.e. entire screen minus status bar if visible)
@end
這個類提供了屏幕的bounds(即可繪製區域drawable),屏幕的尺寸和位置,而接口mainScreen()獲取當前窗口的主屏幕。
UIWindow是UIView的子類,UIView是所有屏幕視圖的SuperClass,比如UIButton、UILabel、UIImageView等,UIView類中定義如下:
…
@property(nonatomic,readonly) UIView *superview;
@property(nonatomic,readonly,copy) NSArray *subviews;
@property(nonatomic,readonly) UIWindow *window;
- (void)removeFromSuperview;
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;
- (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2;
- (void)addSubview:(UIView *)view;
- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview;
- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview;
- (void)bringSubviewToFront:(UIView *)view;
- (void)sendSubviewToBack:(UIView *)view;
- (void)didAddSubview:(UIView *)subview;
- (void)willRemoveSubview:(UIView *)subview;
- (void)willMoveToSuperview:(UIView *)newSuperview;
- (void)didMoveToSuperview;
- (void)willMoveToWindow:(UIWindow *)newWindow;
- (void)didMoveToWindow;
…
可見,利用UIView類可以獲取當前視圖的“父視圖”、“子視圖數組”,還可以添加一個“子視圖”到當前的視圖、刪除“子視圖”、插入“子視圖”等操作。
它們的繼承關係如下圖:
UIResponder – UIView – 自定義視圖
|
UIButton、UILabel、UIImageView等
本文的主要任務是創建一個全屏顯示的自定義窗口。
新建一個“Window-based Application”項目,輸入項目名字“CrazyWindGameEngine”,然後Build&Go可以看到一個淺灰色背景的屏幕,這個默認的屏幕存在幾個問題:
首先需要隱藏“Status Bar”,這個通過在CrazyWindGameEngine-info.plist中添加“Status bar is initially hidden”並勾選,Phone屏幕的構造如下圖:
其次,這個模板程序是通過從CrazyWindGameEngine-info.plist文件的“Main nib file base name”屬性中讀取MainWindow.xib而生成窗口的,所以需要把模板相應的模塊去掉並加入自己生成的窗口,這需要以下幾個步驟:
Ø 刪除CrazyWindGameEngine-info.plist中的Main nib file base name屬性和相應的值。
Ø 到Resources目錄下刪除MainWindow.xib文件。
Ø 到main.m中修改代碼如下:
Ø int retVal = UIApplicationMain(argc, argv, nil, @"CrazyWindGameEngineAppDelegate");
Ø CrazyWindGameEngineAppDelegate.h中變量window的IBOutlet關鍵字去掉(也可以保留,不影響)。
經過以上的步驟,模板生成的窗口就被刪除掉了,接下來需要添家自己定義的窗口,代碼如下:
#import "CrazyWindGameEngineAppDelegate.h"
@implementation CrazyWindGameEngineAppDelegate
@synthesize window;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// setup the main window
CGRect windowRect = [[UIScreen mainScreen] bounds];
window = [[UIWindow alloc] initWithFrame:windowRect];
[window setBackgroundColor:[UIColor redColor]];
…
[window makeKeyAndVisible];
}
上面的代碼會產生一個“紅色背景的窗口”,在前面講過UIView類提供了“添加視圖”、“插入視圖”、“刪除視圖”等操作,而UIButton、UILabel、UIImageView等類繼承自UIView,所以下面的代碼中嘗試添加一個UIButton、一個UILabel、一個UIImageView到新產生的窗口中,如下:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// setup the main window
CGRect windowRect = [[UIScreen mainScreen] bounds];
window = [[UIWindow alloc] initWithFrame:windowRect];
[window setBackgroundColor:[UIColor redColor]];
// Set up the background image
UIImageView *mBgView = [[[UIImageView alloc] initWithImage: [UIImage applicationImageNamed:@"screenshot.png"]] autorelease];
// 旋轉UIImageView
float rotateAngle = M_PI/2;
CGAffineTransform transform = CGAffineTransformMakeRotation(rotateAngle);
mBgView.transform = transform;
[window setContentView: mBgView];
[mBgView release];
// add a UILabel
CGRect labelRect = [[UIScreen mainScreen] applicationFrame];
UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(labelRect.origin.x+30, labelRect.origin.y+150, labelRect.size.width-60, labelRect.size.height-300)];
label.text = @"CrazyWindGameEngine";
label.backgroundColor = [UIColor blackColor];
label.shadowColor = [UIColor whiteColor];
label.textAlignment = UITextAlignmentCenter;
label.font = [UIFont systemFontOfSize:22.0];
label.textColor = [UIColor grayColor];
[window addSubview:label];
[label release];
// add a UIButton
UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setFrame:CGRectMake(0.0f, 0.0f, 80.0f, 30.0f)];
[button setCenter:CGPointMake(160.0f,208.0f)];
[button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[button setTitle:@"Start" forState:UIControlStateNormal];
[button addTarget:self action:@selector(playSound:) forControlEvents:UIControlEventTouchUpInside];
[button setBackgroundColor:[UIColor redColor]];
[button setAlpha:20];
[window addSubview:button];
[button release];
// Override point for customization after application launch
[window makeKeyAndVisible];
}
- (void)dealloc {
[window release];
[super dealloc];
}
@end
其中我們利用了UIImageView類的旋轉方法transform屬性對圖片進行旋轉,運行效果如下圖:
在下面的章節中,筆者會對上面的引擎進行進一步優化:)