From ec6a391cb9cf0c0feac0fe3615a59cc7cb6db2d5 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Fri, 3 Feb 2023 01:32:09 +0000 Subject: drawing changes, world generation, perlin noise --- client/drawing.lua | 34 +++++++++++++++---- client/main.lua | 14 ++++---- common/chunk.lua | 11 ------- common/coords.lua | 2 ++ server/noise.lua | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ server/server.lua | 17 ++++++++-- 6 files changed, 149 insertions(+), 25 deletions(-) create mode 100644 server/noise.lua diff --git a/client/drawing.lua b/client/drawing.lua index 962fdb7..111b2e2 100644 --- a/client/drawing.lua +++ b/client/drawing.lua @@ -26,8 +26,26 @@ end -- love.graphics.pop() -- end +local function c(...) return {love.math.colorFromBytes(...)} end +-- taken from breadquest +local colors = { + c(255,64,64), -- red + c(255,128,0), -- orange + c(192,192,64), -- yellow + c(0,192,0), -- green + + c(0,192,192), -- teal + c(64,64,255), -- blue + c(192,0,192), -- purple + c(128,128,128), -- grey +} + + + +local zthr0 = 2 +local zthr1 = 5 local _corners = {} -local function draw_hex(cpos,color) +local function draw_hex(cpos,color,zoom) local cx,cy = cpos.x,cpos.y for i=0,5 do local angle = tau*(i+0.5)/6 @@ -36,12 +54,14 @@ local function draw_hex(cpos,color) _corners[2*i+1] = x _corners[2*i+2] = y end - love.graphics.setLineWidth(0.1) -- love.graphics.setColor(love.math.colorFromBytes(0xe7,0x9e,0)) love.graphics.setColor(color or {0.91,0.62,0}) love.graphics.polygon("fill",_corners) - love.graphics.setColor(0,0,0) - love.graphics.polygon("line",_corners) + if zoom > zthr0 then + love.graphics.setLineWidth(0.1) + love.graphics.setColor(0,0,0,zoom>zthr1 and 1 or (zoom-zthr0)/(zthr1-zthr0)) + love.graphics.polygon("line",_corners) + end end local function draw_chunk(camera,the_chunk) @@ -56,8 +76,10 @@ local function draw_chunk(camera,the_chunk) for q = minq,maxq do local h = coords.Hex.make(q,r) local t = the_chunk:at(h) - if t then - draw_hex(h:to_pos()) + if type(t) == "number" then + draw_hex(h:to_pos(),colors[t],camera.zoom) + elseif t then + draw_hex(h:to_pos(),nil,camera.zoom) end end end diff --git a/client/main.lua b/client/main.lua index 6572621..2fad49e 100644 --- a/client/main.lua +++ b/client/main.lua @@ -24,7 +24,7 @@ local host,peer local chunk -local f3mode = true +local f3mode = false function love.keypressed(key,scancode,isrepeat) if scancode == "f3" then f3mode = not f3mode end @@ -58,8 +58,8 @@ local function update_local_player(pl,dt) end if dx ~= 0 and dy ~= 0 then - dx = dx / math.sqrt(2) - dy = dy / math.sqrt(2) + dx = dx * 0.5 + dy = dy * (math.sqrt(3)/2) end pl.pos.x = pl.pos.x + SPEED * dt * dx @@ -91,11 +91,11 @@ function love.update(dt) local mh = camera:screen_to_world(Pos.make(love.mouse.getPosition())):to_hex():round() if false== chunk:at(mh) and love.mouse.isDown(1) then chunk:set_at(mh,true) - print(mh,true) + -- print(mh,true) send_settile(mh,true) elseif chunk:at(mh) and love.mouse.isDown(2) then chunk:set_at(mh,false) - print(mh,false) + -- print(mh,false) send_settile(mh,false) end end @@ -164,7 +164,9 @@ function love.draw() "mh "..tostring(hm).." "..tostring(hm:round()), "-", "pw "..tostring(local_player.pos), - "ph "..tostring(local_player.pos:to_hex()).." "..tostring(local_player.pos:to_hex():round()) + "ph "..tostring(local_player.pos:to_hex()).." "..tostring(local_player.pos:to_hex():round()), + "-", + "voob "..tostring(camera.zoom), },10,10) end end diff --git a/common/chunk.lua b/common/chunk.lua index a9a8bc5..8e2ec40 100644 --- a/common/chunk.lua +++ b/common/chunk.lua @@ -20,17 +20,6 @@ Chunk.__index = Chunk function Chunk.make(tiles) return setmetatable({tiles=tiles},Chunk) end -function Chunk.gen() - -- todo actual worldgen - local tiles = {} - for i=0,CHUNK_SIZE-1 do - for j=0,CHUNK_SIZE-1 do - tiles[index(i,j)] = (math.random()<0.5) - end - end - - return Chunk.make(tiles) -end function Chunk.at(self,hoffs) if not index_ok(hoffs.q,hoffs.r) then return nil end return self.tiles[index(hoffs.q,hoffs.r)] diff --git a/common/coords.lua b/common/coords.lua index 1bb9154..2399e43 100644 --- a/common/coords.lua +++ b/common/coords.lua @@ -76,6 +76,8 @@ function Pos.__div(a,b) end function Pos.lensq(self) return self.x^2 + self.y^2 end function Pos.len(self) return math.sqrt(self:lensq()) end +function Pos.norm(self) return self/self:len() end +function Pos.dot(self,other) return self.x*other.x + self.y*other.y end function Pos.to_hex(self) local q = self.x*(SR3/3) - self.y*(1/3) local r = (2/3)*self.y diff --git a/server/noise.lua b/server/noise.lua new file mode 100644 index 0000000..1480448 --- /dev/null +++ b/server/noise.lua @@ -0,0 +1,96 @@ +local Pos = require"common.coords".Pos +local tau = 2*math.pi + +math.randomseed(os.time()) + +local function random_unit_vec() + local theta = math.random()*tau + return Pos.make(math.cos(theta),math.sin(theta)) +end +local function lerp(a,b,t) return (1-t)*a + t*b end +local function smoothstep(x) + if x<0 then return 0 end + if x>1 then return 1 end + return x*x*(3 - 2*x) +end +local function slerp(a,b,t) return lerp(a,b,smoothstep(t)) end + +local NoiseGen = {} +NoiseGen.__index = NoiseGen +function NoiseGen.make() + local grid = {} + setmetatable(grid,{__index=function(t,k) t[k] = {} return t[k] end}) + return setmetatable({grid=grid},NoiseGen) +end +function NoiseGen.vertex(self,ix,iy) + local v = self.grid[ix][iy] + if v then return v end + vv = random_unit_vec() + self.grid[ix][iy] = vv + return vv +end + +function NoiseGen.at(self,x,y) + local x0 = math.floor(x) + local y0 = math.floor(y) + local x1 = x0 + 1 + local y1 = y0 + 1 + + local v00 = self:vertex(x0,y0) + local v01 = self:vertex(x0,y1) + local v10 = self:vertex(x1,y0) + local v11 = self:vertex(x1,y1) + + local p = Pos.make + local d00 = v00:dot(p(x-x0,y-y0)) + local d01 = v01:dot(p(x-x0,y-y1)) + local d10 = v10:dot(p(x-x1,y-y0)) + local d11 = v11:dot(p(x-x1,y-y1)) + + local q0 = slerp(d00,d01,y-y0) + local q1 = slerp(d10,d11,y-y0) + local z = slerp(q0,q1,x-x0) + return z +end + +local NoiseAgg = {} +NoiseAgg.__index = NoiseAgg +function NoiseAgg.make(things) + return setmetatable({things=things or {}},NoiseAgg) +end +function NoiseAgg.make_perlin_octaves(nocts) + local things = {} + for i=1,nocts do + table.insert(things,{amp=2^i,scale=2^(nocts-i),gen=NoiseGen.make()}) + end + return NoiseAgg.make(things) +end +function NoiseAgg.at(self,x,y) + local n = 0 + local t = 0 + assert(#self.things>0,"can't generate noise with no noise things") + for _,thing in ipairs(self.things) do + local gen,scale,amp = thing.gen,thing.scale,thing.amp + n = n + amp + t = t + gen:at(x*scale,y*scale)*amp + end + return t/n +end + +-- local chars = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^`'. " + +-- local scale = 3 + +-- for x=1,10-10/40,10/40 do +-- for y = 1,10-10/60,10/60 do + +-- local n = at(1+(x-1)/scale,1+(y-1)/scale) +-- local nn = (n +1)/2 +-- local nnn = 1+nn*#chars +-- local c = chars:sub(nnn,nnn) +-- io.write(c) +-- end +-- io.write("\n") +-- end + +return {NoiseGen=NoiseGen,NoiseAgg=NoiseAgg} diff --git a/server/server.lua b/server/server.lua index ff3c3eb..67860ea 100644 --- a/server/server.lua +++ b/server/server.lua @@ -1,6 +1,8 @@ local enet = require"enet" local json = require"common.dkjson" +local chunk = require"common.chunk" local Chunk = require"common.chunk".Chunk +local noise = require"noise" local unpack = unpack or table.unpack local coords = require"common.coords" @@ -58,7 +60,18 @@ local function player_move_packet(player,x,y) return json.encode{t="move",id=player.id,x=x,y=y} end -local the_chunk = Chunk.gen() +local the_tiles = {} +local ng = noise.NoiseAgg.make_perlin_octaves(4) +for q = 1,chunk.SIZE-1 do + for r = 1,chunk.SIZE-1 do + local p = coords.Hex.make(q,r):to_pos() + local nv = ng:at(p.x/20,p.y/20) + assert(nv ~= 1,"oopsy") + the_tiles[chunk.index(q,r)] = nv > 0 and 1+math.floor(math.sqrt(nv)*8) or false + end +end +local the_chunk = Chunk.make(the_tiles) +print"generated chunk" while true do local ev = host:service(100) @@ -104,7 +117,7 @@ while true do elseif op == "settile" then local h = coords.Hex.make(j.q,j.r) the_chunk:set_at(h,j.tile) - print(player.id,"settile",h,j.tile) + -- print(player.id,"settile",h,j.tile) for i,otherplayer in ipairs(playerlist) do if otherplayer ~= player then -- same packet structure s2c as c2s -- cgit v1.2.3