我似乎对SpriteKit
中与碰撞检测,行动或职位相关的事情了解不足。
我有一个球员和砖块,当一名球员落在任何砖块上时,他会跳过它,然后所有砖块向下移动一段距离。我将播放器添加为场景的子节点,将砖块添加为包含它们的节点(SKNode
)的子节点。当我想改变他们的y位置时,我只是在该节点上使用moveBy
动作,并且砖确实按照我想要的方式移动。
问题是,当他们移动或者甚至当他们停下来时,玩家不能再降落在他们身上(他们之间的碰撞和玩家不再被检测到),所以玩家只能穿过他们。
这是GameScene.swift
中的代码:
func moveBricksDownFor(movedForY: CGFloat) {
let moveAction = SKAction.moveBy(CGVectorMake(0, -movedForY), duration: 1.0)
brickNode.runAction(moveAction)
for _ in 0...4 {addBrick(0.7)}
}
func playerCollidedWithBrick(brick: Brick) {
if player.position.y > brick.position.y {
player.physicsBody?.velocity.dy = player.maxVelocityY
}
if player.yChangedFor() > 70 {moveBricksDownFor(player.yChangedFor())}
}
物理主体是否可能不附加砖块的可视化表示或类似的东西?
这里也是Player
类(上面代码中使用的部分):
let maxVelocityY: CGFloat = 900
var startPositionY: CGFloat!
init(position: CGPoint) {
let texture = SKTexture(imageNamed: "doodler.png")
super.init(texture: texture, color: UIColor.blackColor(), size: CGSizeMake(60, 60))
self.zPosition = Layer.player.rawValue
self.position = position
self.startPositionY = position.y
self.physicsBody = SKPhysicsBody(rectangleOfSize: self.size)
self.physicsBody?.affectedByGravity = true
self.physicsBody?.allowsRotation = false
self.physicsBody?.dynamic = true
self.physicsBody?.categoryBitMask = PhysicsCategory.Player
self.physicsBody?.contactTestBitMask = PhysicsCategory.Brick
self.physicsBody?.collisionBitMask = PhysicsCategory.None
self.physicsBody?.usesPreciseCollisionDetection = true
}
func yChangedFor() -> CGFloat {
return (self.position.y - startPositionY)
}
我确实谷歌类似的主题,但没有发现任何类似的问题,所以我想我在这里缺少一些基本的东西或者犯了一个愚蠢的错误。
更新(添加Brick
类并初始化worldNode
(SKNode
)):
class Brick: SKSpriteNode {
init(position:CGPoint) {
let texture = SKTexture(imageNamed: "brick.png")
super.init(texture: texture, color: UIColor.clearColor(), size: CGSizeMake(70, 10))
self.position = position
self.zPosition = Layer.brick.rawValue
self.physicsBody = SKPhysicsBody(rectangleOfSize: self.size)
self.physicsBody?.affectedByGravity = false
self.physicsBody?.allowsRotation = true
self.physicsBody?.dynamic = false
self.physicsBody?.categoryBitMask = PhysicsCategory.Brick
self.physicsBody?.contactTestBitMask = PhysicsCategory.Player
self.physicsBody?.collisionBitMask = PhysicsCategory.None
self.physicsBody?.usesPreciseCollisionDetection = true
}
}
设置brickNode
并为其添加砖块作为其子项:
func setupBrickNode() {
brickNode.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
brickNode.physicsBody?.affectedByGravity = false
}
func addBrick(minXPercantage: CGFloat) {
let randomX = random(min: size.width*0.25, max: size.width - 100)
let randomY = random(min: size.height*minXPercantage, max: size.height)
let brick = Brick(position: CGPointMake(randomX, randomY))
brickNode.addChild(brick)
}
func setupBricks() {
for _ in 0...10 {addBrick(0.25)}
}
更新了移动brickNode
的部分(现在设置速度):
func moveBricks() {
brickNode.physicsBody?.velocity = CGVectorMake(0, -player.maxVelocityY/4)
let waitAction = SKAction.waitForDuration(1.0)
let setBrickNodeVelocityToZero = SKAction.runBlock({self.brickNode.physicsBody?.velocity = CGVectorMake(0, 0)})
runAction(SKAction.sequence([waitAction, setBrickNodeVelocityToZero]))
}
func playerCollidedWithBrick(brick: Brick) {
if player.position.y > brick.position.y {
player.physicsBody?.velocity.dy = player.maxVelocityY
moveBricks()
}
}
答案 0 :(得分:1)
如果你想登陆动态参与对象,你可能必须设置它。
self.physicsBody!.restitution = 0
此外,使用SKAction
的移动不是最好的态度而不是通过速度或力矢量进行正确的运动,这可能会改变您的物理对象值并丢失方向。
答案 1 :(得分:1)
示例代码
import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate {
var world: SKNode!
var player: SKSpriteNode!
override func didMoveToView(view: SKView) {
physicsWorld.contactDelegate = self
physicsWorld.gravity = CGVector(dx: 0, dy: -10)
// World
world = SKNode()
addChild(world)
// Player
player = SKSpriteNode(color: SKColor.redColor(), size: CGSize(width: 50, height: 50))
player.position.x = size.width / 2
player.physicsBody = SKPhysicsBody(rectangleOfSize: player.size)
player.physicsBody!.categoryBitMask = 2
player.physicsBody!.contactTestBitMask = 4
player.physicsBody!.collisionBitMask = 0
player.physicsBody!.mass = 1
player.physicsBody!.velocity = CGVector(dx: 0, dy: 2000)
player.physicsBody!.usesPreciseCollisionDetection = true
world.addChild(player)
// Bricks
for index in 0...50 {
// Player
let brick = SKSpriteNode(color: SKColor.greenColor(), size: CGSize(width: 100, height: 25))
brick.position = CGPoint(x: size.width / 2, y: 300 + CGFloat(index) * 200)
brick.zPosition = -1
brick.physicsBody = SKPhysicsBody(rectangleOfSize: brick.size)
brick.physicsBody!.categoryBitMask = 4
brick.physicsBody!.contactTestBitMask = 2
brick.physicsBody!.collisionBitMask = 0
brick.physicsBody!.dynamic = false
world.addChild(brick)
}
}
func didBeginContact(contact: SKPhysicsContact) {
// Is the player falling?
guard player.physicsBody!.velocity.dy <= 0 else {
return
}
player.physicsBody!.velocity = CGVector(dx: 0, dy: 1000)
}
override func didFinishUpdate() {
guard player.position.y > 200 else {
return
}
world.position.y = -player.position.y + 200
}
}
答案 2 :(得分:0)
因为特定的砖块位置始终相同。你正在移动它的父母而不是砖本身。
let realBrickPosition = convertPoint(brick.position, toNode: self)