用swift 重写 AgentsCatalog

        AgentsCatalog是Apple的一个例子,他是基于OC的,我认为重写这些例子是个学习语言的好方法。首先,你的目标是正确的,通过观摩源码,你知道如何达到目标,其次你所使用的手段也是正确的,你可以从中学到某个类的用法,几个类的相互关系等等。

       前几天我一直纠结一个事情,我打算把工具条合并到窗口的标题栏上去,就像Safari那样,我查了很多资料一直没能解决,但是这个例子无意间解决了这个问题。而且只有一行代码。你建立一个Cocoa应用,就像下面这样。


@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    @IBOutlet weak var window: NSWindow!

    @IBOutlet weak var skView: SKView!
    @IBOutlet weak var sceneControl: NSSegmentedControl!

    @IBAction func selectScene(sender: NSSegmentedControl) {
        
        let sceneTYpe = AAPLSceneType(rawValue: sender.selectedSegment)
        let scene = AAPLGameScene.sceneWithType( sceneTYpe!, size: CGSizeMake(800, 600))
        scene.scaleMode = SKSceneScaleMode.AspectFit
        self.skView.presentScene(scene)
    }
    
    func applicationDidFinishLaunching(aNotification: NSNotification) {
        // Insert code here to initialize your application
        self.window.titleVisibility  = NSWindowTitleVisibility.Hidden
        
        // Configure the view.
        self.skView.ignoresSiblingOrder = true
        self.skView.showsFPS = true
        self.skView.showsNodeCount = true
        
        // Present the scene.
        self.selectScene(self.sceneControl )
    }

    func applicationWillTerminate(aNotification: NSNotification) {
        // Insert code here to tear down your application
    }

你的工具条就合并到window标题栏上去了。其他什么也不用做。接下来你要重写下面这个类:

这是所有后面用到的 Scene 类基类,他本身是SKSence的子类。你会看到 SKComponentSystem(组件系统)和 GKAgent2D(跟踪代理)的用法。这里处理了游戏事件循环和对鼠标的响应。

import Cocoa
import SpriteKit
import GameplayKit

enum AAPLSceneType: Int {
    case AAPLSceneTypeSeek = 0,
    AAPLSceneTypeWander,
    AAPLSceneTypeFlee,
    AAPLSceneTypeAvoid,
    AAPLSceneTypeSeparate,
    AAPLSceneTypeAlign,
    AAPLSceneTypeFlock,
    AAPLSceneTypePath,
    
    AAPLSceneTypesCount
}

let AAPLDefaultAgentRadius: CGFloat = 40.0

class AAPLGameScene: SKScene {
    var sceneName: String?
    
    required override init(size: CGSize) {
        super.init(size: size)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // A component system to manage per-frame updates for all agents.
    var agentSystem: GKComponentSystem?
    
    // An agent whose position tracks that of mouseDragged (OS X) or touchesMoved (iOS) events.
    // This agent has no display representation, but can be used to make other agents follow the mouse/touch.
    var trackingAgent: GKAgent2D?
    
    // YES when the mouse is dragging (OS X) or a touch is moving
    var seeking: Bool =  false
    
    var stopGoal: GKGoal?
    
    var lastUpdateTime: NSTimeInterval = 0
    
    class func sceneWithType( sceneType: AAPLSceneType, size: CGSize) -> AAPLGameScene {
        
        var sceneClass: AAPLGameScene.Type
        
        switch (sceneType) {
        case AAPLSceneType.AAPLSceneTypeSeek:
            sceneClass = AAPLSeekScene.self
            break;
            
        case AAPLSceneType.AAPLSceneTypeWander:
            sceneClass = AAPLWanderScene.self
            break;
            
        case AAPLSceneType.AAPLSceneTypeFlee:
            sceneClass = AAPLFleeScene.self
            break;
            
        case AAPLSceneType.AAPLSceneTypeAvoid:
            sceneClass = AAPLAvoidScene.self
            break;
            
        case AAPLSceneType.AAPLSceneTypeSeparate:
            sceneClass = AAPLSeparateScene.self
            break;
            
        case AAPLSceneType.AAPLSceneTypeAlign:
            sceneClass = AAPLAlignScene.self
            break;
            
        case AAPLSceneType.AAPLSceneTypeFlock:
            sceneClass = AAPLFlockScene.self
            break;
            
        case AAPLSceneType.AAPLSceneTypePath:
            sceneClass = AAPLPathScene.self
            break;
            
        default:
            sceneClass = AAPLGameScene.self
            break;
        }
        return sceneClass.init(size: CGSizeMake(800, 600))
    }
    
    
    override func didMoveToView(view: SKView) {
        self.agentSystem = GKComponentSystem( componentClass: GKAgent2D.self )
        self.trackingAgent = GKAgent2D()
        
        let x = CGRectGetMidX(self.frame)
        let y = CGRectGetMidY(self.frame)
        self.trackingAgent!.position = vector_float2( Float(x) , Float(y))
      }
    
    
    override func update(currentTime: NSTimeInterval) {
        // Calculate delta since last update and pass along to the agent system.
        if (lastUpdateTime == 0) {
            lastUpdateTime = currentTime;
        }
        
        let  delta = currentTime - lastUpdateTime
        lastUpdateTime = currentTime
        self.agentSystem!.updateWithDeltaTime( delta )
    }
    
    override func mouseDown(theEvent: NSEvent) {
        self.seeking = true
    }
    override func mouseUp(theEvent: NSEvent) {
        self.seeking = false
    }
    override func mouseDragged(theEvent: NSEvent) {
        let position = theEvent.locationInNode(self)
        self.trackingAgent!.position = vector_float2 (Float(position.x), Float(position.y))
    }
}


下面的代码用于建立一个游戏节点,其实就是一个游戏对象,这里是一条小船。它由一个圆形和一个三角形构成,还添加了粒子水泡。
import Cocoa
import SpriteKit
import GameplayKit


class AAPLAgentNode: SKNode, GKAgentDelegate{
    
    var agent = GKAgent2D()
    var color: SKColor = SKColor.highlightColor()
    var drawsTrail: Bool = false
    var triangleShape: SKShapeNode!
    var particles: SKEmitterNode!
    var defaultParticleRate: CGFloat = 0
    
    
    init( scene: SKScene, radius: CGFloat, position: CGPoint ){
         super.init()
        self.position = position;
        self.zPosition = 10;
        scene.addChild(self)
        // An agent to manage the movement of this node in a scene.
        agent = GKAgent2D()
        agent.radius = Float(radius)
        agent.position = (vector_float2)( Float(position.x), Float(position.y))
        agent.delegate = self;
        agent.maxSpeed = 100;
        agent.maxAcceleration = 50;

        // A circle to represent the agent's radius in the agent simulation.
        let circleShape = SKShapeNode(circleOfRadius: radius)
        circleShape.lineWidth = 2.5
        circleShape.fillColor = SKColor.grayColor()
        circleShape.zPosition = 1
        self.addChild(circleShape)
        
        // A triangle to represent the agent's heading (rotation) in the agent simulation.
        var points = Array(count: 4, repeatedValue: CGPoint())
        let triangleBackSideAngle = CGFloat((135.0 / 360.0) * (2 * M_PI))
        points[0] = CGPointMake(radius,0); // Tip.
        points[1] = CGPointMake(radius * cos(triangleBackSideAngle), radius * sin(triangleBackSideAngle)); // Back bottom.
        points[2] = CGPointMake(radius * cos(triangleBackSideAngle), -radius * sin(triangleBackSideAngle)); // Back top.
        points[3] = CGPointMake(radius, 0); // Back top.
        
        let triangleShape = SKShapeNode(points: &points, count: 4)
        triangleShape.lineWidth = 2.5;
        triangleShape.zPosition = 1;
        self.addChild( triangleShape)
        
        // A particle effect to leave a trail behind the agent as it moves through the scene.
        particles = SKEmitterNode(fileNamed: "Trail.sks")
        defaultParticleRate = particles!.particleBirthRate;
        particles!.position = CGPointMake(-radius + 5, 0);
        particles!.targetNode = scene;
        particles!.zPosition = 0;
        self.addChild( particles!)
        
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    

    // GKAgentDelegate
    func agentWillUpdate(agent: GKAgent){
        
    }
    
    /*
    * Called after [GKAgent updateWithDeltaTime:] is called each frame.
    */
 
    func agentDidUpdate(agent: GKAgent){
        // Agent and sprite use the same coordinate system (in this app),
        // so just convert vector_float2 position to CGPoint.
        let agent2D = agent as! GKAgent2D
        self.position = CGPointMake( CGFloat(agent2D.position.x), CGFloat(agent2D.position.y))
        self.zRotation = CGFloat(agent2D.rotation)
    }
}


这个例子用了八个子类演示 跟踪代理的不同用法。我门这里只做了一个:

//
//  AAPLWanderScene.swift
//  TestAgents
//
//  Created by wuzhiqiang on 15/11/14.
//  Copyright © 2015年 wuzhiqiang. All rights reserved.
//

import Cocoa
import SpriteKit
import GameplayKit

class AAPLWanderScene: AAPLGameScene {

    override func didMoveToView(view: SKView) {
        super.didMoveToView(view)
        
        let pt = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
        
        
        let wanderer = AAPLAgentNode( scene: self, radius: 40, position: pt )
        wanderer.color = SKColor.cyanColor()
        wanderer.agent.behavior = GKBehavior( goal: GKGoal( toWander:10), weight: 100)
        self.agentSystem!.addComponent( wanderer.agent)
     }
}

下面我们来描述一下程序的工作过程。

在AppDelegate里面,我们建立一个Scence,8个中的一个,这里是AAPLWanderScene,漫游型。

这个  AAPLWanderScene 建立一个自己的 Node (一艘船),然后建立并将  GKBehavior 对象赋给了 节点的agent.behavior 属性。

最后,将这个节点作为一个组件加入到组件系统。

就是这样。程序就会运行,组件系统会工作,定时循环更新他的每个组件。你的小船会自动出发漫游。

在节点里,甚至还加入了粒子效果,你能看到小船后面的水泡。









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值