Skip to content
This repository was archived by the owner on Feb 9, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion assets/elm/Main.elm
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,11 @@ playersListItem player =
player.username
else
Maybe.withDefault "" player.displayName

playerLink =
"players/" ++ (toString player.id)
in
li [ class "player-item list-group-item" ]
[ strong [] [ text displayName ]
[ strong [] [ a [ href playerLink ] [ text displayName ] ]
, span [ class "badge" ] [ text (toString player.score) ]
]
196 changes: 111 additions & 85 deletions assets/elm/Platformer.elm
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,25 @@ main =
-- MODEL


type Direction
= Left
| Right


type GameState
= StartScreen
| Playing
| Success
| GameOver


type alias Gameplay =
{ gameId : Int
, playerId : Int
, playerScore : Int
}


type alias Player =
{ displayName : Maybe String
, id : Int
Expand All @@ -55,36 +67,38 @@ type alias Player =


type alias Model =
{ errors : String
, gameId : Int
, gameState : GameState
{ characterDirection : Direction
, characterPositionX : Int
, characterPositionY : Int
, errors : String
, gameId : Int
, gameplays : List Gameplay
, gameState : GameState
, itemPositionX : Int
, itemPositionY : Int
, itemsCollected : Int
, phxSocket : Phoenix.Socket.Socket Msg
, playersList : List Player
, playerScore : Int
, playerScores : List Score
, timeRemaining : Int
}


initialModel : Flags -> Model
initialModel flags =
{ errors = ""
, gameId = 1
, gameState = StartScreen
{ characterDirection = Right
, characterPositionX = 50
, characterPositionY = 300
, errors = ""
, gameId = 1
, gameplays = []
, gameState = StartScreen
, itemPositionX = 150
, itemPositionY = 300
, itemsCollected = 0
, phxSocket = initialSocketJoin flags
, playersList = []
, playerScore = 0
, playerScores = []
, timeRemaining = 10
}

Expand All @@ -100,7 +114,7 @@ initialSocket flags =
in
Phoenix.Socket.init prodSocketServer
|> Phoenix.Socket.withDebug
|> Phoenix.Socket.on "shout" "score:platformer" SendScore
|> Phoenix.Socket.on "save_score" "score:platformer" SaveScore
|> Phoenix.Socket.on "save_score" "score:platformer" ReceiveScoreChanges
|> Phoenix.Socket.join initialChannel

Expand All @@ -124,7 +138,12 @@ initialSocketCommand flags =

init : Flags -> ( Model, Cmd Msg )
init flags =
( initialModel flags, Cmd.map PhoenixMsg (initialSocketCommand flags) )
( initialModel flags
, Cmd.batch
[ fetchPlayersList
, Cmd.map PhoenixMsg (initialSocketCommand flags)
]
)



Expand Down Expand Up @@ -153,16 +172,18 @@ decodePlayer =
(Decode.field "username" Decode.string)


type alias Score =
{ gameId : Int
, playerId : Int
, playerScore : Int
anonymousPlayer : Player
anonymousPlayer =
{ displayName = Just "Anonymous User"
, id = 0
, score = 0
, username = "anonymous"
}


scoreDecoder : Decode.Decoder Score
scoreDecoder : Decode.Decoder Gameplay
scoreDecoder =
Decode.map3 Score
Decode.map3 Gameplay
(Decode.field "game_id" Decode.int)
(Decode.field "player_id" Decode.int)
(Decode.field "player_score" Decode.int)
Expand All @@ -182,9 +203,6 @@ type Msg
| SaveScore Encode.Value
| SaveScoreError Encode.Value
| SaveScoreRequest
| SendScore Encode.Value
| SendScoreError Encode.Value
| SendScoreRequest
| SetNewItemPositionX Int
| TimeUpdate Time

Expand Down Expand Up @@ -214,10 +232,11 @@ update msg model =
32 ->
if model.gameState /= Playing then
( { model
| gameState = Playing
| characterDirection = Right
, characterPositionX = 50
, playerScore = 0
, itemsCollected = 0
, gameState = Playing
, playerScore = 0
, timeRemaining = 10
}
, Cmd.none
Expand All @@ -227,13 +246,23 @@ update msg model =

37 ->
if model.gameState == Playing then
( { model | characterPositionX = model.characterPositionX - 15 }, Cmd.none )
( { model
| characterDirection = Left
, characterPositionX = model.characterPositionX - 15
}
, Cmd.none
)
else
( model, Cmd.none )

39 ->
if model.gameState == Playing then
( { model | characterPositionX = model.characterPositionX + 15 }, Cmd.none )
( { model
| characterDirection = Right
, characterPositionX = model.characterPositionX + 15
}
, Cmd.none
)
else
( model, Cmd.none )

Expand All @@ -252,7 +281,7 @@ update msg model =
ReceiveScoreChanges raw ->
case Decode.decodeValue scoreDecoder raw of
Ok scoreChange ->
( { model | playerScores = scoreChange :: model.playerScores }, Cmd.none )
( { model | gameplays = scoreChange :: model.gameplays }, Cmd.none )

Err message ->
( { model | errors = message }, Cmd.none )
Expand All @@ -261,7 +290,7 @@ update msg model =
( model, Cmd.none )

SaveScoreError message ->
Debug.log "Error saveing score over socket."
Debug.log "Error saving score over socket."
( model, Cmd.none )

SaveScoreRequest ->
Expand All @@ -282,31 +311,6 @@ update msg model =
, Cmd.map PhoenixMsg phxCmd
)

SendScore value ->
( model, Cmd.none )

SendScoreError message ->
Debug.log "Error sending score over socket."
( model, Cmd.none )

SendScoreRequest ->
let
payload =
Encode.object [ ( "player_score", Encode.int model.playerScore ) ]

phxPush =
Phoenix.Push.init "shout" "score:platformer"
|> Phoenix.Push.withPayload payload
|> Phoenix.Push.onOk SendScore
|> Phoenix.Push.onError SendScoreError

( phxSocket, phxCmd ) =
Phoenix.Socket.push phxPush model.phxSocket
in
( { model | phxSocket = phxSocket }
, Cmd.map PhoenixMsg phxCmd
)

SetNewItemPositionX newPositionX ->
( { model | itemPositionX = newPositionX }, Cmd.none )

Expand Down Expand Up @@ -363,20 +367,8 @@ view : Model -> Html Msg
view model =
div []
[ viewGame model
, viewSendScoreButton
, viewSaveScoreButton
, viewPlayerScoresIndex model
]


viewSendScoreButton : Html Msg
viewSendScoreButton =
div []
[ button
[ onClick SendScoreRequest
, Html.Attributes.class "btn btn-primary"
]
[ text "Send Score" ]
, viewGameplaysIndex model
]


Expand All @@ -391,31 +383,56 @@ viewSaveScoreButton =
]


viewPlayerScoresIndex : Model -> Html Msg
viewPlayerScoresIndex model =
if List.isEmpty model.playerScores then
viewGameplaysIndex : Model -> Html Msg
viewGameplaysIndex model =
if List.isEmpty model.gameplays then
div [] []
else
div [ Html.Attributes.class "players-index" ]
[ h1 [ Html.Attributes.class "players-section" ] [ text "Player Scores" ]
, viewPlayerScoresList model.playerScores
, viewGameplaysList model
]


viewPlayerScoresList : List Score -> Html Msg
viewPlayerScoresList scores =
viewGameplaysList : Model -> Html Msg
viewGameplaysList model =
div [ Html.Attributes.class "players-list panel panel-info" ]
[ div [ Html.Attributes.class "panel-heading" ] [ text "Leaderboard" ]
, ul [ Html.Attributes.class "list-group" ] (List.map viewPlayerScoreItem scores)
[ div [ Html.Attributes.class "panel-heading" ] [ text "Scores" ]
, ul [ Html.Attributes.class "list-group" ] (List.map (viewGameplayItem model) model.gameplays)
]


viewPlayerScoreItem : Score -> Html Msg
viewPlayerScoreItem score =
li [ Html.Attributes.class "player-item list-group-item" ]
[ strong [] [ text (toString score.playerId) ]
, span [ Html.Attributes.class "badge" ] [ text (toString score.playerScore) ]
]
viewGameplayItem : Model -> Gameplay -> Html Msg
viewGameplayItem model gameplay =
let
currentPlayer =
model.playersList
|> List.filter (\player -> player.id == gameplay.playerId)
|> List.head
|> Maybe.withDefault anonymousPlayer

displayName =
Maybe.withDefault currentPlayer.username currentPlayer.displayName
in
li [ Html.Attributes.class "player-item list-group-item" ]
[ strong [] [ text displayName ]
, span [ Html.Attributes.class "badge" ] [ text (toString gameplay.playerScore) ]
]


playersListItem : Player -> Html msg
playersListItem player =
let
displayName =
if player.displayName == Nothing then
player.username
else
Maybe.withDefault "" player.displayName
in
li [ Html.Attributes.class "player-item list-group-item" ]
[ strong [] [ text displayName ]
, span [ Html.Attributes.class "badge" ] [ text (toString player.score) ]
]


viewGame : Model -> Svg Msg
Expand Down Expand Up @@ -527,14 +544,23 @@ viewGameGround =

viewCharacter : Model -> Svg Msg
viewCharacter model =
image
[ xlinkHref "/images/character.gif"
, x (toString model.characterPositionX)
, y (toString model.characterPositionY)
, width "50"
, height "50"
]
[]
let
characterImage =
case model.characterDirection of
Left ->
"/images/character-left.gif"

Right ->
"/images/character-right.gif"
in
image
[ xlinkHref characterImage
, x (toString model.characterPositionX)
, y (toString model.characterPositionY)
, width "50"
, height "50"
]
[]


viewItem : Model -> Svg Msg
Expand Down
2 changes: 1 addition & 1 deletion assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import "phoenix_html"
// import socket from "./socket"

// Elm
const Elm = require("./elm.js");
import Elm from "./elm";

const elmContainer = document.querySelector("#elm-container");
const platformer = document.querySelector("#platformer");
Expand Down
Loading