I am making a simple game in spritekit where the screen is full of balls with physics bodies. when the player taps a ball the ball explodes. I want to apply an angular impulse at the point of touch which will push all the surrounding balls away like a real world explosion. I tried fields but they are not really good as all the physics field nodes are forces not impulses. I checked all the impulse methods but they are only to apply force to the node itself. I also tried this:
self.physicsBody?.applyAngularImpulse(100)
and
self.physicsBody?.applyImpulse(impulse: CGVector, at: CGPoint)
thinking it would apply impulse to all child nodes in the scene (all the balls are child of the scene) but had no effect.
I thought this would be very simple but I am out of ideas.
appreciate your time. cheers
This approach is not a real-world explosion simulation but can help you as an idea.
I'm making actions like this on each touched node:
node.run(SKAction.sequence([
SKAction.fadeOut(withDuration: 0.0),
SKAction.scale(to: 10, duration: 0.1),
SKAction.removeFromParent()
]))
You can get this example here: https://github.com/Maetschl/SpriteKitExamples/blob/master/BoxWithBalls/BoxWithBalls/GameScene.swift
Related
is there a way to trigger a function, when a node (e.g. a tossed ball) enters a certain bounding box (e.g. a basket) in SceneKit / ARKit? If not, how would you implement this problem?
The way I would probably approach this. After obtaining a basketball hoop 3D dae model.
https://3dwarehouse.sketchup.com/model/fa42320b3def2c6b4741187cebbc52b3/Basketball-Hoop
I would first setup up the physicsShapes for the different elements.... backboard, pole & ring/hoop, floor & ball. I would then work out the cylinder size to fit inside the ring.
Using:
let cylinder = SCNCylinder(radius: 1.0, height: 0.1)
This becomes the physicBody for the hoop.
hoopNode.physicsBody = SCNPhysicsBody(type: .static, shape: SCNPhysicsShape(geometry:cylinder))
I would then workout the collisions the ball has with each different basketball element/node.
Don’t forget to use the debug feature
SceneView.debugOptions = .showPhysicsShapes
This will help to visually debug the collisions with the physics shapes & make sure the physic shapes are accurately scaled and in the correct position.
How to do setup collisions has already been answered in a previous post here...
how to setup SceneKit collision detection
You probably want the ball to bounce off the backboard, pole and ring, but if it hits the hoop physic shape... you might want to make the ball disappear and create a nice spark/flame animation or something. You could then have a score that registers as well.
This Arkit game on github will give you a nice template for handling all those things, collisions, animations & scoring
https://github.com/farice/ARShooter
You have to implement it using the ball's world position and the basket world position + bounding box.
Calculate the size of the basket using it's bounding box:
var (basketBoundingBoxMin, basketBoundingBoxMax) = (basket?.presentation.boundingBox)!
let size = basketBoundingBoxMax - basketBoundingBoxMin
Use this size and the basket's world position to calculate:
Basket's minimum x,y,z
Basket's maximum x,y,z
Then check if ball's world position is inside the basket's minimum and maximum position.
I'm making a game where a ball rolls down a series of blocks and the player has to anticipate where the ball is going to end up. However, I have a problem with the collision physics that I can't seem to understand.
The Problem
Whenever the ball touches the paddle (What the player moves), the ball does not stop and keeps rolling until it rolls off the paddle. What I would like to happen is for the ball to stop as soon as it touches the paddle and "stick" there. The attributes for the ball are :
and the attributes for the paddle are :
Any advice or solutions would be very helpful!
Are you implementing a SKPhysicsContactDelegate?
If so, when you detect the collision you could set the ball's velocity to zero, like this:
ball.physicsBody?.velocity = CGVector.zero
I have a physics body that is uneven but not dynamic (the terrain) and a physics body (character) that is dynamic and is on top of the terrain, and I want this character to move along the terrain simulating kind of a "walking" action where it will keep going up the terrain but it won't fall back (or move back) like a ball because of gravity, and to set a maximum tilt so that it does not tip over.
My attempt was to add a force in the direction I want the character to move but this is causing the character to fall back due to gravity, and I don't want to disable gravity because then character won't fall down when going down the terrain.
Thank you very much
this is why using a physics engine for a platforming game is very difficult and not always a great approach..
you can try sprite.physicsBody.allowsRotation = false
might help
Create SKAction to move your character to destination point or dx and dy. Run that SKAction from your character node with the runAction. Like
SKAction.moveByX(...
When the action is finished, gravity will bring the character down.
If the movement is slow, play with the character's physicsBody friction and/or mass.
You can also change the the character's physicsBody.velocity = CGVectorMake(
And your terrain will be better with edgeLoop physicsBody which won't be dynamic.
And with uneven you mean inclined but smooth? If not smooth and with edges, your character may get held up at an edge depending on center of gravity of character and if you are allowing rotation.
I use ball.frame.intersects(bar.frame), where ball = SKShapeNode(circleOfRadius: BALL_RADIUS) and bar = SKShapeNode(rectOfSize: <Some CGSize object>)
While this works, there is an invisible square in which the circle is inscribed. The diameter of the circle is the same as the side of the square. This square is what ball.frame is, so sometimes, the ball will act like it's intersecting the bar, but visually it's not.
In this screenshot you can see that the ball is stopped, and therefore the game is over because ball.frame.intersects(bar.frame) returned true, even though visually the ball isn't even touching the bar.
So how do I check if the ball is really intersecting the bar, and not if the ball's frame is intersecting?
SpriteKit has decently powerful collision detection in its physics subsystem — you don't have to roll your own.
Create SKPhysicsBody objects for the ball and the bars, using init(circleOfRadius:) for the former and init(rectangleOfSize: for the latter.
Then, you can either:
Drive all the movement yourself, and use SKPhysics only to test for collisions. In this case you need to set your scene's physicsWorld.gravity to the zero vector, and call allContactedBodies() on the ball when you want to see if it's contacting a bar.
Let SKPhysics drive the movement, by setting velocities or applying impulses. In this case you'll need to set a contact delegate for your physics world, and then you'll get a callback whenever a collision occurs.
For more details on either approach, see the docs.
After detecting that ball frame intersects box frame:
Determine the radius of the ball
Determine the point on the line that is the edge of the ball from the center of the ball to the edge of the box. (Hint: pythagorean theorem - hypotenuse = radius)
Is this point inside the box's rect?
Repeat for each point in the box.
I am making a top down game where I am having cannons fire and having their projectiles move to the clicked location via the SKAction moveTo:duration. I am supposed to have wind change the trajectory so I have the cannonball implemented as an SKPhysicsBody and I am setting gravity to be a the windspeed since it is the only thing I can find that applies a constant force like wind would. The problem I am having is moveTo is probably the wrong way to be implementing the cannonball. The ball moves according to the path it should but then lands at the tapped location which is not what I want. I can't find a good alternative to moveTo. Any ideas?
You have to solve the projectile equations to determine the force needed and angle to applyImpulse. Solving the equation is only considering the gravity force and impulse force applied to projectile using the applyImpulse with your distances known from your cannons to user's click projectile destination.
Your applyImpulse launches the projectile, you start your wind and other external forces which will have an impact on the projectile path, changing it's destination from that of user's clicked.
You need to know few physics and math to re-arrange the equations and solve them :)
Not sure if you need to do all the advanced math, just set the angle of your cannon and apply impulse to the cannonball, and use the scene.physicsWorld.gravity as your wind, just make sure you also give your cannonball a physicsbody that has dynamic and affectedByGravity set to true.
To calculate the angle, you would do:
let angle = atan2(Double(touch.y - cannon.y),Double(touch.x - cannon.x))