如何解决即使速度为0,SKPhysicsBody也会移动
我已经用32x32方形png搭建了一个迷宫,并且将SKPhysicsBody应用于它们,目的是阻止玩家穿过它们(此处未显示玩家)
由于某些奇怪的原因,迷宫中的某些正方形以非常小的速度移动(坐标在变化,并且它们在屏幕上缓慢移动),但是它们的SKPhysicsBody.veLocity在两个轴上均为0
为了弄清楚这一点,我设置了一些最小化可重现环境的代码,该代码突出显示了蓝色移动的正方形。代码在这篇文章的底部
- 允许您使用键盘上的箭头键在屏幕上移动整个迷宫...这将导致突出显示的正方形发生变化,并且这样做时会有一些奇怪的图案
- 允许您单击任何正方形,以便在控制台中输入其位置和速度...蓝色正方形的位置在不断变化,但速度为0
事实
- 注释掉brokenTile中的SKPhysicsBody声明会导致问题消失,但是由于我希望进行碰撞检测,所以这对我来说不是合适的解决方案
- 使用箭头键移动迷宫时,它会更改哪些正方形组为蓝色,但似乎有图案。它始终是蓝色的整个行或列,有时两者都是蓝色。
- 即使最初生成迷宫时,白色方块也不是它们的理想坐标,并且在沉降之前会稍有移动(由于brokenWorld.load中的大小设置,该距离可能是34的倍数)
任何人都知道,即使速度为0,是什么导致蓝色方块以极少量移动?
edit :我尝试向SKSpriteNode添加扩展名,以在spritenode更改时提醒我。我已经确认更改位置内部的x会导致willSet触发,但是似乎仅在我的代码直接更改值时触发。当由于任何未知的过程导致位置移动而改变位置时,是否由于某些原因而不触发?我希望在此处放置一个断点以获得一个堆栈,该堆栈可以准确告诉我更改的来源
extension SKSpriteNode {
open override var position: CGPoint {
willSet {
print("Position of \(self) will change to: \(newValue)")
}
}
}
import SpriteKit
import GameplayKit
import Carbon.HIToolBox.Events // kVK
class IssuePhysics: SKScene,SKPhysicsContactDelegate {
static var instance: IssuePhysics?
var world = brokenWorld()
var keys = [Int: Bool]()
override func didMove(to view: SKView) {
IssuePhysics.instance = self
let O = "e"
let X = "b"
// Load Map
let map = [
[O,X,X],[X,O,X]
]
world.load(map: map)
addChild(world)
world.position = CGPoint(x: 50,y: 50)
}
override func mouseDown(with event: NSEvent) {
// Get mouse position in scene coordinates
let location = event.location(in: self)
// Get node at mouse position
let node = self.atPoint(location)
print((node.name ?? "empty") + ": " + node.position.debugDescription)
print((node.physicsBody?.veLocity.debugDescription) as Any)
}
override func keyDown(with event: NSEvent) {
keys[Int(event.keyCode)] = true
}
override func keyUp(with event: NSEvent) {
keys[Int(event.keyCode)] = false
}
override func update(_ currentTime: TimeInterval) {
world.update(keys: keys)
}
}
class brokenWorld : SKNode {
static var instance: brokenWorld?
var coords = [[brokenTile]]()
static let squareSize = 32
var tile_templates = [String: brokenTile]()
override init(){
super.init()
brokenWorld.instance = self
self.name = "world"
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func load(map: [[String]]){
var tile = brokenTile()
tile_templates["e"] = tile // register empty tile
tile = brokenTile(imageNamed: "Blocker")
tile.initPhysics()
tile_templates["b"] = tile // register standard white tile
let size = 34 // deliberately higher than 32 so that each square in the maze is clearly visible
self.coords = Array(repeating: Array(repeating: brokenTile(),count: map.count),count: map[0].count)
for y in 0...map.count-1 {
for x in 0...map[y].count-1 {
let tile_tmp = tile_templates[map[y][x]]!.clone()
tile_tmp.position = CGPoint(x: x*size,y: y*size)
self.coords[x][y] = tile_tmp
self.addChild(self.coords[x][y])
}
}
}
func update(keys: [Int: Bool]){
for row in self.coords {
for tile in row {
tile.update(keys: keys)
}
}
if keys[kVK_LeftArrow] ?? false {
self.position.x -= 10
} else if keys[kVK_RightArrow] ?? false {
self.position.x += 10
} else if keys[kVK_UpArrow] ?? false {
self.position.y += 10
} else if keys[kVK_DownArrow] ?? false {
self.position.y -= 10
}
}
}
class brokenTile : SKSpriteNode {
var imageName: String = "empty"
var lastPosition: CGPoint = CGPoint(x: 0,y: 0)
var changeTimer = 0
init(imageNamed: String){
let texture = SKTexture(imageNamed: imageNamed)
self.imageName = imageNamed
super.init(texture: texture,color: SKColor.clear,size: texture.size())
self.colorBlendFactor = 1.0
self.name = "tile"
}
init(){
super.init(texture: nil,size: CGSize(width: 32,height: 32))
self.name = "tile"
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func initPhysics(){
// commenting out next two lines resolves the problem,but then collission cannot be enabled,so that is not a satisfactory solution
self.physicsBody = SKPhysicsBody(rectangleOf: self.size)
self.physicsBody!.isDynamic = false
}
func update(keys: [Int: Bool]){
if self.lastPosition.x != self.position.x || self.lastPosition.y != self.position.y {
self.lastPosition.x = self.position.x
self.lastPosition.y = self.position.y
changeTimer = 1
}
if self.imageName == "Blocker" {
if changeTimer > 0 {
self.color = SKColor.blue
changeTimer -= 1
} else {
self.color = SKColor.white
}
}
}
func clone() -> brokenTile {
let clone = self.copy() as! brokenTile
clone.imageName = self.imageName
return clone
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。