-- tilemap test 05 get object 2 -- -- use sti library -- https://github.com/karai17/Simple-Tiled-Implementation local sti = require "sti" enemys = {} -- define Beam class Beam = {} Beam.new = function(x, y, img, angle, speed) local obj = { activate = true, x = x, y = y, img = img, angle = angle, speed = speed } obj.ox = img:getWidth() / 2 obj.oy = img:getHeight() / 2 setmetatable(obj, {__index = Beam}) return obj end Beam.update = function(self, dt) self.y = self.y + ty_diff local spd = self.speed * dt local radv = math.rad(self.angle) self.x = self.x + spd * math.cos(radv) self.y = self.y + spd * math.sin(radv) local x = self.x + tx local y = self.y + ty local gid = map:getGidByPixel(x, y, "bg_a") if gid > 1 or self.y - self.oy > scr_h then self.activate = false end end Beam.draw = function(self) local x, y = math.floor(self.x), math.floor(self.y) love.graphics.draw(self.img, x, y, math.rad(self.angle), 1.0, 1.0, self.ox, self.oy) end function bornBeam(x, y, angle, speed) local obj = Beam.new(x, y, beam_img, angle, speed) table.insert(enemys, obj) end -- define EnemyLargeCanon class EnemyLargeCanon = {} EnemyLargeCanon.new = function(x, y, img, angle) local obj = { activate = true, x = x, y = y, img = img, angle = angle, timer = 0 } obj.ox = img:getWidth() / 2 obj.oy = img:getHeight() / 2 setmetatable(obj, {__index = EnemyLargeCanon}) return obj end EnemyLargeCanon.update = function(self, dt) self.y = self.y + ty_diff self.timer = self.timer + dt local t = 0.8 if self.timer >= t then self.timer = self.timer - t local radv = math.rad(self.angle) local d = 48 local x = self.x + d * math.cos(radv) local y = self.y + d * math.sin(radv) bornBeam(x, y, self.angle, 320) end if self.y - self.oy > scr_h then self.activate = false end end EnemyLargeCanon.draw = function(self) local x, y = math.floor(self.x), math.floor(self.y) love.graphics.draw(self.img, x, y, math.rad(self.angle), 1.0, 1.0, self.ox, self.oy) end -- define EnemyBlock class EnemyBlock = {} EnemyBlock.new = function(x, y, img, angle, speed) local obj = { activate = true, x = x, y = y, img = img, angle = angle, speed = speed } obj.ox = img:getWidth() / 2 obj.oy = img:getHeight() / 2 setmetatable(obj, {__index = EnemyBlock}) return obj end EnemyBlock.update = function(self, dt) self.y = self.y + ty_diff local spd = self.speed * dt local radv = math.rad(self.angle) local dx = math.cos(radv) local dy = math.sin(radv) self.x = self.x + spd * dx self.y = self.y + spd * dy local x = self.x + 32 * dx + tx local y = self.y + 32 * dy + ty if map:getGidByPixel(x, y, "bg_a") > 1 then self.angle = (self.angle + 180) % 360 end if self.y - self.oy > scr_h then self.activate = false end end EnemyBlock.draw = function(self) local x, y = math.floor(self.x), math.floor(self.y) love.graphics.draw(self.img, x, y, 0, 1.0, 1.0, self.ox, self.oy) end -- sprites update, draw, remove function updateSprites(objs, dt) for _, spr in ipairs(objs) do if spr.activate then spr:update(dt) end end end function drawSprites(tbl) for _, spr in ipairs(tbl) do if spr.activate then spr:draw() end end end function removeSprites(objs) local elen = #objs for i=elen,1,-1 do if not objs[i].activate then table.remove(objs, i) end end end function clearAllObjs(objs) local elen = #objs for i=elen,1,-1 do table.remove(objs, i) end end -- born enemy function bornEnemy(bg_x, bg_y) while born_enemy_index <= #enemy_set_tbl do local tbl = enemy_set_tbl[born_enemy_index] if bg_y - 64 > tbl.y then break end local ang = tonumber(tbl.type) local bx = bg_x % 1.0 local by = bg_y % 1.0 local x = tbl.x - bg_x local y = tbl.y - bg_y local obj = nil if tbl.name == "a" then obj = EnemyLargeCanon.new(x, y, canon_img, ang) elseif tbl.name == "b" then local spd = tbl.properties["speed"] obj = EnemyBlock.new(x, y, block_img, ang, spd) end table.insert(enemys, obj) born_enemy_index = born_enemy_index + 1 end end function love.load() love.graphics.setDefaultFilter("nearest", "nearest") scr_w, scr_h = 640, 480 canvas = love.graphics.newCanvas(scr_w, scr_h) -- load image canon_img = love.graphics.newImage("largecanon.png") block_img = love.graphics.newImage("block01.png") beam_img = love.graphics.newImage("beam01_64x64.png") -- load tilemap map = sti("mecha_bg2_map_with_enemy.lua") map.getGidByPixel = function(self, x, y, layer_name) local tilex, tiley = self:convertPixelToTile(math.floor(x), math.floor(y)) tilex = math.floor(tilex) tiley = math.floor(tiley) local layer = map.layers[layer_name] local tilew, tileh = layer.width, layer.height if tilex < 0 or tilex >= tilew or tiley < 0 or tiley >= tileh then return -2 end local tile = layer.data[tiley + 1][tilex + 1] if tile == nil then return -1 end return tile.gid end -- get map objects enemy_set_tbl = {} for k, obj in pairs(map.objects) do local x, y, w, h = obj.x, obj.y, obj.width, obj.height x = math.floor(x + w / 2) y = math.floor(y + h / 2) local data = { name=obj.name, type=obj.type, x=x, y=y, properties = obj.properties } table.insert(enemy_set_tbl, data) end -- sort objects by y table.sort(enemy_set_tbl, function(a, b) return (a.y > b.y) end) map.layers["enemy_tbl"].visible = false tx_start = 32 ty_start = 480 * 7 tx = tx_start ty = ty_start ty_diff = 0 gid = 0 born_enemy_index = 1 -- framerate steady min_dt = 1 / 60 next_time = love.timer.getTime() end function love.update(dt) next_time = next_time + min_dt wdw_w, wdw_h = love.graphics.getDimensions() scr_scale = math.min((wdw_w / scr_w), (wdw_h / scr_h)) scr_ofsx = (wdw_w - (scr_w * scr_scale)) / 2 scr_ofsy = (wdw_h - (scr_h * scr_scale)) / 2 bornEnemy(tx, ty) map:update(dt) ty_diff = 48 * dt ty = ty - ty_diff map.layers["enemy_tbl"].x = -tx map.layers["enemy_tbl"].y = -ty map.layers["bg_a"].x = -tx map.layers["bg_a"].y = -ty map.layers["bg_b"].x = -tx / 2 map.layers["bg_b"].y = -ty / 2 map.layers["bg_c"].x = -tx / 4 map.layers["bg_c"].y = -ty / 4 -- get mouse position and get tile gid local mx, my = love.mouse.getPosition() mx = (mx - scr_ofsx) / scr_scale + tx my = (my - scr_ofsy) / scr_scale + ty gid = map:getGidByPixel(mx, my, "bg_a") updateSprites(enemys, dt) removeSprites(enemys) end function love.draw() love.graphics.setCanvas(canvas) love.graphics.clear(0, 0, 0, 255) -- draw tilemap BG love.graphics.setColor(255, 255, 255, 255) map:draw() -- draw objects love.graphics.setColor(255, 255, 255, 255) drawSprites(enemys) love.graphics.setCanvas() -- draw canvas to window love.graphics.setColor(255, 255, 255) love.graphics.draw(canvas, scr_ofsx, scr_ofsy, 0, scr_scale, scr_scale) love.graphics.print("FPS: "..tostring(love.timer.getFPS()), 10, 10) love.graphics.print("tx = "..tostring(tx), 10, 40) love.graphics.print("ty = "..tostring(ty), 10, 60) love.graphics.print("R : reset", 10, 100) love.graphics.print("ESC : exit", 10, 120) love.graphics.print("objs = "..tostring(#enemys), 10, 140) love.graphics.print("gid = "..tostring(gid), 10, 160) if love.system.getOS() == "Windows" then -- wait local cur_time = love.timer.getTime() if next_time <= cur_time then next_time = cur_time else love.timer.sleep(next_time - cur_time) end end end function love.keypressed(key, isrepeat) if key == "escape" then -- ESC to exit love.event.quit() elseif key == "r" then -- reset scroll position tx = tx_start ty = ty_start born_enemy_index = 1 end end