I'm working on a 2-d Platformer style game. I'm very new to IOS and Swift development. I'm attempting to use a button (a different node) to move my character across the screen from left to right. It works fine until I reach the halfway point then it speeds up dramatically and letting go of the touch of the button doesn't always stop it. Sometimes it requires another touch. Also the background doesn't appear to keep up with the player. Once the player hits mid screen the background should shift as the player continues moving.
I've pieced what I've done together from multiple tutorials SO examples but I'm stuck on this point.
class StoryModeScene: SKScene, SKPhysicsContactDelegate {
var tileMap = JSTileMap(named: "legend1Level1.tmx")
var tileSize:CGSize!
var xPointsToMovePerSecond:CGFloat = 0
var rightMoveButton = SKSpriteNode(imageNamed: "right-move")
var leftMoveButton = SKSpriteNode(imageNamed: "left-move")
var jumpButton = SKSpriteNode(imageNamed: "a-button")
var fireButton = SKSpriteNode(imageNamed: "b-button")
var forwardMarch:Bool = false
var mightAsWellJump:Bool = false
var onGround:Bool = true
//CREATE THE PLAYER ATLAS FOR ANIMATION
let playerAtlas = SKTextureAtlas(named:"legend1")
var playerSprites = Array<Any>()
var player = SKSpriteNode(imageNamed: "legend1")
var repeatActionPlayer = SKAction()
override func didMove(to view: SKView) {
/* Setup your scene here */
setupScene()
addPlayer()
//PREPARE TO ANIMATE THE PLAYER AND REPEAT THE ANIMATION FOREVER
let animatedPlayer = SKAction.animate(with: self.playerSprites as! [SKTexture], timePerFrame: 0.1)
self.repeatActionPlayer = SKAction.repeatForever(animatedPlayer)
leftMoveButton.position.x = 64
leftMoveButton.position.y = 64
leftMoveButton.name = "moveLeft"
addChild(leftMoveButton)
rightMoveButton.position.x = 124
rightMoveButton.position.y = 64
rightMoveButton.name = "moveRight"
addChild(rightMoveButton)
jumpButton.position.x = 771
jumpButton.position.y = 64
jumpButton.name = "jumpButton"
addChild(jumpButton)
fireButton.position.x = 836
fireButton.position.y = 64
fireButton.name = "fireButton"
addChild(fireButton)
}
override func update(_ currentTime: TimeInterval) {
if (forwardMarch) {
//let moveAction = SKAction.moveBy(x: 3, y: 0, duration: 1)
//let repeatForEver = SKAction.repeatForever(moveAction)
//let seq = SKAction.sequence([moveAction, repeatForEver])
//run the action on your ship
//player.run(seq)
player.position.x = player.position.x + 3
setViewpointCenter(player.position)
}
if (mightAsWellJump) {
let jumpForce = CGPoint(x: 0.0, y: 310.0)
let jumpCutoff: Float = 150.0
if mightAsWellJump && onGround {
player.physicsBody!.velocity = CGVector(dx: player.physicsBody!.velocity.dx + jumpForce.x, dy: player.physicsBody!.velocity.dy + jumpForce.y)
onGround = false
} else if !mightAsWellJump && player.physicsBody!.velocity.dy > CGFloat(jumpCutoff) {
player.physicsBody!.velocity = CGVector(dx: player.physicsBody!.velocity.dx, dy: CGFloat(jumpCutoff))
}
player.position = CGPoint(x: player.position.x, y: player.position.y + 5);
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in (touches) {
let positionInScene = touch.location(in: self)
let touchedNode = self.atPoint(positionInScene)
if let name = touchedNode.name {
if name == "jumpButton" {
mightAsWellJump = true
player.texture = SKTexture(imageNamed: "legend1_jump")
}
if name == "moveRight" {
forwardMarch = true
self.player.run(repeatActionPlayer)
}
}
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first!
if rightMoveButton.contains(touch.location(in: self)) {
forwardMarch = false
player.removeAllActions()
player.texture = SKTexture(imageNamed: "legend1")
}
if jumpButton.contains(touch.location(in: self)) {
mightAsWellJump = false
player.removeAllActions()
player.texture = SKTexture(imageNamed: "legend1")
}
}
func setViewpointCenter(_ position: CGPoint) {
var x = max(position.x, size.width / 2)
var y = max(position.y, size.height / 2)
x = min(x, (tileMap!.mapSize.width * tileMap!.tileSize.width) - size.width / 2)
y = min(y, (tileMap!.mapSize.height * tileMap!.tileSize.height) - size.height / 2)
let actualPosition = CGPoint(x: CGFloat(x), y: CGFloat(y))
let centerOfView = CGPoint(x: size.width / 2, y: size.height / 2)
let viewPoint = CGPoint(x: (centerOfView.x - actualPosition.x) * 3, y: centerOfView.y - actualPosition.y)
tileMap!.position = viewPoint
}
func setupScene() {
playerSprites.append(playerAtlas.textureNamed("legend1_0"))
playerSprites.append(playerAtlas.textureNamed("legend1_1"))
playerSprites.append(playerAtlas.textureNamed("legend1_2"))
playerSprites.append(playerAtlas.textureNamed("legend1_3"))
playerSprites.append(playerAtlas.textureNamed("legend1_4"))
playerSprites.append(playerAtlas.textureNamed("legend1_5"))
backgroundColor = UIColor(red: 165.0/255.0, green: 216.0/255.0, blue: 255.0/255.0, alpha: 1.0)
physicsWorld.gravity = CGVector(dx: 0, dy: -9.8)
anchorPoint = CGPoint(x: 0, y: 0)
position = CGPoint(x: 0, y: 0)
let point = tileMap!.calculateAccumulatedFrame()
print (point)
tileMap!.position = CGPoint(x: 0, y: 0)
addChild(tileMap!)
addFloor()
}
func addFloor() {
for a in 0..<Int(tileMap!.mapSize.width) {
for b in 0..<Int(tileMap!.mapSize.height) {
let layerInfo:TMXLayerInfo = tileMap!.layers.firstObject as! TMXLayerInfo
let point = CGPoint(x: a, y: b)
let walls = tileMap!.layerNamed("Walls")
let wallInfo:TMXLayerInfo = walls!.layerInfo
let wallGIDs = wallInfo.layer.tileGid(at: wallInfo.layer.point(forCoord: point))
if wallGIDs > 0 {
//print (wallGIDs)
//let node = walls
let node = wallInfo.layer.tile(atCoord: point)
node!.physicsBody = SKPhysicsBody(rectangleOf: node!.size)
node!.physicsBody?.isDynamic = false
}
}
}
}
func addPlayer() {
tileSize = tileMap?.tileSize
player.position = CGPoint(x: tileSize.width + player.size.width/2, y: tileSize.height + player.size.height*8)
let rect = CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: 50, height: 95))
player.physicsBody = SKPhysicsBody(rectangleOf: rect.size)
player.physicsBody!.velocity = CGVector(dx: 0.0, dy: 0.0)
player.physicsBody!.isDynamic = true
player.physicsBody!.restitution = 0
player.physicsBody!.allowsRotation = false
player.physicsBody!.friction = 1.0
addChild(player)
}
}
Holding the rightMoveButton should move at a consistent pace to the right. As the player gets to mid screen the view point of the background should shift until it reaches the end of the background at which point the player can move off screen and complete the level. Releasing the button should allow the player to stop.
You can move the scene as the character moves by creating an SKCameraNode. You then can choose when to move the camera to create the right affect. Make sure to set the camera as your game’s camera. You can learn about cameras here. As for the speeding up, I assume it has something to do with your physicsBody. If you’re interested about player movement, you could look here or here. There are many other great videos and sites online, which you could find by searching “SpriteKit player movement.”