Jump to content

  • Log In with Google      Sign In   
  • Create Account


Mapping Player Actions to one button


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
6 replies to this topic

#1 I'm Steve   Members   -  Reputation: 102

Like
0Likes
Like

Posted 01 May 2012 - 06:32 AM

This is more of a question how other people would handle this issue. I am making a sim farm game. I have all logic for animating the player, objects, simple quests and things need need to do etc. I am now thinking of how I am going to interact with different objects. For example, my character when you click 'e' could do a number of things depending on what she is interacting with. If the item is a grass tile she will hoe it, if it's a dirt tile she could put down seeds, if it's a crop then she will water it, if it's a mailbox check the mail or something.

In more simple games I have just had a bit if statement in the update method. I don't want to do this because I want it to be more robust and expandable. I was thinking that when the action button is clicked an action object is sent to whatever objects are clicked and if they can handle them then they will themselves? Almost like a chain of command pattern.

like
WorldAction
HoeAction : BaseAction
WaterAction : BaseAction
CheckMailAction : BaseAction

so
phseudo

update()
if input = e then
selectedTool = selectedinventory
objects = getallselectedobjects()
for each object in objects
handletoolaction()
handlewhateverotheractions

I don't know if this all makes sense, perhaps I just need a bit of a hand organizing and focusing. I appreciate any input from you guys. If any of it is unclear or I am just not making sense I can try to elaborate more with code etc.

Sponsor:

#2 ndssia   Members   -  Reputation: 172

Like
0Likes
Like

Posted 01 May 2012 - 09:06 AM

I would create an abstract base class "UsableObject" with an EventHandler for click events; that way every subclass of that (HoeAction, WaterAction etc.) just needs to implement onClick with its own logic.

#3 Plutonium   Members   -  Reputation: 349

Like
0Likes
Like

Posted 01 May 2012 - 04:14 PM

I think fastest would be if you track what item you have (one item at the time), and then only ask
if(pressed(e))
{
if(item==mail)
do mail job
if(item==water)
do water job
}

#4 Canvas   Members   -  Reputation: 239

Like
0Likes
Like

Posted 01 May 2012 - 04:52 PM

you could use a swtich statement,

you can make a enum variable,
like so

enum armour {mail, leather, cloth. plate, crystal};

then use a switch statement

switch (armour) {
  case mail: do this function
    break;
  case plate: do this function
    break;
  case leather: do this function
    break;
  case cloth: do this function
    break;
  case crystal: do this function
    break;
  default:
    cout << "Invalid item"
  }

and then you just code the switch statement, with anything you like :)

#5 I'm Steve   Members   -  Reputation: 102

Like
0Likes
Like

Posted 01 May 2012 - 08:18 PM

That was extremely quick :). THanks a lot. I am spending today and tomorrow working on this. I will post later what I ended up finishing if you guys are interested.

#6 I'm Steve   Members   -  Reputation: 102

Like
0Likes
Like

Posted 02 May 2012 - 05:09 AM

I wanted to again thanks for the suggestions I kinda took the usable object approach with of course switches and ifs etc.

I have abstract class called ActionableObject which has methods

public virtual void Act(ContentObject actingObject) {}
public virtual void Act(ContentObject actingObject, Vector2 location) {}

I set my tileengine to actionableobject and same with all te crops, so I can send a ContentObject (WorldObject more or less) and each of the ActionableObjects take action toward said object.

Partial Main Update method
if (InputManager.IsActionTriggered(InputManager.Action.Ok))
		    {
			    player.State = Character.CharacterState.Acting;
			    if (Session.SelectedInventoryItem is Tool)
				    (Session.SelectedInventoryItem as Tool).ResetAnimation();
			    else if(Session.IsSelectedItemCrop)
				    player.State = Character.CharacterState.Idle;

			    _tileEngine.Act((ContentObject)Session.SelectedInventoryItem, PlayerPosition.SelectionMapVector);
			    /// item used
			    if (_tileEngine.GetCrop(_tileEngine.Map.Name, PlayerPosition.SelectionMapVector) != null &&
				    Session.IsSelectedItemCrop && !(Session.SelectedInventoryItem as Crop).IsGrown)
			    {
				    Session.Inventory.Remove(Session.SelectedInventoryItem);
				    Session.SelectedInventoryItem = null;
			    }
		    }

Act Method for tileEngine
public override void Act(ContentObject actingObject, Vector2 location)
	    {
		    base.Act(actingObject, location);
		    Crop crop = GetCrop(Map.Name, location);
		    int tileIndex = GetTileIndexAtLocation(0, location);
		    int tileIndexValue = GetTileValueAtLocation(0, location);

		    /// IF THERE IS A CROP THERE
		    if (crop != null)
		    {
			    if (actingObject is Tool)
			    {
				    Tool tool = (actingObject as Tool);
				    switch (tool.Type)
				    {
					    case "WateringCan":
						    crop.IsWatered = true;
						    Map.BaseLayer[tileIndex] = (int)TILES.DARKDIRT;
						    /// remove the current handler because we want to have more
						    /// time for the watering <img src='http://public.gamedev.net//public/style_emoticons/<#EMO_DIR#>/tongue.png' class='bbc_emoticon' alt=':P' />
						    crop.OnNoLongerWatered -= new Crop.OnNoLongerWateredHandler(crop_OnNoLongerWatered);
						    crop.OnNoLongerWatered += new Crop.OnNoLongerWateredHandler(crop_OnNoLongerWatered);
						    break;
				    }
			    }
		    }
		    /// THERE IS NO CROP
		    else
		    {
			    if (actingObject is Tool)
			    {
				    Tool tool = (actingObject as Tool);
				    switch (tool.Type)
				    {
					    case "Hoe":
						    if (tileIndexValue == (int)TILES.LIGHTGRASS || tileIndexValue == (int)TILES.MEDIUMGRASS || tileIndexValue == (int)TILES.DARKGRASS)
							    Map.BaseLayer[tileIndex] = (int)TILES.LIGHTDIRT;
						    break;
				    }
			    }
			    else if (actingObject is Crop)
			    {
				    if (tileIndexValue == (int)TILES.LIGHTDIRT || tileIndexValue == (int)TILES.DARKDIRT)
				    {
					    Crop c = actingObject as Crop;
					    c.Coordinates = GetCollidingTileVector2(location);
					    AddCrop(Map.Name, c);
				    }
			    }
		    }
	    }

I know that i will be changing this around a lot but thanks for getting me on my way.

#7 slayemin   Members   -  Reputation: 2480

Like
0Likes
Like

Posted 05 May 2012 - 07:26 AM

I'm in agreement with ndssia. Virtual functions would be the way to go with this. Each object should know what to do when its "interact()" method is invoked.

You might even like to pass in the object which is interacting with it so that you can change in different ways depending on the type of object. Example: The way a postal worker interacts with a mail box is different from how the owner interacts with it.

public class GameObject
{
	 string name;
	 public virtual void Interact(GameObject interactor);
}

public class Mailbox : GameObject
{
	 string address;
	 ...
	 public override void Interact(GameObject actor)
	 {
		  switch(actor.name)
		  {
			   case "postal_worker":
			   {
					((Postal_Worker)actor).place_mail_into(this);
					break;
			   }
			   case "owner":
			   {
					((Mailbox_Owner)actor).take_mail_from(this);
					break;
			   }
			   default:
			   {
					Console.write("You see a mailbox with the street address " + address);
					break;
			   }
		  }
	 }
	 ...
}

If you model your classes by how each object can be interacted with, extending the functionality of objects becomes much easier (just add new functions). Hard coding specific object properties to other object properties will eventually turn your code into a maintenance nightmare and make it much more rigid.

Eric Nevala

Indie Developer | Dev blog





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS