summaryrefslogtreecommitdiff
path: root/client/game.lua
blob: 30dcd756d6b41be2ab342a4adcb765766fedcdc0 (plain)
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
local G = love.graphics
local common = require 'common'
local Camera = require'r.camera'
local Pos = require"r.pos"
local Rect = require'r.rect'
local class = require'r.class'
local enet = require'enet'
local json = require'dkjson'
local rle = require'r.rle'
local print_good = require'r.print_good'
local rmath = require'r.math'
local msgbox = require'r.msgbox'
local utf8 = require'utf8'

local M = {}

local SPEED = 8 -- tiles per second
local colors = {[true]={141/255,128/255,22/255}, [false]={71/255,50/255,122/255}}


local players = {}
local chunks = common.ChunkMap()
local lp = { pos=Pos(0,0), movetimer=0, dir=nil } -- local player
local cam = Camera(nil, 20)

local host, conn
function M.load(_host,_conn,j) host=_host  conn=_conn
	lp.pos=Pos(j.pos.x,j.pos.y)  lp.name=j.name  lp.color=j.color end
function M.quit() conn:disconnect() host:flush() end

local show={ui=true,debug=false}
local chatmsg = nil
local chatmsg_text = G.newText(G.getFont())
local function chat_key(k,s,r)
		if k == 'escape' then chatmsg = nil
	elseif k == 'return' then if #chatmsg>0 then
		msgbox.add(lp.name..': '..chatmsg)
		conn:send(json.encode{type='chat',msg=chatmsg}) end
		chatmsg = nil
	elseif k == 'backspace' and #chatmsg>0 then
		chatmsg = chatmsg:sub(1,utf8.offset(chatmsg,-1)-1) end end
function M.textinput(str) if chatmsg then chatmsg = chatmsg..str end end
local t = 0

local function smoovement(player) if not player.oldpos then return player.pos end
	return rmath.clerp(player.oldpos,player.pos,(t-player.at)*16) end
local function moveplayer(player,newpos)
	player.oldpos = player.pos
	player.pos = newpos
	player.at = t end

local directions = {w=Pos(0,-1),a=Pos(-1,0),s=Pos(0,1),d=Pos(1,0)}
function M.keypressed(k,s,r) if chatmsg then chat_key(k,s,r) else
	if directions[s] then
		if not love.keyboard.isScancodeDown('lshift') then lp.dir = s
		else local tgt = lp.pos + directions[s]
			local val = not chunks:tile(tgt); chunks:set_tile(tgt,val)
			conn:send(json.encode{type='tile',pos=tgt,tile=val}) end
	elseif k=='space' then cam.zoom = cam.zoom == 10 and 20 or 10
	elseif k=='tab' then show.ui = not show.ui
	elseif k=='return' then chatmsg = ''  lp.dir = nil
	elseif k=='f3' then show.debug = not show.debug end end end
function M.keyreleased(k,s)  if s==lp.dir then lp.dir=nil end end
function lp.update(dt)
	lp.movetimer = lp.movetimer - dt
	if lp.movetimer <= 0 and lp.dir then
		local d = directions[lp.dir] local newpos = lp.pos+d
		if chunks:tile(newpos) == false then
			conn:send(json.encode{type='move',pos=newpos})
			moveplayer(lp,newpos) lp.movetimer = 1 / SPEED  end end end
local function draw_player(player,no_label)
	local effpos = smoovement(player)
	G.setColor(player.color) G.circle('fill',effpos.x,effpos.y,0.3)
	if show.ui and not no_label then local f = G.getFont()
		local txtw,h = f:getWidth(player.name), f:getHeight()
		local centre = cam:world_to_screen(effpos-Pos(0,.4))-Pos(0,h/2)
		local bb = Rect:from_centre_dims(centre,txtw,h)
		G.push() G.origin() G.setColor(0,0,0,0.4) bb:draw'fill'
		G.setColor(1,1,1) G.print(player.name,bb.tl:floor():vals()) G.pop() end end
function lp.draw() draw_player(lp,true) end


function M.update(dt)
	t = t + dt   lp.update(dt) msgbox.update(dt)
	local ev = host and host:service()  while ev do
		if ev.type == 'receive' then local j = json.decode(ev.data)
			local pos  if j.pos then pos = Pos(j.pos.x,j.pos.y) end
				if j.type == 'player' 	then
					players[j.name] = {name=j.name,pos=pos,color=j.color,at=t}
					if t > 1 then msgbox.add(j.name..' joined') end
			elseif j.type == 'unplayer' then players[j.from] = nil msgbox.add(j.from..' left')
			elseif j.type == 'move' 	then moveplayer(players[j.from],pos)
			elseif j.type == 'chunk'	then chunks:add(pos,{d=rle.decode(j.d)})
			elseif j.type == 'unchunk'	then chunks:remove(pos)
			elseif j.type == 'tile'		then chunks:set_tile(pos,j.tile)
			elseif j.type == 'chat'		then msgbox.add(j.from..': '..j.msg)
			end
		end
		ev = host and host:service()
	end
end
function M.draw()
	G.clear(1,1,1); G.origin()
	cam.pos = smoovement(lp); cam:apply_trans()

	local tl,br = cam:extents()
	tl = tl:floor()  br = br:ceil()
	for x=tl.x,br.x do for y=tl.y,br.y do
		local t = chunks:tile(Pos(x,y))
		if t ~= nil then G.setColor(colors[t~=(x<0)]) G.rectangle('fill',x-0.5,y-0.5,1,1) end end end
	lp.draw()
	local playernames = {}
	for _,player in pairs(players) do draw_player(player) table.insert(playernames,player.name) end
	table.sort(playernames) playernames = table.concat(playernames,'\n')
	G.origin()
	if show.ui then msgbox.draw() print_good(playernames,'end',0) end
	if chatmsg then
		chatmsg_text:setFont(G.getFont()) chatmsg_text:set(lp.name..': '..chatmsg)
		local W,H = G.getDimensions() local tw,th = chatmsg_text:getDimensions()
		local y = H-th-30
		G.setColor(0,0,0,0.8) G.rectangle('fill',0,y,W,th)
		G.setColor(1,1,1) G.draw(chatmsg_text,0,y)
		G.setColor(.8,.8,.8) G.line(tw,y,tw,y+th)
	end
	if show.debug then
		G.setColor(1,0,0)
		G.print(tostring(lp.pos),100,100)
		G.setColor(0,0,0,0.8)
		G.rectangle('fill',0,0,100,100)
		G.setColor(1,1,1)
		for cx=-7,7 do for cy=-7,7 do local p=Pos(cx,cy) if chunks:get(p) then
			p = (p + Pos(7,7))*10
			G.setColor(1,1,1) G.rectangle('fill',p.x,p.y,10,10)
			G.setColor(0,0,1) G.rectangle('line',p.x,p.y,10,10)
			end end end
		local p = (lp.pos/common.SIZE+Pos(7,7))*10
		G.setColor(1,0,0) G.rectangle('fill',p.x-1,p.y-1,2,2)
	end
end

return M