Graphic Agnostic Architecture Thoughts?

BlitzMax Forums/BlitzMax Programming/Graphic Agnostic Architecture Thoughts?

BLaBZ(Posted 2013) [#1]
I came to this realization recently that most of the games developed with BlitzMAX and minib3d and Blitz3D are build on top of their underlying frameworks.

Meaning if you built a game with BlitzMAX and miniB3d and later decided you want to replace what you have with Ogre, if you're using a lot of miniB3d's feature it could mean you have a lot of work ahead of you.

If you plan on writing a large reusable quality game engine does it make sense to make it as Graphic agnostic as possible? In the sense make your engine do all the movement calculations etc, and then let the graphic api determine how\what 3d models to load then just call the basic graphic commands such as RotateEntity and PositionEntity.

It would make a well written engine more reusable across platforms, as well as make it much easier to change to the latest graphic engines.

I imagine this is how most modern games are developed.

Thanks!


Hardcoal(Posted 2013) [#2]
I like your approach


ImaginaryHuman(Posted 2013) [#3]
It depends on your motives and interests, if you're just doing this for personal pleasure and not as a business, good for you, but otherwise, drop the whole `lets make engine #3492309423094`. It's a huge waste of time. In fact, adding this abstraction layer on top of an API which is already on top of an abstraction layer (DX/OpenGL) is a waste of time. Especially since you're only ever going to make blitzmax apps for Mac or Windows or Linux, that's only 3 platforms to consider. And in what likelihood would you decide to swap out an entire 3d engine at some future date? I mean, when it comes down to it from a programming perspective, sure it makes sense and seems nice and clean and logical to be able to literally flip a switch and jump between engines. But you really are only likely to decide to use one engine for a project once, it's not like you're going to be jumping back and forth many times, right? So just pick something and go with it and get something done.


Yasha(Posted 2013) [#4]
To simplify it a bit... what you are proposing is precisely what things like miniB3D and Ogre are already for.

No, they don't have the same API; that's because they are different things (just as someone else having the same idea as you wouldn't create the same engine-wrapper-layer API); and no, it's really not normal to swap out something so high-level once a project is under way. Doing that is a sign something has gone seriously wrong with your initial plan. (In fact it's not only not how modern games are developed at all - it's a great way to kill a modern game: c.f. Duke Nukem Forever; contrast Half-Life and Source.)

Adding an extra layer on top is guaranteed to mean 1) more work, as you need to rewrite it for every engine you want to support (and since the entire point of your layer is that their layers differ from each other, you must rewrite it); and 2) very poor control as you will end up sacrificing the fine elements of each engine to make them fit together.

This is abstraction for its own sake and would add nothing of value to your project, while making a lot of extra work and massively complicating its overall design (I would go so far as to say that this could not do anything for a "well written engine" because using such a pattern precludes the engine being "well written"). If you want to be able to change backend, you should use or write an engine that can already do that; don't wrap entire engines.


Analogy: When you set out to go to work, you choose at the start of your journey whether you want to take the train, drive, or cycle. What you do not do is design a suit of power armour that dynamically translates your steady jogging motion into either sitting on a train or steering a car or cycling, with the ability to randomly leap off the train and carjack passing commuters.


BLaBZ(Posted 2013) [#5]
@ImaginaryHuman - I am doing this for business purposes which is why it's important to have the logic as loosely coupled to the graphics Engine\API as possible. I do plan on having versions written in different languages as well, so not becoming dependent upon the blitzMAX libraries is important. I've been working on my current project for the last 3 years and I'll continue developing it for the next 3 years. Having code that can stand the test of time is important to me.

What I'm suggesting is don't use something like miniB3D to influence any of the logic in a game. Don't use it for collisions, don't use MoveEntity or TurnEntity, but instead let your game logic\engine determine entity coordinates and just use PositionEntity and RotateEntity base on the values the engine provides.

@Yasha - Imagine if Newton Dynamics or nvidia's PhysX was distributed tightly coupled to a single graphics api. They would be far less desirable to use in games because you'd now have the constraint of the graphics provided.

The reason I want to do this is I have an algorithm that performs a function quickly and flawlessly and I'd like to distribute this algorithm without forcing the client into a specific 3d engine\api.

Thanks for your input guys! I don't know if I'm doing a good job of explaining myself but I do enjoy dissecting this idea from every perspective.


Kryzon(Posted 2013) [#6]
It will depend a lot on the engine and platform you are using. But you can do it to some extent with scripting.

Whether you use LUA, Python or something else, you script how you want your game to behave.
Scripting is primarily used because it's a 'productivity language', meaning it's very fast and easy to program your game with it.
The added benefit is that you're using yet another abstraction layer.



Your scripts should work under a 'framework' which is also written in script code. That is, you have script files that define classes that communicate with the engine.
But your actual game scripts don't call engine functions directly; they instead call only the script framework functions. This effectively decouples your logic from the peculiarities of the engine you may be using.

To illustrate, consider a 'script framework' method that changes the current audio volume of your program. Call this method "SetVolume". This method calls the audio engine's method to change volume.
Now say that this 'audio engine' you're using controls volume by using a floating point value (0.0 ~ 1.0).
So all your game scripts call the script framework function to set the volume, and use a floating point to set this volume.
Now consider you have to port your game to another platform, with some proprietary audio engine that uses a byte value (0 ~ 255) to control volume.

Instead of going through all your game scripts changing the value from floating point to byte, you instead go straight to your "SetVolume" function in your script framework, let it keep accepting float values so you don't have to change anything in game scripts, but rather inside this framework function you map the floating point value to a byte value: (value * 255).
Therefore you have just interfaced with the new audio engine and managed to keep your game scripts intact.

With a consistent and well-thought script framework, you can change its methods and functions to accommodate the new engines you change to, while giving the same result back to the game scripts without having to change them as well.