diff --git a/entities.lua b/entities.lua index ab417d7..7c1fca6 100644 --- a/entities.lua +++ b/entities.lua @@ -56,8 +56,8 @@ function entities.server.update(dt) if choice ~= 'none' then local x = (cx*entities.chunkSize + math.random()*entities.chunkSize)*15 local y = (cy*entities.chunkSize + math.random()*entities.chunkSize)*15 - -- if not in spawn area - if not (x^2 + y^2 < 192^2) then + -- if not in spawn area or wall + if x^2 + y^2 > 192^2 and serverRealm.world:getTile(x, y) ~= tile2id['wall'] then entities.server.defs[choice]:new{x=x, y=y}:spawn() end end @@ -67,7 +67,7 @@ function entities.server.update(dt) local x = (cx*entities.chunkSize + math.random()*entities.chunkSize)*15 local y = (cy*entities.chunkSize + math.random()*entities.chunkSize)*15 -- if on grass - if serverRealm.world:getTile(x, y) == 1 then + if serverRealm.world:getTile(x, y) == tile2id['grass'] then entities.server.defs.tree:new{x=x, y=y}:spawn() end end @@ -76,7 +76,7 @@ function entities.server.update(dt) for j=1, entities.chunkSize do local x = (cx*entities.chunkSize + (i-1))*15 local y = (cy*entities.chunkSize + (j-1))*15 - if serverRealm.world:getTile(x, y) == 8 then + if serverRealm.world:getTile(x, y) == tile2id['wall'] then entities.server.defs.wall:new{x=x, y=y}:spawn() end end diff --git a/entityDefs/player.lua b/entityDefs/player.lua index 963c994..5048a86 100644 --- a/entityDefs/player.lua +++ b/entityDefs/player.lua @@ -92,8 +92,8 @@ for _, sc in ipairs{'server', 'client'} do dd = math.sqrt(dx^2 + dy^2) local spd = self.spd*(self.inputState.keyboard.lshift and 2.5 or 1) local tile = self.realm.world:getTile(self.x, self.y) - if tile == 5 or tile == 6 then spd = spd * 1.5 end -- platform, path - if tile == 4 then spd = spd / 2 end -- water + if tile == tile2id['platform'] or tile == tile2id['path'] then spd = spd * 1.5 end + if tile == tile2id['water'] then spd = spd / 2 end local attackItem = self.items.getItem(self.inventory.items[2]) if dd ~= 0 then self.body:applyForce(dx/dd*spd, dy/dd*spd) @@ -284,7 +284,7 @@ function player.client:draw() -- offset if on platform or path local tile = clientRealm.world:getTile(self.x, self.y) - if tile == 5 or tile == 6 then + if tile == tile2id['platform'] or tile == tile2id['path'] then love.graphics.translate(0, -2) end @@ -305,7 +305,7 @@ function player.client:draw() love.graphics.clear() -- offset/clip feet if in water - if tile == 4 then + if tile == tile2id['water'] then love.graphics.translate(0, 4) love.graphics.stencil(function() love.graphics.rectangle('fill', self.x - 50, self.y - 4, 100, 100) diff --git a/gfx/tiles/all_tiles.png b/gfx/tiles/all_tiles.png new file mode 100644 index 0000000..eb884eb Binary files /dev/null and b/gfx/tiles/all_tiles.png differ diff --git a/gfx/tiles/platformSheet.png b/gfx/tiles/platformSheet.png deleted file mode 100644 index 039e427..0000000 Binary files a/gfx/tiles/platformSheet.png and /dev/null differ diff --git a/gfx/tiles/smooth_tiles.png b/gfx/tiles/smooth_tiles.png new file mode 100644 index 0000000..9d13203 Binary files /dev/null and b/gfx/tiles/smooth_tiles.png differ diff --git a/gfx/tiles/tilesheet1.png b/gfx/tiles/tilesheet1.png deleted file mode 100644 index dc9c307..0000000 Binary files a/gfx/tiles/tilesheet1.png and /dev/null differ diff --git a/gfx/tiles/tilesheet2.png b/gfx/tiles/tilesheet2.png deleted file mode 100644 index e921326..0000000 Binary files a/gfx/tiles/tilesheet2.png and /dev/null differ diff --git a/gfx/tiles/tilesheet2_round.png b/gfx/tiles/tilesheet2_round.png new file mode 100644 index 0000000..214b4c8 Binary files /dev/null and b/gfx/tiles/tilesheet2_round.png differ diff --git a/loadassets.lua b/loadassets.lua index 9295e37..cd909ee 100644 --- a/loadassets.lua +++ b/loadassets.lua @@ -48,9 +48,8 @@ gfx = { } }, tiles = { - tileSheet1 = love.graphics.newImage('gfx/tiles/tilesheet1.png'), - platformSheet = love.graphics.newImage('gfx/tiles/platformSheet.png'), - tileSheet2 = love.graphics.newImage('gfx/tiles/tilesheet2.png') + allTiles = love.graphics.newImage('gfx/tiles/all_tiles.png'), + smoothTiles = love.graphics.newImage('gfx/tiles/smooth_tiles.png') }, environment = { tree = love.graphics.newImage('gfx/environment/tree.png'), @@ -193,14 +192,18 @@ function newTileSheet(sheet, w, h, pad, num, names) local x = (i-1)*(w + pad*2) + 1 local y = 1 local sw, sh = sheet:getDimensions() - t.quads[names[i] or i] = love.graphics.newQuad(x, y, w, h, sw, sh) + local quad = love.graphics.newQuad(x, y, w, h, sw, sh) + t.quads[i] = quad + if names[i] then + t.quads[names[i]] = quad + end end return t end -tileSheets.ts1 = newTileSheet(gfx.tiles.tileSheet1, 15, 15, 1, 4, {'grass', 'sand', 'rock', 'water'}) -tileSheets.platform = newTileSheet(gfx.tiles.platformSheet, 15, 15, 1, 2) -tileSheets.ts2 = newTileSheet(gfx.tiles.tileSheet2, 15, 15, 1, 3, {'path', 'floor', 'wall'}) +tileSheets.allTiles = newTileSheet(gfx.tiles.allTiles, 15, 15, 1, 9, + {'water', 'sand', 'grass', 'rock', 'path', 'floor', 'wall', 'platform', 'platform2'}) +tileSheets.smoothTiles = newTileSheet(gfx.tiles.smoothTiles, 15, 15, 1, 16) fonts = { f10 = love.graphics.newFont(10), @@ -233,33 +236,23 @@ love.graphics.clear(0, 0, 0) love.graphics.setCanvas() -- black tile table.insert(tileImgs, love.graphics.newImage(tileCanv:newImageData())) -for _, v in ipairs{'grass', 'sand', 'rock', 'water'} do +for i=1, 9 do love.graphics.setCanvas(tileCanv) love.graphics.clear() - love.graphics.draw(tileSheets.ts1.sheet, tileSheets.ts1.quads[v], 0, 0) + love.graphics.draw(tileSheets.allTiles.sheet, tileSheets.allTiles.quads[i], 0, 0) love.graphics.setCanvas() table.insert(tileImgs, love.graphics.newImage(tileCanv:newImageData())) end shaders.mapRender:send('tiles', unpack(tileImgs)) -local platformFrames = {} -for _, quad in ipairs(tileSheets.platform.quads) do +smoothTileImgs = {} +for i=1, 16 do love.graphics.setCanvas(tileCanv) love.graphics.clear() - love.graphics.draw(tileSheets.platform.sheet, quad, 0, 0) + love.graphics.draw(tileSheets.smoothTiles.sheet, tileSheets.smoothTiles.quads[i], 0, 0) love.graphics.setCanvas() - table.insert(platformFrames, love.graphics.newImage(tileCanv:newImageData())) + table.insert(smoothTileImgs, love.graphics.newImage(tileCanv:newImageData())) end -shaders.mapRender:send('platformFrames', unpack(platformFrames)) - -local tileImgs2 = {} -for _, v in ipairs{'path', 'floor', 'wall'} do - love.graphics.setCanvas(tileCanv) - love.graphics.clear() - love.graphics.draw(tileSheets.ts2.sheet, tileSheets.ts2.quads[v], 0, 0) - love.graphics.setCanvas() - table.insert(tileImgs2, love.graphics.newImage(tileCanv:newImageData())) -end -shaders.mapRender:send('tiles2', unpack(tileImgs2)) +shaders.mapRender:send('smoothTiles', unpack(smoothTileImgs)) shaders.lifemana:send('lifemanaEmpty', gfx.hud.lifemanaEmpty) diff --git a/main.lua b/main.lua index 4fe84a7..e477f8f 100644 --- a/main.lua +++ b/main.lua @@ -32,6 +32,10 @@ require 'chat' -- todo: better sword check isSword = {['sword0']=true, ['sword1']=true, ['sword2']=true, ['sword3']=true, ['sword4']=true} +tile2id = {} +for i, v in ipairs{'water', 'sand', 'grass', 'rock', 'path', 'floor', 'wall', 'platform', 'platform2'} do + tile2id[v] = i +end function love.load() camera = Camera{ssx=gsx, ssy=gsy} @@ -106,6 +110,8 @@ function love.update(dt) manual_gc(1e-3, 64) prof.pop('update gc') prof.pop('update') + + shaders.mapRender:send('drawDebug', drawDebug) end function love.mousepressed(x, y, btn, isTouch, presses) diff --git a/shaders/mapGen.glsl b/shaders/mapGen.glsl index 5fa6816..2c30eba 100644 --- a/shaders/mapGen.glsl +++ b/shaders/mapGen.glsl @@ -82,14 +82,16 @@ float snoise(vec2 v) } +// 1: water, 2: sand, 3: grass, 4: rock, 5: path, 6: floor, 7: wall, 8: platform + vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) { vec2 uv = screen_coords; uv += camPos; vec2 p = floor(uv); - // grass/sand/rock/water - int tileChoices[3] = int[](1, 2, 4); + // grass/sand/water + int tileChoices[3] = int[](3, 2, 1); float r1 = snoise(p/32.0)*0.5 + 0.5; int choice = 0; for (int i=0; i < 3; i++) { @@ -98,9 +100,10 @@ vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) break; } } + // rock float r2 = snoise(1000.0 + p/64.0)*0.5 + 0.5; if (r1 < 0.2 && r2 < 0.5) { - choice = 3; + choice = 4; } // buildings @@ -109,16 +112,18 @@ vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) vec4 vpts = voronoi(vp, 0.5); vec2 vd = vec2(floor(abs(vp.x - vpts.x)*freq), floor(abs(vp.y - vpts.y)*freq)); // inside + // floor if (vd.x <= 4.0 && vd.y <= 6.0) { - choice = 7; + choice = 6; } + // path if (distance(vp, vpts.xy)*freq < 2.0) { - choice = 6; + choice = 5; } // walls if ((vd.x == 4.0 && vd.y <= 6.0 || vd.y == 6.0 && vd.x <= 4.0) && vd.x > 1.0 && vd.y > 1.0) { - choice = 8; + choice = 7; } // paths @@ -126,14 +131,22 @@ vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) float angle = atan(p.y, p.x); angle += snoise(2000.0 + p/64.0)/d*4.0; if (distance(mod(angle/(2.0*M_PI)*8.0, 1.0), 0.5) < 0.3/(d/8.0)) { - choice = 6; + choice = 5; } // platform if (length(p) < 8.0) { - choice = 5; + choice = 8; } + // test + if (p == vec2(0.0) || p == vec2(1.0, 0.0) || p == vec2(0.0, 1.0) || p == vec2(1.0, 2.0)) { + choice = 5; + } + if (p == vec2(0.0)+vec2(18.0, 0.0) || p == vec2(1.0, 0.0)+vec2(18.0, 0.0) || p == vec2(0.0, 1.0)+vec2(18.0, 0.0) || p == vec2(1.0, 2.0)+vec2(18.0, 0.0)) { + choice = 5; + } + return vec4(choice/255.0, 0.0, 0.0, 1.0); } diff --git a/shaders/mapRender.glsl b/shaders/mapRender.glsl index 76c24ab..ed7f9ed 100644 --- a/shaders/mapRender.glsl +++ b/shaders/mapRender.glsl @@ -3,13 +3,21 @@ uniform vec2 tileIdRes; uniform vec2 camPos; uniform vec2 tilemapPos; uniform Image tileIds; -uniform Image tiles[5]; -uniform Image platformFrames[2]; -uniform Image tiles2[3]; +uniform Image tiles[10]; +uniform Image smoothTiles[16]; uniform float time; +uniform bool drawDebug; float tileSize = 15.0; +float min3(vec3 v) { + return min(min(v.x, v.y), v.z); +} + +float max3(vec3 v) { + return max(max(v.x, v.y), v.z); +} + vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) { vec2 uv = screen_coords; @@ -18,13 +26,12 @@ vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) vec2 tilePos = floor(uv/tileSize); //vec2 tilemapPos = floor(camPos/tileSize) - 2.0; // imprecision errors if calculated in shader? vec2 tileIdPos = tilePos - tilemapPos; - vec4 tileIdColor = Texel(tileIds, tileIdPos/(tileIdRes + vec2(1.0))); - int centerId = int(tileIdColor.r*255.0); vec4 topLeftIdColor = Texel(tileIds, (tileIdPos + vec2(-1.0, -1.0))/(tileIdRes + vec2(1.0))); vec4 topIdColor = Texel(tileIds, (tileIdPos + vec2(0.0, -1.0))/(tileIdRes + vec2(1.0))); vec4 topRightIdColor = Texel(tileIds, (tileIdPos + vec2(1.0, -1.0))/(tileIdRes + vec2(1.0))); vec4 leftIdColor = Texel(tileIds, (tileIdPos + vec2(-1.0, 0.0))/(tileIdRes + vec2(1.0))); + vec4 centerIdColor = Texel(tileIds, tileIdPos/(tileIdRes + vec2(1.0))); vec4 rightIdColor = Texel(tileIds, (tileIdPos + vec2(1.0, 0.0))/(tileIdRes + vec2(1.0))); vec4 bottomLeftIdColor = Texel(tileIds, (tileIdPos + vec2(-1.0, 1.0))/(tileIdRes + vec2(1.0))); vec4 bottomIdColor = Texel(tileIds, (tileIdPos + vec2(0.0, 1.0))/(tileIdRes + vec2(1.0))); @@ -34,54 +41,91 @@ vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) int topId = int(topIdColor.r*255.0); int topRightId = int(topRightIdColor.r*255.0); int leftId = int(leftIdColor.r*255.0); + int centerId = int(centerIdColor.r*255.0); int rightId = int(rightIdColor.r*255.0); int bottomLeftId = int(bottomLeftIdColor.r*255.0); int bottomId = int(bottomIdColor.r*255.0); int bottomRightId = int(bottomRightIdColor.r*255.0); - if (centerId < 5) { - vec4 c1 = Texel(tiles[centerId], tileUV)*color; - if (tileUV.x < 0.5) { - if (tileUV.y < 0.5) { - if (topId != centerId && leftId != centerId - && topLeftId != centerId && topLeftId < 5) { - vec4 c2 = Texel(tiles[topLeftId], tileUV)*color; - float t = length(1.0 - tileUV*2.0) < 1.0 ? 1.0 : 0.0; - return t > 0.5 ? c1 : c2; - } - } else { - if (bottomId != centerId && leftId != centerId - && bottomLeftId != centerId && bottomLeftId < 5) { - vec4 c2 = Texel(tiles[bottomLeftId], tileUV)*color; - float t = length(1.0 - tileUV*2.0) < 1.0 ? 1.0 : 0.0; - return t > 0.5 ? c1 : c2; - } - } + int outId = centerId; + float t = length(1.0 - tileUV*2.0) < 1.0 ? 1.0 : 0.0; + + // this tile, opposite, side1, side2 + vec4 corner; + if (tileUV.x < 0.5) { + if (tileUV.y < 0.5) { + corner = vec4(centerId, topLeftId, topId, leftId); } else { - if (tileUV.y < 0.5) { - if (topId != centerId && rightId != centerId - && topRightId != centerId && topRightId < 5) { - vec4 c2 = Texel(tiles[topRightId], tileUV)*color; - float t = length(1.0 - tileUV*2.0) < 1.0 ? 1.0 : 0.0; - return t > 0.5 ? c1 : c2; - } - } else { - if (bottomId != centerId && rightId != centerId - && bottomRightId != centerId && bottomRightId < 5) { - vec4 c2 = Texel(tiles[bottomRightId], tileUV)*color; - float t = length(1.0 - tileUV*2.0) < 1.0 ? 1.0 : 0.0; - return t > 0.5 ? c1 : c2; - } + corner = vec4(centerId, bottomLeftId, bottomId, leftId); + } + } else { + if (tileUV.y < 0.5) { + corner = vec4(centerId, topRightId, topId, rightId); + } else { + corner = vec4(centerId, bottomRightId, bottomId, rightId); + } + } + + vec3 debugColor = vec3(0.0); + + float maxNeighbors = max3(corner.yzw); + float minNeighbors = min3(corner.yzw); + bool clipped = false; + if (corner.x > maxNeighbors) { + outId = int(t > 0.5 ? corner.x : maxNeighbors); + debugColor.r = 1.0; + clipped = true; + } + if (minNeighbors > corner.x) { + outId = int(t > 0.5 ? corner.x : minNeighbors); + debugColor.g = 1.0; + clipped = true; + } + if (minNeighbors != corner.x && minNeighbors == corner.z && minNeighbors == corner.w) { + outId = int(t > 0.5 ? corner.x : minNeighbors); + debugColor.b = 1.0; + clipped = true; + } + + int smoothId = 0; + if (outId == 5 || outId == 6 || outId == 8) { // smooth path, floor, platform + if (corner.x == corner.y && corner.x == corner.z && corner.x == corner.w + || (corner.x == corner.z || corner.x == corner.w) && corner.z != corner.w && corner.x != corner.y) { + smoothId = 0; + if (corner.x < maxNeighbors && (corner.x != corner.z || corner.x != corner.w) && corner.y != corner.z && corner.y != corner.w) { + smoothId = 3; + } + } else if (corner.x == corner.z && corner.z == corner.w + || corner.x == corner.y && corner.z != corner.w && (corner.x == corner.z || corner.x == corner.w)) { + smoothId = 3; + } else if (corner.x != corner.y && corner.x != corner.z && corner.x != corner.w) { + smoothId = 2; + if (corner.x < maxNeighbors && (corner.y != corner.z && corner.y != corner.w || (corner.y == corner.z || corner.y == corner.w))) { + smoothId = 3; } + } else { + smoothId = 3; + } + if (int(corner.x) != outId) { + smoothId = 1; + } else if (clipped) { + smoothId = 2; } } - if (centerId == 5) { + if (drawDebug) { + return vec4(debugColor, 1.0); + } + + + if (outId == 5) { // path + return Texel(smoothTiles[0 + smoothId], tileUV)*color; + } else if (outId == 6) { // floor + return Texel(smoothTiles[4 + smoothId], tileUV)*color; + } else if (outId == 8) { // platform int frame = int(mod(floor(time - length(tilePos)/4.0), 2.0)); - return Texel(platformFrames[frame], tileUV)*color; - } else if (centerId > 5) { - return Texel(tiles2[centerId - 6], tileUV)*color; + return Texel(smoothTiles[8 + frame*4 + smoothId], tileUV)*color; } else { - return Texel(tiles[centerId], tileUV)*color; + return Texel(tiles[outId], tileUV)*color; } } diff --git a/world.lua b/world.lua index 598d6f6..3c5d139 100644 --- a/world.lua +++ b/world.lua @@ -22,14 +22,15 @@ for _, sc in ipairs{'server', 'client'} do t.chunkImages = {} t.chunkIdImages = {} t.tileColors = { - {98, 195, 116}, - {251, 228, 125}, - {98, 98, 98}, - {41, 137, 214}, - {73, 73, 73}, - {205, 140, 79}, - {183, 163, 43}, - {104, 88, 0} + {41, 137, 214}, -- water + {251, 228, 125}, -- sand + {98, 195, 116}, -- grass + {98, 98, 98}, -- rock + {205, 140, 79}, -- path + {183, 163, 43}, -- floor + {104, 88, 0}, -- wall + {73, 73, 73}, -- platform + {73, 73, 73} -- platform } for _, color in ipairs(t.tileColors) do for i=1, 3 do