elm

Writing A Word Memory Game In Elm - Part 1: Setting Up an Elm Application With Parcel

mickeyvip

Mickey

Posted on March 20, 2019

Writing A Word Memory Game In Elm - Part 1: Setting Up an Elm Application With Parcel

This is part 1 of the series "Writing A Word Memory Game In Elm", find:


Preface

One of the most effective ways to learn is by doing. I was looking for a project to improve my Elm skills and a friend gave me an excellent idea -- to write a word memory game.

Note: this series of posts reflects my personal learning experience, any constructive feedback is welcome.

The Memory Game

There is a sentence which the player can read. Several words are then taken out and the player must reconstruct the sentence from memory.

For example, the sentence is:

If you want something done right, you have to do it yourself.

And with several words removed:

If --- want something ---- right, you ---- to do it yourself."

Game in action

The game is pretty simple, but there are many ways it can be be extended:

  • The missing words can be presented to the user in-place (as a dropdown), or near the sentence as a list
  • Each time the player guesses the correct word, they can be informed straight away or find out the result only when all the words are used
  • At the beginning of the game the sentence is visible to the player for several seconds only
  • Etc

Starting the Project

To make the development cycle easier I chose to use Parcel bundler, which supports Elm out of the box since v1.10.0 and HMR since v1.11.0.

Let's create a project folder, for example word-memory-game, cd into it and initialise the NPM project:

$ npm init -y
Enter fullscreen mode Exit fullscreen mode

The -y option will accept all defaults and create package.json file.

Let's install the Parcel bundler locally (it can also be installed globally):

$ npm i -D parcel-bundler
Enter fullscreen mode Exit fullscreen mode

Following Parcel's Getting Started let's add index.html:

<!doctype html>
<html>
<body>
    <script src="./index.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

and index.js:

console.log('Words Memory Game started');
Enter fullscreen mode Exit fullscreen mode

Also let's add the following lines to the scripts section of package.json:

"scripts": {
    "dev": "parcel index.html",
    "build": "parcel build index.html"
}
Enter fullscreen mode Exit fullscreen mode

In order to start the development server let's run:

$ npm run dev
Enter fullscreen mode Exit fullscreen mode

and navigate to http://localhost:1234

Parcel bundler has loaded our application

In order to host our Elm application in a page let's add

<div id="app"></div>
Enter fullscreen mode Exit fullscreen mode

to index.html:

<!-- index.html -->

<!doctype html>
<html>
<body>
    <div id="app"></div>
    <script src="./index.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Let's create src folder and add Main.elm to it:

module Main exposing (main)

import Html

main =
    Html.text "Words Memory Game"
Enter fullscreen mode Exit fullscreen mode

and change index.js to:

import { Elm } from "./src/Main.elm";

Elm.Main.init({
  node: document.getElementById("app")
});
Enter fullscreen mode Exit fullscreen mode

After we save all the files, Parcel will automatically initialise an Elm project (including creating elm.json file), install needed dependencies and reload. We can also reload the page manually to clear all the previous errors from the console.

Main.elm loaded and working

Now let's make our Elm skeleton a real Elm application by adding Msg, Model, view and update, as well as updating main:

module Main exposing (main)

import Browser
import Html exposing (Html)


type alias Model =
    { sentence : String
    }


initialModel : Model
initialModel =
    { sentence = "The pen is mightier than the sword" }


type Msg
    = NoOp


update : Msg -> Model -> Model
update msg model =
    case msg of
        NoOp ->
            model


view : Model -> Html msg
view model =
    Html.text model.sentence


main : Program () Model Msg
main =
    Browser.sandbox
        { init = initialModel
        , update = update
        , view = view
        }

Enter fullscreen mode Exit fullscreen mode

Great! We have our basic "Hello, World!".

I personally like my applications to look nice, so let's add the popular Bulma CSS framework in our index.html (or we can install it locally and import it) and a meta tag that Bulma recommends:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <title>Words Memory Game</title>
        <link
            rel="stylesheet"
            href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css"
        />
    </head>
    <body>
        <div id="app" class="section"></div>
        <script src="./index.js"></script>
    </body>
</html>

Enter fullscreen mode Exit fullscreen mode

Now in Main.elm let's update our view function to show a title and a sentence in a nice box:

view : Model -> Html msg
view model =
    main_ [ class "section" ]
        [ div [ class "container" ]
            [ viewTitle
            , div [ class "box" ]
                [ p
                    [ class "has-text-centered" ]
                    [ text model.sentence ]
                ]
            ]
        ]


viewTitle : Html msg
viewTitle =
    h1 [ class "title has-text-centered" ]
        [ text "Words Memory Game" ]


Enter fullscreen mode Exit fullscreen mode

Don't forget to import Html and Html.Attributes functions:

import Html exposing (Html, div, h1, main_, p, text)
import Html.Attributes exposing (class)

Enter fullscreen mode Exit fullscreen mode

Now our application looks nicer:

Nice looking application

Another touch that I want to add to our game is the ability to show pretty icons. Therefore let's add a link to Font Awesome web font in our index.html:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <title>Words Memory Game</title>
        <link
            rel="stylesheet"
            href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css"
        />
        <link
            rel="stylesheet"
            href="https://use.fontawesome.com/releases/v5.7.1/css/regular.css"
            integrity="sha384-IG162Tfx2WTn//TRUi9ahZHsz47lNKzYOp0b6Vv8qltVlPkub2yj9TVwzNck6GEF"
            crossorigin="anonymous"
        />
        <link
            rel="stylesheet"
            href="https://use.fontawesome.com/releases/v5.7.1/css/fontawesome.css"
            integrity="sha384-4aon80D8rXCGx9ayDt85LbyUHeMWd3UiBaWliBlJ53yzm9hqN21A+o1pqoyK04h+"
            crossorigin="anonymous"
        />
    </head>
    <body>
        <div id="app" class="section"></div>
        <script src="./index.js"></script>
    </body>
</html>

Enter fullscreen mode Exit fullscreen mode

Now we are all set up for the next steps, read about them in the upcoming posts.

The current progress is saved in the repo under a Tag v0.0: https://github.com/mickeyvip/words-memory-game/tree/v0.0.

💖 💪 🙅 🚩
mickeyvip
Mickey

Posted on March 20, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related