Building a roguelike in F# from scratch - It's ALIVE!!!!
Introduction
I have the basics running and can move around the map!
Just two stupid bugs in the code base, that was all. Not bad given I have never run a single line until today, not even used the REPL to test while I coded.
This is what it looks like, very basic stuff.
So in this part an overview on the LevelFactory and RenderEngine, both quick and dirty to get a test rig running.
Level Factory
The level factory is just some code to get a level structure built fast. It will be thrown away later when I look at random level generation.
First up an ASCII tile map so I could draw the level
let private testLevelTemplate =
[
" "; // y = 0
" ################ "; // y = 1
" #..............# ########### "; // y = 2
" #..............# #......~~~# "; // y = 3
" #..............###########......~~~# "; // y = 4
" #................................### "; // y = 5
" #..............###########.......# "; // y = 6
" #..............# ######### "; // y = 7
" ################ "; // y = 8
" "; // y = 9
" "; // y = 10
" " // y = 11
]
let private width = testLevelTemplate.[0].Length
let private height = testLevelTemplate.Length
Then a dummy player with just the basics filled in
let private testPlayer =
{
id = 1;
isNpc = false;
name = "player";
stats = [(Health, {current = 10; max = 10})] |> Map.ofSeq
location = {x = 9; y = 6};
backpack = []
}
Then a function to translate an ASCII character into a Tile
let private charToTile character =
match character with
| '#' -> Wall
| '.' -> Floor
| '~' -> Water
| _ -> Void
Next a translation to convert the array of strings into a 2D array of tiles. Some basic map/reduce flow.
let private testMap =
let rowToTiles row = row |> Seq.map charToTile |> Array.ofSeq
testLevelTemplate |> Seq.rev |> Seq.map rowToTiles |> Array.ofSeq
Finally put the whole lot together in a level record, notice the use of spawnActor to push the player into the level.
let testLevel =
let level =
{
playerId = testPlayer.id;
map =
{
tiles = testMap;
topRight =
{
x = testMap.[0].Length - 1;
y = testMap.Length - 1
}
}
doors = Map.empty<vector, door>
actors = Map.empty<actorId, actor>
items = Map.empty<itemId, item>
mapActors = Map.empty<vector, actorId>
mapItems = Map.empty<vector, List<itemId>>
}
level |> spawnActor testPlayer
All simple logical stuff :)
Render Engine
The render engine is really basic. it just translates the level into an array of strings. Then clears the console window and prints them out.
A map from Tile to ASCII character, simple reversal of what you have seen.
let private tileToChar tile =
match tile with
| Wall -> '#'
| Floor -> '.'
| Water -> '~'
| _ -> ' '
To render a given tile I check it it has an Actor, if so displays an "@" otherwise converts the tile to ASCII
let private renderTile level location =
match level |> Optic.get (mapActorAt_ location) with
| Some _ -> '@'
| None -> level |> getTile location |> tileToChar
Finally walk the tiles and build the rows of the display, printing them to the console.
let private xs map = seq{0 .. map.topRight.x}
let private ys map = seq{(map.topRight.y - 1) .. -1 .. 0}
let render level =
let buildRow map currentY =
xs map
|> Seq.map (fun nextX -> {x = nextX; y = currentY})
|> Seq.map (renderTile level)
|> Seq.toArray
|> System.String
Console.Clear()
ys level.map
|> Seq.map (buildRow level.map)
|> Seq.iter (printfn "%s")
Really quick and dirty, the screen flashes every redraw but this is just a test rig.
Bug Fixes And Other Tweaks
There were a couple of bug fixes.
- East and West were reversed in the getPlayerCommand
- actorId now passed into getPlayerCommand so it is a function and not a value
- getTile used y twice instead of x y
That was it. Simple obvious bugs that were easy to find.
Summary
I will probably pause on this for a while now while I think about the direction I want to go in.
So next up an introduction into F# before I pick this up again.
And for those who have only just found the series, here is the story so far for Building a roguelike in F# from scratch :
- Introduction
- Repo and Initial Types
- First Problems
- Level Queries
- CRUD Operations
- Validation
- Game Loop Time
Finally the GitHub Repo
Feel free to ask questions and happy coding :)
Woz
Congratulations @woz.software! You have completed some achievement on Steemit and have been rewarded with new badge(s) :
Award for the number of upvotes
Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here
If you no longer want to receive notifications, reply to this comment with the word
STOP
See ; is Needed on Your 2nd Image
Well NICE Post
ALSO
KINDLY TRY TO
UPVOTE ME- FOLLOW ME BACK- RESTEAM MY LATEST POST
upvoted for the ; comment