import SpriteKit
import SwiftUI
class GameScene: SKScene, SKPhysicsContactDelegate {
var thrustActive: Binding!
var rotationDegrees: Binding!
private var rocket: SKSpriteNode!
private var base: SKSpriteNode!
private var background: SKSpriteNode!
override func sceneDidLoad() {
super.sceneDidLoad()
// Remove the default background color
backgroundColor = .clear
// Create a black SKShapeNode that fills the entire scene
let blackBG = SKShapeNode(rect: CGRect(origin: .zero, size: size))
blackBG.fillColor = .black
blackBG.strokeColor = .clear
blackBG.zPosition = -10 // behind everything else
addChild(blackBG)
// Center point for alignment
let centerX = size.width / 2
let centerY = size.height / 2
// Add the base (below the rocket, centered horizontally)
base = SKSpriteNode(imageNamed: "Base")
base.size = CGSize(width: 60, height: 10)
base.position = CGPoint(x: centerX, y: centerY - 25)
base.zPosition = 1
addChild(base)
base.physicsBody = SKPhysicsBody(rectangleOf: base.size)
base.physicsBody?.isDynamic = false
base.physicsBody?.categoryBitMask = PhysicsCategory.base
base.physicsBody?.contactTestBitMask = PhysicsCategory.rocket
base.physicsBody?.collisionBitMask = PhysicsCategory.rocket
// Add the rocket (centered)
rocket = SKSpriteNode(imageNamed: "Rocket")
rocket.size = CGSize(width: 15, height: 25) // Adjusted size
rocket.position = CGPoint(x: size.width / 2, y: size.height / 2)
rocket.zRotation = 0
rocket.zPosition = 1
addChild(rocket)
// Rocket physics body
rocket.physicsBody = SKPhysicsBody(rectangleOf: rocket.size)
rocket.physicsBody?.isDynamic = true
rocket.physicsBody?.linearDamping = 0.02
rocket.physicsBody?.angularDamping = 0.02
rocket.physicsBody?.allowsRotation = true
rocket.physicsBody?.categoryBitMask = PhysicsCategory.rocket
rocket.physicsBody?.contactTestBitMask = PhysicsCategory.base | PhysicsCategory.background
rocket.physicsBody?.collisionBitMask = PhysicsCategory.base | PhysicsCategory.background
// Physics World
physicsWorld.gravity = CGVector(dx: 0, dy: -0.2)
physicsWorld.contactDelegate = self
}
func configureBackground(imageName: String, position: CGPoint, scale: CGFloat = 1.0) {
let bgTexture = SKTexture(imageNamed: imageName)
background = SKSpriteNode(texture: bgTexture)
background.size = CGSize(
width: background.size.width * scale,
height: background.size.height * scale
)
background.position = position
background.zPosition = -1
addChild(background)
// Create a physics body from the texture, ignoring any pixels with alpha < 1.0
background.physicsBody = SKPhysicsBody(
texture: bgTexture,
alphaThreshold: 1.0,
size: background.size
)
background.physicsBody?.isDynamic = false
background.physicsBody?.categoryBitMask = PhysicsCategory.background
background.physicsBody?.contactTestBitMask = PhysicsCategory.rocket
background.physicsBody?.collisionBitMask = PhysicsCategory.rocket
}
override func update(_ currentTime: TimeInterval) {
// Apply rotation based on gesture
if rotationDegrees.wrappedValue != 0 {
rocket.zRotation = (rotationDegrees.wrappedValue + 90) * .pi / 180
}
// Apply thrust if active
if thrustActive.wrappedValue {
let thrustMagnitude: CGFloat = 4.0
let radians = rocket.zRotation + .pi / 2
let dx = cos(radians) * thrustMagnitude
let dy = sin(radians) * thrustMagnitude
rocket.physicsBody?.applyForce(CGVector(dx: dx, dy: dy))
}
}
func didBegin(_ contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
if contactMask == PhysicsCategory.rocket | PhysicsCategory.base {
print("Rocket has landed on the base!")
}
if contactMask == PhysicsCategory.rocket | PhysicsCategory.background {
print("Rocket collided with the background!")
}
}
}
struct PhysicsCategory {
static let rocket: UInt32 = 0x1 << 0
static let base: UInt32 = 0x1 << 1
static let background: UInt32 = 0x1 << 2
}