一。实现界面上的图像;
1.这是界面的布局成为这个熊样。
2.将4个相同类型的植物槽中的植物关联到同一个事件中。
@property (strong, nonatomic) IBOutletCollection(UIImageView) NSArray *plantIVs;
3.将下面的45个草坪中的坑 添加uiview,然后关联到一个相同功能的数组中。
@property (strong, nonatomic) IBOutletCollection(UIView) NSArray *boxes;
4.背景出现什么就拖出什么 ,拖出阳光的图片 阳光图片的下面托出一个lable用于显示数据。
二。拖拽植物槽里点植物:
1。以下代码是用来实现 植物槽里点植物多,从一张图片中截取出你要的图片显示在植物槽里;
-(void)initUI{
UIImage *plantsImage = [UIImageimageNamed:@"seedpackets.png"];
float w = plantsImage.size.width/18;
float h = plantsImage.size.height;
for (int i=0; i<4; i++) {
UIImageView *plantIV =self.plantIVs[i];
float x = 0;
switch (i) {
case1://豌豆射手
x= 2*w;
break;
case2://寒冰射手
x= 3*w;
break;
case3://坚果
x= 5*w;
break;
}
CGImageRef subImage = CGImageCreateWithImageInRect(plantsImage.CGImage, CGRectMake(x, 0, w, h));
plantIV.image = [UIImageimageWithCGImage:subImage];
CGImageRelease(subImage);
三。 创建一个植物类,用来显示植物了, 植物类应该继承uiimageview;
1.因为所有以后要用到多植物都是属于要有动态效果的, 所以在创建好 植物父类的时候就要对其进行一个timer方法: 然后在调用这个方法的时候要创建一个改变图片的方法
- (id)initWithFrame:(CGRect)frame
{
self = [superinitWithFrame:frame];
if (self) {
[NSTimerscheduledTimerWithTimeInterval:.1target:selfselector:@selector(changeImage) userInfo:nilrepeats:YES];
}
returnself;
}
然后在初始化此方法后要对这个方法进行实现。 , 此段代码就是实现图片的所有植物类图片的动态效果。 此方法需要在 viewdidload里面实现。
而且注意对是: 这里面用到了一个count的变量, 所以需要在.h里面进行声明
@property (nonatomic)int count;
@property (nonatomic, strong)UIImage *plantImage;
.h里面的声明代码。 而plantImage 是表示植物槽里点植物 声明的全局属性,其它子类可以继承。
-(void)changeImage{
float w = self.plantImage.size.width/8;
// x 0w 1w 2w 3w
CGImageRef subImage = CGImageCreateWithImageInRect(self.plantImage.CGImage, CGRectMake(self.count++%8*w, 0, w, self.plantImage.size.height));
self.image = [UIImageimageWithCGImage:subImage];
CGImageRelease(subImage);
}做完这些后,也无法实现显示动态植物的原因是, 没有在viewcontroller中进行初始化的声明及使用。
四。接下来 需要创建其它的子类用来继承plant植物类, 因为现在声明了一个全局变量叫plantImage
1.声明一个子类叫做sunflower就是向日葵: 继承父类plant,然后在其自己的类当中实现自己要显示的图片。
- (id)initWithFrame:(CGRect)frame
{
self = [superinitWithFrame:frame];
if (self) {
self.plantImage = [UIImageimageNamed:@"plant_0.png"]; 此段代码是这个阶段要用的! 此时需要在页面中创建一个花 需要代码进行初始化,
就是self.dragPlant =[[SunFloweralloc]initWithFrame:plantIV.frame];类似于这样的
//打开用户交互不然自身及内部子控件的事件响应不了
self.userInteractionEnabled= YES;
//让超出自身范围的子控件不显示
self.clipsToBounds = YES;
}
returnself;
}
接下来此阶段的工作酒时重复以上的工作,创建一个豌豆射手,寒冰射手,坚果类 然后继承父类 的方法:然后在其具体的方法中进行自身图片的显示。
五。第五步,接下来这部分应该实现的是具体的每个草坪的坑中, 需要托45个view 然后45个view需要将其设置成透明,alpha里面设置,用控件全选。
此阶段就需要实现鼠标的点击事件了。
-(void)touchesBegan:(NSSet *)toucheswithEvent:(UIEvent *)event{
UITouch *t = [touches anyObject];
CGPoint p = [t locationInView:self.view];
for (UIImageView *plantIV inself.plantIVs) {
if (CGRectContainsPoint(plantIV.frame, p)) { //植物槽上的植物和p点(鼠标的点)点位置相同的话,用一个switch来创建点击不同植物槽,在当前的植物槽上创建植物。
switch (plantIV.tag) {
case0:
{
self.dragPlant = [[SunFloweralloc]initWithFrame:plantIV.frame];
}
break;
case1:
{
self.dragPlant = [[Peaalloc]initWithFrame:plantIV.frame];
}
break;
case2:
{
self.dragPlant = [[IcePeaalloc]initWithFrame:plantIV.frame];
}
break;
case3:
{
self.dragPlant = [[Nutalloc]initWithFrame:plantIV.frame];
}
break;
}
self.dragPlant.delegate = self;
[self.viewaddSubview:self.dragPlant];
}
}
} 此段代码的意思就是 当你点击植物槽里点植物时 在当前点击的植物上复制一个新的植物 每个植物槽的tag不同。
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ 鼠标移动的事件情况
UITouch *t = [touches anyObject];
CGPoint p = [t locationInView:self.view];
self.dragPlant.center = p;
-(void)touchesEnded:(NSSet *)toucheswithEvent:(UIEvent *)event{
//判断是否拖拽着植物
if (self.dragPlant) {如果拖动的是植物的话:下面的判断是遍历每个草坪上的槽;
for (UIView *box inself.boxes) {
if (CGRectContainsPoint(box.frame, self.dragPlant.center)&&box.subviews.count==0) {如果草坪上的frame和拖动植物的中心点中心点重叠多话:将植物显示到当前你拖动到的草坪槽的中心点上, 而后面加的box的count的判断是为了避免: 一个草坪槽里出现多个植物。
[box addSubview:self.dragPlant];
self.dragPlant.center = CGPointMake(box.frame.size.width/2, box.frame.size.height/2);
//开火儿
[self.dragPlantbeginFire];
}
}
//判断如果没有扔到任何一个坑里面的话就把植物删除
if ([self.dragPlant.superviewisEqual:self.view]) {
[self.dragPlantremoveFromSuperview];
}
self.dragPlant = nil; //如果没有次方法:会出现 如果拖动一个植物后拖动到草坪槽里, 但是点击松手后,但是你鼠标移动的话也会出现植物跟着移动;
}
}
此时实现以上的方法后 会有一个小bug 因为如果遇到了意外中断的情况 是可以讲图片添加等任意位置的: 所以此时就需要实现一个意外中断的方法:
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
if (self.dragPlant) {
[self.dragPlantremoveFromSuperview];
}
第五步完成了以后, 现在所有植物槽的植物能拖动了,,植物也能正确懂种植在草坪上, 但是现在当情况是,没有阳光, 每一个植物所对应的:如产阳光,发射子弹,等功能没有实现。所以,下一步的功能就是 实现��产出阳光。
第六步:
解决方案与需求: 因为��产出阳光 是其自身的状态属性, 但是这个 状态属性,基本上大部分的植物都存在, 所以需要声明一个父类的方法, 然后在父类的.h中声明.m中实现, 但是父类的实现的代码里不做任何代码的操作, 而是要通过子类继承重写的方式进行各自的 子类的植物的具体功能的实现, 所以需要重写。
在子类的重写方法中 因为是要动态的有规律的添加太阳, 需要调用计时器的方法: 然后selector中加入一个 添加阳光的方法:
需要注意的一点是。当你这个��扔到坑里的时候就需要调用开火这个方法, 所以还需要在view didload里面实现:
注意: 一般控件都有一个属性是用户交互, 因为当你拖动到草坪上时交互不开的花可能点不了: 原因是因为图片imageview的交互是默认关闭的,而他如果关闭了,所有在他内部的所有子控件也就变成了关闭的: 所以在这里需要写入一个方法; 这个方法是在向日葵自己的.m方法里面写的;自定义的时候。
//打开用户交互 不然自身及内部子控件的事件响应不了
self.userInteractionEnabled= YES;
//让超出自身范围的子控件不显示
self.clipsToBounds = YES;
-(void)beginFire{
[NSTimerscheduledTimerWithTimeInterval:8target:selfselector:@selector(addSun) userInfo:nilrepeats:YES];
}
-(void)addSun{
UIButton *sunBtn = [[UIButtonalloc]initWithFrame:CGRectMake(10, 25, 25, 25)];//因为阳光是按钮,需要收集,所以是按钮,
[sunBtn setImage:[UIImageimageNamed:@"sun.png"] forState:UIControlStateNormal];
[sunBtn addTarget:selfaction:@selector(clicked:) forControlEvents:UIControlEventTouchUpInside];
[selfaddSubview:sunBtn];
//阳光自己消失
[NSTimerscheduledTimerWithTimeInterval:3target:selfselector:@selector(removeSunAction:) userInfo:sunBtn repeats:NO];
}
-(void)removeSunAction:(NSTimer *)timer{
UIButton *sunBtn = timer.userInfo;
[sunBtn removeFromSuperview];
}
-(void)clicked:(UIButton *)sunBtn{阳光按钮自己的点击事件。
[sunBtn removeFromSuperview];
[self.delegateaddSunCount:25];
现在剩余一个小功能就是:没有阳光的计数。 所以要涉及到反向调用
第七步: 反向调用 给阳光的label添加修改功能。
反向传值流程:1.在B类的.h中声明一个A类型的weak属性delegate
2.在A类中创建完B类的时候给B类型对象的delegate属性赋值
3.在A类的.h中声明方法供B类调用 如果需要传递回来参数那该方法声明时需要带参数
viewcontroller是A类 ,太阳花是B类
1.现在是在sunflower中声明的, 因为方向调用要改Label的值得话 不仅仅是在这个子类当中,其他地方也要用, 所以需要声明在父类当中
2.在A类中 创建完B类的时候 也就是创建太阳花初始化方法的时候 给B类型的对象的delegate赋值。 self.dragPlant.delegate = self;
3.在A类的.h中声明方法供B调用,-(void)addSunCount:(int)count;
然后再.m里面实现以下
-(void)addSunCount:(int)count{
int oldCount = self.sunCountLabel.text.intValue;
self.sunCountLabel.text = [NSStringstringWithFormat:@"%d",oldCount+count];
剩下的工作就是只需要在点击按钮事件的时候 调用此方法就可以了 ;就是太阳花自己的点击消失的时候要计数;
-(void)clicked:(UIButton *)sunBtn{
[sunBtn removeFromSuperview];
[self.delegateaddSunCount:25];
做完这些 ,植物的大部分工作都已经做完了,剩下的工作就是添加子弹。
第八步.添加子弹
发射子弹是每隔一段事件发射, 所以在开火的方法中应该开一个timer pea的.m方法里