您的位置:首页 > 其它

love2d教程4--材质和贴图

2012-12-11 11:59 441 查看
”说明,在love2d的wiki上以下的这些操作都比较费时,建议不要在draw和update里重复加载同样的数据,
而是创建以后保存以重复使用。”

材质可以简单的说是一些图片素材,love2d可以从文件和ImageData(可以看作内存中的图像数据)
载入图片image=love.graphics.newImage(path或imagedata),返回一个Image对象(可以被画在屏幕上)
说明只能从main.lua所在文件夹为相对路径,载入图片,不能使用外面的图片。
显示图片使用love.graphics.draw(image, x, y),x、y为显示在屏幕上的坐标(说明draw其它参数下面
有解释)。

说明在有些较老的显卡上只支持显示为2的整数幂分辨率的图片,下面这段代码可以把图片修改
为2的整数幂,不过最新的0.8已经不需要了。

--修改图片为2的倍数
function newPaddedImage(filename)
local source = love.image.newImageData(filename)
local w, h = source:getWidth(), source:getHeight()

-- Find closest power-of-two.
local wp = math.pow(2, math.ceil(math.log(w)/math.log(2)))
local hp = math.pow(2, math.ceil(math.log(h)/math.log(2)))

-- Only pad if needed:
if wp ~= w or hp ~= h then
local padded = love.image.newImageData(wp, hp)
padded:paste(source, 0, 0)
return love.graphics.newImage(padded)
end

return love.graphics.newImage(source)
end


下面说一下如何从一副大图片中提取所需的部分。
love2d提供了Quad类型,可以通过quad = love.graphics.newQuad( x, y, width, height, sw, sh )

创建一个quad对象,其中x、y是大图中小图左顶点的坐标,width、height是小图的宽和高,sw、sh是

大图的宽和高。

显示所需的小图使用love.graphics.drawq(image,quad, x, y, r, sx, sy, ox, oy, kx, ky )

其中image是大图(需要在绘图前使用image=love.graphics.newImage(path)创建),quad是我们刚才

创建的quad对象,x、y在屏幕上显示的坐标;(以下的几个参数有默认值,没特殊要求不用)r为逆时针

旋转的度数(弧度制);sx、sy是以原图为中心沿x、y轴方向的缩放系数,可以为负,当x为负时,相当

于左右翻转后再缩放,y为负时即上下颠倒后再缩放;ox、oy即显示的坐标与原x、y坐标分别向左、向下

便宜ox、oy像素;kx、ky wiki上解释为Shearing factor ,不知到什么意思(如果你恰好知道,请告诉我)

,我试了一下发现这种变换会偏离原坐标中心,而且当kx、ky都为1时居然没显示,但为其它值却可以显示。

接着我们学习一下贴图(tile,中文意思为贴瓷砖)。贴图实际是重复利用图片的一种方法,但要求这些图片

可以无缝拼接,即把小图片拼装成大图后没有缝隙。对于小图的管理可以有两种方法,一种是把许多小图片放

到一个大图片中(地图多用),另一种则就是把小图按一定名称和顺序编号,直接存贮(人物图像多用)。

wiki上的Tutorial:Tile-based Scrolling,是采用的第二种方法,我就不重复了,下面我介绍一下第一种方法。

请在网上下载Tiled,最新版本是0.8.1。
(说明最新的是0.9了,你可以直接点链接下载0.8.1的)
1、文件-新建,如下图,把地图大小的宽和高都改为10





2、在视图菜单里把显示网格和对齐网格都勾上,你会看到一副网格





3、地图-新图块





如下图,把边距和间距都设为1(这个间距是根据图片来的,你可以打开tmw_desert_spacing.png,放大后可以看见网格,我

就用1试了一下正好),点击浏览,打开自带的example下的"tmw_desert_spacing.png"图片





4、用鼠标选择右边的图块中的小图,在坐标的网格里便可以绘图了,按住鼠标左键不放拖动,可以连续画。

画错了,在工具栏中有橡皮擦。如下图,标有红色的是我选的几幅小图。





5、打开地图--地图属性,我们为tmw_desert_spacing.png添加五个属性,如下图,即水平和竖直方向图块的个数,

图块的宽和高,图片的格式。





接着 文件-导出为,在弹出的对话框下面的“保存类型”选择"lua文件。

6、把刚导出的lua文件和刚才的tmw_desert_spacing.png图片都复制到love2d工程下,把图片放到assets文件夹里。

下面我们来看看这个lua文件,它只有一行,而且返回了一个table。

你可以手动把它换一下行,或者把notepad++的视图菜单--自动换行勾上。

可以看到有一个data表如下

data =

{

30, 30, 30, 30, 30, 30, 30, 30, 30, 30,

30, 30, 30, 30, 30, 30, 30, 30, 30, 30,

38, 38, 38, 38, 38, 38, 38, 38, 38, 38,

38, 38, 38, 38, 38, 38, 38, 38, 38, 38,

46, 46, 46, 46, 46, 46, 46, 46, 46, 46,

46, 46, 46, 46, 46, 46, 46, 46, 46, 46,

47, 47, 47, 47, 47, 47, 47, 47, 47, 47,

47, 47, 47, 47, 47, 47, 47, 47, 47, 47,

31, 31, 31, 31, 31, 31, 31, 31, 31, 31,

31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }

这不就是我们刚才选择的图块的编号在网格里的顺序吗?

下面我们可以直接把data复制出来,更好的是写一个读取该文件的函数。

其中我感兴趣的有图片路径,可是这个路径在love2d里用不了,但图片

的名字到可以用(在tilesets下的name),还有imagewidth,imageheight,

tilewidth,tileheight,width(图块水平的个数),height(图块竖直的个数)

spacing(水平间隔), margin (竖直间隔)。

再看看tmw_desert_spacing.png,发现是265*199像素,正好水平方向32*8+1*7+1*2,竖直方向32*6+1*5+1*2

(1*2是图片四周的框)。其实我们希望没有这个间隔,这样好计算点。

下面是运行的截图

代码下载http://pan.baidu.com/share/link?shareid=125787&uk=1913510140





以下是代码

main.lua

tilemap=require('tilemap')
require('tutor4')
--地图在屏幕上显示的x,y坐标
mapX,mapY=100,100
quadtable={}

--那些注释是我试验坐标时用的,坐标不易确定啊
function love.load()
image=love.graphics.newImage("assets/" .. tilemap["tilesets"][1].name ..tilemap["properties"]["format"])
makeQuad(tilemap)

--quad1=love.graphics.newQuad(1,1,32,32,265,199)
--quad2=love.graphics.newQuad(34,1,32,32,265,199)
end

function love.draw()
drawMap(tilemap,image)
--love.graphics.drawq(image,quad1,100,100)
--love.graphics.drawq(image,quad2,132,100)
end

function love.update(dt)
--按键检测
if(love.keyboard.isDown("up")) then
mapY=mapY-20
end
if(love.keyboard.isDown("down")) then
mapY=mapY+20
end
if(love.keyboard.isDown("left")) then
mapX=mapX-20
end
if(love.keyboard.isDown("right")) then
mapX=mapX+20
end
--边界检测省略

end

function love.keypressed(key)

end


tutor4.lua ,不好意思代码错了,以下标有红色的是更正的. --2012.12.16

--计算一个长为width的矩阵中第num个数所在的x列,y行
function calcXY(num,width)
local x=num%width
local y=num/width
if(x~=0) then
y=math.ceil(y)
else
   x=width
  end
return x,y
end
--从大图生成quad表
function makeQuad(map)
--大图的高和宽
local imageheight=map["tilesets"][1].imageheight
local imagewidth=map["tilesets"][1].imagewidth
--大图水平和竖直方向图块的数目
local numx=tonumber(map["properties"]["numx"])
local numy=tonumber(map["properties"]["numy"])
--水平及竖直间距
local spacing= map["tilesets"][1].spacing
local margin=map["tilesets"][1].margin
--图块的宽和高
local blockx=tonumber(map["properties"]["blockx"])
local blocky=tonumber(map["properties"]["blocky"])
--水平及竖直方向图块的个数
local width=map["layers"][1].width
local height=map["layers"][1].height
--图块排列表
local array=map["layers"][1].data

--统计不同的图块数目
local j=1
for i=1,#array do
if(array[i]~=array[i-1]) then
local x,y=calcXY(array[i],numx)
--创建一个quad图像参数     需要显示的小图的左顶点在大图中的x,y坐标,每个小图的宽、高,大图的宽、高
quadtable[j]=love.graphics.newQuad((x-1)*blockx+x*spacing,(y-1)*blocky+y*margin,blockx,blocky,imagewidth,imageheight)
j=j+1
end
end
end

--画地图
function drawMap(map,image)
--图块排列表
local array=map["layers"][1].data
--水平方向图块的个数
local width=map["layers"][1].width
--图块的宽和高
local blockx=tonumber(map["properties"]["blockx"])
local blocky=tonumber(map["properties"]["blocky"])

local j=0
for i=1,#array do
local x,y=calcXY(i,width)
if(array[i]~=array[i-1]) then
j=j+1
end
love.graphics.drawq(image,quadtable[j],mapX+(x-1)*blockx,mapY+(y-1)*blocky)
end

end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: