Advertisement
ptrelford

Pacman Image Data

Sep 12th, 2013
201
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 15.49 KB | None | 0 0
  1. [<ReflectedDefinition>]
  2. module Program
  3.  
  4. open FunScript
  5. open FunScript.TypeScript
  6.  
  7. type ts = Api<"../Typings/lib.d.ts">
  8.  
  9. let cyand = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAiUlEQVQoU8WSURKAIAhE8Sh6Fc/tVfQoJdqiMDTVV4wfufAAmw3kxEHUz4pA1I8OJVjAKZZ6+XiC0ATTB/gW2mEFtlpHLqaktrQ6TxUQSRCAPX2AWPMLyM0VmPOcV8palxt6uoAMpDjfWJt+o6cr0DPDnfYjyL94NwIcYjXcR/FuYklcxrZ3OO0Ep4dJ/3dR5jcAAAAASUVORK5CYII="
  10. let oranged = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAgklEQVQoU8WS0RGAIAxDZRRYhblZBUZBsBSaUk/9kj9CXlru4g7r1FxBdsFpGwoa2NwrYIFPEIeM6QS+hQQMYC70EjzuuOlt6gT5kRGGTf0Cx5qfwJYOYIw0L6W1bg+09Al2wAcCS8Y/WjqAZhluxD/B3ghZBO6n1sadzLLEbNSg8pzXIVLvbNvPwAAAAABJRU5ErkJggg=="
  11. let pinkd = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAj0lEQVQoU8WSsRWAIAxEZRQpXITGVZzIVWxYxAJHwRfwMInxqZV0XPIvgXeuM05eUuayG73TbULQwKWZGTTwCYIJphfwLcRhAW5DLfWrXFLrNLWBKAIBbOkFxJpfQDIXYAh1XoznumRo6Q0kwE8VTLN8o6UL0ArDnfYjSF/Mg4CEaA330sxD3ApHLvUdSdsBdgNkr9L8gxYAAAAASUVORK5CYII="
  12. let redd = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAkklEQVQoU8WSvRWAIAyEZRQtXIRCV3EiVtGCRSx0FHxBD5MYn1pJl0u+/PDOVcZLY5e47PrJ6TIhaOBSzBoU8AlCE0zP4FuIwwJc25Bz9TyILbVOUwuIJAjAlp5BrPkFpOYC9H6fF+O5LjW09AIS0Az7jUuQN1q6AC0z3Gk/gvTF3AhwiNYQ52Ju4pI4fKljOG0DA3tp97vN6C8AAAAASUVORK5CYII="
  13. let pu1 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAAWElEQVQoU62SUQoAIAhD9f6HNiYYolYi9VfzuXIxDRYbI0LCTHsfe3ldi3BgRRUY9Rnku1Rupf4NgiPeVjVU7STckphBceSvrHHtNPI21HWz4NO3eUUAgwVpmjX/zwK8KQAAAABJRU5ErkJggg=="
  14. let pu2 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAAW0lEQVQoU8WSwQoAIAhD9f8/2lIwdKRIl7o1e010THBESJiJXca76qnoDxFC3SD9LRpWkLnsLt4gdImtlLX/EK4iDapqr4VuI2+BauQjaOrmSz8xillDp5gQrS054jv/0fkNVAAAAABJRU5ErkJggg=="
  15. let pd1 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAAXElEQVQoU62SUQoAIAhD9f6HNgyMWpMs6k/XU5mqwDMTw5yq6JwbAfucwR2qAFHAu75BN11Gt6+Qz54VpMJsMV3BaS9UR8txkUzfLC9DUY0BYbOPGfpyU3g2WdwAOvU1/9KZsT4AAAAASUVORK5CYII="
  16. let pd2 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAAU0lEQVQoU62SUQoAIAhD9f6HNgwUGw4s6q/pc6KqwDMTQ01VtGr56ZIZvKEJEAXc9Q26cUm3r5D3zgrywHeoG3ldJrZIRz6C0I1BoR83FTBCeHsLIlw7/wOkQycAAAAASUVORK5CYII="
  17. let pl1 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAAVUlEQVQoU62S2woAIAhD9f8/2jAwvGRMyDfF49iQKZUISZ4xE/vZaW7LHbwhBLADqjpSUjBAdglRDQa9hxfcQi+vf5RGnpDlkB4KlMgR0N6pBIH83gIPFCb/N+MLCwAAAABJRU5ErkJggg=="
  18. let pl2 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAAUklEQVQoU52SUQoAIAhD3f0PbRQoZgnT/hyttYeQdFRFswYIoubD73JlPibGYA/s1Jmpk+JpDIinWxbiXP3iQslCwbhTxzhHbsWZNFsnCkTevQW2bCb/VRTuVwAAAABJRU5ErkJggg=="
  19. let pr1 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAAWElEQVQoU52S4Q4AIASE3fs/tKalSTHyL/O5CyAXzMQ+BxBsbj9exRE8oQqgDUS1BalNVFSuP2WQL94WIygCBEzttZWOvbz2VBnGtLXg1sgV/L8I679yewN9sScO5wcxLQAAAABJRU5ErkJggg=="
  20. let pr2 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAAVElEQVQoU62SWwoAIAgE9f6HNgqU3BK2R3+J48KoCjwzMaypis61+OyaK3hADOADeuoddJISaQy0iKggbEz2viah7mVPTNq7cp/ApLmcdFPVdaDJBnWdJwjk629HAAAAAElFTkSuQmCC"
  21. let blue = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAeklEQVQoU62S0Q3AIAhEyyi6UcfoRB2jG+koNkeCoVcaTaw/huMeEkS24KTUmpdrFWHbQ2CAzb5AB0eQFTFYwVnIw/+B5by0cD52vTmGhnaF25wBAb/A6HsibR0ctch5fRHi1zCigvCut4oR+wnbhrBmsZr9DlqCQfbcnfZjDyiZqCEAAAAASUVORK5CYII="
  22.  
  23. let maze = "\
  24. ##/------------7/------------7##,\
  25. ##|............|!............|##,\
  26. ##|./__7./___7.|!./___7./__7.|##,\
  27. ##|o|  !.|   !.|!.|   !.|  !o|##,\
  28. ##|.L--J.L---J.LJ.L---J.L--J.|##,\
  29. ##|..........................|##,\
  30. ##|./__7./7./______7./7./__7.|##,\
  31. ##|.L--J.|!.L--7/--J.|!.L--J.|##,\
  32. ##|......|!....|!....|!......|##,\
  33. ##L____7.|L__7 |! /__J!./____J##,\
  34. #######!.|/--J LJ L--7!.|#######,\
  35. #######!.|!          |!.|#######,\
  36. #######!.|! /__==__7 |!.|#######,\
  37. -------J.LJ |      ! LJ.L-------,\
  38. ########.   | **** !   .########,\
  39. _______7./7 |      ! /7./_______,\
  40. #######!.|! L______J |!.|#######,\
  41. #######!.|!          |!.|#######,\
  42. #######!.|! /______7 |!.|#######,\
  43. ##/----J.LJ L--7/--J LJ.L----7##,\
  44. ##|............|!............|##,\
  45. ##|./__7./___7.|!./___7./__7.|##,\
  46. ##|.L-7!.L---J.LJ.L---J.|/-J.|##,\
  47. ##|o..|!.......<>.......|!..o|##,\
  48. ##L_7.|!./7./______7./7.|!./_J##,\
  49. ##/-J.LJ.|!.L--7/--J.|!.LJ.L-7##,\
  50. ##|......|!....|!....|!......|##,\
  51. ##|./____JL__7.|!./__JL____7.|##,\
  52. ##|.L--------J.LJ.L--------J.|##,\
  53. ##|..........................|##,\
  54. ##L--------------------------J##".Split(',')
  55.  
  56. let pills = maze |> Array.map (fun line -> line.ToCharArray() |> Array.map (fun c -> c))
  57.  
  58. let tl =    [|0b00000000;0b00000000;0b00000000;0b00000000;0b00000011;0b00000100;0b00001000;0b00001000|]
  59. let top =   [|0b00000000;0b00000000;0b00000000;0b00000000;0b11111111;0b00000000;0b00000000;0b00000000|]
  60. let tr =    [|0b00000000;0b00000000;0b00000000;0b00000000;0b11000000;0b00100000;0b00010000;0b00010000|]
  61. let left =  [|0b00001000;0b00001000;0b00001000;0b00001000;0b00001000;0b00001000;0b00001000;0b00001000|]
  62. let blank = [|0b00000000;0b00000000;0b00000000;0b00000000;0b00000000;0b00000000;0b00000000;0b00000000|]
  63. let right = [|0b00010000;0b00010000;0b00010000;0b00010000;0b00010000;0b00010000;0b00010000;0b00010000|]
  64. let bl =    [|0b00001000;0b00001000;0b00000100;0b00000011;0b00000000;0b00000000;0b00000000;0b00000000|]
  65. let bottom =[|0b00000000;0b00000000;0b00000000;0b11111111;0b00000000;0b00000000;0b00000000;0b00000000|]
  66. let br =    [|0b00010000;0b00010000;0b00100000;0b11000000;0b00000000;0b00000000;0b00000000;0b00000000|]
  67. let door =  [|0b00000000;0b00000000;0b00000000;0b00000000;0b11111111;0b00000000;0b00000000;0b00000000|]
  68. let pill =  [|0b00000000;0b00000000;0b00000000;0b00011000;0b00011000;0b00000000;0b00000000;0b00000000|]
  69. let power = [|0b00000000;0b00011000;0b00111100;0b01111110;0b01111110;0b00111100;0b00011000;0b00000000|]
  70.  
  71. type Brush = Blue | Yellow
  72.  
  73. let toTile c =
  74.     match c with  
  75.     | '=' -> door, Blue
  76.     | '_' -> top, Blue
  77.     | '|' -> left, Blue
  78.     | '!' -> right, Blue
  79.     | '/' -> tl, Blue
  80.     | '7' -> tr, Blue
  81.     | 'L' -> bl, Blue
  82.     | 'J' -> br, Blue
  83.     | '-' -> bottom, Blue
  84.     | '.' -> pill, Yellow
  85.     | 'o' -> power, Yellow
  86.     | _ -> blank, Blue
  87.  
  88. let isWall x=
  89.     match x with
  90.     | '_' | '|' | '!' | '/' | '7' | 'L' | 'J' | '-' | '*' -> true
  91.     | _ -> false
  92.  
  93. let tileAt (x,y) =
  94.     if x < 0 then ' '
  95.     elif x > 30 then ' '
  96.     else maze.[y].[x]
  97.        
  98. let isWallAt (x,y) = tileAt(x,y) |> isWall
  99.  
  100. [<JSEmit("return {0} & {1};")>]
  101. let BitwiseAnd(a:int,b:int) : int = failwith "never"
  102.  
  103. let draw f (lines:int[]) =
  104.     let width = 8  
  105.     lines |> Array.iteri (fun y line ->
  106.         for x = 0 to width-1 do
  107.             let bit = (1 <<< (width - 1 - x))
  108.             let pattern = BitwiseAnd(line,bit)
  109.             if pattern <> 0 then f (x,y)
  110.     )
  111.  
  112. let createImage data =
  113.     let image = unbox<ts.HTMLImageElement>(ts.document.createElement("image"))  
  114.     image.src <- data
  115.     unbox<ts.HTMLElement>(image)
  116.  
  117. type Plotter(context:ts.CanvasRenderingContext2D) =
  118.     member __.createBrush(r,g,b,a) =
  119.         let id = context.createImageData(float 1,float 1)
  120.         let d = id.data
  121.         d.[0] <- float r; d.[1] <- float g; d.[2] <- float b; d.[3] <- float a
  122.         id
  123.     member __.plot(brush,x,y) =
  124.         context.putImageData(brush, float x, float y)          
  125.  
  126. let createBackground () =
  127.     let background = unbox<ts.HTMLCanvasElement>(ts.document.createElement("canvas"))  
  128.     background.width <- 256.
  129.     background.height <- 256.    
  130.     let context = background.getContext("2d")
  131.     context.fillStyle <- "rgb(0,0,0)"
  132.     context.fillRect (0., 0. , 256., 256.);
  133.     let plotter = Plotter(context)
  134.     let blue = plotter.createBrush (63,63,255,255)
  135.     let yellow = plotter.createBrush (255,255,0,255)
  136.     let lines = maze      
  137.     for y = 0 to lines.Length-1 do
  138.         let line = lines.[y]
  139.         for x = 0 to line.Length-1 do
  140.             let c = line.[x]
  141.             let tile, color = toTile c                
  142.             let brush = match color with Blue -> blue | Yellow -> yellow        
  143.             let f (x',y') = plotter.plot(brush, x*8 + x', y*8 + y')
  144.             draw f tile
  145.     unbox<ts.HTMLElement>(background)
  146.  
  147. let clearCell background (x,y) =    
  148.     let background = unbox<ts.HTMLCanvasElement>(background)
  149.     let context = background.getContext("2d")
  150.     let plotter = Plotter(context)
  151.     let black = plotter.createBrush (0,0,0,255)
  152.     for y' = 0 to 7 do
  153.        for x' = 0 to 7 do                  
  154.             plotter.plot(black, x*8 + x', y*8 + y')        
  155.  
  156. let noWall (x,y) (ex,ey) =
  157.     let bx, by = (x+6+ex) >>> 3, (y+6+ey) >>> 3
  158.     isWallAt (bx,by) |> not
  159.  
  160. let verticallyAligned (x,y) =  (x % 8) = 5
  161. let horizontallyAligned (x,y) = (y % 8) = 5
  162. let isAligned n = (n % 8) = 5
  163.  
  164. let canGoUp (x,y) = isAligned x && noWall (x,y) (0,-4)
  165. let canGoDown (x,y) = isAligned x && noWall (x,y) (0,5)
  166. let canGoLeft (x,y) = isAligned y && noWall (x,y) (-4,0)
  167. let canGoRight (x,y) = isAligned y && noWall (x,y) (5,0)
  168.  
  169. let wrap (x,y) (dx,dy) =
  170.     let x =
  171.         if dx = -1 && x = 0 then 30 * 8
  172.         elif dx = 1  && x = 30 *8 then 0
  173.         else x
  174.     x + dx, y + dy
  175.  
  176. type Ghost(image:ts.HTMLElement,x,y,v) =
  177.     let mutable x' = x
  178.    let mutable y' = y
  179.     let mutable v' = v    
  180.    member val Image = image
  181.    member __.X = x'
  182.     member __.Y = y'
  183.    member __.V = v'
  184.     member ghost.Reset() =
  185.         x' <- x
  186.        y' <- y
  187.     member ghost.Move(v) =
  188.         v' <- v        
  189.        let dx,dy = v
  190.        let x,y = wrap (x',y') (dx,dy)
  191.        x' <- x
  192.         y' <- y
  193.  
  194. let chooseDirection (ghost:Ghost) =
  195.    let x,y = ghost.X, ghost.Y
  196.    let dx,dy = ghost.V
  197.    let isBackwards (a,b) =
  198.        (a <> 0 && a = -dx) || (b <> 0 && b = -dy)
  199.    let directions =
  200.        [|canGoLeft(x,y),(-1,0)
  201.          canGoDown(x,y),(0,1)
  202.          canGoRight(x,y),(1,0)
  203.          canGoUp(x,y),(0,-1)|]
  204.        |> Array.filter fst
  205.        |> Array.map snd
  206.        |> Array.filter (not << isBackwards)        
  207.    let i = int (ts.Math.floor(ts.Math.random() * float directions.Length))
  208.    let dx,dy = directions.[i]
  209.    dx,dy
  210.  
  211. let createGhosts context =
  212.    [|
  213.         redd, (16, 11), (1,0)
  214.         cyand, (14, 15), (1,0)
  215.         pinkd, (16, 13), (0,-1)
  216.         oranged, (18, 15), (-1,0)
  217.    |]
  218.    |> Array.map (fun (data,(x,y),v) ->
  219.        let image = createImage data
  220.        Ghost(image, (x*8)-7, (y*8)-3, v)
  221.    )
  222.  
  223. type Keys() =
  224.    let leftCode, upCode, rightCode, downCode = 90(*z*), 81(*q*), 88(*x*), 65(*a*)
  225.    let mutable isLeft = false
  226.    let mutable isUp = false
  227.    let mutable isDown = false
  228.    let mutable isRight = false
  229.    let update (e,pressed) =
  230.        let e = (unbox<ts.KeyboardEventExtensions>(e))
  231.        let keyCode = int e.keyCode        
  232.        if keyCode = leftCode then isLeft <- pressed
  233.        if keyCode = rightCode then isRight <- pressed
  234.        if keyCode = upCode then isUp <- pressed
  235.        if keyCode = downCode then isDown <- pressed
  236.    member keys.Update (e,pressed) = update(e,pressed)      
  237.    member keys.LeftPressed = isLeft
  238.    member keys.RightPressed = isRight
  239.    member keys.UpPressed = isUp
  240.    member keys.DownPressed = isDown
  241.  
  242. let main() =  
  243.    let keys = Keys()
  244.    ts.addEventListener("keydown", unbox<ts.EventListener>(fun e -> keys.Update(e, true)))
  245.    ts.addEventListener("keyup", unbox<ts.EventListener>(fun e ->keys.Update(e,false)))  
  246.  
  247.    let canvas = unbox<ts.HTMLCanvasElement>(ts.document.getElementById("canvas"))
  248.    canvas.width <- 256.
  249.    canvas.height <- 256.    
  250.    let context = canvas.getContext("2d")
  251.    context.fillStyle <- "rgb(0,0,0)"
  252.    context.fillRect (0., 0. , 256., 256.);
  253.  
  254.    let background = createBackground()
  255.    let ghosts = createGhosts(context)
  256.    let pu1, pu2 = createImage pu1, createImage pu2
  257.    let pd1, pd2 = createImage pd1, createImage pd2
  258.    let pl1, pl2 = createImage pl1, createImage pl2
  259.    let pr1, pr2 = createImage pr1, createImage pr2
  260.    let blue = createImage blue
  261.  
  262.    let score = ref 0
  263.    let flashCountdown = ref 0
  264.    let powerCountdown = ref 0
  265.    let x, y = ref (16 * 8 - 7), ref (23 * 8 - 3)
  266.    let v = ref (0,0)
  267.    let lastp = ref pr1
  268.  
  269.    let moveGhosts () =
  270.        ghosts |> Array.iter (fun ghost ->
  271.            let v = chooseDirection ghost
  272.            ghost.Move(v)
  273.        )
  274.  
  275.    let movePacman () =      
  276.        v :=
  277.            if keys.LeftPressed && canGoLeft(!x,!y) then (-1,0)
  278.            elif keys.RightPressed && canGoRight(!x,!y) then (1,0)
  279.            elif keys.UpPressed && canGoUp(!x,!y) then (0,-1)
  280.            elif keys.DownPressed && canGoDown(!x,!y) then (0,1)
  281.            else (0,0)        
  282.        let x',y' = wrap (!x,!y) !v
  283.        x := x'
  284.         y := y'
  285.  
  286.    let eatPills () =
  287.        let tx = int (ts.Math.floor(float ((!x+6)/8)))
  288.        let ty = int (ts.Math.floor(float ((!y+6)/8)))      
  289.        let c = pills.[ty].[tx]
  290.        if c = '.' then
  291.            pills.[ty].[tx] <- ' '
  292.            clearCell background (tx,ty)
  293.            score := !score + 10
  294.        if c = 'o' then          
  295.            pills.[ty].[tx] <- ' '
  296.            clearCell background (tx,ty)
  297.            score := !score + 50
  298.            powerCountdown := 250
  299.  
  300.    let touchingGhosts () =
  301.        let px, py = !x, !y
  302.        ghosts |> Array.filter (fun ghost ->
  303.            let x,y = ghost.X, ghost.Y
  304.            ((px >= x && px < x + 13) ||
  305.             (x < px + 13 && x >= px)) &&
  306.            ((py >= y && py < y + 13) ||
  307.             (y < py + 13 && y >= py))
  308.        )
  309.  
  310.    let collisionDetection () =
  311.        let touched = touchingGhosts ()
  312.        if touched.Length > 0
  313.        then
  314.            if !powerCountdown > 0 then
  315.                touched |> Array.iter (fun ghost ->
  316.                    ghost.Reset()
  317.                    score := !score + 100
  318.                )
  319.            else
  320.                flashCountdown := 30
  321.        if !flashCountdown > 0
  322.        then flashCountdown := !flashCountdown - 1
  323.    
  324.    let logic () =
  325.        moveGhosts()
  326.        movePacman()
  327.        eatPills ()
  328.        if !powerCountdown > 0 then powerCountdown := !powerCountdown - 1
  329.        collisionDetection()
  330.  
  331.    let getPacmanImage () =
  332.        let p1, p2 =
  333.            match !v with
  334.            | -1,  0 -> pl1, pl2
  335.            |  1,  0 -> pr1, pr2
  336.            |  0, -1 -> pu1, pu2
  337.            |  0,  1 -> pd1, pd2
  338.            |  _,  _ -> !lastp, !lastp
  339.        let x' = int (ts.Math.floor(float (!x/6)))
  340.         let y' = int (ts.Math.floor(float (!y/6)))
  341.        if (x' + y') % 2 = 0 then p1 else p2
  342.  
  343.    let renderPacman () =
  344.        let p = getPacmanImage()
  345.        lastp := p
  346.        if !flashCountdown % 2 = 0
  347.        then context.drawImage(p, float !x, float !y)
  348.  
  349.    let renderGhosts () =
  350.        ghosts |> Array.iter (fun ghost ->
  351.            let image =
  352.                if !powerCountdown = 0
  353.                then ghost.Image
  354.                else blue
  355.            context.drawImage(image, float ghost.X, float ghost.Y)
  356.        )
  357.  
  358.    let renderScore () =
  359.        context.fillStyle <- "white"
  360.        context.font <- "bold 8px";
  361.        context.fillText("Score " + (!score).ToString(), 0., 255.)
  362.  
  363.    let render () =
  364.        context.drawImage(background, 0., 0.)
  365.        renderScore ()
  366.        renderPacman()
  367.        renderGhosts ()
  368.  
  369.    let rec update () =
  370.        render ()
  371.        logic ()
  372.        ts.setTimeout(update, 1000. / 60.) |> ignore
  373.  
  374.    update()
  375.  
  376. do Runtime.Run(directory="Web", components=Interop.Components.all)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement