Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (121)
games submitted by our members
Games in WIP (577)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Handling Layers of Action Code  (Read 2764 times)
0 Members and 1 Guest are viewing this topic.
Offline coltonoscopy

Junior Duke


Medals: 2



« Posted 2012-08-08 07:18:25 »

Hey, everybody!

I'm making a little headway into my game's engine code. However, I'm running into a roadblock (of sorts, anyhow).

Currently, I'm working on implementing the model by which entities in the game expend functionality. I have an Entity class which extends to classes like Sprite, Creature, Player (in that order), ItemEntity (which models items dropped in the game world with their own collisions to detect if the player is near), WorldObject (which is anything not bound to my game's tile map which can basically have its own functionality but is also well-suited to complex decoration), and so forth.

There is a slight problem I'm having, however. The issue is that I feel in order to access the functionality I'm trying to give my Entities so that, say, Entity A can spawn an ItemEntity at coordinates X and Y in the game world, I have to access several layers beyond where that Entity lies (for example, making calls to access the GameManager and ResourceManager to access the current TileMap in use, etc.) to get to that functionality in the first place. My entities have what I have deemed to be called EntityActions, which are basically actions entities can execute at any given time. Say I want to spawn an item when an enemy dies.... upon that entity's death, it will call the perform() function of that corresponding EntityAction, which would look something similar to

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
// called in the main "GameManager" class
entity.die();

// this code exists in the entity's file
public void die()
{
   // sift through the entity's actions to get a spawn action
   for (int i = 0; i < actions.size(); i++)
   {
      if (actions.get(i) == Action.SPAWN)
      {
         action.get(i).perform();
      }
   }
}

// the perform function is defined in any entity subclass and is basically a big switch statement
public void perform()
{
   switch (action)
   {
      case SPAWN:
         // handle spawning code here for items
         break;
   }
}


I guess I could theoretically get this whole design working with parameters that point to the game's GameManager and TileMap classes and whatnot, since those are what will be in charge of managing spawned items, but this just seems entirely efficient, and I feel like my design is fundamentally flawed; in fact, I'm sure it is. I was wondering if you guys could offer me some suggestions on where my design might be tweaked so that it makes more sense or is even more robust and generic on account of it! Thank you guys so much for your time!

Best regards,
Colton

Straight flippin.
Offline 65K
« Reply #1 - Posted 2012-08-08 07:38:36 »

My first suggestion is to explain the idea of your design, what you want to achieve and the expected benefits.
Reading Entity is higly suspicious...

Offline Roquen
« Reply #2 - Posted 2012-08-08 07:56:21 »

I'd just have explicit handlers for each action..no searching and no message pump switch table, but yeah more info is needed.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Ultroman

JGO Knight


Medals: 25
Projects: 1


Snappin' at snizzes since '83


« Reply #3 - Posted 2012-08-08 13:24:51 »

Yeah, more information would be nice, but I think what you want is a GameActionHandler class to pass around. One you can send commands through. You could have different handler-classes for each event, like ItemSpawner, MonsterSpawner etc., and let the entities that are supposed to do these things get them in their constructor as a parameter. So an abstract SplittingMonster-class which becomes 3 smaller monsters when it dies, can just use this handler to spawn an entity of your choice at its position on cue.

- Jonas
Offline coltonoscopy

Junior Duke


Medals: 2



« Reply #4 - Posted 2012-08-08 23:08:35 »

My first suggestion is to explain the idea of your design, what you want to achieve and the expected benefits.
Reading Entity is higly suspicious...
Sorry, I'll try to elaborate a little bit more!

Basically, everything in my game which is interactive or possesses some kind of functionality beyond being a tile is an Entity. However, I have several Entities.... Sprites and Creatures to represent the base for all creature-based entities, WorldObjects to represent things in the game which are objects but which possess some kind of functionality (like trees that can be cut down, pedestals that can be activated, etc.), ItemEntities that represent dropped items in the game world that can be picked up, and so forth. All of those classes extend Entity.

Every Entity possesses its own collection of EntityActions. These are objects composed of an Action and an Attribute. The Action is an enum (SPAWN, EXPLODE, etc.) which is tied to the Attribute, which consists of a name and a value that the action parser will determine affects what the Action does. For example:

1  
creature.addEntityAction(new EntityAction(Action.SPAWN, new Attribute("diamond", 3));


will represent the Entity spawning three diamonds, with the spawn functionality being determined per Entity class (for example, an enemy will have its spawning defined as being upon death, while a tree will activate its spawn functionality upon being cut down).

What I've been getting at more is how to tie this into the game engine a little easier. Right now, I have it designed so that an enemy will have a function (which I posted above), which will call the EntityAction's corresponding perform() code. However, after reading my last post, I decided to change it so that the perform() function will actually exist within the Entity's class instead of the EntityAction class as such:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
// the perform function is defined in any entity subclass and is basically a big switch statement
public void perform(EntityAction action)
{
   switch (action.getAction())
   {
      case SPAWN:
         // handle spawning code here for items
         break;
   }
}


That helps out a little more in a couple of ways, as now I can get the Entity's position directly, but the problem still persists as to an easy way of getting access to the core game code (the TileMap class manages most of the functionality that will be needed by these sorts of functions) without having to pass the entire TileMap into this function and such to, say, spawn an item. The following is sort of a rough way of how I've organized my core game code modules:

GameManager: Manages the game loop, the active map, the resource manager, music, and so forth.
ResourceManager: Handles loading maps, images, sounds, etc.
TileMap: A representation of the current map in memory, which also holds all the active sprites, world objects, and so forth.
TileMapRenderer: Contains all of the map drawing code, which is passed to the GameManager.

So thus, in order to spawn an item, effectively, I have to call a function within TileMap most likely because that's where all of the active spawned items are stored and rendered by the TileMapRenderer, which is passed to GameManager. I suppose it's not the end of the world, per se, to have to pass in the Tile Map, but it seems like sloppy practice and like there could be a more effective and clean way of getting this done (this is basically my entirely own design, which means I'm basically designing everything from scratch based on what I think would work in the most generic way for my game).

I hope that helps! :] Thanks for all your time!

Best regards,
Colton

Straight flippin.
Offline h3ckboy

JGO Coder


Medals: 5



« Reply #5 - Posted 2012-08-09 00:32:37 »

what I learned to do and have stuck with since the beginning is to use an interface.

so make interface Stage (that is just what I call it) and have GameManager implement that, then pass down Stage, and any method in GameManager you need to be accessible from elsewhere you can put into Stage.

Hope this helps,
h3ckboy
Offline coltonoscopy

Junior Duke


Medals: 2



« Reply #6 - Posted 2012-08-09 02:14:48 »

what I learned to do and have stuck with since the beginning is to use an interface.

so make interface Stage (that is just what I call it) and have GameManager implement that, then pass down Stage, and any method in GameManager you need to be accessible from elsewhere you can put into Stage.

Hope this helps,
h3ckboy
Hm, not sure exactly what you mean by that. Would you be willing to elaborate a little more? Thanks! :]

Colton

Straight flippin.
Offline Roquen
« Reply #7 - Posted 2012-08-09 05:43:43 »

Personally I wouldn't go this route, but if the number of your unique actions is relatively small and likewise the number of active entities is small, then don't worry about your extra indirections.
Offline coltonoscopy

Junior Duke


Medals: 2



« Reply #8 - Posted 2012-08-09 05:51:11 »

Personally I wouldn't go this route, but if the number of your unique actions is relatively small and likewise the number of active entities is small, then don't worry about your extra indirections.
I'm building a planned architecture for modding and the like and to make it as generic as possible so that adding additional actions and the like will be fairly easy; because of this, I'm not entirely sure just how many kinds of actions there will be, but I'm anticipating a decent number. Is there an alternative way you would choose to implement this system? Thank you!

Colton

Straight flippin.
Offline 65K
« Reply #9 - Posted 2012-08-09 06:45:23 »

I understand that you want to separate any kind of action into its own class, just like a command pattern. That can be useful. But instead of a hardcoded switch statement you could put the actions into a lookup map. Thus, adding new actions would not require to touch additional code beyond the action class itself.

I would extract that into a dedicated action-caller class. Entities only store required data.
Then, because you want to do a multiplayer game, it might be necessary to queue these actions to be able to later distill required information to be sent to the clients.

You need to provide access to the complete game world from every action class. Could be given as argument when action performs are called. Do not expose more internals than needed. That could be a challenge.

The GameManager: if its not only delegating, then it has too many jobs according to the description.
The ResourceManager: if it's not generic for all different resource types, split it up.
TileMap: should just be a tile map. I would rather invent something like a world class to combine tile maps, sprites, etc.
Keep responsibilities small.

If that answers anything...
I don't know your background but all of this sums up into a huge task, so it might make sense to cut it down a bit.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline coltonoscopy

Junior Duke


Medals: 2



« Reply #10 - Posted 2012-08-09 06:52:52 »

I understand that you want to separate any kind of action into its own class, just like a command pattern. That can be useful. But instead of a hardcoded switch statement you could put the actions into a lookup map. Thus, adding new actions would not require to touch additional code beyond the action class itself.

I would extract that into a dedicated action-caller class. Entities only store required data.
Then, because you want to do a multiplayer game, it might be necessary to queue these actions to be able to later distill required information to be sent to the clients.

You need to provide access to the complete game world from every action class. Could be given as argument when action performs are called. Do not expose more internals than needed. That could be a challenge.

The GameManager: if its not only delegating, then it has too many jobs according to the description.
The ResourceManager: if it's not generic for all different resource types, split it up.
TileMap: should just be a tile map. I would rather invent something like a world class to combine tile maps, sprites, etc.
Keep responsibilities small.

If that answers anything...
I don't know your background but all of this sums up into a huge task, so it might make sense to cut it down a bit.
I was actually in the process of programming an ActionPerformer class which would tie together with a TileMap to handle all Actions passed in rather than have them assigned in Entities or in the TileMap code itself, coincidentally! However, everything you said makes a lot more sense than what I've been trying to concoct somewhat blindly.

I'm now aware that I have a lot of refactoring to do, as my classes have somewhat grown in bulk over time and gathered functionality beyond what they probably should have. I think you have a great point about making a GameWorld class or something of the like, as my TileMap class now also holds all of the sprites and whatnot and I agree that it seems a bit ungainly. I'll work on that immediately, as I probably have to perform that conversion before getting started on the other fun stuff related to all of this.

It does seem like a big task, but that doesn't concern me too much; it's a big game, so I expect it Cheesy I'm always happy to find ways of structuring it better and more sensibly and also in a way that makes it easier to maintain, so I appreciate all of your advice greatly.

One question: Could you elaborate a little more on implementing the actions in the form of a lookup map? From what I understand of the idea, it sounds great, and I'm familiar with HashMaps and the like, but I'm not altogether sure about what you mean in this sense. Thank you so much!

Colton

Straight flippin.
Offline 65K
« Reply #11 - Posted 2012-08-09 07:15:30 »

Looking back again at this:
1  
2  
3  
4  
5  
6  
7  
public void perform(EntityAction action) {
   switch (action.getAction())  {
      case SPAWN:
         // handle spawning code here for items
         break;
   }
}

Now I am not sure if I understand the meaning of EntityAction. I would assume that the spawning code is put into something like a SpawningAction. Then there would be no need for switches or map stuff at all.

Offline Roquen
« Reply #12 - Posted 2012-08-09 07:27:29 »

Basically you're coding something similar to a component-based model (of which I'm not a big fan, but others disagree).  I started describing an old-skool model here: ArchTypes, composition and code is data
Offline coltonoscopy

Junior Duke


Medals: 2



« Reply #13 - Posted 2012-08-09 07:53:24 »

Looking back again at this:
1  
2  
3  
4  
5  
6  
7  
public void perform(EntityAction action) {
   switch (action.getAction())  {
      case SPAWN:
         // handle spawning code here for items
         break;
   }
}

Now I am not sure if I understand the meaning of EntityAction. I would assume that the spawning code is put into something like a SpawningAction. Then there would be no need for switches or map stuff at all.
Well, an EntityAction is the following class:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
/*
 * An EntityAction is anything that may occur by the result of an Entity or by a game object. It will contain
 * both an Action and an Attribute.
 */

package entity;

public class EntityAction
{    
    // the action to be specified
    private Action action;
   
    // the attribute of the action
    private Attribute attribute;
   
    // CONSTRUCTOR
    public EntityAction(Action action, Attribute attribute)
    {
        this.action = action;
        this.attribute = attribute;
    }
   
    /*
     * This method performs the action specified in this object.
     */

    public void perform()
    {
        switch (action)
        {
            case SPAWN:
               
                break;
        }
    }
}


Here are also the Action and Attribute classes for clarification:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
/*
 * The Action enum represents all of the possible action types usable by any entity or game object in the game.
 * Actions will be mapped to instructions depending on where they are used; they are simply a layer of abstraction
 * otherwise.
 */

package entity;

public enum Action
{
    SPAWN,
   
}


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
/*
* This class definition will be used to represent attributes the item can possess.
*/


package entity;

public class Attribute
{
    // stores the name of the attribute
    private String name;

    // stores the value of the attribute
    private float value;

    // CONSTRUCTOR
    public Attribute(String name, float value)
    {
        this.name = name;
        this.value = value;
    }
}


Basically, the EntityAction's goal was to hold an Action, which is an enum, which ties into the EntityAction's Attribute (say, if the Attribute had the fields "potion" and 1, SPAWN in the switch statement would spawn 1 potion. Hope that clears that up! :] Thanks!

EDIT: The perform function actually won't be in the EntityAction class anymore as I described but rather in the ActionPerformer class, referenced by the GameLevel object we talked about!

Basically you're coding something similar to a component-based model (of which I'm not a big fan, but others disagree).  I started describing an old-skool model here: ArchTypes, composition and code is data
Hm, very interesting, because I haven't really taken a look at that kind of thing and am just going basically off of instinct and trying to engineer something from scratch. However, I'd love to hear your alternative ideas! Thanks!

Colton

Straight flippin.
Offline 65K
« Reply #14 - Posted 2012-08-09 07:57:25 »

Just inherit concrete actions from EntityAction like SpawnAction which all have a perform() method.
Then you don't need no switch statements at all

Offline coltonoscopy

Junior Duke


Medals: 2



« Reply #15 - Posted 2012-08-09 08:02:30 »

Just inherit concrete actions from EntityAction like SpawnAction which all have a perform() method.
Then you don't need no switch statements at all
That would work, but it doesn't seem right off the bat like it circumvents the issue of access (unless I'm missing something). It would probably be somewhat cleaner (though it would take more code than having the switch statement), but it still would have to find access to the GameLevel. Also, it seems that if I added a bunch of Actions (let's say the game somehow grew to having 50 actions), that would mean I would need 50 separate classes, wouldn't it?

Straight flippin.
Offline 65K
« Reply #16 - Posted 2012-08-09 08:15:11 »

Also, it seems that if I added a bunch of Actions (let's say the game somehow grew to having 50 actions), that would mean I would need 50 separate classes, wouldn't it?
Well, yes, otherwise you end up in 50 switch cases ?
But back to my first question: because I misunderstood your class meanings, maybe I still don't get your original intentions...

Offline Roquen
« Reply #17 - Posted 2012-08-09 08:19:19 »

Don't get too hung-up on class count.  Class based OO problems stem from depth and not the count of leaf and near-leaf classes.  If it's an organizational issue that static or anonymous inner classes can be used.
Offline coltonoscopy

Junior Duke


Medals: 2



« Reply #18 - Posted 2012-08-09 21:50:19 »

Also, it seems that if I added a bunch of Actions (let's say the game somehow grew to having 50 actions), that would mean I would need 50 separate classes, wouldn't it?
Well, yes, otherwise you end up in 50 switch cases ?
But back to my first question: because I misunderstood your class meanings, maybe I still don't get your original intentions...
Well, I'd like to be able to have an Entity contain a list of EntityActions that it possesses and be able to iterate through and execute them based on certain parameters, though this would still be possible if they were inherited from EntityAction, so I guess it doesn't really matter; your method would probably be more versatile in the end if not a little more cumbersome, since every action class could encapsulate its own functionality and be further extended, so I do see a lot of merit going that route.

Don't get too hung-up on class count.  Class based OO problems stem from depth and not the count of leaf and near-leaf classes.  If it's an organizational issue that static or anonymous inner classes can be used.
Fair enough! Cheesy

Thanks, you guys!

Colton

Straight flippin.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

theagentd (16 views)
2014-10-25 15:46:29

Longarmx (52 views)
2014-10-17 03:59:02

Norakomi (45 views)
2014-10-16 15:22:06

Norakomi (34 views)
2014-10-16 15:20:20

lcass (39 views)
2014-10-15 16:18:58

TehJavaDev (68 views)
2014-10-14 00:39:48

TehJavaDev (68 views)
2014-10-14 00:35:47

TehJavaDev (60 views)
2014-10-14 00:32:37

BurntPizza (74 views)
2014-10-11 23:24:42

BurntPizza (45 views)
2014-10-11 23:10:45
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!