import SpriteKit
import GameplayKit
class GameScene: SKScene, SKPhysicsContactDelegate {
private let playerCategory: UInt32 = 0x1 << 0
private let enemyCategory: UInt32 = 0x1 << 1
private let beamCategory: UInt32 = 0x1 << 0
private let shipCategory: UInt32 = 0x1 << 1
private let rectCategory: UInt32 = 0x1 << 1
private let ballCategory: UInt32 = 0x1 << 1
var label = SKLabelNode(fontNamed: "HelveticaNeue-Light")
var label2 = SKLabelNode(fontNamed: "HelveticaNeue-Light")
var score = 5
var ship = SKSpriteNode()
var bullet : SKSpriteNode!
var bullet2 : SKSpriteNode!
var ball : SKShapeNode!
var touched:Bool = false
var lastUpdateTime2 : TimeInterval = 0
let red = CGFloat.random(in: 0...1)
let gr = CGFloat.random(in: 0...1)
et bl = CGFloat.random(in: 0...1)
let colors = [
SKColor.green, SKColor.red, SKColor.blue,
SKColor.magenta, SKColor.yellow, SKColor.brown,
SKColor.black, SKColor.orange, SKColor.purple, SKColor.lightGray
]
public func randomColor(opacity: CGFloat) -> UIColor {
let r: UInt32 = arc4random_uniform(255)
let g: UInt32 = arc4random_uniform(255)
let b: UInt32 = arc4random_uniform(255)
return UIColor(red: CGFloat(r) / 255.0, green: CGFloat(g) / 255.0, blue: CGFloat(b) / 255.0, alpha: opacity)
}
override func didMove(to view: SKView) {
backgroundColor = .blue
// backgroundColor = .white
self.physicsWorld.contactDelegate = self;
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
label.text = "0"
let labelSize: CGFloat = 60.0
label.fontSize = labelSize
label.position = CGPoint(x:self.frame.midX, y:self.frame.height-120)
label.fontColor = SKColor.black
self.addChild(label)
for _ in 0...5 {
let myrect = SKShapeNode(rectOf: CGSize(width:50, height:50),cornerRadius: 5)
myrect.position = CGPoint(x: Int.random(in: 100...300), y: Int.random(in: 200...500))
myrect.fillColor = randomColor(opacity: 1.0)
// myrect.fillColor = colors.randomElement()!
myrect.lineWidth = 0.0
myrect.physicsBody = SKPhysicsBody(rectangleOf:myrect.frame.size)
myrect.physicsBody?.affectedByGravity = false
myrect.physicsBody?.isDynamic = false
self.addChild(myrect)
myrect.physicsBody?.categoryBitMask = rectCategory
}
for j in 0...5 {
let color1 = UIColor(red: red*CGFloat(j), green: gr*CGFloat(j), blue: bl*CGFloat(j), alpha: 1)
let radius: CGFloat = 20
ball = SKShapeNode(circleOfRadius: radius)
let randIntX = CGFloat(Int.random(in : 0...300) + 50)
let randIntY = CGFloat(Int.random(in : 0...300) + 320)
ball.fillColor = color1
ball.position = CGPoint(x:randIntX, y:randIntY)
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.frame.width / 2)
ball.physicsBody!.isDynamic = true
ball.physicsBody!.affectedByGravity = false
addChild( ball)
ball.name = "Ball"
ball.physicsBody?.categoryBitMask = ballCategory
}
shipstart()
label2.text = ""
label2.fontSize = 75
label2.position = CGPoint(x:self.frame.midX, y:self.frame.height-360)
label2.fontColor = SKColor.yellow
label2.name = "button"
self.addChild(label2)
}
func shipstart(){
ship = SKSpriteNode(imageNamed: "ship")
ship.position = CGPoint(x: self.frame.midX, y: frame.height / 11 )
addChild(self.ship)
ship.physicsBody = SKPhysicsBody(rectangleOf: ship.frame.size)
ship.physicsBody!.isDynamic = true
ship.physicsBody!.affectedByGravity = false
ship.physicsBody?.allowsRotation = false
ship.name = "ship"
ship.physicsBody?.categoryBitMask = playerCategory
// ship.physicsBody?.contactTestBitMask = enemyCategory
}
func shoot() {
bullet = SKSpriteNode(imageNamed: "beam")
// bullet.position = CGPoint(x: Int.random(in: 20...Int(self.frame.width) - 20), y: 100)
bullet.physicsBody = SKPhysicsBody(circleOfRadius: bullet.size.width/2)
bullet.physicsBody!.isDynamic = true
bullet.physicsBody!.affectedByGravity = false
bullet.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 0))
bullet.physicsBody?.allowsRotation = false
// bullet.physicsBody?.usesPreciseCollisionDetection = true
bullet.physicsBody = SKPhysicsBody(rectangleOf: bullet.size)
self.addChild(bullet)
bullet.name = "Bullet"
bullet.anchorPoint = CGPoint(x: 0.5, y: 0)
// 敵ビームスプライトの中央下側を原点とする
bullet.position = CGPoint(x: ship.position.x, y: ship.position.y + ship.size.height * 0.5)
// 敵スプライトの先端にビームを配置する
bullet.physicsBody?.categoryBitMask = playerCategory
bullet.physicsBody?.contactTestBitMask = enemyCategory
// ミサイルの発射位置の作成
// bullet.position = CGPoint(x: self.ship.position.x - 2, y: self.ship.position.y)
let move = SKAction.moveTo(y: frame.height, duration: 0.9)
let remove = SKAction.removeFromParent()
bullet.run(SKAction.sequence([move, remove]))
}
// teki
private func spawnEnemy() {
let enemy = SKSpriteNode(imageNamed: "enemy_ship")
enemy.anchorPoint = CGPoint(x: 0.5, y: 0.5)
enemy.position.x = size.width * (0.25 + CGFloat(arc4random_uniform(5)) / 10.0) // 敵の横方向の位置をシーン幅の1/4〜3/4の間の値にする
enemy.position.y = size.height + enemy.size.height * 0.5 // 敵の縦方向の位置をシーン上端にする
// enemy.zPosition = ship.zPosition + 10
// 敵スプライトをプレイヤーより前面に表示する
enemy.name = "enemy_ship"
enemy.physicsBody = SKPhysicsBody(rectangleOf: enemy.size)
enemy.physicsBody?.affectedByGravity = false
enemy.physicsBody?.categoryBitMask = enemyCategory
// enemy.physicsBody?.contactTestBitMask = shipCategory
enemy.physicsBody?.collisionBitMask = 0
// 衝突しても衝突相手からの力を受けないように設定
// 敵スプライトの縦方向のアクションを定義する:
//1. 敵発生音を再生する
// 2. (シーン縦幅 + 敵スプライト高さ)分の距離を縦方向に3〜6秒の時間(ランダム時間)で移動する
// 3. 敵スプライトをシーンから削除する
let verticalAction = SKAction.sequence([
SKAction.playSoundFileNamed("enemy_spawn.wav", waitForCompletion: false),
SKAction.moveBy(x: 0, y: -(size.height + enemy.size.height * 0.5), duration: TimeInterval(Int(3 + arc4random_uniform(3)))),
SKAction.removeFromParent()
])
// 敵スプライトの横方向のアクションを定義する:
// 以下の操作をずっと繰り返す:
// 1. 0.5〜2秒(ランダム時間)待つ
// 2. -50〜50の距離(ランダム距離)を縦方向に0.5秒で移動する
let horizontalAction = SKAction.repeatForever(
SKAction.sequence([
SKAction.wait(forDuration: 0.9, withRange: 3),
SKAction.run {
enemy.run(SKAction.moveBy(x: 50.0 - CGFloat(arc4random_uniform(100)), y: 0, duration: 0.5))
}
])
)
// 敵スプライトからビームを発射するアクションを定義する
// 以下の操作をずっと繰り返す:
// 1. 0.2~1秒(ランダム時間)待つ
// 2. ビーム発射メソッドを実行する
let beamAction = SKAction.repeatForever(
SKAction.sequence([
SKAction.wait(forDuration: 0.9, withRange: 3),
SKAction.run {
self.spawnEnemyBeam(enemy: enemy);
}
])
)
enemy.run(SKAction.group([verticalAction, horizontalAction, beamAction]))
addChild(enemy)
}
// 敵のビームを生成するメソッド
private func spawnEnemyBeam(enemy: SKSpriteNode) {
let beam = SKSpriteNode(imageNamed: "enemy_beam")
beam.anchorPoint = CGPoint(x: 0.5, y: 0)
// 敵ビームスプライトの中央下側を原点とする
beam.position = CGPoint(x: enemy.position.x, y: enemy.position.y - enemy.size.height * 0.5)
// 敵スプライトの先端にビームを配置する
beam.zPosition = enemy.zPosition - 1
// 敵スプライトの背面にビームを配置する
beam.name = "enemy_beam"
// 敵ビームの物理衝突の設定を行う
beam.physicsBody = SKPhysicsBody(rectangleOf: beam.size)
// 敵ビーム衝突用の物理ボディを用意する
beam.physicsBody?.affectedByGravity = false
// 重力の影響は受けないように設定
beam.physicsBody?.categoryBitMask = beamCategory
beam.physicsBody?.contactTestBitMask = playerCategory
beam.physicsBody?.collisionBitMask = 0
// 衝突しても衝突相手からの力を受けないように設定
// ビーム用に以下のアクションを定義する:
// 1. 敵ビーム発射音を再生する
// 2. シーンの高さ分の距離だけ縦方向に0.75秒かけて移動する
// 3. 敵ビームスプライトをシーンから削除する
let action = SKAction.sequence([
SKAction.playSoundFileNamed("enemy_beam.wav", waitForCompletion: false),
SKAction.moveBy(x: 0, y: -size.height, duration: 0.75),
SKAction.removeFromParent()
])
beam.run(action)
addChild(beam)
}
override func touchesEnded(_ touches: Set, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
let touchedNode = atPoint(location)
if touchedNode.name == "ship" {
shoot()
}
if touchedNode.name == "button" {
let gameOverScene = GameScene(size: self.frame.size)
self.view?.presentScene(gameOverScene)
}
}
}
override func touchesMoved(_ touches: Set, with event: UIEvent?) {
for touch in touches {
let toucLocation = touch.location(in: self)
ship.position.x = toucLocation.x
}
}
override func update(_ currentTime: TimeInterval) {
if lastUpdateTime2 == 0 {
lastUpdateTime2 = currentTime
}
if currentTime - lastUpdateTime2 > 3 {
// 更新コマンドは3秒ごとに起動
spawnEnemy()
lastUpdateTime2 = currentTime
}
}
func didBegin(_ contact: SKPhysicsContact) {
var firstBody, secondBody: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
if firstBody.categoryBitMask == playerCategory &&
secondBody.categoryBitMask == enemyCategory {
secondBody.node?.removeFromParent()
score -= 1
label.text = "\(score)"
if self.score <= 1 {
score = 50
}
}
if firstBody.categoryBitMask == beamCategory &&
secondBody.categoryBitMask == playerCategory {
secondBody.node?.removeFromParent()
label2.text = "GameOver"
}
if firstBody.categoryBitMask == playerCategory &&
secondBody.categoryBitMask == ballCategory {
contact.bodyB.node?.removeFromParent()
score -= 1
label.text = "\(score)"
if self.score <= 1 {
score = 50
}
}
if firstBody.categoryBitMask == playerCategory &&
secondBody.categoryBitMask == rectCategory {
contact.bodyB.node?.removeFromParent()
score -= 1
label.text = "\(score)"
if self.score <= 1 {
score = 50
}
}
}
override func touchesBegan(_ touches: Set, with event: UIEvent?) {
}
}