We'll get to the bottom of this :)
I don't have ANY such problems when I execute this demo, but I've been in your position myself in the past.. some badly-designed code would run ok for other people but not for me :P

HeapAlloc (MemAlloc) CAN FAIL, but generally this only happens after allocating MANY SMALL BLOCKS - basically, the Heap's internal defragmenter is crap, and eventually you start getting NULL instead of pointers to allocated blocks.. again, I must point out, I've only encountered this problem while attempting to allocate hundreds of thousands of small blocks.. and this demo doesn't do that.

In the past I've proven that it was the memory manager in Windows which was at fault because a reboot made the problem go away.

Regardless, I'm willing to investigate this problem and solve it, just give me a couple of days grace as I've just finished translating the DirectPlay and DPlayLobby includes and I want to have a play around with those immediately (I'm used to writing my own network code from the ground up, but since DPlay has been rewritten recently I figured it was worth another look - they've added voicechat, bluetooth support and other fun stuff).
Basically that's why I haven't made any updates to this project in the past few days : I wanted to decide what kind of networking model I should implement. I was leaning toward separate client and server modules, however Dplay makes it fairly easy to write both the server and client sides under one roof, and just has too many features to be ignored.
Posted on 2006-07-19 01:47:33 by Homer
The attached zip contains one new Object, and a little more error-checking (in response to mdevries' bugreport).

The new Object is a replacement for D3DApp.
Its name is D3DGame, and it inherits from D3DApp.
I felt that D3DApp was a useful class for D3D applications in general, and that it would be improper to start adding game-related code to it.
Therefore my solution was to derive a new Class from D3DApp - it inherits all of D3DApp's functionality, and builds on it without cluttering the D3DApp class with code that may well be irrelevant (imagine you wanted to make some kind of 3D tool, NOT a game, you might be understandably upset about 'useless' gamecode bloating your binary).
D3DGame currently contains no code to speak of, but I've posted it in its present form anyway since it's a very clear example of pure inheritance, and I presume some of the less oop-savvy people will benefit from seeing this.. A lot of asmcoders don't see much value in OOP, maybe more posts like this one can help to adjust that attitude.
We're not 'selling out', we're riding the fence between two worlds, taking onboard the best aspects of the old and the new.

Note : This zip contains two BMP files.
I'll be omitting them from future updates, since I'll assume you already have them.

Comedy of errors: A while ago a private Australian contractor was working on a new helicopter simulator for the US Defence forces.
He'd written a 'Soldier' class previously, and decided that he could save a lot of time and effort by deriving the simulation's combatants from his existing class. One particular aspect of his contract was to implement enemy AI which featured 'scattering and swarming' behaviours, particularly wildlife, so that trainee pilots could learn to tell the difference between wildlife and combatants from the air.
At last the day came when his new simulator was to be demonstrated before the top brass. Australian military had also been invited to attend the demo, and did so.
The black hawk thundered along above a grassy savannah.
Below, a herd of kangaroos scattered before the mighty black hawk.
After the chopper had passed in front of them, the herd of kangaroos began to reform.
Then, to the suprise of everyone INCLUDING the programming team, the kangaroos produced shoulder-mounted surface-to-air missile launchers and took out the black hawk.
Needless to say, the US military were not amused... the Australians found it rather amusing however.

The moral of the story is this:
Use inheritance sensibly, don't be a lazy git.
Attachments:
Posted on 2006-07-19 02:51:32 by Homer
Hi Homer,

I decided to have a look at the following demo's you uploaded.
From GameClient17 on I don't seem to have problems.
So, I only have problems with GameClient15 and GameClient16.

Friendly regards,
mdevries.
Posted on 2006-07-21 00:08:54 by mdevries
Thanks for the feedback, that's interesting, I'll investigate what changed between 15 and 17 while I'm writing the html for this tutorial.

I've just spent a couple of days learning more about DirectPlay and DPlayLobby... unfortunately it seems to be remarkably unpopular.
I can't really understand the lack of general interest in DPlay, I must conclude that most people see it as being a complex abstraction of WinSock (which it is, but it's so much more) and think they're better off just writing all the networking code themselves.
Anyway, I'm not ready to introduce DPlay into the tutorial yet, I require more time to familiarize myself with it.. the api is quite large.
In the meantime, there's more code that can be added to the framework.

WHATS NEXT:
I will implement a way for the user to bind keyboard keys and mousebuttons to callback functions, so we can later allow the user to create their own 'key mappings' at runtime, and store those in our handy configfile.
I'll be adding some basic audio support, which we'll build on later.
I'll be adding support for 'Billboards'.
I'll be adding code for a static 'Loading' screen based on a Billboard.
I'll be adding support for 'Billboard Buttons'.
I'll be adding support for 'hierarchical menu' based on 'billboard buttons'.
Basically I want to avoid using a Dialog to choose Networking options.

At this stage we'll be able to implement a basic mouse-driven rendered menu, and then it will be time to revisit the Networking stuff, and make a decision on whether to implement this game as peer-to-peer or client-server, or whether we can/should support BOTH.
At that time, we'll also begin talking about Lobby servers.

I'm just rattling along at my own pace, putting this 'game engine' together in whatever order I've felt was warranted.
If you have a suggestion for something you feel should be implemented next, or a request for something specific, just ask :)


Posted on 2006-07-21 06:16:40 by Homer
Hi Homer. DirectPlay is deprecated. MS recommends using sockets for all Networking.
Posted on 2006-07-21 16:22:04 by ti_mo_n

DirectPlay has been around in some form since the early days of DirectX, and they DID recommend not to use it at one point because it was a mess.
That is old news - DirectPlay was totally rewritten and expanded :)
Microsoft now recommends that we don't use the 'base objects' but rather use the 'DirectPlay8' objects (such as DirectPlayPeer8).
The headers I've translated are from the April 2006 SDK, and include NAT traversal, bluetooth transport and other stuff that simply didn't exist in early releases of DPlay.

I believe the lack of interest in the CURRENT INCARNATION of DPlay is a direct result of this misunderstanding: the internet is peppered with references to the OLD versions of DPlay, along with similar statements of deprecation.
Posted on 2006-07-22 02:15:39 by Homer
Please ignore the new stuff in D3DGame class (I'm messing around with DPlay).

I've implemented a means for the User to decide what happens when a keyboard key is pressed down.. initially I wrote it as a new class called KeyboardManager, but then decided it was better to add this code directly to D3DApp (and thus to D3DGame).

D3DApp now manages a table of 256 Pointers to user callback procs, and has a new Method (SetUserKeyFunction) which allows the user to associate one keycode with one callback function. This is commonly known as 'binding keys', since each key is 'bound' to a function.

The ESCAPE key and the ALT-ENTER keycombo are still managed by D3DApp, but any other keys can be set up by the User.

In order to show this more clearly, I've moved the code associated with the Cursor keys from D3DApp into the main .ASM file, and added some code to the application entrypoint which binds those keys to the appropriate functions.

Later when we begin working on an in-game Menu, we can allow the User to set up their own key bindings, and remember them in our config file.

If you wish to DISABLE a previously-bound key, just set its function pointer to NULL..
eg : ICall pGame::D3DGame.SetUserKeyFunction,VK_SPACE,NULL

Attachments:
Posted on 2006-07-22 03:12:48 by Homer
Hi Homer,

Has GameClient_19 fallen out of the sequence? It's not in one of your posts. You hopped from GameClient_18 to GameClient_20.

In GameClient_21 you happen to include these files, which are not in the zip file:
- Dplay.inc
- Dplay8.inc
- DPlobby.inc
- DPlobby8.inc

I only have Dplay.inc and the corresponding Dplay.lib.
But I think they are old (2003).
Where can I get these files, and the correspronding Lib files?

Friendly regards,
mdevries.
Posted on 2006-07-22 07:02:30 by mdevries
Hi Homer. DirectX SDK states clearly that:

Use of DirectDraw is no longer recommended. With the release of Direct3D 9.0, all two-dimensional functionality is contained within Direct3D and its associated helper functions in D3DX.

DirectPlay is deprecated, and Microsoft strongly recommends against using it to develop new applications. Game developers should use Windows Sockets (see Windows Sockets) and the Windows Firewall APIs (see Games and Firewalls).

DirectShow is no longer recommended for game development. All of the DirectShow components (headers, libraries, utilities, tools, and samples) were removed from the DirectX SDK in the April 2005 release. DirectShow is available in the latest Platform SDK Install.


Please go to http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/DirectX_9_Components.asp . The quote above is from there. Addtionally, somewhere on MSDN forums one guy said that they don't plan to support DirectPlay in 64-bit mode.

I don't have anything against learning DirectPlay (it has some nice functionality), but if someone wants to learn it now, then it might be a waste of time. What do you think?
Posted on 2006-07-22 11:04:12 by ti_mo_n
In regards to tutorial #19 - whoops :) Pretend you didn't notice - nothing substantial changed in there.

In regards to DirectPlay:
I'm wondering why, if DPlay is deprecated, that it was rewritten from the ground up for DX8, and then expanded in DX9... it appears to me as if m$ have quoted themselves from outdated documentation (smell the cut and paste coders), and totally neglected to mention in that statement what has occurred inbetween..unless you can provide a substantial reason why the CURRENT incarnation of DPlay should be ignored, I'll cover it in due course.. however, if you CAN provide valid reasoning for not covering DPlay in its current incarnation, I'll just build up OA32 code which achieves the same things (well, maybe not as nice..)

As for the DPlay and DPlayLobby files, they'll be added to the next public release of OA32.
If you insist, I'll supply them early.
Otherwise, just comment out any references to them.

I guess I should really be covering Orthographic Projections and their relationship to Billboards next.


Posted on 2006-07-24 09:38:00 by Homer
Hi Homer,

I would welcome an early release of the DPlay and DPlayLobby files, if you decide to use them. In that case, please supply them.

This is a great project. Many thanks for your efforts, Homer!!

With this educational project, you aim for a specific public, and you want to attract them even more to the interesting field of game programming.
Missing files, only available in the next release of ObjAsm, could distract some of them from this project, and we don't want that, do we?

B.t.w. Biterider, if you are watching this:
When is the next release of ObjAsm planned?

Friendly regards,
mdevries.
Posted on 2006-07-24 16:03:55 by mdevries
Hi
Due to personal issues, I think that I can release the next OA32 version mid/end august.

Biterider
Posted on 2006-07-25 01:01:00 by Biterider
DirectPlay headers attached (April 2006 SDK).
Posted on 2006-07-25 02:58:58 by Homer
Just a small update today, in which the game engine architecture received a minor overhaul.

I decided to do something with the BrickManager object, which until now has just been handled by the main asm file.
I moved BrickManager into the World object.. thus, the World owns the BrickManager and all of its Brick instances, and is responsible for Loading and Unloading and so on.
The BrickManager object now has a new method called 'RenderAllBricks".. the RenderBrick method was slightly modified to eliminate multiple calls to set the FVF and the render states.
I'll probably rename the World object and use it to enshrine any code that is specific to THIS DEMO GAME, leaving the D3DGame object as generic as possible.
The World object now has some extra methods including its own Render method.
The World::Render method makes a call to BrickManager::RenderAllBricks.
Now when we make a call to 'render the world', all Bricks are rendered.

Mostly I've only moved some code around.. but the result is a huge difference in the clarity of the engine architecture in terms of the relationship between various objects.

I've decided NOT to cover orthographic projections just yet.
There's a high probability that I'll cover the loading, rendering and management of arbitrary Mesh objects and their instances in the next update, since it's about bloody time we had a Player object :)

Loading mesh objects is not the most simple thing in the world, but it's not terribly difficult either.
Rendering them is a cakewalk.

As a closing comment, I'd like to point out that the Creation of the BrickManager and its Bricks is being driven by one of our main user callbacks (GameReloadVolatiles).. for a VERY good reason.

When the Application starts, we HAVE NO D3D DEVICE - we get the Dialog to choose 3D settings.
We CANNOT LOAD ANY RENDERABLES until we have a Device.
Fortunately, our ReloadVolatiles callback is NOT CALLED UNTIL WE HAVE A DEVICE... which makes it IDEAL for LOADING STUFF.

Have a nice day :)
Attachments:
Posted on 2006-07-26 02:38:47 by Homer

Now we can start to draw a mental image of the game engine's architecture.

At the 'main asmfile' level, we have just TWO objects.. D3DGame and World.

The World object owns an instance of BrickManager, which owns any number of instances of the Brick object. Additionally, its important to note that our World instance is associated with our D3DGame instance through its pOwner field (set by the Init method)... thus World can call any method of D3DGame, its ancestors, and its owned objects.

The D3DGame object represents the bulk of our game application framework , including managed callbacks.

The only other code in the project, which is located in the main asm file, represents a number of user callback functions that are called by D3DGame on demand.

We might say that the World object is a kind of 'plugin' which supports stuff that D3DGame doesn't natively support, but which RELIES on D3DGame to manage it.

Eventually, I'll probably show how we can move all the D3DGame code into a DLL, highlighting its modular and reusable nature.
That's a rather pointless exercise, since we consume the same if not more memory, it's an illusion to make our exe smaller, but it's just not 'the done thing' to release a game as one huge exe - for whatever reason, people expect the exe to be of reasonable size, and so we'll pander to the whining majoritah when the time comes.

Posted on 2006-07-27 04:27:12 by Homer
I haven't found much spare time in the past few days, time is valuable.
Anyway, for those of you eagerly anticipating the next lesson, here's a sneak preview.

The attached file contains code to load and unload a 'static mesh' from a '.x' file.. we're going to implement our 'player' with one of these.

Static meshes typically contain no animation data, and no 'joints'.
This is not to say that we can't animate them, or construct complex jointed critters from several of these so-called static meshes, however it does imply that more complex file-based meshes exist.
Generally speaking, meshes contain the following things:
-A VertexBuffer containing Vertices
-An array of one or more Materials, which may or may not be Textured and/or have some degree of translucency.
-An array of 'Faces' (something new for us)
In D3D, Faces are always simply Triangles, or to be more precise, a Face is described by three Indices which represent three Vertices of a Triangle.
The indices are 16-bit WORD sized integers and are zero-based.
Faces are grouped according to which Material they are to be rendered with, and these groups are known as 'Mesh SubSets'.
We can 'sort faces' according to other criteria, but by default, faces are sorted by Material automagically when we Load the mesh.
When we ask D3D to render 'a subset of a mesh', typically we are asking D3D to 'render all the Faces which use a given Material'.

I've designed this D3DMesh object such that it 'parented' to the TextureManager, which may seem counterintuitive at first.
Read the comments in the sourcecode and my motivation and intentions should become clear.. (as clear as mud?).

I haven't included the code to create, destroy or render this object.
Just know that as little as  ONE LINE OF CODE is required to render it (if we don't care about in which order our Materials are rendered).

Understandably, the missing code belongs NOT in this class, but in whatever class Manages its Instances, which in this case is the class we currently call TextureManager.

Tomorrow we'll upgrade our TextureManager class.
We'll be renaming it to ResourceManager, and adding support for Loading, Unloading and Rendering of D3DMesh instances :)

We're going to add code that manages Instances of an object which are  based on a Reference object (ie, share a loaded resource).
By doing this, we can load a Mesh once, but create any number of Instances of that mesh in our World, as we've seen already in regards to our Boxes and their BoxManager..

Questions?


Attachments:
Posted on 2006-07-27 12:04:42 by Homer
Here's your next update.

D3DMesh was added, but its Load method was moved into the TextureManager class...
D3DApp.FlushTextures was renamed to FlushResources.
The TextureManager was rebirthed as ResourceManager.
It now manages loading and unloading of unique filebased resources, and so far handles textures and meshes.. any textures associated with meshes are loaded via the ResourceManager as you'd expect.

No code is provided for rendering loaded meshes (yet).
That will appear in the INSTANCES MANAGER for Meshes, which also is not (yet) provided.

Think of the ResourceManager as a manager of UNIQUE SHARED RESOURCES, ie, 'reference objects'.
We load resources ONCE, then we can create N 'instances' of some object which requires resources.

What I'm implying is that we still need a 'D3DMeshInstance' object, whose fields contain data unique to a specific instance, as WELL as something to manage the instances of it... the REF objects which we load and unload have very little to do with runtime instances, except that they act as 'templates' at runtime, and vastly improve memory efficiency through the sharing of such resources.

The (TextureManager 'was' and the) ResourceManager is an integral component of D3DApp, and as such, D3DApp and thus D3DGame both received these latest changes.

Next, we'll look at the 'instance object' for meshes.
This will be just a little more complex than our 'Bricks', since we're going to add a new feature : in addition to being able to Position our mesh instances in 3D space, we'll be able to Orient them (ie 3D rotation).
As soon as we can rotate, position and render mesh instances, we'll add our Player to the World, and hook up some keys to control it :)

Now tell me how you feel about this tutorial so far :)
Am I going too fast or slow? Do you feel I've missed anything or spent too much time anywhere? Do you think you have gained anything from reading this stuff? etc
Be honest, I won't be insulted easily.
Attachments:
Posted on 2006-07-27 23:44:12 by Homer
After some soulsearching, I decided to implement the manager of mesh instances within the D3DMesh object (which represents a loaded reference mesh).
In English, this means that mesh reference objects each manage a list of instances of themselves.. does that make sense?
We need to understand what is a Reference object as opposed to Instances of it.
A Reference object is a shared resource - you load it once, then create N instances of it in your virtual world.
I've designed the D3DMesh reference object to act as the manager of N instances of D3DMeshInstance.

Tomorrow, like I said, you'll get to see this code in action.

I'm a little disappointed in the lack of feedback apon request.
I'm not going to bite your head off, and I have no expectations.
Please give me some guidance - am I doing OK so far?
I value YOUR opinion, don't be a girly man (or worse), you have nothing to lose by voicing your opinion.

Posted on 2006-07-28 08:00:37 by Homer
Hi Homer
Iím following closely your work and the way it evolve  ;)
Iím curious about the mesh rendering code, but I think I have to wait a little bit.

Regards,

Biterider
Posted on 2006-07-28 08:05:49 by Biterider
Considering that this is just an introduction, it's nice :) . Though, the usage of global floats with names like "r4_m10" instead of introducing a FP() macro and definitions could be ugly (at least for me it's unacceptable). Instead, I'd do:

CAMERA_SPEED equ 10.0
...
OnCursorDown proc uses esi
mov esi,pGame
OCall .D3DGame.pMainCamera::D3DCamera.Move_Camera,FP(-CAMERA_SPEED),fElapsed
OCall .D3DGame.pMainCamera::D3DCamera.Update
ret
OnCursorDown endp


Hopefully some of the future tutorials will be on game-coding style :). Imho, it's something that can make or break your determination to complete a game-project. By "good style" I mean splitting the whole system of the game into different managers, usually: Draw2D,Draw3DAnim,Draw3DStatic, DrawBSP,SceneMgr,Input,...
Though, I don't regard myself as being literate enough in gamedev, and I could be seriously wrong.


I'm also curious about the mesh-rendering code ;)

About the manager of mesh instances, isn't that just a vararray of triples ? (or vararray of pointers to structures that can hold these 3 items).
Posted on 2006-07-28 20:49:59 by Ultrano