-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlevelEditor.ms
348 lines (317 loc) · 9.36 KB
/
levelEditor.ms
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
clear
print "TILE MAP LEVEL EDITOR"
print
print "This program allows you to create, edit, and save an arrangement of tiles."
print
import "tileUtil"
import "textUtil"
sizeToXY = @tileUtil.sizeToXY
EOL = char(13)
min = function(a,b)
if a < b then return a else return b
end function
getOption = function(optionList)
text.inverse = true
print " "
text.inverse = false
text.column = text.column - 1
optionKeys = []
for opt in optionList
optionKeys.push opt[0]
end for
while true
k = key.get.upper
idx = optionKeys.indexOf(k)
if idx >= 0 then
print optionList[idx] + EOL
return optionList[idx]
end if
end while
end function
inputNumber = function(prompt, default, help="")
text.column = 0
if help then
print char(13)*2
r = text.row + 2
c = text.color
text.color = color.gray
print help
text.row = r
text.column = 0
text.color = c
end if
print prompt + " [" + default + "]: "
c = text.column
s = input
if help then
text.row = r - 2
print " " * 67
text.row = r - 1
text.column = 0
end if
if s == "" then
text.row = text.row + 1
text.column = c
print default + char(13)
return default
end if
return val(s)
end function
editMapParams = function
d = sizeToXY(tiles.tileSetTileSize)
d.x = inputNumber("Tile set tile width ", d.x, "Width of one tile in the tile set image, in pixels.")
d.y = inputNumber("Tile set tile height", d.y, "Height of one tile in the tile set image, in pixels.")
tiles.tileSetTileSize = [d.x, d.y]
d = sizeToXY(tiles.extent)
d.x = inputNumber("Tile map columns ", d.x, "Extent (in X) of your level layout, in tiles.")
d.y = inputNumber("Tile map rows ", d.y, "Extent (in Y) of your level layout, in tiles.")
tiles.extent = [d.x, d.y]
d = sizeToXY(tiles.cellSize)
d.x = inputNumber("Tile map tile width ", d.x, "Size (width) of a tile on screen, in pixels.")
d.y = inputNumber("Tile map tile height", d.y, "Size (height) of a tile on screen, in pixels.")
tiles.cellSize = [d.x, d.y]
d = sizeToXY(tiles.overlap)
d.x = inputNumber("Tile map tile overlap (x)", d.x, "How much (in pixels) tiles should overlap horizontally on screen.")
d.y = inputNumber("Tile map tile overlap (y)", d.y, "How much (in pixels) tiles should overlap vertically on screen.")
tiles.overlap = [d.x, d.y]
tiles.oddRowOffset = inputNumber("Tile map odd row offset", tiles.oddRowOffset, "Normally 0, but set to 0.5 for row-aligned hex map.")
tiles.oddColOffset = inputNumber("Tile map odd col offset", tiles.oddColOffset, "Normally 0, but set to 0.5 for column-aligned hex map.")
end function
createNew = function
while true
globals.tileSetPath = input("Tile set path? ") - ".png" + ".png"
tiles.tileSet = file.loadImage(tileSetPath)
if tiles.tileSet != null then break
print "Unable to load image at " + tileSetPath + EOL
end while
tiles.tileSetTileSize = 64
tiles.cellSize = 64
tiles.extent = [gfx.width / tiles.cellSize, gfx.height / tiles.cellSize]
tiles.clear
editMapParams
tiles.clear
globals.layoutFilePath = ""
end function
loadExisting = function
while true
path = findFile
if not path then continue
info = file.info(path)
if not info then
print "Invalid path." + EOL
continue
end if
if info.isDirectory then
print "Invalid path (that's a directory, not a file)." + EOL
continue
end if
globals.layoutFilePath = path
break
end while
tileUtil.loadFromFile layoutFilePath, tiles
if file.name(layoutFilePath) == "stone.dat" then
// HACK: load the level on top, for reference
display(4).mode = displayMode.tile
d = display(4)
tileSetPath = globals.tileSetPath
tileUtil.loadFromFile "level.dat", d
globals.tileSetPath = tileSetPath
d.setCellTint range(0, d.extent[0]), range(0, d.extent[1]), "#FFFFFF88"
end if
end function
saveToFile = function
text.column = 0
if layoutFilePath == "" then
globals.layoutFilePath = input("Save layout to path: ")
if layoutFilePath == "" then return
end if
tileUtil.saveToFile layoutFilePath, tiles
print "Saved data to " + layoutFilePath + EOL
print "(Press any key to continue.)"
k = key.get
text.clear
if k == "q" or k == char(27) then exit
end function
selectBrush = function(index)
count = tileSetRows * tileSetCols
if index < 0 then index = index + count
if index >= count then index = index - count
globals.brush = index
end function
pickBrushDialog = function
img = tiles.tileSet
scale = min(512/img.width, 512/img.height)
destw = img.width * scale
desth = img.height * scale
left = 480 - destw/2
right = 480 + destw/2
bottom = 320 - desth/2
top = 320 + desth/2
gfx.fillRect left-10, bottom-10, destw+20, desth+40, color.gray
gfx.drawImage img, left, bottom, destw, desth
cellSize = sizeToXY(tiles.tileSetTileSize)
for x in range(left, right+1, cellSize.x * scale)
gfx.line x, top, x, bottom, color.white
end for
for y in range(bottom, top+1, cellSize.y * scale)
gfx.line left, y, right, y, color.white
end for
gfx.print "SELECT BRUSH TILE", 400, top + 6, color.black, "small"
while true
if not mouse.button or mouse.x < left or mouse.x > right or
mouse.y < bottom or mouse.y > top then continue
col = floor((mouse.x - left) / (cellSize.x * scale))
row = floor((top - mouse.y) / (cellSize.y * scale))
columns = floor(img.width / cellSize.x)
globals.brush = row * columns + col
break
end while
gfx.fillRect left-10, bottom-10, destw+20, desth+40, color.clear
while mouse.button; end while
end function
showCursorInfo = function(col, row)
text.row = 0
text.column = 0
print "Pixel: " + mouse.x + ", " + mouse.y + " "
text.column = 19
print "Tile: " + col + ", " + row + " "
text.column = 33
val = tiles.cell(col, row)
if val == null then val = "null"
print "Cell value: " + val + " "
text.column = 52
print "Brush: " + brush
for i in range(text.column, 67)
text.setCell i, 0, " "
end for
end function
showHelp = function
lines = []
lines.push " click - Paint/Erase "
lines.push " arrows - Change Brush "
lines.push " click bar - Pick Brush "
lines.push " S - Save "
lines.push " E - Edit Parameters "
lines.push " Esc - Exit "
lines.push " "
lines.push " Push mouse against edge"
lines.push " of screen to scroll. "
d = textUtil.Dialog.make("Level Editor Help", lines.join(char(13)))
d.show
end function
checkKeys = function
if not key.available then return
k = key.get.upper
if k == char(17) then // left arrow
selectBrush brush - 1
else if k == char(18) then // right arrow
selectBrush brush + 1
else if k == char(19) then // up arrow
selectBrush brush - tileSetCols
else if k == char(20) then // down arrow
selectBrush brush + tileSetCols
else if k == "S" then // Save
gfx.fillRect 0, 32, gfx.width, gfx.height-32, "#000000DD"
text.row = 20
saveToFile
gfx.fillRect 0, 32, gfx.width, gfx.height-32, color.clear
else if k == "E" then // Edit Parameters
gfx.fillRect 0, 32, gfx.width, gfx.height-32, "#000000DD"
text.row = 20
editMapParams
text.clear
gfx.fillRect 0, 32, gfx.width, gfx.height-32, color.clear
else
showHelp
end if
end function
scroll = function(dx, dy)
sx = tiles.scrollX + 10 * dx
if sx < 0 then sx = 0
if sx > tiles.extent[0] * tiles.cellSize[0] - 960 then
sx = tiles.extent[0] * tiles.cellSize[0] - 960
end if
sy = tiles.scrollY + 10 * dy
if sy < 0 then sy = 0
if sy > tiles.extent[1] * tiles.cellSize[1] - 640 then
sy = tiles.extent[1] * tiles.cellSize[1] - 640
end if
tiles.scrollX = sx
tiles.scrollY = sy
if display(4).mode == displayMode.tile then
display(4).scrollX = sx
display(4).scrollY = sy
end if
end function
mouseScroll = function
if mouse.x < 1 then scroll -1, 0
if mouse.x > gfx.width-2 then scroll 1, 0
if mouse.y < 1 then scroll 0, -1
if mouse.y > gfx.height-2 then scroll 0, 1
end function
brush = 0
handleClickInBottomBar = function
while mouse.button; end while
pickBrushDialog
end function
// Main edit loop: paint the map with the mouse!
editLoop = function
cellSize = sizeToXY(tiles.cellSize)
overlap = sizeToXY(tiles.overlap)
grid = {"x":cellSize.x + overlap.x, "y":cellSize.y + overlap.y}
mouseWasDown = false
while not key.pressed("escape") and not key.pressed("q")
checkKeys
row = floor((mouse.y + tiles.scrollY) / grid.y)
col = floor((mouse.x + tiles.scrollX) / grid.x)
if mouse.button then
if not mouseWasDown then
if mouse.y < 32 then
handleClickInBottomBar
continue
end if
erasing = (tiles.cell(col,row) == brush)
end if
if erasing then
tiles.setCell col, row, null
else
tiles.setCell col, row, brush
end if
mouseWasDown = true
else
mouseWasDown = false
if mouse.button(1) then
// right-click: set brush to current tile
selectBrush tiles.cell(col, row)
end if
end if
showCursorInfo col, row
mouseScroll
yield
end while
end function
display(6).mode = displayMode.tile
tiles = display(6)
tiles.clear
tiles.scrollX = 0
tiles.scrollY = 0
tiles.oddRowOffset = 0
tiles.oddColOffset = 0
display(5).mode = displayMode.pixel
gfx = display(5)
gfx.clear color.clear
gfx.fillRect 0, 0, gfx.width, 32, "#00000088"
text.delimiter = ""
_printMark "`N`ew layout, or `L`oad existing layout? "
if getOption(["New", "Load"]) == "New" then
createNew
else
loadExisting
end if
tileSetTileSize = sizeToXY(tiles.tileSetTileSize)
tileSetRows = floor(tiles.tileSet.height / tileSetTileSize.y)
tileSetCols = floor(tiles.tileSet.width / tileSetTileSize.x)
text.clear
editLoop
key.clear
text.delimiter = EOL