Wednesday, July 4, 2012

EPI #11: Movement

Now that my roadblocks related to determining game state and handling MapEntitys are all taken care of, it's time draw the PC and the MapEntity to the map, and make the PC move around.  In order to do this, I need to:
  1. Load config.ini
  2. Get a path to a scenario if I don't already have one.
  3. Load the scenario's global.xml
  4. Load the scenario's master entity list (I keep this in entities.xml).
  5. (Load the scenario's master item list.)
  6. (Load the scenario's bestiary.)
  7. Initialize the window.
  8. Initialize the game.
The steps in parentheses aren't strictly necessary for displaying a Map in the appropriate game context, so I put placeholders where those things need to happen instead.  At this point I've taken care of everything except step 8.  That's going to be handled by the magical function init_game(), which I discussed in a previous post.  The gist of it is that it takes the main gtk.Window, the master entity list, the scenario properties, and optionally a save game file to load, and identifies the appropriate map to load, sets appropriate MapEntity states, etc.  It does all the things necessary to either resume a game where it was left off, or start a new game entirely.  Look what it does:


There he is!  A little man, in the appropriate default location on the default map!  A new game started.  Making him move around is pretty simple.  I do a window.connect("key_press_event", lambda w,e: mw.key_press(e)), which tells the my gtk.Window to handle key press events by calling MapWidget.key_press() function, and passing it the gtk.gdk.Event it received originally.  There's almost certainly a better way to do this, and I'm going to need to figure it out as I begin changing around which widgets are attached to my window.  I'll probably end up implementing a class EPIWindow(gtk.Window), which will be capable of managing multiple different widgets (e.g. MapWidget, BattleWidget, PauseWidget, TitleWidget, etc), and keeping its event handlers straight.  I don't want to call MapWidget.key_press() if I'm displaying a BattleWidget, after all.

For the curious, MapWidget.key_press(event) derives a direction from the button that was pressed, calls Map.move(target, dir), and then redraws itself with queue_draw().  Map.move(target, dir) sets the target's direction to dir, and attempts to move the target in that direction.  A move is successful unless one of the following conditions is met:

  1. The new location (which I get from the sum of the target's current location plus the movement vector [which is derived from the movement direction]) is out of the bounds of the map.
  2. A MapEntity is already in the new location.
  3. The new location's tile's passability is greater than the target's move_power.
Cool.  I'd upload a video of me moving Kenfold around the beach, but I don't have any video capture software installed on my computer.  I might get some later, when I have something more exciting to share.

Adding the line <entity id='1' x='7' y='2' /> to my map specification adds entity 1 at (7, 2) on my map:

Looks like I didn't get the shading quite right on the chest.

It's a treasure chest!  Wow!  Kenfold is rich!

Next up, I'm going to start thinking about which events I'm going to support, and how to handle them.  Or maybe I'll write that EPIWindow class...  There's so much to do!  And I start work in 12 days!

No comments:

Post a Comment