Converting UIKit to SceneKit

UIKit to SceneKit problem conversion program. The biggest challenge for me is understanding how the delegate file, Tile, synchronized with the array, Board, is set to SceneKit. This is a simple project. Screenshot: http://imgur.com/9hsv7X5 . It renders a 3 x 5 array. The user removes the item and becomes highlighted. Then touch another item, it will be highlighted, the previous item is not highlighted.

Here is a UIKit project with 3 files:

VIEWCONTROLLER

import UIKit

struct BoardLoc {
    var x: Int
    var y: Int
}

class ViewController: UIViewController, TileDelegate {

    var tile: Tile!

    override func viewDidLoad() {
        super.viewDidLoad()

        let scene = Board()
        tile.tileDelegate = self
        tile.board = scene
    }

    func getTileAtLoc(tile: Tile, _ boardLoc: BoardLoc) {
        tile.boardLoc = boardLoc
    }  
}

      

TIP

import Foundation

class Board {
    var board: Array<Array<String>> = Array(count:3, repeatedValue:Array(count:5, repeatedValue:"foo"))

    func putTileAt(boardLoc: BoardLoc) -> String {
        return board[boardLoc.x][boardLoc.y]
    }  
}

      

TILE

import UIKit

protocol TileDelegate {
    func getTileAtLoc(tile: Tile, _ boardLoc: BoardLoc)
}

class Tile: UIView {
    var boardLoc: BoardLoc?
    var board: Board?
    var tileDelegate: TileDelegate?

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        addGestureRecognizer(UITapGestureRecognizer(target: self, action:"handleTap:"))
    }

    override func drawRect(rect: CGRect) {
        for x in 0...2 {
            for y in 0...4 {

                let context = UIGraphicsGetCurrentContext()
                let red = UIColor.redColor().CGColor
                let orange = UIColor.orangeColor().CGColor
                let bigCircle = CGRectMake(CGFloat(106 * x),CGFloat(106 * y), 106, 106)
                let smallCircle = CGRectMake(CGFloat(106 * x) + 3, CGFloat(106 * y) + 3, 100, 100)

                if (boardLoc != nil && boardLoc!.x == x && boardLoc!.y == y) {
                    CGContextSetFillColorWithColor(context, red)
                    CGContextFillEllipseInRect(context, bigCircle)
                }

                if board!.putTileAt(BoardLoc(x: x, y: y)) == "foo" {
                    CGContextSetFillColorWithColor(context, orange)
                    CGContextFillEllipseInRect(context, smallCircle)
                }
            }
        }
    }

    func handleTap(gestureRecognizer: UIGestureRecognizer) {
        let point = gestureRecognizer.locationInView(self)
        let boardLoc = BoardLoc(x: Int(point.x) / 106, y: Int(point.y) / 106)
        tileDelegate!.getTileAtLoc(self, boardLoc)
        setNeedsDisplay()
    }
}

      

+3


source to share


2 answers


import SceneKit

class GameViewController: UIViewController {

struct BoardLoc {
    var x: Int
    var y: Int
}

enum Type {
    case Yellow
    case Orange
}

var boardArray: Array<Array<Type>> = []

override func viewDidLoad() {
    super.viewDidLoad()

    for x in 0...2 {
        boardArray.append(Array(count:5, repeatedValue:Type.Orange))
        for y in 0...4 {
            boardArray[x][y] = Type.Orange
        }
    }

    let scene = SCNScene(named: "art.scnassets/balls8.dae")
    let scnView = self.view as SCNView
    scnView.scene = scene

    scnView.autoenablesDefaultLighting = true

    let taps = NSMutableArray()
    let tap = UITapGestureRecognizer(target: self, action: "handleTap:")
    taps.addObject(tap)
    scnView.gestureRecognizers = taps
}

func handleTap(gestureRecognizer: UIGestureRecognizer) {
    let scnView = view as SCNView
    let point = gestureRecognizer.locationInView(scnView)
    if let hitResults = scnView.hitTest(point, options: nil) {
        if hitResults.count > 0 {

            let result: AnyObject! = hitResults[0]

            if !result.node!.name!.hasPrefix("Orange") {
                return
            }

            let tapLoc = BoardLoc(x: Int(point.x) / 106, y: Int(point.y) / 106)

            boardArray[tapLoc.x][tapLoc.y] = Type.Yellow



            for col in 0...2 {
                for row in 0...4 {
                    var yellowBall = scnView.scene!.rootNode.childNodeWithName("Yellow", recursively: true)
                    var secxtorX = Float(col) * 16.5 - 16
                    var sectorY = 34 - (Float(row) * 16.5)
                    if boardArray[col][row] == Type.Yellow {
                        yellowBall!.runAction(SCNAction.moveTo(SCNVector3(x: secxtorX, y: sectorY, z: 25), duration: 0.01))
                        boardArray[tapLoc.x][tapLoc.y] = Type.Orange
                    }
                }
            }
        }
    }
}
}

      



+1


source


First of all, I recommend that you read the Apple SceneKit document and some tutorials.

Scene Kit is an Objective-C 3D rendering engine that combines a high-performance rendering engine with a high-level descriptive API. Scene Kit supports import, manipulation and rendering of 3D assets without requiring precise steps to render the scene like OpenGL does.

Scene Kit makes it easy to render a 3D scene without the OpenGL ES API. However, you must understand how the Scene Kit works.

Basically, the Scene Kit provides a view controller that supports the animation loop. This cycle follows a design pattern commonly used in games and simulations, with two phases: refresh and render. The Scene Kit implementation has more phases like the following figure (from http://www.objc.io/issue-18/scenekit.html ), but basically two phases, update and do .



Scene Kit phases

So how to create a Scene Kit project, the basics

  • Prepare SCNView
  • Initialize 3D scene
  • Create touch event handler
  • Implement an update phase: update the game board with an affected object or affected position, update animation of objects, or something like that.
  • Render Phase Implementation: Basically, Scene Kit automatically displays registered 3D objects and models.

Thus, you must implement the following:

  • Use SCNView instead of ViewController
  • Create scene
  • Place the panel and tiles as a 3D plot set
  • Use hitTest to touch a tile and refresh the tile in the refresh phase
+2


source







All Articles