美文网首页程序员iOS Developer
贪吃蛇游戏(三)——定义蛇

贪吃蛇游戏(三)——定义蛇

作者: littlersmall | 来源:发表于2016-02-06 20:46 被阅读791次

    接上篇

    http://www.jianshu.com/p/e0c8afa3d512

    本节目标:
    定义我们游戏的主角:贪吃蛇。
    在上一节里,我们完成了食物的定义,虽然还很粗糙,但基本的功能已经完成了,本节则完成蛇的定义。

    1 定义蛇的组成(bodyItem)
    我们知道在贪吃蛇游戏中,蛇是一段一段的,换句话说:蛇是一段段身体组成的,因此,我们需要先定义『段』作为蛇的基本构成。
    点击file->new->file 选择Swift file,点击next, Save as ListBodyItem



    在左侧找到ListBodyItem.swift,并点击。
    在编辑区添加如下代码:

    import UIKit
    
    class ListBodyItem: UIButton {
        override init(frame: CGRect) {
            super.init(frame: frame)
            backgroundColor = UIColor.redColor()
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    

    有了bodyIItem的雏形还不够,我们需要继续完善。
    在贪吃蛇游戏里,蛇的身体的每一段之间是有联系的。当蛇在运动的时候,每走一步,都是后面一段将自己的位置更新为前一段的位置,是一个明显的传递过程。从代码的角度来说,每一个bodyIItem,都有一个后继(除了蛇的尾部),当自己更新的时候,同时更新自己的后继,将这个移动的过程传递下去。而swift由于有属性重载这样的功能,可以将这个传递的过程实现的很简单,在ListBodyItem的init之前加入如下代码:

    override var frame: CGRect {
        set {
            if let next = nextItem {
                next.frame.origin = frame.origin
            }
    
            super.frame.origin = newValue.origin
        }
            
        get {
            return super.frame
        }
    }
        
    var nextItem: ListBodyItem?
    

    现在,当蛇头运动时,后续的body将自动跟随头部运动。

    2 定义蛇头和蛇的身体
    有了bodyItem的定义之后,我们可以自然而然的定义蛇头,它继承自bodyItme,请在ListBodyItem定义的后面加入如下代码:

    class SnakeHead: ListBodyItem {
        init() {
            super.init(frame: CGRect(x: 90, y: 90, width: 30, height: 30))
        }
        
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    

    单独将蛇头抽象出来是因为蛇头这里有一些单独的逻辑,比如方向,比如吃食物事件的触发等等。
    我们继续在SnakeHead的定义后面定义蛇的身体,蛇的身体是多个bodyIItem的组合,我们使用一个数组来表示,代码如下:

    class SnakeBody {
        var bodys = [ListBodyItem]()
        
        //初始化身体时只有一段
        init() {
            bodys.append(conBody(CGRect(x: 60, y: 90, width: 30, height: 30)))
        }
        
        //为蛇添加一段(完成一次吃食后调用)
        func addOne(view: UIView) {
            let curLast = bodys.last!
            
            bodys.append(conBody(curLast.frame))
            curLast.nextItem = bodys.last
            
            view.addSubview(bodys.last!)
        }
        
        //构造一个bodyItem
        func conBody(frame: CGRect) -> ListBodyItem {
            let body = ListBodyItem(frame: frame)
            
            return body
        }
    }
    

    当蛇成功的吃掉一个食物时,将会触发addOne操作。

    3 完整的定义蛇
    有了蛇头和蛇身体的定义后,我们可以完成蛇的定义了。点击左上角的file->new->file,选择Swift file,点击next,在Save as那里输入Snake,然后在编辑区输入如下代码:

    import UIKit
    
    class Snake {
        let head = SnakeHead()
        let body = SnakeBody()
        //保存弱引用,避免互相引用引起的内存泄露
        weak var mainView: UIView!
        
        init(view: UIView) {
            mainView = view
            head.nextItem = body.bodys[0]
                  
            view.addSubview(head)
            view.addSubview(body.bodys[0])
        }
    }
    

    然后我们在SnakeViewController中增加对Snake的引用。
    点击左侧的SnakeViewController.swift



    在var food: Food!下添加

    var snake: Snake!
    

    并在food = Food(view: view)下添加

    snake = Snake(view: view)
    

    之后点击左上角的运行,如果一步一步操作正常,将在模拟器中显示出如下画面:



    红色部分,就是我们的贪吃蛇了,目前看还很粗糙,而且不会动。没关系,后续我们一步步的完善它。

    4 让蛇动起来
    为了让我们的小蛇能动起来,我们需要增加一个定时器,每隔0.5秒定时器触发,当定时器触发时,我们修改蛇头的坐标,从而完成蛇的运动。在左侧选择SnakeViewController.swift,在var snake: Snake!上边添加代码:

    var time: NSTimer!
    

    这样定义了一个定时器。
    之后我们再定义一个定时器触发时的执行函数。在viewDidLoad定义下面添加如下代码:

    func walk() {
        snake.walk()
    }
    

    然后在viewDidLoad中完成定时器的注册任务,在snake = Snake(view: view)下面添加如下代码:

    timer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: Selector("walk"), userInfo: nil, repeats: true)
    

    目前,SnakeViewController的代码如下:

    import UIKit
    
    class SnakeViewController: UIViewController {
        var timer: NSTimer
        var food: Food!
        var snake: Snake!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            
            //初始化food
            food = Food(view: view)
            snake = Snake(view: view)
            timer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: Selector("walk"), userInfo: nil, repeats: true)
        }
        
        func walk() {
            snake.walk()
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    }
    

    万事俱备,只差在snake中实现walk方法了。
    请在导航左侧找到Snake.swift,并单击:



    在init函数后添加如下代码:

    func walk() {
        //临时代码,后续会修改
        head.frame.origin.x += 30.0
    }
    

    每次触发时修改head的横坐标。(只是暂时这样,后续会有方向的添加等等)
    现在,Snake.swift的代码如下:

    import UIKit
    
    class Snake {
        let head = SnakeHead()
        let body = SnakeBody()
        //保存弱引用,避免互相引用引起的内存泄露
        weak var mainView: UIView!
        
        init(view: UIView) {
            mainView = view
            head.nextItem = body.bodys[0]
            
            
            view.addSubview(head)
            view.addSubview(body.bodys[0])
        }
        
        func walk() {
            head.frame.origin.x += 30.0
        }
    }
    

    点击左上角的运行,我们看到「可爱」的红色小蛇动了起来。


    walk.gif

    相关文章

      网友评论

        本文标题:贪吃蛇游戏(三)——定义蛇

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