Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm working on a 2D RPG. I currently have a MainWorldScreen which has a Player entity, and some MapObjects that he can collide against. The player has a few components (sprite, keyboard input) etc. that implement specific logic for it to work in the main world screen.

The problem now arises when I start working on a "battle" screen. The crux of it is, should I reuse/extend my Player entity or create one entity per screen?

Up to now, components are all behaviour based -- sprites to display something on-screen, input components to capture and expose events to handle input, etc. My entities are a composition of components that implement game logic (eg. move on keyboard click).

If I did this as "pure" object-oriented, I would probably have a larger Player class which had all the combined attributes needed for all screens -- list of equipment, health, etc. and each screen would only take what it needs.

However, since I have components, if I reuse my player entity, it doesn't make much sense to reuse it; I will have to remove and re-add new components, since screens use completely different data, and I don't really know where the player state should go (eg. equipment).

What's the right way to handle this? Should I go with one Player entity per screen (at least with these two screens)? Should I keep player state in the entity, and just add/remove components depending on the screen when I pass it from screen to screen?

share|improve this question
    
I thought I'd seen something like this before: gamedev.stackexchange.com/questions/35972/… –  Byte56 Dec 27 '12 at 18:37
    
@Byte56 it's a different scenario entirely; all we have in common are our use of components and screens. I made a conscious decision not to use systems of any sort. –  ashes999 Dec 27 '12 at 19:39

4 Answers 4

Use one core entity for all game screens.

Overall, though, your issue is one of decoupling the correct classes in the correct places.

Method 1: Per-Entity renderer class, separate from core Entity controller

Here you have a different IEntityView (let's call it) component per screen AND per entity, so if you had two game screens and 100 entities, you'd have a total of 200 entity view components. Each of these would reference a core Entity model or model-controller, such that this core class need not be tainted by view-specifics; you then simply select the right one for the current gamestate and the current entity being rendered, either in your root controller or root view for that state, and say entityViewForThisSpecificGameStateAndThisParticularEntity.render() (a Javaesque name if ever you saw one). So if you have one IEntityView component for a minimap, and another for your main game viewport, then each of these holds a reference to the core model or model-controller for that entity, meaning you are indeed sharing key data.

Method 2: Monolithic renderer class, separate from core Entity controller

Here you use a "raw" renderer based approach as common with e.g. OpenGL. Each monolithic renderer pertains to a particular game screen, and will typically be the root view for that screen. You will, inside this monolithic renderer, run through a massive list of entity models or model-controllers (again, nothing view-specific should really be in there!) and render directly inside a single monolithic update function. Again you are sharing key data, but in this case you do not have additional components for every entity; instead the monolithic renderer know everything it needs to know about how to render any entity for this particular screen, given only that entity's data model.

Method 3: Monolithic renderer with pure memory efficiency (TL; DR) This applies not only to rendering, but to everything. The best possible way to access memory is in large, contiguous blocks where data accesses are, if possible, aligned to the cache width of the system in question. This is often lost in OO, as objects are allocated all over the heap. Refer to the final part of Mick West's Evolve Your Hierarchy... If you ignore all OO structure and aim simply for massive chunks of data, you avoid additional pointer references, which accesses cache, which if there is a cache miss, results in a callout to the heap. This is a serious approach for power users only, as it largely foregoes the nice, human-readable structure which OO provides. As the Tao of Programming reminds us,

You must understand the Tao before transcending structure.


Pros, cons to each? The first approach is easiest to conceptualise as it is a nicely encapsulated system and obeys OO principles nicely; however, it is less efficient as more object references bouncing around means (a) more 32-bit pointers and (b) more potential calls out to heap memory, and furthermore it can be restrictive when you need to play tricks with render order and can also introduce issues when comparing stateful vs stateless rendering subsystems (eg. Flash DisplayObject vs Flash BitmapData, if you know those). In deferred rendering on the GPU, the monolithic approach is preferred, as controlling rendering order is a matter of critical importance. Obviously the third approach is only for if you are trying to milk serious performance out of your system, yet for any VM-based platform (Java, Flash, Unity) performance gains are not as cut and dried as we might like, since both the OS and the VM implementations will muddy the water in terms of what might, in native code, be a clear performance gain.

share|improve this answer

Use the same entity and components. What will change is the systems you have operating on the entities. When you load a new screen, use a different set of systems to process your entities. For example, something like this:

if(gamestate == MainWorld) {
    inputSystem.process();
    movementSystem.process();
} else if (gamestate == BattleState) {
    inputSystem.process();
    movementSystem.process();
    battleSystem.process();
    healthSystem.process();
}

Or even better, just have you screens implement a screen class that has a process function and stick all your system updates in there, so it's handled inside the screen class.

This way you maintain the data for your player in one place, the only thing that changes is how it's processed and what is processed. The systems doing the processing don't care what other components your entity has, they're only interested in the components they operate on. There's no need to add or remove any components.

Using multiple entities would mean you'd need to sync data, or have multiple copies of components. Sounds like a mess.

share|improve this answer
    
I don't use that concept of systems; instead, my entities have business logic. Also, this wouldn't explain how to, say, load different sprites in different screens from the same entity. –  ashes999 Dec 27 '12 at 1:27
    
The business logic can take a state as input. Then alter it's behavior depending on the state received. –  Byte56 Dec 27 '12 at 18:38
up vote 1 down vote accepted

Disclaimer: My entity/component system is a bit unique. Components are very low-level (eg. track input state by keyboard, or draw a sprite); entities combine entities and contain game logic (analogous to systems in other EC systems).

For me, it turned out that the simplest solution that worked well was to treat components and entities as view-specific. For example, I would have a "world map" view (entity) for my player, and an "in battle" view (entity) for my player.

The "traditional" model of the player (eg. inventory, health) became a shared object across each player* entity. When switching screens, I simply take the player "model" out of the current screen and hand it off to the new screen.

share|improve this answer

I guess you're talking about player stats like attributes, health, and such? If so, I'd keep these things outside your player in some global "save state" (which will make loading and saving easier as well). In your player entity just refer to the right "position" (e.g. player x or character x as some kind of index or offset).

I assume you're talking about separate combat screens similar to the older Final Fantasy games. As such I'd create a separate game state for this (so separate entities). This allows you to just "push" the combat scene on your game state stack and it's easy to return back to map screen without issues. Once combat ends, you just pop that state and you're back at your world map.

share|improve this answer
    
Global state is definitely not the answer. In fact, it's a well-understood source of bugs and a poor design practice (creates highly coupled code with hidden dependencies) –  ashes999 Dec 26 '12 at 16:47
    
I'm not talking about making all your player data global. I wouldn't make everything global, just what's shared between screens and has to go both ways. –  Mario Dec 26 '12 at 16:50
    
In this case, it would be the whole player "model" that persists; the entity would be a very screen-specific set of components. –  ashes999 Dec 26 '12 at 18:12
    
Yes, that's how I'd do it. There could still be screen specific properties in the player entity, like facing direction, his position, etc. You'll always have some dependencies going back/forth, but I think this way it's easier and cleaner to do than pushing data between states/screens. –  Mario Dec 26 '12 at 18:37
    
Sorry, I still think global state is a very, very poor software engineering practice. There must be a better way to share "model" data between screens when using an entity system. –  ashes999 Dec 26 '12 at 18:52

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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