经典的贪吃蛇游戏,通过轻扫手势处理器让用户改变蛇的移动方向!!!
工具/原料
苹果电脑
Xcode编译器
方法/步骤
1、创建一个SingleViewApplication,如下图,该应用将会包含一个应用程序委托类和一个视图控制器类,但程序还需要一个自定义UIView控件类,该控件类负责绘制贪吃蛇的游戏界面。
2、添加AudioToolbox.framework框架用于音频的播放,添加步骤如下图:
3、下面是自定义的FKSna氯短赤亻keView类的接口代码:FKSnakeView.h文件内容:#import<UIKit砖镑苣逢/UIKit.h>//记录地图上的宽和高有多少个格子#defineWIDTH15#defineHEIGHT22//定义每个格子的大小#defineCELL_SIZE20typedefenum{ kDown=0, kLeft, kRight, kUp}Orient;@interfaceFKSnakeView:UIView<UIAlertViewDelegate>//定义蛇的移动方向@property(nonatomic,assign)Orientorient;@endFKSnakeView.m文件内容:#import<AudioToolbox/AudioToolbox.h>#import"FKSnakeView.h"#import"FKPoint.h"@implementationFKSnakeView//记录蛇的点,最后一个点代表蛇头NSMutableArray*snakeData;//定义食物所在的点FKPoint*foodPos;NSTimer*timer;UIColor*bgColor;UIImage*cherryImage;UIAlertView*overAlert;//代表游戏音效变量SystemSoundIDgu;SystemSoundIDcrash;@synthesizeorient;-(id)initWithFrame:(CGRect)frame{ self=[superinitWithFrame:frame]; if(self){ //加载食物图片 cherryImage=[UIImageimageNamed:@"cherry.png"]; //加载游戏背景图片,并将背景图片转换为平铺形式的颜色 bgColor=[UIColorcolorWithPatternImage: [UIImageimageNamed:@"grass.png"]]; //获取两个音效文件的的URL NSURL*guUrl=[[NSBundlemainBundle] URLForResource:@"gu"withExtension:@"mp3"]; NSURL*crashUrl=[[NSBundlemainBundle] URLForResource:@"crash"withExtension:@"wav"]; //加载两个音效文件 AudioServicesCreateSystemSoundID((__bridgeCFURLRef)guUrl,&gu); AudioServicesCreateSystemSoundID((__bridgeCFURLRef)crashUrl,&crash); overAlert=[[UIAlertViewalloc]initWithTitle:@"游戏结束" message:@"您输了,是否重新再来?"delegate:self cancelButtonTitle:@"不来了"otherButtonTitles:@"再来一盘!",nil]; [selfstartGame]; } returnself;}-(void)startGame{ //FKPoint第1个参数控制位于水平第几格,第2个参数控制位于垂直第几格 snakeData=[NSMutableArrayarrayWithObjects: [[FKPointalloc]initWithX:1y:0], [[FKPointalloc]initWithX:2y:0], [[FKPointalloc]initWithX:3y:0], [[FKPointalloc]initWithX:4y:0], [[FKPointalloc]initWithX:5y:0],nil]; //定义蛇的初始移动方向 orient=kRight; timer=[NSTimerscheduledTimerWithTimeInterval:0.3target:self selector:@selector(move)userInfo:nilrepeats:YES];}-(void)move{ //除了蛇头受方向控制之外,其他点都是占它的前一个 //获取最后一个点,作为蛇头 FKPoint*first=[snakeDataobjectAtIndex:snakeData.count-1]; FKPoint*head=[[FKPointalloc]initWithX:first.xy:first.y]; switch(orient) { casekDown://代表向下 //新蛇头的位置 head.y=head.y+1; break; casekLeft://代表向左 //新蛇头的位置 head.x=head.x-1; break; casekRight://代表向右 //新蛇头的位置 head.x=head.x+1; break; casekUp://3代表上 //新蛇头的位置 head.y=head.y-1; break; } //如果移动后蛇头超出界面或与蛇身碰撞,游戏结束 if(head.x<0||head.x>WIDTH-1 ||head.y<0||head.y>HEIGHT-1 ||[snakeDatacontainsObject:head]) { //播放碰撞的音效 AudioServicesPlaySystemSound(crash); [overAlertshow]; [timerinvalidate]; }; //表明蛇头与食物点重合 if([headisEqual:foodPos]) { //播放吃食物的音效 AudioServicesPlaySystemSound(gu); //将食物点添加成新的蛇头 [snakeDataaddObject:foodPos]; //食物清空 foodPos=nil; } else { //从第一个点开始,控制蛇身向前 for(inti=0;i<snakeData.count-1;i++) { //将第i个点的坐标设置为第i+1个点的的坐标 FKPoint*curPt=[snakeDataobjectAtIndex:i]; FKPoint*nextPt=[snakeDataobjectAtIndex:i+1]; curPt.x=nextPt.x; curPt.y=nextPt.y; } //重新设置蛇头坐标 [snakeDatasetObject:headatIndexedSubscript:(snakeData.count-1)]; } if(foodPos==nil) { while(true) { FKPoint*newFoodPos=[[FKPointalloc] initWithX:arc4random()%WIDTH y:arc4random()%HEIGHT]; //如果新产生的食物点,没有位于蛇身体上 if(![snakeDatacontainsObject:newFoodPos]) { foodPos=newFoodPos; break;//成功生成了食物的位置,跳出循环 } } } [selfsetNeedsDisplay];}//定义绘制蛇头的方法-(void)drawHeadInRect:(CGRect)rectcontext:(CGContextRef)ctx{ CGContextBeginPath(ctx); //根据蛇头的方向,决定开口的角度 CGFloatstartAngle; switch(orient){ casekUp: startAngle=M_PI*7/4; break; casekDown: startAngle=M_PI*3/4; break; casekLeft: startAngle=M_PI*5/4; break; casekRight: startAngle=M_PI*1/4; break; default: break; } //添加一段弧作为路径 CGContextAddArc(ctx,CGRectGetMidX(rect),CGRectGetMidY(rect) ,CELL_SIZE/2,startAngle,M_PI*1.5+startAngle,0); //将绘制点移动到中心 CGContextAddLineToPoint(ctx,CGRectGetMidX(rect),CGRectGetMidY(rect)); //关闭路径 CGContextClosePath(ctx); CGContextFillPath(ctx);}-(void)drawRect:(CGRect)rect{ //获取绘图API CGContextRefctx=UIGraphicsGetCurrentContext(); CGContextClearRect(ctx,CGRectMake(0,0 ,WIDTH*CELL_SIZE,HEIGHT*CELL_SIZE)); CGContextSetFillColorWithColor(ctx,[bgColorCGColor]); //绘制背景, CGContextFillRect(ctx,CGRectMake(0,0 ,WIDTH*CELL_SIZE,HEIGHT*CELL_SIZE)); //绘制文字 [@"疯狂贪食蛇"drawAtPoint:CGPointMake(50,20) withAttributes:[NSDictionarydictionaryWithObjectsAndKeys: [UIFontfontWithName:@"HeitiSC"size:40],NSFontAttributeName, [UIColorcolorWithRed:1green:0blue:1alpha:.4], NSForegroundColorAttributeName,nil]]; [@"www.fkjava.org"drawAtPoint:CGPointMake(50,60) withAttributes:[NSDictionarydictionaryWithObjectsAndKeys: [UIFontfontWithName:@"HeitiSC"size:26],NSFontAttributeName, [UIColorcolorWithRed:1green:0blue:1alpha:.4], NSForegroundColorAttributeName,nil]]; //设置绘制蛇的填充颜色 CGContextSetRGBFillColor(ctx,1,1,0,1); //遍历蛇的数据,绘制蛇的数据 for(inti=0;i<snakeData.count;i++) { //为每个蛇的点(记录的是在数组的位置),在屏幕上绘制一个圆点 FKPoint*cp=[snakeDataobjectAtIndex:i]; //定义将要绘制蛇身点的矩形 CGRectrect=CGRectMake(cp.x*CELL_SIZE,cp.y*CELL_SIZE ,CELL_SIZE,CELL_SIZE); //绘制蛇尾巴,让蛇的尾巴小一些 if(i<4) { CGFloatinset=(4-i); CGContextFillEllipseInRect(ctx,CGRectInset(rect,inset,inset)); } //如果是最后一个元素,代表蛇头,绘制蛇头 elseif(i==snakeData.count-1) { [selfdrawHeadInRect:rectcontext:ctx]; } else { CGContextFillEllipseInRect(ctx,rect); } } //绘制“食物”图片 [cherryImagedrawAtPoint:CGPointMake(foodPos.x*CELL_SIZE ,foodPos.y*CELL_SIZE)];}-(void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ //如果用户点击了第二个按钮,重新开始游戏 if(buttonIndex==1) [selfstartGame];}@end
4、FKPoint类,该类用于封装X、Y两个属性,并重写了isEqual:方法,用于提供自定义判断两个点相等的标准。FKPoint.h文件内容:#import<Foundation/Foundation.h>@interfaceFKPoint:NSObject@property(nonatomic,assign)NSIntegerx;@property(nonatomic,assign)NSIntegery;-(id)initWithX:(NSInteger)xy:(NSInteger)y;-(BOOL)isEqual:(FKPoint*)other;@endFKPoint.m文件内容:#import"FKPoint.h"@implementationFKPoint-(id)initWithX:(NSInteger)xy:(NSInteger)y{self=[superinit];if(self){_x=x; _y=y;}returnself;}-(BOOL)isEqual:(FKPoint*)other{ if(self==other) { returnYES; } if(FKPoint.class==[otherclass]) { returnself.x==other.x &&self.y==other.y; } returnNO;}-(NSString*)description{ return[NSStringstringWithFormat:@"{%d,%d}",self.x,self.y];}@end
5、FKViewController.m文件内容:拭貉强跳#import<QuartzCore/QuartzCore.h>#import"FKViewCo荏鱿胫协ntroller.h"#import"FKSnakeView.h"@implementationFKViewControllerFKSnakeView*snakeView;-(void)viewDidLoad{[superviewDidLoad]; //创建FKSnakeView控件 snakeView=[[FKSnakeViewalloc]initWithFrame: CGRectMake(10,30,WIDTH*CELL_SIZE,HEIGHT*CELL_SIZE)]; //为snakeView控件设置边框和圆角。 snakeView.layer.borderWidth=3; snakeView.layer.borderColor=[[UIColorredColor]CGColor]; snakeView.layer.cornerRadius=6; snakeView.layer.masksToBounds=YES; //设置self.view控件支持用户交互 self.view.userInteractionEnabled=YES; //设置self.view控件支持多点触碰 self.view.multipleTouchEnabled=YES; for(inti=0;i<4;i++) { //创建手势处理器,指定使用该控制器的handleSwipe:方法处理轻扫手势 UISwipeGestureRecognizer*gesture=[[UISwipeGestureRecognizeralloc] initWithTarget:selfaction:@selector(handleSwipe:)]; //设置该点击手势处理器只处理i个手指的轻扫手势 gesture.numberOfTouchesRequired=1; //指定该手势处理器只处理1<<i方向的轻扫手势 gesture.direction=1<<i; //为self.view控件添加手势处理器。 [self.viewaddGestureRecognizer:gesture]; } [self.viewaddSubview:snakeView];}//实现手势处理器的方法,该方法应该声明一个形参。//当该方法被激发时,手势处理器会作为参数传给该方法的参数。-(void)handleSwipe:(UISwipeGestureRecognizer*)gesture{ //获取轻扫手势的方向 NSUIntegerdirection=gesture.direction; switch(direction) { caseUISwipeGestureRecognizerDirectionLeft: if(snakeView.orient!=kRight)//只要不是向右,即可改变方向 snakeView.orient=kLeft; break; caseUISwipeGestureRecognizerDirectionUp: if(snakeView.orient!=kDown)//只要不是向下,即可改变方向 snakeView.orient=kUp; break; caseUISwipeGestureRecognizerDirectionDown: if(snakeView.orient!=kUp)//只要不是向上,即可改变方向 snakeView.orient=kDown; break; caseUISwipeGestureRecognizerDirectionRight: if(snakeView.orient!=kLeft)//只要不是向左,即可改变方向 snakeView.orient=kRight; break; }}@end
6、将上面的文件内容修改之后,点击run运行就可以看到如下界面:进行游戏,游戏结束后可以选择退出或再来一局