Sprites show up in simulator, not on device - ios

This simple project inserts a square sprite in the center of the field when you press the button, which calls the add() function below. In the simulator, when you add multiple sprites, it pushes the others out of the way, so when you have pressed it a bunch of times you get...
screen shot from simulator, iphone 6, iOS 9.2, and this is the behavior I want.
But the same code running on my iphone, after adding the same number of sprites yields this... screen show from physical iphone 6, iOS 9.2
Here is the code from GameScene.swift:
import SpriteKit
class GameScene: SKScene {
override init(size: CGSize) {
super.init(size:size)
self.physicsWorld.gravity = CGVectorMake(0, -1.0)
let worldBorder = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody = worldBorder
self.physicsBody?.friction = 0.5
}
func add()
{
let sprite = SKSpriteNode(color: UIColor.blueColor(), size: CGSize(width: 10, height: 10))
sprite.position = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2)
sprite.physicsBody = SKPhysicsBody(circleOfRadius: 8)
sprite.physicsBody?.friction = 0.0
sprite.physicsBody?.affectedByGravity = false
sprite.physicsBody?.restitution = 0.5
sprite.physicsBody?.linearDamping = 0.5
addChild(sprite)
}
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
}
}
Where am I going wrong? And how to I get the behavior I want on the real iPhone?

I'm not sure if which one is the desired behavior, but it does make sense that they wouldn't slide if you are stacking them literally right on top of each other. That being said, there is a way to get around this.
Keep in mind that nodes use floating point positioning, but of course they can only actually visibly be positioned by the pixel.
1 pixel would be 0.5 points on a 2x screen, and 0.33 points on 3x screen. With that in mind, you can use an offset of < 0.33 to get the physics bodies offset without it being visible to the user. Here's a little example:
class GameScene: SKScene {
var xOffset: CGFloat = 0.05
var yOffset: CGFloat = 0.3
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
}
override init(size: CGSize) {
super.init(size:size)
self.physicsWorld.gravity = CGVectorMake(0, -1.0)
let worldBorder = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody = worldBorder
self.physicsBody?.friction = 0.5
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
add()
updateOffsets()
}
func add()
{
let sprite = SKSpriteNode(color: UIColor.blueColor(), size: CGSize(width: 10, height: 10))
sprite.position = CGPointMake((self.frame.size.width / 2) + xOffset, (self.frame.size.height / 2) + yOffset)
sprite.physicsBody = SKPhysicsBody(circleOfRadius: 8)
sprite.physicsBody?.friction = 0.0
sprite.physicsBody?.affectedByGravity = false
sprite.physicsBody?.restitution = 0.5
sprite.physicsBody?.linearDamping = 0.5
addChild(sprite)
}
private func updateOffsets() {
xOffset = -xOffset
yOffset = -yOffset
}
}
Switching the offsets is the important part. If you don't do that, you'll have the same problem of stacking exactly on top of each other. The offsets I used get pretty close to the simulator behavior, but a few taps in you'll notice it's a little different. Hopefully you don't care about matching the exact same pattern you're getting in simulator. It's a very similar one with this code. If you do care, you'll notice changing the offsets will change the pattern.

Related

How to move a character back and forth across horizontally in swift

Currently trying to get a monster character to move across the screen horizontal back and forth. I'm extremely new to Swift as I just started learning last week and also haven't exactly master OOP. So how do I properly call the enemyStaysWithinPlayableArea func while it calls the addEnemy func. Heres what I have so far:
import SpriteKit
class GameScene: SKScene {
var monster = SKSpriteNode()
var monsterMove = SKAction()
var background = SKSpriteNode()
var gameArea: CGRect
// MARK: - Set area where user can play
override init(size: CGSize) {
// iphones screens have an aspect ratio of 16:9
let maxAspectRatio: CGFloat = 16.0/9.0
let playableWidth = size.height/maxAspectRatio
let margin = (size.width - playableWidth)/2
gameArea = CGRect(x: margin, y: 0, width: playableWidth, height: size.height)
super.init(size: size)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func didMove(to view: SKView) {
// I want to run addEnemy() while it checks for enemyStayWithinPlayableArea()
// run(SKAction.repeatForever(...)) ???
enemyStayWithinPlayableArea()
// MARK: - Setting the background
background = SKSpriteNode(imageNamed: "background")
background.size = self.size
// Set background at center of screen
background.position = CGPoint(x:self.size.width/2 ,y:self.size.height/2)
// Layering so everything in the game will be in front of the background
background.zPosition = 0
self.addChild(background)
}
func addEnemy() {
// MARK: - Set up enemy and its movements
monster = SKSpriteNode(imageNamed: "monster")
monster.zPosition = 5
// this is where the enemy starts
monster.position = CGPoint(x: 0, y: 300)
self.addChild(monster)
// I want it to move to the end of the screen within 1 sec
monsterMove = SKAction.moveTo(x: gameArea.maxX, duration: 1.0)
monster.run(monsterMove)
}
func enemyStayWithinPlayableArea(){
addEnemy()
// when the monster reaches the right most corner of the screen
// turn it back around and make it go the other way
if monster.position.x == gameArea.maxX{
monsterMove = SKAction.moveTo(x: gameArea.minX, duration: 1.0)
monster.run(monsterMove)
}
// when the monster reaches the left most corner of the screen
// same idea as above
if monster.position.x == gameArea.minX{
monsterMove = SKAction.moveTo(x: gameArea.maxX, duration: 1.0)
monster.run(monsterMove)
}
}
}
So far the enemy moves across the screen to the right edge of the screen, so that part works perfectly. I just need help making sure it continues in a loop (perhaps using the SKAction.repeatForever method but not sure how).
To understand movement of image in spritekit check this example.
let moveLeft = SKAction.moveTo(CGPoint(x: xpos, y: ypos), duration: duration)
let moveRight = SKAction.moveTo(CGPoint(x: xpos, y: ypos), duration: duration)
sprite.runAction(SKAction.repeatActionForever(SKAction.sequence([moveLeft, moveRight])))
for horizontal movement y position never been changed it should be same as in move left and move right.to stop repeatforever action use this.
sprite.removeAllActions()
Make two functions moveToMax and moveToMin with respective SKActions.And run action with completion handler.
func moveToMin(){
monsterMove = SKAction.moveTo(x: gameArea.minX, duration: 1.0)
monster.run(monsterMove, completion: {
moveToMax()
})
}

I made a hitbox sprite as a child to my player, in my player Class. how do I access that hitbox sprite in gamescene's didBegin method?

The purpose of this "hitbox" is so the player will only be able to jump while walking on top of ground/platforms.The hitbox is a little less wide then the player and is on the players feet. Here's my player class:
class Player: SKSpriteNode {
let maxPlayerSpeed:CGFloat = 300
static var isPlayerOnGround = false
init() {
//players texture
let texture = SKTexture(imageNamed: "playerMove1")
super.init(texture: texture, color: SKColor.clear, size: texture.size())
//hitbox that sits underneath the player and follows him
let jumpHitBox = SKSpriteNode(color: .red, size: CGSize(width: texture.size().width - (texture.size().width / 8), height: texture.size().height / 5))
jumpHitBox.position.y = (-texture.size().height) + (texture.size().height / 2)
jumpHitBox.alpha = 0.5
jumpHitBox.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: jumpHitBox.size.width,
height: jumpHitBox.size.height))
jumpHitBox.zPosition = 3
jumpHitBox.physicsBody?.pinned = true
jumpHitBox.physicsBody?.allowsRotation = false
jumpHitBox.physicsBody?.categoryBitMask = CollisionTypes.playerJump.rawValue
jumpHitBox.physicsBody?.collisionBitMask = 0
jumpHitBox.physicsBody?.contactTestBitMask = CollisionTypes.ground.rawValue
addChild(jumpHitBox)
physicsBody = SKPhysicsBody(rectangleOf: size)
physicsBody?.categoryBitMask = CollisionTypes.player.rawValue
physicsBody?.contactTestBitMask = CollisionTypes.star.rawValue | CollisionTypes.saw.rawValue | CollisionTypes.finish.rawValue
physicsBody?.collisionBitMask = CollisionTypes.ground.rawValue
physicsBody?.affectedByGravity = true
physicsBody?.restitution = 0.2
physicsBody?.isDynamic = true
physicsBody?.allowsRotation = false
setScale(0.6)
zPosition = 5
physicsBody?.linearDamping = 0.0 }
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder) //error here
}
I want to use the jumpHitBox in this method as an additional contact.bodyA/B node in GameScene.swift:
func didBegin(_ contact: SKPhysicsContact) {
if contact.bodyA.node == player {
playerCollided(with: contact.bodyB.node!)
} else if contact.bodyB.node == player {
playerCollided(with: contact.bodyA.node!)
}
}
I don't know how to reference the the jumpHitBox child node from my player class in the didBegin in GameScene.swift.
Any advice is greatly appreciated.
EDIT: I'm getting an error at the
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder) //error here
}
I dont put anything in here in my player class but since moving the jumpHitBox sprite to a global declaration I get an error at the super.init(coder: aDecoder) line in the required init saying: Property 'self.jumpHitBox' not initialized at super.init call
Although I would try the much simpler velocity.dy approach as mentioned in comments, your problem is that your hitbox is declared inside the scope of an initializer, so you can only access it there. If you give the hitbox a higher scope, such as a class property, then you can access it most anywhere:
class Player: SKSpriteNode {
let maxPlayerSpeed:CGFloat = 300
// This is probably going to cause you bugs later btw.. it should probably be
// just a regular property:
static var isPlayerOnGround = false
// Now you can just call playerInstance.jumpHitBox :
private(set) var jumpHitBox = SKSpriteNode()
init() {
//players texture
let texture = SKTexture(imageNamed: "playerMove1")
super.init(texture: texture, color: SKColor.clear, size: texture.size())
jumpHitBox = SKSpriteNode(color: .red, size: CGSize(width: texture.size().width - (texture.size().width / 8), height: texture.size().height / 5))
//hitbox that sits underneath the player and follows him
}
}
UPDATE:
class Player: SKSpriteNode {
let maxPlayerSpeed:CGFloat = 300
// This is probably going to cause you bugs later btw.. it should probably be
// just a regular property:
static var isPlayerOnGround = false
// Now you can just call playerInstance.jumpHitBox :
var jumpHitBox = SKSpriteNode()
private func makeHitBox() -> SKSpriteNode {
let texture = SKTexture(imageNamed: "playerMove1")
//hitbox that sits underneath the player and follows him
let localJumpHitBox = SKSpriteNode(color: .red, size: CGSize(width: texture.size().width - (texture.size().width / 8), height: texture.size().height / 5))
localJumpHitBox.position.y = (-texture.size().height) + (texture.size().height / 2)
localJumpHitBox.alpha = 0.5
localJumpHitBox.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: localJumpHitBox.size.width,
height: localJumpHitBox.size.height))
localJumpHitBox.zPosition = 3
localJumpHitBox.physicsBody?.pinned = true
localJumpHitBox.physicsBody?.allowsRotation = false
localJumpHitBox.physicsBody?.categoryBitMask = CollisionTypes.playerJump.rawValue
localJumpHitBox.physicsBody?.collisionBitMask = 0
localJumpHitBox.physicsBody?.contactTestBitMask = CollisionTypes.ground.rawValue
return localJumpHitBox
}
init() {
//players texture
let texture = SKTexture(imageNamed: "playerMove1")
super.init(texture: texture, color: SKColor.clear, size: texture.size())
physicsBody = SKPhysicsBody(rectangleOf: size)
physicsBody?.categoryBitMask = CollisionTypes.player.rawValue
physicsBody?.contactTestBitMask = CollisionTypes.star.rawValue | CollisionTypes.saw.rawValue | CollisionTypes.finish.rawValue
physicsBody?.collisionBitMask = CollisionTypes.ground.rawValue
physicsBody?.affectedByGravity = true
physicsBody?.restitution = 0.2
physicsBody?.isDynamic = true
physicsBody?.allowsRotation = false
setScale(0.6)
zPosition = 5
physicsBody?.linearDamping = 0.0
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder) //error here
jumpHitBox = makeHitBox()
addChild(jumpHitBox)
}
}
One way to reference jumpHitBox from outside its class is by making it a property of the Player class as in let jumpHitBox: SKSpriteNode, in the same way as you have declared maxPlayerSpeed to be a property of the Player class.
If you make this change, then remember to remove the let in this line let jumpHitBox = SKSpriteNode(color: .red .... since you now just need to assign a value to it, instead of declaring it. You should also now move the call to super.init to be after this line. Otherwise the compiler will complain, i.e. all properties of a class must be assigned a value before calling super.init.
The jumpHitBox should be now be accessible in didBegin by using player.hitBox
Hope this helps!
Here is a secondary answer showing a different approach to your problem. Note, the player only jumps when on the ground. This uses a "delayed frame" or "frame skip" or however you want to put it, because the jump command (pb.applyImpulse) is only called inside of didSimulatePhysics which means the character won't actually go any higher until the next frame.
// NOTE: This is a very simple example. The player bounces a bit on landing,
// which is essentially "landing lag" before you can jump again. In other words,
// the less the player bounces when contact the ground, the faster the player
// can jump again. There are ways to make this bouncing effect minimal / 0, but would
// require more work to implement, and I don't have any brilliantly simple ideas at the moment.
class GameScene : SKScene {
var player = SKSpriteNode(color: .blue, size: CGSize(width: 50, height: 50))
var initialY = CGFloat(0)
var flag_wantsToJump = false
override func didMove(to view: SKView) {
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
let pb = SKPhysicsBody(rectangleOf: player.size)
pb.restitution = 0
player.physicsBody = pb
addChild(player)
}
override func mouseDown(with event: NSEvent) {
// Tells game that we want to jump next frame:
flag_wantsToJump = true
}
override func update(_ currentTime: TimeInterval) {
// Give us new, initial frame data to compare against whatever our position.y will be
// later in the frame:
let curY = player.position.y
initialY = curY
}
override func didSimulatePhysics() {
// Determine whether or not we want to jump next frame:
guard flag_wantsToJump else { return }
// Determine whether or not we are allowed to jump:
let curY = player.position.y
print(curY, initialY)
if curY == initialY {
// Even though we are calling .applyImpulse this frame, it won't be processed
// until next frame--because we are calling this from inside `didSimulatePhysics`!
player.physicsBody!.applyImpulse(CGVector(dx: 0, dy: 75))
}
}
override func didFinishUpdate() {
// Clear our flags for new mouse / touch input for next frame:
flag_wantsToJump = false
}
}

SKSpriteNode showing non integer position when assigned an SKPhysicsBody

I have some very simple Swift code which places an SKSpriteNode on screen at position x:214, y:200. In the update method, I print the current position of said SKSpriteNode. If I omit all of the SKPhysicsBody code, then the position of my SKSpriteNode is shown in the debug window as (214.0, 200.0) which is as I would expect it. If, however, I run the program with the SKPhysicsBody code present, then the first print returns correct with (214.0, 200.0), but subsequent calls return (214.000015258789, 200.0).
This looks to me like something in the physics world is affecting (albeit in a very small way) the position of the SKSpriteNode. What I cannot fathom for the life of me is what that could be. My code is exactly as shown below, nothing more and nothing less. I think I have disabled everything that could possibly have any effect on the position. I am just hoping that I might have missed something silly.
The problem may seem trivial as the values are only fractionally off, however when I attempt to move the sprite smoothly across the screen (incrementing it's x position + 1 on each update) then it will occasionally miss an entire position, going from 289.0 to 289.99, then 291.0.
Any help would be much appreciated. It feels like a bug to me, but as I am fairly new to the physics side of SpriteKit, I would like to be certain.
import SpriteKit
class GameScene: SKScene {
private var playerSprite : SKSpriteNode!
override func didMoveToView(view: SKView) {
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)//borderBody
self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
playerSprite = SKSpriteNode(color: UIColor.yellowColor(), size: CGSize(width: 100, height: 100))
playerSprite.position = CGPoint(x: 214, y: 200)
playerSprite.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: 100, height: 100))
if let playerSpritePhysicsObject = playerSprite.physicsBody {
playerSpritePhysicsObject.usesPreciseCollisionDetection = true
playerSpritePhysicsObject.affectedByGravity = false
playerSpritePhysicsObject.allowsRotation = false
playerSpritePhysicsObject.dynamic = false
playerSpritePhysicsObject.angularVelocity = 0.0
playerSpritePhysicsObject.friction = 0.0
playerSpritePhysicsObject.linearDamping = 0.0
playerSpritePhysicsObject.angularDamping = 0.0
playerSpritePhysicsObject.velocity = CGVectorMake(0, 0)
playerSpritePhysicsObject.restitution = 0.0
}
self.addChild(playerSprite)
}
override func update(currentTime: NSTimeInterval) {
print("playerSprite Position = \(playerSprite.position)")
}
}
Here is the debug window output:
playerSprite Position = (214.0, 200.0)
2017-06-19 20:39:47.682 PhysicsTest[9193:2340365] <SKMetalLayer: 0x14fe6e760>: calling -display has no effect.
playerSprite Position = (214.000015258789, 200.0)
playerSprite Position = (214.000030517578, 200.0)
playerSprite Position = (214.000030517578, 200.0)
playerSprite Position = (214.000030517578, 200.0)
playerSprite Position = (214.000030517578, 200.0)
After some time agonising over this problem, I think I may have found a work around. It's nasty but does the trick. Simply reset the position of the SKSpriteNode in the didFinishUpdate() function which occurs after the didSimulatePhysics() function has complete.
override func didFinishUpdate() {
playerSprite.position.x = 214
}
Having tested further, I found this didn't work for iOS 7.1. In order for it work on older devices, you must place the code in the didSimulatePhysics() function instead:
override func didSimulatePhysics() {
playerSprite.position.x = 214
}

Rotate a child node in spritekit

I have a node that I need to rotate, however as it is a child node whenever I rotate it changes size. This is because it is created with a y scale value of 0.7693. I have tried creating a algorithm to manipulate the x and y scale based on the z rotation, but nothing works. Is their anyway to do this?
edit: I have found that statically changing the x and y scales does not work here is my code for that:
var ScaleDir: CGFloat = 1
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
let turnAngle:Double = 1
startWheel.zRotation = startWheel.zRotation + CGFloat(turnAngle / (180/Double.pi))
if startWheel.zRotation*(180/CGFloat.pi) >= 360{
startWheel.zRotation = startWheel.zRotation - (360/(180/CGFloat.pi))
}
startWheel.yScale = startWheel.yScale + (CGFloat((1 - 0.7693) / Double(90/turnAngle)) * ScaleDir)
startWheel.xScale = startWheel.xScale - (CGFloat((1 - 0.7693) / Double(90/turnAngle)) * ScaleDir)
if startWheel.yScale >= 1 || startWheel.xScale >= 1{
ScaleDir = ScaleDir * -1
}
}
I have realized the problem. The automatically assigned Yscale moves with the rotating node however the ovular shape that is created by the spriteKit scaling system does not and stays vertical.
Here is what my problem looks like:
If the scale is applied after the rotation, then you want to use sin on the angle to figure out the Y component and cos to figure out the X.
But, I would try giving this node a dummy parent node and rotate that.
Here's some simple code I was using in a playground to try to duplicate what you described in your question. I tried manipulating the yScale and rotation of various elements in the setup but nothing seemed to reproduce the undesired behavior. Have I reasonably replicated your setup, or am I missing something?
import SpriteKit
import PlaygroundSupport
public class GameScene: SKScene {
let node: SKNode
init(nodeToRotate: SKNode) {
self.node = nodeToRotate
super.init(size: CGSize(width: 500, height: 400))
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func update(_ currentTime: TimeInterval) {
let turnAngle = 9.0
node.zRotation = node.zRotation + CGFloat(turnAngle / (180.0/Double.pi))
}
}
let square = SKShapeNode(rectOf: CGSize(width: 80, height: 80))
square.fillColor = .purple
square.strokeColor = .purple
square.position = CGPoint(x: 250, y: 200)
let circle = SKShapeNode(circleOfRadius: 30)
circle.fillColor = .orange
circle.strokeColor = .orange
circle.position = CGPoint(x: 0, y: 0)
circle.yScale = 0.7
square.addChild(circle)
let scene = GameScene(nodeToRotate: square)
scene.addChild(square)
let view = SKView(frame: CGRect(origin: .zero, size: CGSize(width: 500, height: 400)))
view.presentScene(scene)
PlaygroundPage.current.liveView = view
The problem was that the parent node had a y scale and this was causing all of the problems, as soon as I removed the y-scale and changed it back to 1 everything started to work again.

How to move sprite just left or right using CoreMotion?

For this game I am creating, I want the Sprite "Character" to either move left or right by me tilting the device either left or right.
I have looked into it and changed the code, but it seems like that it does not work.
When I run it, the "Character" moves in only one direction and still goes either up or down.
I would just like the "Character" to move only left or right, not up or down.
Any help on this?
Here is a look at the GameScene.swift file:
import SpriteKit
import CoreMotion
class GameScene: SKScene {
let motionManager = CMMotionManager()
var Ground = SKSpriteNode()
var Character = SKSpriteNode()
override func didMoveToView(view: SKView) {
/* Setup your scene here */
Character = SKSpriteNode(imageNamed: "NinjaGhost")
Character.physicsBody = SKPhysicsBody(circleOfRadius: Character.size.height)
Character.size = CGSize(width: 200, height: 200)
Character.physicsBody?.allowsRotation = false
Character.zPosition = 2
Character.position = CGPoint(x: self.frame.width / 2, y: self.frame.height / 2)
self.addChild(Character)
Ground = SKSpriteNode(imageNamed: "Dirt Background")
Ground.size = CGSize(width: 1920, height: 1080)
Ground.zPosition = 1
Ground.position = CGPoint(x: self.frame.width / 2, y: self.frame.height / 2)
self.addChild(Ground)
motionManager.startAccelerometerUpdates()
motionManager.accelerometerUpdateInterval = 0.1
motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.mainQueue() ) {
(data, error) in
self.physicsWorld.gravity = CGVectorMake(CGFloat((data?.acceleration.x)!) * 1, 0)
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
You should follow the swift guidelines, your properties should not start with capital letters, only classes, structs, enums and protocols should. It makes code harder to read on stack overflow (code is marked blue but shouldn't) and in general its not good practice.
Change your code to this because there was a few errors.
character = SKSpriteNode(imageNamed: "NinjaGhost")
character.size = CGSize(width: 200, height: 200) // Better to call this before positioning
character.position = CGPoint(x: self.frame.width / 2, y: self.frame.height / 2) // Give pos before physics body
character.physicsBody = SKPhysicsBody(circleOfRadius: character.size.width / 2) // You have to divide by 2 when using circleOfRadius to get proper size in relation to the sprite
character.physicsBody?.allowsRotation = false
character.physicsBody?.affectedByGravity = false // Stop falling
character.zPosition = 2
self.addChild(character)
In your motion queue code you are manipulating the scene itself, so that will not work.
Try this code instead which uses the physics body to move the sprite. This is my preferred way of doing it because it gives the sprite more natural movement, especially when changing direction, compared to directly manipulating the sprites position property (If you want to manipulate the sprite position property directly than read this article. http://www.ioscreator.com/tutorials/move-sprites-accelerometer-spritekit-swift)
if let error = error { // Might as well handle the optional error as well
print(error.localizedDescription)
return
}
guard let data = motionManager.accelerometerData else { return }
if UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft {
character.physicsBody?.applyForce(CGVectorMake(-100 * CGFloat(data.acceleration.y), 0))
} else {
character.physicsBody?.applyForce(CGVectorMake(100 * CGFloat(data.acceleration.y), 0))
}
This will make the sprite move on the x axis. I am using data.acceleration.y because in this example the game is in landscape so you have to use the Y data to move it on the x axis.
I am also checking in which landscape orientation the device is so that the motion works in both orientations.
Adjust the 100 here to get the desired force depending on the size of the sprite (higher is more force). Big sprites properly need a few 1000s to move.

Resources