//联系人:石虎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
=========================
===================================================
谢谢!!!