[Lua][Love] "图块集与地图" 加载显示功能 TileMap
效果

安装库
安装两个库,分别用来读xml和csv,如果有luarocks,执行下列命令
luarocks install xml2lua
luarocks install ftcsv
manoelcampos/xml2lua (github.com)
整体结构 tilemap.lua

引入要用的两个库,创建xml解析器,读取xml解析到的数据是从handler.root里读的,而不是parser
local xml2lua = require 'xml2lua'
local handler = require 'xmlhandler.tree'
local ftcsv = require 'ftcsv'
local parser = xml2lua.parser(handler)
local map = {}
local tileset = {}
在love.load执行两个回调函数加载图块集跟地图
function map:load(...)
map:loadTMX(love.filesystem.getWorkingDirectory() .. "/map/map.tmx")
end
function tileset:load(...)
tileset:loadTSX(love.filesystem.getWorkingDirectory() .. "/map/tilemap_packed.tsx")
tileset:loadTile()
end
在游戏窗口绘制各个图块,图层从map列表获得,图块从tileset列表获得
function map:draw()
for _, layer in ipairs(map) do
for i = 1, map.height, 1 do
for k = 1, map.width, 1 do
if layer[i][k] ~= "0" then
love.graphics.draw(
tileset.image,
tileset[tonumber(layer[i][k])],
tileset.tilewidth * (k - 1),
tileset.tileheight * (i - 1)
)
end
end
end
end
end
加载文件用,找不到文件就报错
function openFile(filename)
local f = io.open(filename, 'r')
if f then
return f
else
error("no file exists", 2)
end
end
加载地图文件 tmx,先用xml解析器解析,然后用ftcsv解析各个图层保存到map里
tmx各个图层csv的最后一行末尾没有 , 符号会导致 ftcsv 出错,手动添加一个 , 符号
function map:loadTMX(filename)
local f = openFile(filename)
local tmx = f:read('a')
parser:parse(tmx)
local attr = handler.root.map._attr
map.width = tonumber(attr.width)
map.height = tonumber(attr.height)
for _, value in pairs(handler.root.map.layer) do
map[#map + 1] = ftcsv.parse(value.data[1] .. ',', ",", { headers = false, loadFromString = true })
end
end
加载 TSX 图块集的信息,包括图块大小,图块数量,列数,行数需要自己算,记得转换成 number 类型
function tileset:loadTSX(filename)
local f = openFile(filename)
local tsx = f:read('a')
parser:parse(tsx)
local attr = handler.root.tileset._attr
local image = handler.root.tileset.image._attr
tileset.tilewidth = tonumber(attr.tilewidth)
tileset.tileheight = tonumber(attr.tileheight)
tileset.tilecount = tonumber(attr.tilecount)
tileset.columns = tonumber(attr.columns)
tileset.rows = tileset.tilecount / tileset.columns
tileset.source = image.source
tileset.width = tonumber(image.width)
tileset.width = tonumber(image.height)
end
加载 TSX 图块集信息后,已经拿到图块数量,图块大小,图片集文件地址等信息。通过这些信息,我们使用加载图片集文件,然后使用 newQuad 将图片集各个部分,即图块,保存到tileset列表中
function tileset:loadTile()
self.source = string.gsub(self.source, "%.%.", "")
self.image = love.graphics.newImage(self.source)
for i = 0, tileset.rows - 1, 1 do
for j = 0, tileset.columns - 1, 1 do
tileset[#tileset + 1] = love.graphics.newQuad(
j * tileset.tilewidth, i * tileset.tileheight,
tileset.tilewidth, tileset.tileheight, self.image
)
end
end
end
返回map跟tileset
return {
map = map,
tileset = tileset
}
鼠标位置显示坐标 mouse.lua
根据鼠标在屏幕的x、y坐标绘制方块和文字
local mouse = {}
mouse.pos_x = 0
mouse.pos_y = 0
mouse.size = 32
function mouse:update(t)
mouse.pos_x, mouse.pos_y = love.mouse.getPosition()
end
function mouse:draw()
local x = math.floor(self.pos_x / self.size)
local y = math.floor(self.pos_y / self.size)
love.graphics.rectangle("fill", x * self.size, y * self.size, self.size, self.size)
love.graphics.print(
string.format("(%d,%d)", x + 1, y + 1),
x * self.size + self.size,
y * self.size + math.floor(self.size / 2), 0, 2,
2)
end
return mouse
游戏循环 main.lua
引入我们写的模块
local tilemap = require 'tilemap'
local map = tilemap.map
local tileset = tilemap.tileset
local mouse = require 'mouse'
require 'debugger'
原图块像素只有 16px,游戏画面需要放大几倍,如果按默认过滤模式,会出现“流血现象”(下图所示),全部改成nearest,单纯的像素放大。love 引擎加载时候加载了图块集与地图。

love.load = function()
love.graphics.setDefaultFilter("nearest", "nearest")
tileset:load()
map:load()
player = love.graphics.newImage("assets/player.png")
end
更新鼠标位置
love.update = function(t)
mouse:update(t)
end
先保存原视角状态,修改视角整体放大两倍,绘制地图,之后还原视角,再画玩家(32*32)跟鼠标。
love.draw = function()
love.graphics.push()
love.graphics.scale(2)
map:draw()
love.graphics.pop()
love.graphics.draw(player, 16 * 16, 192)
mouse:draw()
end
自己创建 TSX、TMX
用的一款工具 Tiled Map Editor by Thorbjørn (itch.io)

完整代码 tilemap.lua
local xml2lua = require 'xml2lua'
local handler = require 'xmlhandler.tree'
local ftcsv = require 'ftcsv'
local parser = xml2lua.parser(handler)
local map = {}
local tileset = {}
function map:load(...)
map:loadTMX(love.filesystem.getWorkingDirectory() .. "/map/map.tmx")
end
function tileset:load(...)
tileset:loadTSX(love.filesystem.getWorkingDirectory() .. "/map/tilemap_packed.tsx")
tileset:loadTile()
end
function map:draw()
for _, layer in ipairs(map) do
for i = 1, map.height, 1 do
for k = 1, map.width, 1 do
if layer[i][k] ~= "0" then
love.graphics.draw(
tileset.image,
tileset[tonumber(layer[i][k])],
tileset.tilewidth * (k - 1),
tileset.tileheight * (i - 1)
)
end
end
end
end
end
function openFile(filename)
local f = io.open(filename, 'r')
if f then
return f
else
error("no file exists", 2)
end
end
function map:loadTMX(filename)
local f = openFile(filename)
local tmx = f:read('a')
parser:parse(tmx)
local attr = handler.root.map._attr
map.width = tonumber(attr.width)
map.height = tonumber(attr.height)
for _, value in pairs(handler.root.map.layer) do
map[#map + 1] = ftcsv.parse(value.data[1] .. ',', ",", { headers = false, loadFromString = true })
end
end
function tileset:loadTSX(filename)
local f = openFile(filename)
local tsx = f:read('a')
parser:parse(tsx)
local attr = handler.root.tileset._attr
local image = handler.root.tileset.image._attr
tileset.tilewidth = tonumber(attr.tilewidth)
tileset.tileheight = tonumber(attr.tileheight)
tileset.tilecount = tonumber(attr.tilecount)
tileset.columns = tonumber(attr.columns)
tileset.rows = tileset.tilecount / tileset.columns
tileset.source = image.source
tileset.width = tonumber(image.width)
tileset.width = tonumber(image.height)
end
function tileset:loadTile()
self.source = string.gsub(self.source, "%.%.", "")
self.image = love.graphics.newImage(self.source)
for i = 0, tileset.rows - 1, 1 do
for j = 0, tileset.columns - 1, 1 do
tileset[#tileset + 1] = love.graphics.newQuad(
j * tileset.tilewidth, i * tileset.tileheight,
tileset.tilewidth, tileset.tileheight, self.image
)
end
end
end
return {
map = map,
tileset = tileset
}
完整代码 main.lua
local tilemap = require 'tilemap'
local map = tilemap.map
local tileset = tilemap.tileset
local mouse = require 'mouse'
require 'debugger'
love.load = function()
love.graphics.setDefaultFilter("nearest", "nearest")
tileset:load()
map:load()
player = love.graphics.newImage("assets/player.png")
end
love.update = function(t)
mouse:update(t)
end
love.draw = function()
love.graphics.push()
love.graphics.scale(2)
map:draw()
love.graphics.pop()
love.graphics.draw(player, 16 * 16, 192)
mouse:draw()
end
完整项目
https://linxiaoxu.oss-cn-hangzhou.aliyuncs.com/static/files/2023/tinytown.zip
[Lua][Love] "图块集与地图" 加载显示功能 TileMap的更多相关文章
- Echarts使用及动态加载图表数据 折线图X轴数据动态加载
Echarts简介 echarts,缩写来自Enterprise Charts,商业级数据图表,一个纯JavaScript的图表库,来自百度...我想应该够简洁了 使用Echarts 目前,就官网的文 ...
- Java中静态变量、静态代码块、非静态代码块以及静态方法的加载顺序
在研究单例设计模式的时候,用到了静态变量和静态方法的内容,出于兴趣,这里简单了解一下这四个模块在类初始化的时候的加载顺序. 经过研究发现,它们的加载顺序为: 1.非静态代码块 2.静态变量或者静态代码 ...
- Tiled Editor 图块的两种导入方式
一.图块集图块的导入. 打开或者创建地图后,新建 新图块. 弹出新图块面板 图块类型选择 "基于图块集图块",一定要选择"嵌入地图",否则需要另存为其他类型的文 ...
- CAD数据分块,偏移校准,加载到百度地图、高德地图、谷歌等地图上
前面分享过一篇如何将CAD海量数据显示在百度地图上(百度地图Canvas实现十万CAD数据秒级加载),但是很多开发者在CAD数据提取时遇到了问题,所以接下来的文章将介绍如何将CAD数据提取. 准备软件 ...
- lua加载函数require和dofile
lua加载函数require和dofile Lua提供高级的require函数来加载运行库.粗略的说require和dofile完成同样的功能但有两点不同: 1. require会搜索目录加载文件; ...
- OpenGL(二十二) gluBuild2DMipmaps 加载Mip纹理贴图
当纹理被用于渲染一个面积比它本身小很多的对象时,会由于纹理图像的降采样率不足而导致混叠现象,主要的表现特征是纹理图像的闪烁,出现纹理躁动.特别是在场景远近移动变换时,这种闪烁情况更为明显,严重可能会影 ...
- lua加载动态库缺乏相应的系统库
错误信息: 使用lua测试lm2动态库时,加载时出现如下错误 jfyuan@jfy11-B85M-D2V:~/temp/service/soft/code/ginger_resty/cores/lm2 ...
- (转载)arcgis for js - 解决加载天地图和WMTS服务,WMTS服务不显示的问题,以及wmts服务密钥。
1 arcgis加载天地图和wmts服务 arcgis for js加载天地图的例子网上有很多,这里先不写了,后期有空再贴代码,这里主要分析下WMTS服务为什么不显示,怎么解决. 条件:这里的WMTS ...
- PIE SDK加载WMS服务数据
1. 功能简介 WMS服务,WMS是OGC标准中比较简单也是比较重要的标准之一.它全称是“Web Map Service”(网络地图服务):利用具有地理空间位置信息的数据制作地图.其中将地图定义为 ...
- Web前台直接加载GIS格式数据分析
本文以Flex直接加载Shp.DWG和MDB为例. 首先看一份现估测数据: 1) 加载Shp文件,目前直接由前台Flex代码完成: 图1 在ArcCatalog里面的Shp文件 图2 直接在前台加载 ...
随机推荐
- vue全家桶进阶之路33:Vue3 计算属性computed
在Vue3中,计算属性可以使用computed函数来定义. computed函数接受两个参数:第一个参数是一个函数,该函数返回计算属性的值:第二个参数是一个可选的配置对象,可以包含getter和set ...
- ERRORS: app1.Book.photo: (fields.E210) Cannot use ImageField because Pillow is not installed.
报错: (env) E:\pyAPP\mybook>python manage.py makemigrations SystemCheckError: System check identifi ...
- .Net使用第三方onnx或ModelBuilder轻松接入AI模型
ML.Net - 开源的跨平台机器学习框架 支持CPU/GPU训练 轻松简洁的预测代码 可扩展其他的机器学习平台 跨平台 1.使用Visual Studio的Model Builder训练和使用模型 ...
- Python基础 - 运算符优先级
以下表格列出了从最高到最低优先级的所有运算符: 运算符 描述 ** 指数 (最高优先级) ~ + - 按位翻转, 一元加号和减号 (最后两个的方法名为 +@ 和 -@) * / % // 乘,除,取模 ...
- [abc279 G] At Most 2 Colors
G - At Most 2 Colors (atcoder.jp) 重点讲解方法三,因为方法三是蒟蒻都能想出来的方法一和方法二都可以借助方法三的思想推出 方法一 这是最简单的设置状态的方法,\(dp[ ...
- U3DFrameWorkDemo:二、资源管理
代码参考 代码文件参考下述详解的类图,工程参考第零章工程说明 概述 在游戏项目中有很多资产如:预制体,图片,音频,Lua脚本,Shader等等.他们随打包放在用户的硬盘里.在游戏的运行过程中,需要对这 ...
- 完成第一个 Vue3.2 项目后,使用体会
第一次Composition API 在vue3.2中,正式支持了script setup的写法,这样可以大大简化组件的代码量,减少一些重复操作,我认为当你写vue3时,应该把这当作默认写法.在vue ...
- 9.3. Hibernate框架
Hibernate是一个开源的持久层框架,它可以帮助我们将Java对象映射到数据库表中,并实现对象的持久化操作.Hibernate提供了丰富的API,可以方便地进行CRUD(增删改查)操作,而无需手动 ...
- .NET周报 【6月第1期 2023-06-04】
专题 - NanoFramework项目案例 如果有时间,我会在周报中加入一些专题和项目案例的分享,本周就是讨论.NET NanoFramework项目案例的专题,在讨论 NanoFramework ...
- FTL潜规则:调优,才是算法精华
前言 在存储领域中有一个FTL的概念,这是一种Flash的内存管理算法,属于各个厂商的核心机密,每个厂商的处理方式不同,有的处理简单,有的处理复杂. FTL,即Flash Translations l ...