Intrinsic Programming by Erik Schulz

This blog is a way for me to express my love of programming while keeping a record of it.

Moving on with F# Development

Sunday, January 17, 2010 by gradbot

After a break from game development and finishing a work project in F#, I'm back and it's time for me to leave XNA behind and move on to a collection of specifically designed libraries. For my graphics engine I'm choosing ORGE by way of MORGE a .NET wrapper for it.

After digging into the C# SDK I figured a good start would be porting MorgeForm. To get this code to run install the SDK, create a project, set it to .NET 2.0, add a reference to Mogre_d (C:\MogreSDK\bin\Debug) and set the working directory to C:\MogreSDK\bin\Debug. The sample pulls resources through relative paths so you need to run in the SDK Debug directory.

On a side note I need to make my own custom theme for better syntax highlighting.


open System
open System.Windows.Forms
open System.Drawing

open Mogre

type OgreWindow(origin, hWnd) =
//-----------------------------------------------------
// 1 enter ogre
//-----------------------------------------------------
let root = new Root()

do //-----------------------------------------------------
// 2 configure resource paths
//-----------------------------------------------------
let cf = new ConfigFile()
cf.Load("resources.cfg", "\t:=", true)

// Go through all sections & settings in the file
let seci = cf.GetSectionIterator()

// Normally we would use the foreach syntax, which enumerates the values, but in this case we need CurrentKey too;
while seci.MoveNext() do
for pair in seci.Current do
ResourceGroupManager.Singleton.AddResourceLocation(pair.Value, pair.Key, seci.CurrentKey)

//-----------------------------------------------------
// 3 Configures the application and creates the window
//-----------------------------------------------------
root.RenderSystem <- root.GetAvailableRenderers() |> Seq.find (fun rs -> rs.Name = "Direct3D9 Rendering Subsystem")
root.RenderSystem.SetConfigOption("Full Screen", "No")
root.RenderSystem.SetConfigOption("Video Mode", "640 x 480 @ 32-bit colour")

root.Initialise(false) |> ignore
let misc = new NameValuePairList()
misc.["externalWindowHandle"] <- hWnd.ToString()
let window = root.CreateRenderWindow("Simple Mogre Form Window", 0u, 0u, false, misc.ReadOnlyInstance)
ResourceGroupManager.Singleton.InitialiseAllResourceGroups()

//-----------------------------------------------------
// 4 Create the SceneManager
//
// ST_GENERIC = octree
// ST_EXTERIOR_CLOSE = simple terrain
// ST_EXTERIOR_FAR = nature terrain (depreciated)
// ST_EXTERIOR_REAL_FAR = paging landscape
// ST_INTERIOR = Quake3 BSP
//-----------------------------------------------------
let sceneMgr = root.CreateSceneManager(SceneType.ST_GENERIC, "SceneMgr")
sceneMgr.AmbientLight <- new ColourValue(0.5f, 0.5f, 0.5f)

//-----------------------------------------------------
// 5 Create the camera
//-----------------------------------------------------
let camera = sceneMgr.CreateCamera("SimpleCamera")
camera.Position <- new Vector3(0.0f, 0.0f, 100.0f)
// Look back along -Z
camera.LookAt(new Vector3(0.0f, 0.0f, -300.0f))
camera.NearClipDistance <- 5.0f

let viewport = window.AddViewport(camera)
viewport.BackgroundColour <- new ColourValue(0.0f, 0.0f, 0.0f, 1.0f)

let ent = sceneMgr.CreateEntity("ogre", "ogrehead.mesh")
let node = sceneMgr.RootSceneNode.CreateChildSceneNode("ogreNode")
node.AttachObject(ent)

member this.Paint() =
root.RenderOneFrame() |> ignore

member this.Dispose() =
if root <> null then
root.Dispose()

type MogreForm() as this =
inherit Form()

let mogrePanel = new System.Windows.Forms.Panel()

// Between Suspend and Resume Layout is normal form Designer Code
do base.SuspendLayout()

mogrePanel.Location <- new System.Drawing.Point(0, 0)
mogrePanel.Name <- "mogrePanel"
mogrePanel.Size <- new System.Drawing.Size(483, 375)
mogrePanel.TabIndex <- 0

base.AutoScaleDimensions <- new System.Drawing.SizeF(6.0f, 13.0f)
base.AutoScaleMode <- System.Windows.Forms.AutoScaleMode.Font
base.ClientSize <- new System.Drawing.Size(483, 375)
base.Controls.Add(mogrePanel)
base.Name <- "MogreForm"
base.Text <- "Simple F# Mogre Form";

base.ResumeLayout(false)

let mogreWin = new OgreWindow(Point(100, 30), mogrePanel.Handle)
this.Disposed.Add(fun _ -> mogreWin.Dispose())
this.Paint.Add(fun _ -> mogreWin.Paint())

let main() =
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(false)
Application.Run(new MogreForm())

[]
do main()

Filed under , having 0 comments  

XNA F# Breakout Clone - Model Tutorials

Thursday, May 7, 2009 by gradbot

I'm impressed by how easy it is to use Models in XNA and because of this I'm demoting my render engine to line drawing only. Here is how I went about getting Models into my game.

  1. First you will need software to create models and Autodesk has a free version of just that. Autodesk Softimage Mod Tool 7.5
  2. Watch this video so you can create and export your 3D models correctly. The video series and blog post can be found here.
  3. Third you can follow the Microsoft tutorials to get your models in game Microsoft Tutorial on displaying a 3D Model or you can continue the blog from the previous step.
  4. Finally you will need some video tutorials on how to use Autodesk to create more complex models. XSI Video Tutorials


Breakout Clone - Added Physics Engine and Sound - F# XNA

Sunday, May 3, 2009 by gradbot

I added the Farseer Physics Engine to my game along with XNA sound effects. I'm amazed by how easy it was to use this physics engine. Collisions are handled by Delegates which you create in F# by passing a function to the delegate constructor.

ball.Geometry.OnCollision <- 
Geom.CollisionEventHandler(
fun geom1 geom2 contactList -> true)

My current plan is to add different shapes to the blocks, different masses, and maybe events such as an explosion.


Knockout Clone - Discriminated Unions with F#

Monday, April 27, 2009 by gradbot

F# supports discriminated unions. This along with pattern matching makes for some short and elegant code which quite frankly is awesome. Here's a small example.
type PieceType = Breakable | Solid

member this.needsDisposing() =
match pieceType with
| Breakable -> (life <= 0)
| Solid -> false

member this.points() =
match pieceType with
| Breakable -> 1
| Solid -> 0
Here I use a property of type PieceType to both define when a piece on the board needs to be removed and if the piece returns a point when it is hit. The calling class has no knowledge of this state and filters out pieces based on the returned bool flag needsDisposing() along with adding whatever is returned by points() to the total point score.





Breakout Clone - Line Segment Intersection Algorithm

Sunday, April 19, 2009 by gradbot

For my next game Breakout, I need to detect collisions for a moving object. I choose line segments to represent object borders and motion. Calculating line segment intersections is a simple and fast algorithm and there are more advanced scan line algorithms to speed it up if needed. In order to use it, I take the ball's position and old position as the line segment for the ball.

The hard part of any collision algorithm is of course dealing with the collision. Detection is always easy because it's been done before. I'm doing collision with a simple reflection of the velocity off of the line segment it's intersecting. This works great until you collide close to another line segment and you happen to reflect to the other side of it. To fix this, I made the intersection and reflection algorithm recursive. This works great except for possible race conditions. Also, you no longer have a constant speed for your ball. A quick fix for the race condition is to check to make sure you can't intersect with the same line segment twice in a row. Having the ball move a little faster is acceptable.

Project Homepage

Here's a burn test where I had set the ball to a very high speed to see if it could escape it's enclosure or enter one of the other objects. In order to make any errors apparent, I added a line trail of a random colors behind the ball. This ends up filling in all of the movable area.

I must say it's pretty cool to see the ball travel to every little nook and cranny of the board. This must be how particle chaos works. Like a fragrance filling the room.

Filed under , , , having 0 comments  

Tetris in XNA with F#

Saturday, April 11, 2009 by gradbot

I learned a few things on this project. One is that arrays are not the end all of data structures. My first instinct from my C++ background was to make a 2D array for the tetris game board. After wasting an hour or two I realized that it was over complicated and that a Set would work really well.

Basically each piece in the game is a set of tuple points. The game board boarder is a set of tuple points and the already fallen pieces is a set of pieces. I had to keep the concept of a piece in order to keep the color associated with each tuple point. This setup made collision detection simple. It was just a matter of Seq.union_all and Set.intersect

I'm pretty amazed by the relatively few lines of code it took me to recreate the game. The main game logic is incredibly small. Most of the code is spent setting up the system and handling user input/graphics.

Project Time: 13 hours
Project - Source Code

The game is played with the DPad and A/B buttons.

Filed under , , having 0 comments  

Learning from the Classics

Tuesday, March 10, 2009 by gradbot

So I decided while working on my platformer that I need to reduce the number of jobs I'm undertaking while I program. In order to do that I'm dropping creative director and am instead recreating classic titles. I'm still project manager since I need to manage my time and my development goal has to be playability if I'm ever going to get anything playable.


The below list contains all the 2D video game genres I can think of. I'm going to pick a game and spend a few weeks recreating it and then move on to another game in a different genre. I hope to learn the different challenges associated with each genre and what game mechanics cross genres. I have other long term goals but i'll worry more about those once I have a few games playable.

2d paddle - knockout, pong
2d shooter - galaga, zanak, space invaders
2d platformer - metroid, mario, kurby, castlevania, sonic
2d puzzle - tetris, dr. mario, generic match 3 game
2d maze - pacman, frogger
2d hack & slash - gauntlet, zelda, diablo, crono trigger
2d fighter - street fighter
2d rpg - final fantasy, dragon warrior
2d simulation - simcity, trains
2d strategy - civilization
2d rts - starcraft, red alert, dune 2, lemmings
2d racing - r.c. pro am, excite bike, mario cart
2d board game - chess, checkers, go, othello
2d projectile - gorrila, scorched earth, tank

I'm going to contenue using F# and XNA as they have served me well so far.

Filed under having 0 comments