Applying an impulse to bullets - swift

I have player (SKSpriteNode) he can move and rotate, and I want to shoot five bullets from him, but with another angle. I use this code:
let sinus = sin(player.zRotation)
let cosinus = cos(player.zRotation)
bullet.physicsBody!.applyImpulse(CGVector(dx: -sinus * 100, dy: cosinus * 100))
But, i do not know how to correctly set the vector with angle. I try to make something like this:
Can anyone help me please!

According with this diagram:
you must change the zRotation of your bullets.
Remember that zRotation is expressed in radians so if you need:
extension CGFloat {
var radiansToDegrees: CGFloat {
return self * CGFloat(180.0 / M_PI)
}
var degreesToRadians: CGFloat {
return self * CGFloat(M_PI / 180.0)
}
}
To rotate your bullets you can also use (also this one is expressed in radians) :
let rotate = SKAction.rotateByAngle(angle, duration: 0.01)
You can calculate also the speed and the angle of your bullet impulses :
extension CGVector {
func speed() -> CGFloat {
return sqrt(dx*dx+dy*dy)
}
func angle() -> CGFloat {
return atan2(dy, dx)
}
}
If you need you can connect these element with the screen touches as explained in detail here
About your comments you can use this formula (already explained in my link):
let angle = atan2(location.y - cannon.position.y , location.x - cannon.position.x)
cannon.zRotation = angle - CGFloat(M_PI_2)

Related

Shooting balls from a rotating cannon

I'm making a SpriteKit game. I have six cannons that I've made rotate back and fourth. I want to shoot cannonballs from each cannon that sync with the rotation of each cannon. I want a duration of one second between each cannonball.
So basically: A cannon that is in constant rotation is shooting cannonballs in the same direction as the rotation.
For the cannons i'm using an extension:
extension CGFloat {
func degreesToRadians() -> CGFloat {
return self * CGFloat.pi / 180
}
}
I'm gonna put the code for just one cannon, since I should be able to figure out how to adjust one of the cannonball movements to the others. Here is one:
func createCannons() {
let cannonLeftBottom = SKSpriteNode(imageNamed: "Cannon")
cannonLeftBottom.anchorPoint = CGPoint(x: 0.5, y: 0.5)
cannonLeftBottom.position = CGPoint(x: -325, y: -420)
cannonLeftBottom.zPosition = 4
cannonLeftBottom.setScale(0.4)
cannonLeftBottom.zRotation = CGFloat(65).degreesToRadians()
let rotateLB = SKAction.rotate(byAngle:
CGFloat(-65).degreesToRadians(), duration: 2)
let rotateBackLB = SKAction.rotate(byAngle:
CGFloat(65).degreesToRadians(), duration: 2)
let repeatRotationLB =
SKAction.repeatForever(SKAction.sequence([rotateLB,rotateBackLB]))
cannonLeftBottom.run(repeatRotationLB)
self.addChild(cannonLeftBottom)
}
Here is my function for the cannonball:
func createBalls() {
let cannonBallLB = SKSpriteNode(imageNamed: "Ball")
cannonBallLB.name = "CannonBall"
cannonBallLB.position = CGPoint(x: -325, y: -420)
cannonBallLB.physicsBody = SKPhysicsBody(circleOfRadius:
cannonBallLB.size.height / 2)
cannonBallLB.physicsBody?.affectedByGravity = false
cannonBallLB.zPosition = 3
cannonBallLB.setScale(0.1)
self.addChild(cannonBallLB)
}
THX!
You need to convert from Polar Coordinates to Rectangular Coordinates.
You do this by using sin and cos
E.G.
let speed = 100 //This would mean move 100 points per second
let force = CGVector(dx:cos(cannon.zRotation) * speed,dy:sin(cannon.zRotation) * speed)
cannonBall.applyForce(force)
Note: Now unless they changed this, force used to be in units of points, if they fixed it to units of meters, then you need to divide your speed by 150, since 150 points = 1 meter in Spritekit

Rotating a UIView to point at another UIView

I'm trying to get a UIView called object to rotate to point at the center of another UIView called orig. I can't seem to be able to calculate the angle correctly. My trig is a bit rusty so I can't figure out how my math is wrong.
let y0 = object.center.y
let y1 = orig?.center.y
let x0 = object.center.x
let x1 = orig?.center.x
let angle = atan2((y1! - y0), (x1! - x0)) * 180 / CGFloat.pi
rotateTo(object: object, degrees: angle, time: deplexed[1] as! CGFloat)
To make the top of rotator view point at the target point.
let direction = CGPoint(x: targetPoint.x - rotatorView.center.x, y: targetPoint.y - rotatorView.center.y)
var angle = atan2(direction.y, direction.x)
rotatorView.transform = CGAffineTransform(rotationAngle: angle + .pi/2)
atan2 returns zero if point is to the right.
If you want to convert the atan2 result to degrees:
if angle < 0 {
angle += .pi * 2
}
let degrees = angle * 180.0/.pi
You add a full circle if the angle is negative. 0 degrees points to the right.
Create a default object and suppose it's a button :
let button = UIButton()
if button.transform == CGAffineTransform.identity {
UIView.animate(withDuration: 0.5, animations: {
button.transform = CGAffineTransform(rotationAngle: self.radians(degrees: 180))
})
} else {
UIView.animate(withDuration: 0.5, animations: {
button.transform = CGAffineTransform.identity
})
}
func radians(degrees: CGFloat) -> CGFloat {
return CGFloat(degrees * CGFloat.pi / degrees)
}

Xcode Swift SpriteKit SkSpriteNode Y value isn't moving but X is

In the move Action, the Y value isn't changing and i don't know why because the X value is changing. The changeY variable is doing its job with the correct value of 5.0 or -5.0 but the Y value on the "player" SkSpriteNode isn't changing. Please help.
override func update(_ currentTime: TimeInterval) {
let percent = touchLocation.x / size.width
let newAngle = percent * 180 - 180
print(newAngle)
if playButtonPressed{
var changeY = 0.0
if newAngle >= -180{
changeY = 5.0
}
else{
changeY = -5.0
}
player.zRotation = CGFloat(newAngle) * CGFloat(M_PI) / 180.0
print(changeY)
var move = SKAction.moveBy(x: -(player.position.x+1), y: CGFloat(changeY), duration: 2000.0)
player.run(move)
}
}
It's not entirely clear to me what you ultimate goal is, but your calculations seems of. Especially the fact that the duration for the movement is 2000 seconds. That's more than 30 minutes(!) The x-calculations also suggests that you actually planned to use moveTo rather than moveBy as you're currently doing.
The below is based on your code but as I'm not sure what your actually aiming for this does the following: Moves left+up if the touch is on the left-hand side of the screen, moves down+right if the touch is on the right-hand side of the screen...
override func update(_ currentTime: TimeInterval) {
if playButtonPressed {
let percent = touchLocation.x / size.width
let newAngle = percent * 180 - 180
player.zRotation = CGFloat(newAngle) * CGFloat(M_PI) / 180.0
let moveRightAndUp = touchLocation.x>size.width/2
let changeY: CGFloat = moveRightAndUp ? 5.0 : -5.0
let changeX: CGFloat = moveRightAndUp ? 1.0 : -1.0
let move = SKAction.moveBy(x: changeX, y: changeY, duration: 1/60)
player.run(move)
}
}

shooting moving location in swift

I'm working in a game for my college and i stuck in one thing.
when i try to shoot with my hero the bullet go's up only or side i need my bullet go's where ever my hero rotate plz help me this is my code
func spownBullet() {
let bullet = SKSpriteNode(imageNamed: "Bullet")
let hero = self.childNodeWithName("hero") as! SKSpriteNode
bullet.zPosition = 1
bullet.position = CGPointMake(hero.position.x, hero.position.y)
bullet.size = CGSize(width: 20, height: 30)
let bulletact = SKAction.moveToY(self.size.height + 300, duration: 1)
bullet.runAction(SKAction.repeatActionForever(bulletact))
self.addChild(bullet)
}
If I understand correctly you want your bullet to go a certain distance (e.g. 300) in the same angle as your "hero" sprite is rotated.
Here's a function to compute the destination point:
// destination point moving at angle
// ---------------------------------
func endPointMovingSpriteFrom(origin:CGPoint, atAngle angle:CGFloat,forDistance distance:CGFloat ) -> CGPoint
{
let deltaX = distance / sin(angle + CGFloat(M_PI)/2)
let deltaY = distance / cos(angle + CGFloat(M_PI)/2)
return CGPoint(x: origin.x - deltaX, y:origin.y - deltaY)
}
You can use it to compute the destination and then use the destination in a moveTo action:
let bulletDestination = endPointMovingSpriteFrom(hero.position, atAngle:hero.zRotation, forDistance:300)
let bulletact = SKAction.moveTo(bulletDestination, duration: 1)

How to make a symmetry axis from the floor to my hero every time I click?

I want my hero to do a symmetry axis from the floor. But when I click a second time, instead of returning above the floor, it continues to go down by axes of symmetry versus below it.
Here's the code:
func flip() {
isUpsideDown = !isUpsideDown
var scale: CGFloat!
if isUpsideDown{
scale = -1.0
} else {
scale = 1.0
}
let translate = SKAction.moveByX(0, y: scale*(size.height + kADGroundHeight), duration: 0.1)
let flip = SKAction.scaleYTo(scale, duration: 0.1)
runAction(translate)
runAction(flip)
}
And by the way,
let kADGroundHeight: CGFloat = 20.0
Check that size.height isn't negative. After scaling to -1, it probably is. So your moveBy's y parameter is mis-calculated.