当前位置: 首页 > news >正文

(NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!

大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处.
如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;)


通用的星星类已经完成了,下面我们来实现具体的变长和缩短道具.

变长的反弹棒

我们想实现如下功能:在掉落变长星之后,如果反弹棒接到它,则使反弹棒的长度变为原先的2倍.

看似很简单,但实际有一个问题.你不能仅仅延长反弹棒精灵纹理的长度,因为你在这个游戏中使用的是物理引擎,反弹棒的物理对象的大小是不可以在游戏运行中随意变化的.

所以我们需要想办法延长反弹棒的物理大小,当然同时也要延长其精灵帧的大小,这样才能相互配合达到逼真的延长效果.

这里本猫使用偷梁换柱的方法,用Ai制作一个延长后的反弹棒,并调整它的物理对象适应新的长度,然后在反弹棒需要变长时,用新长棒代替原来的短棒.

首先用Ai制作一个长的反弹棒.然后在SpriteBuilder中创建一个StickLonger.ccb文件,设置好其物理对象的边界:

这里写图片描述

实现变长星道具

回到Xcode中,在Stick类的接口文件中添加一个新属性:

+(instancetype)stickLonger;

在Stick.m中实现该类方法:

+(instancetype)stickLonger{
    Stick *stick = (Stick*)[CCBReader load:@"Elements/StickLonger"];
    stick.name = @"stickLonger";
    return stick;
}

可以看到除了stick对象发生了变化,其名称也和普通的stick有所区别.

回到GameScene.m中在小球与砖块的碰撞处理中添加以下一句:

[Star spawnStar:(Brick*)brick];

接着我们要处理星星和反弹棒接触时的事件:

-(BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair star:(CCNode *)star
                         stick:(CCNode *)stick{
    //star形状是五角星,可能会在短时间内多次发生碰撞;但在star已经由第一次碰撞时删除掉从而导致star为nil
    //所以这里要确保star不为nil.
    //star删除也不能保证其一定为nil,所以增加判断其parent是否为nil.(2015-11-09 2006)
    StarType starType;
    @synchronized(self){
        if (!star || !star.parent) {
            return YES;
        }
        starType = ((Star*)star).starType;
        [star removeFromParentAndCleanup:YES];
    }

    switch (starType) {
        case starTypeStickLonger:
            @synchronized(self){
                [self scheduleBlock:^(CCTimer *timer){
                    [Star doStickLongerWork:self.stickInGameScene];
                } delay:0];
            }
            break;
        case starTypeUnknown:
        case starTypeMax:
            NSAssert(NO, @"error star type!");
            break;
        default:
            break;
    }

    return YES;
}

为什么其中使用了同步伪指令呢?因为其中的代码会改变GameScene中反弹棒的状态,而该状态在GameScene中也可能同时被改变,所以我们需要将其做同步处理.

扩展Star类

最后我们在Star类中添加doStickLongerWork方法:

+(void)doStickLongerWork:(Stick *)stick{

    GameScene *gameScene = [GameScene sharedGameScene];
    CCPhysicsNode *physicsWorld = (CCPhysicsNode*)stick.parent;

    @synchronized(gameScene){
        if ([stick.name isEqualToString:@"stickLonger"]) {
            return;
        }

        if ([stick.name isEqualToString:@"stickShorter"]) {
            Stick *stickNormal = [Stick stickNormal];
            stickNormal.position = stick.position;
            [stick removeFromParent];
            //[physicsWorld removeChild:stick cleanup:YES];
            [physicsWorld addChild:stickNormal];
            gameScene.stickInGameScene = stickNormal;
            return;
        }
    }

    CGPoint position = stick.position;

    __block Stick *stickLonger;

    @synchronized(gameScene){
        stickLonger = [Stick stickLonger];
        //[physicsWorld removeChild:stick cleanup:YES];
        [stick removeFromParent];
        stickLonger.position = position;
        [physicsWorld addChild:stickLonger];
        stickLonger.visible = NO;
        gameScene.stickInGameScene = stickLonger;


        CCSprite *stickNode = (CCSprite*)[CCBReader load:@"Elements/StickNode"];
        stickNode.position = stickLonger.position;
        [gameScene addChild:stickNode z:50];

        CCActionScaleTo *longerAction = [CCActionScaleTo actionWithDuration:0.4f scaleX:2.0f scaleY:1.0f];
        CCActionCallBlock *blk = [CCActionCallBlock actionWithBlock:^{
            [stickNode removeFromParent];
            stickLonger.visible = YES;
        }];
        CCActionSequence *seq = [CCActionSequence actions:longerAction,blk,nil];
        [stickNode runAction:seq];
    }

    [stickLonger scheduleBlock:^(CCTimer *timer){
        @synchronized(gameScene){
            Stick *stickNormal = [Stick stickNormal];
            stickNormal.position = stickLonger.position;
            [stickLonger removeFromParent];
            [physicsWorld addChild:stickNormal];
            gameScene.stickInGameScene = stickNormal;
        }
    } delay:10];
}

你看到以上方法的第一感觉估计是:好长啊!其实内容很好理解,基本上它做了如下几件事:

  • 如果反弹棒已经变长了,则啥也不做返回
  • 如果反弹棒处在变短状态,则恢复其原本大小.这里考虑到了其他可能改变反弹棒的叠加效果.在反弹棒变短的代码逻辑中,我们同样会考虑到这一点.
  • 创建一个变长的反弹棒对象,但暂时将其隐藏,因为我们还想实现一个反弹棒由短变长的动画效果.因为这个动画很短,所以不会影响用户的操控.如果你希望更完美的实现用户操控的连续性,你可以将反弹棒的触摸处理临时”嫁接”到这个临时对象上,当然是有点麻烦,篇幅原因,这里只是点到为止.
  • 在10秒之后将反弹棒恢复为原来大小

变长道具制作完毕,我们现在编译运行app,看一下效果:

这里写图片描述

下一篇将来完成缩小的道具星,see you ;)

相关文章:

  • [转]Java中怎样判断一个字符串能否转成数字
  • JS组件系列——Bootstrap文件上传组件:bootstrap fileinput
  • 来自新浪同学的学习及工作心得
  • Matlab小技巧
  • [转]jmeter实战
  • sudo权限集中管理+日志审计实战
  • 网络安全技术分析
  • hdu 确定比赛名次
  • JS组件系列——Bootstrap Table 表格行拖拽
  • 将字符串转换成uniqueidentifiter类型时出错
  • 小知识~VS2012的xamarin加载失败解决
  • 从盲筹成风 看国内科技企业的喜与忧
  • Hadoop集群应用于大数据分析优势和挑战
  • Angular2组件开发—模板语法(六)
  • ubutun下安装jenkins
  • PHP CLI应用的调试原理
  • PHP面试之三:MySQL数据库
  • React的组件模式
  • Spring核心 Bean的高级装配
  • XML已死 ?
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 如何设计一个微型分布式架构?
  • 什么软件可以提取视频中的音频制作成手机铃声
  • 数组的操作
  • 我是如何设计 Upload 上传组件的
  • 责任链模式的两种实现
  • ​卜东波研究员:高观点下的少儿计算思维
  • !!Dom4j 学习笔记
  • # Swust 12th acm 邀请赛# [ A ] A+B problem [题解]
  • #NOIP 2014# day.2 T2 寻找道路
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (c语言版)滑动窗口 给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • (第30天)二叉树阶段总结
  • (附源码)ssm捐赠救助系统 毕业设计 060945
  • (黑马C++)L06 重载与继承
  • (简单) HDU 2612 Find a way,BFS。
  • (六) ES6 新特性 —— 迭代器(iterator)
  • (十六)Flask之蓝图
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (微服务实战)预付卡平台支付交易系统卡充值业务流程设计
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • (转)scrum常见工具列表
  • ***利用Ms05002溢出找“肉鸡
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .NET Framework .NET Core与 .NET 的区别
  • .NET Remoting Basic(10)-创建不同宿主的客户端与服务器端
  • .NET 使用 ILMerge 合并多个程序集,避免引入额外的依赖
  • .netcore如何运行环境安装到Linux服务器
  • .NET设计模式(7):创建型模式专题总结(Creational Pattern)
  • .net项目IIS、VS 附加进程调试
  • .NET中 MVC 工厂模式浅析