GDR Forum Index
Podcast Podcast
Dev Dev Logs
Search Search
RSS RSS
Register Register
Log in Log in
Reply to topic GDR Forum Index -> Game Developer's Refuge -> Development Log - Wayward Engine
View previous topic :: View next topic  
Author Message
Gil
Developer

Joined: 14 Nov 2005
Posts: 2341
Location: Belgium
PostPosted: Fri Feb 04, 2011 7:43 pm    Post subject: Development Log - Wayward Engine Reply with quote

Don't worry, it's not a general purpose engine, just a little framework to bundle all the parts I wrote in the past. Once it can render stuff and handle input, I'm coupling it to an actual game, so I don't write tons of stuff I don't need. I'm writing this puppy in C# with OpenGL.

Anyway, I'm working on the low level stuff. Game loop, render loop, event polling, etc...

Since I'm using OpenGL directly and not SDL, I need to write something to handle input myself. Does anyone know how to best approach this? I'm probably going to pinvoke native stuff or use a library. Anything simple, low level and interesting I should look into?

I'll write up some posts on the architecture of certain parts as I get to them.
_________________
PoV: I had to wear pants today. Fo shame!
View user's profile Send private message Visit poster's website
Fling-master
Newbie

Joined: 22 Sep 2005
Posts: 6
Location: Toronto, Canada
PostPosted: Sat Feb 05, 2011 12:08 am    Post subject: Reply with quote

I'd recommend using OpenTK. From your desire to use C# and OpenGL, using OpenTK really seems like the perfect choice. Also works well with Mono, and from the little bit of testing I've done with MonoDroid, seems to work reasonably well on Android too.



(Wow, I haven't posted here in years...)
View user's profile Send private message
Gil
Developer

Joined: 14 Nov 2005
Posts: 2341
Location: Belgium
PostPosted: Sat Feb 05, 2011 5:40 am    Post subject: Reply with quote

I'm glad you did :)

That's exactly the sort of low-level wrapper I needed. Thanks. It's a lot more fitted to my needs than Tao too.
_________________
PoV: I had to wear pants today. Fo shame!
View user's profile Send private message Visit poster's website
Gil
Developer

Joined: 14 Nov 2005
Posts: 2341
Location: Belgium
PostPosted: Sun Apr 24, 2011 5:45 am    Post subject: Reply with quote

I'm currently working on WaywardCommons, a library which provides several useful patterns which I always tend to use. The goal is to provide very simple interfaces and classes to work with.

It currently has 3 parts: Domain, Injection and a few general things.

Domain provides you with the interfaces to properly use DDD (Domain driven design). My framework will have a graph for storing game objects, which will use these. It's got interfaces for Aggregates, Entities, Repositories, etc. The special one here is a generic interface for keys (ID).

Code:
interface IKey<TEntity> : IKey, IEquatable<TEntity>
        where TEntity : class, IEntity<TEntity>
Code:
interface IEntity
{
    IKey Key { get; }
}

interface IEntity<TSelf> : IEntity where TSelf : class, IEntity<TSelf>
{
    new IKey<TSelf> Key { get; }
}


The clue is here that IKey is independent of actual underlying ID. You can choose to implement IKey with ints, longs, Guid, whatever. No matter which database or library I use, IKey will let me work with it.

Then there's Injection, which is a very simple implementation of an IoC container relying on Common Service Locator. I can use this when I want very lightweight independency of concern for easier testing, etc.

There is one more interesting class, which is ContractFactory, which lets you get instances of classes which subscribe to a simple pattern: they provide a private constructor with an IFactory parameter:
Code:
class TestElement
{
      private TestElement(IFactory<TestElement> factory)
      { }
}


ContractFactory is an IFactory implementation, which lets me just do this:
Code:
IFactory<TestElement> testFactory = new ContractFactory<TestElement>();
TestElement element = testFactory.Create<TestElement>();


As you can see, it's a library of simple elegant stuff that lets you quickly design complex architecture, without losing days on actual design.
_________________
PoV: I had to wear pants today. Fo shame!
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1651
Location: Your consciousness.
PostPosted: Sun Apr 24, 2011 7:05 am    Post subject: Reply with quote

Well that's awes... wait... what?
_________________
0xDB
View user's profile Send private message Visit poster's website
Gil
Developer

Joined: 14 Nov 2005
Posts: 2341
Location: Belgium
PostPosted: Sun Apr 24, 2011 7:30 am    Post subject: Reply with quote

I'll see if I can get some cooler examples up later, but if you're not into this stuff, you're likely not going to get why they are cool :)

Don't worry, you'll like the stuff after that (featuring robots).
_________________
PoV: I had to wear pants today. Fo shame!
View user's profile Send private message Visit poster's website
IMakeGames
Contributor

Joined: 13 Apr 2011
Posts: 499
Location: Austria
PostPosted: Sun Apr 24, 2011 3:44 pm    Post subject: Reply with quote

DDD for games? I've used DDD in database-driven business applications, but never to develop games. How exactly do things like Repositories translate to the gaming-context?
View user's profile Send private message Visit poster's website
Gil
Developer

Joined: 14 Nov 2005
Posts: 2341
Location: Belgium
PostPosted: Mon Apr 25, 2011 2:40 am    Post subject: Reply with quote

Repositories are one of the less useful patterns for games, since they deal with persistence, but they function as expected. You'll probably only use repositories for storing away objects in save files for example.

In a business application, they are central to the DDD system, but that isn't particularly a feature of DDD, but more a side-product of how persistence-driven business apps tend to be.

Where the repositories do come into play is scripts. I write my scripts in regular C#, so I can even do compile time checks on them. I store them as plain text source and the repositories have access to a persistence object, which can compile them on the fly.

The persistence system is pretty fun, since it only exposes access to the object, so the game doesn't need to know wether that particular resource lives on the harddrive or in memory, the persistence takes care of all that. The game itself can of course control persistence to make sure performance is optimal. When loading a level, it just asks the persistence to preload for example all the scripts, enemies, etc, into memory, so when the repository grabs them, it's just a matter of returning from memory.

This is just for domain resources like game entities. Resources like graphics are accessed by another system entirely.
_________________
PoV: I had to wear pants today. Fo shame!
View user's profile Send private message Visit poster's website
n29
Developer

Joined: 13 Sep 2005
Posts: 879

PostPosted: Tue Apr 26, 2011 4:38 am    Post subject: Reply with quote

In general, anytime I've thought I needed to use a key other than an int or long when interacting with persisted objects, I've been wrong. Are your keys supposed to be unique per class, or globally unique? ie like a handle? I assume the first, but the latter would be interesting.
View user's profile Send private message
Gil
Developer

Joined: 14 Nov 2005
Posts: 2341
Location: Belgium
PostPosted: Tue Apr 26, 2011 9:07 am    Post subject: Reply with quote

It depends.

Usually - int or long depending on precision needed
MySQL - int
MS SQL - Guid (globally unique generated id!)
Progress - decimal

This library is already being used in three distinct projects, with three distinct key types (MySQL for a daycare center, Progress decimals at work, int/long in my game).

So yeah, it's not one thing or the other, it has to support all of them. It's a bit overkill, but with a little syntactic sugar, I get it all for free. On top of that, it can even withstand a database technology switch without refactoring.
_________________
PoV: I had to wear pants today. Fo shame!
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1651
Location: Your consciousness.
PostPosted: Fri Apr 29, 2011 1:26 pm    Post subject: Reply with quote

Am I the only one thinking it would be about time for persistence to become an optional language feature?

Dealing with caching and retrieval and persisting of objects it's such a nuisance, it would be truly awesome if you could simply provide a compiler flag and at runtime a working folder and the whole programme state would automagically be persisted all the time in the back and even if you switch off the machine or have an accidental power out it would all be right there and back again (object and references/pointers between them being rebuilt in memory from the last on-disk state) if you open the programme again after a restart.
_________________
0xDB
View user's profile Send private message Visit poster's website
Sirocco
Moderator

Joined: 19 Aug 2005
Posts: 9410
Location: Not Finland
PostPosted: Fri Apr 29, 2011 2:19 pm    Post subject: Reply with quote

The only bad thing about that would be having to "reboot" large programs after they started accumulating random errors over time.
View user's profile Send private message Visit poster's website
Gil
Developer

Joined: 14 Nov 2005
Posts: 2341
Location: Belgium
PostPosted: Sat Apr 30, 2011 5:23 am    Post subject: Reply with quote

I think that's actually what my persistence object is going to do more or less. It's not going to constantly write to disc with every attribute change, but I could for example force it to write to disc every 10 seconds. With multithreading, I could actually get away with that without too much performance loss I guess.

I just implemented a lightweight DbC (design by contract) module. I can now call:
Code:
Requires.Distinct(param, "param")
It will throw a runtime exception if the value is null, so I can specify in a method which contracts the method has to abide. Another example is:
Code:
Ensures.That(param > 4, "param > 4")
That's an example of a contract that ensures an output value is bigger than 4. If I document those contracts correctly, I could use a method years later and still see on a glance what input and output a method specifies.

You'll notice I'm reinventing the wheel a lot. These are actually just lightweight implementations to use in cases where it'd be overkill to use an external library to do simple things.
_________________
PoV: I had to wear pants today. Fo shame!
View user's profile Send private message Visit poster's website
Gil
Developer

Joined: 14 Nov 2005
Posts: 2341
Location: Belgium
PostPosted: Mon May 02, 2011 1:50 pm    Post subject: Reply with quote

I wrote my first collection! With that, v1.0 of WaywardCommons is done. The collection is one I keep wishing I had: OrderedDictionary, which is a generic hash table which guarantees ordering. It's different from SortedDictionary, because it doesn't sort on keys, it instead keeps the order the items were added (and allows insertion and removing items by index). I needed this for my lightweight IoC container.

I based it on the Mono source for the nongeneric OrderedDictionary (which strangely does exist) and the source for generic Dictionary.
_________________
PoV: I had to wear pants today. Fo shame!
View user's profile Send private message Visit poster's website
Gil
Developer

Joined: 14 Nov 2005
Posts: 2341
Location: Belgium
PostPosted: Thu May 05, 2011 10:00 am    Post subject: Reply with quote

Monads. As you all know, I love how LINQ lets me do lazy functional programming just in the parts where FP shines. I love the concept so much that I'm writing a small extension platform.

Basically, IEnumerable (which LINQ works with) is a list monad. C# also features a Nullable class, which is its version of the maybe monad. I'm adding identity monad to that with proper extensions for both, so I can call all sorts of chainable binds on them (LINQ style).

I'm also looking into other monads, such as the continuation monad, but Microsoft is already working on including that stuff in the next version of C#, so I'm trying to be a little forward compatible.

Anyone here into functional programming?
_________________
PoV: I had to wear pants today. Fo shame!
View user's profile Send private message Visit poster's website
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10781
Location: Canadia
PostPosted: Thu May 05, 2011 10:34 am    Post subject: Reply with quote

Gil wrote:
Anyone here into functional programming?

My programs have Functions and they also work (Functional), does that count? ;)
_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar
View user's profile Send private message
Gil
Developer

Joined: 14 Nov 2005
Posts: 2341
Location: Belgium
PostPosted: Thu May 05, 2011 12:57 pm    Post subject: Reply with quote

Actually, yes! Functional programming is considered this separate thing that you have to use a near-incomprehensible language for (also, 4 PhDs help). This is simply not true.

Functional programming languages just have different first class citizens. Monads and immutability for example. These aren't very hard concepts to grasp (1 hour and a good teacher for the basics) and can be applied as second-rate citizens in any language.

The trick here is that you are writing lengthy code right now that is already a convoluted form of FP. By writing some simple constructs, you can abstract some very complex code away and make your life simpler. Thousands of developers are writing LINQ queries, with just the understanding of the list monad, without even realizing it.

The maybe monad is a 5 line construct (even in C) that can reduce error handling for IO operations to nothing. It basically works like this:

Try to get resource
Assume you have it
Do operations

In the case of an error, the maybe monad just doesn't actually do any of those operations and a specific "fallible monad" could even store the error, so you can then handle errors separately.

The result: IO handling code, without any exception checking, error handling, null checking, etc. And that's without the "async monad", which allows you to do other stuff while the IO is loading, on the same thread!
_________________
PoV: I had to wear pants today. Fo shame!
View user's profile Send private message Visit poster's website
Ninkazu
Contributor

Joined: 21 Sep 2005
Posts: 482
Location: Austin, TX
PostPosted: Fri May 06, 2011 4:35 am    Post subject: Reply with quote

FP doesn't mean Haskell, either. You don't need purity to be a functional language. You just need lambda.
_________________
Get woke. Stay woke. ~@deray
View user's profile Send private message Send e-mail Visit poster's website
Sirocco
Moderator

Joined: 19 Aug 2005
Posts: 9410
Location: Not Finland
PostPosted: Fri May 06, 2011 6:19 am    Post subject: Reply with quote

Okay, so describe a "monad" in 100 words or less.
View user's profile Send private message Visit poster's website
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10781
Location: Canadia
PostPosted: Fri May 06, 2011 8:45 am    Post subject: Reply with quote

Lambda == a function assignable to a variable, right?

I.e. A Function Pointer or Scripting Language Instance in an ordinary language.

Inlining, like java allows, is just gravy IMO.
_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar
View user's profile Send private message
Gil
Developer

Joined: 14 Nov 2005
Posts: 2341
Location: Belgium
PostPosted: Fri May 06, 2011 9:27 am    Post subject: Reply with quote

Sirocco wrote:
Okay, so describe a "monad" in 100 words or less.


Monads are elevated types. They represent a type, but add information. Imagine that your function returns a boolean or fails. You make it return a fallible monad (of type bool if you have generics/templates). From there on, you work with the fallible bool, knowing that it could have failed. You effectively encapsulated a side effect and don't have to care about that particular side effect, as long as you keep performing functions on that monad. Anyone using that method understands the contract and can check the monad to see if it actually failed.

93 words. It explains enough to understand and work with a monad if you see one. All the other mathematical consequences are really only important once you start writing your own monads, which is something you usually shouldn't do. Give me a full hour of attention, so I can start with the basics and work up to a few examples and I can teach anyone interested in programming the monad. 100 words isn't really fair, that's 2 minutes of talking max. I can instill the concept in 100 words, but I can't sell the thing.

PoV wrote:
Lambda == a function assignable to a variable, right?.


Yes, usually with a specific shorthand notation, which is important too, since it's supposed to improve readability. Compare in C#:

Regular function instance
Code:
delegate(SomeVar var) { return var == 1; }
Lambda:
Code:
SomeVar var => var == 1

_________________
PoV: I had to wear pants today. Fo shame!
View user's profile Send private message Visit poster's website
Reply to topic GDR Forum Index -> Game Developer's Refuge -> Development Log - Wayward Engine

Use this link to get a Sign-On Bonus when you get started!

All trademarks and copyrights on this page are owned by their respective owners. All comments owned by their respective posters.
phpBB code © 2001, 2005 phpBB Group. Other message board code © Kevin Reems.