Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Isometric 2d rendering with MonoGame (XNA) and F#
open System
open Microsoft.Xna.Framework
open Microsoft.Xna.Framework.Graphics
open Microsoft.Xna.Framework.Storage
open Microsoft.Xna.Framework.Input
/// Logical type of a MapCell
type CellType =
| Empty
type MapCell(spriteBatch : SpriteBatch, cellType : CellType) =
member val Type : CellType = cellType with get, set
member val BaseTile : Texture2D list = [] with get, set
member val HeightTile : Texture2D list list = [] with get, set
member val BaseColor : Color = Color.White with get, set
member this.AddBaseTile (tile : Texture2D) =
this.BaseTile <- this.BaseTile @ [ tile ]
this
member this.AddHeightTiles (tiles : Texture2D list) =
this.HeightTile <- this.HeightTile @ [ tiles ]
this
// Draw the Tile
member this.Draw (x : int, y : int, tileSize : int) =
let rec draw_base (texList : Texture2D list) =
match texList with
| [] -> ()
| tex::texList' ->
// devo scalarlo
spriteBatch.Draw (tex, new Vector2 (x |> float32, y |> float32), this.BaseColor)
draw_base texList'
draw_base this.BaseTile
type TileMap(width : int, height : int, spriteBatch : SpriteBatch) =
member val Width : int = width with get, set
member val Height : int = height with get, set
member val Cells : MapCell array = Array.init (width * height)
(fun i ->
new MapCell (spriteBatch, CellType.Empty))
// Retrive cell at position (x, y)
member this.CellAt (x, y) =
this.Cells.[y * this.Width + x]
// Draw the TileMap
member this.Draw (indexX, indexY, startX, startY, tileSize) =
// dir = 0 -> sin, 1 -> des, 2 -> sindes
let rec drawLoop x y dir =
if x < 0 || y < 0 || x >= this.Width || y >= this.Height then ()
else
let nx = startX + (x + y) * tileSize / 2
let ny = startY + (x - y) * tileSize / 4
this.Cells.[y * this.Width + x].Draw (nx, ny, tileSize)
if dir > 0 then drawLoop (x+1) (y) 1
if dir <> 1 then drawLoop (x) (y-1) 2
()
drawLoop 0 (this.Height - 1) 2
type IsoGame() as this =
inherit Game ()
do
this.Content.RootDirectory <- "Content"
member val graphics : GraphicsDeviceManager = new GraphicsDeviceManager (this) with get, set
member val spriteBatch : SpriteBatch = null with get, set
member val map : TileMap = new TileMap (0, 0, null) with get, set
member val tiles : Map<int,Texture2D> = Map.empty with get, set
override this.Initialize () =
base.Initialize ()
// Load content, graphics and audio
override this.LoadContent () =
// Create the spritebatch
this.spriteBatch <- new SpriteBatch (this.graphics.GraphicsDevice)
// Create empty 2x2 tilemap
this.map <- new TileMap (10, 10, this.spriteBatch)
// Load tiles
this.tiles <- this.tiles.Add (1, this.Content.Load<Texture2D>("grass"))
this.tiles <- this.tiles.Add (2, this.Content.Load<Texture2D>("sand"))
// Create the map. This will be replaced with a map loader
for x in 0 .. this.map.Width - 1 do
for y in 0 .. this.map.Height - 1 do
(this.map.CellAt (x, y)).Type <- CellType.Empty
(this.map.CellAt (x, y)).AddBaseTile (this.tiles.[1]) |> ignore
override this.Update (gameTime) =
base.Update (gameTime)
override this.Draw (gameTime) =
this.graphics.GraphicsDevice.Clear (Color.CornflowerBlue)
// Draw the tilemap
this.spriteBatch.Begin ()
this.map.Draw (0, 0, 0, this.Window.ClientBounds.Height / 2 - 16, 64)
this.spriteBatch.End ()
base.Draw (gameTime)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.