Corona SDK custom physics bodies - lua

i have some trouble with the custom shapes in corona.
Here is my code and what it does is that i'm adding some spheres to the scene so that they fall inside a basket, this basket is the custom shape object that i defined in the newBasket() function, the problem is that the basket does collide with the ground object but it doesn't collide with the spheres and i don't know why, please someone help me here, i can't find a solution elsewhere, thanks in advance.
_W = display.contentWidth
_H = display.contentHeight
--Physics
local physics = require("physics")
physics.start()
physics.setDrawMode("debug")
-- iOS
display.setStatusBar(display.HiddenStatusBar)
-- screen boundaries
local ground = display.newRect(0, _H, _W, 5)
local leftWall = display.newRect(0,0,1,_H)
local rightWall = display.newRect(_W,0,1,_H)
physics.addBody(ground, "static", {friction = .2, bounce = .1})
physics.addBody(leftWall, "static", {friction = .2, bounce = .1})
physics.addBody(rightWall, "static", {friction = .2, bounce = .1})
local function newBasket()
local body = display.newImage("assets/basket.png")
body.x = 0 body.y = 0
local physics_body = {}
physics_body["basket"] = {
{
--LeftArm
density = 10, friction = 10, bounce = 0.15,
shape = {-126, 40, -110, 40, -140, -64, -156, -64}
},
{
--Bottom
density = 10, friction = 1, bounce = 0,
shape = {-121, 60, 125, 60, 128, 40, -126, 40}
},
{
--RightArm
density = 10, friction = 10, bounce = 0.15,
shape = {113, 40, 129, 40, 158, -64, 143, -64}
}
}
physics.addBody(body, unpack(physics_body["basket"]) )
return body
end
local basket = newBasket()
basket.x = _W * .5 basket.y = _H - 100
local function newPlanet()
local planets = {
{img = "bigBall.png", radius = 45},
{img = "mediumBall.png", radius = 30},
{img = "smallBall.png", radius = 20}
}
local n = math.random(1,3)
local img = "assets/" .. planets[n].img
local ball = display.newImage(img)
ball.x = math.random((_W * 0.5) -100, (_W * 0.5) + 100) ball.y = 0
physics.addBody(ball, {bounce = 0.3, radius = planets[n].radius})
end
local function spawnPlanets(number)
local function spawn(e)
newPlanet()
if(e.count == number) then
timer.cancel(tmr)
tmr = nil
end
end
tmr = timer.performWithDelay(500, spawn, number)
end
spawnPlanets(20)

According to the manual:
If a shape is specified, then the body boundaries will follow the polygon provided by the shape. Note that the maximum number of sides per shape is eight, and all angles must be convex. [...] The shape coordinates must be defined in clockwise order, and the resulting shape must be convex-only.
So you have two issues working against you. First the shapes must be defined in clockwise order, as I've done in the below example. Secondly, all shapes must be convex (even complex body shapes) so you can't do anything that turns in on itself like a crescent moon or basket.
Unfortunantly, this means you have to make your basket as 3 separate shapes. Also, since they are now separate shapes, they won't stay stuck together when they fall (unless you use joints). I've just made the basket 3 static bodies and put it in the right place to start with:
local function newBasket()
local physics_body = {}
physics_body["basket"] = {
{
--LeftArm
density = 10, friction = 10, bounce = 0.15,
shape = {-126, 40, -156, -64, -140, -64, -110, 40 }
},
{
--Bottom
density = 10, friction = 1, bounce = 0,
shape = {-121, 60,-126, 40, 128, 40, 125, 60 }
},
{
--RightArm
density = 10, friction = 10, bounce = 0.15,
shape = {113, 40, 143, -64, 158, -64, 129, 40 }
}
}
for k,shape in pairs(physics_body["basket"]) do
local body = display.newRect(0, 0, 200, 100)
body.x = display.contentCenterX
body.y = display.contentHeight - 60
physics.addBody(body, 'static', shape )
end
end
newBasket()

Related

How to anchor object inside a rectangle in corona sdk?

I am trying to add a little rectangle inside of a big rectangle as seen in the images below but nothing seems to be working. I want to use anchors but I do not know how to proceed. I am trying to put the little rectangle in the top right corner of the bigger rectangle.Any advice would be extremely helpful!
local bigRectangle = display.newRect(200,200,320,400)
bigRectangle:setFillColor(0,0,1)
bigRectangle.x = _X
bigRectangle.y = _Y
local smallRectangle = display.newRect(200,200,20,20)
bigRectangle:setFillColor(255/255,255/255,0/255)
what I am trying to accomplish:
It can be accomplish in many ways. The simplest way is to change anchor point to (1, 0). It requires that both objects have the same x and y coords:
local bigRectangle = display.newRect( 200, 200, 320, 400 )
bigRectangle.anchorX, bigRectangle.anchorY = 1, 0
bigRectangle:setFillColor( 0, 0, 1 )
local smallRectangle = display.newRect( 200, 200, 20, 20 )
smallRectangle.anchorX, smallRectangle.anchorY = 1, 0
smallRectangle:setFillColor( 255 / 255, 255 / 255, 0 / 255 )
More universal method use bounds property of display objects:
local bigRectangle = display.newRect( 200, 200, 320, 400 )
bigRectangle:setFillColor( 0, 0, 1 )
bigRectangle.x = _X
bigRectangle.y = _Y
local smallRectangle = display.newRect( 200, 200, 20, 20 )
smallRectangle:setFillColor( 255 / 255, 255 / 255, 0 / 255 )
local bounds = bigRectangle.contentBounds
smallRectangle.x = bounds.xMax - smallRectangle.width * smallRectangle.anchorX
smallRectangle.y = bounds.yMin + smallRectangle.height * smallRectangle.anchorY

Corona Vertices of a Hexagon

Ok, so I'm trying to create hexagons for my game. The first option I had is to have several images of hexagon, but I'm having problems with clickable area since these images are positioned side-by-side.
So i guess my only option is to create objects using polygons. Here is a code from corona sdk's website:
local halfW = display.contentWidth * 0.5
local halfH = display.contentHeight * 0.5
local vertices = { 0,-110, 27,-35, 105,-35, 43,16, 65,90, 0,45, -65,90, -43,15, -105,-35, -27,-35, }
local o = display.newPolygon( halfW, halfH, vertices )
o.fill = { type="image", filename="mountains.png" }
o.strokeWidth = 10
o:setStrokeColor( 1, 0, 0 )
That code is for creating a star. But I don't know how to create a hexagon using vertices.
Try this to create the vertices array:
local R = 45
local N = 6
local vertices = {}
local i = 0
for t = 0, 2*math.pi, 2*math.pi/N do
i=i+1; vertices[i]= R*math.cos(t)
i=i+1; vertices[i]= R*math.sin(t)
end
And this to draw the hexagon:
local halfW = display.contentWidth * 0.5
local halfH = display.contentHeight * 0.5
local hexagon = display.newPolygon( halfW, halfH, vertices )
hexagon.fill = { type="image", filename="mountains.png" }
hexagon.strokeWidth = 10
hexagon:setStrokeColor( 1, 0, 0 )
I chose R=45 to produce a polygon of the same size of your star.
You could always use a graphics.newMask() to apply a mask to each image hex that would make the outside area not touchable.

Randomly putting a circle in a box

I am making a game and I am trying to randomly put a circle in a rectangle. But, it seems that the circle sometimes appear outside of the rectangle. What would I have to do so the circle ALWAYS appears somewhere in the rectangle?
this is my code:
rectangle:
--bottom
local floor = display.newRect(0, display.contentCenterY/.665, display.contentWidth*2, 10)
physics.addBody(floor, "static", {density = 1, friction = 1, bounce = 0})
--top
local floor = display.newRect(0, display.contentCenterY/2, display.contentWidth*2, 10)
physics.addBody(floor, "static", {density = 1, friction = 1, bounce = 0})
--right
local floor = display.newRect(display.contentCenterX*2, display.contentCenterY/1, 10, display.contentHeight/2)
physics.addBody(floor, "static", {density = 1, friction = 1, bounce = 0})
--left
local floor = display.newRect(0, display.contentCenterY/1, 10, display.contentHeight/2)
physics.addBody(floor, "static", {density = 1, friction = 1, bounce = 0})
circle:
--Small sprites--
local randomX = math.random(1,display.contentCenterX*2)
local randomY = math.random(1, display.contentCenterY*2)
local smallSprite = display.newCircle(randomX, randomY, display.contentWidth/100)
smallSprite:setFillColor(1, 1, .3, 1) --This will set the fill color to transparent
smallSprite.strokeWidth = 7 --This is the width of the outline of the circle
smallSprite:setStrokeColor(.1,1,1) --This is the color of the outline
smallSprite = display.newGroup(smallSprite)
That is easy, you know where the sides of rectangle are (call them rigth, left, top and bottom) and the radius of circle, so: randomX will be between left+radius and right-radius, and randomY will be between top+radius and bottom-radius
-- remember to add/substract the width of the walls
local left = 0 + 10
local right = display.contentCenterX * 2 - 10
--Small sprites--
local randomX = math.random(left+radius,right-radius)
local randomY = math.random(top+radius, bottom-radius)
You can generate a random number between any 2 numbers of your choice.
Remember also you can use display.contentHeight and display.contentWidth
As a tip, you can add at the beginning of your file a section with variables like:
-- Variables
local w = display.contentWidth
local h = display.contentHeight
local centerX = display.contentCenterX
local centerY = display.contentCenterY
So you can use only centerX instead of display.contentCenterX

corona sdk realistic ball bounces off of static objects like walls

I hope to make the ball bouncing realistic. Sometimes it will bounce, the apex will begin to decrease and then it hits the ground again and bounces even higher. Same happens when it hits the walls, it is as if the walls apply a force to the ball against my will (I do not have any force applied to the ball, besides gravity which is at default setting of 9.8 in the y-direction.
physics.addBody(bottomWall, "static", {density = 0, friction = 0, bounce = 0, isSensor = false})
physics.addBody(leftWall, "static", {density = 0, friction = 0, bounce = 0, isSensor = false})
physics.addBody(rightWall, "static", {density = 0, friction = 0, bounce = 0, isSensor = false})
local circle = display.newCircle( halfW, 20, 25 )
circle.x, circle.y = 160, -100
physics.addBody(circle, "dynamic", {bounce = 0.95})
Try also changing linearDamping and angularDamping of ball
circle.linearDamping = 10;
circle.angularDamping = 10;

I drawed a player into my love2d but it only fills out 1/4?

This is my charecter in love2d while jumping.
It looks fine but..
when I get on the ground it looks like this.
I figured out that it may have some thing to do with the img, that it doesn't fill out the entire square.
So it is simply is out of the collision square.
Thats the square it should have been in, but since im quite new to programing I cant figure out how to do it.
I have been searching for a solution but cant find one ATM.
This is my
love.load
function love.load()
love.graphics.setBackgroundColor( 204, 255, 204 )
crazy = love.graphics.newImage("player.png")
pwidth = crazy.getWidth
pheight = crazy.getHeight
AdvTiledLoader.path = "maps/"
map = AdvTiledLoader.load("map.tmx")
map:setDrawRange(0, 0, map.width * map.tileWidth, map.height * map.tileHeight)
camera:setBounds(0, 0, map.width * map.tileWidth - love.graphics.getWidth(), map.height * map.tileHeight - love.graphics.getHeight() )
world = {
gravity = 1536,
ground = 512,
}
player = {
x = 256,
y = 256,
x_vel = 0,
y_vel = 0,
jump_vel = -1024,
speed = 512,
flySpeed = 700,
state = "",
h = 32,
w = 32,
standing = false,
}
function player:jump()
if self.standing then
self.y_vel = self.jump_vel
self.standing = false
end
end
function player:right()
self.x_vel = self.speed
end
function player:left()
self.x_vel = -1 * (self.speed)
end
function player:stop()
self.x_vel = 0
end
function player:collide(event)
if event == "floor" then
self.y_vel = 0
self.standing = true
end
if event == "cieling" then
self.y_vel = 0
end
end
And my love.draw
function love.draw()
camera:set()
love.graphics.draw(crazy, player.x , player.y)
love.graphics.setColor( 255, 255, 255 )
map:draw()
camera:unset()
end
If you need to see my collision or anything else just ask and I will paste it below :)
I really apriciate your help thanks!
What is most likely happening is that the you have the x,y co-ordinate as the centre of the sprite. So it's stopping when the map meets the centre.
As you're drawing the sprite before the map, you only see the bit not covered by the map.
An easy way of proving this is to draw the sprite after the map and you should see the whole sprite over the map.
There would be a couple of ways to resolve this. Either leave the collisions where they are and draw the sprite with ox=-width/2,oy=-height/2.
Alternatively have the collision at the at the bottom of the sprite by adding width/2 and height/2 to the collision point.
If this doesn't help then we'll probably need the collision logic.
First of all, I assume you want pwidth/pheight to be numbers, not the get functions.
pwidth = crazy.getWidth()
pheight = crazy.getHeight()
The image is drawn from it's topleft corner, but I'm guessing that your collision logic has the hitbox centered on the player's position.
You can either compensate by changing the coordinate of the draw function, or pass in an origin offset to the image. The advantage of specifying the origin offset is that you can then rotate and scale relative to that origin.
love.graphics.draw(crazy, player.x - pwidth/2 , player.y - pheight/2)
or
rotation, scalex, scaley = 0, 1, 1
love.graphics.draw(crazy, player.x, player.y, rotation, scalex, scaley, pwidth/2, pheight/2)

Resources