触摸移动SKSpriteNode,半屏点加速
Moving SKSpriteNode with touch, speeds up at half screen point
我正在开发 2-d 平台游戏风格的游戏。我对 IOS 和 Swift 开发还很陌生。我正在尝试使用一个按钮(一个不同的节点)将我的角色从左向右移动到屏幕上。它工作正常,直到我到达中间点然后它急剧加速并且松开按钮并不总是停止它。有时它需要另一个触摸。此外,背景似乎跟不上播放器。一旦玩家到达中间屏幕,背景应该随着玩家继续移动而移动。
我已经从多个教程 SO 示例中拼凑了我所做的事情,但我坚持这一点。
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)
}
}
按住 rightMoveButton 应该以一致的速度向右移动。当玩家到达屏幕中间时,背景的视点应该移动,直到到达背景的尽头,此时玩家可以离开屏幕并完成关卡。释放按钮应该允许播放器停止。
您可以通过创建 SKCameraNode 来随着角色移动而移动场景。然后您可以选择何时移动相机以产生正确的效果。确保将相机设置为游戏的相机。您可以了解相机 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。网上还有许多其他很棒的视频和网站,您可以通过搜索“SpriteKit player movement”找到它们。
Eli Front 的回答为我指明了正确的方向。我对这段代码仍有一些问题,但正如 Eli 指出的那样,我的问题的答案是使用 SKCamera 节点。我只是想 post 有效的代码,所以如果有人有类似的问题,这里有一个关于摄像机随播放器移动的代码示例。速度问题本质上是背景移动太快的错觉。
请注意,控件是相机的子控件。也就是说,它们会随着相机移动,否则当您的节点移动时,控件会移出屏幕。
import UIKit
import SpriteKit
import GameKit
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()
let cam = SKCameraNode()
var previousUpdateTime: TimeInterval = 0
override func didMove(to view: SKView) {
// SETUP CAMERA
self.camera = cam
scene?.addChild(cam)
cam.position.x = 448
cam.position.y = 212
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)
// SETUP CONTROLS
leftMoveButton.position.x = -338
leftMoveButton.position.y = -112
leftMoveButton.name = "moveLeft"
leftMoveButton.zPosition = 5
cam.addChild(leftMoveButton)
rightMoveButton.position.x = -278
rightMoveButton.position.y = -112
rightMoveButton.name = "moveRight"
cam.addChild(rightMoveButton)
jumpButton.position.x = 278
jumpButton.position.y = -112
jumpButton.name = "jumpButton"
jumpButton.zPosition = 5
cam.addChild(jumpButton)
fireButton.position.x = 338
fireButton.position.y = -112
fireButton.name = "fireButton"
cam.addChild(fireButton)
}
override func update(_ currentTime: TimeInterval) {
if (forwardMarch) {
if player.position.x > 448 && player.position.x < 1800 {
cam.position.x = player.position.x
} else if player.position.x >= 1800 {
cam.position.x = 1800
}
setViewpointCenter(player.position)
player.position.x = player.position.x + 3
}
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" {
player.physicsBody!.velocity.dy = 0.0
forwardMarch = true
self.player.run(repeatActionPlayer)
}
}
}
}
override func touchesEnded(_ 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 = false
player.removeAllActions()
player.texture = SKTexture(imageNamed: "legend1")
player.physicsBody!.velocity = CGVector(dx: 0.0, dy: 0.0)
}
if name == "moveRight" {
player.removeAllActions()
player.texture = SKTexture(imageNamed: "legend1")
forwardMarch = false
}
}
}
}
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, y: centerOfView.y - actualPosition.y)
if (actualPosition.x > 1800) {
tileMap!.position = tileMap!.position
} else {
tileMap!.position = viewPoint
}
}
func setupScene() {
// ADD PLAYER SPRITES @TODO MAKE THIS DYNAMIC
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)
anchorPoint = CGPoint(x: 0, y: 0)
position = CGPoint(x: 0, y: 0)
// let point = tileMap!.calculateAccumulatedFrame()
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 {
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
player.physicsBody!.mass = 1.0
addChild(player)
}
}
正如我提到的,当我同时 jump/run 时,我仍然有一些问题,例如播放器节点 floating/flying。第一次跳跃是正确的高度,所有后续跳跃都较小等,但我正在努力解决这些问题。
我正在开发 2-d 平台游戏风格的游戏。我对 IOS 和 Swift 开发还很陌生。我正在尝试使用一个按钮(一个不同的节点)将我的角色从左向右移动到屏幕上。它工作正常,直到我到达中间点然后它急剧加速并且松开按钮并不总是停止它。有时它需要另一个触摸。此外,背景似乎跟不上播放器。一旦玩家到达中间屏幕,背景应该随着玩家继续移动而移动。
我已经从多个教程 SO 示例中拼凑了我所做的事情,但我坚持这一点。
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)
}
}
按住 rightMoveButton 应该以一致的速度向右移动。当玩家到达屏幕中间时,背景的视点应该移动,直到到达背景的尽头,此时玩家可以离开屏幕并完成关卡。释放按钮应该允许播放器停止。
您可以通过创建 SKCameraNode 来随着角色移动而移动场景。然后您可以选择何时移动相机以产生正确的效果。确保将相机设置为游戏的相机。您可以了解相机 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。网上还有许多其他很棒的视频和网站,您可以通过搜索“SpriteKit player movement”找到它们。
Eli Front 的回答为我指明了正确的方向。我对这段代码仍有一些问题,但正如 Eli 指出的那样,我的问题的答案是使用 SKCamera 节点。我只是想 post 有效的代码,所以如果有人有类似的问题,这里有一个关于摄像机随播放器移动的代码示例。速度问题本质上是背景移动太快的错觉。
请注意,控件是相机的子控件。也就是说,它们会随着相机移动,否则当您的节点移动时,控件会移出屏幕。
import UIKit
import SpriteKit
import GameKit
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()
let cam = SKCameraNode()
var previousUpdateTime: TimeInterval = 0
override func didMove(to view: SKView) {
// SETUP CAMERA
self.camera = cam
scene?.addChild(cam)
cam.position.x = 448
cam.position.y = 212
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)
// SETUP CONTROLS
leftMoveButton.position.x = -338
leftMoveButton.position.y = -112
leftMoveButton.name = "moveLeft"
leftMoveButton.zPosition = 5
cam.addChild(leftMoveButton)
rightMoveButton.position.x = -278
rightMoveButton.position.y = -112
rightMoveButton.name = "moveRight"
cam.addChild(rightMoveButton)
jumpButton.position.x = 278
jumpButton.position.y = -112
jumpButton.name = "jumpButton"
jumpButton.zPosition = 5
cam.addChild(jumpButton)
fireButton.position.x = 338
fireButton.position.y = -112
fireButton.name = "fireButton"
cam.addChild(fireButton)
}
override func update(_ currentTime: TimeInterval) {
if (forwardMarch) {
if player.position.x > 448 && player.position.x < 1800 {
cam.position.x = player.position.x
} else if player.position.x >= 1800 {
cam.position.x = 1800
}
setViewpointCenter(player.position)
player.position.x = player.position.x + 3
}
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" {
player.physicsBody!.velocity.dy = 0.0
forwardMarch = true
self.player.run(repeatActionPlayer)
}
}
}
}
override func touchesEnded(_ 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 = false
player.removeAllActions()
player.texture = SKTexture(imageNamed: "legend1")
player.physicsBody!.velocity = CGVector(dx: 0.0, dy: 0.0)
}
if name == "moveRight" {
player.removeAllActions()
player.texture = SKTexture(imageNamed: "legend1")
forwardMarch = false
}
}
}
}
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, y: centerOfView.y - actualPosition.y)
if (actualPosition.x > 1800) {
tileMap!.position = tileMap!.position
} else {
tileMap!.position = viewPoint
}
}
func setupScene() {
// ADD PLAYER SPRITES @TODO MAKE THIS DYNAMIC
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)
anchorPoint = CGPoint(x: 0, y: 0)
position = CGPoint(x: 0, y: 0)
// let point = tileMap!.calculateAccumulatedFrame()
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 {
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
player.physicsBody!.mass = 1.0
addChild(player)
}
}
正如我提到的,当我同时 jump/run 时,我仍然有一些问题,例如播放器节点 floating/flying。第一次跳跃是正确的高度,所有后续跳跃都较小等,但我正在努力解决这些问题。