推箱子简单实现(objective-c)

推箱子大家都知道吧,在cocos2d上简单实现了一个!

typedef enum
{
    None=-1,
    Wall=0,
    Worker,
    Box,
    Passageway,
    Destination,
    WorkerInDest,
    RedBox,
} Map_State;
//代表堆栈长度
#define MaxNum 300

这个枚举很重要, Wall:墙, Worke:工人,Box:箱子,Passageway:通道,Destination:目的地,WorkerInDest:工人在目的地,RedBox:箱子在目的地,游戏中会根据这些不同的类型,生成对应的精灵贴图,也就是说至少有7张图,我这里用Num1.png、Num2.png...Num7.png七张图来表示。游戏开始前我会有一个关卡的配置的plist,里面是一个一维数组:010101234567... 通过这个就可以进行初始化布局!

游戏初始化:

//游戏进入函数
-(void) show
{
    CGSize size = [[CCDirector sharedDirector] winSize];
    movableSprites = [[NSMutableArray alloc] init];
    
    labelStep = [CCLabelBMFont labelWithString:@"0" fntFile:@"mine.fnt"];
    labelStep.position =  ccp( size.width -30 , size.height-15 );
    [self addChild:labelStep];
    
    //后退按钮
	flagBt=[CCSprite spriteWithSpriteFrameName:@"btnFlaged.png"];
	flagBt.position=ccp(40,70);
	[self addChild:flagBt z:1 tag:1000];
	[movableSprites addObject:flagBt];
    
	//向上按钮
	upBt=[CCSprite spriteWithSpriteFrameName:@"up.png"];
	upBt.position=ccp(230,90);
	[self addChild:upBt z:1 tag:1001];
	[movableSprites addObject:upBt];
    
	//向下按钮
    downBt=[CCSprite spriteWithSpriteFrameName:@"down.png"];
	downBt.position=ccp(230,30);
	[self addChild:downBt z:1 tag:1002];
	[movableSprites addObject:downBt];
    
	//向左按钮
    leftBt=[CCSprite spriteWithSpriteFrameName:@"left.png"];
	leftBt.position=ccp(180,60);
	[self addChild:leftBt z:1 tag:1003];
	[movableSprites addObject:leftBt];
    
	//向右按钮
    rightBt=[CCSprite spriteWithSpriteFrameName:@"right.png"];
	rightBt.position=ccp(280,60);
	[self addChild:rightBt z:1 tag:1004];
	[movableSprites addObject:rightBt];
    
	//初始化
    [self intiGameConfig];
}

//游戏初始化
-(void) intiGameConfig
{
    W=30;//每个方块宽度
    m_col=10;//方块矩阵列数
    m_row=10;//方块矩阵行数
    m_count=m_row*m_col;//方块矩阵方块总数
    
    //栈顶
    s_top=-1;
    stackStep=(int *)malloc(sizeof(int)*MaxNum);//保存走过的方向,1上2下3左4右
    boxStatus=(int *)malloc(sizeof(int)*MaxNum);//保存行走时是否推了箱子
    
	//初始化二维数组
    myArrays=(int **)malloc(sizeof(int)*10);
    for (int i=0; i<10; i++) {
        myArrays[i]=(int *)malloc(sizeof(int)*10);
    }
    
	//读取关卡配置,一维数组:01010123456...
    NSString* plistPath = [[NSBundle mainBundle] pathForResource:@"level3" ofType:@"plist"];
    NSArray *Positions = [NSArray arrayWithContentsOfFile:plistPath];
    
    int tx=0;
    int ty=0;
    int type=-1;
    for (int i=0; i<m_count; i++) {
        tx=i/m_col;//行
        ty=i%m_col;//列
        type=[[Positions objectAtIndex:i] intValue];
        myArrays[tx][ty]=type;//保存方块类型
        
		//方块精灵
        CCSprite *p=[CCSprite spriteWithSpriteFrameName:[NSString stringWithFormat:@"Num%i.png",type]];
        p.tag=i;
        //p.anchorPoint=ccp(0, 0);
        p.position=ccp(10+15+ty*W,130+15+tx*W);
        [movableSprites addObject:p];
        [self addChild:p z:1];
        
        //找着工人位置
        if (type==Worker) {
            x=tx;
            y=ty;
            //tag=i=x*m_col+y;
        }
    }
    
}

工人行走功能实现:

-(void) ccTouchEnded:(UITouch*)touch withEvent:(UIEvent *)event
{
    CGPoint touchlocation = [touch locationInView: [touch view]];
    touchlocation =[[CCDirector sharedDirector] convertToGL:touchlocation];
    
    CCSprite * newSprite = nil;
	if (newSprite == nil) {
		for (CCSprite *sprite in movableSprites) {
			if (CGRectContainsPoint(sprite.boundingBox, touchlocation)) {            
				newSprite = sprite;
				break;
			}
		} 
		
	}
    if (newSprite==nil) {
        CCLOG(@"NO CCSprite has beend touched!");
    }
    else
    {
        int x_1;
        int y_1;
        int x_2;
        int y_2;
        
        int na = [newSprite tag];
        //CCLOG(@"tounchTag:%i",na);
        switch (na) {
            case 1000:
                CCLOG(@"后退");
                //
                [self GoBack];
                break;
            case 1001:
                CCLOG(@"上");
                x_1=x+1;
                y_1=y;
                x_2=x+2;
                y_2=y;
                [self MoveTo:1 x1:x_1 y1:y_1 x2:x_2 y2:y_2];
                break;
            case 1002:
                CCLOG(@"下");
                x_1=x-1;
                y_1=y;
                x_2=x-2;
                y_2=y;
                [self MoveTo:2 x1:x_1 y1:y_1 x2:x_2 y2:y_2];
                break;
            case 1003:
                CCLOG(@"左");
                x_1=x;
                y_1=y-1;
                x_2=x;
                y_2=y-2;
                [self MoveTo:3 x1:x_1 y1:y_1 x2:x_2 y2:y_2];
                break;
            case 1004:
                CCLOG(@"右");
                x_1=x;
                y_1=y+1;
                x_2=x;
                y_2=y+2;
                [self MoveTo:4 x1:x_1 y1:y_1 x2:x_2 y2:y_2];
                break;
            default:
                break;
        }
    }
}

//换图
-(void) changeSpritePic:(int) xx yy:(int) yy type:(int) type
{
    int tag=xx*m_col+yy;
    CCSprite *p=(CCSprite *)[self getChildByTag:tag];
    CCSpriteFrame* hpframe = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:@"Num%i.png",type]];
	[p setDisplayFrame:hpframe];
}

//检测是否完成
-(BOOL) IsFinish
{
    BOOL bFinish=YES;
    for (int i=0; i<m_col; i++) {
        for (int j=0; j<m_col; j++) {
            if (myArrays[i][j]==Destination||myArrays[i][j]==WorkerInDest) {
                bFinish=NO;
                break;
            }
        }
    }
    return bFinish;
}

-(void) MoveMan:(int)xx yy:(int)yy
{
    if (myArrays[xx][yy]==Worker) {
        //如果是通路
        myArrays[xx][yy]=Passageway;
        [self changeSpritePic:xx yy:yy type:Passageway];
    }
    else if(myArrays[xx][yy]==WorkerInDest)
    {
        myArrays[xx][yy]=Destination;
        [self changeSpritePic:xx yy:yy type:Destination];
    }
}

//是否在方块矩阵内
-(BOOL) IsInGameArea:(int)row col:(int)col
{
    return (row>=0&&row<m_row&&col>=0&&col<m_col);
}

-(void) MoveTo:(int)path x1:(int)x1 y1:(int)y1 x2:(int)x2 y2:(int)y2
{
    Map_State P1,P2;
    P1=P2=None;
    if ([self IsInGameArea:x1 col:y1]) {
        P1=myArrays[x1][y1];
    }
    if ([self IsInGameArea:x2 col:y2]) {
        P2=myArrays[x2][y2];
    }
    
	//前面是通道
    if (P1==Passageway) {
        [self MoveMan:x yy:y];
        x=x1;
        y=y1;
        myArrays[x1][y1]=Worker;
        [self changeSpritePic:x1 yy:y1 type:Worker];
        [self inStack:path box:0];
    }
	//前面是目的地
    if (P1==Destination) {
        [self MoveMan:x yy:y];
        x=x1;
        y=y1;
        myArrays[x1][y1]=WorkerInDest;
        [self changeSpritePic:x1 yy:y1 type:WorkerInDest];
        [self inStack:path box:0];
    }
    
	//前面是墙
    if (P1==Wall||![self IsInGameArea:x1 col:y1]) {
        return;
    }
    //前面是箱子
    if (P1==Box) {
        if (P2==Wall||![self IsInGameArea:x2 col:y2]||P2==Box) {
            return;
        }
    }
    //前面是箱子,前面的前面是路
    if (P1==Box && P2==Passageway) {
        [self MoveMan:x yy:y];
        x=x1;
        y=y1;
        myArrays[x1][y1]=Worker;
        myArrays[x2][y2]=Box;
        
        [self changeSpritePic:x1 yy:y1 type:Worker];
        [self changeSpritePic:x2 yy:y2 type:Box];
        [self inStack:path box:1];
    }
	//前面是箱子,前面的前面是目的地
    if (P1==Box && P2==Destination) {
        [self MoveMan:x yy:y];
        x=x1;
        y=y1;
        myArrays[x1][y1]=Worker;
        myArrays[x2][y2]=RedBox;
        
        [self changeSpritePic:x1 yy:y1 type:Worker];
        [self changeSpritePic:x2 yy:y2 type:RedBox];
        [self inStack:path box:1];
    }
    //前面是目的地的箱子,前面的前面是路
    if (P1==RedBox && P2==Passageway) {
        [self MoveMan:x yy:y];
        x=x1;
        y=y1;
        myArrays[x1][y1]=WorkerInDest;
        myArrays[x2][y2]=Box;
        
        [self changeSpritePic:x1 yy:y1 type:WorkerInDest];
        [self changeSpritePic:x2 yy:y2 type:Box];
        [self inStack:path box:1];
    }
    //前面是目的地的箱子,前面的前面是目的地
    if (P1==RedBox && P2==Destination) {
        [self MoveMan:x yy:y];
        x=x1;
        y=y1;
        myArrays[x1][y1]=WorkerInDest;
        myArrays[x2][y2]=RedBox;
        
        [self changeSpritePic:x1 yy:y1 type:WorkerInDest];
        [self changeSpritePic:x2 yy:y2 type:RedBox];
        [self inStack:path box:1];
    }
    //判断是否完成
    if ([self IsFinish]) {
        //显示完成界面
        [self showWin];
    }
}

//进栈
-(void) inStack:(int) path box:(int)box
{
    if (s_top+1<MaxNum) {
        s_top++;
        [labelStep setString:[NSString stringWithFormat:@"%i",s_top+1]];
        stackStep[s_top]=path;
        boxStatus[s_top]=box;
    }
    else
    {
        CCLOG(@"堆栈满了!");
    }
    //[self printStack];
}

//出栈
-(CGPoint) outStack
{
    CGPoint temp;
    if (s_top==-1) {
        CCLOG(@"堆栈空了!");
        temp.x=0;
        temp.y=0;
    }
    else
    {
        temp.x=stackStep[s_top];
        temp.y=boxStatus[s_top];
        s_top--;
        [labelStep setString:[NSString stringWithFormat:@"%i",s_top+1]];
    }
    return temp;
}

-(void) showWin
{
    
    winLayer *layer=[winLayer node];
    [layer showWinLayer];
    [self addChild:layer z:2];
    
}

后退功能实现:

//后退函数
-(void) GoBack
{
    //后退专用
    int x_1;//人的前面(箱子)
    int y_1;
    int x_2;//人的后面
    int y_2;
    
    CGPoint p=[self outStack];
    int na=p.x;
    if (na==0) {
        return ;
    }
    switch (na) {
        case 1:
            CCLOG(@"下");
            //
            x_1=x+1;
            y_1=y;
            x_2=x-1;
            y_2=y;
            [self MoveBack:p.y x1:x_1 y1:y_1 x2:x_2 y2:y_2];
            break;
        case 2:
            CCLOG(@"上");
            //
            x_1=x-1;
            y_1=y;
            x_2=x+1;
            y_2=y;
            [self MoveBack:p.y x1:x_1 y1:y_1 x2:x_2 y2:y_2];
            break;
        case 3:
            CCLOG(@"右");
            //
            x_1=x;
            y_1=y-1;
            x_2=x;
            y_2=y+1;
            [self MoveBack:p.y x1:x_1 y1:y_1 x2:x_2 y2:y_2];
            break;
        case 4:
            CCLOG(@"左");
            //
            x_1=x;
            y_1=y+1;
            x_2=x;
            y_2=y-1;
            [self MoveBack:p.y x1:x_1 y1:y_1 x2:x_2 y2:y_2];
            break;
        default:
            break;
    }
}
-(void) MoveBack:(int)box x1:(int)x1 y1:(int)y1 x2:(int)x2 y2:(int)y2
{    
    Map_State P1,P2;
    P1=P2=None;
    //p1:前面,箱子,p2:后面
    if ([self IsInGameArea:x1 col:y1]) {
        P1=myArrays[x1][y1];
    }
    if ([self IsInGameArea:x2 col:y2]) {
        P2=myArrays[x2][y2];
    }
    //后面是路
    if (P2==Passageway) {
        //
        myArrays[x2][y2]=Worker;
        [self changeSpritePic:x2 yy:y2 type:Worker];
    }
	//后面是目的地
    if (P2==Destination) {
        //
        myArrays[x2][y2]=WorkerInDest;
        [self changeSpritePic:x2 yy:y2 type:WorkerInDest];
    }
    
    [self MoveMan:x yy:y];
    //前面是箱子并且当时走这一步时推了箱子
    if (P1==Box&&box==1) {
        //
        if (myArrays[x][y]==Destination) {
            myArrays[x][y]=RedBox;
            [self changeSpritePic:x yy:y type:RedBox];
        }
        if (myArrays[x][y]==Passageway)
        {
            myArrays[x][y]=Box;
            [self changeSpritePic:x yy:y type:Box];
        }
        
        myArrays[x1][y1]=Passageway;
        [self changeSpritePic:x1 yy:y1 type:Passageway];
    }
	//前面是目的地的箱子并且当时走这一步时推了箱子
    if (P1==RedBox&&box==1) {
        //
        
        if (myArrays[x][y]==Destination) {
            myArrays[x][y]=RedBox;
            [self changeSpritePic:x yy:y type:RedBox];
        }
        if (myArrays[x][y]==Passageway)
        {
            myArrays[x][y]=Box;
            [self changeSpritePic:x yy:y type:Box];
        }
        
        myArrays[x1][y1]=Destination;
        [self changeSpritePic:x1 yy:y1 type:Destination];
    }
    x=x2;
    y=y2;
    
}

好了,就这么多,回头我会再贴一个,C#写的地图编辑器!欢迎交流!


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
cocos creator实现推箱子游戏,含源码和功能;游戏一共有100关卡。 cc.Class({ extends: cc.Component, properties: { // foo: { // // ATTRIBUTES: // default: null, // The default value will be used only when the component attaching // // to a node for the first time // type: cc.SpriteFrame, // optional, default is typeof default // serializable: true, // optional, default is true // }, // bar: { // get () { // return this._bar; // }, // set (value) { // this._bar = value; // } // }, starImg : cc.Node, itemBg : cc.Node, levelTxt : cc.Node, }, // LIFE-CYCLE CALLBACKS: onLoad () { }, start () { }, //--------显示星星数量-------- /** * @description: 显示星星数量 * @param {boolean} isOpen 是否开启 * @param {starCount} 星星数量 * @param {cc.SpriteAtlas} levelImgAtlas 纹理图 * @param {number} level 关卡 * @return: */ showStar : function(isOpen, starCount, levelImgAtlas, level){ this.itemBg.attr({"_level_" : level}); if(isOpen){ this.itemBg.getComponent(cc.Sprite).spriteFrame = levelImgAtlas.getSpriteFrame("pass_bg"); this.starImg.active = true; this.starImg.getComponent(cc.Sprite).spriteFrame = levelImgAtlas.getSpriteFrame("point" + starCount); this.levelTxt.opacity = 255; this.itemBg.getComponent(cc.Button).interactable = true; }else{ this.itemBg.getComponent(cc.Sprite).spriteFrame = levelImgAtlas.getSpriteFrame("lock"); this.starImg.active = false; this.levelTxt.opacity = 125; this.itemBg.getComponent(cc.Button).interactable = false; } this.levelTxt.getComponent(cc.Label).string = level; }, /
推箱子游戏是一种经典的益智游戏,主要思路是将箱子推到指定的位置,需要用到栈来实现。 首先,我们需要定义一些数据结构来表示地图和箱子,例如: ```c #define ROW 6 // 地图行数 #define COL 8 // 地图列数 // 地图元素类型 typedef enum { WALL, // 墙壁 SPACE, // 空地 BOX, // 箱子 TARGET, // 目标点 PLAYER // 玩家 } Element; // 地图类型 typedef struct { Element data[ROW][COL]; // 地图数据 int player_x; // 玩家横坐标 int player_y; // 玩家纵坐标 } Map; // 箱子类型 typedef struct { int x; // 箱子横坐标 int y; // 箱子纵坐标 } Box; ``` 然后,我们需要实现一个栈来保存箱子的移动路径,定义如下: ```c #define MAX_PATH 100 // 最大路径长度 // 栈类型 typedef struct { Box data[MAX_PATH]; // 栈数据 int top; // 栈顶指针 } Stack; // 初始化栈 void init(Stack *s) { s->top = -1; } // 判断栈是否为空 int is_empty(Stack *s) { return s->top == -1; } // 判断栈是否已满 int is_full(Stack *s) { return s->top == MAX_PATH - 1; } // 入栈 void push(Stack *s, Box box) { if (!is_full(s)) { s->top++; s->data[s->top] = box; } } // 出栈 Box pop(Stack *s) { Box box = {-1, -1}; if (!is_empty(s)) { box = s->data[s->top]; s->top--; } return box; } ``` 接下来,我们需要实现箱子的移动函数,使用栈来保存移动路径: ```c // 箱子移动函数 void move_box(Map *map, int dx, int dy, Stack *path) { int x = map->player_x + dx; int y = map->player_y + dy; int nx = x + dx; int ny = y + dy; if (map->data[nx][ny] == SPACE || map->data[nx][ny] == TARGET) { // 箱子可以移动 map->data[nx][ny] = BOX; map->data[x][y] = (map->data[x][y] == TARGET) ? TARGET : SPACE; Box box = {x, y}; push(path, box); map->player_x = x; map->player_y = y; } } // 上移箱子 void move_up(Map *map, Stack *path) { move_box(map, -1, 0, path); } // 下移箱子 void move_down(Map *map, Stack *path) { move_box(map, 1, 0, path); } // 左移箱子 void move_left(Map *map, Stack *path) { move_box(map, 0, -1, path); } // 右移箱子 void move_right(Map *map, Stack *path) { move_box(map, 0, 1, path); } ``` 最后,我们需要实现一个主函数来测试我们的程序: ```c int main() { // 初始化地图 Map map = { { {WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL}, {WALL, SPACE, SPACE, SPACE, WALL, SPACE, TARGET, WALL}, {WALL, SPACE, BOX, SPACE, WALL, SPACE, SPACE, WALL}, {WALL, SPACE, SPACE, SPACE, WALL, BOX, SPACE, WALL}, {WALL, BOX, TARGET, SPACE, SPACE, SPACE, SPACE, WALL}, {WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL} }, 1, 1 }; // 初始化栈 Stack path; init(&path); // 移动箱子 move_down(&map, &path); move_right(&map, &path); move_down(&map, &path); move_down(&map, &path); move_right(&map, &path); move_up(&map, &path); move_right(&map, &path); move_down(&map, &path); move_down(&map, &path); move_left(&map, &path); move_up(&map, &path); move_left(&map, &path); move_down(&map, &path); move_right(&map, &path); move_up(&map, &path); // 输出路径 while (!is_empty(&path)) { Box box = pop(&path); printf("(%d, %d) -> ", box.x, box.y); } printf("(%d, %d)\n", map.player_x, map.player_y); return 0; } ``` 输出结果为: ``` (2, 2) -> (3, 2) -> (3, 3) -> (4, 3) -> (4, 4) -> (3, 4) -> (2, 4) -> (2, 5) -> (3, 5) -> (4, 5) -> (4, 4) -> (4, 3) -> (3, 3) -> (2, 3) -> (2, 2) -> (1, 2) -> (1, 1) ``` 这个结果表示我们成功地将箱子推到了指定位置,并且输出了移动路径。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值