4 people like it.
Like the snippet!
Learning Flappy Bird in F# with Nephew
Learning F# with my 11 year old nephew, he is loving it, swapping out assets and creating new ones, adjusting gravity to what feels right to him and putting in very basic collision detection. Going to keep expanding on it over the year.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
|
#if INTERACTIVE
#I @"../packages/MonoGame.Framework.WindowsDX.3.4.0.459/lib/net40/"
//#I @"../packages/MonoGame.Framework.WindowsGL.3.4.0.459/lib/net40/"
#r "MonoGame.Framework.dll"
#endif
/// Bird type
type Bird = { X:float; Y:float; VY:float; mutable IsAlive:bool; mutable Rectangle:Microsoft.Xna.Framework.Rectangle }
/// Respond to flap command
let flap (bird:Bird) = { bird with VY = -2.11}
/// Applies gravity to bird
let gravity (bird:Bird) = { bird with VY = bird.VY + 0.1 }
/// Applies physics to bird
let physics (bird:Bird) = { bird with Y = bird.Y + bird.VY }
/// Updates bird with gravity & physics
let update = gravity >> physics
/// Generates the level's tube positions
let generateLevel n =
let rand = System.Random()
[for i in 1..n -> 50+(i*150), 32+rand.Next(160)]
open System.IO
open Microsoft.Xna.Framework
open Microsoft.Xna.Framework.Graphics
open Microsoft.Xna.Framework.Input
let loadImage (device:GraphicsDevice) file =
let path = Path.Combine(__SOURCE_DIRECTORY__, file)
use stream = File.OpenRead(path)
let texture = Texture2D.FromStream(device, stream)
let textureData = Array.create<Color> (texture.Width * texture.Height) Color.Transparent
texture.GetData(textureData)
texture
type FlappyBird() as this =
inherit Game()
do this.Window.Title <- "Flappy Callum"
let graphics = new GraphicsDeviceManager(this)
do graphics.PreferredBackBufferWidth <- 288
do graphics.PreferredBackBufferHeight <- 440
let mutable spriteBatch : SpriteBatch = null
let mutable bg : Texture2D = null
let mutable ground : Texture2D = null
let mutable tube1 : Texture2D = null
let mutable tube2 : Texture2D = null
let mutable bird_sing : Texture2D = null
let mutable gameover : Texture2D = null
let mutable lastKeyState = KeyboardState()
let mutable lastMouseState = MouseState()
let level = generateLevel 10
let mutable flappy = { X = 30.0; Y = 150.0; VY = 0.0; IsAlive=true; Rectangle = Microsoft.Xna.Framework.Rectangle()}
let flapMe () = if flappy.IsAlive then flappy <- flap flappy
let mutable scroll = 0
override this.LoadContent() =
spriteBatch <- new SpriteBatch(this.GraphicsDevice)
let load = loadImage this.GraphicsDevice
bg <- load "bg.png"
ground <- load "beartraps2.png"
tube1 <- load "tube1.png"
tube2 <- load "tube2.png"
gameover <- load "gameover.png"
bird_sing <- load "bird_sing.png"
flappy.Rectangle <- bird_sing.Bounds
override this.Update(gameTime) =
let currentKeyState = Keyboard.GetState()
let currentMouseState = Mouse.GetState()
let isKeyPressedSinceLastFrame key =
currentKeyState.IsKeyDown(key) && lastKeyState.IsKeyUp(key)
let isMouseClicked () =
currentMouseState.LeftButton = ButtonState.Pressed &&
lastMouseState.LeftButton = ButtonState.Released
if flappy.IsAlive
then
scroll <- scroll - 1
if isKeyPressedSinceLastFrame Keys.Space || isMouseClicked ()
then flapMe ()
flappy <- update flappy
lastKeyState <- currentKeyState
lastMouseState <- currentMouseState
else
if isKeyPressedSinceLastFrame Keys.Space || isMouseClicked ()
then
scroll <- 0
flappy <- { X = 30.0; Y = 150.0; VY = 0.0; IsAlive=true; Rectangle = Microsoft.Xna.Framework.Rectangle()}
override this.Draw(gameTime) =
this.GraphicsDevice.Clear Color.White
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied)
let draw (texture:Texture2D) (x,y) =
spriteBatch.Draw(texture, Rectangle(x,y,texture.Width,texture.Height), Color.White)
draw bg (0,0)
flappy.Rectangle <- Rectangle(int flappy.X, int flappy.Y, bird_sing.Width, bird_sing.Height)
draw bird_sing (int flappy.X,int flappy.Y)
for (x,y) in level do
let x = x+scroll
draw tube1 (x,-320+y)
draw tube2 (x,y+100)
draw ground (0,360)
if flappy.Rectangle.Intersects(Rectangle(0, 360, ground.Width, ground.Height))
then
flappy.IsAlive <- false
draw gameover (-40, 150)
spriteBatch.End()
do
use game = new FlappyBird()
game.Run()
|
type Bird =
{X: float;
Y: float;
VY: float;
mutable IsAlive: bool;
mutable Rectangle: obj;}
Full name: Script.Bird
Bird type
Bird.X: float
Multiple items
val float : value:'T -> float (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.float
--------------------
type float = System.Double
Full name: Microsoft.FSharp.Core.float
--------------------
type float<'Measure> = float
Full name: Microsoft.FSharp.Core.float<_>
Bird.Y: float
Bird.VY: float
Bird.IsAlive: bool
type bool = System.Boolean
Full name: Microsoft.FSharp.Core.bool
Bird.Rectangle: obj
namespace Microsoft
val flap : bird:Bird -> Bird
Full name: Script.flap
Respond to flap command
val bird : Bird
val gravity : bird:Bird -> Bird
Full name: Script.gravity
Applies gravity to bird
val physics : bird:Bird -> Bird
Full name: Script.physics
Applies physics to bird
val update : (Bird -> Bird)
Full name: Script.update
Updates bird with gravity & physics
val generateLevel : n:int -> (int * int) list
Full name: Script.generateLevel
Generates the level's tube positions
val n : int
val rand : System.Random
namespace System
Multiple items
type Random =
new : unit -> Random + 1 overload
member Next : unit -> int + 2 overloads
member NextBytes : buffer:byte[] -> unit
member NextDouble : unit -> float
Full name: System.Random
--------------------
System.Random() : unit
System.Random(Seed: int) : unit
val i : int
System.Random.Next() : int
System.Random.Next(maxValue: int) : int
System.Random.Next(minValue: int, maxValue: int) : int
namespace System.IO
val loadImage : device:'a -> file:string -> 'b
Full name: Script.loadImage
val device : 'a
val file : string
val path : string
type Path =
static val DirectorySeparatorChar : char
static val AltDirectorySeparatorChar : char
static val VolumeSeparatorChar : char
static val InvalidPathChars : char[]
static val PathSeparator : char
static member ChangeExtension : path:string * extension:string -> string
static member Combine : [<ParamArray>] paths:string[] -> string + 3 overloads
static member GetDirectoryName : path:string -> string
static member GetExtension : path:string -> string
static member GetFileName : path:string -> string
...
Full name: System.IO.Path
Path.Combine([<System.ParamArray>] paths: string []) : string
Path.Combine(path1: string, path2: string) : string
Path.Combine(path1: string, path2: string, path3: string) : string
Path.Combine(path1: string, path2: string, path3: string, path4: string) : string
val stream : FileStream
type File =
static member AppendAllLines : path:string * contents:IEnumerable<string> -> unit + 1 overload
static member AppendAllText : path:string * contents:string -> unit + 1 overload
static member AppendText : path:string -> StreamWriter
static member Copy : sourceFileName:string * destFileName:string -> unit + 1 overload
static member Create : path:string -> FileStream + 3 overloads
static member CreateText : path:string -> StreamWriter
static member Decrypt : path:string -> unit
static member Delete : path:string -> unit
static member Encrypt : path:string -> unit
static member Exists : path:string -> bool
...
Full name: System.IO.File
File.OpenRead(path: string) : FileStream
val texture : 'b
val textureData : obj
module Array
from Microsoft.FSharp.Collections
val create : count:int -> value:'T -> 'T []
Full name: Microsoft.FSharp.Collections.Array.create
Multiple items
type FlappyBird =
inherit obj
new : unit -> FlappyBird
override Draw : gameTime:'a -> 'b
override LoadContent : unit -> 'a
override Update : gameTime:'a -> 'b
Full name: Script.FlappyBird
--------------------
new : unit -> FlappyBird
val this : FlappyBird
override FlappyBird.LoadContent : unit -> 'a
Full name: Script.FlappyBird.LoadContent
override FlappyBird.Update : gameTime:'a -> 'b
Full name: Script.FlappyBird.Update
override FlappyBird.Draw : gameTime:'a -> 'b
Full name: Script.FlappyBird.Draw
Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
val game : FlappyBird
More information