Tuesday, May 11, 2010

Pre-submission goals, update #4: About, Help, ...and that's it.

I decided at this point that I've covered all the important/major bugs and enhancements that I wanted to work on between presentations and submission, so the last thing I did was to finally add the "about" and "help" sections.  (Yes, those links actually didn't do anything until perhaps an hour and a half ago.)

In lieu of creating actual separate pages for these sections -- which could severely disturb the logged-in/logged-out status management and gameplay (in the case of people jumping to these pages who knows when) -- I added an "about" div and a "help" div to both the index.php and playgame.php pages, with the same content on each page.  Both divs are hidden when you arrive on the page, but thanks to jQuery, when you click the links up in the header, they will slide into view.  Yes, both can be viewed at the same time, but I think that's fine.  Each div has a little [x] in the upper right; clicking on this slides them back into hiding.  The rest of the page content slides down to allow them to appear (i.e. they don't cover the main page content).  I like this setup because you can view the information whenever you want while using the app.  This allows for handy referral to game instructions even while playing!

I'm pretty tired... moving on to final documentation.

Pre-submission goals, update #3: So, what happens when I fly off the grid?

There is one significant issue I have found (via user testing) that occurs in my Flash version of this game that I do not recall ever occurring when I played this game on paper with my dad.  This would be the possibility of players going so fast that not only do they go out of the track boundaries, but they end up in the position in which all options for their next move are off the playing grid entirely.  I wonder if my discovery of this is a result of my throwing my friends into playing my game without their really having a clue what they had to do, and thus having pretty much no clue (initially) of how to strategize the management of velocity.  But either way, I thought that it would be fairly bad in terms of user experience to force everyone to restart the game if a player went off the grid, so I decided to handle that case.

I consulted with my dad, and he helped me come up with a reasonable solution.  I decided that if a player comes to their turn and all their options are off the grid, that move will be taken for the player as follows:
  1. They will move to the "middle" option (i.e. the gridpoint that would maintain both their x- and y-velocities), wherever it may be, off the grid.
  2. Then, they will "slide" back onto the edge of the grid.  In other words, if they are off past the top or bottom edge, their y-coordinate will be adjusted, and if they are off past the left or right edge, their x-coordinate will be adjusted.
  3. As a "punishment" for going off the grid, their velocity will be reset to (0, 0).
Since the player has no control of this move that's bringing them back onto the grid, they are informed of it, like so:


And on your next turn, you start off at the edge with (0, 0) velocity:

Sunday, May 9, 2010

Ongoing Compendium of Resource Links

As a way of bookmarking and categorizing online [potential] resources I will update this blog post throughout my project.

Update: I am now going to mark the newly added links for each update of this post by highlighting them.



Facebook-application-related  --------------------------------------------------------------------------





Wiki - Cross Domain Communication Channel - so that my pages (within the iframe) can talk to the parent (Facebook-hosted) page.  This is necessary for using the JS client library.

* (See the other post about the Facebook platform integration for a much longer categorized list of links...)


PHP + MySQL  --------------------------------------------------------------------------



PHP - Specific functions etc.  --------------------------------------------------------------------------






mysql_query - includes links to related functions: mysql_fetch_array, mysql_num_rows, mysql_affected_rows

mysql_real_escape_string - apparently you should use this on your query strings before sending them


include - this documentation also applies to 'require' (and mainly to 'include_once' and 'require_once')

Boolean (type) - with useful comments on various funky details of comparisons, casting, how the representation is output


PHP & Flash  --------------------------------------------------------------------------




Cron Jobs  --------------------------------------------------------------------------

Running PHP cron jobs – regular scheduled tasks in PHP

Cron Job setup on Webhostingpad


Javascript  --------------------------------------------------------------------------

Accessing PHP variables in Javascript - a simple issue, but I needed to know :P

AJAX GET and POST examples - mostly because I wanted to remind myself of the format of the parameters string, and didn't realize the content-type had to be set for the POST to indicate it would be in name/value pair format if I was sending a string I constructed.

Setting and clearing timed events - for AJAX polling for database changes



Flash [games]  --------------------------------------------------------------------------


Flash/Actionscript [basic/reference]  --------------------------------------------------------------------------


Flash CS4 Migration Guide from AS2 to AS3 - I expect this to be quite useful when I'm Googling around for random issues I encounter in Actionscript and I find blog posts and whatnot that happen to use AS2 for code examples.  Credit to John for finding this. :)








Flash/Actionscript [specifics]  --------------------------------------------------------------------------

-- The Actionscript Language --


(since there's no native support)










-- Relevant AS Classes --



flash.display.Graphics - access programmatic drawing functions (lines, circles, fills, ...)



-- Buttons --






-- Movie Clips (and other DisplayObjects) --





^ extensive tutorial. I like this one.

This is a multi-page/many-step tutorial... haven't looked at it much.

One of those long multi-page tutorials, but this might have some useful bits in there. (Haven't looked at it much yet.)



scroll down and try what's mentioned at the end, maybe


-- Event handling --

(oh yeah! I remember using this same structure in Javascript...)




-- Actionscript + external code functionality --

[AS3] Forum thread: "Sending variables from AS3 to php and back to AS3" - really helpful posts about how to set up the necessary code pieces (the Actionscript and the PHP), with code snippets

[AS3] "Working with external data" - article with code examples about using the URLVariables and URLLoader classes, pulling from external documents, and accessing external scripts


-- Drawing --

This looks like AS2, but the code structure gives me the basic idea of how to use the drawing API functions together to create a simple drawing app.




-- Edges/intersection --




-- (uncategorized) --




Oh hey, detecting and updating user presence is ridiculous. ( = pre-submission goals: update #2)

An annoying behind-the-scenes bug turned out, as I've learned after many hours of struggle today, to be far more frustrating and complicated than I could have imagined.

In my Users table in the database, I simply store a boolean, 'logged_in', by which I intend to record which players are currently using the app.  This does not mean whether they are logged into Facebook, since that status is likely unrelated to my app.  So, I define my logged_in boolean to mean whether the user is on either the index (home) page or the playgame.php page.

It's simple enough to ensure this boolean is marked true when the user loads either of these pages.  Detecting their leaving a page, however -- with the added requirements of updating all contingent information -- is unbelievably far more difficult.

Concerning the latter note, if a user leaves a game while it's in progress...
  • They should be marked 'logged_in' = false, since if they're navigating to one of the app pages, that page will restore that boolean to true.
  • Their 'current_game_id' and 'current_pid' variables must be set to null, to indicate they are no longer in that game.
  • If they were the last remaining player in that game, all turns pertaining to that game as well as the game's entry itself must be cleared from the Turns and Games tables, respectively.
  • If there are any other players left in that game, the 'num_players' value for that game must be set to the new correctly decremented value (and I don't want to just subtract 1, in case of race conditions, so I always want to check with how many players are still marked as involved in the game based on 'current_game_id' in the Users table).
  • The other players in the game should be checking for whether their fellow players have left, and must be informed of such dropouts.
 My original solution to detecting a player leaving the game page was to register the window.onunload event to make an AJAX POST to a php script that would update all appropriate things (see the list above).  This worked well enough in Firefox; I checked the results in the database, and Firebug showed me that the POST was indeed going through, despite the fact that the browser was navigating to another page.  However, I ended up discovering that the window.onunload event, or perhaps the POST, wasn't going through fully in Safari.  This led me to realize I should try an entirely different approach that would not rely on a browser event that may not have solid implementation in all browsers...

Many thanks are due here to John for helping me form new ideas for how to make this work.  Without going into the painful details and resulting unfortunate spaghetti-fication of my code (err..), the basic solution architecture is in three components:
  • The Users table now has a field called 'activity_time'.  Every 30 seconds, whether a user is on the home page or the gameplay page, an AJAX POST calls a php script to set this field to the MySQL CURRENT_TIMESTAMP.  So this is saying "user x is still here".
  • While on the gameplay page, the same script additionally checks for (a) any users marked with that 'current_game_id' but whose 'activity_time' is more than 30 seconds old, and (b) any users with one of the 'fb_id's registered (in a Javascript object stored by the page) as involved in that game, but with 'current_game_id' set to null.  [Note: (a) condition = those who have left the app by going to another page outside of it or closing the browser tab/window, and the cron job has not yet cleared up their data; see next bullet...  (b) condition = those who moved back to the app home page, which clears up their game data immediately, or those who have been cleared up already by the cron job.]  The id's of these "dropout" users are sent back to the page; the display of players in the game is updated to remove the dropouts, and a message is given to the user to advise them to return to the home page and start another game...(see below *).
  • There is now a cron job set up on the server to run every 5 minutes.  It calls another php script which retrieves all users whose activity time is more than 50 seconds old, removes any current game data they have, marks them as logged out, and either decreases the number of players in the game they had been in, or deletes that game entirely if it's now empty of players.
(*) Right now, there is no handling for updating the game state as it's stored in the ActionScript within the Flash app instance, nor does the page stop polling for the dropout players' turns.  As I see it, there are two options for where to go from here, regarding this issue:
  • Don't bother fixing the AS game state.  Just redirect the user automatically back to the home page.  This would make sense anyway for games that only had 2 players to start with, since playing alone is not as much fun.
  • Use the ExternalInterface class in AS to receive a notification from the page (via JS); update the game state accordingly; allow play to continue without the lost player(s).
Given how much trouble logout status has given me for many hours today, I'm inclined to go with the first option (or just let the user figure out that it doesn't work, and that they need to manually go back to the home page or leave the app).  It might turn out to be pretty quick to implement the second option, as long as there is still at least one player in the game, but I would rather turn my attention and remaining time towards a couple of the other goals on my pre-submission list, since I do think they are still important.

Finally, finally:


(I wonder how many Pandora hours I've used, out of my 40 hours given for the month, just from working today...)

Saturday, May 8, 2010

Pre-submission goals: update #1

Things fixed or completed so far...
  • The current velocity for each player is now displayed next to the thumbnail of their Facebook picture and is updated after each turn.
  • Players now cannot occupy the same gridpoint at the same time.  To do this, I simply don't display the little circle that indicates that you can move to a point if another player's piece is currently located on that point.  (I had one hitch initially -- I forgot that if your current velocity allows, you sometimes can stay on the same exact point you're already on, so I didn't want to hide the circle if it's on top of your own piece.)
  • I believe I have now fixed the bug of move-option circles not appearing when they should have, during the case of both (out of 2) players being out of bounds at the same time.  Luckily, it was a simple matter of updating a boolean that pertained to the other player; as in, I'd forgotten to update that bit of game state across all player instances (not just the instance of the player whose turn it had been).
  • (??) As John is graciously allowing me to test via his Facebook login, I was able to play a couple of full games (by logging in as myself in Firefox and as John in Safari) on my own screen, and the winner notification worked in all cases.  So maybe this is not a bug after all?
A thought I just had: I should really test this on more than just two players.  I don't think I ever really have.

p.s. Screenshot of preventing players from occupying the same point, without removing the option circle that coincides with your own current position:

Sunday, May 2, 2010

Goals prior to final submission

So after my first full night ever in the SIG lab, I managed to pull off my presentation pretty well, I think.  I even ran a live demo, playing against John, and nothing broke. (!!)

Post-presentation, I've still got about a week to wrap this project up.  Here's what I'm hoping to get done in that time:
  • (bug) Fix/rework the way user logout is recorded in the database... right now I keep finding that users are still marked logged-in when I don't think they are.  (At least login is working right, I think!)
  • (bug) Make sure the "player __ won!" popup works for all players.  I seem to remember a couple of test runs in which only one out of two players saw it when someone had won.
  • (feature) Show each player's current x- and y-velocity somewhere next to their picture.  This should be really easy to do and would be helpful to see.
  • ("feature") Write the About and Help pages (including gameplay instructions)
  • (enhancement) Spruce up the (logged-out) intro page and the main page with a short intro to the gameplay.
  • (enhancement) I kind of forgot to implement preventing players from occupying the same grid point at the same time.  This also should be extremely easy to implement.
  • (bug?) I just today played the game against a friend and we ran into the case in which both of us were out of bounds at the same time.  I think there might have briefly been a mix-up regarding displaying the move options for one of us.  (Gameplay still proceeded properly though, I think.)  So I should test this again and fix if needed.
  • (bug) I nearly forgot this one... but I really should do something about the case of players running off the edge of the entire grid.  Apparently this happens more easily in my online version than on grid paper with a pencil, haha.  (See previous blog post.)
  • (enhancement) Show more clearly when another player takes their move.  I'm thinking I should highlight the position circle they've chosen for about a second prior to turning off those circles and showing their piece in the new position.
  • ("enhancement") Write some back-logged blog posts.
I don't think any of these changes are too major, and none of them significantly change the gameplay, which was certainly functional by presentation time.

Will update this list if I think of anything else.

Saturday, May 1, 2010

Double fail: another full game played against a friend

Things I learned from this game:
  • I really need to do something about people flying off the edge of the entire grid.
  • I also really need to write an instructions page.  It needs to be really clear about how your acceleration works...
  • I need to double check what's going on when two players are out of bounds at the same time.  The flow of turns seemed to happen properly, but I think at one point my opponent's set of move-option circles didn't appear on my screen when they should have.  (I guess they showed up on his though because he was able to take his move.)
  • Also, Matt exploited his out-of-bounds moves to jump back into the track by just cutting straight through, whereas I basically slowed down to almost zero speed and turned around.  I'd actually never thought of his strategy before.  It's not exactly a bug that he was able to do this, and I'm not sure how to curb it in any simple way in the code, either...
Now for the fun screenshots...

Game 1 (well, the attempt):
(filename: matt_fail.png)



Game 2
(filename: tory_fail.png)