Wednesday, March 31, 2010

Successful push of variables in AS =[PHP]=> database, plus AS callback

So the other night I set out to implement the plan I outlined before to figure out how to push data (i.e. each turn's information) from Actionscript variables to the database.  Here are the components I wrote/set up:
  • Database:  set up a test table called TestTurns with 3 fields - p_id (piece's ID number), xpos, and ypos.
  • Actionscript:  added a storeTurn() method to the 'piece' class, which makes use of the URLVariables, URLRequest, and URLLoader classes to structure and send an HTTP POST request, containing a piece's ID number, x-position, and y-position, to the PHP file.  Also wrote a callback function - which gets attached to the Loader's COMPLETE event - that spits the echoed data from the PHP script (provided in name/value query-string format) into a URLVariables object and "logs" some information into a dynamic text box currently sitting in the middle of the race track.  (This is a temporary debugging mechanism, obviously.)
  • PHP:  wrote a small script in a file which grabs the 3 POSTed variables, runs an insert query on the database, and echoes back the information it received and whether the query was successful.
These components seemed straightforward enough, but I did run into some issues along the way.
  • First, I was trying to test the POST to the PHP script by running the Actionscript locally.  It was able to pull the file, but in the AS callback function I was getting these strange strings as supposed value counterparts of the names that the URLVariables constructor was able to parse out.  I rearranged and tested things for some time until the "well duh" moment: I was expecting PHP to run while sitting on my machine.  Oh, wait.  :)  (To test locally, I wrote a simple text file containing a name/value string, directed the HTTP request to that file, and the URLVariables constructor parsed it just fine.)  After this, I uploaded the files so I could test it for real (i.e. with the PHP running).
  • I knew that for an insert query, the mysql_query function would return a true or false based on whether the query was successful or an error occurred.  However, I didn't know the details on the representation of that boolean, and how it would get converted when echoed by the PHP and then parsed by the URLVariables constructor in the Actionscript.  From the output I was getting dumped into the "log" it was appearing as a 1 or 0 instead of the string "true" or "false", so in order that the URLVariables variable for 'success' would actually have a value of true or false (that could then be used in a conditional), I just used the ternary conditional operator (?:) to convert the 1/0 value ahead of time in the PHP echo string.
  • Also from the output log I realized that since I was calling (in the handler PHP file) require_once for the db_connect file, whatever was echoed in that file was showing up amidst what the handler file was echoing.  Naturally this was screwing up the name/value query string I was trying to create so that the URLVariables constructor (in AS) could read it.  I was looking through the PHP documentation for the include/require functions to see if there was a way to suppress the output of the included file, but didn't find anything along those lines.  As an alternative for echoing messages of success or error in db_connect.php, I created a variable to store a boolean for connection success.  Then, when I require db_connect.php in the handler file, I can store that boolean (i.e. $connect_success = require_once "db_connect.php";) to discover and deal with connection errors.
Once I had figured out these problems, though, it actually worked...!  I took screenshots both of the turn data in the test table and the output as it showed up in Flash:

Tuesday, March 23, 2010

Storing a Turn: From Actionscript to the Database (Plan)

After deciding last night might be a good time to do something useful for my project, I chose to tackle an important feature component of my game that I had yet to really look into: making it multiplayer across client machines.  In other words, I needed to figure out how to:
  • take the occurrence of one player's turn (which happens on the Flash movie on one player's browser), 
  • send the critical information (which player and their new position on the grid) to the database on the server, 
  • and update the display of that player on all of the other players' Flash movies.
Since PHP is my avenue to the database, I set out to learn how to send information between Actionscript and PHP.  I stumbled on a forum thread that includes enough code to seemingly walk me through the necessary steps for packaging up Actionscript variables and sending an HTTP POST request to a PHP script (which can then insert values into the database).

In addition, the thread mentions that you can attach a callback function which will handle the event of the completion of the request--i.e. once the data has been loaded from the requested URL, that function is called and you can access the returned data.  So in the PHP I'll check on the success of the database insertion and send that result back (which I believe is just via 'echo' in PHP... wow I'm rusty on PHP).

I intended to draw a higher-level diagram of how this would all work, but I ended up writing in what is almost entirely correct code (as opposed to pseudocode or less).  I have some explanatory side notes written in, and arrows to show the overall informational flow.


*Important note*  I realized that this plan encompasses only the communication between one instance of the Flash game (on one client browser) and the database.  It does not cover the implementation of updating multiple players' instances of the same game on different clients, but it is the first step towards that.


Anyway here's the diagram.  (As usual, click to see in full size.)  I have a propensity for hand-drawing/writing stuff these days, it seems.

Friday, March 19, 2010

Found my game on BoardGameGeek!!

Joe suggested I try to find and scan an old piece of paper on which my dad and I had played the game.  I'll probably try to do that, but in the meantime, I found a listing for the game under the name "Racetrack" on boardgamegeek.com.  There are also some user-submitted photos.  My favorites...

(click the images to see them in full size)

Love the comments... The caption on the page says this one is from the 1960s!

Thursday, March 18, 2010

Meeting with Dr. Nimeroff: Database structure and linking multiple players

I met with my adviser, Dr. Nimeroff, for a bit the other day and we mainly discussed two related points.  Since it's been awhile since I've tried to design a database, we first talked over my ER diagram.  He didn't see any major potential issues with it right off the bat, so that was a good start.  We focused on the 'player_group' relation between the 'games' and 'users' entities.  I had not been sure whether it would be necessary to store player state information, like the x- and y-position, for a running game--in my newness to Flash/Actionscript, I'd been thinking something like that could be stored in Actionscript variables.  Dr. Nimeroff explained, though, that the Flash swf and associated Actionscript are run locally on each user's browser, so when values and visual elements change for one player, they aren't automatically updated for other players.  The key here is that whatever information is needed to update players' states on each others' "copies" of the swf and of variable values in the code must be saved into the database (since that, of course, is stored on the server) and then retrieved by calls from the other players' browsers to receive the new state.  Thus, it was a good thing I included such state information in my ER design.

Along these lines, I then asked about an issue that has been a "hole" in my mental plan of implementation since the beginning: how do other players' local machines find out that an update has been made to the database and take appropriate action to update their own copy of the game state in the code and swf?  I do want the game to be real-time, though it is turn-based, which makes it far easier than having to support multiple players doing things at the same time.  The only thing I could think of was polling; the Actionscript would just ping the database every fixed interval of time to look for a change and pull the new info if necessary.  I had also wondered whether the reverse idea would be feasible: could the database notify the game instances when an update was ready?  Dr. Nimeroff said that the former (games-poll-database) method was definitely the way to go about it.  Since the game is turn-based, it's not creating a constant stream of updates that need to be passed around; thus, a polling request every couple of seconds or so would not be a strain on the server.  Plus, the amount of data to be transferred per request is very little.  Finally, this is much simpler than the database trying to keep track of which instance to notify, where to send the notification, and the like.  This conclusion was very exciting for me, as I am no longer in the dark about a doable and sensible approach the implementation of multiplayer support.  And I think I might even know at a high level how to go about it.  Yay!

Tuesday, March 16, 2010

Discussion with Dad, part 2: Detecting boundaries and out-of-bounds moves

I also spoke in a more high-level sense with my dad about an important issue that I need to solve programmatically via Flash and Actionscript: the program's "awareness" of boundaries.  Here are some methods that I or we came up with:  (Note that I may not have yet researched the feasibility of each.)
  • Store a 2D array of booleans.  Each cell corresponds to a grid point (i.e. potential position) and the boolean simply states whether the point is inside (true) or outside (false) the track boundaries.  This takes initial overhead to create but makes detection of out-of-bounds moves a simple array-access call.  I could create such arrays manually for tracks I draw that will be provided as pre-made tracks; the bigger issue is how to compute this array for user-drawn tracks.  My dad's solution to that is to allow users to draw the track only as a series of connected straight line segments; as each segment is created, the its slope (change in x / change in y, in grid-points) can be used to set the booleans for nearby grid points.  [This corresponds to the left-hand part of the scanned diagram below.]
  • Check each player move for bounds-crossing.  An idea I had already had is for each time a player selects their next move, a line will be "drawn" (programmatically and hopefully invisibly) from the previous position to the new one.  Then, check if this line intersects with (crosses) a track boundary.  I'm not exactly sure how such an intersection check would be accomplished in Actionscript, though I tried to look around a bit for some methods (see the resource links post)...  [This corresponds to the right-hand side of the diagram below.]
  • Use the intrinsic ability of Flash to "know" which area is inside and outside a shape.  This is not as crazy as it sounds.  My dad explained that such data must be stored somehow; the simplest justifying example is that enclosing bounds (i.e. a shape) can be filled with a color.  Since I had no clue how I might access this stored data, I realized maybe I could take the color-filling ability at face value: maybe I can just fill the space outside the outer boundary and inside the inner boundary with a color, and check pixel colors to see if a particular move is in bounds or not.  Again, I figure this can be accomplished with Actionscript; the solution could range from not-so-elegant to rather-hackerish.  Anyway, I'll have to look into it.  [This only corresponds to diagrams in my head, so far.]

Dicussion with Dad, part 1: Handling when a player gets stuck out of bounds

Over lunch with my dad during spring break, I finally remembered to ask him about the one critical point of the game rules that I could not remember: what happens when a player's speed forces them to move out of bounds? -- In other words, all of the 9 possible positions for their current move are located outside the outer edge of the track, or inside the inner edge.  (From playing games with my dad, I definitely remember that this happens sometimes.)

My original idea for handling such a case was to set the player back to their latest prior position (past move) such that subsequent speeds/moves would not force them out of bounds.  As my dad pointed out, this might require backtracking by more than just one previous move, because that might not be enough to allow them to decrease speed within the next move (and stay in bounds).  The process of backtracking and computing at each prior position whether or not the player could stay in bounds from that point would also be a bit of a tedious procedure.  Finally, he maintained that this solution is "unrealistic"; in other words, you don't go backing up your car and slowing down on an actual race track.  Keeping the game realistic isn't especially important to me, but it's kind of a nice feature to attempt to uphold.  (It's kind of like when movies try to stay scientifically accurate.)

My dad's alternative solution is apparently what we always did when we used to play the game (and I just forgot).  It's actually very simple:
  1.  When all of a player's options for their current move are out of bounds, the player simply takes the move anyhow.
  2.  On their next turn, they lose a turn: their piece/marker stays in place on the grid, but they are considered to hold the same speed in the x and y directions.
  3.  On the subsequent turn, they take a move, maintaining the same rules about speed--the x and y speeds may change by 1 unit in either direction.
  4.  This alternation between lost turns and normal-movement turns continues for as long as the player is outside of bounds.
Obviously, the point here is to slow the player down while outside bounds, and hence encourage them to get back in bounds as efficiently as possible.

Here's the diagram my dad sketched to show this.  (Ignore the lines on either side of the '2' and the dots they lead to--that was a different idea.)  Suppose a player is forced to move outside the track on the turn indicated by the line next to '1'.  Their next turn, then, is lost; my dad designates this with the circle surrounding the dot.  The circle means they've stayed at that location for a lost turn.  Two more alterations of turn/loss are then depicted, as the player aims to return to the track.

Just to note, I'm not sure yet how I'll indicate visually that the player has stayed in place for the lost turn, since so far in development the game display is not exactly like it would be on paper in some ways.