-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmap.lua
More file actions
148 lines (118 loc) · 4.8 KB
/
map.lua
File metadata and controls
148 lines (118 loc) · 4.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
--[[
Filgrim Engine
map.lua
A 2D platformer engine for LÖVE
By Hoover and Phil
]]
-- Globals
Map = {}
-- OO Methods =================================================================
function Map:new(width, height , zIndex, scrollRateX, scrollRateY, data)
-- Constructor
local object = { width = width, height = height, data = data, zIndex = zIndex, scrollRate = { x = scrollRateX, y = scrollRateY }, lastUpdate = {} }
setmetatable(object, { __index = Map } )
return object
end
-- Accessors ==================================================================
function Map:getTileSize()
return self.tileSize
end
function Map:getDimensions()
return self.width, self.height
end
function Map:getDimensionsInPixels()
return self.width * self.tileSize, self.height * self.tileSize
end
function Map:getTile(x, y)
-- Please note that map coordinates are 0 indexed, with the origin at top left.
--if self.debug then print("Getting tile at index "..self.width * y + x + 1 ..", coordinates ("..x..", "..y..")") end
return self.data[self.width * y + x + 1]
end
function Map:getCoordinatesAtPixel(x, y)
x = math.floor(x / self.tileSize)
y = math.floor(y / self.tileSize)
return x, y
end
function Map:getTileAtPixel(x, y)
x, y = self:getCoordinatesAtPixel(x, y)
return self:getTile(x, y)
end
-- Map Methods ================================================================
function Map:loadTiles(tilesetImagePath, tileSize)
-- Loads the tileset from an image and breaks them up into individual quads.
self.tiles = {}
self.tileSize = tileSize
self.tileBatch = nil
-- Load the image file.
self.tiles.tilesetImage = love.graphics.newImage(tilesetImagePath)
assert(self.tiles.tilesetImage, "Could not load tileset: "..tilesetImagePath)
-- This removes artifacts if we scale the image.
self.tiles.tilesetImage:setFilter("nearest", "nearest")
-- Calculate the dimensions of the tile set.
local tileRows = self.tiles.tilesetImage:getHeight() / tileSize
local tileColumns = self.tiles.tilesetImage:getWidth() / tileSize
local tileCount = tileRows * tileColumns
-- Create quads for each tile.
local currentTile = 1
for currentRow = 0, tileRows - 1 do
for currentColumn = 0, tileColumns - 1 do
self.tiles[currentTile] = love.graphics.newQuad(currentColumn * tileSize, currentRow * tileSize, tileSize, tileSize, self.tiles.tilesetImage:getWidth(), self.tiles.tilesetImage:getHeight() )
currentTile = currentTile + 1
end
end
end
function Map:initTileBatch(maxTiles)
if not self.tileBatch then
self.tileBatch = love.graphics.newSpriteBatch(self.tiles.tilesetImage, maxTiles)
end
end
function Map:update(camera)
-- Calculates what tiles to draw on screen. Must be called once for each map per update loop.
-- Pass in the camera you're using to draw.
-- Adjust our drawing position according to our scroll rate.
local cameraX, cameraY = camera:getPosition()
cameraX = cameraX * self.scrollRate.x
cameraY = cameraY * self.scrollRate.y
-- We can optimize our function here by comparing the current camera
-- position to the one that was used the last time we were called.
if cameraX == self.lastUpdate.cameraX and cameraY == self.lastUpdate.cameraY then return end
-- Calculate our viewport dimensions.
local scale = camera:getScale()
local width, height = camera:getDimensions()
local viewportWidth = math.ceil(width / scale / self.tileSize)
local viewportHeight = math.ceil(height / scale / self.tileSize)
-- Next, we need to calculate our origin tile (the tile in the top left of the viewport).
local originX, originY = self:getCoordinatesAtPixel(cameraX, cameraY)
-- We lazily create a SpriteBatch here if one does not already exist.
maxTiles = (viewportWidth + 1) * (viewportHeight + 1)
if self.tileBatch == nil then
self:initTileBatch(maxTiles)
elseif self.lastUpdate.viewportWidth ~= viewportWidth or self.lastUpdate.viewportHeight ~= viewportHeight then
-- If it already exists but the viewport dimensions have changed, recreate the batch.
self.tileBatch = nil
self:initTileBatch(maxTiles)
end
-- Store updated data.
self.lastUpdate.scale = scale
self.lastUpdate.viewportWidth = viewportWidth
self.lastUpdate.viewportHeight = viewportHeight
self.lastUpdate.cameraX = cameraX
self.lastUpdate.cameraY = cameraY
self.lastUpdate.originX = originX
self.lastUpdate.originY = originY
-- Clear the tile batch.
self.tileBatch:clear()
-- Populate the tilebatch using the tiles currently on screen.
for y = 0, viewportHeight do
for x = 0, viewportWidth do
local currentTile = self:getTile(originX + x, originY + y)
if currentTile then
self.tileBatch:addq(self.tiles[currentTile], (x * self.tileSize) - (cameraX % self.tileSize), (y * self.tileSize) - (cameraY % self.tileSize) )
end
end
end
end
function Map:draw(camera)
local x, y = camera:getOriginPosition()
love.graphics.draw(self.tileBatch, x, y)
end