1
\$\begingroup\$

I've been working on a little game for the last few months, trying to approach it as a software engineer and employ best patterns and practices in my coding. I have gotten to the point where I have to distinct elements in my game.

  1. The Game Logic: aka business logic. Its the meat of the game rules. It contains all information about game objects (such as Character, Weapon, and Item class definitions). It contains the game world as far as rules are required; mainly so Characters are aware of the world they are in, and who else is in it. It contains a chunk of logic use to determine how Fighting is resolved between Characters, as we as other game actions requiring rules. It contains my AI implementations. So in reality it's a combination of Class definitions and Service logic.

    As it stands, the Game Logic can actually play out a game without any interface. All I need to do is create a World, add some Characters to it, assign some AI's to them, then in a loop tell their AIs to run. The result of each AIs action is reflected in the states of the Characters (eg, if damaged, health is reduced), and a summary of what happened is returned by the execution (which is intended for the UI to make sense of what happened).

  2. The Game UI: which is using Cocos2d-xna for WP7. It contains definitions of all the different animations. It takes in inputs and sends the to the Game Logic, and renders its results.

    As it stands, as well as all UI components for a Character (textures, sprites, animations) a UI Character also contains a Begin method which executes a Cocos2d Sequence (ccSequence) to do two things 1) Execute AI and render result for this Character 2) Re-Execute the sequence (essentially its own call back loop for executing actions).

The problem I keep running into is, the more I try to keep these two layers separate, the more they need to come together. E.g., my UI Character which is used to render what the Game Logic character is doing, so it needs a reference to the Character object from Game Logic. When this Character's AI attacks someone in the Game Logic world, the UI needs to know what happened. This works fine for rendering its own Animations based of its results, but to know what to do for other Characters affected by this action is difficult as I dont have reference to them. At the moment I do this by queuing up Pending Animations in the other character's Game Logic Character and render it when that character next executes, but this is anti SoC (Separation of Concerns) as it now contains something specific for the UI to focus on.

I don't want the two projects to merge into one where a Game Logic Character contains all things UI as well, such as animations and actions. Is there a nice clean way that is used for this separation? Ideally something that works nicely with Cocos2d's Action pattern?

\$\endgroup\$
2
\$\begingroup\$

I agree with Engineer's answer, where the main point is "don't fight the framework".

Games are different

However, another point I want to add is that when it comes to software, games are different.

Even though the article is a bit outdated by now, I want to quote a part from Joel's five worlds of software programming:

Here’s an important thing to know. Whenever you read one of those books about programming methodologies written by a full time software development guru/consultant, you can rest assured that they are talking about internal, corporate software development. Not shrinkwrapped software, not embedded software, and certainly not games. Why? Because corporations are the people who hire these gurus. They’re paying the bill. (Trust me, id software is not about to hire Ed Yourdon to talk about structured analysis.)

All that clever architecture stuff like MVC, onion architecture etc, is not made for games.

Have an anecdote

I struggled for about half a year to develop a layered approach to writing a game in Unity3D, until I finally thought good and well about a thing as simple as movement.

You probably want to put some kind of normalizing code in between input and actually moving your game elements - but passing a Vector2 down 3 layers, only to do some super simple math with it and then passing it up 3 layers again is just over-engineered. Especially if you just quickly wanted to try it and might scrap it again in a week, as is common when developing games.

Business rules

Another problem is that what is called "business rules" in corporate software is just very difficult to differentiate from the rest in a game. For example, look at collisions: If two boxes collide, it would be a business rule that they move in a certain way after that - but you don't want to write a whole physics engine in your business layer. You just want to create a box and then let the physics engine handle it.

Have another anecdote

Now, here's the thing: At my workplace, we also use Unity3D. Not for making a game, but some architecture stuff. We mostly just use the engine as a 3D renderer (plus the physics engine for a few raycasts etc). I managed to get it working with a Clean Architecture approach. It wasn't too easy, but I am now reaping the benefits from that. There's no ongoing real-time processes. It's mostly the user clicking buttons in the GUI and then something happens in the virtual world and for that, it works. I did that before I failed trying to create a game this way - so it's not an experience thing.

It's not really the game-ness that makes the difference, but the real-time-ness of things colliding and spawning and raycasting etc. If you make a management game which is really just clicking buttons in the UI, those corporate architectures will work just fine (but will still take some tinkering to play nice with game engines).

We can still separate concerns

With all that being said, concerns can still be separated - it just doesn't work in the same way as corporate software. The arguably most established way to separate concerns in games are Entity-Component-Systems. Here, rendering is the concern of the renderer component and playing audio is the concern of the audio component, but these components don't care about each other.

As it happens, that is exactly what Cocos2D gives you.

So, going a full circle towards the beginning of this answer, "don't fight the framework", but if you want your concerns separated, Cocos2D gives you a way to do that, which will play nice with the rest of it.

\$\endgroup\$
1
\$\begingroup\$

If you want decent SoC for games, without annoying wrapper code and consequent performance concerns, you should to pick a language / platform / library combination that meets that goal in the first place, or at least gives you the ability to write your own framework without undue restrictions.

You'll soon enough get the Cocos2D guys telling you to do it the Cocos2D way. And I'd agree with them. There is no inherent MVC separation there, and trying to force it will make your life harder.

(I maintain a small, cross-platform library on google code which exists for the purpose of cross-platform SoC. I wrote it in such a way as to make it repluggable between languages / platforms, but some are just too far gone to bother with. Take Unity3D for instance. The core classes / "framework" that they have in place is so obtrusive and over-engineered that while I certainly could wrap Unity3D, I'd probably not even attempt the task in the first place -- not to mention that wherever an accepted framework already exists, the associated community could probably be said to hold fairly rigid beliefs about how awesomely structured it is, and so tend not to want to adapt to a whole different structure. Hence the above comment about the Cocos2D guys. They have a point, even if the architecture they're willing to use, is not particularly well thought out.)

But this is about your coding comfort, not anyone else's. So for decent architecture, my advice is look into rolling your own in a more flexible, less assumptive language / platform like JS, Python, Java, C or C++.

Adapt, or move on.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.