I have tried following a tutorial on YouTube by CraniumCode, to learn the syntax for Swift. The tutorial is to create the game ZigZag.
When I press the Play button I am sent to the game screen containing 10 randomly places pillars and the ball. The game then stops, and I get the error at the top, aswell as
Could not load the "" image referenced from a nib in the bundle with
identifier "user.App".
First time asker, long time reader, still haven't found a viable solution.
Code:
import UIKit
class ViewController: UIViewController {
#IBAction func Play(_ sender: Any) {
self.GameOver.isHidden = true
self.Play.isHidden = true
self.Retry.isHidden = true
self.Logo.isHidden = true
self.Ball.center.x = 178.0
self.Ball.center.y = 390.0
self.Pillar1.center = CGPoint (x: 175.0, y: 436.0)
self.Pillar2.center = CGPoint (x: 214.0, y: 407.0)
timer = Timer.scheduledTimer(timeInterval:0.045, target:self,
selector: Selector("movement"),
userInfo:nil, repeats:true)
self.Pillar3.center = pillarPlacement(x: Pillar2.center.x, y:
Pillar2.center.y)
self.Pillar4.center = pillarPlacement(x: Pillar3.center.x, y:
Pillar3.center.y)
self.Pillar5.center = pillarPlacement(x: Pillar4.center.x, y:
Pillar4.center.y)
self.Pillar6.center = pillarPlacement(x: Pillar5.center.x, y:
Pillar5.center.y)
self.Pillar7.center = pillarPlacement(x: Pillar6.center.x, y:
Pillar6.center.y)
self.Pillar8.center = pillarPlacement(x: Pillar7.center.x, y:
Pillar7.center.y)
self.Pillar9.center = pillarPlacement(x: Pillar8.center.x, y:
Pillar8.center.y)
self.Pillar10.center = pillarPlacement(x: Pillar9.center.x, y:
Pillar9.center.y)
self.Ball.isHidden = false
self.Pillar1.isHidden = false
self.Pillar2.isHidden = false
self.Pillar3.isHidden = false
self.Pillar4.isHidden = false
self.Pillar5.isHidden = false
self.Pillar6.isHidden = false
self.Pillar7.isHidden = false
self.Pillar8.isHidden = false
self.Pillar9.isHidden = false
self.Pillar10.isHidden = false
}
#IBAction func Retry(_ sender: Any) {
}
#IBOutlet var GameView: UIView!
#IBOutlet weak var Pillar1: UIImageView!
#IBOutlet weak var Pillar2: UIImageView!
#IBOutlet weak var Pillar3: UIImageView!
#IBOutlet weak var Pillar4: UIImageView!
#IBOutlet weak var Pillar5: UIImageView!
#IBOutlet weak var Pillar6: UIImageView!
#IBOutlet weak var Pillar7: UIImageView!
#IBOutlet weak var Pillar8: UIImageView!
#IBOutlet weak var Pillar9: UIImageView!
#IBOutlet weak var Pillar10: UIImageView!
#IBOutlet weak var Retry: UIButton!
#IBOutlet weak var Play: UIButton!
#IBOutlet weak var Logo: UIImageView!
#IBOutlet weak var GameOver: UIImageView!
#IBOutlet weak var Ball: UIImageView!
var timer = Timer()
var TapsValid:Bool?
var BallRight:Bool?
var BallChange:Bool?
override func viewDidLoad() {
super.viewDidLoad()
self.GameOver.isHidden = true
self.Play.isHidden = false
self.Retry.isHidden = true
self.Logo.isHidden = false
self.Ball.isHidden = true
self.Pillar1.isHidden = true
self.Pillar2.isHidden = true
self.Pillar3.isHidden = true
self.Pillar4.isHidden = true
self.Pillar5.isHidden = true
self.Pillar6.isHidden = true
self.Pillar7.isHidden = true
self.Pillar8.isHidden = true
self.Pillar9.isHidden = true
self.Pillar10.isHidden = true
}
func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
if (TapsValid == true) {
if (BallRight == true) {
BallChange = false
} else {
BallChange = true
}
}
}
func movement() {
if (BallChange == false) {
BallRight = false
} else {
BallRight = true
}
if (BallRight == true) {
Ball.center.x += 6.5
Ball.center.y -= 0.5
} else {
Ball.center.x -= 6.5
Ball.center.y -= 0.5
}
Ball.center.y += 0.5
Pillar1.center.y += 5
Pillar2.center.y += 5
Pillar3.center.y += 5
Pillar4.center.y += 5
Pillar5.center.y += 5
Pillar6.center.y += 5
Pillar7.center.y += 5
Pillar8.center.y += 5
Pillar9.center.y += 5
Pillar10.center.y += 5
Pillar1.center = movePillarUp(floatx: Pillar1.center.x,
floaty: Pillar1.center.y,
pillarNumber: 1)
Pillar2.center = movePillarUp(floatx: Pillar1.center.x,
floaty: Pillar1.center.y,
pillarNumber: 2)
Pillar3.center = movePillarUp(floatx: Pillar1.center.x,
floaty: Pillar1.center.y,
pillarNumber: 3)
Pillar4.center = movePillarUp(floatx: Pillar1.center.x,
floaty: Pillar1.center.y,
pillarNumber: 4)
Pillar5.center = movePillarUp(floatx: Pillar1.center.x,
floaty: Pillar1.center.y,
pillarNumber: 5)
Pillar6.center = movePillarUp(floatx: Pillar1.center.x,
floaty: Pillar1.center.y,
pillarNumber: 6)
Pillar7.center = movePillarUp(floatx: Pillar1.center.x,
floaty: Pillar1.center.y,
pillarNumber: 7)
Pillar8.center = movePillarUp(floatx: Pillar1.center.x,
floaty: Pillar1.center.y,
pillarNumber: 8)
Pillar9.center = movePillarUp(floatx: Pillar1.center.x,
floaty: Pillar1.center.y,
pillarNumber: 9)
Pillar10.center = movePillarUp(floatx: Pillar1.center.x,
floaty: Pillar1.center.y,
pillarNumber: 10)
}
func movePillarUp(floatx: CGFloat, floaty: CGFloat, pillarNumber: Int )
-> (CGPoint) {
var center = CGPoint(x: floatx, y: floaty)
if checkPillarPosition(y: floaty) == true {
switch pillarNumber{
case 1:
GameView.sendSubview(toBack:Pillar1)
center = pillarPlacement(x: self.Pillar10.center.x, y: self.Pillar10.center.y)
break
case 2:
GameView.sendSubview(toBack:Pillar2)
center = pillarPlacement(x: self.Pillar1.center.x, y: self.Pillar1.center.y)
break
case 3:
GameView.sendSubview(toBack:Pillar3)
center = pillarPlacement(x: self.Pillar2.center.x, y: self.Pillar2.center.y)
break
case 4:
GameView.sendSubview(toBack:Pillar4)
center = pillarPlacement(x: self.Pillar3.center.x, y: self.Pillar3.center.y)
break
case 5:
GameView.sendSubview(toBack:Pillar5)
center = pillarPlacement(x: self.Pillar4.center.x, y: self.Pillar4.center.y)
break
case 6:
GameView.sendSubview(toBack:Pillar6)
center = pillarPlacement(x: self.Pillar5.center.x, y: self.Pillar5.center.y)
break
case 7:
GameView.sendSubview(toBack:Pillar7)
center = pillarPlacement(x: self.Pillar6.center.x, y: self.Pillar6.center.y)
break
case 8:
GameView.sendSubview(toBack:Pillar8)
center = pillarPlacement(x: self.Pillar7.center.x, y: self.Pillar7.center.y)
break
case 9:
GameView.sendSubview(toBack:Pillar9)
center = pillarPlacement(x: self.Pillar8.center.x, y: self.Pillar8.center.y)
break
case 10:
GameView.sendSubview(toBack:Pillar10)
center = pillarPlacement(x: self.Pillar9.center.x, y: self.Pillar9.center.y)
break
default:
break
}
}
return(center)
}
func checkPillarPosition(y: CGFloat) -> (Bool) {
return (y > 720)
}
func pillarPlacement(x: CGFloat, y: CGFloat) -> (CGPoint) {
var pillarNewX: CGFloat
var pillarNewY: CGFloat
let random: Int = Int(arc4random() % 2)
if (random == 1) {
pillarNewX = x + 39
pillarNewY = y - 29
if (pillarNewX >= 319) {
pillarNewX = x - 40
pillarNewY = y - 30
}
} else {
pillarNewX = x - 40
pillarNewY = y - 30
if (pillarNewX <= 17) {
pillarNewX = x + 39
pillarNewY = y - 29
}
}
let newPillarCenter = CGPoint(x: pillarNewX, y: pillarNewY)
return(newPillarCenter)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
var timer = Timer.scheduledTimer(timeInterval:0.045, target:self,
selector: #selector(self.movement), userInfo:nil, repeats:true)
And adding #objc infront of func movement()removed the error!
Here is the entire coded
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var logo: UIImageView!
#IBOutlet weak var gameOver: UIImageView!
#IBAction func Play(_ sender: Any) { //What Happens After you click the "Play" button
tapsValid = true
ballChange = true
self.gameOver.isHidden = true
self.retry.isHidden = true
self.Ball.isHidden = false
self.logo.isHidden = true
self.Play.isHidden = true
self.scoreBoard.isHidden = true
self.Ball.center.x = 178.0
self.Ball.center.y = 390.0
self.pillar.center = CGPoint(x: 175.0,y: 436.0)
self.pillar2.center = CGPoint(x: 214.0,y: 407.0)
timer = Timer.scheduledTimer(timeInterval: 0.045, target: self, selector: #selector(ViewController.movement), userInfo: nil, repeats: true)
self.pillar3.center = pillarPlacement(x: pillar2.center.x, y: pillar2.center.y)
self.pillar4.center = pillarPlacement(x: pillar3.center.x, y: pillar3.center.y)
self.pillar5.center = pillarPlacement(x: pillar4.center.x, y: pillar4.center.y)
self.pillar6.center = pillarPlacement(x: pillar5.center.x, y: pillar5.center.y)
self.pillar7.center = pillarPlacement(x: pillar6.center.x, y: pillar6.center.y)
self.pillar8.center = pillarPlacement(x: pillar7.center.x, y: pillar7.center.y)
self.pillar9.center = pillarPlacement(x: pillar8.center.x, y: pillar8.center.y)
self.pillar10.center = pillarPlacement(x: pillar9.center.x, y: pillar9.center.y)
self.pillar.isHidden = false
self.pillar2.isHidden = false
self.pillar3.isHidden = false
self.pillar4.isHidden = false
self.pillar5.isHidden = false
self.pillar6.isHidden = false
self.pillar7.isHidden = false
self.pillar8.isHidden = false
self.pillar9.isHidden = false
self.pillar10.isHidden = false
self.pillarTop.isHidden = false
self.pillarTop2.isHidden = false
self.pillarTop3.isHidden = false
}
#IBAction func Retry(_ sender: Any) {
}
#IBOutlet var gameView: UIView!
#IBOutlet weak var pillar10: UIImageView!
#IBOutlet weak var pillar9: UIImageView!
#IBOutlet weak var pillar8: UIImageView!
#IBOutlet weak var pillar7: UIImageView!
#IBOutlet weak var pillar6: UIImageView!
#IBOutlet weak var pillar5: UIImageView!
#IBOutlet weak var pillar4: UIImageView!
#IBOutlet weak var pillar3: UIImageView!
#IBOutlet weak var pillar2: UIImageView!
#IBOutlet weak var pillar: UIImageView!
#IBOutlet weak var pillarTop3: UIImageView!
#IBOutlet weak var pillarTop2: UIImageView!
#IBOutlet weak var pillarTop: UIImageView!
#IBOutlet weak var Play: UIButton!
var timer = Timer()
var tapsValid:Bool?
var ballRight:Bool?
var ballChange:Bool?
var ballCenter: CGPoint?
var pillarCenter: CGPoint?
var pillar2Center: CGPoint?
var pillar3Center: CGPoint?
var pillar4Center: CGPoint?
var pillar5Center: CGPoint?
var pillar6Center: CGPoint?
var pillar7Center: CGPoint?
var pillar8Center: CGPoint?
var pillar9Center: CGPoint?
var pillar10Center: CGPoint?
var pillarTopCenter: CGPoint?
var pillarTop2Center: CGPoint?
var pillarTop3Center: CGPoint?
#IBOutlet weak var scoreBoard: UIImageView!
#IBOutlet weak var retry: UIButton!
#IBOutlet weak var Ball: UIImageView!
//Start Screen
override func viewDidLoad() {
super.viewDidLoad()
self.gameOver.isHidden = true
self.retry.isHidden = true
self.Ball.isHidden = true
self.logo.isHidden = false
self.Play.isHidden = false
self.scoreBoard.isHidden = true
self.Ball.isHidden = true
self.pillar.isHidden = true
self.pillar2.isHidden = true
self.pillar3.isHidden = true
self.pillar4.isHidden = true
self.pillar5.isHidden = true
self.pillar6.isHidden = true
self.pillar7.isHidden = true
self.pillar8.isHidden = true
self.pillar9.isHidden = true
self.pillar10.isHidden = true
self.pillarTop.isHidden = true
self.pillarTop2.isHidden = true
self.pillarTop3.isHidden = true
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if tapsValid == true
{
if ballRight == true
{
ballChange = false
} else
{
ballChange = true
}
}
}
func movement()
{
ballCenter = self.Ball.center
pillarCenter = self.pillar.center
pillar2Center = self.pillar2.center
pillar3Center = self.pillar3.center
pillar4Center = self.pillar4.center
pillar5Center = self.pillar5.center
pillar6Center = self.pillar6.center
pillar7Center = self.pillar7.center
pillar8Center = self.pillar8.center
pillar9Center = self.pillar9.center
pillar10Center = self.pillar10.center
if ballChange == false
{
ballRight = false
} else
{
ballRight = true
}
if ballRight == true
{
Ball.center.x += 6.5
Ball.center.y -= 0.5
}else
{
Ball.center.x -= 6.5
Ball.center.y -= 0.5
}
Ball.center.y += 0.5
pillar.center.y += 5.0
pillar2.center.y += 5.0
pillar3.center.y += 5.0
pillar4.center.y += 5.0
pillar5.center.y += 5.0
pillar6.center.y += 5.0
pillar7.center.y += 5.0
pillar8.center.y += 5.0
pillar9.center.y += 5.0
pillar10.center.y += 5.0
pillar.center = movePillarUp(floatx: pillar.center.x, floaty: pillar.center.y, pillarNumber: 1)
pillar2.center = movePillarUp(floatx: pillar2.center.x, floaty: pillar2.center.y, pillarNumber: 2)
pillar3.center = movePillarUp(floatx: pillar3.center.x, floaty: pillar3.center.y, pillarNumber: 3)
pillar4.center = movePillarUp(floatx: pillar4.center.x, floaty: pillar4.center.y, pillarNumber: 4)
pillar5.center = movePillarUp(floatx: pillar5.center.x, floaty: pillar5.center.y, pillarNumber: 5)
pillar6.center = movePillarUp(floatx: pillar6.center.x, floaty: pillar6.center.y, pillarNumber: 6)
pillar7.center = movePillarUp(floatx: pillar7.center.x, floaty: pillar7.center.y, pillarNumber: 7)
pillar8.center = movePillarUp(floatx: pillar8.center.x, floaty: pillar8.center.y, pillarNumber: 8)
pillar9.center = movePillarUp(floatx: pillar9.center.x, floaty: pillar9.center.y, pillarNumber: 9)
pillar10.center = movePillarUp(floatx: pillar10.center.x, floaty: pillar10.center.y, pillarNumber: 10)
}
func movePillarUp(floatx: CGFloat, floaty: CGFloat, pillarNumber: Int) -> (CGPoint)
{
var center = CGPoint(x: floatx,y: floaty)
if checkPillarPosition(y: floaty) == true
{
switch pillarNumber
{
case 1:
gameView.sendSubview(toBack: pillar)
center = pillarPlacement(x: self.pillar10.center.x, y: self.pillar10.center.y)
break
case 2:
gameView.sendSubview(toBack: pillar2)
center = pillarPlacement(x: self.pillar.center.x, y: self.pillar.center.y)
break
case 3:
gameView.sendSubview(toBack: pillar3)
center = pillarPlacement(x: self.pillar2.center.x, y: self.pillar2.center.y)
break
case 4:
gameView.sendSubview(toBack: pillar4)
center = pillarPlacement(x: self.pillar3.center.x, y: self.pillar3.center.y)
break
case 5:
gameView.sendSubview(toBack: pillar5)
center = pillarPlacement(x: self.pillar4.center.x, y: self.pillar4.center.y)
break
case 6:
gameView.sendSubview(toBack: pillar6)
center = pillarPlacement(x: self.pillar5.center.x, y: self.pillar5.center.y)
break
case 7:
gameView.sendSubview(toBack: pillar7)
center = pillarPlacement(x: self.pillar6.center.x, y: self.pillar6.center.y)
break
case 8:
gameView.sendSubview(toBack: pillar8)
center = pillarPlacement(x: self.pillar7.center.x, y: self.pillar7.center.y)
break
case 9:
gameView.sendSubview(toBack: pillar9)
center = pillarPlacement(x: self.pillar8.center.x, y: self.pillar8.center.y)
break
case 10:
gameView.sendSubview(toBack: pillar10)
center = pillarPlacement(x: self.pillar9.center.x, y: self.pillar9.center.y)
break
default:
break
}
}
return(center)
}
func checkPillarPosition(y: CGFloat) -> (Bool)
{
var low = false
if y>720
{
low = true
}
return(low)
}
override func viewDidLayoutSubviews()
{
if let newBallCenter = ballCenter{
self.Ball.center = newBallCenter
}
if let newPillarCenter = pillarCenter{
self.pillar.center = newPillarCenter
}
if let newPillar2Center = pillar2Center{
self.pillar2.center = newPillar2Center
}
if let newPillar3Center = pillar3Center{
self.pillar3.center = newPillar3Center
}
if let newPillar4Center = pillar4Center{
self.pillar4.center = newPillar4Center
}
if let newPillar5Center = pillar5Center{
self.pillar5.center = newPillar5Center
}
if let newPillar6Center = pillar6Center{
self.pillar6.center = newPillar6Center
}
if let newPillar7Center = pillar7Center{
self.pillar7.center = newPillar7Center
}
if let newPillar8Center = pillar8Center{
self.pillar8.center = newPillar8Center
}
if let newPillar9Center = pillar9Center{
self.pillar9.center = newPillar9Center
}
if let newPillar10Center = pillar10Center{
self.pillar10.center = newPillar10Center
}
if let newPillarTopCenter = pillarTopCenter{
self.pillarTop.center = newPillarTopCenter
}
if let newPillarTop2Center = pillarTop2Center{
self.pillarTop2.center = newPillarTop2Center
}
if let newPillarTop3Center = pillarTop3Center{
self.pillarTop3.center = newPillarTop3Center
}
}
// This Function Places the Pillars
func pillarPlacement(x:CGFloat , y:CGFloat ) -> (CGPoint)
{
var pillarNewX:CGFloat
var pillarNewY:CGFloat
var random:Int = Int(arc4random() % 2)
if random == 1
{
pillarNewX = x + 39
pillarNewY = y - 29
if pillarNewX >= 319
{
pillarNewX = x-40
pillarNewY = y-30
}
}
else
{
pillarNewX = x - 40
pillarNewY = y - 30
if pillarNewX <= 17
{
pillarNewX = x+39
pillarNewY = y-29
}
}
var newPillarCenter = CGPoint(x: pillarNewX,y: pillarNewY)
return(newPillarCenter)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The problem pops up here
func movement()
{
ballCenter = self.Ball.center
pillarCenter = self.pillar.center
pillar2Center = self.pillar2.center
pillar3Center = self.pillar3.center
pillar4Center = self.pillar4.center
pillar5Center = self.pillar5.center
pillar6Center = self.pillar6.center
pillar7Center = self.pillar7.center
pillar8Center = self.pillar8.center
pillar9Center = self.pillar9.center
pillar10Center = self.pillar10.center
if ballChange == false
{
ballRight = false
} else
{
ballRight = true
}
if ballRight == true
{
Ball.center.x += 6.5
Ball.center.y -= 0.5
}else
{
Ball.center.x -= 6.5
Ball.center.y -= 0.5
}
Ball.center.y += 0.5
pillar.center.y += 5.0
pillar2.center.y += 5.0
pillar3.center.y += 5.0
pillar4.center.y += 5.0
pillar5.center.y += 5.0
pillar6.center.y += 5.0
pillar7.center.y += 5.0
pillar8.center.y += 5.0
pillar9.center.y += 5.0
pillar10.center.y += 5.0
pillar.center = movePillarUp(floatx: pillar.center.x, floaty: pillar.center.y, pillarNumber: 1)
pillar2.center = movePillarUp(floatx: pillar2.center.x, floaty: pillar2.center.y, pillarNumber: 2)
pillar3.center = movePillarUp(floatx: pillar3.center.x, floaty: pillar3.center.y, pillarNumber: 3)
pillar4.center = movePillarUp(floatx: pillar4.center.x, floaty: pillar4.center.y, pillarNumber: 4)
pillar5.center = movePillarUp(floatx: pillar5.center.x, floaty: pillar5.center.y, pillarNumber: 5)
pillar6.center = movePillarUp(floatx: pillar6.center.x, floaty: pillar6.center.y, pillarNumber: 6)
pillar7.center = movePillarUp(floatx: pillar7.center.x, floaty: pillar7.center.y, pillarNumber: 7)
pillar8.center = movePillarUp(floatx: pillar8.center.x, floaty: pillar8.center.y, pillarNumber: 8)
pillar9.center = movePillarUp(floatx: pillar9.center.x, floaty: pillar9.center.y, pillarNumber: 9)
pillar10.center = movePillarUp(floatx: pillar10.center.x, floaty: pillar10.center.y, pillarNumber: 10)
}
Specifically this line
pillar9.center = movePillarUp(floatx: pillar9.center.x, floaty: pillar9.center.y, pillarNumber: 9)
Any help would be appreciated. Sorry If this question was already asked, but, I could not find it anywhere. I am new to Swift and XCode, so if you could go into some depth of what I am doing wrong, that would be lovely and extremely helpful. Thank you for all the help!
Aside from there being a breakpoint set (which should be checked first, of course!) you have a lot of repeated code which can be a great source of errors. Not having your entire project I can't test it all but I've simplified it quite a bit by using an array to hold your pillar UIImageView objects:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var logo: UIImageView!
#IBOutlet weak var gameOver: UIImageView!
#IBAction func Play(_ sender: Any) { //What Happens After you click the "Play" button
tapsValid = true
ballChange = true
self.gameOver.isHidden = true
self.retry.isHidden = true
self.Ball.isHidden = false
self.logo.isHidden = true
self.Play.isHidden = true
self.scoreBoard.isHidden = true
self.Ball.center.x = 178.0
self.Ball.center.y = 390.0
timer = Timer.scheduledTimer(timeInterval: 0.045, target: self, selector: #selector(ViewController.movement), userInfo: nil, repeats: true)
// verify that we have more than 2 pillars before we use subscripts
guard pillars.count > 2 else { return }
self.pillars[0].isHidden = false
self.pillars[0].center = CGPoint(x: 175.0,y: 436.0)
self.pillars[1].center = CGPoint(x: 214.0,y: 407.0)
var last = self.pillars[1]
for pillar in self.pillars.suffix(from: 2) {
last.isHidden = false
pillar.center = pillarPlacement(center: last.center)
last = pillar
}
}
#IBAction func Retry(_ sender: Any) {
}
// outlet collection
#IBOutlet var pillars: [UIImageView]!
#IBOutlet var gameView: UIView!
#IBOutlet weak var pillarTop3: UIImageView!
#IBOutlet weak var pillarTop2: UIImageView!
#IBOutlet weak var pillarTop: UIImageView!
#IBOutlet weak var Play: UIButton!
var timer = Timer()
var tapsValid:Bool?
var ballRight:Bool?
var ballChange:Bool?
var ballCenter: CGPoint?
var pillarTopCenter: CGPoint?
var pillarTop2Center: CGPoint?
var pillarTop3Center: CGPoint?
#IBOutlet weak var scoreBoard: UIImageView!
#IBOutlet weak var retry: UIButton!
#IBOutlet weak var Ball: UIImageView!
//Start Screen
override func viewDidLoad() {
super.viewDidLoad()
self.gameOver.isHidden = true
self.retry.isHidden = true
self.Ball.isHidden = true
self.logo.isHidden = false
self.Play.isHidden = false
self.scoreBoard.isHidden = true
self.Ball.isHidden = true
self.pillarTop.isHidden = true
self.pillarTop2.isHidden = true
self.pillarTop3.isHidden = true
// set the whole collection at once
self.pillars.forEach { $0.isHidden = true }
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if tapsValid == true
{
if ballRight == true
{
ballChange = false
} else
{
ballChange = true
}
}
}
func movement()
{
ballCenter = self.Ball.center
if ballChange == false
{
ballRight = false
} else
{
ballRight = true
}
if ballRight == true
{
Ball.center.x += 6.5
Ball.center.y -= 0.5
} else
{
Ball.center.x -= 6.5
Ball.center.y -= 0.5
}
Ball.center.y += 0.5
// move all the pillars
pillars.forEach(movePillarUp)
}
func movePillarUp(pillar: UIImageView)
{
pillar.center.y += 5.0
if pillar.center.y > 720
{
gameView.sendSubview(toBack: pillar)
pillar.center = pillarPlacement(center: pillar.center)
}
}
override func viewDidLayoutSubviews()
{
if let newBallCenter = ballCenter{
self.Ball.center = newBallCenter
}
if let newPillarTopCenter = pillarTopCenter{
self.pillarTop.center = newPillarTopCenter
}
if let newPillarTop2Center = pillarTop2Center{
self.pillarTop2.center = newPillarTop2Center
}
if let newPillarTop3Center = pillarTop3Center{
self.pillarTop3.center = newPillarTop3Center
}
}
// This Function Places the Pillars
func pillarPlacement(center: CGPoint) -> CGPoint
{
var newCenter = center
if Int(arc4random() % 2) == 1
{
newCenter.x += 39
newCenter.y -= 29
if newCenter.x >= 319
{
newCenter.x -= 40
newCenter.y -= 30
}
}
else
{
newCenter.x -= 40
newCenter.y -= 30
if newCenter.x <= 17
{
newCenter.x += 39
newCenter.y -= 29
}
}
return newCenter
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You can connect to the pillars outlet collection the same way you do a normal outlet, it will appear under the heading "Outlet Connections". The order in which you add the connections will determine the index of each connection. Now all of your pillars can be under one collection and can be handled at once using loops and other methods. This will reduce code size, decrease the chance of errors, and allow for easier development.
Please test this code and see if it clears up your issue.
I am making a grid game in swift where there is a five by five grid of squares and they each are a skspritenode and when the player moves on them they turn to a different color.
This is what i have done so far
import SpriteKit
class GameScene: SKScene {
var alive = Bool()
var targetColors = Array<UIColor>()
var permanent = Array<Bool>()
var has3Colors = Array<Bool>()
var secondColors = Array<UIColor>()
var positions = Array<CGPoint>()
var startColors = Array<UIColor>()
var circle = SKSpriteNode()
var completedSquares = Int()
var started = Bool()
var squares = Array<SKSpriteNode>()
var square1 = SKSpriteNode(imageNamed: "SquareTile")
var square2 = SKSpriteNode(imageNamed: "SquareTile")
var square3 = SKSpriteNode(imageNamed: "SquareTile")
var square4 = SKSpriteNode(imageNamed: "SquareTile")
var square5 = SKSpriteNode(imageNamed: "SquareTile")
var square6 = SKSpriteNode(imageNamed: "SquareTile")
var square7 = SKSpriteNode(imageNamed: "SquareTile")
var square8 = SKSpriteNode(imageNamed: "SquareTile")
var square9 = SKSpriteNode(imageNamed: "SquareTile")
var square10 = SKSpriteNode(imageNamed: "SquareTile")
var square11 = SKSpriteNode(imageNamed: "SquareTile")
var square12 = SKSpriteNode(imageNamed: "SquareTile")
var square13 = SKSpriteNode(imageNamed: "SquareTile")
var square14 = SKSpriteNode(imageNamed: "SquareTile")
var square15 = SKSpriteNode(imageNamed: "SquareTile")
var square16 = SKSpriteNode(imageNamed: "SquareTile")
var square17 = SKSpriteNode(imageNamed: "SquareTile")
var square18 = SKSpriteNode(imageNamed: "SquareTile")
var square19 = SKSpriteNode(imageNamed: "SquareTile")
var square20 = SKSpriteNode(imageNamed: "SquareTile")
var square21 = SKSpriteNode(imageNamed: "SquareTile")
var square22 = SKSpriteNode(imageNamed: "SquareTile")
var square23 = SKSpriteNode(imageNamed: "SquareTile")
var square24 = SKSpriteNode(imageNamed: "SquareTile")
var square25 = SKSpriteNode(imageNamed: "SquareTile")
var basicSize = CGSize()
var columb1 = CGFloat()
var columb2 = CGFloat()
var columb3 = CGFloat()
var columb4 = CGFloat()
var columb5 = CGFloat()
var row1 = CGFloat()
var row2 = CGFloat()
var row3 = CGFloat()
var row4 = CGFloat()
var row5 = CGFloat()
var targetColor = UIColor()
var isPermanent = Bool()
var hasThreeColors = Bool()
var secondColor = UIColor()
var position1 = CGPoint()
var startColor = UIColor()
var square = SKSpriteNode()
override func didMove(to view: SKView) {
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
if started == false{
started = true
start()
for i in 0 ... 24{
targetColor = targetColors[i]
isPermanent = permanent[i]
hasThreeColors = has3Colors[i]
secondColor = secondColors[i]
position1 = positions[i]
startColor = startColors[i]
square = squares[i]
createSquare(targetColor: targetColor, permanent: isPermanent, has3Colors: hasThreeColors, secondColor: secondColor, position: position1, startColor: startColor, newSquare: square)
}
self.addChild(square1)
self.addChild(square2)
self.addChild(square3)
self.addChild(square4)
self.addChild(square5)
self.addChild(square6)
self.addChild(square7)
self.addChild(square8)
self.addChild(square9)
self.addChild(square10)
self.addChild(square11)
self.addChild(square12)
self.addChild(square13)
self.addChild(square14)
self.addChild(square15)
self.addChild(square16)
self.addChild(square17)
self.addChild(square18)
self.addChild(square19)
self.addChild(square20)
self.addChild(square21)
self.addChild(square22)
self.addChild(square23)
self.addChild(square24)
self.addChild(square25)
}
circle.run(SKAction.moveTo(x: location.x, duration: 0.2))
}
}
func createSquare(targetColor: UIColor, permanent: Bool, has3Colors: Bool, secondColor: UIColor, position: CGPoint, startColor:UIColor, newSquare: SKSpriteNode){
var border = SKSpriteNode()
var firstTouch = Bool()
border = SKSpriteNode(imageNamed: "BorderTile")
newSquare.size = basicSize
newSquare.position = position
newSquare.color = startColor
border.size = newSquare.size
border.position = newSquare.position
firstTouch = true
self.addChild(border)
if permanent{
border.color = targetColor
}else{
let targetColor1 = targetColor.darker()
border.color = targetColor1
}
func start(){
basicSize = CGSize(width: self.frame.width / 7, height: self.frame.width / 7)
createCircle()
getArrays()
}
func getArrays(){
rowsAndColumbs()
squares = [square1,square2,square3,square4,square5,square6,square7,square8,square8,square10,square11,square12,square13,square14,square15,square16,square17,square1,square19,square20,square21,square22,square23,square24,square25]
positions = [CGPoint(x: row1,y:columb1),CGPoint(x: row1,y:columb2),CGPoint(x: row1,y:columb3),CGPoint(x: row1,y:columb4),CGPoint(x: row1,y:columb5),CGPoint(x: row2,y:columb1),CGPoint(x: row2,y:columb2),CGPoint(x: row2,y:columb3),CGPoint(x: row2,y:columb4),CGPoint(x: row2,y:columb5),CGPoint(x: row3,y:columb1),CGPoint(x: row3,y:columb2),CGPoint(x: row3,y:columb3),CGPoint(x: row3,y:columb4),CGPoint(x: row3,y:columb5),CGPoint(x: row4,y:columb1),CGPoint(x: row4,y:columb2),CGPoint(x: row4,y:columb1),CGPoint(x: row4,y:columb1),CGPoint(x: row4,y:columb1),CGPoint(x: row5,y:columb1),CGPoint(x: row5,y:columb2),CGPoint(x: row5,y:columb3),CGPoint(x: row5,y:columb4),CGPoint(x: row5,y:columb5)]
loadLvl1()
}
func loadLvl1(){
var targetColors1 = Array<UIColor>()
var permanent1 = Array<Bool>()
var has3Colors1 = Array<Bool>()
var secondColors1 = Array<UIColor>()
var startColors1 = Array<UIColor>()
targetColors1 = [.green,.green,.green,.green,.green,.green,.green,.green,.green,.green,.green,.green,.green,.green,.green,.green,.green,.green,.green,.green,.green,.green,.green,.green,.green]
permanent1 = [true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true]
secondColors1 = [.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear,.clear]
has3Colors1 = [false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false]
startColors1 = [.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue,.blue]
var lvl1Array = Array<Array<Any>>()
lvl1Array = [targetColors1,permanent1,has3Colors1,secondColors1,startColors1]
targetColors = lvl1Array[0] as! Array<UIColor>
permanent = lvl1Array[1] as! Array<Bool>
has3Colors = lvl1Array[2] as! Array<Bool>
secondColors = lvl1Array[3] as! Array<UIColor>
startColors = lvl1Array[4] as! Array<UIColor>
}
func rowsAndColumbs(){
columb1 = CGFloat( basicSize.width * 1.5)
columb2 = CGFloat( basicSize.width * 2.5)
columb3 = CGFloat( basicSize.width * 3.5)
columb4 = CGFloat( basicSize.width * 4.5)
columb5 = CGFloat( basicSize.width * 5.5)
row1 = CGFloat( basicSize.height * 5.5)
row1 = CGFloat( basicSize.height * 4.5)
row1 = CGFloat( basicSize.height * 3.5)
row1 = CGFloat( basicSize.height * 2.5)
row1 = CGFloat( basicSize.height * 1.5)
}
func createCircle(){
circle = SKSpriteNode(imageNamed: "Circle")
circle.size = CGSize(width: self.frame.width / 7, height: self.frame.width / 7)
circle .position = CGPoint(x: 50, y: 50)
self.addChild(circle)
//alive = true
}
override func update(_ currentTime: TimeInterval) {}
// Called before each frame is rendered
}
What i have done is there is a function that uses an array of arrays of values to make the grid but i know there would be a better way to do this and shorten it but i don't know how. I have considered structs but still they would be really long sense i have so any values and i know there is a better way to do this so can someone tell me.
Well, I'll just give you one hint. Think about replacing this:
var columb1 = CGFloat()
var columb2 = CGFloat()
var columb3 = CGFloat()
var columb4 = CGFloat()
var columb5 = CGFloat()
// ...
columb1 = CGFloat( basicSize.width * 1.5)
columb2 = CGFloat( basicSize.width * 2.5)
columb3 = CGFloat( basicSize.width * 3.5)
columb4 = CGFloat( basicSize.width * 4.5)
columb5 = CGFloat( basicSize.width * 5.5)
with this:
var columns : [CGFloat] = (1...5).map {basicSize.width * (CGFloat($0) + 0.5)}
Do you see the difference? I don't just mean the fact that we've reduced 10 lines to 1 line. I mean that we completely eliminated columb1, columb2, and so on — instead, we are using one variable, an array, and we're using it as an array.
You have a feeling something is wrong, and you're quite right. There is no need for all your intermediate variables with numbers on the end of the name. Throw them all away. An array serves exactly that purpose; that is what an array is — a name together with a number (the index number) that references one of many values. Use patterns, loops, and arrays for storage; that is what basic programming is.
You have a number of arrays that contain 25 items, one for each square. What you really need is a class or struct that represents a square that has the properties held by those arrays:
class Square {
var node = SKSpriteNode(imageNamed: "SquareTile")
var startColor = UIColor.blue
var secondColor = UIColor.clear
var targetColor = UIColor.green
var permanent = true
var has3Colors = false
}
// create the array of squares
var squares = (1...25).map { _ in Square() }
// add the nodes as children of self
squares.forEach { self.addChild($0.node) }
You then access each square by index: square[0], square[1], all the way to square[24].
The properties are accessed like square[0].startColor and square[7].has3Colors.