DonMugad - 1 year ago 111
Swift Question

# Shooting bullets from SKSpriteNode

I try to build 2D - top down game, and I have player (SKSpriteNode) he can move and rotate, and I want to shoot two bullets from him.
I use this code to shoot:

``````func setBullet(player: Player, bullet: Int)
{
let weaponPosition = scene!.convertPoint(player.weapon.position, fromNode: player)
var xPos, yPos: CGFloat!

let sinus = sin(player.zRotation)
let cosinus = cos(player.zRotation)

if bullet == 1
{
xPos = converted.x - sinus * player.size.height / 2
yPos = converted.y + cosinus * player.size.height / 2
}
else if bullet == 2
{
xPos = weaponPosition.x - sinus * player.size.height / 2
yPos = weaponPosition.y + cosinus * player.size.height / 2
}

position = CGPoint(x: xPos, y: yPos)
physicsBody!.applyImpulse(CGVector(dx: -sinus * normalSpeed, dy: cosinus * normalSpeed))
}
``````

But, i do not know how to correctly set the position...
I try to make something like this
(Green dots - this is a bullets). Can anyone help me please!

Shooting multiple bullets in the same direction is fairly straightforward. The key is to determine the bullets' initial positions and direction vectors when the character is rotated.

You can calculate a bullet's initial position within the scene by

``````let point = node.convertPoint(weapon.position, toNode: self)
``````

where `node` is the character, `weapon.position` is non-rotated position of a gun, and `self` is the scene.

Typically, a bullet moves to the right, `CGVector(dx:1, dy:0)`, or up, `CGVector (dx:0, dy:1)`, when the character is not rotated. You can calculate the direction of the impulse to apply to the bullet's physics body by rotating the vector by the character's `zRotation` with

``````func rotate(vector:CGVector, angle:CGFloat) -> CGVector {
let rotatedX = vector.dx * cos(angle) - vector.dy * sin(angle)
let rotatedY = vector.dx * sin(angle) + vector.dy * cos(angle)
return CGVector(dx: rotatedX, dy: rotatedY)
}
``````

Here's an example of how to shoot two bullets from a rotated character:

``````struct Weapon {
var position:CGPoint
}

class GameScene: SKScene {
let sprite = SKSpriteNode(imageNamed:"Spaceship")
let dualGuns = [Weapon(position: CGPoint(x: -15, y: 15)), Weapon(position: CGPoint(x: 15, y: 15))]
let singleGun = [Weapon(position: CGPoint(x: 0, y: 15))]
let numGuns = 1
// If your character faces up where zRotation == 0, offset by pi
let rotationOffset = CGFloat(M_PI_2)
override func didMoveToView(view: SKView) {
scaleMode = .ResizeFill
sprite.position = view.center
sprite.size = CGSizeMake(25, 25)
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
if let _ = touches.first {
let action = SKAction.rotateByAngle(CGFloat(M_PI_4/2), duration:1)
sprite.runAction(action) {
[weak self] in
if let scene = self {
switch (scene.numGuns) {
case 1:
for weapon in scene.singleGun {
scene.shoot(weapon: weapon, from: scene.sprite)
}
case 2:
for weapon in scene.dualGuns {
scene.shoot(weapon: weapon, from: scene.sprite)
}
default:
break
}
}
}
}
}

func shoot(weapon weapon:Weapon, from node:SKNode) {
// Convert the position from the character's coordinate system to scene coodinates
let converted = node.convertPoint(weapon.position, toNode: self)

// Determine the direction of the bullet based on the character's rotation
let vector = rotate(CGVector(dx: 0.25, dy: 0), angle:node.zRotation+rotationOffset)

// Create a bullet with a physics body
let bullet = SKSpriteNode(color: SKColor.blueColor(), size: CGSizeMake(4,4))
bullet.physicsBody?.affectedByGravity = false
bullet.position = CGPointMake(converted.x, converted.y)