美文网首页iOS Developer
SpriteKit 如何用精灵制作按钮

SpriteKit 如何用精灵制作按钮

作者: 遮住眼睛的草纸 | 来源:发表于2018-04-25 20:25 被阅读77次

    前言

        前段时间,在知乎看到一个回答,iOS开发以及被玩的差不多了,只有SpriteKit,SceneKit这两个难兄难弟还没有被“开发”。确实,毕竟做手游,有unity,虚幻等,谁用这玩意。。
        随着ARKIT的发布,SpriteKit和SceneKit渐渐重回视野。最近研究了一下SpriteKit。用下来还是觉得很鸡肋。可以说是要啥没啥。啥轮子都没,都得自己做。没办法,毕竟也不是专门做游戏的,这样子也不错了。
        言归正传。在你兴致勃勃的,准备制作一个菜单界面的时候。你习惯性找一个按钮。UIButton扔进去?显然不可行啊。浏览一圈,居然没有可以用的Button。WTF?
        OK,没有,那咱自己做呗。造轮子什么的我最擅长了。

    预览

    按钮可以设置不同的点击颜色,和文字颜色,但是暂不支持图片。


    button.gif

    讲解

    先上代码

    //
    //  MeCustomButton.swift
    //  mng
    //
    //  Created by WTFKL on 2018/4/16.
    //  Copyright © 2018年 WTF. All rights reserved.
    //
    
    import SpriteKit
    import UIKit
    class MeCustomButton: SKSpriteNode{
        /**
             在创建完成后,调用touchUpInside方法来触发点击事件
         */
        private var m_ButtonLabel : SKLabelNode?;
        private var border : SKShapeNode?;
    
        //边框颜色
        public var borderColor : SKColor = SKColor.yellow{
            didSet{
                border?.strokeColor = borderColor;
            }
        };
        //按钮背景颜色
        public var m_BackgroundColor : SKColor = SKColor.white{
            didSet{
                border?.fillColor = m_BackgroundColor;
            }
        };
        //按钮文字
        public var m_LabelText : String = "Label"{
            didSet{
                m_ButtonLabel?.text = m_LabelText;
            }
        };
        //按钮字体颜色
        public var m_fontColor : SKColor = .black{
            didSet{
                m_ButtonLabel?.fontColor = m_fontColor;
            }
        };
        //按钮边框宽度
        public var m_borderLineWidth:CGFloat = 1{
            didSet{
                border?.lineWidth = m_borderLineWidth;
            }
        }
        
        //按钮文字字体
        public var m_FontName : String = ""{
            didSet{
                m_ButtonLabel?.fontName = m_FontName;
            }
        }
        //按钮文字尺寸
        public var m_FontSize : CGFloat = 20 {
            didSet{
                m_ButtonLabel?.fontSize = m_FontSize;
            }
        }
        
        public var clickEvent = {};
        
    
        convenience init(btnName : String,btnSize:CGSize,btnCornerRadius:CGFloat) {
            self.init(color: .clear, size: btnSize);
            self.color = .clear;
            self.name = btnName;
            let location = CGRect(x: -self.frame.size.width/2, y:-self.frame.size.height/2 , width: self.frame.size.width, height: self.frame.size.height);
            border = SKShapeNode(rect: location, cornerRadius: btnCornerRadius);
            border!.fillColor = m_BackgroundColor;
            border?.lineWidth = m_borderLineWidth;
            border?.strokeColor = borderColor;
            self.addChild(border!);
            
            m_ButtonLabel = SKLabelNode(text: m_LabelText);
            m_ButtonLabel?.position = CGPoint(x: 0, y: -((m_ButtonLabel?.frame.size.height)!/2));
            m_ButtonLabel?.fontColor = m_fontColor;
            m_ButtonLabel?.fontName = m_FontName;
            m_ButtonLabel?.fontSize = m_FontSize;
            self.addChild(m_ButtonLabel!);
        }
        
        public func touchUpInside(highLightBGColor:SKColor,highLightFontColor:SKColor){
            let oldBGColor = self.m_BackgroundColor;
            let oldFontColor = self.m_fontColor;
            self.m_BackgroundColor = highLightBGColor;
            self.m_fontColor = highLightFontColor;
            let waitTime = SKAction.wait(forDuration: 0.05);
            let bgcolor = SKAction.run {
                self.m_BackgroundColor = oldBGColor;
                self.m_fontColor = oldFontColor;
            }
            self.run(SKAction.sequence([waitTime,bgcolor]));
            clickEvent();
        }
        
        
        
    }
    
    
    首先是属性
     private var m_ButtonLabel : SKLabelNode?;
        private var border : SKShapeNode?;
    
        //边框颜色
        public var borderColor : SKColor = SKColor.yellow{
            didSet{
                border?.strokeColor = borderColor;
            }
        };
        //按钮背景颜色
        public var m_BackgroundColor : SKColor = SKColor.white{
            didSet{
                border?.fillColor = m_BackgroundColor;
            }
        };
        //按钮文字
        public var m_LabelText : String = "Label"{
            didSet{
                m_ButtonLabel?.text = m_LabelText;
            }
        };
        //按钮字体颜色
        public var m_fontColor : SKColor = .black{
            didSet{
                m_ButtonLabel?.fontColor = m_fontColor;
            }
        };
        //按钮边框宽度
        public var m_borderLineWidth:CGFloat = 1{
            didSet{
                border?.lineWidth = m_borderLineWidth;
            }
        }
        
        //按钮文字字体
        public var m_FontName : String = ""{
            didSet{
                m_ButtonLabel?.fontName = m_FontName;
            }
        }
        //按钮文字尺寸
        public var m_FontSize : CGFloat = 20 {
            didSet{
                m_ButtonLabel?.fontSize = m_FontSize;
            }
        }
        public var clickEvent = {};//点击事件
    

    一目了然,重写了set方法,因为后面要随时更改这些属性。swift重写set方法也是比较奇葩的。重点提一下

    public var clickEvent = {}
    

    这个传递了一个闭包,将点击事件传递进来,方便调用。
    其他这段基本都写注释了。我就不多嘴了。

    其次是便利构造方法
     convenience init(btnName : String,btnSize:CGSize,btnCornerRadius:CGFloat) {
            self.init(color: .clear, size: btnSize);
            self.color = .clear;
            self.name = btnName;
            let location = CGRect(x: -self.frame.size.width/2, y:-self.frame.size.height/2 , width: self.frame.size.width, height: self.frame.size.height);
            border = SKShapeNode(rect: location, cornerRadius: btnCornerRadius);//设置圆角
            border!.fillColor = m_BackgroundColor;//填充色
            border?.lineWidth = m_borderLineWidth;//边框宽度
            border?.strokeColor = borderColor;//边框颜色
            self.addChild(border!);
            
            m_ButtonLabel = SKLabelNode(text: m_LabelText);//添加文字label
            m_ButtonLabel?.position = CGPoint(x: 0, y: -((m_ButtonLabel?.frame.size.height)!/2));//尺寸
            m_ButtonLabel?.fontColor = m_fontColor;//字体颜色
            m_ButtonLabel?.fontName = m_FontName;//字体
            m_ButtonLabel?.fontSize = m_FontSize;//字体尺寸
            self.addChild(m_ButtonLabel!);
        }
    

    便利构造方法常规写法,附上默认数值属性。
    border使用了SKShapeNode,在自身周围画出边框。

    再者就是点击事件方法
     public func touchUpInside(highLightBGColor:SKColor,highLightFontColor:SKColor){//传入高亮背景色,高亮文字颜色
            let oldBGColor = self.m_BackgroundColor;//保存原本的颜色
            let oldFontColor = self.m_fontColor;//保存原本的文字颜色
            self.m_BackgroundColor = highLightBGColor;//把传入的高亮颜色赋值
            self.m_fontColor = highLightFontColor;//把传入的高亮颜色赋值
            let waitTime = SKAction.wait(forDuration: 0.05);//按钮等待时间
            let bgcolor = SKAction.run {//动画
                self.m_BackgroundColor = oldBGColor;
                self.m_fontColor = oldFontColor;
            }
            self.run(SKAction.sequence([waitTime,bgcolor]));//运行动画
            clickEvent();//调用闭包点击事件
        }
    

    这里就必须重点提一下了。因为按钮点击最好是有反馈。所以,运用SKSpritekit的动画特性,用SKAction的wait,来等待0.5s,来模拟按钮反馈。这是最关键的。

    CustomButton类就完成了

    如何使用这个类?

         //便利构造方法,初始化出一个100*50的button,带弧度为5的边框
          startButton = MeCustomButton(btnName: "start", btnSize:CGSize(width: 100, height: 50) , btnCornerRadius: 5);
            startButton?.position = CGPoint(x: 0, y: 5);//button的位置
            startButton?.m_fontColor = .white;//文字颜色默认为白色
            startButton?.m_BackgroundColor = .clear;//背景色为透明
            startButton?.m_FontName = "GB18030Bitmap";//设置字体,然而手机没这个字体,可以忽略
            startButton?.m_LabelText = "开始";//设置文字
            startButton?.m_FontSize = 35;//设置文字尺寸
            startButton?.borderColor = .white;//设置文字颜色
            startButton?.m_borderLineWidth = 1;//边框宽度
            startButton?.clickEvent = {//设置点击事件
                let firstScene = SKScene(fileNamed: "Third")!//这里我点击跳转第三个场景
                self.view?.presentScene(firstScene,transition: SKTransition.crossFade(withDuration: 0.5));
            };
            self.addChild(startButton!);//场景添加按钮
    

    常规设置属性,点击事件也一目了然,不多说。

    注意

      override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            for t in touches {
                let location = t.location(in: self);
                
                let mnode = nodes(at: location);
                
                for nnode in mnode{
                    let na = nnode as? MeCustomButton;
                    if(na?.name == "instructions"){
                        instructions?.touchUpInside(highLightBGColor: .white, highLightFontColor: .black);
                    }else if(na?.name == "start"){
                        startButton?.touchUpInside(highLightBGColor: .white, highLightFontColor: .black);
                    }
                }
            }
        }
    

    与通常button不同的是,我们必须通过触摸事件来判断,你点的是哪个精灵。touchesBegan用法和常规也一样,找出你的精灵后,调用touchUpInside方法,传入你想要的高亮颜色。这时候,你的button就算是完成了。

    总结

        怎么样,造轮子也挺不错的。我个人觉得还是没有完全把这个方法抽好,还是很麻烦。而且不支持图片,等过段时间有空了,把这个方法在完善一下,支持图片,方法命名什么的都根据UIButton来。各位看官,也试试看吧,喜欢给个赞哦。有问题请小心翼翼指出,心理承受能力弱,哈哈。预告一下,之后几天,会写一篇完整的swift游戏开发文章。

    相关文章

      网友评论

        本文标题:SpriteKit 如何用精灵制作按钮

        本文链接:https://www.haomeiwen.com/subject/rmoylftx.html