diff options
-rw-r--r-- | client/chunk.lua | 42 | ||||
-rw-r--r-- | client/conf.lua | 1 | ||||
-rw-r--r-- | client/drawing2.lua | 144 | ||||
-rw-r--r-- | client/main.lua | 21 | ||||
-rw-r--r-- | common/map.lua | 4 | ||||
-rw-r--r-- | server/server.lua | 2 |
6 files changed, 205 insertions, 9 deletions
diff --git a/client/chunk.lua b/client/chunk.lua new file mode 100644 index 0000000..73fe949 --- /dev/null +++ b/client/chunk.lua @@ -0,0 +1,42 @@ +local class = require"common.class" +local chunk = require"common.chunk" +local Chunk = require"common.chunk".Chunk +local CHUNK_SIZE = require"common.constants".CHUNK_SIZE + +local ChunkC = class.extend(chunk.Chunk) +function ChunkC.make(cls,...) + local self = chunk.Chunk.make(cls,...) + self.imesh = cls.imesh_from_chunk_data(self) + return self +end +local function tile_to_vattr(tile) + -- for now tiles are always numbers + -- so this just returns the input + -- this function might move to drawing.lua once it does something less trivial + assert(type(tile) == "number","can't send non-numerical tile to gpu") + return tile +end +function ChunkC.imesh_from_chunk_data(the_chunk) + local mesh_data = {} + for q=0,CHUNK_SIZE-1 do + for r =0,CHUNK_SIZE-1 do + local t = the_chunk:_atqr(q,r) + table.insert(mesh_data,{tile_to_vattr(t)}) + end + end + + local imesh = love.graphics.newMesh({ + {"tile_type","float",1} + }, mesh_data, nil, "dynamic") + + return imesh +end + +function ChunkC.set_at(self,hoffs,tile) + Chunk.set_at(self,hoffs,tile) + + local idx = chunk.index(hoffs.q,hoffs.r) + self.imesh:setVertexAttribute(idx, 1, tile_to_vattr(tile)) +end + +return {ChunkC=ChunkC} diff --git a/client/conf.lua b/client/conf.lua index 76459ff..3a68be3 100644 --- a/client/conf.lua +++ b/client/conf.lua @@ -1,5 +1,6 @@ function love.conf(t) t.window.title = "hexagon emulator" t.window.resizable = true + t.window.msaa =4 end diff --git a/client/drawing2.lua b/client/drawing2.lua new file mode 100644 index 0000000..e09d7dc --- /dev/null +++ b/client/drawing2.lua @@ -0,0 +1,144 @@ +local CHUNK_SIZE = require"common.constants".CHUNK_SIZE +local coords = require"common.coords" + +local tau = 2*math.pi + +-- funny hexagon +local vertices = {} +-- v[1] {0,0}, fill +-- v[2-7] edge, fill +-- v[8-13] inner, outline +-- v[14-19] outer, outline +local map = {} + +do + local function ix(n) return n%6 end + local function th(n) return tau*(ix(n)+0.5)/6 end + local cos,sin = math.cos,math.sin + local OLWIDTH = 0.11 + local hw = OLWIDTH/2 + local ri,ro = 1-hw,1+hw + local function ve(n,f) return {cos(th(n)),sin(th(n)), f} end + local function vi(n,f) return {ri*cos(th(n)),ri*sin(th(n)), f} end + local function vo(n,f) return {ro*cos(th(n)),ro*sin(th(n)), f} end + local function apv(...) for _,x in ipairs({...}) do table.insert(vertices,x) end end + local function apm(...) for _,x in ipairs({...}) do table.insert(map,x) end end + + vertices[1] = {0,0, 1} + for n=0,5 do apv(ve(n,1)) end + for n=0,5 do apv(vi(n,0)) end + for n=0,5 do apv(vo(n,0)) end + + -- fill area + for n=0,5 do apm(1, 2+n, 2+ix(1+n) ) end + + local function ii(n) return 8+ix(n) end + local function oi(n) return 14+ix(n) end + + -- outline area + for n=0,5 do + apm( ii(n), oi(n), oi(n+1) ) + apm( ii(n), oi(n+1), ii(n+1) ) + end +end + +local shape_mesh = love.graphics.newMesh({ + {"VertexPosition","float",2}, + {"fillness","float",1}, +},vertices,"triangles","static") +shape_mesh:setVertexMap(map) + +local function c(...) return {love.math.colorFromBytes(...)} end +-- taken from breadquest +local colors = { + {0,0,0}, + 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 + + c(0xe7,0x9e,0), -- ubqorange +} + +local shader = love.graphics.newShader([[ +#pragma language glsl3 + +const mat2 hex_to_pos = mat2( sqrt(3), 0, sqrt(3)/2, 1.5); +#define CHUNK_SIZE ]]..tostring(CHUNK_SIZE)..[[.0 + + +uniform vec3 colors[10]; + +uniform float zoom; + +attribute float tile_type; +attribute float fillness; + +varying vec4 tcol; + +const float zthr0 = 2.7; +const float zthr1 = 6; +const float zthrd = zthr1-zthr0; + +vec4 position(mat4 transform_projection, vec4 vertex_position) +{ + + + vec2 instance_pos = vec2( floor(love_InstanceID/CHUNK_SIZE), mod(love_InstanceID, CHUNK_SIZE) ); + vertex_position.xy += hex_to_pos * instance_pos; + + float a = clamp( (zoom-zthr0)/zthrd, 0, 1); + a = max(fillness, a); + + int tidx = int(tile_type); + tcol = (tidx == 0) ? vec4(0.0) : vec4(fillness*colors[tidx], a); + + + return transform_projection * vertex_position; +} +]],[[ +#pragma language glsl3 + +varying vec4 tcol; +vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) +{ + // return vec4(tcol.xyz,0.5); + return tcol; +} +]]) + +shader:send("colors",unpack(colors)) + + +local function set_imesh(im) + shape_mesh:detachAttribute("tile_type") + shape_mesh:attachAttribute("tile_type",im,"perinstance") +end + +local function draw_map(camera,map) + shader:send("zoom",camera.zoom) + love.graphics.setShader(shader) + + local count = CHUNK_SIZE*CHUNK_SIZE + for _,ch in map:iter_chunks() do + if ch then + -- todo: skip chunks that aren't on screen, maybe + local htl,hbr = ch.cp:extents() + local tl = htl:to_pos() + + set_imesh(ch.imesh) + love.graphics.drawInstanced(shape_mesh, count, tl.x, tl.y) + end + end + + love.graphics.setShader() +end + + + + +return {draw_map=draw_map} diff --git a/client/main.lua b/client/main.lua index f74cfa9..e37e18f 100644 --- a/client/main.lua +++ b/client/main.lua @@ -13,11 +13,12 @@ local drawing = require"drawing" local coords = require"common.coords" local Pos = coords.Pos local camera = require"camera".Camera:make() -local Chunk = require"common.chunk".Chunk +local ChunkC = require"chunk".ChunkC local util = require"util" local Map = require"common.map".Map local movement = require"movement" local msgbox = require"msgbox" +local drawing2 = require"drawing2" -- local pprint=require"common.pprint" -- pprint.setup{show_all=true} @@ -97,12 +98,14 @@ end local function draw_player(pl,islocal) local hplsz = PLAYER_SIZE/2 love.graphics.setColor(pl.color) - love.graphics.rectangle("fill",pl.pos.x-hplsz,pl.pos.y-hplsz,PLAYER_SIZE,PLAYER_SIZE) + love.graphics.circle("fill",pl.pos.x,pl.pos.y, hplsz) + -- love.graphics.rectangle("fill",pl.pos.x-hplsz,pl.pos.y-hplsz,PLAYER_SIZE,PLAYER_SIZE) -- love.graphics.print(tostring(pl.id),pl.pos.x,pl.pos.y) if islocal then love.graphics.setLineWidth(0.01) love.graphics.setColor(0.5,0,0) - love.graphics.rectangle("line",pl.pos.x-hplsz,pl.pos.y-hplsz,PLAYER_SIZE,PLAYER_SIZE) + love.graphics.circle("line",pl.pos.x,pl.pos.y,hplsz) + -- love.graphics.rectangle("line",pl.pos.x-hplsz,pl.pos.y-hplsz,PLAYER_SIZE,PLAYER_SIZE) end end @@ -111,7 +114,7 @@ local remote_players = {} local function update_local_player(pl,dt) local SPEED = 8*math.sqrt(3) -- 8 hexagonheights per second - if love.keyboard.isDown("lshift") then SPEED = SPEED*2.5 end + if love.keyboard.isDown("lshift") then SPEED = SPEED*2 end local function kd(code) if love.keyboard.isScancodeDown(code) then return 1 else return 0 end end @@ -131,13 +134,14 @@ local function update_local_player(pl,dt) local try_pos = Pos:make(pl.pos.x + SPEED*dt*dx, pl.pos.y + SPEED*dt*dy) pl.pos = movement.collide_with_terrain(pl.pos,try_pos,map) + -- pl.pos = try_pos pl.pos_dirty = true end local function sync_local_player(pl) -- send updated info about local player to server if pl.pos_dirty then - peer:send(json.encode{t="ppos",x=pl.pos.x,y=pl.pos.y}) + peer:send(json.encode{t="ppos",x=pl.pos.x,y=pl.pos.y},1) pl.pos_dirty = false end end @@ -223,7 +227,7 @@ function love.update(dt) local pl = j.pl local_player = {pos=coords.Pos:make(pl.x,pl.y),color=pl.color,id=pl.id} elseif op == "chunk" then - local ch = Chunk:from_packet_data(j) + local ch = ChunkC:from_packet_data(j) map:add_chunk(ch) elseif op == "settile" then local h = coords.Hex:make(j.q,j.r) @@ -244,7 +248,9 @@ function love.draw() end camera:apply_trans() - drawing.draw_map(camera,map) + -- drawing.draw_map(camera,map) + drawing2.draw_map(camera,map) + if local_player then draw_player(local_player,true) @@ -301,6 +307,7 @@ function love.draw() love.graphics.line(tw,y,tw,y+th) end + end function love.load() diff --git a/common/map.lua b/common/map.lua index 1028982..67e2834 100644 --- a/common/map.lua +++ b/common/map.lua @@ -8,8 +8,10 @@ -- to test whether a chunk needs to be loaded you do if map:chunk(cp) == nil then ... end. -- it will probably also do things relating to entities and multiblock things +-- note that the Map never creates any Chunks itself, which means it should be agnostic +-- to whatever actual Chunk class is being used (ChunkC or ChunkS or whatever) + local class = require"common.class" -local chunk = require"common.chunk" local coords = require"common.coords" local CHUNK_SIZE = require"common.constants".CHUNK_SIZE diff --git a/server/server.lua b/server/server.lua index f78bdd0..03a5fd9 100644 --- a/server/server.lua +++ b/server/server.lua @@ -103,7 +103,7 @@ local function handle_ev(ev) -- print(player.id,"-->",player.pos[1],player.pos[2]) for i,otherplayer in ipairs(playerlist) do if otherplayer ~= player then - otherplayer.peer:send(player_move_packet(player,x,y)) + otherplayer.peer:send(player_move_packet(player,x,y),1) end end elseif op == "settile" then |