Browse Source

First commit

Super-basic version sort of working. Need to present the different
"drawers" better, so that they fit in the screen and the parts are
easier to find.
master
commit
01f4cb7da5
22 changed files with 318 additions and 0 deletions
  1. +3
    -0
      .gitignore
  2. +32
    -0
      app/Main.elm
  3. +7
    -0
      app/Messages.elm
  4. +31
    -0
      app/Models.elm
  5. +17
    -0
      app/Ports.elm
  6. +36
    -0
      app/Routing.elm
  7. +40
    -0
      app/Update.elm
  8. +40
    -0
      app/Views.elm
  9. +14
    -0
      app/Wardrobes.elm
  10. +3
    -0
      app/assets/css/app.css
  11. +18
    -0
      app/assets/index.html
  12. +33
    -0
      app/assets/js/redrawDoll.js
  13. BIN
      app/assets/wardrobes/pixel-people/Sprite Sheet - Bottoms.png
  14. BIN
      app/assets/wardrobes/pixel-people/Sprite Sheet - Eyes.png
  15. BIN
      app/assets/wardrobes/pixel-people/Sprite Sheet - Full Body.png
  16. BIN
      app/assets/wardrobes/pixel-people/Sprite Sheet - Hair.png
  17. BIN
      app/assets/wardrobes/pixel-people/Sprite Sheet - Shoes.png
  18. BIN
      app/assets/wardrobes/pixel-people/Sprite Sheet - Skin.png
  19. BIN
      app/assets/wardrobes/pixel-people/Sprite Sheet - Tops.png
  20. +16
    -0
      brunch-config.js
  21. +17
    -0
      elm-package.json
  22. +11
    -0
      package.json

+ 3
- 0
.gitignore View File

@@ -0,0 +1,3 @@
node_modules/
elm-stuff/
public/

+ 32
- 0
app/Main.elm View File

@@ -0,0 +1,32 @@
import Navigation
import Dict

import Routing
import Messages exposing (..)
import Models exposing (Model, OutfitSelection)
import Views
import Update
import Wardrobes exposing (initialWardrobe)
import Ports exposing (redrawDoll, redrawEvent)

main : Program Never
main =
Navigation.program Routing.parser
{ init = init
, view = Views.mainApplicationView
, update = Update.update
, urlUpdate = Update.urlUpdate
, subscriptions = subscriptions
}

init : Result String Routing.Route -> (Model, Cmd Msg)
init result =
let
route = Routing.routeFromResult result
model = Model route initialWardrobe (Dict.fromList [])
in
(model, redrawDoll (redrawEvent model))

subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none

+ 7
- 0
app/Messages.elm View File

@@ -0,0 +1,7 @@
module Messages exposing (..)

import Models exposing (..)

type Msg
= Refresh
| SelectPart String (Float, Float)

+ 31
- 0
app/Models.elm View File

@@ -0,0 +1,31 @@
module Models exposing (..)

import Dict exposing (Dict)

import Routing

type alias Drawer =
{ id : String
, spriteUrl : String
}

type alias Wardrobe =
{ id : String
, name : String
, dollWidth : Int
, dollHeight : Int
, spacerWidth : Int
, spacerHeight : Int
, drawers : List Drawer
}

type alias OutfitSelection =
{ drawerCol : Int
, drawerRow : Int
}

type alias Model =
{ route : Routing.Route
, wardrobe : Wardrobe
, selectedOutfit : Dict String OutfitSelection
}

+ 17
- 0
app/Ports.elm View File

@@ -0,0 +1,17 @@
port module Ports exposing (redrawDoll, redrawEvent)

import Dict

import Models exposing (..)

type alias RedrawEvent =
{ dollCanvasId : String
, wardrobe : Wardrobe
, outfitSelections : List (String, OutfitSelection)
}

port redrawDoll : RedrawEvent -> Cmd msg

redrawEvent : Model -> RedrawEvent
redrawEvent model =
RedrawEvent "final-doll" model.wardrobe (Dict.toList model.selectedOutfit)

+ 36
- 0
app/Routing.elm View File

@@ -0,0 +1,36 @@
module Routing exposing (..)

import String
import Navigation
import UrlParser exposing (..)

type Route
= Index
-- | SectionIndex Int
-- | ItemDetail Int
| NotFoundRoute

matchers : Parser (Route -> a) a
matchers =
oneOf
[ format Index (s "")
]

hashParser : Navigation.Location -> Result String Route
hashParser location =
location.hash
|> String.dropLeft 1
|> parse identity matchers

parser : Navigation.Parser (Result String Route)
parser =
Navigation.makeParser hashParser

routeFromResult : Result String Route -> Route
routeFromResult result =
case result of
Ok route ->
route

Err string ->
NotFoundRoute

+ 40
- 0
app/Update.elm View File

@@ -0,0 +1,40 @@
module Update exposing (..)

import Dict

import Routing
import Messages exposing (..)
import Models exposing (Model, Wardrobe, OutfitSelection)
import Ports exposing (redrawDoll, redrawEvent)

urlUpdate : Result String Routing.Route -> Model -> (Model, Cmd Msg)
urlUpdate result model =
let
currentRoute =
Routing.routeFromResult result
in
({ model | route = currentRoute }, Cmd.none)

calculateOutfitSel : Wardrobe -> (Float, Float) -> OutfitSelection
calculateOutfitSel wardrobe offsets =
let
multiplierX = wardrobe.dollWidth + wardrobe.spacerWidth
multiplierY = wardrobe.dollHeight + wardrobe.spacerHeight
(offsetX, offsetY) = offsets
in
OutfitSelection (floor (offsetX / (toFloat multiplierX)))
(floor (offsetY / (toFloat multiplierY)))

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Refresh ->
(model, redrawDoll (redrawEvent model))

SelectPart drawerId offsets ->
let
initialSel = model.selectedOutfit
updatedSel = Dict.insert drawerId (calculateOutfitSel model.wardrobe offsets) initialSel
updatedModel = { model | selectedOutfit = updatedSel }
in
(updatedModel, redrawDoll (redrawEvent updatedModel))

+ 40
- 0
app/Views.elm View File

@@ -0,0 +1,40 @@
module Views exposing (..)

import List
import Json.Decode as Json exposing (..)
import Html exposing (Html, div, canvas, img, text)
import Html.Attributes exposing (id, class, width, height, src)
import Html.Events exposing (on)

import Models exposing (..)
import Messages exposing (..)

onClickWithOffsets messageFromOffsets =
on "click" (customDecoder (object2 (,) ("offsetX" := float) ("offsetY" := float)) messageFromOffsets)

drawerView : Wardrobe -> Drawer -> Html Msg
drawerView wardrobe drawer =
img [ id drawer.id
, src ("/wardrobes/" ++ wardrobe.id ++ "/" ++ drawer.spriteUrl)
, onClickWithOffsets (\offsets -> Ok (SelectPart drawer.id offsets))
] []

wardrobeView : Wardrobe -> Html Msg
wardrobeView wardrobe =
let
drawerList = List.map (\d -> drawerView wardrobe d) wardrobe.drawers
in
div []
(List.append
[ text ("Wardrobe " ++ wardrobe.name) ]
drawerList)

mainApplicationView : Model -> Html Msg
mainApplicationView model =
div []
[ canvas [ id "final-doll"
, width model.wardrobe.dollWidth
, height model.wardrobe.dollHeight
] []
, wardrobeView model.wardrobe
]

+ 14
- 0
app/Wardrobes.elm View File

@@ -0,0 +1,14 @@
module Wardrobes exposing (..)

import Models exposing (..)

initialWardrobe : Wardrobe
initialWardrobe =
Wardrobe "pixel-people" "Pixel People" 64 112 4 4
[ Drawer "skins" "Sprite Sheet - Skin.png"
, Drawer "eyes" "Sprite Sheet - Eyes.png"
, Drawer "hair" "Sprite Sheet - Hair.png"
, Drawer "tops" "Sprite Sheet - Tops.png"
, Drawer "bottoms" "Sprite Sheet - Bottoms.png"
, Drawer "shoes" "Sprite Sheet - Shoes.png"
]

+ 3
- 0
app/assets/css/app.css View File

@@ -0,0 +1,3 @@
#final-doll {
border: 3px solid black;
}

+ 18
- 0
app/assets/index.html View File

@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Doll Dresser</title>
<link rel="stylesheet" href="css/app.css" />
</head>
<body>
<header>
<div class="site-title">Doll Dresser</div>
</header>

<div id="main"></div>

<script src="js/main.js"></script>
<script src="js/redrawDoll.js"></script>
</body>
</html>

+ 33
- 0
app/assets/js/redrawDoll.js View File

@@ -0,0 +1,33 @@
var node = document.getElementById("main");
var app = Elm.Main.embed(node);

app.ports.redrawDoll.subscribe(function(evt) {
var canvas = document.getElementById(evt.dollCanvasId),
canvasContext = canvas.getContext("2d"),
multiplierX = evt.wardrobe.dollWidth + evt.wardrobe.spacerWidth,
multiplierY = evt.wardrobe.dollHeight + evt.wardrobe.spacerHeight;

canvasContext.clearRect(0, 0, canvas.width, canvas.height);

var selectionDict = {};
evt.outfitSelections.forEach(function(part) {
selectionDict[part[0]] = part[1];
});

evt.wardrobe.drawers.forEach(function(drawer) {
if (selectionDict.hasOwnProperty(drawer.id)) {
var img = document.getElementById(drawer.id),
drawerCoords = selectionDict[drawer.id];

canvasContext.drawImage(img,
multiplierX * drawerCoords.drawerCol,
multiplierY * drawerCoords.drawerRow,
evt.wardrobe.dollWidth,
evt.wardrobe.dollHeight,
0,
0,
evt.wardrobe.dollWidth,
evt.wardrobe.dollHeight);
}
});
});

BIN
app/assets/wardrobes/pixel-people/Sprite Sheet - Bottoms.png View File

Before After
Width: 1692  |  Height: 692  |  Size: 22KB

BIN
app/assets/wardrobes/pixel-people/Sprite Sheet - Eyes.png View File

Before After
Width: 1152  |  Height: 112  |  Size: 994B

BIN
app/assets/wardrobes/pixel-people/Sprite Sheet - Full Body.png View File

Before After
Width: 880  |  Height: 112  |  Size: 3.7KB

BIN
app/assets/wardrobes/pixel-people/Sprite Sheet - Hair.png View File

Before After
Width: 880  |  Height: 576  |  Size: 13KB

BIN
app/assets/wardrobes/pixel-people/Sprite Sheet - Shoes.png View File

Before After
Width: 1152  |  Height: 228  |  Size: 4.7KB

BIN
app/assets/wardrobes/pixel-people/Sprite Sheet - Skin.png View File

Before After
Width: 812  |  Height: 112  |  Size: 3.2KB

BIN
app/assets/wardrobes/pixel-people/Sprite Sheet - Tops.png View File

Before After
Width: 1560  |  Height: 1272  |  Size: 37KB

+ 16
- 0
brunch-config.js View File

@@ -0,0 +1,16 @@
module.exports = {
paths: {
public: 'public/'
},

files: {
javascripts: {joinTo: 'app.js'}
},

plugins: {
elmBrunch: {
mainModules: ['app/Main.elm'],
makeParameters: ['--warn']
}
}
};

+ 17
- 0
elm-package.json View File

@@ -0,0 +1,17 @@
{
"version": "0.0.1",
"summary": "Assembles sprites together to create a single image",
"repository": "https://github.com/emanchado/doll-dresser.git",
"license": "BSD3",
"source-directories": [
"app"
],
"exposed-modules": [],
"dependencies": {
"elm-lang/core": "4.0.1 <= v < 5.0.0",
"elm-lang/html": "1.1.0 <= v < 2.0.0",
"elm-lang/navigation": "1.0.0 <= v < 2.0.0",
"evancz/url-parser": "1.0.0 <= v < 2.0.0"
},
"elm-version": "0.17.1 <= v < 0.18.0"
}

+ 11
- 0
package.json View File

@@ -0,0 +1,11 @@
{
"scripts": {
"build": "brunch build",
"watch": "brunch watch",
"dev": "brunch watch --server"
},
"devDependencies": {
"brunch": "^2.8.2",
"elm-brunch": "^0.5.0"
}
}

Loading…
Cancel
Save