Hey Everyone,
This is my first time posting but I have received a lot of help by searching through this forum. I am currently creating a 2D platformer with the assets provided by codea. I have most of my features working but I am running into a bit of trouble with physics and collisions. Most of the time everything works as expected, but on occassion my character ignores collisions with my ground tiles and falls through the map. I’ve included my code below and would really appreciate some feedback, also I feel like my level generator code is pretty easy and effective to use so feel free to use it in your own projects.
-- 2D Platformer
supportedOrientations(CurrentOrientation)
-- Use this function to perform your initial setup
function setup()
--Character setup
player = Character()
--Level setup
stage = Level()
end
function draw()
background(0, 92, 255, 255)
strokeWidth(5)
camera(mainCharacter.x-WIDTH/2, mainCharacter.y-HEIGHT/3, 10, mainCharacter.x-WIDTH/2, mainCharacter.y-HEIGHT/3, 1)
player:draw()
stage:draw()
end
function touched(touch)
player:touched(touch)
end
function collide(contact)
player:collide(contact)
end
Character = class()
function Character:init(x)
-- you can accept and set parameters here
spriteMode(CENTER)
characterSize = 75
characterSpeed = 6
characterMaxSpeed = 250
mainCharacter = physics.body(CIRCLE, characterSize/1.5)
mainCharacter.gravityScale = 2
mainCharacter.restitution = .2
mainCharacter.x = WIDTH/2
mainCharacter.y = HEIGHT/2
characterGrounded = 0 -- 0 is false, 1 is true
mainCharacter.friction = .2
mainCharacter.fixedRotation = true
end
function Character:draw()
-- Codea does not automatically call this method
sprite("Platformer Art:Guy Standing", mainCharacter.x, mainCharacter.y, characterSize)
--print(mainCharacter.linearVelocity.x)
if mainCharacter.linearVelocity.x < characterMaxSpeed and mainCharacter.linearVelocity.x > -characterMaxSpeed then
mainCharacter:applyForce(vec2(Gravity.x*300, 0))
end
-- mainCharacter.x = mainCharacter.x + Gravity.x * characterSpeed
end
function Character:touched(touch)
-- Codea does not automatically call this method
end
function Character:collide(contact)
if contact.state == BEGAN then
print( contact.bodyA.info)
if contact.bodyA ~= nil then
if contact.bodyA.info == "ground" then
characterGrounded = 1
print("hit")
end
end
end
end
function Character:touched(touch)
if touch.state == BEGAN then
if characterGrounded == 1 then
mainCharacter:applyForce(vec2(0, 5000))
characterGrounded=0
print("jump")
end
end
end
Level = class()
function Level:init()
-- you can accept and set parameters here
rectMode(CENTER)
--0: empty
--1:ground
--2: wall
--3: cloud
--4: levelEnd
--5: coin
levelLayout =
{
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,4},
{1,0,0,0,0,0,0,0,5,1},
{2,0,0,0,3,0,0,5,1,2},
{2,0,0,0,0,0,5,1,2,2},
{2,0,0,0,0,5,1,2,2,2},
{2,0,0,0,0,1,2,2,2,2},
{1,1,1,1,1,1,1,1,1,1}
}
for i, row in ipairs(levelLayout) do
for j, block in pairs(row) do
if levelLayout[i][j] == 1 or levelLayout[i][j] == 2 then
--print(levelLayout[i][j])
rectWidth = 100
rectHeight = 100
physicsRect = physics.body(POLYGON,
vec2(-rectWidth/2, -rectHeight/2), --bottom left
vec2(-rectWidth/2, rectHeight/2), --top left
vec2(rectWidth/2, rectHeight/2), --top right
vec2(rectWidth/2, -rectHeight/2) --bottom right
)
physicsRect.gravityScale = 0
physicsRect.restitution = 0.1
physicsRect.x = j*100
physicsRect.y = HEIGHT-(100*i)
physicsRect.type = STATIC
physicsRect.friction = .2
if levelLayout[i][j] == 1 then
physicsRect.info = "ground"
end
if levelLayout[i][j] == 2 then
physicsRect.info = "wall"
end
end
if levelLayout[i][j] == 4 then
starSize = 100
star = physics.body(CIRCLE, starSize/2)
star.gravityScale = 5
star.restitution = .2
star.x = j*100
star.y = HEIGHT-(100*1)
star.info = "star"
end
end
end
end
function Level:draw()
-- Codea does not automatically call this method
for i, row in ipairs(levelLayout) do
for j, block in pairs(row) do
if levelLayout[i][j] == 1 then
sprite("Platformer Art:Block Grass", j*100, HEIGHT-(100*i), 100, 100)
end
if levelLayout[i][j] == 2 then
sprite("Platformer Art:Block Brick", j*100, HEIGHT-(100*i), 100, 100)
end
if levelLayout[i][j] == 3 then
sprite("Platformer Art:Cloud 2", j*100, HEIGHT-(100*i), 200, 100)
end
if levelLayout[i][j] == 4 then
sprite("Small World:Glow", j*100, HEIGHT-(100*i), 100, 100)
end
if levelLayout[i][j] == 5 then
sprite("Platformer Art:Coin", j*100, HEIGHT-(100*i), 30, 30)
end
end
end
end
function Level:touched(touch)
-- Codea does not automatically call this method
end