UI比較基礎(chǔ)的都過了一遍,就找了一個開源的簡單項目運行了下然后看了一遍代碼,雖然小游戲很簡單,甚至都沒有用到Cocoa2d之類的,但還是很高興基本代碼都看懂了,通過查官方文檔也學(xué)習(xí)了一些新的用法。感覺通過小例子來學(xué)習(xí)是一個比較有意思的方式。
現(xiàn)在把自己注釋過的代碼貼上來,感覺非常適合看完教程后的第一個小游戲。
項目地址:https://github.com/rmd6502/monkey
monkeyViewController.h
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #d12f1b}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #703daa}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #bb2ca2}span.s1 {font-variant-ligatures: no-common-ligatures; color: #78492a}span.s2 {font-variant-ligatures: no-common-ligatures}span.s3 {font-variant-ligatures: no-common-ligatures; color: #bb2ca2}span.s4 {font-variant-ligatures: no-common-ligatures; color: #000000}span.s5 {font-variant-ligatures: no-common-ligatures; color: #008400}span.s6 {font: 11.0px 'Heiti SC Light'; font-variant-ligatures: no-common-ligatures; color: #008400}span.s7 {font-variant-ligatures: no-common-ligatures; color: #703daa}span.Apple-tab-span {white-space:pre}
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface monkeyViewController : UIViewController<AVAudioPlayerDelegate> { //音頻播放協(xié)議
NSUInteger hiddenLocation; //"藏猴子"的位置
NSTimer *clock; //計時用
NSUInteger elapsed_seconds;
AVAudioPlayer *avp; //兩種音頻
AVAudioPlayer *win;
}
@property (nonatomic, assign) IBOutlet UIButton *startButton; //IBOutlet可視化編程自動生成變量
@property (nonatomic, assign) IBOutlet UITextField *timeRemaining;
@property (nonatomic, assign) IBOutlet UILabel *where;
- (IBAction)startGame:(id)sender; //可視化編程自動生成事件函數(shù)
- (void)guess:(id)sender; //傳遞猜的位置 并判斷正誤
- (void)tick:(NSTimer *)timer; //計時
- (void)resetGame; //重新開始
@end
monkeyViewController.m
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #d12f1b}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px 'Heiti SC Light'; color: #008400}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #bb2ca2}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #008400}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #3d1d81}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #703daa}p.p9 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #31595d}p.p10 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #4f8187}span.s1 {font-variant-ligatures: no-common-ligatures}span.s2 {font-variant-ligatures: no-common-ligatures; color: #78492a}span.s3 {font: 11.0px Menlo; font-variant-ligatures: no-common-ligatures}span.s4 {font-variant-ligatures: no-common-ligatures; color: #bb2ca2}span.s5 {font-variant-ligatures: no-common-ligatures; color: #000000}span.s6 {font-variant-ligatures: no-common-ligatures; color: #3d1d81}span.s7 {font: 11.0px 'Heiti SC Light'; font-variant-ligatures: no-common-ligatures}span.s8 {font-variant-ligatures: no-common-ligatures; color: #703daa}span.s9 {font-variant-ligatures: no-common-ligatures; color: #008400}span.s10 {font: 11.0px 'Heiti SC Light'; font-variant-ligatures: no-common-ligatures; color: #008400}span.s11 {font-variant-ligatures: no-common-ligatures; color: #272ad8}span.s12 {font: 11.0px Menlo; font-variant-ligatures: no-common-ligatures; color: #000000}span.s13 {font-variant-ligatures: no-common-ligatures; color: #d12f1b}span.s14 {font-variant-ligatures: no-common-ligatures; color: #4f8187}span.s15 {font-variant-ligatures: no-common-ligatures; color: #31595d}span.Apple-tab-span {white-space:pre}
#import <QuartzCore/QuartzCore.h>
#import "monkeyViewController.h"
//quartz 是主要的描畫接口,支持基于路徑的描畫、抗鋸齒渲染、漸變填充模式、圖像、顏色、坐標(biāo)空間變換、以及PDF 文檔的創(chuàng)建、顯示、和分析。UIKit 為Quartz 的圖像和顏色操作提供了Objective-C 的封裝。Core Animation 為很多UIKit 的視圖屬性聲明的動畫效果提供底層支持,也可以用于實現(xiàn)定制的動畫。
@implementation monkeyViewController
@synthesize startButton;
@synthesize timeRemaining;
@synthesize where;
/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
*/
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
//CGColor主要用于CoreGaphics框架之
CGColorSpaceRef csp = CGColorSpaceCreateDeviceRGB();
CGColorRef col1 = [UIColor cyanColor].CGColor; //cyanColor RGB=011 青色
CGFloat comps[4] = {0};
//內(nèi)存拷貝函數(shù),memcpy函數(shù)的功能是從源src所指的內(nèi)存地址的起始位置開始拷貝n個字節(jié)到目標(biāo)dest所指的內(nèi)存地址的起始位置中。
memcpy(comps, CGColorGetComponents(col1), 4 * sizeof(CGFloat));
comps[0] = 0.75;
CGColorRef col2 = CGColorCreate(csp, comps);
comps[0] = 0;
for (int i=0; i < 3; ++i) comps[i] *= .7;
col1 = CGColorCreate(csp, comps); //在csp空間中通過CGColorCreate用RGB創(chuàng)建顏色
//CGColorRef col2 = [UIColor whiteColor].CGColor;
const CGColorRef cols[] = {col1, col2};
CFArrayRef collist = CFArrayCreate(nil, (const void **)cols, sizeof(cols)/sizeof(CGColorRef), NULL);
CGFloat locs[] = {.99,0.0}; //?
UIButton *b1 = (UIButton *)[self.view viewWithTag:1001];
CGContextRef ctx = CGBitmapContextCreate(nil, b1.bounds.size.width, b1.bounds.size.height, 8, 4 * b1.bounds.size.width, csp, kCGImageAlphaPremultipliedLast);
CGGradientRef grad = CGGradientCreateWithColors(csp, collist, locs);
CGContextDrawRadialGradient(ctx, grad, CGPointMake(b1.bounds.size.width/2,b1.bounds.size.height/2), 1, CGPointMake(b1.bounds.size.width/2,b1.bounds.size.height/2), b1.bounds.size.width/2, kCGGradientDrawsAfterEndLocation);
CGImageRef bg = CGBitmapContextCreateImage(ctx);
UIImage *im = [UIImage imageWithCGImage:bg];
//猜的格子設(shè)置為UIButton
//用guess事件函數(shù)判斷猜對沒有
//傳送過去的參數(shù)就是點擊的那個UIButton對象
for (int i=1001; i < 1010; ++i) {
UIButton *b = (UIButton *)[self.view viewWithTag:i];
[b addTarget:self action:@selector(guess:) forControlEvents:UIControlEventTouchUpInside];
[b setBackgroundImage:im forState:UIControlStateNormal];
}
//內(nèi)存釋放
CGImageRelease(bg);
CFRelease(collist);
CGColorRelease(col2);
CGColorRelease(col1);
CGGradientRelease(grad);
CGColorSpaceRelease(csp);
[self resetGame];
//載入音頻
NSError *error = nil;
NSURL *noiseURL = [[NSBundle mainBundle] //猜錯的音樂
URLForResource:@"buzzer"
withExtension:@"mp3"];
avp = [[AVAudioPlayer alloc]
initWithContentsOfURL:noiseURL error:&error];
if (error) {
NSLog(@"failed to load sound: %@", [error localizedDescription]);
return;
}
noiseURL = [[NSBundle mainBundle] //猜對的音樂
URLForResource:@"win"
withExtension:@"m4a"];
win = [[AVAudioPlayer alloc]
initWithContentsOfURL:noiseURL error:&error];
//設(shè)置音頻屬性
[avp setDelegate:self];
[avp setVolume:1.0];
[avp prepareToPlay];
[win setDelegate:self];
[win setVolume:1.0];
[win prepareToPlay];
[self becomeFirstResponder];//:第一響應(yīng)對象是窗口中,應(yīng)用程序認(rèn)為最適合處理事件的對象
}
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
NSLog(@"motion %@", event);
if (motion == UIEventSubtypeMotionShake) {
[self startGame:nil];
}
}
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event {
NSLog(@"motion began %@", event);
if (motion == UIEventSubtypeMotionShake) {
[self startGame:nil];
}
}
- (void) viewDidUnload {
[avp release];
[win release];
[super viewDidUnload];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self becomeFirstResponder];
}
//重新開始游戲
- (void)resetGame {
CABasicAnimation *trans = [CABasicAnimation animation];
trans.keyPath = @"transform.scale";
trans.repeatCount = HUGE_VALF;
trans.duration = 0.5;
trans.autoreverses = YES;
trans.removedOnCompletion = NO;
trans.fillMode = kCAFillModeForwards;
trans.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
trans.fromValue = [NSNumber numberWithFloat:0.9];
trans.toValue = [NSNumber numberWithFloat:1.1];
[self.startButton.titleLabel.layer addAnimation:trans forKey:@"pulse"];
for (int i=1001; i < 1010; ++i) [(UIButton *)[self.view viewWithTag:i] setEnabled:NO];
elapsed_seconds = 0;
}
//開始游戲
- (IBAction)startGame:(id)sender { //觸發(fā)事件函數(shù)
for (int i=1001; i < 1010; ++i) {
UIButton *b = (UIButton *)[self.view viewWithTag:i]; //創(chuàng)建9個Button
[b setImage:nil forState:UIControlStateNormal];
[b setTitle:@"?" forState:UIControlStateNormal]; //顯示問號
b.enabled = YES;
}
[self.startButton.titleLabel.layer removeAllAnimations];
NSUInteger isCorrect = 0;
SecRandomCopyBytes(kSecRandomDefault, sizeof(NSUInteger), (void *)&isCorrect); //產(chǎn)生隨機數(shù)
hiddenLocation = isCorrect % 9;
elapsed_seconds = 0;
[timeRemaining setText:@"00:00:00"];
if (clock) {
[clock invalidate];
}
clock = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(tick:) userInfo:nil repeats:YES];
}
- (BOOL)canBecomeFirstResponder { return YES; }
//猜猴子判斷是否猜中的事件函數(shù)
//由UIButton觸發(fā)
- (void)guess:(id)sender {
UIButton *guessed = (UIButton *)sender;
guessed.enabled = NO;
CATransition *trans = [[CATransition alloc] init]; //CATransition轉(zhuǎn)場動畫
trans.duration = 0.25;
//類型:
// NSString * const kCATransitionFade;//逐漸消失
// NSString * const kCATransitionMoveIn;//移入
// NSString * const kCATransitionPush;//平移(暫且這么稱呼吧)
// NSString * const kCATransitionReveal;//顯露
trans.type = kCATransitionFade;
[guessed.layer addAnimation:trans forKey:@"Fade"];
[trans release];
[CATransaction begin];//CATransaction 用來修改圖層樹
if (guessed.tag - 1001 == hiddenLocation) { //hiddenLocation 猜對的位置
[guessed setTitle:@"" forState:UIControlStateNormal]; //去掉?的title
[guessed setImage:[UIImage imageNamed:@"monkey_toy"] forState:UIControlStateNormal];
[clock invalidate]; //停止計時
clock = nil;
[self resetGame]; //重新開始
[win play];
} else { //猜錯的位置
[guessed setTitle:@"×" forState:UIControlStateNormal];
[avp stop];
[avp prepareToPlay];
[avp play];
}
[CATransaction commit];
}
//計時
- (void)tick:(NSTimer *)timer { //timeRemaining、elapsed_seconds都是自己定義的
++elapsed_seconds;
[timeRemaining setText:[NSString stringWithFormat:@"%02d:%02d:%02d",
elapsed_seconds / 3600, (elapsed_seconds % 3600) / 60, elapsed_seconds % 60]];
}
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)dealloc {
[super dealloc];
}
@end