私はSpriteKitを使って簡単なプラットフォームゲームを作っています。ゲームがfunc didBeginで地面に当たったときにゲームが検出されますが、何らかの理由でbooleanのplayerTouchingGround(Playerクラス内)がtrueに変更されていません。私はvar playerTouchingGroundをtrueに初期化し、プレーヤーは一度ジャンプすることができますが、再びジャンプすることはできません。アウトプットコンソールは、「ヒットグラウンド、左グラウンド、ヒットグラウンド」を印刷します。私は何が間違っているのか分かりません。私はおそらく単純なものを探しています。ここでスプライトを素早く地上に飛ばせるにはどうすればよいですか?
はここに私のGameSceneコード
import SpriteKit
import GameplayKit
class GameScene: SKScene{
let player: Player!
let ground: Ground!
let controller: ControllerNode!
let contactManager = Player()
// MARK: - Init
override init(size: CGSize) {
player = Player()
ground = Ground(size: size)
controller = ControllerNode(position: CGPoint(x:0, y: 0))
super.init(size: size)
self.physicsWorld.contactDelegate = contactManager
setup()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Setup
func setup() {
// Background Color
self.backgroundColor = UIColor.white
// Adding Player
addChild(player)
player.position.x = size.width/2
player.position.y = size.height/2
// Adding Ground
addChild(ground)
ground.position.x = size.width/2
ground.position.y = size.height/4
// Adding ControllerNode
addChild(controller)
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
player.movement(directions: self.controller!.pressedDirections())
}
}
はここに私のプレーヤーのクラスコード
import SpriteKit
enum CharacterMovement : Int {
case Up
case Right
case Down
case Left
}
enum ColliderType: UInt32 {
case player = 1
case ground = 2
}
class Player: SKSpriteNode, SKPhysicsContactDelegate {
var tick = 0
var currentMovement: CharacterMovement?
var lastMovement: CharacterMovement?
var contactMask: Int = 0
var playerTouchingGround = true
// MARK: - Init
init() {
let playerSize = CGSize(width: 30, height: 60)
super.init(texture: nil, color: UIColor.cyan, size: playerSize)
lastMovement = .Right
self.zPosition = 10
setup()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Setup
func setup() {
physicsBody = SKPhysicsBody(rectangleOf: size)
physicsBody?.usesPreciseCollisionDetection = true
physicsBody?.categoryBitMask = ColliderType.player.rawValue
physicsBody?.collisionBitMask = ColliderType.ground.rawValue
physicsBody?.contactTestBitMask = ColliderType.ground.rawValue
physicsBody?.allowsRotation = false
physicsBody?.restitution = 0
physicsBody?.isDynamic = true
}
func didBegin(_ contact: SKPhysicsContact) {
print("hit ground")
playerTouchingGround = true
}
func movement(directions: [ControllerInput]) {
// if (directions.index(of: .Up) != nil) && (touchingGround == true){
if (directions.index(of: .Up) != nil) && (playerTouchingGround) {
physicsBody?.applyImpulse(CGVector(dx: 0, dy: 30))
playerTouchingGround = false
currentMovement = .Up
print("left ground")
}
if directions.index(of: .Right) != nil {
physicsBody?.applyImpulse(CGVector(dx: 1, dy: 0))
currentMovement = .Right
}
if directions.index(of: .Left) != nil {
physicsBody?.applyImpulse(CGVector(dx: -1, dy: 0))
currentMovement = .Left
}
if currentMovement != nil {
lastMovement = currentMovement
}
if !directions.isEmpty && self.currentMovement != nil {
// Player Animations
}
else {
currentMovement = nil
}
tick += 1
if tick > 60 {
tick = 0
}
}
}
であることは私のグランドクラスコードは、あなたの問題は、あなたが複数のプレイヤーを作成しているある
import SpriteKit
class Ground: SKSpriteNode {
// MARK: - Init
init(size: CGSize) {
let groundSize = CGSize(width: size.width, height: 20)
super.init(texture: nil, color: UIColor.black, size: groundSize)
setup()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Setup
func setup() {
physicsBody = SKPhysicsBody(rectangleOf: size)
physicsBody?.categoryBitMask = ColliderType.ground.rawValue
physicsBody?.usesPreciseCollisionDetection = true
physicsBody?.isDynamic = false
physicsBody?.restitution = 0
physicsBody?.categoryBitMask = ColliderType.ground.rawValue
physicsBody?.collisionBitMask = ColliderType.player.rawValue
physicsBody?.contactTestBitMask = ColliderType.player.rawValue
}
}
同じインスタンスではないことを意味します。私のプレーヤークラスを私のcontactDelegateにすることは良い考えですか?私は私のgameSceneにすべてのプレイヤーの動きのコードを入れたくないのですが、複数のPlayerオブジェクトを作成せずにSKPhysicsContactDelegateを自分のプレーヤークラスに初期化する方法はわかりません。 – TommyC
実際には、衝突する唯一のことがプレイヤーでない限り、シーンに残されたほうがいいです。 – Knight0fDragon
私はSkPhysicsContactDelegateを設定し、私のGameSceneにdidBegin(連絡先)を設定しました。次に、GameSceneクラスとPlayerクラスの両方からアクセスできるブール値変数を持つGlobalVariableクラスを作成しました。これを行う最も効率的な方法であるかどうかはわかりませんが、今はゲームが完璧に実行されています。ご協力ありがとうございますKnightOfDragon。 – TommyC