Question
Hello, I am currently working on a ios game where you play as a cactus on the left and you shoot enemies on the right.
Hello, I am currently working on a ios game where you play as a cactus on the left and you shoot enemies on the right. When I tap the screen the enemies end up disappearing because of the collision but I am not sure why it is hitting all of the enemies at once. It is supposed to hit one enemy at a time. I have commented code that I was thinking would work but it is not working out well. Can you please see if you can see the problem and fix the code you think will work. Please see if you can fix it. Thank you. This is written using swift
This is what it does when it runs.
https://drive.google.com/file/d/1e5vQUIcnosfILXXEu_yCczi2sOGipB9E/view?usp=sharing
Swift Code:
import SpriteKit
import GameplayKit
import CoreGraphics
import AVFoundation
var invaderNum = 1
struct CollisionCategories{
// static let Invader : UInt32 = 0x1 << 0
// static let Player: UInt32 = 0x1 << 1
// static let InvaderBullet: UInt32 = 0x1 << 2
// static let PlayerBullet: UInt32 = 0x1 << 3
static let coinManCategory : UInt32 = 0x1 << 1
static let coinCategory : UInt32 = 0x1 << 2
static let bombCategory : UInt32 = 0x1 << 3
static let groundAndCeilCategory : UInt32 = 0x1 << 4
let playableRect = CGRect()
}
class GameScene: SKScene, SKPhysicsContactDelegate{
var cat = SKSpriteNode(imageNamed: "cat")
var enemy = SKSpriteNode(imageNamed: "enemy")
var ceil : SKSpriteNode?
var yourScoreLabel : SKLabelNode?
var finalScoreLabel : SKLabelNode?
var scoreLabel : SKLabelNode?
var score = 0
private var label : SKLabelNode?
private var spinnyNode : SKShapeNode?
var background = SKSpriteNode(imageNamed: "background1")
var backgroundMusicPlayer: AVAudioPlayer!
let texture = SKTexture(imageNamed: "apple")
let textureEnemy = SKTexture(imageNamed: "enemy")
let rowsOfInvaders = 4
var invaderSpeed = 2
let leftBounds = CGFloat(30)
var rightBounds = CGFloat(0)
var invadersWhoCanFire:[Apple] = []
let player:Player = Player()
let maxLevels = 3
var playableRect = CGRect()
var bullet = InvandarApple(imageName: "apple",bulletSound: nil)
override func didMove(to view: SKView) {
let maxAspectRatio:CGFloat = 16.0/9.0
let playableHeight = size.width / maxAspectRatio
let playableMargin = (size.height-playableHeight)/2.0
playableRect = CGRect(x: 0, y: playableMargin,
width: size.width,
height: playableHeight)
playBackgroundMusic("backgroundMusic.wav")
self.physicsWorld.gravity = CGVector(dx : 0, dy : 0)
self.physicsWorld.contactDelegate = self
background.anchorPoint = CGPoint.zero
background.position = CGPoint(x: 0, y: 0)
addChild(background)
debugDrawPlayableArea()
// setupInvaders()
setupPlayer()
invokeInvaderFire()
run(SKAction.repeatForever(
SKAction.sequence([SKAction.run(spawnEnemy),
SKAction.wait(forDuration: 1.0)])))
run(SKAction.repeatForever(
SKAction.sequence([SKAction.run(spawnCat),
SKAction.wait(forDuration: 2.0)])))
scoreLabel = childNode(withName: "scoreLabel") as? SKLabelNode
}
func debugDrawPlayableArea() {
let shape = SKShapeNode()
let path = CGMutablePath()
path.addRect(playableRect)
shape.path = path
shape.strokeColor = SKColor.red
shape.lineWidth = 4.0
addChild(shape)
}
func touchDown(atPoint pos : CGPoint) {
if let n = self.spinnyNode?.copy() as! SKShapeNode? {
n.position = pos
n.strokeColor = SKColor.green
self.addChild(n)
}
}
func touchMoved(toPoint pos : CGPoint) {
if let n = self.spinnyNode?.copy() as! SKShapeNode? {
n.position = pos
n.strokeColor = SKColor.blue
self.addChild(n)
}
}
func touchUp(atPoint pos : CGPoint) {
if let n = self.spinnyNode?.copy() as! SKShapeNode? {
n.position = pos
n.strokeColor = SKColor.red
self.addChild(n)
}
}
override func touchesBegan(_ touches: Set
if let touch = touches.first {
let position = touch.location(in: view)
print(position)
bullet.position.y = position.y
}
player.fireBullet(scene: self)
if let label = self.label {
label.run(SKAction.init(named: "Pulse")!, withKey: "fadeInOut")
}
for t in touches { self.touchDown(atPoint: t.location(in: self)) }
let touch = touches.first
if let location = touch?.location(in: self) {
let theNodes = nodes(at: location)
for node in theNodes {
if node.name == "play" {
score = 0
let myScene = GameScene(size: self.size)
myScene.scaleMode = self.scaleMode
let reveal = SKTransition.fade(with: UIColor.black, duration: 1.5)
myScene.scaleMode = .resizeFill
self.view?.presentScene(myScene, transition: reveal)
node.removeFromParent()
finalScoreLabel?.removeFromParent()
yourScoreLabel?.removeFromParent()
scene?.isPaused = false
scoreLabel?.text = "Score: \(score)"
// startTimers()
}
}
}
}
func gameOver() {
scene?.isPaused = true
// coinTimer?.invalidate()
// bombTimer?.invalidate()
yourScoreLabel = SKLabelNode(text: "Your Score:")
yourScoreLabel?.position = CGPoint(x: self.size.width/2-30, y:200)
yourScoreLabel?.fontSize = 60
yourScoreLabel?.zPosition = 1
if yourScoreLabel != nil {
addChild(yourScoreLabel!)
}
finalScoreLabel = SKLabelNode(text: "\(score)")
finalScoreLabel?.position = CGPoint(x:(yourScoreLabel?.frame.size.width)!+60 , y:200)
finalScoreLabel?.fontSize = 60
finalScoreLabel?.zPosition = 1
if finalScoreLabel != nil {
addChild(finalScoreLabel!)
}
let playButton = SKSpriteNode(imageNamed: "playButton")
playButton.position = CGPoint(x: self.size.width/2, y:self.size.height/2)
playButton.name = "play"
playButton.zPosition = 1
addChild(playButton)
}
override func touchesMoved(_ touches: Set
for t in touches { self.touchMoved(toPoint: t.location(in: self)) }
}
override func touchesEnded(_ touches: Set
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
override func touchesCancelled(_ touches: Set
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
override func update(_ currentTime: TimeInterval) {
moveInvaders()
}
func setupInvaders(){
var invaderRow = 1;
var invaderColumn = 1;
let numberOfInvaders = invaderNum * 2 + 1
for i in 0.. invaderRow = i for j in 0.. invaderColumn = j let tempInvader:Apple = Apple() let invaderHalfWidth:CGFloat = tempInvader.size.width/2 let xPositionStart:CGFloat = size.width/2 - invaderHalfWidth - (CGFloat(invaderNum) * tempInvader.size.width) + CGFloat(10) tempInvader.position = CGPoint(x:xPositionStart + ((tempInvader.size.width+CGFloat(10))*(CGFloat(j-1))), y:CGFloat(self.size.height - CGFloat(i) * 46)) tempInvader.invaderRow = invaderRow tempInvader.invaderColumn = invaderColumn addChild(tempInvader) if(i == self.rowsOfInvaders){ invadersWhoCanFire.append(tempInvader) } } } } func setupPlayer(){ player.zPosition = 1 player.position = CGPoint(x:(self.frame.size.width/4)-50, y:player.size.height+50) addChild(player) } func moveInvaders(){ var changeDirection = false enumerateChildNodes(withName: "apple") { node, stop in let invader = node as! SKSpriteNode let invaderHalfWidth = invader.size.width/2 invader.position.x -= CGFloat(self.invaderSpeed) if(invader.position.x > self.rightBounds - invaderHalfWidth || invader.position.x < self.leftBounds + invaderHalfWidth){ changeDirection = true } } if(changeDirection == true){ self.invaderSpeed *= -1 self.enumerateChildNodes(withName: "apple") { node, stop in let invader = node as! SKSpriteNode invader.position.y -= CGFloat(46) } changeDirection = false } } func fireBullet(scene: SKScene){ bullet = InvandarApple(imageName: "apple",bulletSound: nil) bullet.position.y = self.position.x bullet.position.x = self.position.x - self.size.width/2 scene.addChild(bullet) let moveBulletAction = SKAction.move(to: CGPoint(x:self.position.x,y:bullet.position.y), duration: 2.0) let removeBulletAction = SKAction.removeFromParent() bullet.run(SKAction.sequence([moveBulletAction,removeBulletAction])) } func invokeInvaderFire(){ let fireBullet = SKAction.run(){ self.fireInvaderBullet() } let waitToFireInvaderBullet = SKAction.wait(forDuration: 1.5) let invaderFire = SKAction.sequence([fireBullet,waitToFireInvaderBullet]) let repeatForeverAction = SKAction.repeatForever(invaderFire) run(repeatForeverAction) } // func didBeginContact(contact: SKPhysicsContact) { // var firstBody: SKPhysicsBody // var 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 & CollisionCategories.Invader != 0) && // (secondBody.categoryBitMask & CollisionCategories.PlayerBullet != 0)){ // NSLog("Invader and Player Bullet Conatact") // } // // if ((firstBody.categoryBitMask & CollisionCategories.Player != 0) && // (secondBody.categoryBitMask & CollisionCategories.InvaderBullet != 0)) { // NSLog("Player and Invader Bullet Contact") // } // // if ((firstBody.categoryBitMask & CollisionCategories.Invader != 0) && // (secondBody.categoryBitMask & CollisionCategories.Player != 0)) { // NSLog("Invader and Player Collision Contact") // // } // if ((firstBody.categoryBitMask & CollisionCategories.Player != 0) && // (secondBody.categoryBitMask & CollisionCategories.InvaderBullet != 0)) { // player.die() // } // // if ((firstBody.categoryBitMask & CollisionCategories.Invader != 0) && // (secondBody.categoryBitMask & CollisionCategories.Player != 0)) { // player.kill() // } // // } func didBegin(_ contact: SKPhysicsContact) { if contact.bodyA.categoryBitMask == CollisionCategories.coinCategory { contact.bodyA.node?.removeFromParent() score += 1 scoreLabel?.text = "Score: \(score)" } if contact.bodyB.categoryBitMask == CollisionCategories.coinCategory { contact.bodyB.node?.removeFromParent() score += 1 scoreLabel?.text = "Score: \(score)" } if contact.bodyA.categoryBitMask > contact.bodyB.categoryBitMask{ if cat.position.x == 167.0 { gameOver() } } //if contact.bodyB.categoryBitMask == CollisionCategories.bombCategory { // } } func fireInvaderBullet(){ if(invadersWhoCanFire.isEmpty){ invaderNum += 1 }else{ let randomInvader = invadersWhoCanFire.randomElement() randomInvader.fireBullet(scene: self) } } func spawnCat() { cat = SKSpriteNode(imageNamed: "cat") cat.name = "cat" let catScenePos = CGPoint( // x: CGFloat.random(min: playableRect.minX, // max: playableRect.maxX) x: self.size.width, // y: CGFloat.random(min: playableRect.minY, // max: playableRect.maxY)) y: cat.size.height/2+200) cat.position = self.convert(catScenePos, from: self) cat.physicsBody = SKPhysicsBody(rectangleOf: cat.size) cat.physicsBody?.affectedByGravity = true cat.physicsBody?.categoryBitMask = CollisionCategories.coinCategory cat.physicsBody?.contactTestBitMask = CollisionCategories.coinManCategory cat.physicsBody?.collisionBitMask = 0 addChild(cat) let actionMove = SKAction.moveBy(x: -size.width-cat.size.width, y: 0, duration: 2.0) let actionRemove = SKAction.removeFromParent() cat.run(SKAction.sequence([actionMove, actionRemove])) } func spawnEnemy() { enemy = SKSpriteNode(imageNamed: "enemy") enemy.name = "enemy" let enemyScenePos = CGPoint( x: self.size.width, // y: CGFloat.random( // min: playableRect.minY + enemy.size.height/2, // max: playableRect.maxY - enemy.size.height/2)) y: enemy.size.height/2+175) enemy.physicsBody = SKPhysicsBody(rectangleOf: enemy.frame.size) enemy.physicsBody?.usesPreciseCollisionDetection = true enemy.position = self.convert(enemyScenePos, from: self) enemy.physicsBody = SKPhysicsBody(rectangleOf: enemy.size) enemy.physicsBody?.affectedByGravity = true enemy.physicsBody?.categoryBitMask = CollisionCategories.coinCategory enemy.physicsBody?.contactTestBitMask = CollisionCategories.coinManCategory enemy.physicsBody?.collisionBitMask = 0 enemy.position = self.convert(enemyScenePos, from: self) addChild(enemy) let actionMove = SKAction.moveBy(x: -size.width-enemy.size.width, y: 0, duration: 2.0) let actionRemove = SKAction.removeFromParent() enemy.run(SKAction.sequence([actionMove, actionRemove])) } }
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started