Tuesday 31 January 2012

Version Control for Dummies - part 3


This will be a three part series. Part 1 is aimed at the project leader. It explains why you need version control and how to set it up. Part 2 is aimed at the developer who will need to work with the version control, so covers how to use it. Part 3 is about conflicts and other important topics.

Introduction
The version control is working, its being used ok. This is looking at some of the other features and a very common issue: conflicts.

What is a Conflict?
Take a case when you have two developers 'Fred' and 'Jim' both working on the same set of code.  We will assume they both get copies of the code & work on their machines adding different features.
When it comes times to commit back to the version control, this is when problems occur.

Fred commits first and there is no issue, after all he is working with the most recent copy of the code.
But when Jim want to commit what will happen?

If you are using a shared directory approach, Jim's code will just overwrite Fred's (not good).  Instead, the version control detects that Jim's code was based upon an older copy of the code and will not allow it to happen:
This is known as a conflict.

You can find out a bit more about this using the 'show log' command, and then do a compare your current code against the code stored in the version control.
This will provide a graphics difference comparing the two copies of the code. (Looks complex, doesn't it?)

Resolving the conflict
There are basically 3 ways to solve the conflict:

  1. Jim can delete out your own code, then do a update from the version control and replace all his code with Fred's newer copy
  2. Jim could move his code out of the way, get an updated copy of the code and try to copy/merge his changes in (good luck)
  3. Jim can let the version control system merge the code together (which is hopefully not too painful)

If none of these sound good, thats because they are.  But remember, the alternative was just to blindly overwrite someones else code.

First you need to update the code to get it up to the most recent version (done before, not covered)
You will get a warning message like this:
It warns you that there is a conflict which needs to be resolved.
If you look at your hard disk, you will see a set of files:
The .mine is your original code, the .r4 & .r5 are the other copies of the code (in this case version 4 & 5, you will have other numbers).  The original file will have been replaced by the merged code which looks a bit like this:
If you know how, you can edit this directly and fix the code, but its easier to instead right click and use 'Edit Conflicts' which gets the merge program up.
The code in the top left is the 'most up-to-date' code from the repository.  The code on the top right is 'your code', and the code at the bottom is where you put the merged code.
There are a number of helpful features to make it a little easier:
This allows you to just copy the block of code from one side or the other or have them both.

VITAL: Once you have finished making a merge, load the code back into your compiler and recompile to make sure there are no errors in the code.  Just because it merges, doesn't mean the code is good.

Once the code has been checked, its time to commit the new code to the repository and move on.

Backups
One of the great things about version control systems is it keeps a complete copy of all the code.  But what happens if the server goes down?
If usually possible to backup the repository, here's how to backup an SVN http://stackoverflow.com/questions/2302592/how-do-i-back-up-a-remote-svn-repository

Getting a certain copy of the code
Again another task you might want to do: Get last weeks code.  To do this, just use Checkout, but instead of getting the 'HEAD', you can specify a given revision in the dialog box.

Branches & Merges
Its possible (though I just about never do it). To branch the code off, then you can work on two versions of the code (the main trunk and the branch).
Possible, not required, probably not advisable.

Conclusion
Thats about all I have ever needed to do with the version control systems, and overall it has served me well.
Hope this gives you a good idea of what its all about.

Happy coding,
Mark


Monday 30 January 2012

Simple Shadows

Nice shadows? What do you think?


Will its actually a quick hack and simple to do. So lets look at it.

The basics
How did I do it?  Well take a suitable transparent looking texture.  Then you just stick on onto the ground like this:
Suddenly it becomes obvious what I did, doesn't it?

What do we need:

  1. A suitable transparent texture (you can do this yourself)
  2. A textured quad to draw on the ground
  3. A way to make sure it appears on the ground but not in the ground

So, lets get to it...

The Textured Quad
This is using DirectX 9, but the idea is the same for DirectX 10, or even XNA.  We just need to an array of positions and UV coordinates.  The code will probably be something like this:
// the structure for feeding into DX9
struct ShadowVertex
{
  D3DXVECTOR3 pos;
  D3DXVECTOR2 uv;
};
// the FVF
const DWORD ShadowVertex_FVF=D3DFVF_XYZ | D3DFVF_TEX1;

// sets up the UV coordinates, which only needs to be done once
void InitShadowQuad(ShadowVertex quad[4])
{
  quad[0].uv=D3DXVECTOR2(1,1);
  quad[1].uv=D3DXVECTOR2(0,1);
  quad[2].uv=D3DXVECTOR2(1,0);
  quad[3].uv=D3DXVECTOR2(0,0);
}

// sets up the XZ coordinates for the quad
// you will need to adjust the Y coordinates to make sure they are
// neatly on the ground
void UpdateShadowQuad(ShadowVertex quad[4],D3DXVECTOR3 pos,float size)
{
  quad[0].pos=pos+D3DXVECTOR3(size,0,size);
  quad[1].pos=pos+D3DXVECTOR3(size,0,-size);
  quad[2].pos=pos+D3DXVECTOR3(-size,0,size);
  quad[3].pos=pos+D3DXVECTOR3(-size,0,-size);
}

I really should have a vertex buffer to hold these in, but I'm going for the simplest possible solution and just sticking with an array of data.

The other task you will need to do is to make sure that the Y coordinates of the quad are neatly on the ground.  For flat terrain that's just a matter of quad[0].pos.y=0, but it you are doing it on 3D terrain, it will be a little more complex.


The Rendering
For those who know their render states, this should be simple.  But for those who don't, it could be a bit more complex, so here are the main issues to consider.
  • Must have blending: to blend nicely with the terrain under the shadow
  • No lights: the shadow affect the terrains appearance, we don't want apply lighting twice
  • Z-Buffering must be dealt with: this is the tricky part 
The most obvious solution would be to just draw the shadow on the ground.  The trouble is you get something like this:
Some bits of the quad are above the ground, some bits of the quad are in the ground.  Its caused by rounding errors in the Z-buffer.  We can try to fix this by moving the quad a little bit above the ground, but this then asks the question how much? 0.1 units? 0.01units? 0.00001?  Depending on various factors in your game this may (or may not) look good.

I experimented with disabling the Z-buffer write or just turning the whole Z-buffer off, and I found that turning the Z-buffer off worked better.  You just have to be careful in your draw order (my first attempt had the shadow drawn on top of my model).

So here is the quick summary in english:
draw the ground
turn off Z-buffer
turn off lights
turn on blend
draw the quad with the shadow on it
turn off blend
turn on lights
turn on Z-buffer
NOW draw the model over the shadow

In code it looks like this:
// draw the shadow quad
void DrawShadowQuad(IDirect3DDevice9* pDev,IDirect3DTexture9* pTex,
                      ShadowVertex quad[4])
{
 pDev->SetRenderState(D3DRS_LIGHTING,false); // lights off
 pDev->SetRenderState(D3DRS_ZENABLE,false); // Z-buffer off
 pDev->SetRenderState(D3DRS_ALPHABLENDENABLE,true); // blend on 
 pDev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
 pDev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
 pDev->SetTransform(D3DTS_WORLD,&IDENTITY_MAT); // world set with identity matrix
 pDev->SetFVF(ShadowVertex_FVF);
 pDev->SetTexture(0,pTex);
 pDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,quad,sizeof(ShadowVertex)); // draw
 pDev->SetRenderState(D3DRS_LIGHTING,true); // lights back on
 pDev->SetRenderState(D3DRS_ZENABLE,true); // Z-buffer on
 pDev->SetRenderState(D3DRS_ALPHABLENDENABLE,false); // blend off
}

(Note on DrawPrimitiveUP: Yes, I KNOW it has a horrible performance penalty, but its the simplest way to get the code up.  It should certainly be done with a vertex buffer.  However, you try and make the vertex buffer code this simple!  I went for simplicity, not efficiency)


Final Code
The main code looks something like this (but it will vary depending upon your ground):
// draw the shadow quad
// draw ground...
D3DXVECTOR3 pos=players pos
float radius=players radius
UpdateShadowQuad(verts,pos,radius); // update the vertex position
// put the vertexes on the ground
for(int i=0;i<4;i++) verts[i].pos.y=0;
DrawShadowQuad(GetDevice(),mpTex,verts); // draw the shadow
// draw the player...

And there we have it.

Improvements
Nope: its not a true shadow, and it is just a circle, and its not very realistic.  But it was very simple.  To do this properly, we need to start messing around with stencil buffers and possibly shaders too.  Frank Luna (http://www.d3dcoder.net/) has some good books on the topic and there are probably some other references on the net somewhere else.

This is quick and it works, and I have not found any articles explaining this simple trick. So I hope it helps.

Happy Coding,
Mark

Version Control for Dummies - part 2


This will be a three part series. Part 1 is aimed at the project leader. It explains why you need version control and how to set it up. Part 2 is aimed at the developer who will need to work with the version control, so covers how to use it. Part 3 is about conflicts and other important topics.

Introduction
You have version control.  Either the team lead told you you use it, or you understand how useful it is. Or perhaps you just joined a sourceforge project and you need to get access to their repository.  Whatever the reasons are, this post is looking at how to use SVN (in particular tortoise SVN) in your development.

A few terms
I'm using the SVN terms as it will help later
  • Repository: The 'shared directory' where the code lives, usually on a hosted server somewhere
  • Import: take some brand new code & put it into the repository
  • Check out: Get a fresh set of the code (usually the latest version) from the repository onto your local machine
  • Update: Update the code on your local machine with the latest version in the repository
  • Commit: Copy the code from your local machine into the repository
  • Conflict: What happens when you try to commit some code and someone else has already made a modification to it
You will need
  • A copy of Tortoise SVN ( http://tortoisesvn.net/)
  • The URL of the SVN repository (the project lead will know this)
  • A username & password (probably)
    • Its worthwhile each developer having their own account, it encourages more responsible behaviour, as each commit has your name attached to it

The First Check Out
We need to get the latest code to work with, so this is where we start.
Get yourself a suitable directory.  It doesn't need to be 100% empty, but it cannot have a directory with the same name as your project.
Right click on the base directory and SVN->Check out
For the repository name, give it the information that you were given (remember, your project lead needs to set up the repository and give you the URL of it). As you want to copy the whole directory, you need to also give a directory name. I.E. we are copying https://whatever_the_SVN_repository_was/trunk/project_name
to d:\work\project_name So we will get all the code we need in a new directory.
(PS. The HEAD revision, means the latest copy).

After we hit OK, the SVN will get the latest copy of the code, create the directory and put all the code in it.
Currently its just the readme, but we will add some code later.  If you have a look on the hard disk, you will see the files added with a little green tick icon, which means they are up to date.
We now have the latest code.

General Usage: Adding, Ignoring and Committing
OK, so we have a version control up, what next?
Write code of course...
<some time later>

What next?
Lets have a look at my directory right now:
I have added in a Visual C++ project and put in a bit of code.  But life gets a little bit more complicated.
I don't want ALL of this stuff into the source control, mainly all the temp files and stuff, but especially the 100MB temp files which Visual Studio likes to generate.
As for knowing what to add & what not to add, this is down to the individual programming environment/language.  But in my case, I want to ignore the following:

  • Debug and Release folder
  • The .NCB, the .SUO and the .user files
Therefore I right click on them and mark them to be ignored.
After that, I add in the files I want to add again by right clicking.
You notice how it is now marked with a + to show its been added.  
However this does not mean its in the repository yet, that will not happen until we commit the directory to the server.  We do this by selecting the directory and doing a commit.
This will show which files are changed (& will be sent to the repository), at the same time it will show up which files are unversioned (not added or ignored), for you to decide what to do with them.  You can just right click & decide to add or ignore them.
(If you want to know what the changes are, just right click on the file & select 'compare')


Very Important: Use the text box to add some comments to explain what you did.  You want to know what other people have been doing to the code, so give the same feedback for them.
Most of the time it should work fine, unless you are working on old code.  In which case you may need to do an update (see below).


General Usage: Viewing and Updating
What happens if the others are working on the project and you need to find out what is going on?  Well, select the directory (or file), right click and select 'check log' which will give you the current history of the project:
Remember I said about adding the comments when you commit? Well you can see the comments listed here.
You can 'check for modifications' which will show you if your code if the most up to date, or if others have made changes to your code:
In this case, it seems that someone have updated one of the files, so what I can do is 'Update' to the latest copy of the code.


General Rules for use with Version Control
  1. Never check broken code into the version control, test it first
  2. Don't check in generated files (object code or similar), just the original source.
    • It should be easy to regenerate the files from the source
  3. Make sure you are careful with what you add into the version control, don't add in junk.
    • On one project, someone added a 200MB movie files into the version control. I was very unhappy with them
  4. Try to minimise the amount of non-text files which you add into your version control, as most systems don't handle them well & they take up a lot of space (compared with code)
    • Some teams run version control for the code and then use a shared drive for art assets
  5. On a similar note, If you are going to add art assets in, only add in the final items in a form which is useable in the project
    • Don't put in your raw photoshop files, just the final exported bitmap
    • Keep the raw photoshop files in the shared drive
  6. It should be possible for someone to check out a complete your code from the version control system and build it without errors.



Conclusion
There are quite a few other items which I could cover (reverting, comparing and such), but these are the most common operations you need.
In part 3, I will cover dealing with the issues.  In particular what happens when two people try to change the same piece for code at the same time?

Until then, Happy Coding,
Mark


 


Friday 27 January 2012

Version Control for Dummies - part 1


This will be a three part series.  Part 1 is aimed at the project leader.  It explains why you need version control and how to set it up.  Part 2 is aimed at the developer who will need to work with the version control, so covers how to use it.  Part 3 is about conflicts and an other important topics.


The problem?
When you are writing programs on your own its quite easy to do, but what happens when there are two (or more) people working on the project together.  What do you do?
  1. Everyone hack the code & hope
    • Never going to work
  2. Pass latest copies of the code about using email/thumb drives
    • Sort of workable, but its hard to know which bits have been updated
    • And you never know where the latest copy of the code is
  3. Everyone writes their own code & gives it to one person who holds the master copy of the code
    • I've tried this, its a lot of work for the one person
  4. Some kind of shared drive or drop box (http://www.dropbox.com/)
    • Getting there, but if you have to be careful, or you can overwrite each others code
  5. A Version Control System
    • This is what I'm talking about

So what is it?
Think about a shared drive somewhere, which holds all your code.
It also holds all the backup copies of your code, so that every time you make a change, it makes a backup (just in case you mess it up).
It also keeps track of who have been changing what so it will stop you from accidentally overwriting someone else's code if you both have been making a change to the same file.

This is a version control system.

Different types of version control
There are quite a few different types of version control: CVS, SVN, Perforce, GIT, Mercurial, Visual Source Safe and many others. See http://en.wikipedia.org/wiki/Comparison_of_revision_control_software
I'm currently using SVN, but they are all fairly similar.
(Note: those people who are familiar with distributed version control are entitled to scream at me for the previous statement.  I don't use DVCS I know they perform a similar but in a totally different way)

A few terms
See: http://betterexplained.com/articles/a-visual-guide-to-version-control/ for a good summary.
I'm using the SVN terms as it will help later
  • Repository: The 'shared directory' where the code lives, usually on a hosted server somewhere
  • Import: take some brand new code & put it into the repository
  • Check out: Get a fresh set of the code (usually the latest version) from the repository onto your local machine
  • Update: Update the code on your local machine with the latest version in the repository
  • Commit: Copy the code from your local machine into the repository
  • Conflict: What happens when you try to commit some code and someone else has already made a modification to it

Getting started
You will need:
  1. A repository
    • Since you want this to be accessible by your team all the time, its a bad idea to stick it on your machine (unless you have a spare server which you can use), so here are a few options.  They all have free plans and many have paid plans too.
    • You only need one person to set up the repository, but you will need accounts for all your developers
  2. A SVN client
  3. Some code (duh!)

Setting up the Repository and performing the initial import
This is a little tedious, but only need to do once, so its a good idea to have your senior/experienced developer do this.
My example will be using https://riouxsvn.com/ and http://tortoisesvn.net/, but its roughly the same for all.

1. Go to your host and set up the repository
You will have to figure this one out for yourself. But it should be simple enough.
While you are doing this, look out for an option to create 'trunk' and all the other default directories.
(I usually do this, but I'm not 100% sure I really need to)
Once you are done, look out for the URL of your SVN repository, it looks like a normal URL. You will need this later.

2. Create an (almost) empty directory to put your code into
Advise: Never start by putting 300 files into your repository on the first attempt. KISS.  If it doesn't work, its only one file.

As SVN cannot put empty directories into the repository, I always create a empty directory and put a readme.txt in there, then import this.
Note: I like to add the entire directory into source control. This gives me the option to put multiple project into one repository if I want.  I'm not sure if its a best practice, but it seems logical.

Right click on the new DIRECTORY (not the file), and import it.
When the dialog appears you will need to enter the URL of the repository which should be of the form:
https://whatever_the_SVN_repository_was/trunk/project_name
(Most will be https, though it might be http)
You need to get this first bit right, or you will hit all sorts of problems.  I always have project_name as the same as the directory, mainly for convenience.  I never have spaces or strange characters in it.  And remember to choose a suitable name too. (I have an SVN project called 'labtask', oops!)
It might ask you for your username & password, but you should soon see a result like this:
Take note of the full URL as you will need to pass this information to all your fellow developers.

At this point, I will usually delete/rename the directory away and perform the checkout (see part 2) to make sure it worked.

Continued in part 2

Mark

Thursday 26 January 2012

Programmer Art

I'm a programmer.
I have an O level in Art (D grade :-< )

I need art for my game...

Or do I????

Have a watch of these videos:
http://penny-arcade.com/patv/episode/the-uncanny-valley
http://penny-arcade.com/patv/episode/graphics-vs.-aesthetics

Ok, so what do they say?
  • For art there are two choices: Stylisation (Mario) or Realism (Modern Warfare)
  • High Graphics IS NOT looking good, High Graphics is higher fidelity (detail)
  • Aesthetics is the style of the game (sort of)
  • Aesthetics is the visuals, sound, mechanics & a few other bits
  • Aesthetics is what we really want to have good in our game.
Right so where does this put me?

I don't need to look photo realistic (I cannot draw that well anyway), but what it need is a good consistent art style which works well together.
I'm not going to get this by the use of google and copy-paste but without use of my brains. All that will get is a Frankenstein monster.

To prove my point, here are a few great games which have very simple graphics, but looks (and plays) great.
Battalion (iPhone app)

Battleships Forever (this is the MOST awesome Game Maker game EVER)

Geometry Wars

 Notebook wars (drawn using pencil paper & scanned into the game)

 Torus Trooper (or any of the other games by Kenta Choo) 

Vector Tower Defense

Xiao Xiao (or any of the other stickman based games)
Or even Pac Man!

So what am I getting at?

Graphics are not the main thing, its the package (graphics, sound, interaction, feedback, gameplay) which makes the game.  No one ever looks at Mickey Mouse and says 'this graphics suck', they accept the graphics style and watch the show.  If the show is good, people will suspend disbelief and just watch, the same is true of games.

So my plan for graphics? Keep It Simple, Keep It Consistent and Make sure the overall package is Good.

Here are a few links which might be useful:
http://www.gamasutra.com/blogs/ChrisHildenbrand/20111015/8669/
http://www.gamedev.net/page/resources/_/creative/visual-arts/better-programmer-art-r2594
http://www.gamedev.net/topic/603593-methods-for-creating-effective-programmer-art/

Happy Coding (or doing the art)
Mark

Monday 16 January 2012

3D XACT using C++

Today is a heavy tech session.
I have spent a lot of time looking about on how to do 3D sound within XACT.
There are quite a few articles about the C#/XNA version, but very little in the C++ land.  Oh, and those of you who may have looked at the DirectX SDK examples know how little use they are. (I mean, the two examples they have are 500 and 600 lines of code each!)

The basics can be found at http://msdn.microsoft.com/en-us/library/ee416190.aspx
I have been working on it all day & this is what I have found so far (its not perfect, but it works).

Variables
I'm going to assume that you already have XACT working.  If not, try looking at the DX SDK examples, The XACT tutorial 1 was not too bad, though I needed to read the other examples to get it working perfectly.

You will need the following sets of variables:
// you need one set of these:
X3DAUDIO_HANDLE xact3dInstance;
X3DAUDIO_DSP_SETTINGS dspSettings;
X3DAUDIO_LISTENER listener;

// and one set of these PER 3D sound
// probably put it into a struct or similar
X3DAUDIO_EMITTER emitter;
IXACT3Cue* pCue;

The Setup
Once you have your XACT setup, you will need the following extra code, to turn on the X3DAudio:
// Assuming you have the IXACT3Engine* pEngine:

// setup the XACT3D
XACT3DInitialize(pEngine,xact3dInstance);

// check how many output channels are supported
WAVEFORMATEXTENSIBLE format;
pEngine->GetFinalMixFormat(&format);

// fill the DSP
ZeroMemory(&dspSettings,sizeof(dspSettings));
// different code's seem to suggest 1 or 2 channels for the emitter
// i'm going for 1
dspSettings.SrcChannelCount = 1;
dspSettings.DstChannelCount = format.Format.nChannels;  // as supported  
dspSettings.pMatrixCoefficients = new FLOAT32[dspSettings.SrcChannelCount * dspSettings.DstChannelCount];
ZeroMemory(dspSettings.pMatrixCoefficients ,sizeof(FLOAT32)*dspSettings.SrcChannelCount * dspSettings.DstChannelCount);

// could probably set some of the default values
// for the emitter and listener here
// (you can do this yourself) 

Playing the sound
This is just about the same as normal XACT, you just need to remember to keep a pointer to the IXACT3Cue:
// Assuming you have the IXACT3SoundBank* pSoundBank
// and you have the XACTINDEX cueIdx:

// play the sound
pSoundBank->Play(cueIdx,0,0,&pCue);
// the documentation is a little value,
// but I think you need to remember to call pCue->Release() yourself 

Making the sound 3D
To make the sound 3D, you need to specify two basic things: Where the sound is coming from and where the listener is.  Then you need to update the cue with this information.
The documentation for this seems to suggest you only need to do it once every 2-3 frames.  But here is the code:
// Set the listener information
ZeroMemory(&listener,sizeof(listener));
// set the XYZ of the camera
listener.Position = camPos;
// set the direction the camera looks in
// this must be a unit vector
listener.OrientFront = camLook;
// set the up-direction of the camera
// again, this must be a unit vector and orthogonal to camLook
listener.OrientTop = camUp;
// assuming no doppler effect 
listener.Velocity = D3DXVECTOR3(0,0,0);

// Set the emitter information
ZeroMemory(&emitter,sizeof(emitter));

// only worrying about its position, just giving fixed other info
emitter.OrientFront = D3DXVECTOR3(0,0,1);
emitter.OrientTop = D3DXVECTOR3(0,1,0);
emitter.Position = emitterPos;
emitter.Velocity = D3DXVECTOR3(0,0,0);

// emitter ChannelCount and DSP Setting's SrcChannelCount must match
emitter.ChannelCount = dspSettings.SrcChannelCount;
// computer the effects on the sound and apply it
XACT3DCalculate( xact3dInstance, &listener, &emitter, &dspSettings );
XACT3DApply( &dspSettings, pCue);

And that's the basics.
If you try this with sound sources which move around the listener, you should hear it louder on one side and quieter on the other.

Making the sound attenuate
Once I got this working, I moved on to the getting the sound to fade off.
This is where is all went wrong.
What happened is my code did not follow the documentation and I have little idea why.

According to the documentation, there should be a simple falloff of sound built it, but I could not make it work.  So I experimented until I got something working.
What I really wanted was something like this:
If you are within a certain distance of the emitter (minDistance), the sound is 100%, and after that it drops until another distance (maxDistance) where the sound reaches 0%.
According to the documentation, it should be built in, but I can I make it work, can I heck!

Therefore I had to code it myself.  At least it wasn't too much code:
// assuming a pair of float's MIN_SOUND_DIST & MAX_SOUND_DIST
// listener code unchanged:

// emitter code has the following extra lines
...
// the falloff curve:
// at range 0=>100%, MIN_SOUND_DIST=>100%, MAX_SOUND_DIST=>0%
X3DAUDIO_DISTANCE_CURVE_POINT soundFalloffPt[] = { 0.0f, 1.0f, MIN_SOUND_DIST, 1.0f, MAX_SOUND_DIST, 0.0f  };
X3DAUDIO_DISTANCE_CURVE       soundFalloff          = { &soundFalloffPt[0], 3 };
// set the falloff curve
emitter.pVolumeCurve =(X3DAUDIO_DISTANCE_CURVE*)&soundFalloff;
emitter.CurveDistanceScaler = 1.0; // this is a multiplier on all distances

// perform the XACT3DCalculate & XACT3DApply as before
Now we have sound falloff and stereo playback working
I'm a little disappointed that the default behaviour didn't work (there is a InnerRadius parameter which I could never get working), but at least the code works now.

Hope this helps
Happy Coding:
Mark

Sunday 8 January 2012

Childrens worksheets

Hello All,
A minimal-technical post today.
I was at Church and saw some of the Sunday School teachers had been trying to build a childrens worksheet. You know the kind, with some of the text is dashed, so the kids can do it themselves.
Anyway, I offered to explain how to do this properly, so here it is.

1) Get a suitable dashed/dotted font.
I quick google will help you, but http://www.fontspace.com/category/dashed seems to give a few good choices. So pick one which looks good and download it.
(I found the 'Trace' font a little faint, but the 'Print Clearly' was much better.  But you can decide for yourself.)

2) Install the font
This is simple, unzip the file and double click on the font file.  It will open up into a preview mode. After that you just click on the 'install' button, nothing to it.
(Sorry, I'm not sure about how to do this on a Mac, I'm a PC guy. But it should be simple, Apple makes a big thing about how easy they are to use.)

3) Use the font
Start up your favourite word processor and just type away. Then select the text you want the kids to write and change the font to the dashed font.

4) Print and Use
Thats it really, nothing too it.
Just one word of note: if you want to email your document to your friends, you may also need to email them the font as well.

Thats All Folks,
Mark