I am making a game that, when the game loads in, doesn't require the user to tap the screen to start, but starts straight away.
My code with the "tap to start":
import Foundation
import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate {
var isStarted = false
override func didMoveToView(view: SKView) {
//backgroundColor = UIColor.greenColor()
addTapToStartLabel()
func addTapToStartLabel() {
let tapToStartLabel = SKLabelNode(text: "Tap to start!")
tapToStartLabel.name = "tapToStartLabel"
tapToStartLabel.position.x = view!.center.x
tapToStartLabel.position.y = view!.center.y + 40
tapToStartLabel.fontColor = UIColor.whiteColor()
tapToStartLabel.fontName = "Helvetica"
tapToStartLabel.fontSize = 22.0
addChild(tapToStartLabel)
}
func start() {
isStarted = true
let tapToStartLabel = childNodeWithName("tapToStartLabel")
tapToStartLabel?.removeFromParent()
square1.stop()
movingGround.start()
wallGen.startGenWallsEvery(1)
diamondGen.startGenDiamondsEvery(1)
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
if isGameOver {
restart()
} else if !isStarted {
start()
} else {
square1.flip()
}
}
I have tried a couple of things and I can't seem to figure it out.
First, your didMoveToView is missing }
Your game have started, but you should override update() function that is called at the beginning of every frame and do some actions there.
Related
I am trying to implement moving to another scene when a wheel stops rotating. The code I have is shown below. I cannot figure out how to detect when the velocity has reached 0.0?
import SpriteKit
import GameplayKit
class GameplayScene: SKScene {
var player: Player?;
override func didMove(to view: SKView) {
player = self.childNode(withName: "spinner") as! Player?;
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
if atPoint(location).name == "play_button" {
spin()
}
}
}
func spin () {
let random = GKRandomDistribution(lowestValue: 20, highestValue: 90)
let r = random.nextInt()
player?.physicsBody = SKPhysicsBody(circleOfRadius: CGFloat(self.frame.width))
player?.physicsBody?.affectedByGravity = false
player?.physicsBody?.isDynamic = true
player?.physicsBody?.allowsRotation = true
player?.physicsBody?.angularVelocity = CGFloat(r)
player?.physicsBody?.angularDamping = 1.0
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
}
}
So from here, I would like to execute the following when the wheel has stopped spinning:
let play_scene = Questions(fileNamed: "QuestionsScene")
play_scene?.scaleMode = .aspectFill
self.view?.presentScene(play_scene!, transition: SKTransition.doorsOpenVertical(withDuration: 1))
I have now edited the class and it looks as follows:
import SpriteKit
import GameplayKit
class GameplayScene: SKScene, SKSceneDelegate {
var player: Player?
override func didMove(to view: SKView) {
self.delegate = self
player = self.childNode(withName: "spinner") as! Player?;
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
if atPoint(location).name == "play_button" {
spin()
}
}
}
func spin () {
let random = GKRandomDistribution(lowestValue: 20, highestValue: 90)
let r = random.nextInt()
player?.physicsBody = SKPhysicsBody(circleOfRadius: CGFloat(self.frame.width))
player?.physicsBody?.affectedByGravity = false
player?.physicsBody?.isDynamic = true
player?.physicsBody?.allowsRotation = true
player?.physicsBody?.pinned = true
player?.physicsBody?.angularVelocity = CGFloat(r)
player?.physicsBody?.angularDamping = 1.0
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
}
override func didSimulatePhysics() {
if ((player?.physicsBody?.angularVelocity)! <= CGFloat(0.01))
{
print("Got it")
}
}
}
Problem is I still receive an error on the if statement within didSimulatePhysics function. The error I receive is "Thread 1: EXC_BAD_INSTRUCTION...."
Your wheel's SKPhysicsBody has a built-in property, angularVelocity, that tells you how fast it's spinning. You're already using it when you set it to r to start the wheel spinning.
To watch angularVelocity you can use didSimulatePhysics(). It gets called once every frame, right after the physics calculations are done. That will look something like this:
func didSimulatePhysics() {
if wheelIsSpinning && angularVelocity != nil && angularVelocity! <= CGFloat(0.001) {
wheelIsSpinning = false
// wheel has stopped
// add your code here
}
}
Due to the vagaries of physics modeling, the angularVelocity might never be exactly zero. So instead we watch for it to be less than some arbitrary threshold, in this case 0.001.
You don't want it to execute every frame when the wheel isn't moving, so I added a property wheelIsSpinning to keep track. You'll need to add it as an instance property to GameplayScene, and set it to true in spin().
https://github.com/bmh3110/JackTheGiantGame
I'm unable to move my sprite left or right when the screen is touched. I'm just starting this game and I can't even get it to work. I've had this problem for a few days and it's getting really frustrating.
GameplayScene.swift
import SpriteKit
class GameplayScene: SKScene {
var player : Player?
var canMove = false
var moveLeft = false
var center : CGFloat?
override func didMoveToView(view: SKView) {
center = (self.scene?.size.width)! / (self.scene?.size.height)!
player = self.childNodeWithName("Player") as? Player!
}
override func update(currentTime: NSTimeInterval) {
managePlayer()
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
if location.x > center {
moveLeft = false
} else {
moveLeft = true
}
}
canMove = true
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
}
func managePlayer() {
if canMove {
player?.movePlayer(moveLeft)
}
}
}
Player.swift
import SpriteKit
class Player: SKSpriteNode {
func movePlayer(moveLeft: Bool) {
if moveLeft {
self.position.x = self.position.x - 7
} else {
self.position.x = self.position.x + 7
}
}
}
In the touchesEnded function set canMove = false
I am trying to delete an image that is moving by touch and only that image. I spawn multiple images of that same image and I only want to delete the ones that are being touched. How can I do this? Any ideas? I am running IOS app Game and SpriteKit.
import SpriteKit
`class GameScene: SKScene {
override func didMoveToView(view: SKView) {
/* Setup your scene here */
let myLabel = SKLabelNode(fontNamed:"Chalkduster")
myLabel.text = "Hello, World!"
myLabel.fontSize = 45
myLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
self.addChild(myLabel)
}
func generateNode() {
let Bullet = SKSpriteNode(imageNamed: "Bullets")
Bullet.name = "generatedNode"
}
func touchesCancelled(touches: NSSet, withEvent event: UIEvent?) {
let touch = touches.anyObject() as! UITouch?
if let location = touch?.locationInNode(self)
{
for Bullet in self.nodesAtPoint(location)
{
if Bullet.name == "generatedNode"
{
Bullet.removeFromParent()
}
}
}
}
}
func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
I'm trying to make a game where you have a pig and where you swipe or hold the pig moves. I have a class for my pig with atributes but an error comes up in GameScene.swift saying guy is not a member of porker. Please help.
import SpriteKit
import UIKit
class GameScene: SKScene {
var porker:Porker!
var touchLocation = CGFloat()
var gameOver = false
override func didMoveToView(view: SKView) {
addBG()
addPig()
}
func addBG() {
let bg = SKSpriteNode(imageNamed: "bg");
addChild(bg)
}
func addPig() {
let Pig = SKSpriteNode(imageNamed: "pig")
porker = Porker(guy:Pig)
addChild(Pig)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches{
if !gameOver {
touchLocation = (touch.locationInView(self.view!).y * -1) + (self.size.height/2)
}
}
let MoveAction = SKAction.moveToY(touchLocation, duration: 0.5)
MoveAction.timingMode = SKActionTimingMode.EaseOut
Porker.guy.runAction(MoveAction) }
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
and here is the pig class
import Foundation
import SpriteKit
class Porker {
var Guy:SKSpriteNode
var speed = 0.1
init(guy:SKSpriteNode){
self.Guy = guy
}
}
First of all, variable/constants/parameter names should start with a lowercase, so you don't mix them up with class names. For example,
class Porker {
var guy:SKSpriteNode
var speed = 0.1
init(guy:SKSpriteNode){
self.guy = guy
}
}
and inside touches began:
let moveAction = SKAction.moveToY(touchLocation, duration: 0.5)
moveAction.timingMode = SKActionTimingMode.EaseOut
porker.guy.runAction(MoveAction)
Hopefully that fixes things!
How to tap the correct SKSpriteNode in my iOS game created in swift (XCode 7, SpriteKit)? Finding the node seems not to be the issue, since in the test, 'exists' returns true. When I change my test to "app.tap()" then it does work. Except I have multiple SKSpriteNodes, so this does not solve my problem.
Below you can find code snippets. I hope you can help me with my problem. Any suggestions/hints are welcome.
Code snippet from my SKScene:
override func didMoveToView(view: SKView) {
var newGameButton : SKSpriteNode!
newGameButton = SKSpriteNode(imageNamed: "button")
newGameButton.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)+5)
newGameButton.size = CGSizeMake(200.0, 40.0)
newGameButton.name = "newGame"
newGameButton.isAccessibilityElement = true
newGameButton.userInteractionEnabled = true
newGameButton.accessibilityLabel = "newGame"
self.addChild(newGameButton)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = touches.first as UITouch!
let location = touch.locationInNode(self)
let nodes = self.nodesAtPoint(location)
for node in nodes {
if (node.name == "newGame") {
viewController.beginNewGame()
break
}
}
}
Current setup in UITest:
import XCTest
class MemoryPlayUITests: XCTestCase {
override func setUp() {
super.setUp()
continueAfterFailure = false
XCUIApplication().launch()
}
override func tearDown() {
super.tearDown()
}
func testStartNewGame() {
let app = XCUIApplication()
let newGameButton = app.otherElements["newGame"]
XCTAssertEqual(newGameButton.label, "newGame")
XCTAssertTrue(newGameButton.exists)
newGameButton.tap()
...{test logic to test if new game is started}
}
}