平衡精灵
Balancing a sprite
所以我的问题是关于精灵的旋转。我希望它看起来像是在平衡。当您向左轻按时 - 精灵向左移动,当您向右轻按时 - 精灵向右移动。为了得到一个更好的主意,在它的末端放一支铅笔并尝试平衡它......是的......那个(但仅限于 x 轴)。
目前我正在顺时针或逆时针旋转精灵,具体取决于我是点击屏幕的左侧还是右侧。这一切都是使用 SKActions 完成的。
这样做的问题是它会导致非常 'jerky' 而不是特别逼真的运动。
我假设我想使用物理体和类似于速度的东西,但我的问题是:
- 速度的使用是正确的...不是吗?
- 我会更好地使用基于体积的精灵(并让它考虑到它的体积和质量)或只是一个简单的基于边缘的精灵吗?
提前致谢!
-- 代码 -
这就是我目前旋转和移动精灵的方式:
import SpriteKit
enum rotationDirection{
case clockwise
case counterClockwise
case none
}
// Creates GameScene and initialises Sprites in Scene //
class GameScene: SKScene, SKPhysicsContactDelegate {
// Rotation direction variable for ship motion (rotation and movement) //
var currentRotationDirection = rotationDirection.none
var xVelocity: CGFloat = 0
var sprite = SKSpriteNode()
// Setup Scene here //
override func didMoveToView(view: SKView) {
// Background colour //
self.backgroundColor = SKColor.whiteColor()
// sprite Physics + add's sprite //
sprite.physicsBody = SKPhysicsBody(rectangleOfSize: ship.size)
sprite.physicsBody?.affectedByGravity = true
sprite.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
self.addSprite()
// Initialises sprite node and it's properties //
func addSprite() {
// Sprite dimension properities //
sprite.name = "sprite"
sprite = SKSpriteNode(imageNamed: "sprite")
sprite.setScale(0.5)
sprite.position = CGPointMake(frame.midX, 220)
sprite.anchorPoint = CGPoint(x: 0.5, y: 0.25)
sprite.zPosition = 1;
// sprite Physics properties //
sprite.physicsBody = SKPhysicsBody(rectangleOfSize: ship.size)
sprite.physicsBody?.categoryBitMask = UInt32(shipCategory)
sprite.physicsBody?.dynamic = true
sprite.physicsBody?.contactTestBitMask = UInt32(obstacleCategory)
sprite.physicsBody?.collisionBitMask = 0
self.addChild(sprite)
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
// Defines UI Touch //
let touch = touches.first as UITouch!
let touchPosition = touch.locationInNode(self)
// Sets up Inital Rotation Direction //
let newRotationDirection : rotationDirection = touchPosition.x < CGRectGetMidX(self.frame) ? .clockwise : .counterClockwise
// Left or Right movement based on touch //
if touchPosition.x < CGRectGetMidX(self.frame) {xVelocity = -75}
else {xVelocity = 75}
// Clockwise or anticlockwise rotation based on touch //
if currentRotationDirection != newRotationDirection && currentRotationDirection != .none {
reverseRotation()
currentRotationDirection = newRotationDirection
}
else if (currentRotationDirection == .none) {
setupRotationWith(direction: newRotationDirection)
currentRotationDirection = newRotationDirection
}
}
func reverseRotation() {
let oldRotateAction = sprite.actionForKey("rotate")
let newRotateAction = SKAction.reversedAction(oldRotateAction!)
sprite.runAction(newRotateAction(), withKey: "rotate")
}
func stopRotation() {
sprite.removeActionForKey("rotate")
}
func setupRotationWith(direction direction: rotationDirection){
let angle : CGFloat = (direction == .clockwise) ? CGFloat(M_PI) : -CGFloat(M_PI)
let rotate = SKAction.rotateByAngle(angle, duration: 2)
let repeatAction = SKAction.repeatActionForever(rotate)
sprite.runAction(repeatAction, withKey: "rotate")
}
override func update(currentTime: CFTimeInterval) {
let rate: CGFloat = 0.3; //Controls rate of motion. 1.0 instantaneous, 0.0 none.
let relativeVelocity: CGVector = CGVector(dx:xVelocity-sprite.physicsBody!.velocity.dx, dy:0);
sprite.physicsBody!.velocity=CGVector(dx:sprite.physicsBody!.velocity.dx+relativeVelocity.dx*rate, dy:0);
}
我认为您要研究的是加速。现在您正在使用以下静态量调整 verlocityX:
if touchPosition.x < CGRectGetMidX(self.frame) {
xVelocity = -75
}
else {
xVelocity = 75
}
这样做会导致动作不稳。这实际上只是线性的。使用加速可以避免这种情况。
为此,您还需要 maxVelocity
和 acceleration
两个变量。你可能想要一个 maxVelocity 来限制速度。每帧你都需要增加 velocity
的加速度。
我建议你尝试这样的事情:
velocity = 0 // No movement
acceleration = 2 // Increase velocity with 2 each frame
maxVelocity = 75 // The maximum velocity
if touchPosition.x < CGRectGetMidX(self.frame) {
xVelocity += acceleration
if xVelocity <= -maxVelocity {
xVelocity = -maxVelocity
}
}
else {
xVelocity -= acceleration
if xVelocity >= maxSpeed {
xVelocity = maxSpeed
}
}
像这样提高速度将导致第一帧的旋转速度为 2,第二帧为 4,第三帧为 6,等等。因此它会产生增加的效果。与此同时,当你试图扭转它时,你也不会有生涩的效果。假设速度为 50,您首先将其降低到 48、46、44 等。直到 0 点,您才真正开始以另一种方式旋转。
所以我的问题是关于精灵的旋转。我希望它看起来像是在平衡。当您向左轻按时 - 精灵向左移动,当您向右轻按时 - 精灵向右移动。为了得到一个更好的主意,在它的末端放一支铅笔并尝试平衡它......是的......那个(但仅限于 x 轴)。
目前我正在顺时针或逆时针旋转精灵,具体取决于我是点击屏幕的左侧还是右侧。这一切都是使用 SKActions 完成的。
这样做的问题是它会导致非常 'jerky' 而不是特别逼真的运动。
我假设我想使用物理体和类似于速度的东西,但我的问题是:
- 速度的使用是正确的...不是吗?
- 我会更好地使用基于体积的精灵(并让它考虑到它的体积和质量)或只是一个简单的基于边缘的精灵吗?
提前致谢!
-- 代码 - 这就是我目前旋转和移动精灵的方式:
import SpriteKit
enum rotationDirection{
case clockwise
case counterClockwise
case none
}
// Creates GameScene and initialises Sprites in Scene //
class GameScene: SKScene, SKPhysicsContactDelegate {
// Rotation direction variable for ship motion (rotation and movement) //
var currentRotationDirection = rotationDirection.none
var xVelocity: CGFloat = 0
var sprite = SKSpriteNode()
// Setup Scene here //
override func didMoveToView(view: SKView) {
// Background colour //
self.backgroundColor = SKColor.whiteColor()
// sprite Physics + add's sprite //
sprite.physicsBody = SKPhysicsBody(rectangleOfSize: ship.size)
sprite.physicsBody?.affectedByGravity = true
sprite.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
self.addSprite()
// Initialises sprite node and it's properties //
func addSprite() {
// Sprite dimension properities //
sprite.name = "sprite"
sprite = SKSpriteNode(imageNamed: "sprite")
sprite.setScale(0.5)
sprite.position = CGPointMake(frame.midX, 220)
sprite.anchorPoint = CGPoint(x: 0.5, y: 0.25)
sprite.zPosition = 1;
// sprite Physics properties //
sprite.physicsBody = SKPhysicsBody(rectangleOfSize: ship.size)
sprite.physicsBody?.categoryBitMask = UInt32(shipCategory)
sprite.physicsBody?.dynamic = true
sprite.physicsBody?.contactTestBitMask = UInt32(obstacleCategory)
sprite.physicsBody?.collisionBitMask = 0
self.addChild(sprite)
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
// Defines UI Touch //
let touch = touches.first as UITouch!
let touchPosition = touch.locationInNode(self)
// Sets up Inital Rotation Direction //
let newRotationDirection : rotationDirection = touchPosition.x < CGRectGetMidX(self.frame) ? .clockwise : .counterClockwise
// Left or Right movement based on touch //
if touchPosition.x < CGRectGetMidX(self.frame) {xVelocity = -75}
else {xVelocity = 75}
// Clockwise or anticlockwise rotation based on touch //
if currentRotationDirection != newRotationDirection && currentRotationDirection != .none {
reverseRotation()
currentRotationDirection = newRotationDirection
}
else if (currentRotationDirection == .none) {
setupRotationWith(direction: newRotationDirection)
currentRotationDirection = newRotationDirection
}
}
func reverseRotation() {
let oldRotateAction = sprite.actionForKey("rotate")
let newRotateAction = SKAction.reversedAction(oldRotateAction!)
sprite.runAction(newRotateAction(), withKey: "rotate")
}
func stopRotation() {
sprite.removeActionForKey("rotate")
}
func setupRotationWith(direction direction: rotationDirection){
let angle : CGFloat = (direction == .clockwise) ? CGFloat(M_PI) : -CGFloat(M_PI)
let rotate = SKAction.rotateByAngle(angle, duration: 2)
let repeatAction = SKAction.repeatActionForever(rotate)
sprite.runAction(repeatAction, withKey: "rotate")
}
override func update(currentTime: CFTimeInterval) {
let rate: CGFloat = 0.3; //Controls rate of motion. 1.0 instantaneous, 0.0 none.
let relativeVelocity: CGVector = CGVector(dx:xVelocity-sprite.physicsBody!.velocity.dx, dy:0);
sprite.physicsBody!.velocity=CGVector(dx:sprite.physicsBody!.velocity.dx+relativeVelocity.dx*rate, dy:0);
}
我认为您要研究的是加速。现在您正在使用以下静态量调整 verlocityX:
if touchPosition.x < CGRectGetMidX(self.frame) {
xVelocity = -75
}
else {
xVelocity = 75
}
这样做会导致动作不稳。这实际上只是线性的。使用加速可以避免这种情况。
为此,您还需要 maxVelocity
和 acceleration
两个变量。你可能想要一个 maxVelocity 来限制速度。每帧你都需要增加 velocity
的加速度。
我建议你尝试这样的事情:
velocity = 0 // No movement
acceleration = 2 // Increase velocity with 2 each frame
maxVelocity = 75 // The maximum velocity
if touchPosition.x < CGRectGetMidX(self.frame) {
xVelocity += acceleration
if xVelocity <= -maxVelocity {
xVelocity = -maxVelocity
}
}
else {
xVelocity -= acceleration
if xVelocity >= maxSpeed {
xVelocity = maxSpeed
}
}
像这样提高速度将导致第一帧的旋转速度为 2,第二帧为 4,第三帧为 6,等等。因此它会产生增加的效果。与此同时,当你试图扭转它时,你也不会有生涩的效果。假设速度为 50,您首先将其降低到 48、46、44 等。直到 0 点,您才真正开始以另一种方式旋转。