iOS MonsterBall(怪物舞会)~demo

//联系人:石虎QQ: 1224614774昵称:嗡嘛呢叭咪哄

/**

注意点: 1.看 GIF 效果图.

2.看连线视图的效果图.

3.看实现代码(直接复制实现效果).

4.需要真机设备 才有效果 ...

5.关于  "gate" "ball1" "monster_move_1" "grass"  分别是加载的图片

*/

一、GIF 效果图:

二、连线视图的效果图:

图1:

图2:

图3:

三、实现代码:

=========================

===================================================

==========================

控制器1:SHBallView.h

//

//  SHBallView.h

//  MonsterBall(怪物舞会)~demo

//

//  Created by石虎on 2017/8/14.

//  Copyright © 2017年shihu. All rights reserved.

//

#import

#import

@interfaceSHBallView :UIView

//定义属性来记录足球的当前位置

@property(nonatomic,assign)CGPointcurrentPoint;

@property(nonatomic,assign)CMAccelerationacceleration;

//定义属性来记录足球滚动的X、Y轴方向的速度

@property(nonatomic,assign)CGFloatxVelocity;

@property(nonatomic,assign)CGFloatyVelocity;

- (void)update;

@end

控制器1:SHBallView.m

//

//  SHBallView.m

//  MonsterBall(怪物舞会)~demo

//

//  Created by石虎on 2017/8/14.

//  Copyright © 2017年shihu. All rights reserved.

//

#import"SHBallView.h"

#define BALL_SIZE24

//定义怪物的数量

#define MONSTER_NUM3

//定义球门的起始位置

#define GATE_ORIGIN_X85

//定义球门的宽度

#define GATE_WIDTH150

@interfaceSHBallView()

{

NSArray* ballImages;

NSArray* monsterImages;

UIImage* gateImage;

//定义变量记录足球动画帧的索引

NSIntegerballIndex , count;

//定义变量记录每个怪物当前显示的动画帧的索引

NSIntegermonsterImageIndexs[MONSTER_NUM];

//定义数组来记录每个怪物的位置

CGPointmonsterPoints[MONSTER_NUM];

NSTimer* timer;

BOOLisPlaying;//定义变量记录游戏的状态

}

@end

@implementationSHBallView

- (id)initWithCoder:(NSCoder*)aDecoder

{

self= [superinitWithCoder:aDecoder];

if(self) {

//加载球门图片

gateImage= [UIImageimageNamed:@"gate"];

//加载足球滚动的每一帧的图片

ballImages= [NSArrayarrayWithObjects:

[UIImageimageNamed:@"ball1"],

[UIImageimageNamed:@"ball2"],

[UIImageimageNamed:@"ball3"],

[UIImageimageNamed:@"ball4"],

[UIImageimageNamed:@"ball5"],

[UIImageimageNamed:@"ball6"],

[UIImageimageNamed:@"ball7"],

[UIImageimageNamed:@"ball8"],nil];

//加载怪物走动的每一帧的图片

monsterImages= [NSArrayarrayWithObjects:

[UIImageimageNamed:@"monster_move_1"],

[UIImageimageNamed:@"monster_move_2"],

[UIImageimageNamed:@"monster_move_3"],

[UIImageimageNamed:@"monster_move_4"],nil];

monsterImageIndexs[1] =1;

monsterImageIndexs[2] =2;

[selfstartGame];//开始游戏

}

returnself;

}

- (void) moveMonster

{

for(inti =0; i

{

//控制怪物动画显示下一帧的图片

monsterImageIndexs[i] =monsterImageIndexs[i] +1;

//改变第i个怪物的X坐标

monsterPoints[i].x=monsterPoints[i].x+arc4random() %9-4;

}

[selfsetNeedsDisplay];

}

- (void)drawRect:(CGRect)rect

{

//绘制足球

[ballImages[ballIndex++ %8]drawAtPoint:self.currentPoint];

//绘制球门

[gateImagedrawAtPoint:CGPointMake(GATE_ORIGIN_X,64)];

//采用循环绘制3个怪物

for(inti =0; i

{

[monsterImages[monsterImageIndexs[i] %4]drawAtPoint:monsterPoints[i]];

}

}

//重写实现currentPoint属性的setter方法

- (void)setCurrentPoint:(CGPoint)newPoint

{

//如果正在游戏中,且足球新的位置点与原来的位置点不位于同一个点。

if(isPlaying&& (fabs(_currentPoint.x- newPoint.x) >1

||fabs(_currentPoint.y- newPoint.y) >1))

{

_currentPoint= newPoint;

//如果足球当前的X坐标小于0,就足球已经位于最左边

if(_currentPoint.x<0)

{

//将足球设置在最左边,并将水平速度设为0

_currentPoint.x=0;

self.xVelocity=0;

}

//球已经到了底线,且没进球门

if(_currentPoint.y<75&& (_currentPoint.x

||_currentPoint.x>GATE_ORIGIN_X+GATE_WIDTH-4))

{

//将足球设置在底线上,并将垂直速度设为0

_currentPoint.y=75;

self.yVelocity=0;

}

//球进了球门

if(_currentPoint.y<75&& (_currentPoint.x>=GATE_ORIGIN_X+2

||_currentPoint.x<=GATE_ORIGIN_X+GATE_WIDTH-4))

{

//使用UIAlertView提示用户游戏结束,并询问用户是否要开始下一盘游戏

[[[UIAlertViewalloc]initWithTitle:@"游戏结束"

message:@"您进球了,再来一盘?"delegate:self

cancelButtonTitle:@"好"otherButtonTitles:nil]show];

//取消计时器

[timerinvalidate];

isPlaying=NO;

}

//如果足球的X坐标大于该控件的高度,表明足球已经到了屏幕最下方

if(_currentPoint.x>self.bounds.size.width-BALL_SIZE)

{

//将足球设置到屏幕最下方,并将垂直速度设为0

_currentPoint.x=self.bounds.size.width-BALL_SIZE;

self.xVelocity=0;

}

//如果足球的Y坐标大于该控件的宽度,表明足球已经到了屏幕最右边

if(_currentPoint.y>self.bounds.size.height-BALL_SIZE)

{

//将足球设置到屏幕最右边,并将水平速度设为0

_currentPoint.y=self.bounds.size.height-BALL_SIZE;

self.yVelocity=0;

}

//遍历每个怪物,检测怪物与足球是否碰撞

for(inti =0; i

{

//如果怪物所在矩形和足球所在矩形有交集,表明二者相撞

if(CGRectIntersectsRect([selfgetBallRect], [selfgetMonsterRect:i]))

{

//怪物将足球快速向下踢出,也就是足球的Y方向上速度增加0.6

self.yVelocity=self.yVelocity+0.6;

}

}

[selfsetNeedsDisplay];

}

}

- (void)update

{

staticNSDate*lastUpdateTime;

//如果初始化过lastUpdateTime变量

if(lastUpdateTime !=nil)

{

//计算上次到现在的时间差

NSTimeIntervalsecondsSinceLastDraw =

-([lastUpdateTimetimeIntervalSinceNow]);

//根据加速度数据计算足球在X方向、Y方向的速度

self.yVelocity=self.yVelocity+ -(self.acceleration.y*

secondsSinceLastDraw);

self.xVelocity=self.xVelocity+self.acceleration.x*

secondsSinceLastDraw;

//根据足球的速度计算足球在单位时间内滚动的距离。

//由于实际算出来的滚动距离太小,因此都需要乘以500(实际上可用400、600等)

CGFloatxDelta = secondsSinceLastDraw *self.xVelocity*500;

CGFloatyDelta = secondsSinceLastDraw *self.yVelocity*500;

//设置足球的位置为新计算出来的位置

self.currentPoint=CGPointMake(self.currentPoint.x+ xDelta,

self.currentPoint.y+ yDelta);

}

lastUpdateTime = [[NSDatealloc]init];

}

//获取怪物所在的矩形框

- (CGRect) getMonsterRect:(NSInteger) monsterIndex

{

CGRectrect;

//获取索引为monsterIndex的怪物的左上角坐标

rect.origin=monsterPoints[monsterIndex];

//获取图片的大小

rect.size= ((UIImage*)monsterImages[0]).size;

returnrect;

}

//获取足球所在的矩形框

- (CGRect) getBallRect

{

CGRectrect;

rect.origin=self.currentPoint;

rect.size= ((UIImage*)ballImages[0]).size;

returnrect;

}

- (void) resetGame

{

//依次设置每个怪物的位置

monsterPoints[0] =CGPointMake(20,150);

monsterPoints[1] =CGPointMake(190,150);

monsterPoints[2] =CGPointMake(80,280);

//设置足球开始的位置,位于该UIView的中心

self.currentPoint=CGPointMake((self.bounds.size.width-BALL_SIZE) /2.0f,

(self.bounds.size.height-BALL_SIZE) /2.0f);

//设置足球的开始速度

self.xVelocity=0.0f;

self.yVelocity=0.0f;

}

//当用户单击UIAlertView警告框上按钮时激发该方法

- (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:

(NSInteger)buttonIndex

{

//如果用户单击第一个按钮

if(buttonIndex ==0)

{

[selfstartGame];//重新开始游戏

}

}

- (void) startGame

{

//设置游戏状态:正在游戏

isPlaying=YES;

//重设足球和怪物的位置

[selfresetGame];

//使用定时器控制怪物的动作

timer= [NSTimerscheduledTimerWithTimeInterval:0.2target:self

selector:@selector(moveMonster)userInfo:nilrepeats:YES];

}

@end

=========================

===================================================

控制器2:ViewController.m

//

//  ViewController.m

//  MonsterBall(怪物舞会)~demo

//

//  Created by石虎on 2017/8/14.

//  Copyright © 2017年shihu. All rights reserved.

//

#import"ViewController.h"

#import

#import"SHBallView.h"

@interfaceViewController()

//运动管理器

@property(strong,nonatomic)CMMotionManager*motionManager;

@property(weak,nonatomic)SHBallView*ballView;

@end

@implementationViewController

- (void)viewDidLoad {

[superviewDidLoad];

//创建以grass.png图片平铺的颜色

UIColor* bgColor = [UIColorcolorWithPatternImage:

[UIImageimageNamed:@"grass"]];

//将该视图控制器管理的View控件转换为SHBallView

self.ballView= (SHBallView*)self.view;

//将背景设为以grass.png图片平铺的颜色

self.ballView.backgroundColor= bgColor;

//创建CMMotionManager对象

self.motionManager= [[CMMotionManageralloc]init];

NSOperationQueue* queue = [[NSOperationQueuealloc]init];

//设置CMMotionManager获取加速度数据的频率

self.motionManager.accelerometerUpdateInterval=0.05;

//使用代码块获取加速度数据

[self.motionManagerstartAccelerometerUpdatesToQueue:queuewithHandler:

^(CMAccelerometerData*accelerometerData,NSError*error)

{

//将获取得到的加速度数据传给FKBallView对象

self.ballView.acceleration= accelerometerData.acceleration;

//在主线程中调用FKBallView对象的update方法

[self.ballViewperformSelectorOnMainThread:@selector(update)

withObject:nilwaitUntilDone:NO];

}];

}

@end

=========================

===================================================

谢谢!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容