summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2023-02-03 19:37:28 +0000
committerubq323 <ubq323@ubq323.website>2023-02-03 19:51:07 +0000
commit1ebd7d9b7b62c8e05d527611a1944ed1a876b890 (patch)
treecfc5ddf3fc15985c4369aa12d56de5fa8d6fc7e5
parentec6a391cb9cf0c0feac0fe3615a59cc7cb6db2d5 (diff)
debug drawing change, zoom clamping, partial refactoring of class mechanisms to allow inheritance, minor refactor of noise generator, changes to temp worldgen, rework of class constructor mechanism
-rw-r--r--client/camera.lua16
-rw-r--r--client/drawing.lua19
-rw-r--r--client/main.lua22
-rw-r--r--common/.map.lua.kak.Xd2mKc5
-rw-r--r--common/chunk.lua15
-rw-r--r--common/class.lua23
-rw-r--r--common/coords.lua34
-rw-r--r--common/map.lua6
-rw-r--r--server/noise.lua34
-rw-r--r--server/server.lua41
10 files changed, 140 insertions, 75 deletions
diff --git a/client/camera.lua b/client/camera.lua
index 6309e38..528b45b 100644
--- a/client/camera.lua
+++ b/client/camera.lua
@@ -1,15 +1,15 @@
local coords = require"common.coords"
+local class = require"common.class"
-- in screen units
local screen_width, screen_height = love.graphics.getDimensions()
-- zoom is screen pixels per world unit
-local Camera = {}
-Camera.__index = Camera
-function Camera.make(pos,zoom)
- pos = pos or coords.Pos.make(0,0)
+local Camera = class()
+function Camera.make(cls,pos,zoom)
+ pos = pos or coords.Pos:make(0,0)
zoom = zoom or 30
- return setmetatable({pos=pos,zoom=zoom},Camera)
+ return setmetatable({pos=pos,zoom=zoom},cls)
end
function Camera.apply_trans(self)
love.graphics.origin()
@@ -21,7 +21,7 @@ function Camera.apply_trans(self)
love.graphics.translate(-self.pos.x,-self.pos.y)
end
-local screen_offset = coords.Pos.make(screen_width/2,screen_height/2)
+local screen_offset = coords.Pos:make(screen_width/2,screen_height/2)
function Camera.screen_to_world(self,pos)
return (pos-screen_offset)/self.zoom + self.pos
end
@@ -31,8 +31,8 @@ end
function Camera.extents(self)
-- returns top left and bottom right pos's in world coords
- return self:screen_to_world(coords.Pos.make(0,0)),
- self:screen_to_world(coords.Pos.make(screen_width,screen_height))
+ return self:screen_to_world(coords.Pos:make(0,0)),
+ self:screen_to_world(coords.Pos:make(screen_width,screen_height))
end
diff --git a/client/drawing.lua b/client/drawing.lua
index 111b2e2..bbcf03a 100644
--- a/client/drawing.lua
+++ b/client/drawing.lua
@@ -33,7 +33,6 @@ local colors = {
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
@@ -67,14 +66,14 @@ end
local function draw_chunk(camera,the_chunk)
local tl,br = camera:extents()
local tlh,brh = tl:to_hex():round(), br:to_hex():round()
- local trh = coords.Pos.make(br.x,tl.y):to_hex():round()
+ local trh = coords.Pos:make(br.x,tl.y):to_hex():round()
for r = tlh.r-1,brh.r+1 do
local rowidx = r-tlh.r
local minq = tlh.q - math.floor((rowidx+1)/2)
local maxq = minq+(trh.q-tlh.q)+1
for q = minq,maxq do
- local h = coords.Hex.make(q,r)
+ local h = coords.Hex:make(q,r)
local t = the_chunk:at(h)
if type(t) == "number" then
draw_hex(h:to_pos(),colors[t],camera.zoom)
@@ -84,6 +83,20 @@ local function draw_chunk(camera,the_chunk)
end
end
+ if _G.debugmode then
+ love.graphics.setColor(0,1,0)
+
+ local function p(q,r) return coords.Hex:make(q,r):to_pos() end
+ local h = chunk.SIZE-0.5
+ local c00 = p(-0.5,-0.5)
+ local c01 = p(-0.5,h)
+ local c10 = p(h,-0.5)
+ local c11 = p(h,h)
+
+ love.graphics.polygon("line",
+ c00.x,c00.y, c01.x,c01.y, c11.x,c11.y, c10.x, c10.y)
+ end
+
end
diff --git a/client/main.lua b/client/main.lua
index 2fad49e..7af1bd4 100644
--- a/client/main.lua
+++ b/client/main.lua
@@ -10,7 +10,7 @@ local local_player = nil
local drawing = require"drawing"
local coords = require"common.coords"
local Pos = coords.Pos
-local camera = require"camera".Camera.make()
+local camera = require"camera".Camera:make()
local Chunk = require"common.chunk".Chunk
local util = require"util"
@@ -24,10 +24,10 @@ local host,peer
local chunk
-local f3mode = false
+_G.debugmode = false
function love.keypressed(key,scancode,isrepeat)
- if scancode == "f3" then f3mode = not f3mode end
+ if scancode == "f3" then _G.debugmode = not _G.debugmode end
end
local function draw_player(pl,islocal)
@@ -45,7 +45,8 @@ end
local remote_players = {}
local function update_local_player(pl,dt)
- local SPEED = 10 -- pixels/sec
+ local SPEED = 10 -- units/sec
+ if love.keyboard.isScancodeDown("lshift") then SPEED = 100 end
local function kd(code)
if love.keyboard.isScancodeDown(code) then return 1 else return 0 end
end
@@ -85,10 +86,11 @@ function love.update(dt)
update_local_player(local_player,dt)
if love.keyboard.isScancodeDown"q" then camera.zoom = camera.zoom*1.05 end
if love.keyboard.isScancodeDown"e" then camera.zoom = camera.zoom/1.05 end
+ camera.zoom = math.max(2.25,math.min(50,camera.zoom))
sync_local_player(local_player,peer)
end
if chunk then
- local mh = camera:screen_to_world(Pos.make(love.mouse.getPosition())):to_hex():round()
+ 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)
@@ -108,7 +110,7 @@ function love.update(dt)
local op = j.t
if op == "join" then
local pl = j.pl
- remote_players[pl.id] = {pos=coords.Pos.make(pl.x,pl.y),color=pl.color,id=pl.id}
+ remote_players[pl.id] = {pos=coords.Pos:make(pl.x,pl.y),color=pl.color,id=pl.id}
elseif op == "leave" then
local id = j.id
remote_players[id]=nil
@@ -119,11 +121,11 @@ function love.update(dt)
remote_players[id].pos.y = y
elseif op == "you" then
local pl = j.pl
- local_player = {pos=coords.Pos.make(pl.x,pl.y),color=pl.color,id=pl.id}
+ local_player = {pos=coords.Pos:make(pl.x,pl.y),color=pl.color,id=pl.id}
elseif op == "chunk" then
chunk = Chunk.from_packet_data(j)
elseif op == "settile" then
- local h = coords.Hex.make(j.q,j.r)
+ local h = coords.Hex:make(j.q,j.r)
chunk:set_at(h,j.tile)
end
end
@@ -152,12 +154,12 @@ function love.draw()
love.graphics.setColor(1,0,0)
love.graphics.rectangle("fill",0,0,1,1)
- local sm = Pos.make(love.mouse.getPosition())
+ local sm = Pos:make(love.mouse.getPosition())
local wm = camera:screen_to_world(sm)
local hm = wm:to_hex()
love.graphics.origin()
- if f3mode and local_player then
+ if _G.debugmode and local_player then
util.print_good({
"ms "..tostring(sm),
"mw "..tostring(wm),
diff --git a/common/.map.lua.kak.Xd2mKc b/common/.map.lua.kak.Xd2mKc
new file mode 100644
index 0000000..aa2bfb0
--- /dev/null
+++ b/common/.map.lua.kak.Xd2mKc
@@ -0,0 +1,5 @@
+-- a Map is a 2d array of chunks
+-- it handles loading and unloading of chunks
+-- the specifics of which are then implemented separately for client and server
+-- it will probably also do things relating to entities and multiblock things
+
diff --git a/common/chunk.lua b/common/chunk.lua
index 8e2ec40..1d3faa6 100644
--- a/common/chunk.lua
+++ b/common/chunk.lua
@@ -1,6 +1,7 @@
local json = require"common.dkjson"
+local class = require"common.class"
-local CHUNK_SIZE = 128
+local CHUNK_SIZE = 64
-- for now tiles shall be booleans
@@ -15,10 +16,9 @@ local function index(offq,offr)
return CHUNK_SIZE*offq + offr + 1
end
-local Chunk = {}
-Chunk.__index = Chunk
-function Chunk.make(tiles)
- return setmetatable({tiles=tiles},Chunk)
+local Chunk = class()
+function Chunk.make(cls,tiles)
+ return setmetatable({tiles=tiles},cls)
end
function Chunk.at(self,hoffs)
if not index_ok(hoffs.q,hoffs.r) then return nil end
@@ -35,11 +35,12 @@ end
function Chunk.from_packet_data(packet)
-- assuming packet has already been json.decoded
-- since otherwise how would we know it's a chunk packet
- return Chunk.make(packet.tiles)
+ return Chunk:make(packet.tiles)
end
return {
Chunk=Chunk,
SIZE=CHUNK_SIZE,
- index=index
+ index=index,
+ index_ok=index_ok,
}
diff --git a/common/class.lua b/common/class.lua
new file mode 100644
index 0000000..37cf7bd
--- /dev/null
+++ b/common/class.lua
@@ -0,0 +1,23 @@
+local function class()
+ local T = {}
+ T.__index = T
+ return T
+end
+
+local function extend(Base)
+ local T = {}
+ T.__index = T
+ for k,v in pairs(Base) do
+ if k:sub(1,2) == "__" and k~="__index" then
+ T[k]=v
+ end
+ end
+ setmetatable(T,{__index=Base})
+end
+
+return setmetatable({
+ class=class,
+ extend=extend
+},{__call=class})
+
+
diff --git a/common/coords.lua b/common/coords.lua
index 2399e43..351aa53 100644
--- a/common/coords.lua
+++ b/common/coords.lua
@@ -1,3 +1,5 @@
+local class = require"common.class"
+
-- Hex: q,r,s. invariant that q+r+s=0
-- add, subtract
-- constructor takes 3 positions and rounds to closest hex centre.
@@ -15,12 +17,11 @@ local Pos, Hex
local SR3 = math.sqrt(3)
-Hex={}
-Hex.__index = Hex
-function Hex.make(q,r,s)
+local Hex = class()
+function Hex.make(cls,q,r,s)
s=s or -q-r
assert(q+r+s==0,"hex coord doesn't meet invariant")
- return setmetatable({q=q,r=r,s=s},Hex)
+ return setmetatable({q=q,r=r,s=s},cls)
end
function Hex.round(self)
-- return a new Hex rounded to integer coordinates
@@ -40,32 +41,31 @@ function Hex.round(self)
rs = -rq-rr
end
- return Hex.make(rq,rr,rs)
+ return Hex:make(rq,rr,rs)
end
function Hex.to_pos(self)
local x = self.q*SR3 + self.r*(SR3/2)
local y = self.r*(3/2)
- return Pos.make(x,y)
+ return Pos:make(x,y)
end
-function Hex.__add(self,other) return Hex.make(self.q+other.q, self.r+other.r, self.s+other.s) end
-function Hex.__sub(self,other) return Hex.make(self.q-other.q, self.r-other.r, self.s-other.s) end
+function Hex.__add(self,other) return Hex:make(self.q+other.q, self.r+other.r, self.s+other.s) end
+function Hex.__sub(self,other) return Hex:make(self.q-other.q, self.r-other.r, self.s-other.s) end
function Hex.__tostring(self) return string.format("H(%.2f,%.2f)",self.q,self.r) end
-Pos = {}
-Pos.__index=Pos
-function Pos.make(x,y)
- return setmetatable({x=x,y=y},Pos)
+Pos = class()
+function Pos.make(cls,x,y)
+ return setmetatable({x=x,y=y},cls)
end
-function Pos.__add(self,other) return Pos.make(self.x+other.x,self.y+other.y) end
-function Pos.__sub(self,other) return Pos.make(self.x-other.x,self.y-other.y) end
+function Pos.__add(self,other) return Pos:make(self.x+other.x,self.y+other.y) end
+function Pos.__sub(self,other) return Pos:make(self.x-other.x,self.y-other.y) end
function Pos.__mul(a,b)
if type(a) == "number" then
- return Pos.make(a*b.x,a*b.y)
+ return Pos:make(a*b.x,a*b.y)
elseif type(b) == "number" then
- return Pos.make(a.x*b,a.y*b)
+ return Pos:make(a.x*b,a.y*b)
else
error("can only multiply Pos by scalar")
end
@@ -81,7 +81,7 @@ 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
- return Hex.make(q,r,-q-r)
+ return Hex:make(q,r,-q-r)
end
function Pos.__tostring(self) return string.format("(%.2f,%.2f)",self.x,self.y) end
diff --git a/common/map.lua b/common/map.lua
new file mode 100644
index 0000000..fe4b9e0
--- /dev/null
+++ b/common/map.lua
@@ -0,0 +1,6 @@
+-- a Map is a 2d array of chunks
+-- it handles loading and unloading of chunks
+-- the specifics of which are then implemented separately for client and server
+-- it will probably also do things relating to entities and multiblock things
+
+
diff --git a/server/noise.lua b/server/noise.lua
index 1480448..8a83b60 100644
--- a/server/noise.lua
+++ b/server/noise.lua
@@ -1,11 +1,12 @@
local Pos = require"common.coords".Pos
+local class = require"common.class"
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))
+ 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)
@@ -15,14 +16,13 @@ local function smoothstep(x)
end
local function slerp(a,b,t) return lerp(a,b,smoothstep(t)) end
-local NoiseGen = {}
-NoiseGen.__index = NoiseGen
-function NoiseGen.make()
+local PerlinNoise = class()
+function PerlinNoise.make(cls)
local grid = {}
setmetatable(grid,{__index=function(t,k) t[k] = {} return t[k] end})
- return setmetatable({grid=grid},NoiseGen)
+ return setmetatable({grid=grid},cls)
end
-function NoiseGen.vertex(self,ix,iy)
+function PerlinNoise.vertex(self,ix,iy)
local v = self.grid[ix][iy]
if v then return v end
vv = random_unit_vec()
@@ -30,7 +30,7 @@ function NoiseGen.vertex(self,ix,iy)
return vv
end
-function NoiseGen.at(self,x,y)
+function PerlinNoise.at(self,x,y)
local x0 = math.floor(x)
local y0 = math.floor(y)
local x1 = x0 + 1
@@ -41,7 +41,7 @@ function NoiseGen.at(self,x,y)
local v10 = self:vertex(x1,y0)
local v11 = self:vertex(x1,y1)
- local p = Pos.make
+ local p = function(...) return Pos:make(...) end
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))
@@ -53,17 +53,9 @@ function NoiseGen.at(self,x,y)
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)
+local NoiseAgg = class()
+function NoiseAgg.make(cls,things)
+ return setmetatable({things=things or {}},cls)
end
function NoiseAgg.at(self,x,y)
local n = 0
@@ -72,7 +64,7 @@ function NoiseAgg.at(self,x,y)
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
+ t = t + gen:at(x/scale,y/scale)*amp
end
return t/n
end
@@ -93,4 +85,4 @@ end
-- io.write("\n")
-- end
-return {NoiseGen=NoiseGen,NoiseAgg=NoiseAgg}
+return {PerlinNoise=PerlinNoise,NoiseAgg=NoiseAgg}
diff --git a/server/server.lua b/server/server.lua
index 67860ea..08f75c0 100644
--- a/server/server.lua
+++ b/server/server.lua
@@ -60,19 +60,42 @@ local function player_move_packet(player,x,y)
return json.encode{t="move",id=player.id,x=x,y=y}
end
+
+-- worldgen
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
+local function p(amp,scale) return {scale=scale,amp=amp,gen=noise.PerlinNoise:make()} end
+local ng = noise.NoiseAgg:make{
+ p(1,20),
+ -- p(0.7,2),
+ p(0.5,15),
+ --p(2,200),
+}
+local ng2 = noise.NoiseAgg:make{p(1,20),p(0.5,15)}
+
+for q = 0,chunk.SIZE-1 do
+ for r = 0,chunk.SIZE-1 do
+ local p = coords.Hex:make(q,r):to_pos()
+ local ix = chunk.index(q,r)
+ local nv = ng:at(p.x,p.y)
+ if nv <= 0 then
+ the_tiles[ix] = false
+ else
+ local nv2 = ng2:at(p.x,p.y)
+ nv2 = math.max(-0.9999999,math.min(0.9999999,nv2*2.5))
+ nv2 = (nv2+1)/2
+ print(nv2)
+
+ local tv = 1+math.floor(nv2*8)
+ assert(1<=tv and tv<=8,"oopsy woopsy")
+ the_tiles[ix] = tv
+ end
end
end
-local the_chunk = Chunk.make(the_tiles)
+local the_chunk = Chunk:make(the_tiles)
print"generated chunk"
+
+
while true do
local ev = host:service(100)
if ev then
@@ -115,7 +138,7 @@ while true do
end
end
elseif op == "settile" then
- local h = coords.Hex.make(j.q,j.r)
+ local h = coords.Hex:make(j.q,j.r)
the_chunk:set_at(h,j.tile)
-- print(player.id,"settile",h,j.tile)
for i,otherplayer in ipairs(playerlist) do