Make collision boxes stay when camera is used
Posted: Tue Jun 23, 2020 2:42 am
I'm making a basic 1986 Zelda game and so far I am comfortable using love.physics and setting up the collisions boxes and things of that nature. Once I tried to move the camera down all my boxes don't stay where they're supposed to be at. I only have an offset of -3 for the camera. They collision boxes just remain on the screen, how do I go about updating this?
Main.lua
Main.lua
Code: Select all
Class = require 'class'
push = require 'push'
require 'Util'
require 'Player'
require 'BoxP'
require 'BoxE1'
require 'Enemy1'
require 'Enemy2'
require 'Enemy3'
require 'Enemy_fire'
-- Initialize classes to main
my_player = Player:init()
my_enemy_1 = Enemy1:init()
my_enemy_2 = Enemy2:init()
my_enemy_3 = Enemy3:init()
enemy_fire = Enemy_fire:init()
my_enemy1_box = BoxE1:init()
TILE_EMPTY = -1
-- Tree tiles
TILE_TREE = 4
-- Top wall tiles
TILE_WALL = 2
SECRET_WALL = 6
TILE_HEART = 1
-- close resolution to NES but 16:9
VIRTUAL_WIDTH = 432
VIRTUAL_HEIGHT = 243
-- actual window resolution
WINDOW_WIDTH = 1280
WINDOW_HEIGHT = 720
local SCROLL_SPEED = 65
love.graphics.setDefaultFilter('nearest', 'nearest')
local tileWidth = 16
local tileHeight = 16
local mapWidth = 30
local mapHeight = 28
local xOffset = 8
local yOffset = 10
local tiles = {}
local p = love.physics
function love.load()
world = love.physics.newWorld()
-- Create collision boxes for each object
wall_left = {}
wall_left.b = p.newBody(world,8,115,'static')
wall_left.s = p.newRectangleShape(tileWidth,225)
wall_left.f = p.newFixture(wall_left.b,wall_left.s)
wall_right = {}
wall_right.b = p.newBody(world,424,1,'static')
wall_right.s = p.newRectangleShape(tileWidth,450)
wall_right.f = p.newFixture(wall_right.b,wall_right.s)
wall_top = {}
wall_top.b = p.newBody(world,210,11,'static')
wall_top.s = p.newRectangleShape(420,tileHeight)
wall_top.f = p.newFixture(wall_top.b,wall_top.s)
wall_bottom = {}
wall_bottom.b = p.newBody(world,210,235,'static')
wall_bottom.s = p.newRectangleShape(377,tileHeight)
wall_bottom.f = p.newFixture(wall_bottom.b,wall_bottom.s)
secret_wall = {}
secret_wall.b = p.newBody(world,377,235,'static')
secret_wall.s = p.newRectangleShape(416,tileHeight)
secret_wall.f = p.newFixture(secret_wall.b,secret_wall.s)
tree_top = {}
tree_top.b = p.newBody(world,151,75,'static')
tree_top.s = p.newRectangleShape(tileWidth * 11 - 5,tileHeight)
tree_top.f = p.newFixture(tree_top.b,tree_top.s)
tree_bottom = {}
tree_bottom.b = p.newBody(world,151,140,'static')
tree_bottom.s = p.newRectangleShape(tileWidth * 11 - 5,tileHeight)
tree_bottom.f = p.newFixture(tree_bottom.b,tree_bottom.s)
tree_left = {}
tree_left.b = p.newBody(world,344,105,'static')
tree_left.s = p.newRectangleShape(tileWidth,tileHeight * 7)
tree_left.f = p.newFixture(tree_left.b,tree_left.s)
player.b = p.newBody(world,Player.x + 8,Player.y + 11,'dynamic')
player.b:setFixedRotation(true)
player.s = p.newRectangleShape(16,16)
player.f = p.newFixture(player.b,player.s)
enemy1.b = p.newBody(world,Enemy1.x + 8,Enemy1.y + 11,'dynamic')
enemy1.b:setFixedRotation(true)
enemy1.s = p.newRectangleShape(16,16)
enemy1.f = p.newFixture(enemy1.b,enemy1.s)
enemy2.b = p.newBody(world,Enemy2.x,Enemy2.y,'dynamic')
enemy2.b:setFixedRotation(true)
enemy2.s = p.newRectangleShape(16,16)
enemy2.f = p.newFixture(enemy2.b,enemy2.s)
enemy3.b = p.newBody(world,Enemy3.x ,Enemy3.y ,'dynamic')
enemy3.b:setFixedRotation(true)
enemy3.s = p.newRectangleShape(16,16)
enemy3.f = p.newFixture(enemy3.b,enemy3.s)
push:setupScreen(VIRTUAL_WIDTH, VIRTUAL_HEIGHT, WINDOW_WIDTH, WINDOW_HEIGHT, {
fullscreen = false,
resizable = true
})
spritesheet = love.graphics.newImage('Sprites/hearts_tree_walls.png')
-- camera offsets
camX = 0
camY = -3
sprites = generateQuads(spritesheet, 16, 16)
-- cache width and height of map in pixels
mapWidthPixels = mapWidth * tileWidth
mapHeightPixels = mapHeight * tileHeight
-- sets a tile at a given x-y coordinate to an integer value
-- first, fill map with empty tiles
for y = 1, mapHeight do
for x = 1, mapWidth do
-- support for multiple sheets per tile; storing tiles as tables
setTile(x, y, TILE_EMPTY)
end
end
-- create wall tiles on the bottom of the screen
for y = mapHeight / 2 + 1, mapHeight / 2 + 1 do
for x = 0, 25 do
setTile(x, y, TILE_WALL)
end
end
-- Secret wall
if player.b:isTouching(secret_wall.b) then
for y = mapHeight / 2 + 1, mapHeight / 2 + 1 do
for x = 26, 26 do
setTile(x, y, TILE_EMPTY)
end
end
else
for y = mapHeight / 2 + 1, mapHeight / 2 + 1 do
for x = 26, 26 do
setTile(x, y, SECRET_WALL)
end
end
end
--left hand side tile
for y = 0, 25 do
for x = 1, 1 do
setTile(x, y, TILE_WALL)
end
end
-- Upper right hand side tiles
for y = 0, 25 do
for x = 27, 27 do
setTile(x, y, TILE_WALL)
end
end
--Top screen tiles
for y = 1, 1 do
for x = 0, 26 do
setTile(x, y, TILE_WALL)
end
end
-- tree top left
for y = 5, 5 do
for x = 5, 15 do
setTile(x, y, TILE_TREE)
end
end
-- tree bottom-left
for y = 9, 9 do
for x = 5, 15 do
setTile(x, y, TILE_TREE)
end
end
-- tree right
for y = mapHeight / 2 - 10, mapHeight / 2 - 4 do
for x = 22, 22 do
setTile(x, y, TILE_TREE)
end
end
for y = mapHeight / 2 - 12, mapHeight / 2 - 12 do
for x = 26, 26 do
setTile(x, y, TILE_HEART)
end
end
love.window.setTitle('Legend of Zelda Demo')
love.keyboard.keysPressed = {}
love.keyboard.keysReleased = {}
end
function setTile(x, y, id)
tiles[(y - 1) * mapWidth + x] = id
end
-- gets the tile type at a given pixel coordinate
function tileAt(x, y)
return {
x = math.floor(x / tileWidth) + 1,
y = math.floor(y / tileHeight) + 1,
id = getTile(math.floor(x / tileWidth) + 1, math.floor(y / tileHeight) + 1)
}
end
-- returns an integer value for the tile at a given x-y coordinate
function getTile(x, y)
return tiles[(y - 1) * mapWidth + x]
end
function collides(tile)
-- define our collidable tiles
collidables = {
TILE_TREE,TILE_WALL,SECRET_WALL
}
-- iterate and return true if our tile type matches
for _, v in ipairs(collidables) do
if tile.id == v then
return true
end
end
return false
end
function love.resize(w,h)
push:resize(w,h)
end
function love.keyboard.wasReleased(key)
if (love.keyboard.keysReleased[key]) then
return true
else
return false
end
end
function love.keypressed(key)
if key == 'escape' then
love.event.quit()
end
love.keyboard.keysPressed[key] = true
end
function love.keyreleased(key)
love.keyboard.keysReleased[key] = true
end
function love.update(dt)
if love.keyboard.isDown('w') then
camY = math.max(0,camY - dt * SCROLL_SPEED)
elseif love.keyboard.isDown('s') then
camY = math.min(camY + dt * SCROLL_SPEED, mapHeightPixels - VIRTUAL_HEIGHT)
end
world:update(dt)
Player:update(dt)
Enemy1:update(dt)
Enemy2:update(dt)
Enemy3:update(dt)
BoxE1:update(dt)
--Enemy_fire:update(dt)
-- reset all keys pressed and released this frame
love.keyboard.keysPressed = {}
love.keyboard.keysReleased = {}
end
function love.draw()
push:apply('start')
-- Clears screen with light brown color
love.graphics.clear(252/255, 216/255, 169/255, 1)
-- Draws left wall
love.graphics.polygon('line',wall_left.b:getWorldPoints(wall_left.s:getPoints()))
-- Draws right wall
love.graphics.polygon("line", wall_right.b:getWorldPoints(wall_right.s:getPoints()))
-- Draws top wall
love.graphics.polygon("line", wall_top.b:getWorldPoints(wall_top.s:getPoints()))
-- Draws bottom wall
love.graphics.polygon("line", wall_bottom.b:getWorldPoints(wall_bottom.s:getPoints()))
-- Draws secret wall
love.graphics.polygon("line", secret_wall.b:getWorldPoints(secret_wall.s:getPoints()))
-- Draws Top tree
love.graphics.polygon("line", tree_top.b:getWorldPoints(tree_top.s:getPoints()))
-- Draws Bottom tree
love.graphics.polygon("line", tree_bottom.b:getWorldPoints(tree_bottom.s:getPoints()))
-- Draws left tree
love.graphics.polygon("line", tree_left.b:getWorldPoints(tree_left.s:getPoints()))
-- Draws Link's(player) collision box
love.graphics.polygon("line", player.b:getWorldPoints(player.s:getPoints()))
-- Draws enemy1's collision box
love.graphics.polygon("line", enemy1.b:getWorldPoints(enemy1.s:getPoints()))
-- Draws enemy2's collision box
love.graphics.polygon("line", enemy2.b:getWorldPoints(enemy2.s:getPoints()))
-- Draws enemy3's collision box
love.graphics.polygon("line", enemy3.b:getWorldPoints(enemy3.s:getPoints()))
love.graphics.translate(math.floor(-camX + 0.5), math.floor(-camY + 0.5))
local scaleX = -1
for y = 1, mapHeight do
for x = 1, mapWidth do
local tile = getTile(x, y)
if tile ~= TILE_EMPTY then
love.graphics.draw(spritesheet, sprites[tile],
(x - 1) * tileWidth, (y - 1) * tileHeight)
end
end
end
Player:render()
Enemy1:render()
Enemy2:render()
Enemy3:render()
--BoxP:draw()
--BoxE1:draw()
push:apply('end')
end