Monday, October 31, 2011

Chasing Dragons

A few days ago, my wife and I watched Get Lamp, a documentary on the rise and fall of text adventures and the persisting genre of interactive fiction. I had heard about it on Richard Bartle's blog and have been eager to watch it. I grew up playing text adventures on my C64. Although I spent a lot of time reading Byte and Compute magazines—mostly typing in BASIC programs and reading advertisements for games, as I recall—I did not have a larger context to understand the industry and the personalities behind it.

I found the documentary fascinating, but I'm not sure how strongly I can recommend it to those who didn't cut their teeth on text adventures. The documentary assumes a certain amount of tacit knowledge: how could a viewer appreciate the discussion of mapping if they had never been in a maze of twisty little passages, all the same? I'll definitely bring it up for a potential movie night next semester when I'm at the Virginia Ball Center for Creative Inquiry.

The documentary consists almost exclusively of interviews, and one of the interviewees was Chris Crawford. I had previously only known him by reputation as a respected game designer and as the author of The Art of Computer Game Design. I enjoyed his interview in the documentary as well as the extended interview in the DVD extras, so I decided to read more about him.

Of course, I turned to Wikipedia, on whose page there is a section devoted to Crawford's Dragon Speech.   Wikipedia's summary piqued my curiosity. Thanks to the wonder of the Internet, this 1992 speech is available on YouTube, despite its having been given a year before Mosaic ushered in the World Wide Web revolution. I've embedded part one here; parts two through five should come up as recommended links after.



This goes immediately into my list of great presentations (which someday needs to migrate from my old blog to this one). Crawford is clearly a master of the topic and has carefully crafted the presentation. I could go on about the specifics, but really, you should just take some time to watch it. I am envious of the opportunity he had to study under another one of my heroes, Alan Kay. I'd love to have a day to shadow either of these visionaries, to get a better sense of how they see the world and of what drives them.

Crawford is passionate about his work, and it's his well-calculated passion that helped me to understand that this presentation isn't really about games at all. It's about dreams. It's about working to identify what it is that you really want, and then consciously and intentionally deciding to pursue it, even if it means making painful decisions.

Presentations like this make me uncomfortable, but that's a good thing. They induce introspection, resulting in an honest evaluation of what I am doing and where it is leading. I feel like I am in Crawford's six years at Atari: I'm working diligently on what seems right for now, but every now and then I see the shadow of the dragon.

Sunday, October 23, 2011

Notes from the Indiana Video Game Developers' Business/Game Design Panel

Yesterday, I went down to Indianapolis for the Indiana Video Game Developers Business/Game Design Panel, hosted by the Independent Video Game Developers Association and the Indianapolis Chapter of the International Game Developers Association. The bios of each of the panelists are available online, so I won't  summarize who they are here, but it is noteworthy that there was a great mix of expertise, including those interested in corporate branding, serious games, independent self-funded development, and even an IP lawyer. One of my students was there with me, but it was a great discussion and I wish more could have come. I will use this post to share some of my notes, both for my own use and to share with those who could not be there.

The topic of iterative design came up several times, with the folks from Studio Cypher especially advocating for physical prototyping. Most of the panelists strongly advocated for focus groups throughout the development of a game. I was tempted to ask about specific methodologies: no one mentioned "agile" by name, but the spirit of it was strong. I ended up holding my question, in hopes that I could follow up with some of the panelists at a later date to discuss their methodologies more closely, perhaps even in a research context.

A few panelists mentioned making games for children and using children in their focus groups, so I asked how they went about recruiting children, especially since some were adamant about needing NDAs for focus groups. Two out of the three suggestions were the same approaches I have used: friends/family and schools. The other group they mentioned was the Girl Scouts, which I had not considered. They also mentioned that research firms could be hired, at a high price, to do these things for you. That's another one I had not thought of, but all agreed that this was likely not worth the price.

There were a few questions about how to choose technology for projects, and the panelists answered with a predictable and appropriate, "it depends." The panelists observed that all programmers want to write their own game engine, but that this is impractical unless it is one of the team's core competencies. This matches advice I've heard elsewhere, but I get the impression that the younger members of the audience had not thought about the issue before. When it came down to what technology was being used, there was glowing praise for Unity—even the teams that weren't using it seemed to wish they were. This made me feel good about getting my own game programming students this semester exposed to it.

While there was a lot of love for Unity, the relationship between HTML5 and Flash was mixed among the panelists. The consensus seemed to be that some clients had started asking for HTML5 games, but not all. While most current Web-based games were still in Flash, there was an expectation that HTML5 would be escalating quickly due to its being backed by such large corporations.

The highlight of the panel, for me, was actually something shared by a non-panelist. It was a question I was going to ask as well, but Andy Harris beat me to it. It sounds like he's in the same boat as I am, where he is constantly asked by middle and high school students what they should do to become a "game designer." When I am posed this question by prospective students, I explain, verbosely, the relationship between video game design and programming, the history of the two, and the transfer of skills among them. Andy had a much more memorable and clever explanation that, if you want to be a game designer, you write the code or you write the check. All the panelists agreed. This was great to hear, but I couldn't help but feel a little bad for the handful of young aspiring artists in the room who clearly had not done their homework along these lines.

The importance of a portfolio was mentioned, and after a question from the crowd, the panelists clarified that a portfolio is as important for programmers as for artists. One panelist recommend grabbing a library like Flixel or FlashPunk, then creating ten games with them, each one exploring a different aspect of game design such as pathfinding or AI. This would provide you, as a programmer, with evidence that you have the range of skills required. This sounds like a great break project to me!

The panel had been advertised as running from 1:00 to 3:30, but at 3:30, it was only an intermission to be followed by some other activities. Looking over the handouts, it looks like one of the activities was to be drinks at MacNiven's to talk about the IGDA, which would have been fantastic. Alas, I already had plans to return home for dinner, and so I had to step away. I am glad I was able to attend the panel, and it was great to see some of my colleagues whom I don't see very often. Next time, I'll try to keep time for a pint in my schedule!

Wednesday, October 19, 2011

DeMillo wrote this post for me already

I have been reading and enjoying Rich DeMillo's new book, Abelard to Apple: The Fate of American Colleges and Universities. I am planning to read the final chapter tonight and had intended to post a summary afterward. However, on his innovate-edu blog today, DeMillo posted his comments to the Joint Education Subcommittee of the Georgia Senate, and these provide an excellent summary of the book. This link will get you there.

Friday, October 7, 2011

Computer Science: It's not just for dead women

How ironic that today is Ada Lovelace Day, as I just took a picture of her out of a Computer Science Department display case this morning.

Since I came to Ball State, we had a display case that showed four images of women in computing. I did not snap a picture of the display case, but here are the four individual images.





On one hand, one could argue that these images show that women can succeed in computing. On the other hand, I think there's a good chance that a modern young woman who walks by these will come to the conclusions that women could succeed in computing, ... back before color photography and pants. That's not very relevant to a generation that has grown up with the Internet, social media, games, and service learning, four factors that have been identified that get girls interested in pursuing Computer Science.

I got the blessing from my department to update the display case, which now looks like this:

The plaques on the left and right are awards from the 2008 and 2011 CCSC:Midwest Programming Competitions, in which teams from Ball State placed second and third, respectively. In the middle is a research poster put together by the students who were involved in both the Morgan's Raid and the Digital Archaeology project. The poster describes how we used Scrum and principles of agile software development and the lessons learned in the process.

One wouldn't know to look at the plaques, but both teams comprised of two men and one woman. The genders of these students was irrelevant: their success speaks for itself. Taking a closer look at the poster, you can see that although the teams have a male majority, there are women there too.

This is not as flashy as the University of Washington's excellent Why CSE page, which overtly demonstrates how underrepresented groups can and do succeed in Computer Science and Engineering. However, it does show that—right here and now—women are integral parts of successful research and development projects. Whenever I meet with a prospective CS major, we walk by this display case. I am glad that now I can point to these pictures of some of our most successful majors and show how they are working hard, together, and that they are proud of their work.

After all, Computer Science is not just for dead women.

A new team's first Daily Scrum

We spent the first several weeks in my game programming class covering the basics and exploring two platforms for game development, Slick and Unity. On Monday, the eleven students decided that for their semester project, they would like to work on one big team to try porting Morgan's Raid to Unity. I decided to mentor the team using Scrum, since that has worked so well for me in the past. For Wednesday, I put together a product backlog and the team had its first spring planning meeting. While I had recommended that the students read The Scrum Primer, I got the distinct impression that the vast majority had not done so; in their defense, I had emailed the link Tuesday night.

The planning meeting went well, although fifty minutes was awfully tight to introduce the fundamentals of Scrum and to do the planning. I used my Scrum diagram as a reference to talk through the process. We were missing three of the eleven team members, but we were still able to get a reasonable number of stories committed for the first Sprint.

Today was the team's first "daily scrum." At 8am sharp, everyone was present. I told them to get into a circle and report what they had done since last time, what they had planned for next time, and what were the impediments. They got up and moved to the open area in the front of the classroom, while I stood behind the teaching station.

Here's where the team really surprised me. In using Scrum with students many times in the past, I have found that they find it challenging to report to each other, that they prefer to report to me. I wrote about how my Summer team was able to leverage the physical space to have productive Daily Scrums, but that team was half comprised of people experienced with Scrum, so their team-facing attitude was to be expected. This team of eleven had one student with Scrum experience (Tom), and the rest had none. They formed the circle and showed a few signs of anxiety, but Tom started right in with his daily status. He passed it on to the teammate by his side, and the whole stand-up meeting went as smoothly as one could hope.

There are four differences between this team and those from my past experiences, and I suspect that each is a contributor to this team's success. First and foremost, I learned a lot about managing a Scrum team through my experiences last academic year, and so I was more careful to separate myself from the stand-up meeting. Second, there was the issue of physical obstacles between me and the team: as with the Summer team, the furniture provided a convenient separation. Third, there was exactly one team member who had Scrum experience, and he showed no hesitation in starting the meeting and reporting progress to the team. Whether he meant to or not, his example provided the perfect template from which the other students intuited the expected social behavior. Fourth, all save one of these students have taken previous courses with me in which we repeatedly applied principles of agile development. We did not use Scrum in  particular, but we discussed the philosophy and the implications as well as learning the practice through a six-week project in two deliverables.

I wish I had more data to support that last point. I would love to be able to claim that the students' experience in CS222 is a contributing factor to their ability to work in teams in upper-level courses, since that's one of the explicit goals of CS222. Unfortunately, the assessment data is not that rich. I mentioned three other contributing factors, and there are undoubtedly more. Still, it's anecdotal evidence that some combination of my teaching and the curriculum are working in tandem to improve student learning experiences.

Thursday, October 6, 2011

UI classes should not implement event listener interfaces

When one does a rudimentary search for Swing tutorials, one finds approximately a zillion examples that recommend writing code like this:
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;

/**
 * A frame that holds a button which really wants to be pressed.
 * 
 * @author <a href="http://paulgestwicki.blogspot.com">Paul Gestwicki</a>
 */
public class PressMeFrame extends JFrame implements ActionListener {

    /**
     * Start the application.
     * 
     * @param args
     *            command-line arguments (ignored)
     */
    public static void main(String[] args) {
        PressMeFrame frame = new PressMeFrame();
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    /** The uneditable text field into which we will put our output */
    private JTextField outputField;

    /**
     * Create an instance of this class.
     */
    public PressMeFrame() {
        outputField = new JTextField(20);
        outputField.setEditable(false);

        JButton button = new JButton("Press me");
        button.addActionListener(this);

        Container contentPane = getContentPane();
        contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
        contentPane.add(button);
        contentPane.add(outputField);
    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        outputField.setText("Thank you.");
    }

}


The problem I want to focus in on is that PressMeFrame implements ActionListener, but in truth, I can't stand looking at a class that extends JFrame when it doesn't have to. Do I really want to bind myself to JFrame right now? Not when I can just as easily make a reusable component that can be stuck into other things. Let me start this again...

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

/**
 * A frame that holds a button which really wants to be pressed.
 * 
 * @author <a href="http://paulgestwicki.blogspot.com">Paul Gestwicki</a>
 */
public class PressMePanel extends JPanel implements ActionListener {

    /**
     * Start the application.
     * 
     * @param args
     *            command-line arguments (ignored)
     */
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.getContentPane().add(new PressMePanel());
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    /** The uneditable text field into which we will put our output */
    private JTextField outputField;

    /**
     * Create an instance of this class.
     */
    public PressMePanel() {
        outputField = new JTextField(20);
        outputField.setEditable(false);

        JButton button = new JButton("Press me");
        button.addActionListener(this);

        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        add(button);
        add(outputField);
    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        outputField.setText("Thank you.");
    }

}


That's a little better, and if you followed the first, you can follow the second. Now, to the heart of the matter. While this works, I argue that it is not right. When we say that PressMePanel implements ActionListener, we are making a bold statement: we are saying that every PressMePanel instance is designed to listen for action events. For example, we could make another class that uses PressMePanel, like this:

import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

/**
 * A panel for text entry.
 * 
 * @author <a href="http://paulgestwicki.blogspot.com">Paul Gestwicki</a>
 */
public class TextEntryPanel extends JPanel {

    /**
     * Start the application.
     * 
     * @param args
     *            command-line arguments (ignored)
     */
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(new TextEntryPanel());
        frame.pack();
        frame.setVisible(true);
    }

    public TextEntryPanel() {
        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));

        PressMePanel pressMePanel = new PressMePanel();
        JTextField textField = new JTextField(10);
        textField.addActionListener(pressMePanel);

        add(textField);
        add(pressMePanel);
    }

}


That "works," in that when we press enter in the text field—which fires an ActionEvent—the message comes up in the PressMePanel. However, it doesn't really make sense. The interaction logic of PressMePanel is internal. It's simply not designed to be used in this way, but because it implemented ActionListener, this is perfectly legal. Defensive coding practice dictates that we should prevent this kind of abuse if we can. We get much better encapsulation if, instead of having PressMePanel implement ActionListener, it creates its own delegate listeners. One easy way to do this is to create inner classes to handle it:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

/**
 * A frame that holds a button which really wants to be pressed.
 * 
 * @author <a href="http://paulgestwicki.blogspot.com">Paul Gestwicki</a>
 */
public final class PressMePanel extends JPanel {

    /**
     * Start the application.
     * 
     * @param args
     *            command-line arguments (ignored)
     */
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.getContentPane().add(new PressMePanel());
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    /** The uneditable text field into which we will put our output */
    private JTextField outputField;

    /**
     * Create an instance of this class.
     */
    public PressMePanel() {
        outputField = new JTextField(20);
        outputField.setEditable(false);

        JButton button = new JButton("Press me");
        button.addActionListener(new MyButtonListener());

        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        add(button);
        add(outputField);
    }

    /**
     * Listens for action events, posting a message to the {@link #outputField}
     * when this happens.
     * 
     * @author <a href="http://paulgestwicki.blogspot.com">Paul Gestwicki</a>
     */
    private final class MyButtonListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            outputField.setText("Thank you.");
        }
    }

}


I've added a private inner class, MyButtonListener, which has one job: listen for action events and update the message in outputField when that happens. This is nicely encapsulated, and by making the class private, I'm not exporting it for potential abuse by other parts of the system. (Notice that I've also made both classes final. In the spirit of defensive programming, if I'm not designing for extension, I should prevent it.) There's another design improvement to be made. By defining the MyButtonListener as a class, I can now make as many instances of it as I want. Yet, my semantic model is that there is really only one, and it's attached to the button. Notice that this is implied by the naming of the class. Let's use anonymous inner classes instead:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

/**
 * A frame that holds a button which really wants to be pressed.
 * 
 * @author <a href="http://paulgestwicki.blogspot.com">Paul Gestwicki</a>
 */
public final class PressMePanel extends JPanel {

    /**
     * Start the application.
     * 
     * @param args
     *            command-line arguments (ignored)
     */
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.getContentPane().add(new PressMePanel());
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    /** The uneditable text field into which we will put our output */
    private JTextField outputField;

    /**
     * Create an instance of this class.
     */
    public PressMePanel() {
        outputField = new JTextField(20);
        outputField.setEditable(false);

        JButton button = new JButton("Press me");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                outputField.setText("Thank you.");
            }
        });

        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        add(button);
        add(outputField);
    }
}


Now, there is no doubt that this specific behavior is tied to the button. Of course, if I had a need to replicate this behavior, I could make a named class or an Action object, but we can cross that bridge when we get there. Better to solve the problem at hand than one that may or may not come up later. Moving to an anonymous inner class provides with another interesting refactoring opportunity. I like to have as few fields in my objects as I can. Now that the text field is only ever accessed or manipulated from the constructor, I can pull it into a local variable rather than an instance variable. The only piece of Java magic required for this is that we have to make the field final so that it can be read from the inner class:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

/**
 * A frame that holds a button which really wants to be pressed.
 * 
 * @author <a href="http://paulgestwicki.blogspot.com">Paul Gestwicki</a>
 */
public final class PressMePanel extends JPanel {

    /**
     * Start the application.
     * 
     * @param args
     *            command-line arguments (ignored)
     */
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.getContentPane().add(new PressMePanel());
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    /**
     * Create an instance of this class.
     */
    public PressMePanel() {
        final JTextField outputField = new JTextField(20);
        outputField.setEditable(false);

        JButton button = new JButton("Press me");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                outputField.setText("Thank you.");
            }
        });

        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        add(button);
        add(outputField);
    }
}


Nice and tidy, but more importantly, our PressMePanel is well-encapsulated.

Now, textbook and tutorial authors, you can stop making every class under the sun implement listener interfaces.

You're welcome.