What are you using on FE? Re-frame etc. or do you paint in canvas?
@jakub.zika-extern I normally use re-frame for my projects. For the game instead I use html divs and css animations. I would switch if I find a good what to handle the animations
2šÆ@merklefabian I am playing with Quil currently (wrapper over processing(js)), it is nice. You can create simple 2d/3d games with it. http://quil.info/api You can also provide atom to quil so it can be easily connected to RUM (and reagent and reframe - but i did not try it yet), so you can control your canvas by custom html elementsā¦ + I would recommend tips taken from: https://github.com/alexkehayias/chocolatier Tips Here are some tips for optimizing performance of game loops: ā¢ Use the Chrome dev tools to do a CPU profile and trace where time is being spent ā¢ Donāt useĀ `partial`Ā orĀ `apply`Ā as they are slow ā¢ Always specify each arrity of a function instead of usingĀ `(fn [& args] ...)` ā¢ Donāt useĀ `multimethod`, useĀ `cond`Ā orĀ `condp`Ā and manually dispatch ā¢ UseĀ `array`Ā when you need to quickly append items to a collection (mutable) ā¢ UseĀ `loop`Ā instead ofĀ `for`Ā orĀ `into`Ā with transients or arrays as the accumulator ā¢ Avoid boxing and unboxing i.e multiple maps/fors over a collection, use transducers, reducers or loops ā¢ Donāt make multiple calls to get the same data, put it in aĀ `let` ā¢ Avoid heavily nested closures as the lookup tree becomes very long and slow ā¢ Favor eager operations over lazy operations i.eĀ `reduce`Ā instead ofĀ `for` ā¢ Donāt useĀ `concat`Ā orĀ `mapcat`Ā as they can be slow and generate lots of garbage ā¢ Donāt useĀ `last`Ā as it will need to traverse the whole sequence, useĀ `nth`Ā instead if you know how many elements are in the collection ā¢ Donāt use hashmaps as functionsĀ `({:a 1} :a)`, instead useĀ `get`Ā or keywords as functions ā¢ Always return the same type from a function (V8 can then optimize it)
@jakub.zika-extern Thanks for the extensive tips. I saw chocolatier before but had the impression that it was discontinued. Quil looks interesting. Why do you say Donāt useĀ
multimethod` `
@oconn Thanks for your answer. Would you share the code how you do 1. with me, please?
@merklefabian No problem. That workflow is going to be dependent on what youāre using for your websocket server & authentication / user pool. It may be more useful if you share architecture / code for your specific setup. With that said, Iām doing this; 1. Each time a player opens the browser, I check to see if they are authenticated. (Do they have a valid auth token) 2. If the player does have a valid auth token then jump right to an authenticated connection
(let [connection-url
(cond-> ws-url
(some? credentials)
(str "?token=" credentials)
(nil? credentials)
(str "?token=anonymous"))
set-new-connection
#(let [ws (new js/WebSocket connection-url)]
(doto ws
(aset "onopen" (partial ws-on-open ws on-open))
(aset "onclose" (partial ws-on-close ws on-close config))
(aset "onmessage" (partial ws-on-message ws))
(aset "onerror" (partial ws-on-error ws on-error))
(aset "connection-identifier" connection-identifier))
(reset! last-connection-attempt (time-now))
(reset! conn ws))])
3. On the server, before the authenticated connection is created, the credentials are checked against the user pool to identify the player.
4. The player can now send / receive messages over the websocket.
You would adjust the onopen
onclose
onmessage
onerror
handlers to work with your app.
Not sure what youāre using for your websocket server, but Iāve had luck using https://github.com/ptaoussanis/sente and http-kit (one of its supported web servers) before.Chocolatier is discontinued, yeah.
Multimethod can get slower than using condp
.
Your code can get ugly once you will start optimizing JS / Java in Clojure - or you can keep your game simple and it should be fast enough š.
Slower of call time or initialization? Iām using multimethod a lot to separate out the logic of different cards. Didnāt notice any huge speed difference.
I remember that i had got some better call time results with condp but dont take it as granted. It is long time agoā¦
What are you using Quil for?
I did some fun stuff like walking in 3d environment with wasd and jumping etc. But nothing is finished yet. I am more interested in creating the engine and the toolset than the game itself to be honest.
why not edn in a text field?
how would you persist āa text fieldā?
Postgres is highly optimized for indexing and searching data at a granular level. If you do JSONB, you get all the indexing and search stuff for free. If you do EDN in a text field, itās just an opaque blob as far as Postgres is concerned, so you canāt look inside it and search on / index its constituents.
@paul.legato What are lib are you using to convert the edn game state into JSONB before saving it into Postgres?
JSONB just means āJSON binaryā; itās an optimized storage format used internally by Postgres. You can put any standard JSON in there. I use Cheshire, but any JSON will work.
you will wind up adding redundant metadata to the row that allows you to find, say, āinventory for player 1234ā or āall players who have item XYZā, which will eventually drift out of alignment with what it says in the EDN blob. Synchronizing two sources of truth is a hard problem.