mirror of
https://github.com/gren-lang/compiler.git
synced 2024-09-19 21:07:37 +03:00
Changed type signature of JSON.fromString; added multiplayer mario example
This commit is contained in:
parent
f15dbef968
commit
40c1cfa81a
3
.gitignore
vendored
3
.gitignore
vendored
@ -11,4 +11,5 @@ cabal-dev
|
|||||||
/Examples/elm-js/Redirect/Redirect.html
|
/Examples/elm-js/Redirect/Redirect.html
|
||||||
/Examples/elm-js/Form/Form.html
|
/Examples/elm-js/Form/Form.html
|
||||||
/Examples/elm-js/FrameRate/FrameRate.html
|
/Examples/elm-js/FrameRate/FrameRate.html
|
||||||
/Examples/elm-js/Maps/Map.html
|
/Examples/elm-js/Maps/Map.html
|
||||||
|
elm/elm-runtime.js
|
||||||
|
6
Examples/mario_mp/Clicks.elm
Normal file
6
Examples/mario_mp/Clicks.elm
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
module Clicks where
|
||||||
|
import WebSocket
|
||||||
|
msgs = show <~ count Mouse.clicks
|
||||||
|
main = asText <~ open "ws://localhost:8080/ws" msgs
|
||||||
|
|
91
Examples/mario_mp/Mario.elm
Normal file
91
Examples/mario_mp/Mario.elm
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
|
||||||
|
module Mario where
|
||||||
|
|
||||||
|
import Dict
|
||||||
|
import JavaScript
|
||||||
|
import JSON
|
||||||
|
import Random
|
||||||
|
import WebSocket
|
||||||
|
|
||||||
|
{- INPUT -}
|
||||||
|
|
||||||
|
jumpStep isJump obj = if isJump && obj.y == 0 then { obj | vy <- 5 } else obj
|
||||||
|
gravityStep t obj = { obj | vy <- if obj.y > 0 then obj.vy - t/4 else obj.vy }
|
||||||
|
timeStep t obj = let {x,y,vx,vy} = obj in
|
||||||
|
{ obj | x <- x + t * vx , y <- max 0 $ y + t * vy }
|
||||||
|
walkStep dir obj = { obj | vx <- dir, dir <- if | dir < 0 -> "left"
|
||||||
|
| dir > 0 -> "right"
|
||||||
|
| otherwise -> obj.dir }
|
||||||
|
|
||||||
|
step t d j = timeStep t . gravityStep t . jumpStep j . walkStep d
|
||||||
|
|
||||||
|
delta = lift (flip (/) 20) (fps 25)
|
||||||
|
leftRight = toFloat . .x <~ Keyboard.arrows
|
||||||
|
jump = (\{y} -> y > 0) <~ Keyboard.arrows
|
||||||
|
steps = sampleOn delta (lift3 step delta leftRight jump)
|
||||||
|
|
||||||
|
{- LOCAL STATE -}
|
||||||
|
|
||||||
|
initialMario = { x = 0, y = 0, vx = 0, vy = 0, dir = "right" }
|
||||||
|
stateSignal = foldp ($) initialMario steps
|
||||||
|
|
||||||
|
encode obj id =
|
||||||
|
castJSStringToString . (toPrettyJSString "") . JSON.fromList $
|
||||||
|
[ ("id", JsonNumber id)
|
||||||
|
, ("x", JsonNumber obj.x)
|
||||||
|
, ("y", JsonNumber obj.y)
|
||||||
|
, ("vx", JsonNumber obj.vx)
|
||||||
|
, ("dir", JsonString obj.dir) ]
|
||||||
|
--encode obj id = show id ++ " " ++ show obj.x ++ " " ++ show obj.y
|
||||||
|
|
||||||
|
clientID = inRange 0 99999
|
||||||
|
myStream = encode <~ stateSignal ~ clientID
|
||||||
|
|
||||||
|
{- NETWORK LAYER -}
|
||||||
|
|
||||||
|
worldMessageStream = open "ws://localhost:8080/ws" myStream
|
||||||
|
|
||||||
|
-- :: String -> Maybe (Float, Record)
|
||||||
|
parsePlayer msg =
|
||||||
|
case fromString msg of
|
||||||
|
Nothing -> Nothing
|
||||||
|
Just json ->
|
||||||
|
let id = findNumber "id" json
|
||||||
|
x = findNumber "x" json
|
||||||
|
y = findNumber "y" json
|
||||||
|
vx = findNumber "vx" json
|
||||||
|
dir = findString "dir" json
|
||||||
|
in Just (id, { x = x, y = y, vx = vx, vy = 0, dir = dir })
|
||||||
|
|
||||||
|
-- :: Maybe (Float, Record) -> Dict String Record -> Dict String Record
|
||||||
|
updateWorldPositions maybeMario marioDict = case maybeMario of
|
||||||
|
Just (id, mario) -> (Dict.insert) (show id) mario marioDict
|
||||||
|
Nothing -> marioDict
|
||||||
|
|
||||||
|
-- :: Signal (Dict String Record)
|
||||||
|
worldPositions = foldp updateWorldPositions Dict.empty (parsePlayer <~ worldMessageStream)
|
||||||
|
--worldPositions = constant empty
|
||||||
|
|
||||||
|
marios = Dict.values <~ worldPositions
|
||||||
|
|
||||||
|
{- RENDER CODE -}
|
||||||
|
|
||||||
|
-- :: Record -> Form
|
||||||
|
mario2Form (w,h) mario =
|
||||||
|
let verb = if mario.vx /= 0 then "walk" else "stand"
|
||||||
|
src = "/imgs/mario/" ++ verb ++ "/" ++ mario.dir ++ ".gif"
|
||||||
|
in toForm (mario.x, (h-63)-mario.y) (image 35 35 src)
|
||||||
|
|
||||||
|
-- :: (Int,Int) -> [Record] -> Element
|
||||||
|
render (w,h) marios =
|
||||||
|
collage w h ( (filled cyan $ rect w h (w `div` 2, h `div` 2))
|
||||||
|
: (filled green $ rect w 50 (w `div` 2,h-25))
|
||||||
|
: List.map (mario2Form (w,h)) marios )
|
||||||
|
|
||||||
|
{- PUTTING IT TOGETHER -}
|
||||||
|
|
||||||
|
-- :: Signal Element
|
||||||
|
main = render <~ Window.dimensions ~ marios
|
||||||
|
--main = above <~ ((plainText . show) <~ (marios)) ~ (render <~ Window.dimensions ~ marios)
|
||||||
|
--main = (plainText . show) <~ (marios)
|
||||||
|
|
8
Examples/mario_mp/Object.elm
Normal file
8
Examples/mario_mp/Object.elm
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
module Object where
|
||||||
|
|
||||||
|
import JavaScript
|
||||||
|
import JSON
|
||||||
|
|
||||||
|
main = plainText . castJSStringToString . (toPrettyJSString "") . fromList $ [ ("answer", JsonNumber 42) ]
|
||||||
|
|
7
Examples/mario_mp/Values.elm
Normal file
7
Examples/mario_mp/Values.elm
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
module Values where
|
||||||
|
|
||||||
|
import Dict
|
||||||
|
|
||||||
|
main = constant . plainText . show . values $ empty
|
||||||
|
|
43
Examples/mario_mp/conn.go
Normal file
43
Examples/mario_mp/conn.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"code.google.com/p/go.net/websocket"
|
||||||
|
)
|
||||||
|
|
||||||
|
type connection struct {
|
||||||
|
// The websocket connection.
|
||||||
|
ws *websocket.Conn
|
||||||
|
|
||||||
|
// Buffered channel of outbound messages.
|
||||||
|
send chan string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *connection) reader() {
|
||||||
|
for {
|
||||||
|
var message string
|
||||||
|
err := websocket.Message.Receive(c.ws, &message)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
h.broadcast <- message
|
||||||
|
}
|
||||||
|
c.ws.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *connection) writer() {
|
||||||
|
for message := range c.send {
|
||||||
|
err := websocket.Message.Send(c.ws, message)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.ws.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func wsHandler(ws *websocket.Conn) {
|
||||||
|
c := &connection{send: make(chan string, 256), ws: ws}
|
||||||
|
h.register <- c
|
||||||
|
defer func() { h.unregister <- c }()
|
||||||
|
go c.writer()
|
||||||
|
c.reader()
|
||||||
|
}
|
1
Examples/mario_mp/elm-runtime.js
Symbolic link
1
Examples/mario_mp/elm-runtime.js
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../elm/elm-runtime.js
|
44
Examples/mario_mp/hub.go
Normal file
44
Examples/mario_mp/hub.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type hub struct {
|
||||||
|
// Registered connections.
|
||||||
|
connections map[*connection]bool
|
||||||
|
|
||||||
|
// Inbound messages from the connections.
|
||||||
|
broadcast chan string
|
||||||
|
|
||||||
|
// Register requests from the connections.
|
||||||
|
register chan *connection
|
||||||
|
|
||||||
|
// Unregister requests from connections.
|
||||||
|
unregister chan *connection
|
||||||
|
}
|
||||||
|
|
||||||
|
var h = hub{
|
||||||
|
broadcast: make(chan string),
|
||||||
|
register: make(chan *connection),
|
||||||
|
unregister: make(chan *connection),
|
||||||
|
connections: make(map[*connection]bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *hub) run() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case c := <-h.register:
|
||||||
|
h.connections[c] = true
|
||||||
|
case c := <-h.unregister:
|
||||||
|
delete(h.connections, c)
|
||||||
|
close(c.send)
|
||||||
|
case m := <-h.broadcast:
|
||||||
|
for c := range h.connections {
|
||||||
|
select {
|
||||||
|
case c.send <- m:
|
||||||
|
default:
|
||||||
|
delete(h.connections, c)
|
||||||
|
close(c.send)
|
||||||
|
go c.ws.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
Examples/mario_mp/imgs/mario/stand/left.gif
Normal file
BIN
Examples/mario_mp/imgs/mario/stand/left.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 357 B |
BIN
Examples/mario_mp/imgs/mario/stand/right.gif
Normal file
BIN
Examples/mario_mp/imgs/mario/stand/right.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 364 B |
BIN
Examples/mario_mp/imgs/mario/walk/left.gif
Normal file
BIN
Examples/mario_mp/imgs/mario/walk/left.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
Examples/mario_mp/imgs/mario/walk/right.gif
Normal file
BIN
Examples/mario_mp/imgs/mario/walk/right.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
24
Examples/mario_mp/main.go
Normal file
24
Examples/mario_mp/main.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"code.google.com/p/go.net/websocket"
|
||||||
|
"flag"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
var addr = flag.String("addr", ":8080", "http service address")
|
||||||
|
|
||||||
|
func fileHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
http.ServeFile(w, r, r.URL.Path[1:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
go h.run()
|
||||||
|
http.HandleFunc("/", fileHandler)
|
||||||
|
http.Handle("/ws", websocket.Handler(wsHandler))
|
||||||
|
if err := http.ListenAndServe(*addr, nil); err != nil {
|
||||||
|
log.Fatal("ListenAndServe:", err)
|
||||||
|
}
|
||||||
|
}
|
19
Examples/mario_mp/makefile
Normal file
19
Examples/mario_mp/makefile
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
all: mario_mp Mario.html Clicks.html Object.html Values.html
|
||||||
|
|
||||||
|
mario_mp: *.go
|
||||||
|
go build
|
||||||
|
|
||||||
|
Mario.html: Mario.elm
|
||||||
|
elm -r elm-runtime.js Mario.elm
|
||||||
|
|
||||||
|
Clicks.html: Clicks.elm
|
||||||
|
elm -r elm-runtime.js Clicks.elm
|
||||||
|
|
||||||
|
Object.html: Object.elm
|
||||||
|
elm -r elm-runtime.js Object.elm
|
||||||
|
|
||||||
|
Values.html: Values.elm
|
||||||
|
elm -r elm-runtime.js Values.elm
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf *.html mario_mp
|
@ -5,10 +5,10 @@
|
|||||||
cat \
|
cat \
|
||||||
Guid.js\
|
Guid.js\
|
||||||
foreign/JavaScript.js\
|
foreign/JavaScript.js\
|
||||||
foreign/JSON.js\
|
|
||||||
Value.js\
|
|
||||||
List.js\
|
List.js\
|
||||||
Maybe.js\
|
Maybe.js\
|
||||||
|
foreign/JSON.js\
|
||||||
|
Value.js\
|
||||||
Char.js\
|
Char.js\
|
||||||
Graphics/Color.js\
|
Graphics/Color.js\
|
||||||
Graphics/Collage.js\
|
Graphics/Collage.js\
|
||||||
@ -29,4 +29,5 @@ cat \
|
|||||||
Dict.js\
|
Dict.js\
|
||||||
Set.js\
|
Set.js\
|
||||||
Automaton.js\
|
Automaton.js\
|
||||||
|
Signal/WebSocket.js\
|
||||||
> ../elm/elm-runtime.js
|
> ../elm/elm-runtime.js
|
||||||
|
@ -104,7 +104,12 @@ Elm.JSON = function() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
function fromJSString(str) {
|
function fromJSString(str) {
|
||||||
var obj = JSjson.parse(str);
|
var obj;
|
||||||
|
try {
|
||||||
|
obj = JSjson.parse(str);
|
||||||
|
} catch (e) {
|
||||||
|
return Elm.Maybe.Nothing;
|
||||||
|
}
|
||||||
function toValue(v) {
|
function toValue(v) {
|
||||||
switch (typeof v) {
|
switch (typeof v) {
|
||||||
case 'string' : return [ "JsonString", JS.castJSStringToString(v) ];
|
case 'string' : return [ "JsonString", JS.castJSStringToString(v) ];
|
||||||
@ -122,12 +127,13 @@ Elm.JSON = function() {
|
|||||||
for (var i in obj) {
|
for (var i in obj) {
|
||||||
obj[i] = toValue(obj[i]);
|
obj[i] = toValue(obj[i]);
|
||||||
}
|
}
|
||||||
return ['JSON',obj];
|
return Elm.Maybe.Just( ['JSON',obj] );
|
||||||
}
|
}
|
||||||
return {empty : empty,
|
return {empty : empty,
|
||||||
singleton : singleton,
|
singleton : singleton,
|
||||||
insert : insert,
|
insert : insert,
|
||||||
lookup : lookup,
|
lookup : lookup,
|
||||||
|
findNumber : find("JsonNumber",0),
|
||||||
findString : find("JsonString",["Nil"]),
|
findString : find("JsonString",["Nil"]),
|
||||||
findObject : find("JsonObject", empty ),
|
findObject : find("JsonObject", empty ),
|
||||||
findArray : find("JsonArray" ,["Nil"]),
|
findArray : find("JsonArray" ,["Nil"]),
|
||||||
|
@ -125,7 +125,7 @@ json = prefix "JSON"
|
|||||||
, "JsonObject" -: jsonObject ==> jsonValue
|
, "JsonObject" -: jsonObject ==> jsonValue
|
||||||
, numScheme (\n -> n ==> jsonValue) "JsonNumber"
|
, numScheme (\n -> n ==> jsonValue) "JsonNumber"
|
||||||
, "toString" -: jsonObject ==> string
|
, "toString" -: jsonObject ==> string
|
||||||
, "fromString" -: string ==> jsonObject
|
, "fromString" -: string ==> maybeOf jsonObject
|
||||||
, "lookup" -: string ==> jsonObject ==> maybeOf jsonValue
|
, "lookup" -: string ==> jsonObject ==> maybeOf jsonValue
|
||||||
, "findObject" -: string ==> jsonObject ==> jsonObject
|
, "findObject" -: string ==> jsonObject ==> jsonObject
|
||||||
, "findArray" -: string ==> jsonObject ==> listOf jsonValue
|
, "findArray" -: string ==> jsonObject ==> listOf jsonValue
|
||||||
|
Loading…
Reference in New Issue
Block a user