swift4(Xcode9)iPhoneアプリ、パズドラ風ゲームを作成する
こちらのサイトで紹介されていたコードはswift4環境だと
エラーが沢山出たので、修正したのを紹介する。
swiftという言語は頻繁にバージョンアップし内容も変わるので、超うんこ面倒くさい。
恐らく、数年もしないうちに、swift5、6・・・と出て、(2018年1月の現時点)互換性がすぐ無くなるだろうと思う。iphoneという機種が世代交代する度に機能に併せてバージョンアップしているから仕方ないかもしれない。(・・にしてもである(´Д` ))
プロジェクトはSingle View Appで作る。
modelフォルダを作成して、samp04.swift,GameSene4.swiftを新規作成、他のファイルはいじらない。
Assets.xcassetsにアイコン配置。
アイコンは以下を利用した。
(他のタイルについては、面倒なので用意していない。)
Mainstory.board、画面の上の左側をクリックして
custam classにsamp04(この画面で実行するクラス)を指定する。
samp04.swift
// // samp04.swift // Pazz // // Created by su5file on 2018/01/29. // Copyright © 2018年 su5file. All rights reserved. // import UIKit import SpriteKit let _w = UIScreen.main.bounds.size.width let _h = UIScreen.main.bounds.size.height class samp04: UIViewController { var skView : SKView? override func viewDidLoad() { super.viewDidLoad() let sv = SKView(frame: CGRect(x:0, y:0,width:_w,height:_h)) let ss = GameScene4(size: sv.frame.size) sv.presentScene(ss) view.addSubview(sv) } open override var shouldAutorotate: Bool { return true } open override var supportedInterfaceOrientations: UIInterfaceOrientationMask { if UIDevice.current.userInterfaceIdiom == .phone { return UIInterfaceOrientationMask(rawValue: UIInterfaceOrientationMask.RawValue(Int(UIInterfaceOrientationMask.allButUpsideDown.rawValue)));UIInterfaceOrientationMask.allButUpsideDown } else { return UIInterfaceOrientationMask(rawValue: UIInterfaceOrientationMask.RawValue(Int(UIInterfaceOrientationMask.all.rawValue)));UIInterfaceOrientationMask.all } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Release any cached data, images, etc that aren't in use. } // 追加 override var prefersStatusBarHidden: Bool { return true } }
GameScene4.swift
// // GameSene4.swift // Pazz // // Created by su5file on 2018/01/29. // Copyright © 2018年 su5file. All rights reserved. // import UIKit import SpriteKit let NumColumns = 6 let NumRows = 10 let TileSize:CGFloat = 50 let BoardLayerPosition = CGPoint(x:20, y:-80) let TextFieldPosition = CGPoint(x:20, y:-20) class GameScene4: SKScene { var board = SKSpriteNode() let boardLayer = SKNode() let shapeLayer = SKNode() let textLayer = SKNode() let strLayer = SKNode() let score = SKLabelNode() var tileArrayPos = Array(repeating: Array(repeating: CGPoint(), count: NumRows), count: NumColumns) var touchedNode = SKNode() var moveActionFlag = false var scorePoint = 0 override init(size:CGSize){ super.init(size: size) backgroundColor = UIColor.gray anchorPoint = CGPoint(x:0, y:1.0) addChild(boardLayer) addChild(textLayer) board = SKSpriteNode(color:UIColor.white,size:CGSize(width:CGFloat(NumColumns)*TileSize, height:CGFloat(NumRows)*TileSize)) board.name = "board" board.anchorPoint = CGPoint(x:0, y:1.0) board.position = BoardLayerPosition let textfield = SKSpriteNode(color:UIColor.white,size:CGSize(width:CGFloat(NumColumns)*TileSize,height: 80)) textfield.position = TextFieldPosition textfield.anchorPoint = CGPoint(x:0, y:1.0) score.fontColor = UIColor.black score.position = CGPoint(x:textfield.position.x*10, y:textfield.position.y-30) textfield.addChild(score) strLayer.position = TextFieldPosition strLayer.addChild(textfield) textLayer.addChild(strLayer) shapeLayer.position = BoardLayerPosition shapeLayer.addChild(board) boardLayer.addChild(shapeLayer) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func didMove(to view: SKView) { /* Setup your scene here */ initMakeTile() } //タイルの初期化 func randomColor()->UIColor{ //0:red,1:green,2:blue,3:yellow let rnd = arc4random()%4 var color:UIColor! switch rnd{ case 0: color = UIColor.red case 1: color = UIColor.green case 2: color = UIColor.blue case 3: color = UIColor.yellow default: break } return color } //タイルの初期化 func initMakeTile(){ for i in 0..<NumColumns{ for j in 0..<NumRows{ let sprite = makeTileOne() sprite.position = CGPoint(x:CGFloat(i)*TileSize,y:-CGFloat(j)*TileSize) tileArrayPos[i][j] = sprite.position board.addChild(sprite) } } } //タイルの初期化 func makeTileOne()->SKSpriteNode{ let sprite = SKSpriteNode() sprite.anchorPoint = CGPoint(x:0, y:1.0) sprite.alpha *= 0.8 sprite.color = randomColor() sprite.size = CGSize(width:TileSize-1, height:TileSize-1) if sprite.color == .red { // 画像を変更 sprite.texture = SKTexture(imageNamed: "icons8cat.png") } return sprite } //タイルの移動 func moveTile(node:SKNode){ let touchedAction = SKAction.move(to: node.position, duration: 0.08) let passeagedAction = SKAction.move(to: touchedNode.position, duration: 0.08) moveActionFlag = true touchedNode.run(touchedAction, completion: {self.moveActionFlag = false}) node.run(passeagedAction, completion: {self.moveActionFlag = false}) } func searchNode(pos:CGPoint)->SKSpriteNode{ let node = self.atPoint(CGPoint(x:pos.x+TileSize,y:pos.y-4*TileSize)) return node as! SKSpriteNode } func searchEmpty(node:SKSpriteNode)-> Int{ var count = 0 if(node.name != "board"){ for k in Int(-1*node.position.y/TileSize)..<NumRows{ let sprite = searchNode(pos: tileArrayPos[Int(node.position.x/TileSize)][k]) if(sprite.name == "board"){ count+=1 } } } return count } func insertArray( arrayA:inout [SKNode],arrayB:[SKNode]){ for node in arrayB{ arrayA.append(node) } } func deleteColumns( array:inout [SKNode]){ var deleteColumnsArray = Array(arrayLiteral:SKNode()) for i in 0..<NumColumns{ var color = searchNode(pos: tileArrayPos[i][0]).color var count = 0 for j in 0..<NumRows{ let node = searchNode(pos: tileArrayPos[i][j]) if(color == node.color){ deleteColumnsArray.append(node) count+=1 }else{ if(count >= 3){ insertArray(arrayA: &array, arrayB: deleteColumnsArray) } deleteColumnsArray.removeAll() deleteColumnsArray.append(node) color = node.color count = 1 } } if(count >= 3){ insertArray(arrayA: &array, arrayB: deleteColumnsArray) } deleteColumnsArray.removeAll() } } func deleteRows( array:inout [SKNode]){ var deleteRowsArray = Array(arrayLiteral:SKNode()) for j in 0..<NumRows{ var color = searchNode(pos: tileArrayPos[0][j]).color var count = 0 for i in 0..<NumColumns{ let node = searchNode(pos: tileArrayPos[i][j]) if(color == node.color){ deleteRowsArray.append(node) count+=1 }else{ if(count >= 3){ insertArray(arrayA: &array, arrayB: deleteRowsArray) } deleteRowsArray.removeAll() deleteRowsArray.append(node) color = node.color count = 1 } } if(count >= 3){ insertArray(arrayA: &array, arrayB: deleteRowsArray) } deleteRowsArray.removeAll() } } //タイルの消去と落ちる処理 func dropTile(completion:@escaping ()->()){ for i in 0..<NumColumns{ for j in 0..<NumRows{ let k = searchEmpty(node: searchNode(pos: tileArrayPos[i][j])) if(k != 0){ let sprite = searchNode(pos: tileArrayPos[i][j]) let action = SKAction.move(to: tileArrayPos[i][j+k], duration: 0.1) sprite.run(action) } } } run(SKAction.wait(forDuration: 0.2), completion: completion) } func makeTileInEmpty(completion:@escaping ()->()){ var emptyList = Array(repeating:0, count:NumColumns) for i in 0..<NumColumns{ var count = 0 for j in 0..<NumRows{ if(searchNode(pos: tileArrayPos[i][j]).name == "board"){ count+=1 scorePoint += 100 } } emptyList[i] = count } var i = 0 for k in emptyList{ for j in 0..<k{ let sprite = makeTileOne() board.addChild(sprite) let action = SKAction.move(to: tileArrayPos[i][j], duration: 0.1) sprite.run(action) } i+=1 } run(SKAction.wait(forDuration: 0.2), completion: completion) } //タイルの消去と落ちる処理 func deleteAndDropTile(){ var deleteTileArray = Array(arrayLiteral:SKNode()) deleteTileArray.removeAll() deleteColumns(array: &deleteTileArray) deleteRows(array: &deleteTileArray) if(deleteTileArray.isEmpty){ moveActionFlag = false return } board.removeChildren(in: deleteTileArray) dropTile(){ self.makeTileInEmpty(){ self.deleteAndDropTile() } } } //タッチ操作 override func touchesBegan(_ touches: Set, with event: UIEvent?) { /* Called when a touch begins */ for touch in touches { let location = touch.location(in: self) touchedNode = self.atPoint(location) for node in self.board.children{ if(touchedNode == node as NSObject && !moveActionFlag){ touchedNode.alpha *= 0.5 } } } } override func touchesMoved(_ touches: Set , with event: UIEvent?) { for touch in touches { let location = touch.location(in: self) let passagedNode = self.atPoint(location) for node in self.board.children{ if(passagedNode == node as NSObject && touchedNode != passagedNode && !moveActionFlag){ moveTile(node: passagedNode) } } } } override func touchesEnded(_ touches: Set , with event: UIEvent?) { for touch in touches { let location = touch.location(in: self) let endedNode = self.atPoint(location) for node in self.board.children{ if(endedNode == node as NSObject && !moveActionFlag){ moveActionFlag = true deleteAndDropTile() touchedNode.alpha *= 2 } } } } override func update(_ currentTime: CFTimeInterval) { /* Called before each frame is rendered */ score.text = "Score : \(scorePoint)" } }
ちなみに、わしのパズドラのランクは379(´Д` )だす。
以上。
参考URL
https://qiita.com/konpeto000/items/0003db7e561fb03a4c8a