Command Pattern Review

Started by
6 comments, last by swiftcoder 6 years, 2 months ago

I tried to implement the command pattern explained in this book : http://gameprogrammingpatterns.com/command.html. I'm looking up for someone which could revise my code and see if I did implement it the right way, or even if I did deviate a lot from how it should be implemented.

Here's the code : https://github.com/Luhanmacedo/Command-Pattern  

Questions:

  1. I didn't understand if the base class (Command) could be modified to introduce methods as I did to facilitate implementation details in the derived classes.
  2. What would be a good way to map the buttons according to the configuration the player wants to use, such as X for Jump and Y to shoot.

 

P.S. :  If it's not possible to review the whole code, tips in some parts are welcome as well.

Advertisement
22 hours ago, Luhan M. said:

I tried to implement the command pattern explained in this book : http://gameprogrammingpatterns.com/command.html. I'm looking up for someone which could revise my code and see if I did implement it the right way, or even if I did deviate a lot from how it should be implemented.

Here's the code : https://github.com/Luhanmacedo/Command-Pattern  

Questions:

  1. I didn't understand if the base class (Command) could be modified to introduce methods as I did to facilitate implementation details in the derived classes.
  2. What would be a good way to map the buttons according to the configuration the player wants to use, such as X for Jump and Y to shoot.

 

P.S. :  If it's not possible to review the whole code, tips in some parts are welcome as well.

I was just looking quickly at the link, are you talking about just remapping 4 buttons on a game pad while still being able to operate the following actions (example):

A = Jump

B = Shoot

X = Potion

Y = Melee Attack

There are several ways to do this.

Assume you have an event manager that checks for those four buttons:

If A is Pressed -> aButton pressed is now True (will execute code outside of events)

If B is Pressed -> bButton pressed is now True (will execute code outside of events)

If X is Pressed  -> xButton pressed is now True (will execute code outside of events)

If Y is Pressed  -> yButton pressed is now True (will execute code outside of events)

And your action ids are:

Jump = 1

Shoot = 2

Potion = 3

Melee Attack = 4

You would simply map IDs to each Button.

So by default A = Jump which means A will return ID 1. If we set Shoot for A, A will return the ID 2. You can just make a object for Button, and make a function that sets the ID and gets the ID.

In our logic loop we would see if an action is pending.


if (aButton.isPressed()) {
	player1.doAction(aButton.getId());
  	aButton.togglePressed(); // Just means aButton bool pressed = !pressed
}

In your player code for doAction() you would just reference the method based on the ID


void Player::doAction(int id) {
  if (id == 1) { 
    jump(); 
  } 
  else if (id == 2) { 
    shoot(); 
  }

ect….

There are different approaches you can use to solve the same problem. I find a lot of books very "dry" and they don't explain in layman's terms well enough.

Is this what you were looking for?

 

Programmer and 3D Artist

You are doing something a little unorthodox here, by having distinct command objects, but then boiling them back down to an enum at the back end and having specialised behaviour based on both the command object and the enum.

I'd advise sticking to one or the other. Either make command objects be pure data, and use the giant enum/switch on the backend to process them in their entirety, or encapsulate all the necessary logic in the methods invoked by the command objects. Both are reasonable strategies, although the former will result in less tight coupling than the latter.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

@Rutin Thanks, that was one of my questions, and it's very clear for me now. About the books, what way you did learn some of the patterns?

 

33 minutes ago, swiftcoder said:

You are doing something a little unorthodox here, by having distinct command objects, but then boiling them back down to an enum at the back end and having specialised behaviour based on both the command object and the enum.

I'd advise sticking to one or the other. Either make command objects be pure data, and use the giant enum/switch on the backend to process them in their entirety, or encapsulate all the necessary logic in the methods invoked by the command objects. Both are reasonable strategies, although the former will result in less tight coupling than the latter.

@swiftcoder So what I'm actually making is a base class which is focused only in these two objects: MoveUp and MoveDown right?

Just to make sure I understood the second way to do it, it's means the object in this case (MoveUp and MoveDown) would have all the methods and the necessary logic to execute the action?

P.S. : Thank you for taking the time to read my code.

10 minutes ago, Luhan M. said:

what way you did learn some of the patterns?

Patterns are... not as important as books/courses might lead you think. It's pretty rare to see someone explicitly use a pattern per se. Its more about learning to recognise the shape of common solutions to problems.

For example, the command pattern is mostly about decoupling the source of some events from the target of those events. That's a useful thing in a number of situations, but there are many ways to accomplish it.

13 minutes ago, Luhan M. said:

So what I'm actually making is a base class which is focused only in these two objects: MoveUp and MoveDown right?

You can do it that way, yes. That's the way the article you linked did it.

14 minutes ago, Luhan M. said:

it's means the object in this case (MoveUp and MoveDown) would have all the methods and the necessary logic to execute the action?

Well, no. The actual logic probably lives in an object responsible for running the game simulation. The command objects are just inputs t that logic. You can either have the command objects wrap calls to the simulation object (as the article does), or have them contain data that the simulation object inspects.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

26 minutes ago, swiftcoder said:

Well, no. The actual logic probably lives in an object responsible for running the game simulation. The command objects are just inputs t that logic. You can either have the command objects wrap calls to the simulation object (as the article does), or have them contain data that the simulation object inspects.

I think I understand now.

27 minutes ago, swiftcoder said:

Patterns are... not as important as books/courses might lead you think. It's pretty rare to see someone explicitly use a pattern per se. Its more about learning to recognise the shape of common solutions to problems.

I started studying about patterns because I see a lot people saying that everybody should use state machine, update (), etc, and after a light read about these, I thought they would facilitate to implement a game as you get further in the development

31 minutes ago, Luhan M. said:

...I see a lot people saying that everybody should use state machine...

/slightly offtopic: state machines are an extremely useful way of looking at problems. I wouldn't typically classify them as design patterns though - they predate the whole object oriented thing :)

Certainly nothing wrong with learning design patterns, they illustrate useful approaches to problem solving. I'm just providing a light warning, because programmers tend to go through a phase where they rigidly apply design patterns to every problem they see, and over time you'll find that not everything fits such a rigid methodology.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

This topic is closed to new replies.

Advertisement