将物理应用到自定义 SKSpriteNode 类

Posted

技术标签:

【中文标题】将物理应用到自定义 SKSpriteNode 类【英文标题】:apply physics to a custom SKSpriteNode class 【发布时间】:2016-12-19 18:18:57 【问题描述】:

我想以更有序和更清晰的方式设置我的 SpriteKit 游戏,因此我决定为每种类型的精灵节点使用类。

在我的例子中,我在 swift 中创建了一个单独的 Player 类,看起来像这样

import SpriteKit

class Player: SKSpriteNode 

func initializePlayer()         
    self.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: self.size.width, height: self.size.height))
    self.physicsBody?.affectedByGravity = true



func moveLeft () 
    print("left")


func moveRight () 
    print("right")
   

我在场景编辑器的自定义类检查器中正确引用了这个 Sprite 节点,我可以毫无问题地触发类方法 - 所以效果很好。

我像这样在我的 GameScene 中引用 Player 类:

class GameplayScene: SKScene    
var player: Player = Player()   
let myNode = SKSpriteNode(imageNamed: "player")   
override func didMove(to view: SKView)        
    player.initializePlayer()           


但是没有应用物理体,我不知道为什么会这样。

在我将物理体添加到精灵节点后,我希望节点会从屏幕上掉下来。但这不会发生,我不知道为什么。

有人知道如何在课堂上应用物理体吗?

【问题讨论】:

你说的物理体没有应用是什么意思? 在我将物理体添加到精灵节点后,我希望节点从屏幕上掉下来。但这不会发生,我不知道为什么。 我在发布的代码中看不到,您只是将物理体添加到 self.更具体并发布更多代码。 @Mina 感谢您的反馈,我更新了我的描述,希望我的问题现在更清楚一点 在调用initializePlayer()之前是否设置了节点的大小?也许物理体的大小是 0x0 并引起了问题? 【参考方案1】:

我可以用 initializePlayer 以外的其他名称调用您的函数,这与实现的代码更相关:

func setPhysics()         
    self.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: self.size.width, height: self.size.height))
    self.physicsBody?.affectedByGravity = true

之后,如果您想从场景编辑器中检索您的精灵,您可以使用:

if let node = self.childNode(withName:"//mySpriteNodeName") as? Player 
            // Set up your sprite here
            node.setPhysics()

P.S.:我还添加了//:这指定搜索应该从根节点开始,并在整个节点树中递归执行。否则,它会从当前位置执行递归搜索。

【讨论】:

感谢您的支持。我尝试了您的方法,但仍然从所需的 init 方法中得到相同的错误。 @Mina 向我推荐的解决方案是我不明白的,我不知道如何解决这个问题。你觉得你可以再看看吗? 在 Mina 代码的第一部分中,她向您解释了如何将 Player 类构建为 SKSpriteNode 子类,但您也可以决定不覆盖 init 方法并构建其他自定义函数离开原始的 init 函数保持不变。【参考方案2】:

问题是你没有在 SKSpriteNode 内置的 init 函数中初始化你的播放器节点。

使用以下代码:

init() 
    let texture = SKTexture(imageNamed: "Spaceship")
    super.init(texture: texture, color: UIColor.blue, size: texture.size())
    self.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: self.size.width, height: self.size.height))
    self.physicsBody?.affectedByGravity = true


required init(coder aDecoder: NSCoder) 
    super.init(coder: aDecoder)
    fatalError("init(coder:) has not been implemented")

代替:

func initializePlayer()         
    self.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: self.size.width, height: self.size.height))
    self.physicsBody?.affectedByGravity = true

它将解决您的问题并正确应用物理体。

【讨论】:

这在我的情况下不起作用。编译器会抛出一个错误:“致命错误:init(coder:) 尚未实现:file / Player.swift 此外,我不需要也不想在启动实例时指定纹理。我想从在 SceneEditor 中。 我已经测试过了,它一定不会出错。但是你可以使用这个thread来解决这个错误。 @Mina 您的代码是正确的,但 OP 遇到该错误,因为 initWIthCoder: 被调用。这是因为他从 .sks 文件加载 Player。 @Whirlwind 这是什么意思?你可以解释吗?我想不出一个解决方案:-/

以上是关于将物理应用到自定义 SKSpriteNode 类的主要内容,如果未能解决你的问题,请参考以下文章

在 SKSpriteNode 中调用自定义方法不起作用

编辑 SKSpriteNode 自定义类的属性?

Xcode7场景编辑器SKSpriteNode自定义类

如何使用该节点的自定义类检测在单独场景中创建的 skspritenode 上的触摸

将纹理应用到线框

我可以将纹理应用到 UIToolbar 吗?