500 likes | 641 Views
iPhone 系统 应用与开发. -- 制作 iPhone 游戏场景. 李云玮. 回顾. -- 游戏中添加了哪些控件? -- 控件响应了哪些事件?. 教学分析. 上节课我们对游戏菜单页的界面进行了设计并响应事件,这节课我们要对游戏的场景创建主类。 学生分小组讨论并回答. 新任务介绍. 创建游戏主类 添加游戏角色 实现各个页面切换. 任务目标. 任务效果. 知识准备. 复习学过的知识 以小组形式收集信息学习讨论. 任务实施. -- 制作 iPhone 游戏场景. 单元一 创建游戏主类. 创建游戏主类. 布置游戏页界面.
E N D
iPhone系统 应用与开发 -- 制作iPhone游戏场景 李云玮
回顾 --游戏中添加了哪些控件? --控件响应了哪些事件?
教学分析 上节课我们对游戏菜单页的界面进行了设计并响应事件,这节课我们要对游戏的场景创建主类。 学生分小组讨论并回答
新任务介绍 创建游戏主类 添加游戏角色 实现各个页面切换
知识准备 复习学过的知识 以小组形式收集信息学习讨论
任务实施 -- 制作iPhone游戏场景
单元一 创建游戏主类
布置游戏页界面 这是游戏运行过程中的界面,我们来分析一下有哪些控件:在GameViewController自带的view上添加图像视图UIImageView,在左上角添加按钮UIButton用来返回主菜单,在左下角和右下角各添加标签UILabel用来显示剩余命数和关卡数。其他的角色我们已定义好HeroView类、RectView类、CoalView类和EnemyView类,只需在初始化函数init中实例化对象即可。点击按钮返回主菜单,我们声明方法backToMenu。
导入图片 下面把游戏页中需要的两张图导入到Resources——Images——UI中。 GameViewController自带的view上我们使用的背景图像是“GameBack”,返回主菜单的按钮图片使用的是“BtnGoBack”。 右击Resources-Images-UI,选择Add-Existing Files,加入这两张图片。
声明变量和方法 @interface GameViewController : UIViewController { //本页所使用的控件 //背景 UIImageView* imgvBack; //返回的按钮 UIButton* btnBack; //显示剩余命数的文字框 UILabel* lblGameLife; //显示关卡数的文字框 UILabel* lblGameLevel; } //返回主菜单 - (void)backToMenu; @end
初始化控件 在自身的初始化函数init中,初始化各个控件 制作UIImageView视图对象 imgvBack=[[UIImageView alloc] initWithImage:getPNGImage(@"GameBack")]; imgvBack.center=CGPointMake(160, 240); [self.view addSubview:imgvBack]; [imgvBack release];
初始化控件 在自身的初始化函数init中,初始化各个控件 用以显示所剩命数的UILabel对象 lblGameLife=[[UILabel alloc] init]; lblGameLife.frame=CGRectMake(0, 0, 100, 20); lblGameLife.center=CGPointMake(lblGameLife.frame.size.width/2,480- lblGameLife.frame.size.height/2); [lblGameLife setBackgroundColor:[UIColor colorWithWhite:1 alpha:0.6]]; lblGameLife.textColor=[UIColor redColor]; lblGameLife.font=[UIFont boldSystemFontOfSize:14]; [lblGameLife setTextAlignment:UITextAlignmentLeft]; [self.view addSubview:lblGameLife]; [lblGameLife release];
初始化控件 在自身的初始化函数init中,初始化各个控件 用以显示关卡数的UILabel对象 lblGameLevel=[[UILabel alloc] init]; lblGameLevel.frame=CGRectMake(0, 0, 220, 20); lblGameLevel.center=CGPointMake(320-lblGameLevel.frame.size.width/2,480-lblGameLevel.frame.size.height/2); [lblGameLevel setBackgroundColor:[UIColor colorWithWhite:1 alpha:0.6]]; lblGameLevel.textColor=[UIColor redColor]; lblGameLevel.font=[UIFont boldSystemFontOfSize:14]; [lblGameLevel setTextAlignment:UITextAlignmentRight]; [self.view addSubview:lblGameLevel]; [lblGameLevel release];
初始化控件 在自身的初始化函数init中,初始化各个控件 返回游戏菜单的按钮 btnBack=[[UIButton alloc] initWithFrame:CGRectMake(0,0,30,30)]; btnBack.center=CGPointMake(btnBack.frame.size.width/2,btnBack.frame.size.height/2); [btnBack setImage:getPNGImage(@"BtnGoBack") forState:UIControlStateNormal]; [btnBack addTarget:self action:@selector(CrtlSetting:) forControlEvents:UIControlEventTouchUpInside]; btnBack.tag=0; [self.view addSubview:btnBack]; [btnBack release];
回收内存 //本类释放时运行的函数 - (void)dealloc { NSLog(@"GameViewController dealloc"); [imgvBack removeFromSuperview];//移除图像视图 imgvBack=nil; [btnBack removeFromSuperview];//移除返回按钮 btnBack=nil; [lblGameLife removeFromSuperview];//移除剩余命数文本框 lblGameLife=nil; [lblGameLevel removeFromSuperview];//移除关卡数文本框 lblGameLevel=nil; //调用父类的释放函数 [super dealloc]; }
返回按钮的事件响应 //点击按钮的相应函数 - (void) CrtlSetting: (UIButton*) myBtn { switch (myBtn.tag) { case 0: //返回主菜单 [self backToMenu]; break; default: break; } } //返回主菜单 - (void)backToMenu { [self.navigationController popViewControllerAnimated:YES]; } @end
事件分析 在我们刚才设置的两个UILabel上要分别显示剩余命数和当前关卡数,在这里定义两个变量sumLifeLeft、cruLevel分别存储当前的剩余命数和当前关卡数,游戏总命数是一个固定值,我们在“CONSTANTS.h”中定义宏#define GameTotalLife 2,游戏总的关卡数随时可以增加,因此也定义为一个变量maxLevelID。游戏所有关卡的数据存放在数组中,我们可以通过方法getMaxLevelID获取数组的元素个数即为总的关卡数。
宏定义 “CONSTANTS.h”中 #define GameTotalLife 2
声明变量 //GameViewController类,继承自UIViewController @interface GameViewController : UIViewController { //剩余命数 int sumLifeLeft; //当前关卡数 int curLevel; //最后一关的ID int maxLevelID; } @end
初始化变量 - (id)init { if (self = [super init]) { //游戏变量赋初值 //剩余命数 sumLifeLeft= GameTotalLife; //当前关卡数 curLevel=0; //最后一关的ID maxLevelID=[BasicFunctions getMaxLevelID]; //刷新文本框 lblGameLife.text=[NSString stringWithFormat:@”剩余命数:%i”,sumLifeLeft]; lblGameLevel.text=[NSString stringWithFormat:@”第%i关”,curLevel]; }
定义类BasicFunctions 在BasicSupprot文件下新建类BasicFunctions,该类继承自NSObject,该类中定义了以+开头的类函数,是程序中用到的辅助函数。我们在BasicFunctiongs.h中声明: @interface BasicFunctions : NSObject { } +(int)getMaxLevelID; @end
实现方法 我们在BasicFunctiongs.m中实现: +(int)getMaxLevelID{ //待完成 }
声明对象 首先声明对象:在GameViewController.h头文件中,声明游戏的四个角色对象:小球、终点、黑洞、砖块。
宏定义 在“CONSTANT.h”中定义如下: //屏幕中纵向有多少砖块 #define SumEnemyAndRectEveryLine SCREEN_WIDTH/WidthAndHeighOfRect //屏幕中横向有多少砖块 #define SumEnemyAndRectLines SCREEN_HEIGHT/WidthAndHeighOfRect //屏幕中共有的砖块数量 #define MaxSumEnemyAndRect SumEnemyAndRectEveryLine*SumEnemyAndRectLines
导入类 //导入游戏角色类和宏定义类 #import "HeroView.h" #import "EnemyView.h" #import "RectView.h" #import "GoalView.h" #import "CONSTANT.h"
声明游戏角色的对象 GameViewController.h头文件中 //游戏角色 //小球(主角) HeroView*vHero; //终点 GoalView*vGoal; //黑洞 EnemyView*vEnemy[MaxSumEnemyAndRect]; //砖块 RectView*vRect[MaxSumEnemyAndRect];
实例化游戏角色对象 在初始化函数中,实例化黑洞角色 for (int a=0; a<MaxSumEnemyAndRect; a++) { //根据图片初始化黑洞 vEnemy[a] = [[EnemyView alloc] initWithImage:getPNGImage(@"Enemy")]; //设置黑洞对象的代理为本类 vEnemy[a].delegate=self; //添加并显示黑洞对象 [self.view addSubview:vEnemy[a]]; //将黑洞对象的生命周期减一 [vEnemy[a] release]; }
实例化游戏角色对象 在初始化函数中,实例化砖块角色 for (int a=0; a<MaxSumEnemyAndRect; a++) { //实例化砖块对象,原理如实例化黑洞对象 vRect[a] = [[RectView alloc] initWithImage:getPNGImage(@"Rect")]; vRect[a].delegate=self; [self.view addSubview:vRect[a]]; [vRect[a] release]; }
实例化游戏角色对象 在初始化函数中,实例化小球角色 vHero = [[HeroView alloc] initWithImage:getPNGImage(@"Hero")]; vHero.delegate=self; [self.view addSubview:vHero]; [vHero release];
实例化游戏终点对象 游戏过程中的终点是由两张图片重复交替显示,我们这里采用的是Goal0和Goal1,将这两张图片存放在数组中,并且设置动画重复显示数组中的图片,所以在这里我们需要创建图片数组,设置动画所使用的数组、图片交替显示时间、动画重复次数,动画播放等。
实例化游戏终点对象 在“CONSTANT.h”中定义图片交替显示的时间: #define GoalAnimationDuration 1.0/2
实例化游戏终点对象 //创建保存图片的数组 NSArray *arrGoalImages = [NSArray arrayWithObjects: getPNGImage(@"Goal0"), getPNGImage(@"Goal1"), nil];
实例化游戏终点对象 //实例化游戏终点对象 vGoal = [[GoalView alloc] initWithImage:getPNGImage(@"Goal0")]; //设置游戏终点对象的动画所使用的图片数组 vGoal.animationImages = arrGoalImages; //设置游戏终点对象的动画的持续时间 vGoal.animationDuration = GoalAnimationDuration; // seconds //设置游戏终点对象的动画的重复次数 vGoal.animationRepeatCount = 0; // 0 = loops forever //游戏终点对象开始动画 [vGoal startAnimating]; //设置游戏终点对象的代理为本类 vGoal.delegate=self; //添加并显示游戏终点对象 [self.view addSubview:vGoal]; //将游戏终点对象的生命周期减一 [vGoal release];
UINavigationController 初始化UINavigationController: UINavigationController *nvcViewController=[[UINavigationController alloc] initWithRootViewController:myViewController]; 推入新的VIewController: [self.navigationController pushViewController:myNewViewController animated:YES]; 推出VIewController: [self.navigationController popViewControllerAnimated:YES];
UINavigationController 在游戏的主代理类中,我们已经添加了导航控制器: //实例化myNC导航器对象,并将myMenuViewController作为“根ViewController”。 myNC=[[UINavigationController alloc] initWithRootViewController:myMenuViewController]; //将导航器加载到窗口上 [myMenuViewController release]; [window addSubview:myNC.view];
实现切换页面 通过委托协议实现页面切换的回调函数。
定义协议 //游戏页面的协议,包含了changeViewWithID(更换页面的)函数 @protocol GameViewControllerDelegate - (void)changeViewWithID:(int)viewID; @end
定义委托对象 //GameViewController类,继承自UIViewController @interface GameViewController : UIViewController { //定义代理对象,可以理解位id<协议名称>是代理对象的固有写法 id<GameViewControllerDelegate> delegate;} //将代理对象设置为属性 @property(nonatomic,assign) id<GameViewControllerDelegate> delegate;
执行协议 在本类的代理类中,即BallHoleAppDelegate.m中实现切换页面的回调函数。 //根据传递的参数,更换页面 - (void)changeViewWithID:(int)viewID { switch (viewID) { case STATE_MAINMENU: break; case STATE_GAME: //具体参见代码 break; case STATE_SCORES: //具体参见代码 break; default: break; } }
定义高分榜页面中的协议 //高分榜页面的协议,包含了changeViewWithID(更换页面的)函数 @protocol ScoresViewControllerDelegate - (void)changeViewWithID:(int)viewID; @end
定义委托对象 //ScoresViewController类,继承自UIViewController @interface ScoresViewController : UIViewController { //定义代理对象,可以理解位id<协议名称>是代理对象的固有写法 id<ScoresViewControllerDelegate> delegate;} //将代理对象设置为属性 @property(nonatomic,assign) id<ScoresViewControllerDelegate> delegate;
拓展任务 独立制作若干个界面,并实现各个页面的切换