UI比较基础的都过了一遍,就找了一个开源的简单项目运行了下然后看了一遍代码,虽然小游戏很简单,甚至都没有用到Cocoa2d之类的,但还是很高兴基本代码都看懂了,通过查官方文档也学习了一些新的用法。感觉通过小例子来学习是一个比较有意思的方式。
现在把自己注释过的代码贴上来,感觉非常适合看完教程后的第一个小游戏。
项目地址: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> { //音频播放协议
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; //可视化编程自动生成事件函数
- (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 是主要的描画接口,支持基于路径的描画、抗锯齿渲染、渐变填充模式、图像、颜色、坐标空间变换、以及PDF 文档的创建、显示、和分析。UIKit 为Quartz 的图像和颜色操作提供了Objective-C 的封装。Core Animation 为很多UIKit 的视图属性声明的动画效果提供底层支持,也可以用于实现定制的动画。
@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};
//内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。
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创建颜色
//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];
//猜的格子设置为UIButton
//用guess事件函数判断猜对没有
//传送过去的参数就是点击的那个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];
}
//内存释放
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];
//设置音频属性
[avp setDelegate:self];
[avp setVolume:1.0];
[avp prepareToPlay];
[win setDelegate:self];
[win setVolume:1.0];
[win prepareToPlay];
[self becomeFirstResponder];//:第一响应对象是窗口中,应用程序认为最适合处理事件的对象
}
- (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 { //触发事件函数
for (int i=1001; i < 1010; ++i) {
UIButton *b = (UIButton *)[self.view viewWithTag:i]; //创建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); //产生随机数
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; }
//猜猴子判断是否猜中的事件函数
//由UIButton触发
- (void)guess:(id)sender {
UIButton *guessed = (UIButton *)sender;
guessed.enabled = NO;
CATransition *trans = [[CATransition alloc] init]; //CATransition转场动画
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