【发布时间】:2016-06-15 03:52:45
【问题描述】:
我在为正确移动玩家节点的方式建模时遇到了一点麻烦 我想要的。
这是我第一次涉足 Spritekit,我已经建立并运行了基础知识(我有一个静态背景,添加了播放器节点并有一个可播放的带边界检查的边界矩形)
我添加玩家移动的方式是跟踪开始的触摸位置并 将其存储在场景类作用域变量(称为 beginTouchPosition)中,并存储当前触摸位置(称为 currentTouchPosition)。 我还跟踪玩家精灵节点位置(currentPlayerPosition)
我所做的是 onTouchesBegan 我更新“beginningTouchPosition”,然后在 onTouchesMoved 中更新“currentTouchPosition”,这样我可以通过获取相对于“beginningTouchPosition”的方向来了解用户希望他的船移动的方向,因为他/她移动他们的手指。 'currentTouchPosition' 与 'beginningTouchPosition' 的距离也决定了飞船的移动速度。
我通过使用上述要点创建一个 CGVector 并将其与 SKAction.MoveBy 调用一起使用,从而在更新中移动玩家。
我这样做是因为我希望用户能够触摸屏幕上的任何位置以控制移动。
我希望玩家如何移动。我宁愿让船通过在某个方向上应用某个设定速度和设定加速度来移动。这样当手指移动时,玩家将在 1/2 秒的空间内从零加速到 1,并继续朝该方向移动,直到手指再次移动或抬起。
如果手指被抬起,那么船应该继续沿最后一个方向移动,但会开始减速,直到速度回到零。
我基本上是在尝试模拟物体在零重力下的移动方式,具有明显的不现实的减速特征。
我找到了一些教程,展示了如何将对象移向手指触摸,但这不是我想要的,因为我正在尝试制作一款侧面滚动空间射击游戏,玩家可以在可玩区域内的任何地方移动,而不是简单的上下。类似于老式复古游戏“复仇女神”,请参见下面的屏幕:
我附上了我的播放器类代码和场景代码,以便更好地可视化我当前的操作方式。
任何有关如何在指定方向上应用加速度的文献的指针都会有所帮助:)
场景文件 - Level_1.swift
import SpriteKit
// Global
/*
Level_1 set up and control
*/
class Level_1: SKScene {
// Instance variables
var lastUpdateTime:NSTimeInterval = 0
var dt:NSTimeInterval = 0
var player = Player() // Sub classed SKSpriteNode for all player related stuff
var currentTouchPosition: CGPoint!
var beginningTouchPosition:CGPoint!
var currentPlayerPosition: CGPoint!
let playableRectArea:CGRect
override init(size: CGSize) {
// Constant - Max aspect ratio supported
let maxAspectRatio:CGFloat = 16.0/9.0
// Calculate playable height
let playableHeight = size.width / maxAspectRatio
// Determine margin on top and bottom by subtracting playable height
// from scene height and then divide by 2
let playableMargin = (size.height-playableHeight)/2.0
// Calculate the actual playable area rectangle
playableRectArea = CGRect(x: 0, y: playableMargin,
width: size.width,
height: playableHeight)
super.init(size: size)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func didMoveToView(view: SKView) {
/* Setup your scene here */
currentTouchPosition = CGPointZero
beginningTouchPosition = CGPointZero
let background = SKSpriteNode(imageNamed: "background1")
background.position = CGPoint(x: size.width/2, y: size.height/2)
background.zPosition = -1
self.addChild(background)
currentPlayerPosition = CGPoint(x: 100, y: size.height/2)
player.position = currentPlayerPosition
self.addChild(player)
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
currentTouchPosition = touch.locationInNode(self)
}
let dxVectorValue = (-1) * (beginningTouchPosition.x - currentTouchPosition.x)
let dyVectorValue = (-1) * (beginningTouchPosition.y - currentTouchPosition.y)
player.movePlayerBy(dxVectorValue, dyVectorValue: dyVectorValue, duration: dt)
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
player.removeAllActions()
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch: AnyObject in touches {
beginningTouchPosition = touch.locationInNode(self)
currentTouchPosition = beginningTouchPosition
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
currentPlayerPosition = player.position
if lastUpdateTime > 0 {
dt = currentTime - lastUpdateTime
}else{
dt = 0
}
lastUpdateTime = currentTime
player.boundsCheckPlayer(playableRectArea)
}
}
播放器节点 - Player.swift
import Foundation
import SpriteKit
struct PhysicsCategory {
static let None : UInt32 = 0
static let All : UInt32 = UInt32.max
static let Player : UInt32 = 0b1 // 1
static let Enemy : UInt32 = 0b10 // 2
}
class Player: SKSpriteNode{
init(){
// Initialize the player object
let texture = SKTexture(imageNamed: "ship1")
super.init(texture: texture, color: UIColor.clearColor(), size: texture.size())
self.xScale = 2
self.yScale = 2
self.anchorPoint = CGPoint(x: 0.5, y: 0.5)
self.zPosition = 1
// Player physics
self.physicsBody?.allowsRotation = false
self.physicsBody?.dynamic = false
self.physicsBody?.categoryBitMask = PhysicsCategory.Player
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// Check if the player sprite is within the playable area bounds
func boundsCheckPlayer(playableArea: CGRect){
let bottomLeft = CGPoint(x: 0, y: CGRectGetMinY(playableArea))
let topRight = CGPoint(x: playableArea.size.width, y: CGRectGetMaxY(playableArea))
if(self.position.x <= bottomLeft.x){
self.position.x = bottomLeft.x
// velocity.x = -velocity.x
}
if(self.position.x >= topRight.x){
self.position.x = topRight.x
// velocity.x = -velocity.x
}
if(self.position.y <= bottomLeft.y){
self.position.y = bottomLeft.y
// velocity.y = -velocity.y
}
if(self.position.y >= topRight.y){
self.position.y = topRight.y
// velocity.y = -velocity.y
}
}
/*
Move the player in a certain direction by a specific amount
*/
func movePlayerBy(dxVectorValue: CGFloat, dyVectorValue: CGFloat, duration: NSTimeInterval)->(){
let moveActionVector = CGVectorMake(dxVectorValue, dyVectorValue)
let movePlayerAction = SKAction.moveBy(moveActionVector, duration: 1/duration)
self.runAction(movePlayerAction)
}
}
【问题讨论】:
标签: ios swift sprite-kit