zoukankan      html  css  js  c++  java
  • SpriteKit再探之连连看

    1.初始化地图并且绘制地图。

    这是我的图片素材,大家可以找更漂亮的。

    SKTexture类里面的textureWithRect方法,作用是利用一个纹理的部分区域生成一个新的纹理。第一个参数是一个矩形,值得注意的是,矩形的四个参数都是一个不大于1的小数,表示的是新纹理在原纹理中的比例。

    连连看的行和列的乘积必须为偶数,这样才能保证连到最后不会剩下一个。我的做法是,地图数组前一半在图片数组范围内随机赋值,后一半复制前一半的值,然后通过洗牌的方法打乱整个地图。

    2.捕捉点击事件并且计算两次所选的位置。

    左下角是坐标(0,0)点。

    刚开始获得的坐标是在场景上的坐标,要减去相应的边距才能得到在地图上的坐标,然后计算出相应的行和列。记录两次点击的位置,并且确保两次位置不相同。

    3.判断两次选择的图片是否可以相连。

    判断两个图片是否可以相连,分为以下几种。水平相连,垂直相连,通过一个转角相连,通过两个转角相连,通过边界相连。

    4.添加选中和连线的动画。

    动画的方法放在update方法里面。其中,实现连线动画,需要记录各个转角点的坐标。

    详细代码如下:

    GameScene.h

    #import <SpriteKit/SpriteKit.h>


    //图片个数

    #define IMAGE_NUMBER 7

    //map的行和列的乘积必须为偶数,这样才可以保证游戏有解。

    #define MAP_ROW 8

    #define MAP_COLUMN 8

    //屏幕尺寸

    #define SCREEN_WIDTH 320

    #define SCREEN_HEIGHT 480

    //图片尺寸

    #define BLOCK_WIDTH 32

    #define BLOCK_HEIGHT 32

    //地图尺寸

    #define MAP_WIDTH BLOCK_WIDTH * MAP_COLUMN

    #define MAP_HEIGHT BLOCK_HEIGHT * MAP_ROW

    //左边距和下边距

    #define LEFT (SCREEN_WIDTH - BLOCK_WIDTH * IMAGE_NUMBER - 1) / 2

    #define BOTTOM (SCREEN_HEIGHT - BLOCK_HEIGHT * IMAGE_NUMBER - 1) / 2


    typedefstruct Select{

       int row;

       int column;

    }Select;


    typedefstruct LinePath{

       Select point1;

       Select point2;

    }LinePath;


    typedefenum SELECT_TYPE{

        SELECT_NONE =0,

        SELECT_ONE =1,

        SELECT_TWO =1<<1,

    }SELECT_TYPE;


    @interface GameScene :SKScene

    {

       SKTexture * imgArray[IMAGE_NUMBER];

       int map[MAP_ROW][MAP_COLUMN];

       Select firstSelect;

       Select secondSelect;

       SELECT_TYPE selectType;

       LinePath linePath;

    }


    @end


    GameScene.m

    #import "GameScene.h"


    @implementation GameScene


    - (id)initWithSize:(CGSize)size{

       if(self = [super initWithSize:size]){

           memset(map, -1,sizeof(map));

           memset(&firstSelect, -1,sizeof(Select));

           memset(&secondSelect, -1,sizeof(Select));

           memset(&linePath, -1,sizeof(LinePath));

            

           SKTexture * img = [SKTexture textureWithImageNamed:@"img.png"];

            //init imgArray

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

               imgArray[i] = [SKTexture textureWithRect:CGRectMake((float)i /IMAGE_NUMBER, 0.0,1.0 /IMAGE_NUMBER,1.0)

                                              inTexture:img];

            }

            //init and draw map

           /**

             这里要注意一个问题,任意一个元素出现的个数必须为偶数,这样本游戏才可能有解。

             解决方法如下,

             .数组前一半用随机赋值,后一半复制前一半的值。

             .利用洗牌算法使整个数组乱序。

             */

           int * point = &map[0][0];

           int count =MAP_ROW *MAP_COLUMN /2;

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

                *(point + i) =arc4random()%IMAGE_NUMBER;

                *(point + count + i) = *(point + i);

            }

            [self shuffle];

            [self drawMap];

        }

        return self;

    }


    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

       for(UITouch * touch in touches){

           CGPoint location = [touch locationInNode:self];

            //获取两次选择的图片的行和列,并确保两次位置不同。

            location.x -= (LEFT -BLOCK_WIDTH /2);

            location.y -= (BOTTOM -BLOCK_HEIGHT /2);

           if((location.x >0) && (location.x <MAP_WIDTH) && (location.y >0) && (location.y <MAP_HEIGHT)){

               int row = location.y /BLOCK_WIDTH;

               int column = location.x /BLOCK_HEIGHT;

               if(map[row][column] != -1){

                   if((firstSelect.row == -1) && (firstSelect.column == -1)){

                       firstSelect.row = row;

                       firstSelect.column = column;

                       selectType =SELECT_ONE;

                        

                    }else{

                       if((firstSelect.row != row) || (firstSelect.column != column)){

                           secondSelect.row = row;

                           secondSelect.column = column;

                           selectType =SELECT_TWO;

                        }

                       else{

                           memset(&firstSelect, -1,sizeof(Select));

                           selectType =SELECT_NONE;

                        }

                    }

                }

            }

        }

    }


    - (void)update:(NSTimeInterval)currentTime{

        [self playMatchAction];

    }


    #pragma mark  洗牌

    - (void)shuffle{

       int *point = &map[0][0];

        int size =MAP_ROW *MAP_COLUMN;

       while(size >1){

            size--;

           int index =arc4random()%size +1;

           int swap = *(point + index);

            *(point + index) = *(point + size);

            *(point + size) = swap;

        }

    }


    #pragma mark  绘制

    - (void)drawMap{

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

           for(int j =0; j <MAP_COLUMN; j++){

               SKSpriteNode * spriteNode = [SKSpriteNode spriteNodeWithTexture:imgArray[map[i][j]]];

                spriteNode.name = [NSString stringWithFormat:@"%d%d",i,j];

                spriteNode.position =CGPointMake(j *BLOCK_WIDTH +LEFT,i *BLOCK_HEIGHT +BOTTOM);

                [self addChild:spriteNode];

            }

        }

    }


    #pragma mark - 判断两个图片是否可以消去

    - (BOOL)match:(Select)startSelect andOtherSeclet:(Select)endSelect{

        //判断是否是一样的图片

       if(map[startSelect.row][startSelect.column] !=map[endSelect.row][endSelect.column]){

           return NO;

        }

        //水平直连

       if([self horizon:startSelect andOtherSeclet:endSelect] ==YES){

           return YES;

        }

        //垂直直连

       if([self vertical:startSelect andOtherSeclet:endSelect] ==YES){

           return YES;

        }

        //一个转角

       if([self oneCorner:startSelect andOtherSeclet:endSelect] ==YES){

           return YES;

        }

        //两个转角

       if([self twoCorner:startSelect andOtherSeclet:endSelect] ==YES){

           return YES;

        }

        //是否可以通过边界相连

       if([self border:startSelect andOtherSeclet:endSelect] ==YES){

           return YES;

        }

        return NO;

    }


    - (BOOL)horizon:(Select)startSelect andOtherSeclet:(Select)endSelect{

       if(startSelect.row == endSelect.row){

           int start = startSelect.column < endSelect.column ? startSelect.column : endSelect.column;

           int end = startSelect.column < endSelect.column ? endSelect.column : startSelect.column;

           for(start = start +1; start < end; start++){

               if(map[startSelect.row][start] != -1){

                   return NO;

                }

            }

           return YES;

        }

        return NO;

    }


    - (BOOL)vertical:(Select)startSelect andOtherSeclet:(Select)endSelect{

       if(startSelect.column == endSelect.column){

           int start = startSelect.row < endSelect.row ? startSelect.row : endSelect.row;

           int end = startSelect.row < endSelect.row ? endSelect.row : startSelect.row;

           for(start = start +1; start < end; start++){

               if(map[start][startSelect.column] != -1){

                   return NO;

                }

            }

           return YES;

        }

        return NO;

    }


    - (BOOL)oneCorner:(Select)startSelect andOtherSeclet:(Select)endSelect{

       Select point;

       memset(&point, -1,sizeof(Select));

        point.row = startSelect.row;

        point.column = endSelect.column;


       if(map[point.row][point.column] == -1){

           if(([self horizon:startSelect andOtherSeclet:point] && [self vertical:point andOtherSeclet:endSelect]) ==YES){

               linePath.point1 = point;

               return YES;

            }

        }

        point.row = endSelect.row;

        point.column = startSelect.column;

       if(map[point.row][point.column] == -1){

           if(([self vertical:startSelect andOtherSeclet:point] && [self horizon:point andOtherSeclet:endSelect]) ==YES){

               linePath.point1 = point;

               return YES;

            }

        }

        return NO;

    }


    - (BOOL)twoCorner:(Select)startSelect andOtherSeclet:(Select)endSelect{

       Select point1;

       Select point2;

       memset(&point1, -1,sizeof(Select));

       memset(&point1, -1,sizeof(Select));

        point1 = startSelect;

       for(point1.column = point1.column -1; point1.column >0; point1.column--){

           if(map[point1.row][point1.column] != -1){

               break;

            }else{

                point2.row = endSelect.row;

                point2.column = point1.column;

               if(map[point2.row][point2.column] != -1){

                   break;

                }

               if([self vertical:point1 andOtherSeclet:point2] && [self horizon:point2 andOtherSeclet:endSelect]){

                   linePath.point1 = point1;

                   linePath.point2 = point2;

                   return YES;

                }

            }

        }

        point1 = startSelect;

       for(point1.column = point1.column +1; point1.column <MAP_COLUMN; point1.column++){

           if(map[point1.row][point1.column] != -1){

               break;

            }else{

                point2.row = endSelect.row;

                point2.column = point1.column;

               if(map[point2.row][point2.column] != -1){

                   break;

                }

               if([self vertical:point1 andOtherSeclet:point2] && [self horizon:point2 andOtherSeclet:endSelect]){

                   linePath.point1 = point1;

                   linePath.point2 = point2;

                   return YES;

                }

            }

        }

        point1 = startSelect;

       for(point1.row = point1.row -1; point1.row >0; point1.row--){

           if(map[point1.row][point1.column] != -1){

               break;

            }else{

                point2.row = point1.row;

                point2.column = endSelect.column;

               if(map[point2.row][point2.column] != -1){

                   break;

                }

               if([self horizon:point1 andOtherSeclet:point2] && [self vertical:point2 andOtherSeclet:endSelect]){

                   linePath.point1 = point1;

                   linePath.point2 = point2;

                   return YES;

                }

            }

        }

        point1 = startSelect;

       for(point1.row = point1.row +1; point1.row <MAP_ROW; point1.row++){

           if(map[point1.row][point1.column] != -1){

               break;

            }else{

                point2.row = point1.row;

                point2.column = endSelect.column;

               if(map[point2.row][point2.column] != -1){

                   break;

                }

               if([self horizon:point1 andOtherSeclet:point2] && [self vertical:point2 andOtherSeclet:endSelect]){

                   linePath.point1 = point1;

                   linePath.point2 = point2;

                   return YES;

                }

            }

        }

        return NO;

    }


    - (BOOL)border:(Select)startSelect andOtherSeclet:(Select)endSelect{

       Select point1;

       Select point2;

       memset(&point1, -1,sizeof(Select));

       memset(&point2, -1,sizeof(Select));

        

        point1.row = firstSelect.row;

        point2.row = secondSelect.row;

        if([self horizon:point1 andOtherSeclet:firstSelect] && [self horizon:point2 andOtherSeclet:secondSelect]){

           linePath.point1 = point1;

           linePath.point2 = point2;

           return YES;

        }

        point1.column =MAP_COLUMN;

        point2.column =MAP_COLUMN;

        if([self horizon:firstSelect andOtherSeclet:point1] && [self horizon:secondSelect andOtherSeclet:point2]){

           linePath.point1 = point1;

           linePath.point2 = point2;

           return YES;

        }

        point1.row = -1;

        point1.column =firstSelect.column;

        point2.row = -1;

        point2.column =secondSelect.column;

        if([self vertical:point1 andOtherSeclet:firstSelect] && [self vertical:point2 andOtherSeclet:secondSelect]){

           linePath.point1 = point1;

           linePath.point2 = point2;

           return YES;

        }

        point1.row =MAP_ROW;

        point2.row =MAP_ROW;

        if([self vertical:firstSelect andOtherSeclet:point1] && [self vertical:secondSelect andOtherSeclet:point2]){

           linePath.point1 = point1;

           linePath.point2 = point2;

           return YES;

        }

        return NO;

    }

    #pragma mark -


    #pragma mark 播放消去动画

    - (void)playMatchAction{

        switch(selectType){

            caseSELECT_NONE:

               if([self childNodeWithName:@"selected1"] !=nil){

                    [[self childNodeWithName:@"selected1"removeFromParent];

                }

               if([self childNodeWithName:@"selected2"] !=nil){

                    [[self childNodeWithName:@"selected2"removeFromParent];

                }

               if([self childNodeWithName:@"line"] !=nil){

                    [[self childNodeWithName:@"line"removeFromParent];

                }

               break;

           caseSELECT_ONE:

               if([self childNodeWithName:@"selected1"] ==nil){

                   SKSpriteNode * selected = [SKSpriteNode spriteNodeWithImageNamed:@"selected.png"];

                    selected.position =CGPointMake(firstSelect.column *BLOCK_WIDTH + LEFT,firstSelect.row *BLOCK_HEIGHT +BOTTOM);

                    selected.name =@"selected1";

                    [self addChild:selected];

                }

               break;

           caseSELECT_TWO:

               if([self childNodeWithName:@"selected2"] ==nil){

                   SKSpriteNode * selected = [SKSpriteNode spriteNodeWithImageNamed:@"selected.png"];

                    selected.position =CGPointMake(secondSelect.column *BLOCK_WIDTH + LEFT,secondSelect.row *BLOCK_HEIGHT +BOTTOM);

                    selected.name =@"selected2";

                    [self addChild:selected];

                   if([self match:firstSelect andOtherSeclet:secondSelect] ==YES){

                        [self matchAction];

                    }

                   memset(&firstSelect, -1,sizeof(Select));

                   memset(&secondSelect, -1,sizeof(Select));

                   selectType =SELECT_NONE;

                }

               break;

        }

    }


    - (void)matchAction{

        [self lineAction];

        [[self childNodeWithName:[NSString stringWithFormat:@"%d%d",firstSelect.row,

                                 firstSelect.column]] removeFromParent];

        [[self childNodeWithName:[NSString stringWithFormat:@"%d%d",secondSelect.row,

                                 secondSelect.column]] removeFromParent];

        map[firstSelect.row][firstSelect.column] = -1;

        map[secondSelect.row][secondSelect.column] = -1;

    }


    - (void)lineAction{

        SKShapeNode * line = [[SKShapeNode allocinit];

        CGMutablePathRef myPath =CGPathCreateMutable();

        if((linePath.point1.row == -1) && (linePath.point2.row == -1)){

           CGPoint point[2];

            point[0].x =firstSelect.column *BLOCK_WIDTH + LEFT;

            point[0].y =firstSelect.row *BLOCK_HEIGHT + BOTTOM;

            point[1].x =secondSelect.column *BLOCK_WIDTH + LEFT;

            point[1].y =secondSelect.row *BLOCK_HEIGHT + BOTTOM;

           CGPathAddLines(myPath,NULL, point,2);

        }elseif(linePath.point2.row == -1){

           CGPoint point[3];

            point[0].x =firstSelect.column *BLOCK_WIDTH + LEFT;

            point[0].y =firstSelect.row *BLOCK_HEIGHT + BOTTOM;

            point[1].x =linePath.point1.column *BLOCK_WIDTH + LEFT;

            point[1].y =linePath.point1.row *BLOCK_HEIGHT + BOTTOM;

            point[2].x =secondSelect.column *BLOCK_WIDTH + LEFT;

            point[2].y =secondSelect.row *BLOCK_HEIGHT + BOTTOM;

           CGPathAddLines(myPath,NULL, point,3);

        }else{

           CGPoint point[3];

            point[0].x =firstSelect.column *BLOCK_WIDTH + LEFT;

            point[0].y =firstSelect.row *BLOCK_HEIGHT + BOTTOM;

            point[1].x =linePath.point1.column *BLOCK_WIDTH + LEFT;

            point[1].y =linePath.point1.row *BLOCK_HEIGHT + BOTTOM;

            point[2].x =linePath.point2.column *BLOCK_WIDTH + LEFT;

            point[2].y =linePath.point2.row *BLOCK_HEIGHT + BOTTOM;

            point[3].x =secondSelect.column *BLOCK_WIDTH + LEFT;

            point[3].y =secondSelect.row *BLOCK_HEIGHT + BOTTOM;

           CGPathAddLines(myPath,NULL, point,4);

        }

        line.path = myPath;

        line.name =@"line";

        [selfaddChild:line];

        memset(&linePath, -1,sizeof(LinePath));

    }

    #pragma mark -


    @end

  • 相关阅读:
    jQuery学习易忘细节
    mysql关键字与自己设置的字段冲突
    jquery导航栏html页面跳转导航字体变色
    css解决谷歌,360浏览器默认最小字体为12px问题
    ThinkPHP中关于JS文件如何添加类似__PUBLIC__图片路径
    (谷歌浏览器等)解决css中点击input输入框时出现外边框方法【outline:medium;】
    为何在font-family属性中设置多个值
    jquery实现简单的Tab切换菜单
    Thinkphp下嵌套UEditor富文本WEB编辑器
    thinkphp框架下404页面设置
  • 原文地址:https://www.cnblogs.com/pingyunlong/p/3238750.html
Copyright © 2011-2022 走看看