Compare commits
2 Commits
fb0c3357dc
...
dc5397331b
Author | SHA1 | Date |
---|---|---|
Pascal Abresch | dc5397331b | |
Pascal Abresch | a195005f91 |
32
Readme.md
32
Readme.md
|
@ -2,7 +2,6 @@
|
||||||
This is the Poppy game\
|
This is the Poppy game\
|
||||||
A server is required to play the game, if you do not have one running then\
|
A server is required to play the game, if you do not have one running then\
|
||||||
run ```love .``` in the ```server/``` directory for a local one for now.\
|
run ```love .``` in the ```server/``` directory for a local one for now.\
|
||||||
(per default the client will connect to this server, it is currently a hardcoded constant in lua/networkThread.lua :/ )\
|
|
||||||
|
|
||||||
|
|
||||||
The performance is currently not so great on older computers,\
|
The performance is currently not so great on older computers,\
|
||||||
|
@ -15,7 +14,7 @@ I have not investigated this much yet. Safe to say it is not intended to run so
|
||||||
* Loading textures
|
* Loading textures
|
||||||
* drawing on canvases
|
* drawing on canvases
|
||||||
* physics calculation for collison and movement
|
* physics calculation for collison and movement
|
||||||
* drawing physics collisions (on the physics layer)
|
* drawing physics collisions (on the physics layer) (debug)
|
||||||
* Basic networking
|
* Basic networking
|
||||||
* Get clientID
|
* Get clientID
|
||||||
* Draw all players
|
* Draw all players
|
||||||
|
@ -25,17 +24,28 @@ I have not investigated this much yet. Safe to say it is not intended to run so
|
||||||
* Send disconnect on client error
|
* Send disconnect on client error
|
||||||
* Chat support
|
* Chat support
|
||||||
|
|
||||||
|
* Retrieve initial game state (partial)
|
||||||
|
* Get users name
|
||||||
|
* Get users avatar
|
||||||
|
* Get world size
|
||||||
|
|
||||||
* Drawing
|
* Drawing
|
||||||
* Draw with custom color
|
* Draw with custom color
|
||||||
* Re-do base textures as gray scale to color in arbitrarily
|
* Re-do base textures as gray scale to color in arbitrarily
|
||||||
|
|
||||||
|
* UI
|
||||||
|
* UI to connect to specific server
|
||||||
|
* Reconnect to server
|
||||||
|
* connect to other server during a session
|
||||||
## Not implemented (rough goals anyhow)
|
## Not implemented (rough goals anyhow)
|
||||||
* UI to connect to specific server
|
* Remember visited servers (save the list)
|
||||||
* Reconnect to server
|
* Add new servers to the list by user input
|
||||||
* connect to other server during a session
|
* Add new servers at runtime via DNS-SD mDNS discovery
|
||||||
* Open second window? Open second instance instead? (does love2d allow that?)
|
|
||||||
* Saving the game (server stuff?)
|
* Saving the map
|
||||||
* Loading the game/map (server stuff?)
|
* Loading the map from disk (and send it to the server)
|
||||||
|
* Loading the map from server on connect
|
||||||
|
|
||||||
* confirmation before clearing canvas (that's quite destructive :D)
|
* confirmation before clearing canvas (that's quite destructive :D)
|
||||||
* Make a way to add dialogs and stuff
|
* Make a way to add dialogs and stuff
|
||||||
|
|
||||||
|
@ -72,7 +82,9 @@ I have not investigated this much yet. Safe to say it is not intended to run so
|
||||||
|
|
||||||
* Networking support
|
* Networking support
|
||||||
* Figure out why and how physics is tied to framerate, why does jump height differ?
|
* Figure out why and how physics is tied to framerate, why does jump height differ?
|
||||||
* Implement initial state sync (mainly server work)
|
* Implement initial state sync
|
||||||
|
* Server remembers plays last position and tells you
|
||||||
|
* Server remembers drawn stuff and tells you
|
||||||
* Add ack que, resend lost packets (but only for stuff like drawing and such, movement may drop)
|
* Add ack que, resend lost packets (but only for stuff like drawing and such, movement may drop)
|
||||||
* Tell the user if the server doesn't support the networking version requested
|
* Tell the user if the server doesn't support the networking version requested
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
gameloop = {}
|
gameloop = {}
|
||||||
gameloop.world = nil
|
gameloop.world = nil
|
||||||
gameloop.textures = {}
|
gameloop.textures = {}
|
||||||
|
gameloop.avatars = {}
|
||||||
local rpc = require("server.rpc")
|
local rpc = require("server.rpc")
|
||||||
local v2_message = require("lua.network")
|
local v2_message = require("lua.network")
|
||||||
local socket = require "socket"
|
local socket = require "socket"
|
||||||
local util = require("server.utils")
|
local util = require("server.utils")
|
||||||
|
|
||||||
|
|
||||||
local function normalDraw()
|
local function normalDraw()
|
||||||
local layerTransform = love.math.newTransform(math.floor(view.x) * scale, math.floor(view.y) * scale, 0, scale, scale)
|
local layerTransform = love.math.newTransform(math.floor(view.x) * scale, math.floor(view.y) * scale, 0, scale, scale)
|
||||||
|
|
||||||
|
@ -63,14 +65,14 @@ end
|
||||||
|
|
||||||
local function normalNetworkSend(args)
|
local function normalNetworkSend(args)
|
||||||
if clientID == "0" then print("Invalid clientID?") end
|
if clientID == "0" then print("Invalid clientID?") end
|
||||||
local request = "poppyV002" ..US.. clientID ..US.. args
|
local request = "poppyV003" ..US.. clientID ..US.. args
|
||||||
gameloop.client:send(request)
|
gameloop.client:send(request)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function debugNetworkSend(args)
|
local function debugNetworkSend(args)
|
||||||
assert(clientID ~= 0)
|
assert(clientID ~= 0)
|
||||||
local request = "poppyV002" ..US.. clientID ..US.. args
|
local request = "poppyV003" ..US.. clientID ..US.. args
|
||||||
print("=> " .. util.pprint(request))
|
print("=> " .. util.pprint(request))
|
||||||
gameloop.client:send(request)
|
gameloop.client:send(request)
|
||||||
end
|
end
|
||||||
|
@ -129,7 +131,7 @@ function errorhandler(msg)
|
||||||
if love.filesystem.getInfo("fonts/font.ttf") then
|
if love.filesystem.getInfo("fonts/font.ttf") then
|
||||||
errorfont = love.graphics.newFont("fonts/font.ttf", 45)
|
errorfont = love.graphics.newFont("fonts/font.ttf", 45)
|
||||||
else
|
else
|
||||||
errorfont = love.graphics.getFont(45)
|
errorfont = love.graphics.newFont(45)
|
||||||
end
|
end
|
||||||
love.graphics.reset()
|
love.graphics.reset()
|
||||||
love.graphics.origin()
|
love.graphics.origin()
|
||||||
|
@ -139,14 +141,16 @@ function errorhandler(msg)
|
||||||
local message2 = love.graphics.newText(errorfont, "Press q to exit")
|
local message2 = love.graphics.newText(errorfont, "Press q to exit")
|
||||||
local message3 = love.graphics.newText(errorfont, msg)
|
local message3 = love.graphics.newText(errorfont, msg)
|
||||||
love.graphics.draw(message, 40, 40, 0, 1, 1)
|
love.graphics.draw(message, 40, 40, 0, 1, 1)
|
||||||
love.graphics.draw(message2, 40, 95, 0, 1, 1)
|
love.graphics.draw(message2, 40, 90, 0, 1, 1)
|
||||||
love.graphics.draw(message3, 40, 145, 0, 1, 1)
|
love.graphics.draw(message3, 40, 140, 0, 1, 1)
|
||||||
|
print(msg)
|
||||||
local indent = 0
|
local indent = 0
|
||||||
local messageline
|
local messageline
|
||||||
for line in debug.traceback():gmatch("([^\n]*)\n?") do
|
for line in debug.traceback():gmatch("([^\n]*)\n?") do
|
||||||
|
print(line)
|
||||||
messageline = love.graphics.newText(errorfont, line)
|
messageline = love.graphics.newText(errorfont, line)
|
||||||
love.graphics.draw(messageline, 40, 255 + indent, 0, 1, 1)
|
love.graphics.draw(messageline, 40, 250 + indent, 0, 1, 1)
|
||||||
indent = indent + 55
|
indent = indent + 50
|
||||||
end
|
end
|
||||||
love.graphics.present()
|
love.graphics.present()
|
||||||
return function()
|
return function()
|
||||||
|
@ -169,10 +173,33 @@ function gameloop.mousepressed(mousex, mousey)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function gameloop.init(server, nickname)
|
function gameloop.loadAvatars()
|
||||||
|
local container = {}
|
||||||
|
local entries = love.filesystem.getDirectoryItems("textures/player")
|
||||||
|
if #entries == 0 then return error("no avatars found") end
|
||||||
|
for i, file in pairs(entries) do
|
||||||
|
local path = "textures/player" .."/".. file
|
||||||
|
local entry = love.filesystem.getInfo(path)
|
||||||
|
if entry.type == "directory" then
|
||||||
|
local textures = love.filesystem.getDirectoryItems(path)
|
||||||
|
for i, texture in pairs(textures) do
|
||||||
|
print(path)
|
||||||
|
local imageData = love.image.newImageData(path .. "/" .. texture)
|
||||||
|
local image = love.graphics.newImage(path .. "/" .. texture)
|
||||||
|
local imageHash = love.data.hash("sha512", imageData:getString())
|
||||||
|
container[imageHash] = {data = imageData, image = image}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
gameloop.avatars = container
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function gameloop.init(server, nickname, avatarHash)
|
||||||
love.errorhandler = errorhandler
|
love.errorhandler = errorhandler
|
||||||
assert(server, "Gameloop called without server to connect to?")
|
assert(server, "Gameloop called without server to connect to?")
|
||||||
assert(nickname, "Gameloop called without nickname?")
|
assert(nickname, "Gameloop called without nickname?")
|
||||||
|
assert(avatarHash, "Gameloop called without avatar?")
|
||||||
gameloop.server = server
|
gameloop.server = server
|
||||||
|
|
||||||
scale = 1
|
scale = 1
|
||||||
|
@ -196,6 +223,9 @@ function gameloop.init(server, nickname)
|
||||||
view.y = 0
|
view.y = 0
|
||||||
clientID = "0"
|
clientID = "0"
|
||||||
|
|
||||||
|
-- Must be done now because it has to be ready before "init" returns from the server
|
||||||
|
-- which is /before/ the game world is loaded
|
||||||
|
gameloop.loadAvatars()
|
||||||
|
|
||||||
gameloop.client = socket.udp()
|
gameloop.client = socket.udp()
|
||||||
gameloop.client:setpeername(server.adress, server.port)
|
gameloop.client:setpeername(server.adress, server.port)
|
||||||
|
@ -204,7 +234,7 @@ function gameloop.init(server, nickname)
|
||||||
print("Socketnname: " .. gameloop.client:getsockname())
|
print("Socketnname: " .. gameloop.client:getsockname())
|
||||||
print("Connecting to [" .. server.adress .."]:" .. server.port)
|
print("Connecting to [" .. server.adress .."]:" .. server.port)
|
||||||
|
|
||||||
local request = "poppyV002" ..US.. "0" ..US.. unit("init", nickname)
|
local request = "poppyV003" ..US.. "0" ..US.. unit("init", nickname, love.data.encode("string", "base64", avatarHash))
|
||||||
gameloop.client:send(request)
|
gameloop.client:send(request)
|
||||||
if NETWORK_DEBUG then print("=> " .. util.pprint(request)) end
|
if NETWORK_DEBUG then print("=> " .. util.pprint(request)) end
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,9 @@ function menu.mousepressed(mousex, mousey)
|
||||||
local fullName = names[love.math.random(1, #names)] .. " " .. lastNames[love.math.random(1, #lastNames)]
|
local fullName = names[love.math.random(1, #names)] .. " " .. lastNames[love.math.random(1, #lastNames)]
|
||||||
local serverID = v.identifier
|
local serverID = v.identifier
|
||||||
local serverEntry = menu.serverlist[serverID]
|
local serverEntry = menu.serverlist[serverID]
|
||||||
gameloop.init({ adress = serverEntry.host, port = serverEntry.port }, fullName)
|
local avatar = love.image.newImageData("textures/player/nephele/dog.png")
|
||||||
|
local avatarHash = love.data.hash("sha512", avatar:getString())
|
||||||
|
gameloop.init({ adress = serverEntry.host, port = serverEntry.port }, fullName, avatarHash)
|
||||||
uiState = {}
|
uiState = {}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,19 +2,20 @@ local player = require("lua.player")
|
||||||
local util = require("server.utils")
|
local util = require("server.utils")
|
||||||
local v2_message = {}
|
local v2_message = {}
|
||||||
|
|
||||||
|
|
||||||
v2_message.init = function(clientID, args)
|
v2_message.init = function(clientID, args)
|
||||||
local nickname, args = util.nextStringRecord(args)
|
local nickname, args = util.nextStringRecord(args)
|
||||||
|
local avatarEncoded, args = util.nextStringRecord(args)
|
||||||
local worldID, args = util.nextStringRecord(args)
|
local worldID, args = util.nextStringRecord(args)
|
||||||
local x, args = util.nextIntRecord(args)
|
local x, args = util.nextIntRecord(args)
|
||||||
local y = tonumber(args)
|
local y = tonumber(args)
|
||||||
|
local avatar = love.data.decode("string", "base64", avatarEncoded)
|
||||||
print("Connected as " .. clientID .. " with name " .. nickname)
|
print("Connected as " .. clientID .. " with name " .. nickname)
|
||||||
print("New world is " .. worldID .. " Size is [" .. x .. "|" .. y .. "]")
|
print("New world is " .. worldID .. " Size is [" .. x .. "|" .. y .. "]")
|
||||||
players[clientID] = player.newPlayer()
|
players[clientID] = player.newPlayer({name = nickname, avatar = gameloop.avatars[avatar].image})
|
||||||
camera.target = clientID
|
camera.target = clientID
|
||||||
_G.clientID = clientID
|
_G.clientID = clientID
|
||||||
|
|
||||||
players[clientID].name = nickname
|
|
||||||
|
|
||||||
local world = { id = worldID, x = x, y = y }
|
local world = { id = worldID, x = x, y = y }
|
||||||
gameloop.loadworld(world)
|
gameloop.loadworld(world)
|
||||||
end
|
end
|
||||||
|
@ -25,11 +26,12 @@ v2_message.ping = function(clientID)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
v2_message.playerJoin = function(clientID, name)
|
v2_message.playerJoin = function(clientID, args)
|
||||||
ui.addChatEntry("", name .. " Joined the game")
|
local nickname, avatarEncoded = util.nextStringRecord(args)
|
||||||
players[clientID] = player.newPlayer()
|
avatar = love.data.decode("string", "base64", avatarEncoded)
|
||||||
players[clientID].label = love.graphics.newText(ui.smallFont, name)
|
ui.addChatEntry("", nickname .. " Joined the game")
|
||||||
players[clientID].name = name
|
players[clientID] = player.newPlayer({name = nickname, avatar = gameloop.avatars[avatar].image})
|
||||||
|
players[clientID].label = love.graphics.newText(ui.smallFont, nickname)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
local playerfuncs = {}
|
local playerfuncs = {}
|
||||||
playerfuncs.newPlayer = function(arg)
|
playerfuncs.newPlayer = function(arg)
|
||||||
|
assert(arg.avatar)
|
||||||
|
assert(arg.name)
|
||||||
local playerTable = {}
|
local playerTable = {}
|
||||||
playerTable.avatar = love.graphics.newImage("textures/player/andysphinx/personb.png")
|
playerTable.avatar = arg.avatar
|
||||||
|
playerTable.name = arg.name
|
||||||
playerTable.speed = {}
|
playerTable.speed = {}
|
||||||
playerTable.speed.x = 0
|
playerTable.speed.x = 0
|
||||||
playerTable.speed.y = 0
|
playerTable.speed.y = 0
|
||||||
|
|
Loading…
Reference in New Issue