05 September 2007

So I dug up the ol' gravitas solution and decided it was time to load a mesh in there. Coding4Fun again proved helpful. Unlike the very uninformative error messages from DirectX. With some playing about, I managed to get the sample heli.x to load and render in stark white.

Then I had to turn on the lights. (device.RenderState.Lighting = true; device.RenderState.Ambient = Color.White;)

For some reason my point list is now ignoring its colours and using the last one that heli did. Sheep.

Posted on Wednesday, September 05, 2007 by David Campey

No comments

14 May 2007

Title says it all. Pictures of walls.

Man some of these are funny.

Great content, amusing presentation, and occasional irony. Nothing quite like the venting of profound, repressed, anonymous vandals.

Posted on Monday, May 14, 2007 by David Campey

No comments

08 May 2007

TeamPlain has a goto work-item search that opens up workitems, oddly enough. I wanted to use the Firefox search box to fire this off.


Using the guide: Creating OpenSearch plug-ins for Firefox, I started putting together an XML OpenSearch description in notepad.


Needing an icon, I Gimped out the logo from the TeamPlain site, took it past the data: URI kitchen and popped it in.

data:image/png,%89PNG%0D%...

Okay, so it's fugly, but it doesn't look too bad on the search bar.


A glance at the OpenSearch Specification provided final tips when deciding what data should go where. Now I had an XML file and needed someway to consume it


I tried installing the OpenSearch plug-in. I used the Error Console in Firefox, running the command window.external.AddSearchProvider(engineURL); using a file:/// URI for the engineURL, but kept getting a URL formatting error.

Error: Invalid argument passed to 
window.sidebar.addSearchEngine:
Unsupported search engine
Source File: file:///C:/Program%20Files/Gran%20Paradiso
/components/nsSidebar.js
Line: 114

Initially I thought this was due to the URL in the XML definition file, so I hacked around with that for a bit, then when that yielded no fruit, I extended the error message in the mentioned .js to include the invalid URL. This was the URL to the XML doc, not the search URL inside the XML. Turns out the URL check in the .js that was throwing the exception was only regexing https?|ftp, so needed a |file appended.


Now that Firefox was playing nicely with the XML, it was happy to load it up and prompt me to install it.



And it worked!



Final code: (adjust search URL to your liking)



<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
xmlns:moz="http://www.mozilla.org/2006/browser/search/">
<ShortName>TeamPlain Item</ShortName>
<Description>Load items from local TeamPlain</Description>
<Image width="16"height="16">
data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%10%00%00%00%10%08%06%00%00%00%1F%F3%FFa%00%00%00%06bKGD%00%FF%00%FF%00%FF%A0%BD%A7%93%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%07tIME%07%D7%05%08%14%0D(U%8F%FC%B3%00%00%00%1DtEXtComment%00Created%20with%20The%20GIMP%EFd%25n%00%00%03%D9IDATx%DA%25%CD%D9SUu%1C%00%F0%EFo9%F7%2C%F7%C0%85%CBv7%B8%C8%A6%80%2C%CA%92%2CS%86%25%C94%9A%19%92%8D%CD%80a5M%0F-%D34%95V%0F%3Dd%F1%D0%83H%93%83%93%E2LS4c6%26%88T6%23%13h%0B(%16b%5C%20%05%94%ED%02%F7r%B7s~%BF_%0F%7D%FE%81%0F%02E%D5%B1E%00'%08%B0%10%80%88%80%C7%1F%DD%EB%AA%DB%B5%DB%93%E6pj%CB%8B%F3%A1%BE%8B%DF%DF%BD%DCsn%16!%0E%00%18%B0%84%20*%24%C0FD%60%20%00%1C%10%00%07%E0%04%030%02%C9%DE%7C%C7%E6%ED%0Du%17%2C%B1%AA%EC%EA%9D%B5vO%AE%8B%23%0A%18K%C0%23B0%03%83%14%8D%82D9%A2%98%0B%E0%F0%FF%CE1%80%10%1CVW%FC%B1%D3%96%07%D2%A52%FB%86%85%D1%C1%F5%B8%15%7F%9F%C4%23%20%04%05BM%10%94%80%A1Y%81%98%01%81%85%10%08%13%86%B9%82%00%9B%02%803%B9%B5%B9%B9%ACQM%A9%8E%9FYZmN%CF%F7%B6%B6%B4%94%9A%26%969%05%00L%11%B0(%81p%08%0BF%10y%EE%C57%F2%DF%7C%FB%C3%B2%D9%09%9Fp%3B%5Cq%C7%DA%DA%AB%AA%B7%D5%BC%EE%95Tg%AB%3D%DB%91%A7%258%DD%8E%B4%92-%E5%E5%F7%EENLE%5C%9E%8C%C4%8F%DANV%A4o%C8%B3%5C%BF%FA%E3%02%EA%1E%B8sTNZ4%03%E1%2F%A1%D8%F1~F%92%EEj%00%60%BE_~%EA%BB22%3CL%0B%0A%0B%CD%9D%F5%0D%B5%80h%C1z%C4%E8%1D%EF%B8%F5%3B%2F%B3%A7%80%03kO%D6%E6%B5Q%87%CB%93%B3%E4%AC%1B%84%05%FF%E6%A9%F9%F2%A4%E4%B8%D6%FBG%8E%BC%F5i%E7%E7'%261B~!%C0%F6L%D3%81%C1%F6%8ES%EF%B2%81%90%BF%B8%D3%A5%FC%FC%F1P0k%AC!gc%CD%0E%1By%A8~oE2)u%AF-%07%D5m%B9G%BD%91%08%BB%FAJ%EB%C1%CB%20%C3%2C2D%0Cd%12%18%1B%BD%11j9%F4%92%23%C1%9DP%F3%CF%AF%E3AyO%0ALX%E7%B8%CF7%ED%03%90%B5%CA%AC%D2%CA%3D%DF%5C%F9%F3%BD%7F%D7%C4%9D%1B%BE%D9N%A4%D14%9A%A4%E9TUtl%B3%EAD%C5%C9%BF%FD5%D95%13%10%93%3F%0C%FD%FD%C1%D6G%1E%DB%07%B2V%89%AC%9A%07%40Uu%D0%15%1BM%F3n%19_b%E7%E7%82%FCRaEE.%8E%D7uK%A2%A4%D3DU%CF-)%CA%9CY%89%5C%9C%F4%B3%9E%B8%EC%82%ADT%93%E3I%7C%9CUN%94%AD%18c%01%00%88%99k%8B%81%A8%C9V%98%40%1B%BB%CE~%DB%A2%11)%C9%08%09%2B%8B1%FB%99%D3_%1F%C2T.%8A%9A%2C%14%98%9D%0A%80baB%A5%60Z%40P%C1%11%60%99%83%96%98%8A%23%E1u%D5o%C2P%AA3%E3%E9%DBS%0F%AA%40%B0%01%82q9C%96%AC%95%D5%C0%CD%18%03%C9%EE%CE%40%C1%A5i%60%0C%012%10%60%C4%05%08Ch%C7%BF%F8j%87v%EB%C0%9A%D1%E3%8C%AE%AC%CF%F7F%85%E4%8E%81%B2%3F%CC-%D9%A1%B5%60%BF%F1%7C%D1%D8Zs%C5%FD%E3%1D%5D%DB%8D(X%11cB%20%02%94c%04%0DM%AFffm*-w%8F%8F%E83%C4p%AD%07%E6%A6%8E%7D%D2%FE%D9%ED%9B%7F%90%CC%EC%3C%F3%9D%C3%87%3D9%A1%A5%82I%93%AA%D2%A6%12c%FF%0B%AF%8Dv%9F91%22%A10%00%B6*%3A(%AA%B3%A0%B6~%DFw%FD%E7%DB%AE%0F%F7%9Fz%E2%E0%CB%CF%12%C5%EA%25%AAd%C3%0Au%3D%BC%BB%E9%A9k%17zO%9E%3B%DB%DDQ%B9%AB%B1%11%5B%157I%B1Y%B1C%D6%10h%AA%8E%25%01%9CqE%92l%C5i%E9Y%A9%B3%D3%13%D7%90%14%9A%87%00%07%A1%08%101%9C%E8%CE-%A9%9E%BF%E7%5B6%C3%91aI5BQ*%03%8D%86%C5%7Fs%3B%AAS%D9I.%22%00%00%00%00IEND%AEB%60%82
</Image>
<InputEncoding>UTF-8</InputEncoding>
<Url type="text/html" method="GET"
template="http://05rnb-dev02:8090/workitem.aspx?id={searchTerms}" />
<moz:SearchForm>searchFormURL</moz:SearchForm>
</OpenSearchDescription>

Posted on Tuesday, May 08, 2007 by David Campey

2 comments

03 May 2007

So my screen went on the blink; more like the scramble. It was very upsetting, and it carried on like this for a few weeks. I used an external monitor and sometimes the regular screen would work. It was very unpredictable and would break without any cause, which frustrated the hell out of me.


Eventually while sitting in a friend's loungue I decided I really just had to see my screen. So I grappled with her rather useless screwdrivers and took out the retaining screws for the keyboard. After this was done I flipped the keyboard open, gave the internal screen connector a poke and turned it on.


And it worked. Just like that. And it's been working ever since.

Posted on Thursday, May 03, 2007 by David Campey

No comments

So, I went to the 'My Coke Fest' in Joburg. It was pretty cool. Hoobastank rocked ;) their lead singer looked like he couldn't have been more than 20; turns out the whole band is over 30 -- there's hope for us yet.

The picture (left) is of Hoobastank, with their lead singer standing on his box -- he was so tiny. Apparently he's Incubus' brother, which is kinda cool. They played some Bon Jovi and AC-DC to warm the crowd up for their no. 1 track, "The Reason". It was unexpected to hear an international act covering, but they pulled it off with style. Definitely the high-point of the 12-hour concert for me.

Posted on Thursday, May 03, 2007 by David Campey

No comments

Not only is Rocket Commander a pretty cool looking (but rather boring) MDX game with publicly available source, it turns out they've done a series of 10 30-minute video tutorials on the making of the game. Sweet.

Posted on Thursday, May 03, 2007 by David Campey

No comments

02 May 2007

So, I wanted to add substance to my craft. This was quite easy. I rearranged the points in the VertexBuffer into a list describing a triangle fan and fiddled to get that to work.

pointList_VB = new VertexBuffer(typeof(CustomVertex.PositionColored),
12, device,
Usage.Dynamic | Usage.WriteOnly,
CustomVertex.PositionColored.Format,
Pool.Default);

CustomVertex.PositionColored[] verts = new CustomVertex.PositionColored[12];

// Triangle #1

verts[0].Position = new Vector3(0.0f, 0.5f, 0.0f);
verts[0].Color = Color.Blue.ToArgb();

verts[1].Position = new Vector3(0.5f, -0.2f, 0.0f);
verts[1].Color = Color.Green.ToArgb();

verts[2].Position = new Vector3(0.0f, 0.0f, 0.2f);
verts[2].Color = Color.Orange.ToArgb();

verts[3].Position = new Vector3(-0.5f, -0.2f, 0.0f);
verts[3].Color = Color.Red.ToArgb();

verts[4].Position = new Vector3(0.0f, 0.0f, -0.2f);
verts[4].Color = Color.Yellow.ToArgb();

verts[5].Position = new Vector3(0.5f, -0.2f, 0.0f);
verts[5].Color = Color.Green.ToArgb();

Yawn. Then I appended some points to that list for a triangle list to close off the object.

verts[6].Position = new Vector3(-0.5f, -0.2f, 0.0f);
verts[6].Color = Color.Red.ToArgb();

verts[7].Position = new Vector3(0.5f, -0.2f, 0.0f);
verts[7].Color = Color.Green.ToArgb();

verts[8].Position = new Vector3(0.0f, 0.0f, -0.2f);
verts[8].Color = Color.Yellow.ToArgb();

verts[9].Position = new Vector3(-0.5f, -0.2f, 0.0f);
verts[9].Color = Color.Red.ToArgb();

verts[10].Position = new Vector3(0.5f, -0.2f, 0.0f);
verts[10].Color = Color.Green.ToArgb();

verts[11].Position = new Vector3(0.0f, 0.0f, 0.2f);
verts[11].Color = Color.Orange.ToArgb();

pointList_VB.SetData(verts, 0, LockFlags.None);

And then drawing it with indexed calls to my VB stream as follows.

d3dDevice.SetStreamSource(0, pointList_VB, 0);
d3dDevice.DrawPrimitives(PrimitiveType.PointList, 0, 7);
d3dDevice.Transform.World = Matrix.Multiply(
Matrix.RotationYawPitchRoll(Geometry.DegreeToRadian(p1.Rotation.X), Geometry.DegreeToRadian(p1.Rotation.Y), Geometry.DegreeToRadian(p1.Rotation.Z)),
Matrix.Translation(p1.Position.X, p1.Position.Y, 20.0f)
);
d3dDevice.DrawPrimitives(PrimitiveType.TriangleFan, 0, 5);
d3dDevice.DrawPrimitives(PrimitiveType.TriangleList, 6, 11);

Drawing it revealed to me that I'd got up & down confused on the y-rotation.. so after fixing that it was all solid.

And it looks something like this. (from a few viewpoints)



Really has to be seen in motion for full effect.

Posted on Wednesday, May 02, 2007 by David Campey

No comments

So, I had collected a lovely bunch of variables to track the position of the craft, looking something like this: (gotta love having your dev history in an SVN repo)
        private Vector3 p1rot;
private Vector3 p1rotInput;
private float p1rotForce;
public Vector3 Player1Rotation
{
get { return p1rot; }
set { p1rot = value; }
}
private Vector2 p1;
public Vector2 Player1Location
{
get { return p1; }
set { p1 = value; }
}
private Vector2 p1force;
private Vector2 p1spring;
private Vector2 p1grav;

And the time had come to move it out into an object. Which ended up looking like this:

class Player
{
private Vector2 _position;
private Vector2 _force;
private Vector3 _rotation;
private Vector3 _rotationInput;
private float _thrust;
private float _rotationForce;

public Vector2 Position
{
get { return _position; }
set { _position = value; }
}

.. blah blah properties. Thankfully we can use CTRL-R,E in Visual Studio to make a private variable into a public property; no mess, no fuss. There was also dome debate as to where to put the public properties w.r.t. their privates, I went with Turner and used the C++ style approach.

And I even gave the object its very own method to update it's internals. Lucky thing.

public void HandleInput(float dt)
{ ..blah.. }
}


This also meant that I can now make my property grid show only properties of Player p1.



Which is a lot more useful.

Also evident is the pretty point field I forgot to blog about; this is just a bunch of for loops adding the gravity vector at a point in the grid to the vector to that point.. the result is a point distorted by gravity.

Posted on Wednesday, May 02, 2007 by David Campey

No comments

01 May 2007

So, I demoed my game on battery power.. and it sucked. Interestingly whenever windows showed a tooltip, the game ran at full pelt.. something fishy there. But anyway, I introduced a Δt (delta t for the unicode (or greek) unaware) into my calculations. The first stumbling block was that I was using the tick counter, which sucks a bit. The thing is, even though it has damn good accuracy, it is only updated every now and then. Which is a bit odd. I managed to hack it into working by doing the following:

private void Physics()
{
    while (System.DateTime.Now.Ticks == Tick) { }
    //time interval
    long thisTick = System.DateTime.Now.Ticks;
    float dt = (Tick - thisTick) / 100000.0f;
    Tick = thisTick;
But that really feels dirty. All that hanging around waiting for the tick. - Spoon! So, anyways. After a bit of ferreting, I found the Coding4Fun: Beginning Game Development article I'd been reading, which contains a section "All about timers". In summary, I grabbed the dxmutmisc.cs file from the sample code (in DirectX SDK\Samples\Managed\Common), commented out everything but NativeMethods and FrameworkTimer, called FrameworkTimer.Start() before starting the Main loop, then did
private void Physics()
{
    dt = (float)(FrameworkTimer.GetElapsedTime()*1000);
to get the time interval since the last physics call. The *1000 is just to get the number into something I could count on my fingers-and-toes. And, with a little tweaking of cosmological constants, all was working again.

Posted on Tuesday, May 01, 2007 by David Campey

No comments

19 April 2007

I wanted to have my game panel run inside a splitter with a collapsible properties panel. This was quite easy to achieve, merely needing the changing of the handle that directX was pointing at. i.e. changing this:

d3dDevice = new Microsoft.DirectX.Direct3D.Device(0, Microsoft.DirectX.Direct3D.DeviceType.Hardware, this, flags, d3dpp);

to this:

d3dDevice = new Microsoft.DirectX.Direct3D.Device(0, Microsoft.DirectX.Direct3D.DeviceType.Hardware, this.panel1, flags, d3dpp);


But-it-broke-my-game.

How? The OnKeyDown event doesn't percolate to parents. That truly sucks. Oddly the only key that does percolate is ALT+key which windows needed to get menu key-presses (ALT-F,X) -- ain't that just too hacky. The mechanism is there, but disabled to frustrate us.

I didn't really want my players to have to play while holding ALT ;) so I went and figured out how to use DirectInput, with the aid of Riemer's tutorial. And it just works. Quickly.

I'm polling the input from my main loop now, and compared to the handling of the OnKeyDown event I'm getting squagillions more keypresses. Needless to say ints became floats (Vector3s actually) rather quickly to handle the smaller iterations.

Other changes include having to have to input de-bounce. I do this by copying the previous state's keys and passing them into the next input parse.

private List Input(List laststate)
{
List seen = new List();
Vector3 rotationInput = new Vector3(0, 0, 0);
KeyboardState keys = keyb.GetCurrentKeyboardState();
if (keys[Key.Escape]) this.Dispose();
if (keys[Key.W]) rotationInput.Y++;
...
if (keys[Key.P] && !laststate.Contains(Key.P))
{
PropertyGridVisible = !PropertyGridVisible;
splitContainer1.Panel2Collapsed = !PropertyGridVisible;
OnResetDevice(d3dDevice, null);
}

...
return seen;
}

And in the main loop:

static void Main()
{ ...
using (Game grav = new Game())
{ ...
List laststate = new List();
while (grav.Created) { ...
laststate = grav.Input(laststate);
... }}}

The debouncer was necessary to do 'edge detection' on the squagillion keypresses that I was getting, e.g. to toggle the property pane once only. The extra call to OnResetDevice is to handle the change in FoV which is done based on the current size of the panel.



End of dev iteration.

Posted on Thursday, April 19, 2007 by David Campey

No comments

17 April 2007

Update: I'm using MDX, Rein's using XNA and Colin has joined us using GL.

My first deliverable was to have an object in a scene with tilt-to-steer and gravity.

This is done.



yay!

The object


The object is a triangle list primitive with a single triangle in it. Each vertex is differently coloured to help with orientation. It whizzes around quite satisfactorily with a simple spring function restoring it to zero-tilt, resulting in a max thrust of about 70deg.

Gravity


Gravity... sucks. Really.

Inverse r-squared explodes quite quickly near to the centre, I had great fun experimenting with my singularity-like point-source gravity and watching things magically teleport off into the far reaches of game-space, never to be seen again. Okay, maybe frustration as well as fun ;) .

Other things



  • I'm thinking of a few weapon types: a shotgun of low-damage point-bullets, thrust based rockets (possibly steerable).
  • Planets should bubble into their positioins from the deep below the playing surface, with a bouyant-spring effect upon arriving. The gravity field vis should ripple away from them as they arrive.
  • Thinking of indicating a planet's power charge by encasing the planet in a platonic solid, increasing/decreasing count to indicate power. Maybe CTF-style planet capturing? Perhaps charged planets repel craft.
  • Sitting in a gravity field charges the batteries in proportion to the strength of the field. See, in the future they've figured out how to generate power from gravity: It's a cunning arrangement of pulleys, levers, cats and buttered toast.

Posted on Tuesday, April 17, 2007 by David Campey

No comments

29 March 2007

So, Rein and I decided to have a little compo. To learn DirectX and make something cool. The first thing I've been able to come up with is a remake of an old game that used to go by the name of 'VGA planets', not the VGA planets, mind you. With such a name, it's just not possible to find in amongst the birdmen and the borg ( I think they've assimilated the original).

Spec:

We have a bunch of planets which remain stationary, players' space ships which are fitted with inertial drives which can be turned off. A ship has fuel and a gun. The gun fires a round that is influenced by the gravity of the planets. The goal is to fire a round that hits your opponent. Probably turn based unless I can figure out a good way to balance timing of firing and try to stop dodging.

Features

Based on my initial thinking I'd like to include these features:
  • bump-mapped planets
  • point sprites spinning into the active player
  • glowy bullets
  • tracers
  • asteroids floating in and around the space
  • side-scroller-esque (or ala crimson land) power ups
  • a pong mode (bounce shields around planets)
  • did I mention glowy bullets
  • maybe some different guns
  • and npcs to feast on
  • landing on planetary bases/docking with orbiting stations for bonuses is hard but rewarding
  • teleport uses a full tank of fuel
  • network play
  • zooming battle field
  • visual of each players ship at full zoom in the corners

Physics

Draw grid for gravity, green standard, bending in and getting darker, and bending out and getting yellower for anti-grav. Tilt-based thrust, optional gyro for stabilising; a gyro should align you to the field at that point.
  • elastic physics - springs and things
  • tilt to steer physics

Posted on Thursday, March 29, 2007 by David Campey

No comments

26 March 2007

So, I had a plane trip ahead of me, and I wanted to be able to use .net StringBuilder with operators, below is the bstring class I wrote to do this. It's pretty straightforward, except the * operator behaves like python's and additionally is faster than a looped StringBuilder because of the pre-calculation (and allocation) of capacity. Still trivial, but it makes the StringBuilder useful without having to remember its syntax.

In testing it (obviously) beat the string class and also was indistinguishable from the StringBuilder in all but the * operator, in which case it was faster.

    class bstring
    {
        private string _tstring;
        private StringBuilder _string;
        public StringBuilder Builder
        {
            get
            {
                if (this._string != null) return this._string;
                else
                {
                    this._string = new StringBuilder(_tstring);
                    return this._string;
                }
            }
        }
        public bstring(string value)
        {
            _tstring = value;
        }

        public int Length
        {
            get { return Builder.Length; }
        }

        

        public static bstring operator + (bstring stringA, bstring stringB)
        {
            stringA.Builder.Append(stringB);
            return stringA;
        }

        public static bstring operator +(bstring stringA, string stringB)
        {
            stringA.Builder.Append(stringB);
            return stringA;
        }

        public static bstring operator *(bstring stringA, int howMany)
        {
            if (stringA.Builder.Capacity < stringA.Length * howMany)
                stringA.Builder.Capacity = stringA.Length * howMany;
            string tstring = stringA.ToString();
            for (int i = 0; i < howMany - 1; i++)
                stringA.Builder.Append(tstring);
            return stringA;
        }


        public override string ToString()
        {
            if (this._string != null) return _string.ToString();
            else return _tstring;
        }
    }

And here's the body of the test class: in the current state it compares a += loop to the * operator:

        static void Main(string[] args)
        {
            bstring bob;
            //bstring joe = new bstring("I am joe. ");
            string bobs = "I am bob. ";
            //string joe = "I am joe";
            int tick = 0;
            int iter = 1000000;
            Console.WriteLine("bstring +");
            tick = Environment.TickCount;
            for (int j = 0; j < 100; j++ )
            {
                bob = new bstring("I am bob. ");

                for (int i = 0; i < iter - 1; i++)
                    bob += bobs;
            }
            Console.WriteLine(Environment.TickCount - tick);
            Console.WriteLine("bstring *");
            tick = Environment.TickCount;
            for (int j = 0; j < 100; j++)
            {
                bob = new bstring("I am bob. ");
                bob = bob * iter;
            }
            Console.WriteLine(Environment.TickCount - tick);
            Console.ReadLine();
        }

and the output, showing approx 50% speed increase from pre-allocation on 100 runs of a 1 million part string:

bstring +
13657
bstring *
7062

Posted on Monday, March 26, 2007 by David Campey

No comments