love2d教程4--材質和貼圖


”說明,在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

image

2、在視圖菜單里把顯示網格和對齊網格都勾上,你會看到一副網格

image

3、地圖-新圖塊

image

如下圖,把邊距和間距都設為1(這個間距是根據圖片來的,你可以打開tmw_desert_spacing.png,放大后可以看見網格,我
就用1試了一下正好),點擊瀏覽,打開自帶的example下的"tmw_desert_spacing.png"圖片

image

4、用鼠標選擇右邊的圖塊中的小圖,在坐標的網格里便可以繪圖了,按住鼠標左鍵不放拖動,可以連續畫。
畫錯了,在工具欄中有橡皮擦。如下圖,標有紅色的是我選的幾幅小圖。

image 

5、打開地圖--地圖屬性,我們為tmw_desert_spacing.png添加五個屬性,如下圖,即水平和豎直方向圖塊的個數,
圖塊的寬和高,圖片的格式。

image 

接着 文件-導出為,在彈出的對話框下面的“保存類型”選擇"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

 

image

以下是代碼
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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM