从 GameScene 设置自定义 SKSpriteNode 的位置
Setting position of custom SKSpriteNode from GameScene
我正在制作自定义 SKSpriteNode,当我逐步调用 createShip 时,class 中的 heroShip 常量是正确的,但是当我跳回 gameScene 时,那里的 heroShip 常量没有我的属性调用 createShip 时分配,我不确定我做错了什么。我试过使用 class 函数,但是使用高度和宽度属性不起作用。
自定义 SKSpriteNode class
class hero: SKSpriteNode {
var width: CGFloat = 0.0
var height: CGFloat = 0.0
func createShip() -> SKSpriteNode {
let heroShip = SKSpriteNode(imageNamed: "heroShip")
heroShip.anchorPoint = CGPointMake(1.0, 0.5)
heroShip.physicsBody = SKPhysicsBody(rectangleOfSize: heroShip.size)
heroShip.physicsBody?.usesPreciseCollisionDetection = true
heroShip.zPosition = 1.0
heroShip.physicsBody?.mass = 0.02
heroShip.physicsBody?.dynamic = true
heroShip.physicsBody?.affectedByGravity = false
heroShip.physicsBody?.categoryBitMask = ObjectCategory.collisionHeroCategory.rawValue
heroShip.physicsBody?.contactTestBitMask = ObjectCategory.sceneCategory.rawValue
heroShip.physicsBody?.collisionBitMask = 0x0 | ObjectCategory.sceneCategory.rawValue
//heroShip.position = CGPointMake((scene?.frame.size.width)!/6.0, (scene?.frame.size.height)!/2.0)
heroShip.position = CGPointMake(width, height)
return heroShip
}
}
我的游戏场景
class GameScene: SKScene,SKPhysicsContactDelegate{
let background = SKSpriteNode(imageNamed: "background")
var score:Int = 0
let scoreLabel = SKLabelNode(fontNamed: "Courier")
let MotionManager = CMMotionManager()
var heroShip = hero()
override func didMoveToView(view: SKView) {
heroShip.width = self.size.width/6.0
heroShip.height = self.size.height/2.0
heroShip.createShip()
let enemyShip = SKSpriteNode(imageNamed: "enemyShip")
/* Setup your scene here */
self.physicsWorld.contactDelegate = self
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: CGRectMake(0,heroShip.size.width/1.25,frame.width,frame.height - heroShip.size.width*1.6))
scene?.physicsBody?.contactTestBitMask = ObjectCategory.sceneCategory.rawValue
scene?.physicsBody?.categoryBitMask = ObjectCategory.sceneCategory.rawValue
background.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame))
scoreLabel.fontColor = SKColor.whiteColor()
scoreLabel.text = String(format: "Score: %01u",score)
scoreLabel.position = CGPointMake(frame.size.width/2, frame.size.height - scoreLabel.frame.size.width/1.2)
scoreLabel.zPosition = 1.0
enemyShip.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
enemyShip.zPosition = 1.0
enemyShip.physicsBody = SKPhysicsBody(rectangleOfSize: heroShip.size)
enemyShip.physicsBody?.usesPreciseCollisionDetection = true
enemyShip.physicsBody?.mass = 0.02
enemyShip.physicsBody?.dynamic = true
enemyShip.physicsBody?.affectedByGravity = false
enemyShip.physicsBody?.categoryBitMask = ObjectCategory.collisionEnemyCategory.rawValue
enemyShip.physicsBody?.contactTestBitMask = ObjectCategory.collisionBulletCategory.rawValue
enemyShip.physicsBody?.collisionBitMask = 0x0
self.addChild(enemyShip)
self.addChild(background)
self.addChild(self.heroShip)
self.addChild(scoreLabel)
if MotionManager.accelerometerAvailable{
MotionManager.startAccelerometerUpdates()
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let bullet = SKSpriteNode(imageNamed: "bullet")
bullet.position = CGPointMake(heroShip.position.x, heroShip.position.y)
bullet.zPosition = 1.0
// Add physics body for collision detection
bullet.physicsBody = SKPhysicsBody(rectangleOfSize: bullet.frame.size)
bullet.physicsBody?.dynamic = true
bullet.physicsBody?.affectedByGravity = false
bullet.physicsBody?.categoryBitMask = ObjectCategory.collisionBulletCategory.rawValue
bullet.physicsBody?.contactTestBitMask = ObjectCategory.collisionHeroCategory.rawValue
bullet.physicsBody?.collisionBitMask = 0x0;
let action = SKAction.moveToX(CGRectGetMaxX(self.frame) + bullet.size.width, duration: 0.75)
self.addChild(bullet)
bullet.runAction(action, completion: {
bullet.removeAllActions()
bullet.removeFromParent()
})
}
func didBeginContact(contact: SKPhysicsContact) {
if contact.bodyB.categoryBitMask == ObjectCategory.collisionBulletCategory.rawValue && contact.bodyA.categoryBitMask == ObjectCategory.collisionEnemyCategory.rawValue{
score++
}
}
override func update(currentTime: CFTimeInterval) {
let data = MotionManager.accelerometerData
if data?.acceleration.x == nil{
print("nil")
}
else if fabs((data?.acceleration.x)!) > 0.2 {
heroShip.physicsBody?.applyForce(CGVectorMake(0.0, CGFloat(40 * (data?.acceleration.x)!)))
}
scoreLabel.text = String(format: "Score: %01u",score)
}
}
您似乎没有理解您的代码发生了什么。
截至目前createShip()
正在创建一艘英雄飞船,但您从未使用过它。
通过查看您的代码,似乎甚至不需要 createShip()
。看hero是heroShip,你init里的代码也是。
convenience init(imageNamed: String,sceneSize:CGSize) {
let heroTexture = SKTexture(imageNamed: imageNamed)
self.init(texture: heroTexture, color: UIColor.whiteColor(), size: heroTexture.size()) //This may need to be tweeked, my mac is dead right now to verify.
self.anchorPoint = CGPointMake(1.0, 0.5)
self.physicsBody = SKPhysicsBody(rectangleOfSize: self.size)
self.physicsBody?.usesPreciseCollisionDetection = true
self.zPosition = 1.0
self.physicsBody?.mass = 0.02
self.physicsBody?.dynamic = true
self.physicsBody?.affectedByGravity = false
heroShip.physicsBody?.categoryBitMask = ObjectCategory.collisionHeroCategory.rawValue
heroShip.physicsBody?.contactTestBitMask = ObjectCategory.sceneCategory.rawValue
heroShip.physicsBody?.collisionBitMask = 0x0 | ObjectCategory.sceneCategory.rawValue
//self.position = CGPointMake((scene?.frame.size.width)!/6.0, (scene?.frame.size.height)!/2.0)
self.position = CGPointMake(sceneSize.width, sceneSize.height)
}
你现在遇到了另一个问题,那就是你的SKPhysicsBody
不会对齐你的锚点。
要解决此问题,请像这样创建 SKPhysicsBody
:
let centerPoint = CGPointMake(self.size.width / 2 - (self.size.width * self.anchorPoint.x), self.size.height / 2 - (self.size.height * self.anchorPoint.y))
self.physicsBody = SKPhysicsBody(rectangleOfSize: self.size, center: centerPoint)
你运行
heroShip.createShip()
然后永远不要对 returned 的 SKSpriteNode
做任何事情。据我所知,英雄 class 是 英雄船。对于这个答案的其余部分,我将放弃这个假设。
从 GameScene
的顶部开始,您应该进行一些重构。
var heroShip = hero()
将被替换为使用 SKSpriteNode
结构的 init:
var heroShip = hero(imageNamed: "heroShip")
移动到hero
class,func createShip() -> SKSpriteNode {
应该变成func createShip() {
。由于您现在已经使用图像纹理设置了节点,并且正在使用 hero
class 作为节点,因此不需要 return a SKSpriteNode
.
删除 let heroShip = SKSpriteNode(imageNamed: "heroShip")
因为 hero
class 是 将成为我们的 heroShip
.
将 heroShip.whatever
变量的所有用法替换为 self.whatever
。最后,删除 return heroShip
.
我正在制作自定义 SKSpriteNode,当我逐步调用 createShip 时,class 中的 heroShip 常量是正确的,但是当我跳回 gameScene 时,那里的 heroShip 常量没有我的属性调用 createShip 时分配,我不确定我做错了什么。我试过使用 class 函数,但是使用高度和宽度属性不起作用。
自定义 SKSpriteNode class
class hero: SKSpriteNode {
var width: CGFloat = 0.0
var height: CGFloat = 0.0
func createShip() -> SKSpriteNode {
let heroShip = SKSpriteNode(imageNamed: "heroShip")
heroShip.anchorPoint = CGPointMake(1.0, 0.5)
heroShip.physicsBody = SKPhysicsBody(rectangleOfSize: heroShip.size)
heroShip.physicsBody?.usesPreciseCollisionDetection = true
heroShip.zPosition = 1.0
heroShip.physicsBody?.mass = 0.02
heroShip.physicsBody?.dynamic = true
heroShip.physicsBody?.affectedByGravity = false
heroShip.physicsBody?.categoryBitMask = ObjectCategory.collisionHeroCategory.rawValue
heroShip.physicsBody?.contactTestBitMask = ObjectCategory.sceneCategory.rawValue
heroShip.physicsBody?.collisionBitMask = 0x0 | ObjectCategory.sceneCategory.rawValue
//heroShip.position = CGPointMake((scene?.frame.size.width)!/6.0, (scene?.frame.size.height)!/2.0)
heroShip.position = CGPointMake(width, height)
return heroShip
}
}
我的游戏场景
class GameScene: SKScene,SKPhysicsContactDelegate{
let background = SKSpriteNode(imageNamed: "background")
var score:Int = 0
let scoreLabel = SKLabelNode(fontNamed: "Courier")
let MotionManager = CMMotionManager()
var heroShip = hero()
override func didMoveToView(view: SKView) {
heroShip.width = self.size.width/6.0
heroShip.height = self.size.height/2.0
heroShip.createShip()
let enemyShip = SKSpriteNode(imageNamed: "enemyShip")
/* Setup your scene here */
self.physicsWorld.contactDelegate = self
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: CGRectMake(0,heroShip.size.width/1.25,frame.width,frame.height - heroShip.size.width*1.6))
scene?.physicsBody?.contactTestBitMask = ObjectCategory.sceneCategory.rawValue
scene?.physicsBody?.categoryBitMask = ObjectCategory.sceneCategory.rawValue
background.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame))
scoreLabel.fontColor = SKColor.whiteColor()
scoreLabel.text = String(format: "Score: %01u",score)
scoreLabel.position = CGPointMake(frame.size.width/2, frame.size.height - scoreLabel.frame.size.width/1.2)
scoreLabel.zPosition = 1.0
enemyShip.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
enemyShip.zPosition = 1.0
enemyShip.physicsBody = SKPhysicsBody(rectangleOfSize: heroShip.size)
enemyShip.physicsBody?.usesPreciseCollisionDetection = true
enemyShip.physicsBody?.mass = 0.02
enemyShip.physicsBody?.dynamic = true
enemyShip.physicsBody?.affectedByGravity = false
enemyShip.physicsBody?.categoryBitMask = ObjectCategory.collisionEnemyCategory.rawValue
enemyShip.physicsBody?.contactTestBitMask = ObjectCategory.collisionBulletCategory.rawValue
enemyShip.physicsBody?.collisionBitMask = 0x0
self.addChild(enemyShip)
self.addChild(background)
self.addChild(self.heroShip)
self.addChild(scoreLabel)
if MotionManager.accelerometerAvailable{
MotionManager.startAccelerometerUpdates()
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let bullet = SKSpriteNode(imageNamed: "bullet")
bullet.position = CGPointMake(heroShip.position.x, heroShip.position.y)
bullet.zPosition = 1.0
// Add physics body for collision detection
bullet.physicsBody = SKPhysicsBody(rectangleOfSize: bullet.frame.size)
bullet.physicsBody?.dynamic = true
bullet.physicsBody?.affectedByGravity = false
bullet.physicsBody?.categoryBitMask = ObjectCategory.collisionBulletCategory.rawValue
bullet.physicsBody?.contactTestBitMask = ObjectCategory.collisionHeroCategory.rawValue
bullet.physicsBody?.collisionBitMask = 0x0;
let action = SKAction.moveToX(CGRectGetMaxX(self.frame) + bullet.size.width, duration: 0.75)
self.addChild(bullet)
bullet.runAction(action, completion: {
bullet.removeAllActions()
bullet.removeFromParent()
})
}
func didBeginContact(contact: SKPhysicsContact) {
if contact.bodyB.categoryBitMask == ObjectCategory.collisionBulletCategory.rawValue && contact.bodyA.categoryBitMask == ObjectCategory.collisionEnemyCategory.rawValue{
score++
}
}
override func update(currentTime: CFTimeInterval) {
let data = MotionManager.accelerometerData
if data?.acceleration.x == nil{
print("nil")
}
else if fabs((data?.acceleration.x)!) > 0.2 {
heroShip.physicsBody?.applyForce(CGVectorMake(0.0, CGFloat(40 * (data?.acceleration.x)!)))
}
scoreLabel.text = String(format: "Score: %01u",score)
}
}
您似乎没有理解您的代码发生了什么。
截至目前createShip()
正在创建一艘英雄飞船,但您从未使用过它。
通过查看您的代码,似乎甚至不需要 createShip()
。看hero是heroShip,你init里的代码也是。
convenience init(imageNamed: String,sceneSize:CGSize) {
let heroTexture = SKTexture(imageNamed: imageNamed)
self.init(texture: heroTexture, color: UIColor.whiteColor(), size: heroTexture.size()) //This may need to be tweeked, my mac is dead right now to verify.
self.anchorPoint = CGPointMake(1.0, 0.5)
self.physicsBody = SKPhysicsBody(rectangleOfSize: self.size)
self.physicsBody?.usesPreciseCollisionDetection = true
self.zPosition = 1.0
self.physicsBody?.mass = 0.02
self.physicsBody?.dynamic = true
self.physicsBody?.affectedByGravity = false
heroShip.physicsBody?.categoryBitMask = ObjectCategory.collisionHeroCategory.rawValue
heroShip.physicsBody?.contactTestBitMask = ObjectCategory.sceneCategory.rawValue
heroShip.physicsBody?.collisionBitMask = 0x0 | ObjectCategory.sceneCategory.rawValue
//self.position = CGPointMake((scene?.frame.size.width)!/6.0, (scene?.frame.size.height)!/2.0)
self.position = CGPointMake(sceneSize.width, sceneSize.height)
}
你现在遇到了另一个问题,那就是你的SKPhysicsBody
不会对齐你的锚点。
要解决此问题,请像这样创建 SKPhysicsBody
:
let centerPoint = CGPointMake(self.size.width / 2 - (self.size.width * self.anchorPoint.x), self.size.height / 2 - (self.size.height * self.anchorPoint.y))
self.physicsBody = SKPhysicsBody(rectangleOfSize: self.size, center: centerPoint)
你运行
heroShip.createShip()
然后永远不要对 returned 的 SKSpriteNode
做任何事情。据我所知,英雄 class 是 英雄船。对于这个答案的其余部分,我将放弃这个假设。
从 GameScene
的顶部开始,您应该进行一些重构。
var heroShip = hero()
将被替换为使用 SKSpriteNode
结构的 init:
var heroShip = hero(imageNamed: "heroShip")
移动到hero
class,func createShip() -> SKSpriteNode {
应该变成func createShip() {
。由于您现在已经使用图像纹理设置了节点,并且正在使用 hero
class 作为节点,因此不需要 return a SKSpriteNode
.
删除 let heroShip = SKSpriteNode(imageNamed: "heroShip")
因为 hero
class 是 将成为我们的 heroShip
.
将 heroShip.whatever
变量的所有用法替换为 self.whatever
。最后,删除 return heroShip
.