How can I disable gravity for certain physic bodies using LOVE Physics for Lua?
blocks.ground.body = love.physics.newBody(world, 0, blocks.ground.y, "dynamic")
blocks.ground.shape = love.physics.newRectangleShape(500, 50)
blocks.ground.fixture = love.physics.newFixture(blocks.ground.body, blocks.ground.shape)
blocks.ground.color = {86,176,0}
That is my current code for the body, I also need it to stay "dynamic" because I need to move its X
View Full Code: code
Assuming you are using LÖVE 0.8.0+:
Option 1:
Your Code:
blocks.ground.body = love.physics.newBody(world, 0, blocks.ground.y, "dynamic")
blocks.ground.shape = love.physics.newRectangleShape(500, 50)
blocks.ground.fixture = love.physics.newFixture(blocks.ground.body, blocks.ground.shape)
blocks.ground.color = {86,176,0}
Note: In your code love.physics.newFixture(blocks.ground.body, blocks.ground.shape)
From LOVE's Website (1):
objects.ground.fixture = love.physics.newFixture(objects.ground.body, objects.ground.shape) --attach shape to body
Also from LOVE's Website (2):
objects.ball.fixture = love.physics.newFixture(objects.ball.body, objects.ball.shape, 1) -- Attach fixture to body and give it a density of 1.
In the second snippet from their website they set the balls density (mass) to 1. Similarly you should be able to set the mass to 0 in which case gravity would have no affect on the object. However if other objects collide with your object, of mass 0, I am not sure what type of funky actions may occur.
Option 2:
The other option is to create a new world with gravity of 0:
love.physics.setMeter(64) --the height of a meter our worlds will be 64px
worldNoGravity = love.physics.newWorld(0, 0, true)
Then add the bodies to that world:
blocks.ground.body = love.physics.newBody(worldNoGravity , 0, blocks.ground.y, "dynamic")
blocks.ground.shape = love.physics.newRectangleShape(500, 50)
blocks.ground.fixture = love.physics.newFixture(blocks.ground.body, blocks.ground.shape)
blocks.ground.color = {86,176,0}
Hope one of those will work for you :).
Related
Im fighting here with the so called ghost collisions on a simple tile based map with a circle as player character.
When applying an impulse to the circle it first starts bouncing correctly, then sooner or later it bounces wrong (wrong angle).
Looking up on the internet i read about an issue in Box2D (i use iOS Swift with Box2d port for Swift).
Using b2ChainShape does not help, but it looks i misunderstood it. I also need to use the "prevVertex" and "nextVertex" properties to set up the ghost vertices.
But im confused. I have a simple map made up of boxes (simple square), all placed next to each other forming a closed room. Inside of it my circle i apply an impulse seeing the issue.
Now WHERE to place those ghost vertices for each square/box i placed on the view in order to solve this issue? Do i need to place ANY vertex close to the last and first vertice of chainShape or does it need to be one of the vertices of the next box to the current one? I dont understand. Box2D's manual does not explain where these ghost vertices coordinates are coming from.
Below you can see an image describing the problem.
Some code showing the physics parts for the walls and the circle:
First the wall part:
let bodyDef = b2BodyDef()
bodyDef.position = self.ptm_vec(node.position+self.offset)
let w = self.ptm(Constants.Config.wallsize)
let square = b2ChainShape()
var chains = [b2Vec2]()
chains.append(b2Vec2(-w/2,-w/2))
chains.append(b2Vec2(-w/2,w/2))
chains.append(b2Vec2(w/2,w/2))
chains.append(b2Vec2(w/2,-w/2))
square.createLoop(vertices: chains)
let fixtureDef = b2FixtureDef()
fixtureDef.shape = square
fixtureDef.filter.categoryBits = Constants.Config.PhysicsCategory.Wall
fixtureDef.filter.maskBits = Constants.Config.PhysicsCategory.Player
let wallBody = self.world.createBody(bodyDef)
wallBody.createFixture(fixtureDef)
The circle part:
let bodyDef = b2BodyDef()
bodyDef.type = b2BodyType.dynamicBody
bodyDef.position = self.ptm_vec(node.position+self.offset)
let circle = b2CircleShape()
circle.radius = self.ptm(Constants.Config.playersize)
let fixtureDef = b2FixtureDef()
fixtureDef.shape = circle
fixtureDef.density = 0.3
fixtureDef.friction = 0
fixtureDef.restitution = 1.0
fixtureDef.filter.categoryBits = Constants.Config.PhysicsCategory.Player
fixtureDef.filter.maskBits = Constants.Config.PhysicsCategory.Wall
let ballBody = self.world.createBody(bodyDef)
ballBody.linearDamping = 0
ballBody.angularDamping = 0
ballBody.createFixture(fixtureDef)
Not sure that I know of a simple solution in the case that each tile can potentially have different physics.
If your walls are all horizontal and/or vertical, you could write a class to take a row of boxes, create a single edge or rectangle body, and then on collision calculate which box (a simple a < x < b test) should interact with the colliding object, and apply the physics appropriately, manually calling the OnCollision method that you would otherwise specify as the callback for each individual box.
Alternatively, to avoid the trouble of manually testing intersection with different boxes, you could still merge all common straight edge boxes into one edge body for accurate reflections. However, you would still retain the bodies for the individual boxes. Extend the boxes so that they overlap the edge.
Now here's the trick: all box collision handlers return false, but they toggle flags on the colliding object (turning flags on OnCollision, and off OnSeparation). The OnCollision method for the edge body then processes the collision based on which flags are set.
Just make sure that the colliding body always passes through a box before it can touch an edge. That should be straightforward.
I've created a tiled map composed of multiple sprite nodes that are 367x367. I create this map like so:
for var i = 0; i < Int(multiplier); i++ {
for var j = 0; j < Int(multiplier); j++ {
// Positive
var map = SKSpriteNode(imageNamed: "tiledBackground.png")
var x = CGFloat(i) * map.size.height
var y = CGFloat(j) * map.size.height
map.position = CGPointMake(x, y)
self.addChild(map)
}
}
In the above example, the multiplier is 27 and the map size is 10,000x10,000.
This creates the map as expected, however I want this map to have boundaries that the player can't leave. I know how to create the boundaries, but I'm not sure what values to initialize the physics body with.
I've tried this: SKPhysicsBody(rectangleOfSize: map.mapSize) however that produced very erroneous results.
I also tried this: SKPhysicsBody(edgeLoopFromRect: CGRectMake(0, 0, map.mapSize.width, map.mapSize.height)) which built a physics body like it should (I have showPhysics = TRUE), however the physics body seemed to move with the player (I have the player moving and am centering the map on the player). You can see what I mean here: http://gyazo.com/675477d5dd86984b393b10024341188a (It's a bit hard to see, but that green line is the boundary for the physics body. When the tiled map ends (And where it turns grey), the physics body should stop as that's where the player shouldn't be allowed to move any more).
Just leave a comment if you need any more code (I believe I included anything that is relevant).
After messing around with a bit of my code I found a fix was to just add the physicsBody to my map instead of the scene. A rather easy fix, so I'm surprised I didn't think of it sooner.
With this in mind, I've answered my own question and no longer need help.
I'm developing a game on Iphone and Ipad like a space invaders.
Balloons to destroy are falling from the top of the screen in a straight line.
Here my codes to add them :
func addBalloonv(){
var balloonv:SKSpriteNode = SKSpriteNode (imageNamed: "ballonvert.png")
balloonv.physicsBody = SKPhysicsBody (circleOfRadius: balloonv.size.width/2)
balloonv.physicsBody.dynamic = true
balloonv.physicsBody.categoryBitMask = balloonCategory | greenCategory
balloonv.physicsBody.contactTestBitMask = flechetteCategory
balloonv.physicsBody.collisionBitMask = balloonCategory
balloonv.physicsBody.mass = 1
balloonv.physicsBody.restitution = 1
balloonv.physicsBody.allowsRotation = true
let minX = balloonv.size.width/2
let maxX = self.frame.size.width - balloonv.size.width/2
let rangeX = maxX - minX
let position:CGFloat = CGFloat(arc4random()) % CGFloat(rangeX) + CGFloat(minX)
balloonv.position = CGPointMake(position, self.frame.size.height+balloonv.size.height)
self.addChild(balloonv)
I have one func by balloon color.
So for the moment they move in straight line and I'm looking for random movements (with turbulences like balloon in air) from the top and both sides.
How can I do that?
Thank you very much !!
This is exactly what the new Physics Fields feature in SpriteKit (as of iOS 8 / OS X Yosemite) is for. These let you apply different kinds of forces to all physics bodies in region, like gravity, drag, and turbulence. See the SKFieldNode class docs for details.
Fields are a kind of node, so to get what you're after, you'd add one noise (or turbulence) field to your scene, covering the area that the balloons fall through, and it'll perturb the path of each balloon that passes. The simplest way to do it goes something like this:
let field = SKFieldNode.noiseFieldWithSmoothness(0.5, animationSpeed: 0.1)
scene.addChild(field)
You'll want to tweak the smoothness, animation speed, and field.strength till you get just the level of noise you want. You might also look into whether you want just a noise field, which applies random forces in random directions, or a turbulence field, which does the same thing, but with forces that get stronger when bodies are moving faster.
The above code gets you a field whose region of effect is infinite. You might want to limit it to a specific area (for example, so it doesn't keep knocking your balloons around after they land). I did this to make a field that covers only the top 3/4 of a 300x200 scene:
field.region = SKRegion(size: CGSize(width: 300, height: 100))
field.position = CGPoint(x: 150, y: 150)
I have an endless runner game, my main character has a physics body, I use it to handle jumping.
Everything is great before he collides with obstacles. He starts shifting back, and I want him to stay on his x position at all times.
I tried setting the body dynamic to NO, but this stops jumping.
How do I go about this? I don't want character to move on the x axis.
do this on the update method
- (void)didSimulatePhysics {
CGPoint fixedXPos = myCharacter.position;
fixedXPos.x = fixedX;
[myCharacter setPosition:fixedXPos];
}
you can also use constraints
let range = SKRange(lowerLimit: 300, upperLimit: 340)
let lockToCenter = SKConstraint.positionX(range, y: range)
node.constraints = [ lockToCenter ]
and set the lower and upper limits to the same value for it to be locked in position.
In below mentioned code, what exactly is the difference between sprite, body and ground? Why are there no parameters passes to createBody while declaring ground?
what is difference between edgeshape.new() and polygonshape.new()?
require "box2d"
b2.setScale(20)
-- this function creates a box sprite with 2 happy and sad children
local function createBoxSprite(sx, sy)
local happy = Bitmap.new(Texture.new("happy-box.png", true))
happy:setAnchorPoint(0.5, 0.5)
local sad = Bitmap.new(Texture.new("sad-box.png", true))
sad:setAnchorPoint(0.5, 0.5)
local sprite = Sprite.new()
sprite:addChild(happy)
sprite:addChild(sad)
sprite:setScale(sx, sy)
return sprite
end
-- this table holds the dynamic bodies and their sprites
local actors = {}
-- create world
local world = b2.World.new(0, 9.8)
-- create a ground body and attach an edge shape
local ground = world:createBody({})
local shape = b2.EdgeShape.new(-200,480,520,480)
ground:createFixture({shape = shape, density = 0})
-- every 3 seconds, we create a random box
local function onTimer()
local sx = math.random(70, 100) / 100
local sy = math.random(70, 100) / 100
local body = world:createBody{type = b2.DYNAMIC_BODY, position = {x = math.random(0, 320), y = -35}}
local shape = b2.PolygonShape.new()
-- box images are 70x70 pixels. we create bodies 1 pixel smaller than that.
shape:setAsBox(34.5 * sx, 34.5 * sy)
body:createFixture{shape = shape, density = 1, restitution = 0.1, friction = 0.3}
local sprite = createBoxSprite(sx, sy)
stage:addChild(sprite)
actors[body] = sprite
end
Sprite is an empty object to group other Sprite inherited objects as in your case happy and sad Bitmaps.
Body is a representation of the physical body in box2d, it does not have any visual representation, only numbers as dimensions (width and height), position, rotation and different forces. Usually inside ENTER_FRAME event you take this values as position and rotation and apply them to the Sprite inherited object, so it would move exactly like the body in box2d simulated world.
Ground is an empty dummy box2d object. If you don't provide parameters to createBody it means the defaults are used, which basically means you don't care what values it has. The most common example of such body usage is for joints.
To create a joint you usually need two bodies, but what if you would to attach body through joint to some random position in the air, or dynamic position as mouse cursor, well you can do it by creating dummy physics object
Here is an example: http://appcodingeasy.com/Gideros-Mobile/Dragging-Box2d-object-in-Gideros-Mobile
In case of your example, then this body is used for EdgeShape which is usually an arbitrary shape used for creating world boundaries or in this case simply ground, so the dynamic object won't fall outside the screen