Use Tableviewcontroller Inside Skscene

Using a UITableView in Spritekit

Usually I don't prefer subclass the UITableView as you doing, I prefer to use the UITableView delegate and datasource directly to my SKScene class to control both table specs and data to my game code.

But probably you have your personal scheme so I make an example to you follow your request:

import SpriteKit
import UIKit
class GameRoomTableView: UITableView,UITableViewDelegate,UITableViewDataSource {
var items: [String] = ["Player1", "Player2", "Player3"]
override init(frame: CGRect, style: UITableViewStyle) {
super.init(frame: frame, style: style)
self.delegate = self
self.dataSource = self
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell")! as UITableViewCell
cell.textLabel?.text = self.items[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Section \(section)"
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You selected cell #\(indexPath.row)!")
}
}
class GameScene: SKScene {
var gameTableView = GameRoomTableView()
private var label : SKLabelNode?
override func didMove(to view: SKView) {
self.label = self.childNode(withName: "//helloLabel") as? SKLabelNode
if let label = self.label {
label.alpha = 0.0
label.run(SKAction.fadeIn(withDuration: 2.0))
}
// Table setup
gameTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
gameTableView.frame=CGRect(x:20,y:50,width:280,height:200)
self.scene?.view?.addSubview(gameTableView)
gameTableView.reloadData()
}
}

Output:

Sample Image

Is it possible to subclass UITableView to a SKNode?

One thing to keep in mind while adding UIKit elements to an SKScene is that you must remove it from the view when the scene is uninitialized, otherwise it will remain even as the scene switches.

But back to your question. I believe that this will solve your answer. Between the question and the answer you should be good to go.
Use TableViewController inside SKScene

Adding a small UIView to an SKScene

LearnCocos2D definitely deserves credit for this, so if he ever posts an answer I will accept it. Essentially, I was failing to set the frame for the navigation controller's view. Here is my method for adding the smaller view to the scene:

override func didMoveToView(view: SKView) {

anchorPoint = CGPoint(x: 0.5, y: 0.5)

self.name = "Bugs Scene"
backgroundColor = bugsColor

let smallerRect = CGRectMake(400, 24, 600, 720)
let navRect = CGRectMake(0, 0, 600, 720)
let bugsTableView: BugsTVC = BugsTVC()
nav = UINavigationController(rootViewController: bugsTableView)
nav.view.frame = navRect
smallerView = UIView(frame: smallerRect)
smallerView.backgroundColor = UIColor.clearColor()

bugsTableView.view.frame = smallerRect
smallerView.frame = smallerRect
smallerView.addSubview(nav.view)
self.view.addSubview(smallerView)

}

It could probably be refined some but this is working for me. Now if I can only figure out how to remove the view when I transition to another scene!

Losing reference to GameViewController from inside SpriteKit when moving between scenes - want to move between SKScene and UITableView

There are two simple methods to call a GameViewController function from other classes: through a delegate or by making the class instance static.

// DELEGATE
//
// GameViewController.swift

protocol GameView_Delegate
{
func show_ui()
}

class GameViewController: UIViewController, GameView_Delegate
{
override func viewDidLoad()
{

// ...

if let view = self.view as! SKView?
{
if let scene = SKScene(fileNamed: "MenuScene")
{
scene.scaleMode = .aspectFill

// pass GameViewController reference
scene.gv_delegate = self
}

view.presentScene(scene)
}

// ...

}

func show_ui()
{
// show ui
// ...
}
}

// MenuScene.swift

class MenuScene: SKScene
{
var gv_delegate : GameView_Delegate!

func settings()
{
// call function show_ui from GameViewController
gv_delegate.show_ui()
}

func game_scene()
{
let transition = SKTransition.fade(with: UIColor.white, duration: 1.0)
let next_scene = GameScene()
next_scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
next_scene.scaleMode = self.scaleMode
next_scene.size = self.size

// before moving to next scene, we must pass the delegate, so we
// don't lose the connection with the GameViewController
next_scene.gv_delegate = gv_delegate
self.view?.presentScene(next_scene, transition: transition)
}
}

// GameScene.swift

class GameScene: SKScene
{
var gv_delegate : GameView_Delegate!

func settings()
{
// call function show_ui from GameViewController
gv_delegate.show_ui()
}

func main_scene()
{
let transition = SKTransition.fade(with: UIColor.white, duration: 1.0)
let next_scene = MainScene()
next_scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
next_scene.scaleMode = self.scaleMode
next_scene.size = self.size

// before moving to next scene, we must pass the delegate, so we
// don't lose the connection with the GameViewController
next_scene.gv_delegate = gv_delegate
self.view?.presentScene(next_scene, transition: transition)
}
}

When you enter a new scene, for example GameScene, the old scene MainScene in our case is deallocated (all variables emptied, all references destroyed) and a new GameScene instance is created and displayed on screen. If afterwards you want to exit that scene and enter MainScene, a new instance of that class will be created with the GameViewController reference empty. We should reference it again or pass the reference before exiting the scene (as in my example).

// STATIC
//
// GameViewController.swift

class GameViewController: UIViewController
{
static var shared : GameViewController!

override func viewDidLoad()
{
super.viewDidLoad()

GameViewController.shared = self

// ...

}

func show_ui()
{
// show ui
// ...
}
}

// MenuScene.swift

class MenuScene: SKScene
{
func settings()
{
// call function show_ui from GameViewController

GameViewController.shared.show_ui()
}
}

Read pros/cons of each method and chose the one that suits your app the best. Also, avoid using UIKit inside SpriteKit.

Getting the UIViewController from an SKScene

Your view controller is:

self.view?.window?.rootViewController

Example:

        let isReady = GADRewardBasedVideoAd.sharedInstance().isReady          
guard let controller = self.view?.window?.rootViewController as? GameViewController else {return}

if isReady {
print("ADMOB: started")
GADRewardBasedVideoAd.sharedInstance().present(fromRootViewController: controller)
}

UITableView with SpriteKit

If you want to use your UITableView (that was created in a storyboard, you said outlet so I am guessing that is where you created it) within your scene you will need to do a few things.

First create a variable for your table view in your scene. My swift is rusty, but if it was Objective-C it would be a matter of creating a property in the YourScene.h file.

Now when you instantiate your scene you can set the table view you have an outlet for in your scene. Something like this...

scene.tableView = tableView
skView.presentScene(scene)

Next thing in your scene you would want to implement UITableViewDelegate, UITableViewDataSource That way in your didMoveToView in your scene you can do this...

tableView?.delegate = self;
tableView?.dataSource = self;

Now in your scene you would have

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
func cellForRowAtIndexPath(indexPath: NSIndexPath) -> UITableViewCell?

This should allow you to do anything you would do with a tableView within your scene code.

Just remember a UITableView is part of UIKit and will likely be sitting on top of your SKView (added as a child). Positioning and size will be in the UIKit coordinate system.

Hopefully that makes sense and is helpful.

How to create a subview inside an SKScene?

I have figured out how to get the conformation screen to work. Thanks to @AlessandroOrnano for all the help! I have attached my code below for future reference. If anyone has a more efficient way of doing this I would greatly appreciate any suggestions.

import Foundation
import SpriteKit

class ShopPage1: SKScene{

override func didMove(to view: SKView) {

let background = SKSpriteNode(imageNamed: "background")
background.position = CGPoint(x: self.size.width/2, y: self.size.height/2)
background.zPosition = 0
self.addChild(background)

let balance = SKLabelNode(fontNamed: "The Bold Font")
balance.text = "$\(balanceAmount)"
balance.fontSize = 100
balance.fontColor = SKColor.green
balance.position = CGPoint(x: self.size.width/2, y: self.size.height*0.87)
balance.zPosition = 1
self.addChild(balance)

let backToMainMenuButton = SKSpriteNode(imageNamed: "backButton2")
backToMainMenuButton.position = CGPoint(x: self.size.width*0.25, y: self.size.height*0.89)
backToMainMenuButton.zPosition = 1
backToMainMenuButton.size = CGSize(width: 200, height: 200)
backToMainMenuButton.name = "backToMainMenuButton"
self.addChild(backToMainMenuButton)

let shipNameLabel = SKLabelNode(fontNamed: "The Bold Font")
shipNameLabel.text = "Stealth"
shipNameLabel.fontSize = 200
shipNameLabel.fontColor = SKColor.white
shipNameLabel.position = CGPoint(x: self.size.width/2, y: self.size.height*0.60)
shipNameLabel.zPosition = 1
shipNameLabel.name = "shipNameLabel"
self.addChild(shipNameLabel)

let nextShipButton = SKSpriteNode(imageNamed: "nextShipButton1")
nextShipButton.position = CGPoint(x: self.size.width*0.75, y: self.size.height*0.40)
nextShipButton.zPosition = 1
nextShipButton.size = CGSize(width: 300, height: 300)
nextShipButton.name = "nextShipButton"
self.addChild(nextShipButton)

let nextShipClick = SKLabelNode(fontNamed: "The Bold Font")
nextShipClick.text = "▲"
nextShipClick.fontSize = 300
nextShipClick.fontColor = UIColor.clear
nextShipClick.position = CGPoint(x: self.size.width*0.753, y: self.size.height*0.36)
nextShipClick.zPosition = 2
nextShipClick.name = "nextShipClick"
self.addChild(nextShipClick)

let shipForSale = SKSpriteNode(imageNamed: "playerShip4")
shipForSale.position = CGPoint(x: self.size.width/2, y: self.size.height*0.40)
shipForSale.zPosition = 1
shipForSale.size = CGSize(width: 150, height: 300)
self.addChild(shipForSale)

let shipPodium = SKSpriteNode(imageNamed: "shipPodium")
shipPodium.position = CGPoint(x: self.size.width*0.527, y: self.size.height*0.31)
shipPodium.zPosition = 1
shipPodium.size = CGSize(width: 1200, height: 70)
self.addChild(shipPodium)

let shipsCostLabel = SKLabelNode(fontNamed: "The Bold Font")
shipsCostLabel.text = "$500"
shipsCostLabel.fontSize = 200
shipsCostLabel.fontColor = SKColor.white
shipsCostLabel.position = CGPoint(x: self.size.width/2, y: self.size.height*0.20)
shipsCostLabel.zPosition = 1
self.addChild(shipsCostLabel)

let shipBuyButton = SKSpriteNode(imageNamed: "shipBuyButton")
shipBuyButton.position = CGPoint(x: self.size.width*0.54, y: self.size.height*0.15)
shipBuyButton.zPosition = 1
shipBuyButton.size = CGSize(width: 1500, height: 900)
shipBuyButton.name = "shipBuyButton"
self.addChild(shipBuyButton)

let shipBuyButtonClick = SKLabelNode(fontNamed: "The Bold Font")
shipBuyButtonClick.text = "▅▅"
shipBuyButtonClick.fontSize = 300
shipBuyButtonClick.fontColor = UIColor.clear
shipBuyButtonClick.position = CGPoint(x: self.size.width/2, y: self.size.height*0.05)
shipBuyButtonClick.zPosition = 2
shipBuyButtonClick.name = "shipBuyButtonClick"
self.addChild(shipBuyButtonClick)

}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

for touch: AnyObject in touches{

let pointOfTouch = touch.location(in: self)
let tappedNode = atPoint(pointOfTouch)
let tappedNodeName = tappedNode.name

if tappedNodeName == "nextShipClick"{

let sceneToMoveTo = ShopPage2(size: self.size)
sceneToMoveTo.scaleMode = self.scaleMode
let myTransition = SKTransition.fade(withDuration: 0.5)
self.view!.presentScene(sceneToMoveTo, transition: myTransition)
}

if tappedNodeName == "backToMainMenuButton"{

let sceneToMoveTo = MainMenuScene(size: self.size)
sceneToMoveTo.scaleMode = self.scaleMode
let myTransition = SKTransition.fade(withDuration: 0.5)
self.view!.presentScene(sceneToMoveTo, transition: myTransition)
}

if tappedNodeName == "shipBuyButtonClick"{

let sceneToMoveTo = ShopPage1ConformationScreen(size: self.size)
sceneToMoveTo.scaleMode = self.scaleMode
let myTransition = SKTransition.fade(withDuration: 0.5)
self.view!.presentScene(sceneToMoveTo, transition: myTransition)
}

}

}

}

This is the code for ShopPage1ConformationScreen:

 import Foundation
import SpriteKit

let shipForSale = SKSpriteNode(imageNamed: "playerShip4")

class ShopPage1ConformationScreen: SKScene{

override func didMove(to view: SKView) {

let background = SKSpriteNode(imageNamed: "background")
background.position = CGPoint(x: self.size.width/2, y: self.size.height/2)
background.zPosition = 0
self.addChild(background)

let balance = SKLabelNode(fontNamed: "The Bold Font")
balance.text = "$\(balanceAmount)"
balance.fontSize = 100
balance.fontColor = SKColor.green
balance.position = CGPoint(x: self.size.width/2, y: self.size.height*0.87)
balance.zPosition = 1
self.addChild(balance)

let backToMainMenuButton = SKSpriteNode(imageNamed: "backButton2")
backToMainMenuButton.position = CGPoint(x: self.size.width*0.25, y: self.size.height*0.89)
backToMainMenuButton.zPosition = 1
backToMainMenuButton.size = CGSize(width: 200, height: 200)
backToMainMenuButton.name = "backToMainMenuButton"
self.addChild(backToMainMenuButton)

let shipNameLabel = SKLabelNode(fontNamed: "The Bold Font")
shipNameLabel.text = "Stealth"
shipNameLabel.fontSize = 200
shipNameLabel.fontColor = SKColor.white
shipNameLabel.position = CGPoint(x: self.size.width/2, y: self.size.height*0.60)
shipNameLabel.zPosition = 1
shipNameLabel.name = "shipNameLabel"
self.addChild(shipNameLabel)

let nextShipButton = SKSpriteNode(imageNamed: "nextShipButton1")
nextShipButton.position = CGPoint(x: self.size.width*0.75, y: self.size.height*0.40)
nextShipButton.zPosition = 1
nextShipButton.size = CGSize(width: 300, height: 300)
nextShipButton.name = "nextShipButton"
self.addChild(nextShipButton)

let nextShipClick = SKLabelNode(fontNamed: "The Bold Font")
nextShipClick.text = "▲"
nextShipClick.fontSize = 300
nextShipClick.fontColor = UIColor.clear
nextShipClick.position = CGPoint(x: self.size.width*0.753, y: self.size.height*0.36)
nextShipClick.zPosition = 2
nextShipClick.name = "nextShipClick"
self.addChild(nextShipClick)

shipForSale.position = CGPoint(x: self.size.width/2, y: self.size.height*0.40)
shipForSale.zPosition = 1
shipForSale.size = CGSize(width: 150, height: 300)
self.addChild(shipForSale)

let shipPodium = SKSpriteNode(imageNamed: "shipPodium")
shipPodium.position = CGPoint(x: self.size.width*0.527, y: self.size.height*0.31)
shipPodium.zPosition = 1
shipPodium.size = CGSize(width: 1200, height: 70)
self.addChild(shipPodium)

let shipsCostLabel = SKLabelNode(fontNamed: "The Bold Font")
shipsCostLabel.text = "$500"
shipsCostLabel.fontSize = 200
shipsCostLabel.fontColor = SKColor.white
shipsCostLabel.position = CGPoint(x: self.size.width/2, y: self.size.height*0.20)
shipsCostLabel.zPosition = 1
self.addChild(shipsCostLabel)

let shipBuyButton = SKSpriteNode(imageNamed: "shipBuyButton")
shipBuyButton.position = CGPoint(x: self.size.width*0.54, y: self.size.height*0.15)
shipBuyButton.zPosition = 1
shipBuyButton.size = CGSize(width: 1500, height: 900)
shipBuyButton.name = "shipBuyButton"
self.addChild(shipBuyButton)

let conformationBackground = SKSpriteNode(imageNamed: "conformationBackground")
conformationBackground.position = CGPoint(x: self.size.width*0.51, y: self.size.height*0.40)
conformationBackground.zPosition = 2
conformationBackground.size = CGSize(width: 1300, height: 1400)
conformationBackground.name = "conformationBackground"
self.addChild(conformationBackground)

let conformationScreenTextTop = SKLabelNode(fontNamed: "The Bold Font")
conformationScreenTextTop.text = "Are you sure you wish to"
conformationScreenTextTop.fontSize = 80
conformationScreenTextTop.fontColor = SKColor.white
conformationScreenTextTop.position = CGPoint(x: self.size.width/2, y: self.size.height*0.46)
conformationScreenTextTop.zPosition = 3
conformationScreenTextTop.name = "comformationScreenTextTop"
self.addChild(conformationScreenTextTop)

let conformationScreenTextBottom = SKLabelNode(fontNamed: "The Bold Font")
conformationScreenTextBottom.text = "purchase this ship?"
conformationScreenTextBottom.fontSize = 80
conformationScreenTextBottom.fontColor = SKColor.white
conformationScreenTextBottom.position = CGPoint(x: self.size.width/2, y: self.size.height*0.41)
conformationScreenTextBottom.zPosition = 3
conformationScreenTextBottom.name = "conformationScreenTextBottom"
self.addChild(conformationScreenTextBottom)

let conformationScreenTextYes = SKLabelNode(fontNamed: "The Bold Font")
conformationScreenTextYes.text = "Yes"
conformationScreenTextYes.fontSize = 150
conformationScreenTextYes.fontColor = SKColor.green
conformationScreenTextYes.position = CGPoint(x: self.size.width*0.30, y: self.size.height*0.30)
conformationScreenTextYes.zPosition = 3
conformationScreenTextYes.name = "conformationScreenTextYes"
self.addChild(conformationScreenTextYes)

let conformationScreenTextNo = SKLabelNode(fontNamed: "The Bold Font")
conformationScreenTextNo.text = "No"
conformationScreenTextNo.fontSize = 150
conformationScreenTextNo.fontColor = SKColor.red
conformationScreenTextNo.position = CGPoint(x: self.size.width*0.70, y: self.size.height*0.30)
conformationScreenTextNo.zPosition = 3
conformationScreenTextNo.name = "conformationScreenTextNo"
self.addChild(conformationScreenTextNo)
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

for touch: AnyObject in touches{

let pointOfTouch = touch.location(in: self)
let tappedNode = atPoint(pointOfTouch)
let tappedNodeName = tappedNode.name

if(balanceAmount >= 500){
if tappedNodeName == "conformationScreenTextYes"{
player = shipForSale
balanceAmount -= 500
let sceneToMoveTo = ShopPage1(size: self.size)
sceneToMoveTo.scaleMode = self.scaleMode
let myTransition = SKTransition.fade(withDuration: 0.5)
self.view!.presentScene(sceneToMoveTo, transition: myTransition)
}
}

if tappedNodeName == "conformationScreenTextNo"{
let sceneToMoveTo = ShopPage1(size: self.size)
sceneToMoveTo.scaleMode = self.scaleMode
let myTransition = SKTransition.fade(withDuration: 0.5)
self.view!.presentScene(sceneToMoveTo, transition: myTransition)
}

}
}
}

For additional shop pages just copy and paste these sets of codes. With the exception of changing the the tapped nodes around to the correct order in which you wish to move from page to page.

How To Present a SKScene from a UIViewController

I think I might have found a solution-I didn't present the GameScene directly from the MenuViewController, but instead, when the playButton is pressed I transitioned to the GameViewController and then presented the GameScene from there.

I don't know why it doesn't work in the MenuViewController, but this method works.



Related Topics



Leave a reply



Submit