Create \(Use) SKView as \(in a) factory \(static class)

≯℡__Kan透↙ 提交于 2019-12-29 08:26:17

问题


I want to make an SKView I can use as a factory to make SKShapeNodes and "render" them to textures.

But I can't find how I would initialise such a thing, and am having no luck, at all.

How do I make a standalone SKView for this purpose?

Or is there a better way to do this that avoids using the gamescene?

Here's my FUTILE Effort at making a factory, this complains that texture(from: ) is ambiguous. I have no idea what that means.

import SpriteKit

class Make: SKView{

static func circle() -> SKSpriteNode {
    let myShapeNode = SKShapeNode(circleOfRadius: 100)
    myShapeNode.fillColor = SKColor.lightGray
    myShapeNode.strokeColor = SKColor.gray
    let tex = texture(from: myShapeNode)
    return SKSpriteNode(texture: tex)
    }

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
    }   
}

Update

After more futile time on google, I tried searching for initialisation of a UIView, and found and added this piece of code, that initialises to a frame that seems imaginary... but it works! I don't know why... but I can't use it as a factory method, only as an instance method, this way:

import Foundation
import SpriteKit

class Make: SKView{

    // added randomly found UIView initialisation "code"...
    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    func circle() -> SKSpriteNode {
        let myShapeNode = SKShapeNode(circleOfRadius: 100)
        myShapeNode.fillColor = SKColor.lightGray
        myShapeNode.strokeColor = SKColor.gray
        let tex = texture(from: myShapeNode)
        return SKSpriteNode(texture: tex)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

回答1:


It's not quite clear what you mean by "how I would initialise such a thing". How is dependent upon technique and what the factory does overall. Some factories do not need external input for initialization while others do. Here is are a couple of really crude examples. These are perhaps overly simplistic and have not been tested at all.

One uses the concept of a static class whilst the other is a singleton. None of this is to serve as "this is better than that". Nor is it to open Pandora's Box on which is better, etc. There are other threads which go over those details. Rather they are just a couple of approaches to get you going.

Here is a static class version

// static class version
class SpriteFactory1 {
    private static let view:SKView = SKView()

    static func spriteFromShape(shape:SKShapeNode) -> SKSpriteNode? {
        guard let tex = view.texture(from:shape) else {
            return nil
        }

        return SKSpriteNode(texture:tex)
    }
}

Here is a singleton version. Adding your circle code from above ...

// singleton version
class SpriteFactory2 {
    static let sharedInstance = SpriteFactory2()

    private let view:SKView = SKView()

    func spriteFromShape(shape:SKShapeNode) -> SKSpriteNode? {
        guard let tex = view.texture(from:shape) else {
            return nil
        }

        return SKSpriteNode(texture:tex)
    }

    func circle() -> SKSpriteNode {
        let myShapeNode = SKShapeNode(circleOfRadius: 100)
        myShapeNode.fillColor = SKColor.lightGray
        myShapeNode.strokeColor = SKColor.gray
        let tex = texture(from: myShapeNode)
        return SKSpriteNode(texture: tex)
    }
}

You'll also note the code is more or less the same. However in the case of the static, the class variables must be static as well.

Usage would look something like:

// Test shape
let shape = SKShapeNode()
// Pretend shape is constructed as desired

let sprite1 = SpriteFactory1.spriteFromShape(shape: shape)    
let sprite2 = SpriteFactory2.sharedInstance.spriteFromShape(shape: shape)
let circle = SpriteFactory2.sharedInstance.circle()



回答2:


(Posted on behalf of the OP).

Problem solved!

For those of you that understand coding better than I, the following commentary is not for you. It's for all the fools and aspiring tools, like me.

Thanks to the wondrous patience and mine of knowledge that is @MobileBen, I am able to do exactly as desired, ie have a factory for creating SKShapeNodes from anywhere in the project, via an SKView instance in a Static Class of no type, whose only purpose is to be this factory.

  1. A class can have no superclass or inheritance in Swift. This means it's possible to make perfectly isolated Class files that have no purpose other than to store functionality and properties for universal access within a project.

  2. This is somewhat considered "wrong" in OOP programming, but from a conception and usage point, and the urgency of getting things done neatly and easily to find and read, it's invaluable, in my NAIVE opinion.

  3. Despite SKView being an intimidatingly high class within the UIKit world, it's possible to simply make an instance of an otherwise unused and unrecognised SKView within a static class for the purposes of exploiting its functionality

  4. The resulting usage is elegant and simple, thanks to MobileBen, like this:

a factory, with completely incorrect use of capitals for the naming, so I can instantly see it in code:

import SpriteKit

class MAKE {

private static let view:SKView = SKView()

static func circle(radius: CGFloat) -> SKSpriteNode {
    let myShapeNode = SKShapeNode(circleOfRadius: radius)
    myShapeNode.fillColor = SKColor.lightGray
    myShapeNode.strokeColor = SKColor.gray
    let tex = view.texture(from: myShapeNode)
    return SKSpriteNode(texture: tex)
    }
}

With this in the project, from within just about any other part of the project, the following creates a circle and stores it in myCircle:

let myCircle = MAKE.circle(radius: 50)


来源:https://stackoverflow.com/questions/40084701/create-use-skview-as-in-a-factory-static-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!