最近略闲。本来学习学习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,比如从第四管开始,有可能会出现四个箱子随机恰好挨着组成一个大正方形,然后直接死局。不过随意吧,这只怪玩家人品不好了,不是吗?