现在的位置: 首页 > 综合 > 正文

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

2013年10月21日 ⁄ 综合 ⁄ 共 7928字 ⁄ 字号 评论关闭

推箱子大家都知道吧,在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#写的地图编辑器!欢迎交流!

抱歉!评论已关闭.