Tuesday, May 12, 2009

I'm Still Alive!

I realized it's been almost 2 months since I posted here, sorry about that! Here's what I've been up to!

Yes, I've been very busy, but I'm going to try to stop ignoring this blog as I have been. I promise.

Tuesday, March 3, 2009

New Blog!

While I intend to continue posting to this blog, I have a new blog over at kavwoosh.com! It is primarily going to focus on games and game design, while this blog will stay at a more technical "i-had-this-problem-and-did-this" level. Kavwoosh will also focus on my professional activities, so keep an eye out!

Friday, February 27, 2009

MySql Subquerys Are Molasses

Just a quick note on an issue I ran into today.

When using MySql, if you have a query that looks like this:

Select A, B
From table
where A in (Select C, D From AnotherTable)

Even when the subquery returns a very small resultset, the overall query will slow to a crawl, if it completes at all. This is because of how mysql handles the "in" statement. The only way to really get around it is just to join the two queries and filter, which isn't terrible, though I hope a situation comes up where this solution is untenable.

Monday, February 23, 2009

Peek-a-Boo Divs

I was just messing around with some HTML/CSS/Javascript stuff the other day, and came up with something kind of awesome. It's a div that hides until it has the mouse placed over it, and then hides again when the mouse leaves. It's very similar to a hiding toolbar, and could be very useful if applied correctly.

Due to its ability to be present, although mainly unseen, it would be particularly useful for web pages/applications that require large amounts of content on screen, so that more wouldn't have to be devoted to the standard menu.

I've tested this in IE7, Firefox, Chrome, and Opera. It works no matter the resolution, though I have yet to try it on my G1 (for the size tests, I basically just scrunched firefox and IE down very small). It's W3C compliant (except for the colors, which I don't really care about) for both the html and the CSS. The HTML uses the XHTML 1.0 strict dtd, and there isn't a single table anywhere. This is how I roll.

HTML:


< !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Menu Bar Test</title>
<link rel="stylesheet" href="./menubar.css" />
<script type="text/javascript" src="./menubar.js"></script>
</head>
<body onload='pageLoaded()'>
<!--<div id="collapsedmenubar" class="menubar" onMouseOver="overCollapsedMenu()">
<p>Click here for menu</p>
</div>-->
<div id="fullmenubar" class="menubar" onmouseover="overCollapsedMenu()" onmouseout="leftFullMenu()">
<h1>Menu</h1>
<p>
<a href="index.html">Home</a>
<a href="index.html">Projects</a>
<a href="index.html">Contact Info</a>
</p>
</div>
<div id="content">
<p>This is where the content goes!</p>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Proin nibh nisi, dapibus vel, elementum eget, vehicula vel, lorem. Donec ipsum est, tincidunt iaculis, nonummy ut, dictum vel, velit. In leo magna, aliquam et, suscipit sed, cursus in, tellus. Suspendisse dui felis, convallis vel, porttitor pellentesque, dapibus vitae, neque. Suspendisse potenti. Sed erat orci, rhoncus at, tempor in, pellentesque vel, tortor. Nam urna. Sed bibendum. Aenean ultrices vehicula lacus. Duis ac arcu. Nulla facilisi. Sed pulvinar risus eget leo. Praesent pulvinar varius ante. Cras lorem nibh, elementum nec, accumsan nec, imperdiet et, felis. Fusce gravida sem et orci. Suspendisse lectus nibh, tempus eget, sagittis sit amet, pretium vel, dui. </p>
<!--There was more Lorem Ipsum, but I dropped it for readability's sake.--%gt;
</div>

<div id="footer">
<p>Here is the footer!</p>
</div>
</body>
</html>


CSS:
*{ /*I know this is bad, but hey, it's a test document.*/
padding: 0px;
margin: 0px;
border: 0px;
}

.floatedlabel{
float:left;
}

.menubar{
background-color: green;
border-left: 5px yellow solid;
border-right: 5px yellow solid;
border-bottom: 5px yellow solid;
color: white;
left: 10%;
position: fixed;
right: 10%;
text-align: center;
top: 0px;
width: 80%;
z-index: 9001;
}

body{
background: lightblue;
padding-top: 5%;
}

h1{
float: left;
}

#content{
background-color: lightgreen;
border: 2px yellow solid;
left: 5%;
position: relative;
width: 90%;
}

#footer{
background-color: lightgreen;
border-left: 2px yellow solid;
border-right: 2px yellow solid;
border-top: 2px yellow solid;
left: 15%;
position: relative;
text-align: center;
top: 5px;
width: 70%;
}


Javascript:
function pageLoaded()
{
var fullmenu = document.getElementById("fullmenubar");
//fullmenu.style.visibility = "hidden";
fullmenu.style.top = "-70em";
fullmenu.style.height = "70.2em";
}

function overCollapsedMenu()
{
var fullmenu = document.getElementById("fullmenubar");
//fullmenu.style.visibility = "visible";
fullmenu.style.top = "0px";
fullmenu.style.height = "";
}

function leftFullMenu()
{
var fullmenu = document.getElementById("fullmenubar");
//fullmenu.style.visibility = "hidden";
fullmenu.style.top = "-70em";
fullmenu.style.height = "70.2em";
}


Oh, sorry, did you want that menu to be at the bottom, maybe for some Mac OS X dock-style menu? Well, in that case, for the menubar, change
top: 0px;

to
bottom: 0px;


and in the javascript replace all instances of "top" with "bottom". Enjoy.

Wednesday, February 4, 2009

PyGame Presentation

It's been a while since I posted, I know, but I've been busy. Here's one of the things that's been occupying my time. I worked up a 2d top-down collecting game demo for the Drexel Game Developer's Group, and a presentation to go along with it. I'm only a week behind schedule for posting it, which is easily attributable to my laziness.


Here's the presentation:





And here's a link to the code:


You need to have python and pygame installed to run it, but other than that, just execute runner.py.

Wednesday, December 31, 2008

Defend The < Insert Anything >!

Happy New Year! It's been a while since I last posted but I've started a few other posts, and will hopefully will be getting them out of the tube sometime soon. 


When I was younger, my dad, who was in the military, told me that whenever the Army is going to attack a fortified position, they always tried to have a 3 to 1 advantage on the defenders, to minimize their casualties. This is because it is much easier to hold ground than it is to gain it, especially if you know the lay of the battlefield better (or even fortified it yourself). You can concentrate your resources in certain chokepoints, and gain significant advantages on your adversaries. Unless taken by surprise, it is very easy for a defensive position to hold back wave after wave of attackers.

I think that this is one of the primary reasons that the "Tower Defense" style of games is getting very popular, especially in the casual/mobile gaming scene. Usually termed as "Strategy", "Action Strategy", or something similar, these games have a very basic premise: you've got a thing, the bad guys want to blow up your thing, don't let them blow up your thing. It's actually quite ingenious the way game designers have kind of spun us on our heads. Back in the days of yore, the player was always attempting to get past the defenses, rescue someone or something, or blow something to smithereens. Now, players are tasked with keeping out all those pesky interlopers, though the basic characterizations are the same.

What do I mean by that, you ask. Well, when one character was able to singlehandedly slaughter the entire Russian army with nothing but a toothbrush, some people called that "unrealistic." However, when that single person is tasked with repelling wave after wave of robotic archer demons, that's much more believable.

Like in my post about zombies, people who play video games like to suspend disbelief far enough to accept the game world, the (usually ridiculous) story, and the mystical powers that they are somehow imbued with. However, granting a modicum of realism, such as having them set up defenses, and actively engaging swarms of enemies, allows them to feel empowered, but not invincible. When the player feels like they can do anything with little or no consequences, the game breaks down somewhat, as the player tears through the levels, unconcerned about what will become of their avatar.

That's all I have to say on the subject, don't worry, I promise that my next post will have some code in it. ;-P

Thursday, December 18, 2008

The Analysis of the Dead

In this past week's Zero Punctuation (I should really stop getting my blog ideas from it, I'll work on that), Yahtzee remarked that besides Pirates, Monkeys, and Ninjas, Zombies were perhaps the most popular thing among "nerds". Specifically gaming nerds. Yes, the "legitimacy" of zombies in popular culture is growing every year. What used to just be a cheap horror movie effect has actually been used to create artsy, compelling narratives and games. Need proof? Check out "Fido."

Sure, zombies are getting big. Pirates got big, Ninjas got big, monkeys...I think their time has passed as well. Zombies seem to be sticking around for a bit longer though. It's probably partly due to the whole "decomposing" thing. All joking aside, what makes nerds, a generally erudite and intolerant bunch, so happy to have an antagonist that is slow, dim-witted, operates in hordes, and attempts to eat brains?
Hey, wait a second, I think there might be something there.
Zombies are the exact opposite of what a stereotypical nerd wants to be. They're barely above fungi when it comes to IQ, and have an unstoppable need to attack those that aren't one of themselves. Is it just me, or does this sound exactly like the kids that made fun of you in high school because you'd rather read than watch "Grey's Anatomy"? In fact, when you think about it, what do zombies usually want to eat? Brains? What's the only way to kill them? Kill their brains? If someone was coming up with these metaphors, they weren't digging very deep (probably about 6 feet). 
What naturally follows the intelligence disparity is the common criticism nerds have for "normal" people, that they act like sheep, meandering pointlessly around in herds. Or hordes. Used to social exile, imposed either by self or by others, nerds generally scoff at being part of a large group. They don't want to be following the trends that everyone else follows, because everyone else is stupid, and probably wrong. If you hadn't noticed, this is where the intolerance comes out. Although they commonly accept people who are "different" into their ranks, many nerds find non-nerds to be unbearable. Therefore, any nerd anathema is most definitely going to exist in some sort of large group. This serves another purpose as well. By making their antagonists a seething mass, each individual is deidentified, and it doesn't really matter who's head you're having to lop off to get to the rescue zone. It could be your old gym teacher, that cute girl who said you smelled funny when you asked her out, anyone. 
All that being said, I have to say that I'm still a zombie fan. Although I like to think of myself as a very tolerant person, I'd definitely agree that part of my liking of the zombie metaphor is a bit of distrust and dislike of the general public. Not exactly as a mass of individuals, but the whole societies themselves. To me, the zombie hordes represent the selfish, immutable cultures that are sending all of us to hell in a handbasket, finally imploding upon themselves, making way for a new world, while still representing major obstacles to that world as they slowly rot away.
Or maybe I'm just hungry for BRAIIINS.

Tuesday, November 25, 2008

Thoughts on Advertising

This is actually a topic that I've been thinking about for a while now, going back to a conversation I had at with Corvus Elrod at his "moving to the West Coast" party. We were discussing advertising in games, and generated a lot of interesting points. As a storyteller, it is anathema for him to see anything that pulls a player out of the game experience, and have them thinking about products in the real world. I agree with this, to a point. When one thinks of the rise of casual games, and the free product business model, it has to be conceded that advertising is one of the main revenue streams (and therefore driver of) the games industry. Armor Games was a company that I though had nothing but cheesy, vapid fare, until I was given a disk by the people of the Indie Games Showcase. Some of their offerings, particularly in the puzzle category (which I usually avoid), blew my mind with their innovations. This company, which is producing quality (though flash) games, is completely supported by the ads on their site (as far as I can tell). 


However, I just bought a new cell phone (a Google G1, in fact, and I love it), and got my first telemarketing call on it a few days afterward. Rather than encouraging me to buy whatever product they were hocking, all that call did was remind me to add my number to the "Do Not Call" list. So, the real question here is, why don't I mind unsolicited advertising next to games I play online, or even in my email, but there's a national response to telemarketing and spamming?

One word: Interference.

If advertising interferes with what you're trying to do, then it's a problem. Calling my phone, or sending me email, wastes time that I would otherwise spend doing other things. Interrupt me, and you're not hooking me as a customer. If I'm already on a website (or watching TV, or at some sort of sporting event), I'm an audience member already. If I happen to look at an ad that is up while I'm waiting for the next play, that's not interfering with what I'm trying to do, it's not breeding any resentment in me. In fact, if it's entertaining enough, I might even be glad it's there. Just look at how many funny/amazing commercials have been posted, by random people, up on YouTube. I readily admit that I would not buy Brawndo if they hadn't gone with an over-the-top, hilarious ad campaign.

Personally, I have no problem with advertising. In its most basic form, it's just trying to get you to buy something. That's fine, if we didn't buy things, we wouldn't really have an economy. Buying things drives innovation, and makes our lives easier. I even don't have a problem with targeted advertising. Some people say it's an invasion of privacy, and it is slightly, but personally, I'd rather not be pitched Depends while I'm checking my email. I see nothing wrong with companies collecting information about buying habits, customer satisfaction and whatnot. It's all supposed to make things more efficient and convenient.

However, if advertising gets too pervasive, too omnipotent, then we have a problem.

Wednesday, November 19, 2008

Dealing with Null or "All" Parameters in MS SQL Reporting Services

I finally had something happen to me at work that I can add to this blog. Oh happy day, I feel as if I might faint.

Either way, I've recently become the SSRS "rock star" at my office, where even my bosses are stopping by and asking me questions about how to get their queries/formatting to work. It's not as glamorous as I thought it would be, and the groupies haunt my nightmares, but it's fun...ish.

Anyways, the person who was running the Reporting Services before me had an interesting way of dealing with using parameters to filter results in the SQL Query. I know there's a way to filter just using the wizard, but I'm of the opinion that it is probably faster (or at least more efficient) to do filtering in the query. For our filters, if the user doesn't want to use that filter, the first option says "All", but actually has a value of null. The way my predecessor would handle this would be to have a single query for every combination of null/not null parameters. So, if there was one parameter that could be null, there would be two queries, and IF statements to select which one. If there were two nullable parameters, that number raised to four. Three meant nine separate queries...et cetera

This wasn't really acceptable to me (mostly because I didn't want to have to add five more queries), so I looked to see if it was possible to use the IF statements right in the middle of the WHERE clause. No dice. So, what I did instead was use the following style of WHERE filter:

WHERE/AND (@param is null OR object.RelevantValue = @param)

This way, if the parameter the expression would still evaluate to true, and the filter statement would only matter if the parameter was actually specified. Now, the report query is 1/4 of its previous size, and 1/9th the size it would've been if I had done it the old way. Rock star? Maybe, maybe not, I don't care. This is just what I do.

Monday, November 17, 2008

Tables for Layout?

I love this

http://shouldiusetablesforlayout.com/

It was a response to a page that claimed that the average time that a web developer took before abandoning CSS for web layout was 47 minutes. Anyone who has worked with me (or watched me work on a web project) will vouch that I have toiled untold hours of my life away, simply trying to get a CSS layout to work. It warms my heart to see that other people are willing to be as fanatical about standards and best practices as I am.

Also, I'll be at the Philadelphia Game Expo this weekend. If you're there, say hi!

Sorry about the lack of posts, I've been working quite dilligently in what little free time I've had, but hopefully some more posts will be forthcoming soon.

Wednesday, October 22, 2008

Lock's Quest Recap

This is sort of a game review, but also a discussion about interface design, and the nature of fun in games. I recently purchased Lock's Quest, which was the best Strategy game at E3, which for a DS title, is pretty impressive. It's developers also put out Drawn to Life, a game that I wanted, but never got around to purchasing. Basically, you're a special boy in a war...blah blah blah, the story isn't really that important, but the game itself is really involving. 


You have so build walls and turrets to fend off increasingly large and tough armies of clockwork robots. That in and of itself sold me, but the DS's touchscreen is really well implemented in both combat and repairing damaged structures. Depending on what you're trying to do, there's an associated task (pulling a lever, spinning a gear, etc) that makes the action you're attempting go faster, or more effective. While this sounds kind of hackneyed and repetitive, they're mixed up nicely, and you don't just sit around for 10 minutes doing the same thing over and over again.

I'm also really impressed with how they set the flow of the game up. After a few rounds with your defenses, you have an impenetrable death-fortress, and you're able to handle even the most vicious onslaughts. Then, the game tells you that you have to go grab an objective all the way on the other side of the map. It's frustrating, yes, but it breaks the whole build-repair-fight cycle, which is nice. It's also worth noting that there's few things more awesome than watching wave after waves of bad guys crash on the rocky cliffs of your defenses.

One thing is infuriating though. The screen doesn't zoom out, and there's a fixed speed to the camera, so panning from one wall to another can sometimes take precious seconds. This in and of itself is not too bad, since (if you're like me) you can set up relatively smaller, close defenses. However, when you pan to a location, and then tap (which tells your character to move there), the AI that keeps the main character from running aimlessly into a tree is a little bit lacking. So far, I have lost a solid number of turrets, and even a level or two, just because there was a rock or tree or bit of something in the way, and the flax-haired hero did nothing except struggle against the properties of matter until I realized and gave him an easier location to get to (after a while, you get used to tapping out smaller, shorter paths).

With that behind me, I do have a few more good things to say about this game. Despite the "ehh" story, the game has a good length to it. I thoroughly enjoy the game mechanics that are in place, and was worried that with all the cool stuff in it, that the levels would be cut tragically short, leaving me wanting more, much like when you when you visit home, and only get a single strip of bacon, because that's "healthier." Don't worry, this game has platters of bacon. I've been playing it for about two solid weeks now, mostly during my commute and at home and I think I'm only 2/3 of the way through it. 

Also, the difficulty is really well done. While I didn't like that there wasn't a standard dial-a-difficulty, which would be pretty easy to do with this game, I was able to clear most of the levels on the first try, though a good number of those were nail-biters, and a couple of them required a do-over. The increases in challenge over time are well-paced. I never felt too bored, and when I was right on the edge, something new popped up. Also, there's a fun little seige mini-game which would be right at home as a flash game.

Monday, October 13, 2008

Using A LIKE Operator With A String Parameter In SSRS

Hey-o,


Just something quick that I figured out today, that I felt warranted sharing. I'm doing some work with SQL Server Reporting Services (SSRS) and the Business Intelligence Development Studio (BIDS), creating reports for work. Today, I was asked to create one that used a LIKE statement in a WHERE clause where the argument passed to the LIKE statement is a string parameter. The challenge here is that concatenating "%"s to the parameter didn't work in the query, nor did the same process in the Dataset -> Filter By tab. The only possible answer I could find was on experts exchange,  which requires a subscription, so I had to figure it out myself. Here's what I did:

  1. Create the String parameter you actually want to search with. Make sure that it can be blank, but don't let it be null. For the sake of the example, I'm calling it Filter.
  2. Create another, hidden parameter that is also a string. Make sure it is hidden! Then, set the default value to be non-queried ="%" & Parameters!Filter.Value & "%". I gave this parameter the name FilterFormatted. Now, hit okay and close out your Report Parameters.
  3. Now, in the query, all you need to do is write "WHERE columntofilter LIKE @FilterFormatted". If you're testing the report, make sure you put the "%" before and after your search string, but going to the "Preview" tab will let you test it the way it'll be deployed (though you should probably know that already).
That's it! Interesting problem, simple fix, solution posted.

Wednesday, September 24, 2008

OpenSocial Version 0.8 App Development From Scratch


With the newest version of OpenSocial out, I felt compelled to revisit it, despite the fact that my new job couldn't have me farther from it. A labor of love, some would say, to stay up-to-date on a constantly evolving platform, like trying to hold onto pudding with your bare hands. Anyways, where was I?

I'm going to develop an OpenSocial 0.8 app from scratch. Let's get started. First, I need to set up the initial scaffold.


<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="Pandaface">
    <Require feature="opensocial-0.8"/>
  </ModulePrefs>
  <Content type="html">
    <![CDATA[
         <div id="gadgetdiv">
             Panda!
         </div>
    ]]>
  </Content>
</Module>

This app is going to be named "Pandaface," as you can see from the line (  ModulePrefs title="Pandaface"). It's also important to point out the gadgets.util.registerOnLoadHandler line. This sets the Javascript function that will execute when the gadget loads. Usually, one would define this in the body tag of an html page, but declaring it in that manner makes sure that the callback function (in this case gogoGadget, I prefer that over "main") won't execute until all the gadget code and its dependencies are loaded.

Step 2 is setting up the first data request. In my first request, I like to get the OWNER and VIEWER objects. These will allow me to know if the viewer is looking at their own version of the App or someone else's. To do this, gogoGadget is changed to look like this.

function gogoGadget()
{
var request = opensocial.newDataRequest();
request.add(request.newFetchPersonRequest("OWNER"), "get_owner");
request.add(request.newFetchPersonRequest("VIEWER"), "get_viewer");
request.send(response);
};
This creates a request object, adds two FetchPersonRequests, and sends the request out, saying that the function 'response' will deal with the data response. It is important to note that the callback will not execute until it has all the data. Let's lake a took at the response function.

function response(responseData) { owner = responseData.get('get_owner').getData(); viewer = responseData.get('get_viewer').getData(); };

Not terribly interesting at the moment, but it is important to note a few things. In gogoGadget, the last paramter that is given is a name for the specific response. MAKE SURE THESE MATCH UP. In my other OpenSocial adventures, I got that mixed up at one point, and couldn't for the life of me figure out what was going wrong.

Now, let's pull down some persistent data. I'm just going to have a single variable, face_data, and pull it from the orkut sandbox server. To do this, I have to declare another datarequest, and add a newFetchPersonAppDataRequest. Back in .7, you could just pass the user's id, and the name of the app data you wanted to pull. Now, however, you have to create an IdSpec object for it. This is new, and fairly unintuitive (especially to people who've been working with it as long as I have).  Here's the full data request.

var ownerspec = opensocial.newIdSpec({ "userId" : "OWNER" , "groupId" : "SELF"});
var datarequest = opensocial.newDataRequest();
datarequest.add(datarequest.newFetchPersonAppDataRequest(ownerspec,"face_data"),"face_data");
datarequest.add(datarequest.newFetchPersonAppDataRequest(ownerspec,"face_url"),"face_url");
datarequest.send(loadUI);

Make sure to pay attention to what you name the variable, like with the personrequest. You also have to make sure your idspec is constructed correctly. At this point, you can only have "OWNER" and "VIEWER" for "userId", and "SELF" or "FRIENDS" for "groupId." There's also an important thing to note at the 3rd line. The first "face_data" is actually the name of the variable the request is supposed to retrieve. Along with named variables (which return as "null" if they haven't been set yet), you can also just put a *, for all variables associated with your app. On the response side, there is another main difference from the person requests.

function loadUI(responseData)
        {
          var facedata = responseData.get('face_data').getData()[owner.getId()];
          var faceurl = responseData.get('face_url').getData()[owner.getId()];
          var to_output = owner.getDisplayName() + " is a ";
          
          if(facedata == null)
          {
            to_output += "lazy";
          }else{
            to_output += facedata.face_data;
          }
          to_output += " panda.";
          if(faceurl == null)
          {
            faceurl = "http://www.cs.drexel.edu/~asc38/Google/meh.png";
          }else{
            faceurl = faceurl.face_url;
          }
It is important to note how to retrieve the data from the response object. Not only do you have to call get() with the field name, and getData(), but you must also grab the data from the index of the owner's id, and then call the name of the variable off THAT. 

What this does is set default values for facedata and faceurl, and then combines them to make the entire gadget rendering. Now, if you look at my profile, either as me, or as someone else, you see the following:













Not terribly exciting, but you can see what it's trying to do. Now, to add a bit of user functionality. For this app, the only real interactivity is going to be when the owner changes their emotion or the panda's face. To do that, we first have to see if the person viewing the app is the owner. That's pretty intuitive:

if(owner.isViewer())
          {

See? Now, what I do is build an admin panel/form that has a text box for the user to input their emotion, and then radio buttons.

owner_output = '


New Panda Emotion?
';
            owner_output += '
New Panda Face?
';
            owner_output += '
';
            owner_output += '
';
            owner_output += '
';
            owner_output += '
';
            document.getElementById("gadgetdiv").innerHTML += owner_output;
          }

For the sake of brevity, I'm not going to detail both changing functions, but just the important bits of changeFace. You get the value of the new emotion, and then create an updateAppDataRequest and submit it. You still need to specify a callback though. This lets you do error checking to make sure that the request made it through alright.

var updaterequest = opensocial.newDataRequest();
 updaterequest.add(updaterequest.newUpdatePersonAppDataRequest("VIEWER", "face_data", newemotion), "update1");
updaterequest.send(finishUpdate);

For finishUpdate, I just have it mirror the initial data pull, and loop back to loadUI, thus completing a beautiful life cycle.

        function finishUpdate(responseData)
        {
          var ownerspec = opensocial.newIdSpec({ "userId" : "OWNER" , "groupId" : "SELF"});
          var datarequest = opensocial.newDataRequest();
          datarequest.add(datarequest.newFetchPersonAppDataRequest(ownerspec,"face_data"),"face_data");
          datarequest.add(datarequest.newFetchPersonAppDataRequest(ownerspec,"face_url"),"face_url");
          datarequest.send(loadUI);
        }

Obviously this example could be fleshed out a LOT more. By adding posting to the activity stream (which I may still do) and a much prettier, this app could be a lot more solid. All in all, it's not bad for a few hours of work. The full gadget xml is at:

Monday, September 8, 2008

Browser Inconsistencies: Part 2

Hey-o

Today was my first day at my new job. Exciting, but nothing notable yet. Hence, this is a relatively shorter entry.

Anyways, I was playing around with HTML and CSS again, putting together a chess/checkers-style board with HTML and CSS, and found another browser inconsistency.

I have a 4x4 grid of alternating white and black tiles. The tiles are arranged in rows, and there are tokens that are placed absolutely on top of them. The rows of tiles and tokens are all in a master div. The rows are each divs that have a clear: both property to make them cascade properly. At first, I didn't define the horizontal position of the tokens. In firefox/opera/chrome, you see the following:
















The absolutely positioned tokens are removed from where they "should" be, and are placed in the upper-left corner of their containing div (the white token has been defined to be that low). However, in IE8, this happens:















Apparently, if a horizontal position is not specified, the absolutely positioned elements stay where they would, even though they are removed from the box model. You can tell they have still been removed, because if they hadn't, then the border would be surrounding them as well. Setting the left: 0px; property makes IE8 render the same as all the others, but it is still interesting.

Monday, August 18, 2008

Browser Inconsistencies: Part 1

I did a freelance gig recently that required me to do some HTML/CSS. Like all web tasks, one of the primary concerns was browser compatibility. After several hours of cursing at IE and Firefox, I found a good php script that reliably detected browser, so I used that, but doing that always feels like cheating, so I'm going to be spending some time in the coming months playing around with CSS and HTML, looking at where the breakdowns occur. Here's my first post on the subject.

Surprisingly, when just messing around, it took a little while before I found my first break. I put two divs, one absolutely positioned, one relatively positioned, inside a larger div. The larger div was placed relatively at the top of the screen, and given the style "top: 20%;" What happened then? I'll show you.


















Surprisingly, Firefox was the one that did not register this style correctly. I'm pretty sure it is an issue, and not something laid down by the W3C. This is because when I changed the style to read "top: 20px;", both browsers behaved the same. Interesting.

Thursday, August 7, 2008

Little Bit of Good News

Apparently, my blog is the top hit for the search "add hidden fields programmatically" on Google.

Hooray!

Welcome everyone who's looking for how to add hidden fields programmatically. Please leave comments as to whether or not you found my entry useful!

Monday, July 28, 2008

Variable Scope Issues

Again, here's a new link to my latest project. http://www.cs.drexel.edu/~asc38/Projects/CdlC/
I think it's actually pretty fun, so I hope you try it out.

The only major issue left to tackle is the high score board. When the game ends, you can submit your score to the online scoreboard (I'm currently in first place, go figure.) It was a chance for me to play around with flash's internet communication abilities. It works pretty decently as well, if you ask me. The problem is that, for some reason, the scoreboard only shows up the first time you play it (per page refresh). What that means is that if you press the "Play again" button, play the game, end the game, and submit your score, you won't see the scoreboard. I'm completely scoobied as to why that is. The code to update the scoreboard is as such:

trace(event.target.data);
htmltext = event.target.data;
scoreBox.htmlText = htmltext;

If you're not familiar with flash, trace is a command that outputs things to a special "output" window. Therefore, the event.target.data variable should be shown on my screen. The problem is that despite the fact that I do get the correct text outputted to me by the trace call, the scoreBox.htmlText doesn't reflect what it was given on anything other than the first time through the game. I had a similar issue (in fact it was the only real major "bug" in the first iteration) with the images from the last scoop being present on replays as well, and that was fixed by making sure that everything was reset properly at the appropriate time.

My guess is that this is a variable scoping issue, partially because that was the issue the first time, and partially because Flash's scoping is about as confusing as watching Memento when you're tripping acid. As far as I can tell, variables instantiated within a frame are scoped globally, unless they're within a loop or function. However, commands, or anything else for that matter, only apply at that specific frame. This kinda makes sense. You might want to use a variable you defined somewhere else in the program, and you don't want all of your code executing at once. The issue here is, when are objects (like the scoreBox) that are defined in the scene, not in the code, created? Are they global? Can I change their values before they're visible? I'm still trying to figure it out, so if anyone has any suggestions, feel free to leave them in the comments.

As far as I can tell, it's only used for debugging, as my experiences with the actual Flash debugger were about as pleasant as shaving with a rusty butter knife.

Wednesday, July 9, 2008

Baby Steps

I think this is probably my first post ever that contains any actual coding in it, and frankly, I'm a little scared. This is such foreign territory for me, I don't know where to start.

So I'll start with a link. http://www.cs.drexel.edu/~asc38/Projects/Invaders/

Yes, it is in flash. I feel dirty with this being the first "complete" program I post, but we all have our flaws. I actually haven't paid for Flash CS3, but I'm using the 30-day free trial, and working fast. In terms of development, there are some things I like and some things I really dislike, but I'll get into that later.

If you can't tell by the URL, or the name, it's just a cheesy, quick Space Invaders clone. I programmed it in ActionScript 3, despite never having used it before, in about 3 hours. My main problem so far is that when there is contact between the lasers and their target. The lasers are (obviously) placed dynamically, and in their update method, I tried using the following line to "kill" invaders when they touch.

stage.removeChild(thislaser);
stage.removeChild(Invader1);

Which, on top of being horribly hardcoded, throws the following error.

Error #2025: The supplied DisplayObject must be a child of the caller.

I tried everything I could think of, and eventually just decided that it was just a "Flash Thing," until I realized that the lasers were being added like so:

this.addChild(newLaser);

The problem here was that when I was looking at how to dynamically add new objects, the tutorial didn't have their code in a function, it was just on the stage. Therefore, using the keyword this on the frame added for the stage, setting up for a similar removal with this.removeChild(). Apparently, when inside the function, this is not the stage. There was another issue, however.

The Invader still would not be removed via stage.RemoveChild. It continued to throw the "Child of the Caller" error. I intend to dig deeper into this, but not too much, though, since the issue is relatively moot. This is because the Invaders were added to the scene statically, which I found is unlikely to happen in any sort of "normal" game. Things that are dynamically added and removed (just as God intended,) come into and out of the scene without an issue. Not terribly enlightening, but at least it wasn't about the iPhone.

Monday, June 30, 2008

Get Ready To Grind Yourself Retarded

One of my current favorite web video series at the moment is The Escapist's Zero Punctuation. Ben Croshaw definitely has his own brand of humor, but I feel the need to comment on one of his common criticisms: grinding for inordinate amounts of time. First, a definition.

Grind (v): To repeatedly perform an identical action or sequence of actions in a game solely for the purposes of advancement otherwise unreachable.

Being forced by a game to perform the same action or actions over and over again is actually what gaming is usually about. Take any game you can think of. FPS, RTS, casual games especially, they're just an endless repetition of doing the same thing over and over and over, until you either fail to perform that action correctly a certain number of times, or you get bored/tired, and go to do something else. This isn't necessarily bad. Can you imagine a game where controls changed every two minutes, along with the perspective, goals, and game mechanics? It would be horrible and confusing. It could be intriguing to some (see: masochists,) but for most people, it would something that would be set aside almost instantly.

So, assuming that almost all games are a set of repeated actions, what makes some mechanics fun, while others are more boring and tedious than de-lousing your grandpa? Why is it that battling 500 rats or goblins to level up is mind-numbingly sloggy, whereas blasting your way through the Combine, Covenant, or NOD fun?

Pardon me for using programmer-speak if you're not into that, but the answer is shifting arguments. If you're the Ruby or Python interpreter, you don't mind seeing the same function called with the same values 500 times. You're a computer program, you don't even have feelings. In fact, why are you reading my blog? Get back to work, damnit.

Ahem.

As I was saying, people are not computers. We like things to change frequently, but in small and occasionally medium-sized ways. For example, most JRPGs I've played are basically big grinders wrapped in a tissue-thin container of plot. You encounter some bad guys, you have to hit "Attack" or "Magic," and direct death towards your enemies. Occasionally, there's a cool cut scene thrown in. This could be fun for a while, but eventually you know the key controls that you could be a blind vegetable (personally, I like carrots, but some people are partial to broccoli) and achieve the same results. The original Pokemon games (Red and Blue, for you youngsters) realized this, and also realized one of the potential ways to fix it. If you have so many different enemies that you only counter the same one every once in a while, it isn't that monotonous. Eventually, that will get boring, but before it does, they let you advance onto a new area with a new set of creatures to brutalize and enslave.

Causal games are the kings of grinding. In fact, it's pretty much their modus operandi. You take one concept, one mechanic, and apply it ad nauseum until the player is either comatose or victorious. Why are they still ridiculously fun (and addictive)? Variation. Bubble bobble and Sudoku wouldn't be fun if they had the exact same patterns every single time. Even before computer games were invented, we had crossword puzzles that had the exact same concept. Do a thing, change the parameters, do the thing again, etc.

So how does fun repetition become painful grinding?

  1. When you want to advance in the storyline, but can't because you have to grind some more. This is almost more of a pacing issue than it is a game mechanic issue. Of course, you don't want to just shuffle the player from cutscene to cutscene, with barely any gameplay (unless you're Devil May Cry 4, of course) but at the same time, you don't want the player to be so bored that they turn off the game before they get to the next plot point.
  2. When the challenges don't change at all. This should really be a no-brainer. It's why Postal workers used to go crazy. All work and no play makes Jack a dull boy. If you don't want your players to be bored, than switch things up a bit. Vary the enemies somehow. Difficulty, color, tactics, numbers, whatever, just try to throw a wrench in the player's grind machine every once in a while. They'll be surprised, possibly angry at first, but hey, angry beats bored.
  3. When the types of challenges don't change. This is subtly different from #2, but important. It's actually the reason why the concept of "boss battles" has done so well throughout the course of video game history. This is the "medium-sized" shift I was talking about earlier. The game mechanics can still be the same here, but there has to be a significant shift in what the player is doing with them. Instead of slicing through hordes of little enemies, they're fighting one very difficult one. Instead of building up a base and defenses, building an army and attacking, the player is given an army, and shoved out the door to complete an objective. Minor changes like the ones mentioned in #2 will hold off the feelings of grinding, but nothing abates them faster then having their usual plans rendered temporarily useless.
Whenever I design a game, or even a game mechanic, I always have to ask myself "would this still be fun after two hours?" I think that if more game designers did the same thing, then we wouldn't have to hear about how someone had to grind all night to get the items necessary to get up to level Y so they could make beef stew.

Wednesday, June 25, 2008

Why I Hate Flash

I could apologize for this being the first post in two months, but I won't. This is my third rewrite, mostly due to my incompetence, but frankly it's beginning to wear thinly on me.

I'm currently taking a game design course at my university along with two of my friends. Woo and yay. A class that actually may have some bearing on what I might actually do with my life. Don't get me wrong, but I don't see any time in my future when explaining if the character in John Updike's A&P will be required of me in the line of work. Anyways, I love gaming, I love game design, I love talking about game design, and I like several people in the class. However, after our first meeting, I feel a little down. Why? This sentence:

"2D Games will be done in Flash."

Well, there's the chandelier made of rabbit droppings. I despise Flash, and apparently most people cannot understand why, so I'm going to lay it out here, as much for me as it is for the half-dozen other people who will read it.

First and foremost, I don't like Flash because I have to pay to program it. This, if you didn't know, is a bit of an anomaly in the programming world. With the exception of Flash, there isn't a single other programming language that you have to pay to use. Even Microsoft's .NET languages have an open framework, and if you'll really itching to do some Mac-Based VBscript, you can use the (open-source, no less) Mono project headed by Miguel de Icaza.

As a student, the cheapest I could get flash for is around $250. If I wasn't a student, this price point goes up to $700. I have no problem with Macromedia Adobe wanting money for their code, that's all well and good. However, there is NO WAY to do anything in flash without using their IDE. Microsoft's Visual Studio is a great IDE. It comes with lots of awesome tools built in, and that's effing sweet. It also costs around the same amount as Flash. I couldn't find the exact price point, mostly because I was bombarded with offers for trial and free versions. There is a free edition of almost every Microsoft Developers product. They're called the "Express" editions, and though they lack the bells and whistles of the paid versions, they still get the job done. In fact, if you're a student, you CAN get free versions of the full product. Yes, that's right, you can get Microsoft products for FREE, if you're a student.

The reason for this is that Microsoft wants to get students used to using their products and their languages. It's a little sinister when you think about it, them baiting you with freebies when you're a poor college student, but Adobe doesn't even attempt to do the same thing, and basically just flips you the middle finger.

When I bring this point up, most people say "Why don't you just pirate it? Problem solved!" No, you vacuum-craniumed dolt, I'm a programmer. I want to get paid for the programs I write. If someone wants to charge for their program, that's fine by me. I love open source, but hey, someone's got to make a living somehow. If I don't want to pay for their development environment, then that should be their problem, not mine. My problem is that I cannot do Flash development without buying their product. Stealing it would be similar to a wheat farmer stealing potatoes. It's just wrong. Hell, I'm sure that half the reason Flash is so expensive is to offset the lost profits from people pirating it.

The other big pro-flash reason I get is this: artists use it. Well you know what, screw the artists. Last time I checked, a game artist should be doing artsy things, like drawing or modeling or whatnot. My job is programming, not theirs. If some beret-topped punter is going to tell me that he likes using Flash because he can program in it, that let me get my paintbrush out, cram it up my bum, and start "composing assets." Images are all the same. A JPEG in Flash is a JPEG to PyGame, or OpenGL, or DirectX. You want vector graphics? Awesome. Fireworks does SVG. I checked. If artists want to start doing programming, then I might as well go fly helicopters, because apparently I'm not needed anymore.

As vitriolic as I'm being, there would be one simple thing that Adobe could do that would make them a-ok in my book. Don't sell the platform, sell the IDE. If I can program Flash using a text editor, I'd go for it. Eventually, once I'd made some cash, I'd see the benefits to using the IDE, and purchase it. Having an up-front cost is nothing but an unnecessary barrier that is a relic of a bygone era.

Also, I'm hoping my artist friends take my slurs against them as being all in good fun. ;-P