【300行小游戏】一、推箱子

最近略闲。本来学习学习cocos2dx,u3d神马的。但是为人太懒了,于是嚼了嚼老知识。写了点所谓的游戏自娱自乐。纯OC代码,仅仅实现了游戏主要内容。每个游戏限制在300行代码内(主要是为了代码可读性,不然可以再压缩一半)。

 

不多说。

一、搬箱子。

开始之前,我们要确定到底要做什么?做到什么程度?

1、搬箱子必须的元素:小人,箱子,目标

2、成功条件:目标全部被箱子占领

3、失败条件:不设置

4、具体细节,地图的大小(正矩形不超过9*9),小人的移动(可以往前进方向推动箱子以及穿越目标),箱子的移动(靠边不能移动),关卡的设置(第一关一个箱子,每关递增一个)等

开始。(笔者再次声明:本人没做过游戏,这个只是写来自己玩的,如有误导,纯属坑爹)

先贴出笔者自定义的常量和枚举类型,看面看不懂的可以回过头看看

#define kCount_Grid 6    //地图大小-小于10

#define kTotalRound 6    //关卡数

#define kHero [UIColor yellowColor]

#define kBox [UIColor blackColor]

#define kDragon [UIColor redColor]

#define kNormal [UIColor brownColor]



typedef NS_ENUM(NSInteger, GridType) {

    GridTypeNormal = 0,

    GridTypeBox = 1,

    GridTypeHero = 2,

    GridTypeDragon = 3,

};



typedef NS_ENUM(NSInteger, MoveDirection) {

    MoveDirectionUp = 0,

    MoveDirectionDown = 1,

    MoveDirectionLeft = 2,

    MoveDirectionRight = 3,

};

首先,我们来绘制我们的游戏地图

-(void)initMap

{

    CGRect frame = self.view.frame;

    CGFloat width_Grid = frame.size.width/kCount_Grid;

    vMap = [[UIView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.width)];

    [vMap setCenter:CGPointMake(frame.size.width/2, frame.size.height/2)];

    [self.view addSubview:vMap];

    for (int i=1; i<kCount_Grid+1; i++) {

        for (int j=1; j<kCount_Grid+1; j++) {

            UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake((i-1)*width_Grid, (j-1)*width_Grid, width_Grid, width_Grid)];

            btn.layer.borderWidth = 1;

            btn.layer.borderColor = [[UIColor lightGrayColor]CGColor];

            [btn setBackgroundColor:[UIColor brownColor]];

            [btn setTag:i+j*10];

            [vMap addSubview:btn];

        }

    }

}

如果是和笔者一样的菜鸟需注意一个细节,int i和int j是从1而非0开始的。

然后初始化小人,箱子,和目标的位置(笔者YY成Hero,box,和Dragon)

-(void)initHero

{

    btnHero = [self randomPoint:GridTypeHero];

    [btnHero setBackgroundColor:kHero];

    [btnHero setSelected:YES];

}



-(void)initBox

{

    for (int i=0; i<round; i++) {

        UIButton *btn = [self randomPoint:GridTypeBox];

        btn = [self checkRepeat:btn gridType:GridTypeBox];

        [btn setBackgroundColor:kBox];

        [btn setSelected:YES];

        [array_Box addObject:btn];

    }

}



-(void)initDragon

{

    for (int i=0; i<round; i++) {

        UIButton *btn = [self randomPoint:GridTypeDragon];

        btn = [self checkRepeat:btn gridType:GridTypeDragon];

        [btn setBackgroundColor:kDragon];

        [btn setSelected:YES];

        [array_Dragon addObject:btn];

    }

}

位置的初始化笔者采用的随机位置,因为懒得画地图

-(UIButton *)randomPoint:(GridType)type

{

    int x = 1;

    int y = 1;

    if (type == GridTypeBox) {

        x = arc4random()%(kCount_Grid-2);

        y = arc4random()%(kCount_Grid-2);

        x++;

        y++;

    }else{

        x = arc4random()%kCount_Grid;

        y = arc4random()%kCount_Grid;

    }

    x++;

    y++;

    UIButton *btn = (UIButton *)[vMap viewWithTag:(x+y*10)];

    return btn;

}

当然,得查一下重。不能一开始,所有的随机都随机到一个位置上去了是吧

此外,还应考虑到箱子的位置,不能初始化就靠再墙壁上。不然很容易就死局了。

-(UIButton *)checkRepeat:(UIButton*)btn gridType:(GridType)type

{

    if ([btn isSelected] == YES) {

        btn = [self randomPoint:type];

        return [self checkRepeat:btn gridType:type];

    }else{

        return btn;

    }

}

为了界面的简单,我抛弃了摆方向控制键的想法,全部用手势搞定

-(void)initAction

{

    UISwipeGestureRecognizer *recognizer;

    recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(goRight)];

    [recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];

    [[self view] addGestureRecognizer:recognizer];

    

    recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(goLeft)];

    [recognizer setDirection:(UISwipeGestureRecognizerDirectionLeft)];

    [[self view] addGestureRecognizer:recognizer];

    

    recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(goUp)];

    [recognizer setDirection:(UISwipeGestureRecognizerDirectionUp)];

    [[self view] addGestureRecognizer:recognizer];

    

    recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(goDown)];

    [recognizer setDirection:(UISwipeGestureRecognizerDirectionDown)];

    [[self view] addGestureRecognizer:recognizer];

}

这里暴露了笔者的菜鸟真相,顺便求一句,向之上的方法怎么传参啊?因为不知道如何传参,笔者多写了四个方法

-(void)goUp

{

    [self moveAction:btnHero direction:MoveDirectionUp];

}



-(void)goDown

{

    [self moveAction:btnHero direction:MoveDirectionDown];

}



-(void)goLeft

{

    [self moveAction:btnHero direction:MoveDirectionLeft];

}



-(void)goRight

{

    [self moveAction:btnHero direction:MoveDirectionRight];

}

然后再调到真正想执行的方法

-(BOOL)moveAction:(UIButton *)btn direction:(MoveDirection)direction

{

    int tag = btn.tag;

    int x = tag%10;

    int y = tag/10;

    switch (direction) {

        case MoveDirectionUp:

        {

            if (y<2) return NO;

            return [self moveItem:btn tag:(x+(y-1)*10) direction:MoveDirectionUp];

            break;

        }

        case MoveDirectionDown:

        {

            if (y+1>kCount_Grid) return NO;

            return [self moveItem:btn tag:(x+(y+1)*10) direction:MoveDirectionDown];

            break;

        }

        case MoveDirectionLeft:

        {

            if (x<2) return NO;

            return [self moveItem:btn tag:((x-1)+y*10) direction:MoveDirectionLeft];

            break;

        }

        case MoveDirectionRight:

        {

            if (x+1>kCount_Grid) return NO;

            return [self moveItem:btn tag:((x+1)+y*10) direction:MoveDirectionRight];

            break;

        }

    }

    return NO;

}

稍微解释一下,方格游戏的移动,其实就是坐标的+1-1,在这里笔者偷懒使用tag作为坐标,个位数表示x轴,十位数表示y轴。所以地图大小不能超过9*9

继续,具体的移动方法

-(BOOL)moveItem:(UIButton *)btn tag:(int)tag direction:(MoveDirection)direction

{

    UIButton *btnTarget = (UIButton*)[vMap viewWithTag:tag];

    if (btn == btnHero) {           //移动英雄

        if ([btnTarget isSelected] == YES) {

            if ([array_Box containsObject:btnTarget]) {

                if ([self moveAction:btnTarget direction:direction] == NO) {

                    return NO;

                }

            }

        }

        [btnHero setBackgroundColor:kNormal];

        [btnHero setSelected:NO];

        if ([array_Dragon containsObject:btnHero]) {

            [btnHero setBackgroundColor:kDragon];

            [btnHero setSelected:YES];

        }

        btnHero = btnTarget;

        [btnHero setBackgroundColor:kHero];

        [btnHero setSelected:YES];

    }else{                          //移动箱子

        [btn setBackgroundColor:kNormal];

        [btn setSelected:NO];

        [array_Box removeObject:btn];

        if ([array_Dragon containsObject:btn]) {

            count_Cover--;

        }

        [btnTarget setBackgroundColor:kBox];

        [btnTarget setSelected:YES];

        [array_Box addObject:btnTarget];

        if ([array_Dragon containsObject:btnTarget]) {

            count_Cover++;

        }

        if (count_Cover == round) {

            if (round >= kTotalRound) {

                UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"通过所有关卡" message:nil delegate:self cancelButtonTitle:@"再玩一遍" otherButtonTitles:nil];

                alert.tag = 100;

                [alert show];

            }else{

                UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"过关" message:nil delegate:self cancelButtonTitle:@"进入下一关" otherButtonTitles:nil];

                alert.tag = 200;

                [alert show];

            }

            

        }

    }

    return YES;

}

一切为了简单,所以笔者有些地方就纯粹用逻辑堆出来。

于是呢、第一个小游戏基本上就竣工了……当然还存在些许BUG,比如从第四管开始,有可能会出现四个箱子随机恰好挨着组成一个大正方形,然后直接死局。不过随意吧,这只怪玩家人品不好了,不是吗?

 

完整代码下载:Demo

你可能感兴趣的:(游戏)