summaryrefslogtreecommitdiff
path: root/client/main.lua
diff options
context:
space:
mode:
Diffstat (limited to 'client/main.lua')
-rw-r--r--client/main.lua364
1 files changed, 26 insertions, 338 deletions
diff --git a/client/main.lua b/client/main.lua
index c2d5a76..f52801c 100644
--- a/client/main.lua
+++ b/client/main.lua
@@ -1,354 +1,42 @@
-local enet = require"enet"
-local json = require"common.dkjson"
-local utf8 = require"utf8"
+local gamescene = require"game"
-
-local SERVER_HOSTNAME = "ubq323.website"
-if os.getenv"HEXEMU_LOCAL" then SERVER_HOSTNAME = "localhost" end
-
-local PLAYER_SIZE = require"common.constants".PLAYER_SIZE
-local local_player = nil
-
-local drawing = require"drawing"
-local coords = require"common.coords"
-local Pos = coords.Pos
-local camera = require"camera".Camera:make()
-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}
-
-
-local help_text = [[
-controls:
-wasd: move
-shift: sprint
-
-left mouse: place
-right mouse: destroy
-mousewheel: zoom in/out
-
-F1: show/hide this help
-F3: show/hide debug
-
-enter: toggle chat]]
-
-
-
-
-math.randomseed(os.time())
-
-local map = Map:make()
-
-local host,peer
-
-
-local selected_tile = 9
-
--- normal: regular gameplay
--- chat: chat box is open
--- more modes may come
-local ui_mode = "normal"
-
-_G.debugmode = false
-
-local show_controls = false
-
-local this_chatmsg = ""
-local chatmsg_text = love.graphics.newText(love.graphics.getFont())
-
-
-function love.keypressed(key,scancode,isrepeat)
- if ui_mode == "normal" then
- if key == "f3" then _G.debugmode = not _G.debugmode end
- if key == "f1" then show_controls = not show_controls end
- for i = 1,9 do if key == tostring(i) then selected_tile = i end end
- if key == "return" then
- ui_mode = "chat"
- this_chatmsg = ""
- end
- elseif ui_mode == "chat" then
- if key == "return" then
- ui_mode = "normal"
- if this_chatmsg:sub(1,3) == "/tp" then
- local x,y = this_chatmsg:match("/tp (%S+) (%S+)")
- if x then
- x,y = tonumber(x),tonumber(y)
- local_player.pos.x=x
- local_player.pos.y=y
- local_player.pos_dirty=true
- end
- else
- peer:send(json.encode{t="chat",msg=this_chatmsg})
- end
- -- msgbox.add("[me] "..this_chatmsg)
- elseif key == "escape" then
- ui_mode = "normal"
- elseif key == "backspace" then
- local boffs = utf8.offset(this_chatmsg,-1)
- if boffs then
- this_chatmsg = this_chatmsg:sub(1,boffs-1)
- end
-
- end
- end
-end
-
-function love.textinput(text)
- if ui_mode == "chat" then
- this_chatmsg = this_chatmsg..text
- end
-end
-
-local function draw_player(pl,islocal)
- love.graphics.setColor(pl.color)
- love.graphics.circle("fill",pl.pos.x,pl.pos.y, PLAYER_SIZE)
-
- if islocal then
- love.graphics.setLineWidth(0.01)
- love.graphics.setColor(0.5,0,0)
- love.graphics.circle("line",pl.pos.x,pl.pos.y,PLAYER_SIZE)
- end
-end
-
-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 end
- local function kd(code)
- if love.keyboard.isScancodeDown(code) then return 1 else return 0 end
- end
- local dx = kd"d"-kd"a"
- local dy = kd"s"-kd"w"
-
- if dx == 0 and dy == 0 then
- return
- end
-
- if dx ~= 0 and dy ~= 0 then
- -- 60degrees direction, to follow hex grid
- -- instead of 45degrees diagonal
- dx = dx * 0.5
- dy = dy * (math.sqrt(3)/2)
- end
-
- 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},1)
- pl.pos_dirty = false
- end
+local current_scene
+local function switch_scene(newscene)
+ if current_scene.quit then current_scene.quit() end
+ current_scene = newscene
+ if newscene.load then newscene.load() end
end
-local function send_settile(hpos,tile)
- peer:send(json.encode{t="settile",q=hpos.q,r=hpos.r,tile=tile})
-end
-
-function love.wheelmoved(dx,dy)
- camera.zoom = camera.zoom * (1.15 ^ dy)
- camera.zoom = math.max(2.5,math.min(50,camera.zoom))
-end
-function love.update(dt)
- msgbox.update(dt)
- if ui_mode == "normal" then
-
- -- movement and zoom in/out (keyboard input)
- if local_player then
- update_local_player(local_player,dt)
- sync_local_player(local_player)
- end
-
- -- mouse input
- local msx,msy = love.mouse.getPosition()
- local mh = camera:screen_to_world(Pos:make(msx,msy)):to_hex():round()
- if map:at(mh) == 0 and love.mouse.isDown(1) then
- map:set_at(mh,selected_tile)
- send_settile(mh,selected_tile)
- elseif map:at(mh) ~= 0 and love.mouse.isDown(2) then
- map:set_at(mh,0)
- send_settile(mh,0)
- end
- end
+local big_font = love.graphics.newFont(72)
+local normal_font = love.graphics.getFont()
- -- load and unload chunks
- if local_player then
- local player_cp = local_player.pos:to_hex():containing_chunk()
- -- load chunks near to player (within 3x3 square)
- for _,cp in ipairs(player_cp:neighborhood()) do
- if map:chunk(cp) == nil then
- map:mark_chunk_loading(cp)
- peer:send(json.encode{t="reqchunk",u=cp.u,v=cp.v})
- end
- end
-
- -- unload chunks not near player
- -- todo maybe: instead of immediately unloading chunks when we move away,
- -- have some kind of 'last near' time, so that if player is moving back and forth,
- -- we don't repeatedly unload and reload a given chunk
- local to_remove = {}
- for cp in map:iter_chunks() do
- local d = player_cp:orth_dist(cp)
- if d > 1 then
- map:remove_chunk(cp)
- end
- end
-
- end
-
-
- -- handle network packets
- repeat
- local ev = host:service()
- if ev and ev.type == "receive" then
- -- print(ev.data)
- local j = json.decode(ev.data)
- local op = j.t
- -- if op ~= "chunk" then print(ev.channel,ev.data) end
- 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}
- msgbox.add(pl.id.." joined")
- elseif op == "leave" then
- local id = j.id
- remote_players[id]=nil
- msgbox.add(id.." left")
- elseif op == "move" then
- local id,x,y = j.id,j.x,j.y
- assert(remote_players[id],"wheeze "..id)
- remote_players[id].pos.x = x
- 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}
- elseif op == "chunk" then
- local ch = ChunkC:from_packet_data(j)
- map:add_chunk(ch)
- elseif op == "settile" then
- local h = coords.Hex:make(j.q,j.r)
- map:set_at(h,j.tile)
- elseif op == "chat" then
- local msg,from = j.msg,j.from
- msgbox.add("["..tostring(from).."] "..msg)
- end
- end
- until not ev
-end
-
-function love.draw()
+local titlescene = {}
+function titlescene.draw()
love.graphics.clear(1,1,1)
love.graphics.origin()
- if local_player then
- camera.pos = local_player.pos
- end
- camera:apply_trans()
-
- -- drawing.draw_map(camera,map)
- drawing2.draw_map(camera,map)
+ love.graphics.setColor(0,0,0)
+ love.graphics.setFont(big_font)
+ love.graphics.print("hexagon emulator",30,30)
-
- if local_player then
- draw_player(local_player,true)
- end
- for _,pl in pairs(remote_players) do
- draw_player(pl)
+ love.graphics.setFont(normal_font)
+ love.graphics.print("press <enter> to start",40,120)
+end
+local evilscene
+function titlescene.keypressed(k,s,r)
+ if k=="return" then
+ switch_scene(gamescene)
end
+end
- love.graphics.setColor(1,0,0)
- love.graphics.rectangle("fill",0,0,1,1)
- local sm = Pos:make(love.mouse.getPosition())
- local wm = camera:screen_to_world(sm)
- local hm = wm:to_hex()
+current_scene=titlescene
- -- draw reticle
- local hmr = hm:round()
- local mouse_tile = map:at(hmr)
- if mouse_tile then
- local col = {0.5,0.5,0.5}
- if mouse_tile == 0 then col = {0,0,0} end
- local c = hmr:to_pos()
- local verts = {}
- for i=0,5 do
- local angle = math.pi*2*(i+0.5)/6
- table.insert(verts, c.x+math.cos(angle))
- table.insert(verts, c.y+math.sin(angle))
- end
- love.graphics.setColor(col)
- love.graphics.setLineWidth(0.05)
- love.graphics.polygon("line",verts)
+for _,f in ipairs{"update","draw","keypressed","textinput","wheelmoved"} do
+ love[f] = function(...)
+ local x = current_scene[f]
+ if x then return x(...) end
end
-
-
-
- love.graphics.origin()
- util.print_good(tostring(selected_tile), "center",10)
- if _G.debugmode and local_player then
- util.print_good(table.concat({
- "ms "..tostring(sm),
- "mw "..tostring(wm),
- "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()),
- "",
- "voob "..tostring(camera.zoom),
- "",
- "fps "..tostring(love.timer.getFPS()),
- "ping "..tostring(peer:round_trip_time()),
-
- },"\n"),10,10)
- end
- if show_controls then
- util.print_good(help_text,"center","center")
- end
-
- msgbox.draw()
-
- if ui_mode ~= "normal" then
- util.print_good(ui_mode, -20,10)
- end
-
- if ui_mode == "chat" then
- local W,H = love.graphics.getDimensions()
- chatmsg_text:set("- "..this_chatmsg)
- local tw,th = chatmsg_text:getDimensions()
- local y = H-th-30
- love.graphics.setColor(0,0,0,0.8)
- love.graphics.rectangle("fill",0,y,W,th)
- love.graphics.setColor(1,1,1)
- love.graphics.draw(chatmsg_text,0,y)
- love.graphics.setColor(0.8,0.8,0.8)
- love.graphics.line(tw,y,tw,y+th)
- end
-
-
end
-function love.load()
- love.keyboard.setKeyRepeat(true)
- -- require"profile".start(10,io.open("./trace","w"))
- host = enet.host_create()
- peer = host:connect(SERVER_HOSTNAME..":8473",2)
- msgbox.add("connected to "..SERVER_HOSTNAME..":8473")
- msgbox.add("press F1 for controls help")
-end
-function love.quit()
- -- require"profile".stop()
- peer:disconnect()
- host:flush()
-end