view issue

Fun and Games: Multi-Language Development
Download PDF version of this article

by Andrew M. Phelps, David M. Parks | February 24, 2004

Topic: Game Development

  • View Comments
  • Print

Fun and Games with Multi-Language Development


ANDREW M. PHELPS, ROCHESTER INSTITUTE OF TECHNOLOGYDAVID M. PARKS, ROCHESTER INSTITUTE OF TECHNOLOGY

Game development can teach us much about the common practice of combining multiple languages in a single project.

Computer games (or “electronic games” if you encompass those games played on console-class hardware) comprise one of the fastest-growing application markets in the world. Within the development community that creates these entertaining marvels, multi-language development is becoming more commonplace as games become more and more complex. Today, asking a development team to construct a database-enabled Web site with the requirement that it be written entirely in C++ would earn scornful looks and rolled eyes, but not long ago the idea that multiple languages were needed to accomplish a given task was scoffed at.

It is taken for granted now that Web projects will use several different languages, but applications in other areas are less likely to adopt such an approach. Enter the behemoth of the gaming industry, of software projects that take years to develop and are some of the most complicated things on the planet. What can we learn from this industry and how game developers create these technological marvels? Do the lessons of these developers apply to the rest of us?

THE IMPORTANCE OF MULTI–LANGUAGE DEVELOPMENT

Until a few years ago, nearly all games were written entirely in native code, if not assembly language, and the idea of adding portions of the game through interpreted code or by linking to a virtual machine was unheard of. This was done for reasons of “performance”—games are on the bleeding edge of creating software that performs under pressure. Trying to crank out a believable world with AI (artificial intelligence), input from several devices, 3D graphics, and surround sound in realtime is nontrivial. Electronic entertainment is in fact the application space that is driving the market in terms of end-user hardware advancement, constantly pushing the envelope for better picture, louder sound, and faster calculation. It is no surprise, given the “new feature glitz factor” (the element in gaming culture that seems to demand that all games support the latest and greatest technological fad), that games are typically written entirely in C/C++. If developers want to access the latest features of the latest hardware, they have very few options.

With the recent advancements in processing power and computing capability on the desktop, it is now possible to execute the logic and “upper layers” of a complex application almost as fast in interpreted code as is possible in native languages. Some languages are better than others at various things, or for certain types of authors. Recently, a number of games have used “dirty Java” techniques that link Java to a native engine through JNI (Java Native Interface).1 Vampire: The Masquerade—Redemption (Nihilistic Software, 2000) used JDK 1.1 as its scripting engine with great success.2, 3 Java also contains a wonderfully well-written networking API (application programming interface) for communication using TCP/IP: One possible use of “dirty Java” would be a multi-user game engine handling all of the net code through the Java language, but rendering graphics using native code. The bottleneck in this case is the network itself; using Java byte code is a trivial cost in terms of execution speed, but a huge savings in development time and ease of construction.

The games community has embraced the trend of multi-language development and undergone what could almost be described as a revolution in the past few years. Gone are the days of hardcore assembly number crunching and small teams of developers throwing out thousands of lines of C-header files. Instead, the gaming community is using several languages large and small, some off-the-shelf and some of their own design, for a variety of purposes. The fundamental tenet of when to use what is now a choice based on developer audience and specific capability—as opposed to raw performance power.

ANATOMY OF A GAME ENGINE

To understand how the games industry is thinking about languages and their uses, it is helpful to understand exactly what is being built. Languages are, after all, tools with which to build things, and the particular language or set of languages should be based upon the desired functionality of the engine being constructed. Figure 1 represents a modern game engine with regard to its functional flow, at a very high level. This represents the simplest of all game engines and would be suitable, perhaps, for a simple shooter game or basic RPG (role-playing game). Note that this assumes a simple single-threaded model and thus does not take advantage of several modern practices in game design, nor does it make any effort to synchronize the game across a number of players, either in a LAN or Internet-based networking model.

Right away, it is easy to see that game engines are responsible for much more than the graphics seen on the screen, even though graphics are still stereotyped as the primary focus of a game. In point of fact, the engine is responsible for a number of tasks, from gathering input, loading and unloading files, AI, and path planning to playing music, sound, and video in conjunction with the traditional graphical responsibilities. Games are some of the most complex applications being built today, the only difference being that their purpose is for entertainment instead of productivity.

Before looking carefully at which languages fit together to form the game engine just described, we should note that within the graphical core of the game, native code still reigns supreme. This is because speed is still intensely critical, and it is not uncommon to see elements of the rendering pipeline written in C or assembly for the express purpose of optimization. As more of this work is being offloaded to the graphics processor units (GPUs) available in modern hardware, more and more processing power on the CPU is available for the rest of the engine. Recently, the amount of processor time given to AI and physics has radically increased, also as a direct result of graphics being able to offload some of the work.

SCRIPTING

One of the primary uses of non-native code is “scripting.” This refers, in gaming terms, to the idea of a control layer that sits atop the belly of the engine. Characters are controlled by AI scripts; inventories are tracked by logic and database scripts; maps are created for levels using level-editing scripts; and so forth. In the AI example, a number of interesting requirements are visible that would argue for the use of a second “lightweight” language with interpreted or JIT (just-in-time) compilation capability.

In a general-purpose game engine, no specific behavior is described until runtime other than the behavior of the core engine itself—that is, the game logic, game entities, and so forth are all defined by some set of pluggable modules that the core engine loads and processes in a generic way. The core includes the bulk of the graphics engine, the core infrastructure, and a module management system. In treating each entity as its own module, the core would be responsible for loading and processing entities according to some interface.

This presents some challenges. The first is that the script controlling the entity will change hundreds, if not thousands, of times as the game is turned into its final form. Using a language or build process that requires the source to be recompiled on every change can lead only to a loss of development time. Also, AI algorithms tend to be largely recursive and generally object-based. Classical algorithms in this field frequently use self-modifying behavior. Languages that support these capabilities are good choices for this particular area, provided that they can easily pass control data back to the core of the engine. Many game houses choose to implement their own languages with a very “C-like” syntax for this kind of work (a la QuakeC, the custom version of C used in the core of id Software’s Quake series of games). It is also common that the custom language runs in an interpreted framework.4 In addition to custom language development, other popular choices are Java, Lua, Python, Ruby, and Lisp.5, 6 Python in particular has been used in a number of recent projects including Toontown (Disney Interactive, 2003), Eve Online (CCP, 2003), Blade of Darkness (Codemasters, 2001), Star Trek Bridge Commander (Totally Games, 2002), and Earth and Beyond (Electronic Arts, 2002).7, 8 Any of these can be made to communicate with a C/C++ engine, and they offer a way to quickly develop and rework the behavior of an entity within the game without overhauling the entire engine.

AUDIENCE

The second primary reason that game developers use non-native code is that games are created by several kinds of people, not just the core programming team. The number of people needed to create a commercial game is on the rise and can involve tens, if not hundreds, of individuals with varying backgrounds—from computer science to art and design. It is costly and generally unsound to require your programming team to implement all of the AI requirements for a given game, not only because of salary issues, but also because they are not the game or level designers and may not know that “King Jeoff the Great” is supposed to run from “Harry the Evil Warlord” on sight. As games take shape and the number of details increase astronomically, entire development teams are devoted to scripting particular behaviors for different entities, so placing tools that are easy to use and languages that are forgiving in the hands of these professionals is critical. The likelihood that they are all experienced with native-code development is slim.

Another area in which simple scripting is greatly desired is in art and design teams. Several 3D tool suites now feature small scripting languages to make the tools easier to use—for example, Maya uses the Maya Embedded Language (MEL), 3D-Studio Max uses MAXScript, and Houdini uses VEX. Each of these languages has the same goal: to empower the artist by providing the ability to access the features of the software through code. Artists, however, are generally not software engineers, nor should they have to be. Using a simple, quick scripting language allows them several advantages in producing game data, but that data then needs to be accessible to the game core.9 Several game houses use plug-in or snap-in architecture to access content from 3D tools, and they often wind up creating their own level-creation tools with their own scripting languages built in.

COMMON PROBLEMS

Given that multi-language development is desirable in terms of modularity and specific functionality, what then are the pitfalls of using this approach? Unfortunately, they are many, and they are often difficult to find and plan for until encountered. This section will briefly describe generic issues, with additional details and workarounds presented in the case study that follows.

Lack of Documentation. Few resources exist for making multiple languages behave together, and for debugging across them. Some popular tools allow you to debug across languages (Visual Studio, CodeWarrior, etc.), whereas others are significantly less integrated. In almost all cases, documentation is available that demonstrates simple, nonthreaded examples that pass various basic data types to or from another language. Unfortunately, the number of resources available on advanced practices such as object sharing, type casting, thread-locking, and so forth seem to be few. In our own work, we repeatedly went back and forth across the same set of JNI documentation to gain the understanding needed to implement the system, as we were unable to uncover a set of real-world examples. This is a problem not only with JNI (which is in fact one of the best-documented native code interfaces available), but it is a problem in general with multi-language development. We can only hope that as this practice becomes more widespread, this issue will be solved through the introduction of more materials and case studies.

Memory Management. As difficult as memory management usually is to envision conceptually, it is a nightmare in multi-language development. This is partly because it is possible to have references to a given pointer on “both sides of the fence,” meaning from two areas of the software written in different languages. In such an instance, one of two very awful things can happen: The first is that the memory is never reclaimed because there is always a reference to it on one side or the other, producing a memory leak; the second is that the reference on one side or the other is ignored and the memory is reclaimed, in which case a read from the remaining reference will fault. Neither of these is desirable, but both are fairly common.

Coupled with this mess is the fact that most of the languages described thus far use built-in garbage collection schemes instead of forcing programmers to explicitly manage memory themselves. This is certainly true of Java and is largely true of most interpreted scripting languages as well. That being the case, it is exceedingly difficult to know precisely when something is cleared from memory. Code structures that check for the existence of an entity and then take action on its existence should be explicitly avoided: The entity may still exist but may be passed out of scope. A pointer accessing values from native code will have absolutely no ability to determine if the data it is reading is on the list to be collected.

An alternative is to use state variables that are easily accessible and never reclaimed (but often reused). In situations where such structures cannot be avoided, it is necessary to take control of the garbage collection mechanism. Note that this control is still not usually absolute (the system.gc() method in JNI, for example, is not foolproof; there is still variability in precisely when and how objects are destroyed and cleared).10 JNI provides mechanisms for native code to create global references to objects, thus protecting them from being garbage collected, but does not provide a way to force an object to be collected. This is a significant risk to consider when choosing a language.

Threading. With most scripting languages, the scripted code can be thought of as an extension of the native code that calls it and can thus be treated as though it is executing from the same thread as the native code. With languages that rely on virtual machines to execute, however, native threads must somehow synchronize themselves with non-native threads. In addition, references to an object that are valid in one thread may not be valid in another. It is possible, however, to have two native threads using the same virtual machine, and non-native threads can be spawned by non-native code transparently to native code. It is easy to see how the “dirty Java” style of programming would be useful in developing network applications, especially when you consider the synchronization capabilities already built into the language.

In designing a general-purpose game engine model, you can then create update and render methods that are synchronized with one another, making scheduling between separate simulation and rendering threads nearly effortless. In this situation, since the rendering cycle is hardware dependent, it is a good idea to start a non-native thread that handles simulation, and explicitly call render methods on objects directly from the graphics thread. Of course, the render methods are largely native methods, but synchronizing the native code on each side of the fence is not necessary, because the non-native language is already synchronizing itself.

Another consideration is cross-platform capability. Windows threading techniques are vastly different from Linux and OS X when using native languages, but almost identical in Java. If your application relies on several threads and must be ported to many platforms, designing the project to use Java to control threads can result in code that differs very slightly from one platform to the next.

Performance. Performance issues are almost simplistic in the sense that it is easy to deduce the cause, but not as easy to come up with reliable solutions. The basic reason for performance hits in multi-language development is the cost of moving things “across the bridge” from one language to another. Calling a native method from Java, for example, is more expensive than calling a normal one.11 This is generally true of all language integration and is exacerbated by interpreted languages that perform more slowly than those that produce native code or use JIT strategies. The solution is to play very detailed games about what to put on which side of the bridge. Although the first inclination may be to put as much as possible on the native end, this in fact generally winds up not being the optimal solution, because the number of calls to the native elements is increased. In the end, an architecture that minimizes the calls from language to language is the most desirable and will perform better than one that is heavily skewed in one direction or another.

For simulation, this means having all update cycles on non-native entities managed by an autonomous non-native entity. In general, it is trivial to create a system where objects are never referenced directly by native code, and non-native objects reference native code only for complex algorithms such as collision detection and pathfinding during their simulation cycles. For graphics, this means having a single point of entry into native code for rendering complex objects such as player models and special effects. It is generally a performance drain to create a non-native wrapper around a native graphics library that does not incorporate this single-entry model.

MUPPETS: A CASE STUDY

To present a more detailed view of some of the problems just described, we present a system that we have worked on for the past two years, entitled MUPPETS: Multi-user Programming Pedagogy for Enhancing Traditional Study.12

We have built upon existing research and technical developments in the field to design and construct a CVE (collaborative virtual environment) and supporting infrastructure that allows students, researchers, and game developers to write simple Java code to control and extend the environment. As part of the MUPPETS system, this code can control objects in a shared virtual world very much like a modern MMOG (massively multiplayer online game). A simple world created by student teams is presented in figure 2.

This system is designed to use a C/C++ core for rendering graphical objects and avatars that users create in a Java programming environment. The idea of creating an object in MUPPETS is both programmatic and visual: While an object can technically exist as mere memory space, more often than not it exists as a MuppetsObject that references some piece of geometry, either a primitive or a custom model. These objects are thus pieces of Java software that are represented graphically in the virtual world. The interface is described as a Java interface, and all objects must implement this interface so the client can interpret them properly. The client does not verify implementation of this interface, but if any exceptions are thrown while interpreting an object, the stack trace of the exception is dumped to the console (and, therefore, the console log file), and the object is removed from the world.

The MUPPETS system contains an IDE (integrated development environment) for developing these objects through the Java language, but the IDE is integrated directly into the world and is available anytime, anywhere: The IDE and the world are one and the same. This means that, from within the client, the user can build, compile, instantiate, revise, and reinstantiate the objects without having to exit the world and without stopping the execution of the native core. A view of the IDE is provided in figure 3.

From the user’s perspective, using the MUPPETS system requires no knowledge of the underlying graphics system or C/C++. Instead, any capable Java programmer can create objects that are represented in the three-dimensional world as graphical entities complete with behavior and per-frame operations. The code for a simple box that changes its color is presented in figure 4.

FIGURE 4
Source Code Listing of a MUPPETS ColorCube

/* Color Cube Class – creates a cube that animates color over time*/
import java.util.Random;
import java.lang.Math;
public class ColorCube extends MuppetsObject {
private float clock; //clock to increment
private float[] color; //3-float color
//constructor
public ColorCube() {
Random rand;
rand = new Random();
color = new float[3];
clock = rand.nextFloat() * 6.284f;
setPrimitive(CUBE); //set primitive call using pre-def constant
}

//overwrite update method for custom animation
public void update(float dt) {
//increment clock
clock += dt;

//create new color
color[0] = ((float) Math.sin(clock) + 1) / 2.0f;
color[1] = ((float) Math.cos(clock) + 1) / 2.0f;
color[2] = ((float) Math.sin(clock) *
(float) Math.cos(clock) + 1) / 2.0f;

//set the color of the cube
setColor(color[0], color[1], color[2]);

}
}

 

As far as the user is concerned, this is all that is needed. The cube appears after it is compiled from within the environment and begins to animate its visible color. Any Java object that extends MuppetsObject instantly knows how to draw a 3D representation of itself in the world, and has several states and variables for animation, rendering, and the like. A great deal of further complexity is hidden from the user. MUPPETS exists as a networked virtual world; all objects are shared across several clients the moment they are “published,” allowing students to see and experience the creation of others. Needless to say, it handles all of the networking in Java because of the rich libraries found there, safely hidden from the end user’s viewpoint. (The system places no restrictions on access to any portion of the Java language so users could in fact write their own net code as desired; it just wouldn’t be integrated into the native core.)

Trickier still, since multiple versions of the same class can exist in the world at the same time, each object must be loaded via a unique ClassLoader. Underneath the hood, the client creates an instance of a MUPPETS-specific ClassLoader that holds the System ClassLoader as its parent. The System ClassLoader is set up to be aware of only the core MUPPETS classes (the MUPPETS interface, MuppetsObject, Avatar, MuppetsGL), whereas the MUPPETS-specific ClassLoader is aware of user-created classes. This poses a few restrictions on MuppetsObjects:

• First, if one object wants to interact with another, it must do so through one of the core class interfaces. In fact, if one instantiates two objects of type ColorCube and one ColorCube obtains a reference “b” to the other one, then “b instanceof ColorCube” will return false because they were loaded with separate ClassLoaders. This applies only to objects that are instantiated by the client directly; any child classes instantiated by an object will exist under the same ClassLoader and act as a single, contained, Java-class hierarchy. This obstacle can be overcome by placing all unchanging interfaces and super classes where the System ClassLoader can find them. Keep in mind that all class names in the System class scope must be unique, and user-created objects must not conflict with these names.

• Second, it is impossible to have a truly static state across all instances of a MuppetsObject. Since static state is maintained at a class level, loading under separate ClassLoaders creates a separate copy of said state for every ClassLoader used. Again, this applies only to objects instantiated directly by the client. If an object itself instantiates child objects, those objects will maintain static state exactly as they would in a single ClassLoader environment, as all the objects in question were loaded using one ClassLoader.

• Finally, objects may not assume that another object with the same class name is the same class as the current object—that is, two users may implement their own versions of a ColorCube class; one version may obtain a reference (b) to the other, and while “b instanceof ColorCube” will return false, b.getClass().getName().equals(“ColorCube”) will return true. Attempting to type cast b to ColorCube will throw a ClassCastException. All of this becomes apparent when looking at the overall mechanism that MUPPETS uses to organize its use of JNI, shown in figures 5 and 6.

Figure 6 outlines the relationship between JNI and MUPPETS. A JavaController acts as a mediator between JVM (Java Virtual Machine) and the MUPPETS client. The JavaController controls when MuppetsObjects are rendered and updated. Hardware-specific rendering techniques are defined in Renderer and MuppetsGL.dll. The client accesses these routines through the Renderer class, and MuppetsObjects themselves gain access to hardware calls through MuppetsGL. Additional native libraries can be used and given Java interfaces as a plug-in system. A plug-in of this type exists that lets users load, animate, and render MD3 models using only three method calls. There is no noticeable loss in performance when rendering models this way rather than rendering them using pure native code.

MUPPETS is an example of a C/C++ program that uses Java. We needed the added control over JVM that the invocation interface provides and thus treats each game entity as more of an application than an object. The core systems try to provide these applications with as much information and power as possible while maintaining a decent level of security. For example, we created Java interfaces to OpenGL and DirectInput. One of the problems that we encountered was providing the necessary state to the Java library, as the native library loaded by the Java library is loaded outside of the scope of our main application runtime linker. To solve this problem, MUPPETS statically links identical classes into both the core and the native library accessed by Java. To provide both Java objects and C/C++ objects with access to the same DirectInput devices, MUPPETS creates an instance of the DirectInput handler in the native core and then passes a pointer to it through Java to the native library as an array of four bytes (a 32-bit pointer). In this way, it can provide access to any state that needs to be shared between Java and C/C++, solving one of the issues described previously in terms of memory management. Without such a scheme, the state would be inaccessible or, worse, stored in several places independently of each other.

The final division between native and Java code can be seen in looking at the entire object framework for the MUPPETS system, which uses the JavaController, as shown in figure 7. This diagram illustrates the division between the logic layers at the client end of the MUPPETS system and the rendering core, with the JavaController managing the interaction of the core with all of the client-created objects. Creating a manager to encapsulate this type of behavior is, in our opinion, critical. Otherwise, the mess is simply too great, the number of things that can go wrong too untraceable, and the chances of success greatly diminished.

The MUPPETS system is still in development, and one of the primary changes occurring in the system now is moving more and more of the logic of the application to the Java layer. Collision detection, for example, now exists on a per-object basis at the user level. This is because, while C++ can certainly execute the algorithms for such detection faster, the number of calls needed across JNI for a relatively cluttered scene was a performance drain compared with simply executing the algorithms in Java. Now the system provides a mechanism for quickly querying the native-world geometry system for geometry that intersects with an axis-aligned bounding box in a single native call. After a reference to the geometry is passed into the virtual machine, more detailed routines are run on it as defined by the object code itself. Several other things are now moving to “the Java side,” leaving what is essentially a rendering core and a JNI management system at the base of the engine.

LEADING THE PACK

In the end, the question remains as to the validity of the multi-language approach. Certainly, development takes longer and is, for lack of a better term, “stickier” than single-language approaches. Despite this, using multiple languages, and in particular interpreted languages or JIT-capable environments, allows the design and tuning phases of engine development to go much smoother. Game developers are leading the pack in using multi-language development on large-scale performance-driven applications. The realtime nature of games and the features-obsessed culture of their audience leaves little room for error and presents one of the most demanding environments in which to develop. We are convinced that several best practices for multi-language development are being born within the halls of game development houses at this very moment—and that they are creating a need for better tools and better documentation, a need from which we will all benefit.

ACKNOWLEDGMENTS

The authors would like to thank the Rochester Institute of Technology for its continued support, and especially the Provost’s Learning Initiative Grants program that funded the start of this project. Special thanks also to Sun Microsystems for its support through its matching grants program. The usual thanks to the entire student development team involved in the MUPPETS project is in order; your continued time and involvement is making this project the success that it is. Special thanks to Assistant Professor Kevin Bierre, whose involvement with the database and networking portions of the system have been invaluable. Finally, thank you to Eydie Lawson, former chair of information technology and current associate dean of GCCIS for believing in this system when it was laid out on a whiteboard several years ago. For more information and to contact the development team, go to http://muppets.rit.edu.

REFERENCES

1. Kreimeier, B. Dirty Java: Using the Java Native Interface within Games. Game Developer Magazine (July 1999); http://www.gamasutra.com/features/ 19990611/java_01.htm.

2. Marner, J. Evaluating Java for Game Development. Department of Computer Science, University of Copenhagen, Denmark, March 4, 2002; http://www.rolemaker.dk/articles/ evaljava/Evaluating Java for Game Development.pdf.

3. Huebner, R. Postmortem of Nihilistic Software’s Vampire: The Masquerade—Redemption. Game Developer Magazine (July 2000); http://www.gamasutra.com/features/20000802/huebner_01.htm.

4. LaMothe, A. Tricks of the Windows Game Programming Gurus, 2nd Edition. Sams Publishing, Indianapolis: IN, 2002.

5. Varanese, A. Game Scripting Mastery (Premier Press Game Development Series). Ed. LaMothe, A. Premier Press, Cincinnati: OH, 2002.

6. Dalmau, D. S-C. Core Techniques and Algorithms in Game Programming. New Riders Publishing, Indianapolis: IN, 2003.

7. Dawson, B. Game scripting in Python. Game Developers Conference Proceedings (2002); http://www.gamasutra.com/features/ 20020821/dawson_pfv.htm.

8. Riley, S. Game Programming with Python (Game Development Series). Charles River Media, Hingham: MA, 2003.

9. Reed, R. G. A framework for rapid 3D level design using MAXScript code generation. In Graphics Programming Methods, ed. J. Lander, 211–226. Charles River Media, Hingham: MA, 2003.

10. Mulchandani, D. Java for Embedded Systems. IEEE Internet Computing 2, 3 (May-June, 1998), 30-39; http://java.sun.com/products/personaljava/w3mulc.pdf.

11. Murray, P., Smith, T., Srinivas, S., and Jacob, M. Performance issues for multi-language Java applications. International Workshop on Java for Parallel and Distributed Computing (2000); http://ipdps.eece.unm.edu/2000/java/18000545.pdf.

12. Phelps, A., Bierre, K., and Parks, D. MUPPETS: Multi-User Programming Pedagogy for Enhancing Traditional Study. Proceedings of ACM Conference on Information Technology Education (2003), 100–105; http://delivery.acm.org/10.1145/950000/947143/p100-phelps.pdf?key1=947143&key2=7829449601&coll=portal&dl=ACM&CFID=14345170&CFTOKEN=65821319.

ANDREW M. PHELPS is an assistant professor at the Rochester Institute of Technology, in Rochester, NY. He is the founding faculty member of the game programming concentration within the department of information technology, and his work in games programming education has been featured in the New York Times, CNN.com, USA Today, National Public Radio, IEEE Computer, and several other articles and periodicals. He regularly publishes work exploring Web-based game engines at the Director Online User’s Group (DOUG) and the Macromedia DevNet Center. He is at work on his first text with Prentice Hall. He maintains a Web site at http://andysgi.rit.edu featuring his work as an educator, artist, programmer, and game addict. He teaches courses in multimedia programming, game engine development, 2D and 3D graphics, and information technology theory.

DAVID M. PARKS is an undergraduate student in information technology, specializing in graphics and game programming, at the Rochester Institute of Technology. He has written several graphics engines and supporting libraries and has served as the lead developer on the MUPPETS system while completing coursework in games, graphics, multimedia, and software design. He is also the standing graphics guru at the Entertainment Technology Lab, where he is a tutor in the areas of graphics and games development. He maintains a Web site of his work at http://www.rit.edu/~dmp9199/.

 

acmqueue

Originally published in Queue vol. 1, no. 10
see this item in the ACM Digital Library

Back to top

s
  • DAVID M. PARKS is an undergraduate student in information technology, specializing in graphics and game programming, at the Rochester Institute of Technology. He has written several graphics engines and supporting libraries and has served as the lead developer on the MUPPETS system while completing coursework in games, graphics, multimedia, and software design. He is also the standing graphics guru at the Entertainment Technology Lab, where he is a tutor in the areas of graphics and games development. He maintains a Web site of his work at http://www.rit.edu/~dmp9199/.

    For additional information see the ACM Digital Library Author Page for: David M. Parks
     
  • ANDREW M. PHELPS is an assistant professor at the Rochester Institute of Technology, in Rochester, NY. He is the founding faculty member of the game programming concentration within the department of information technology, and his work in games programming education has been featured in the New York Times, CNN.com, USA Today, National Public Radio, IEEE Computer, and several other articles and periodicals. He regularly publishes work exploring Web-based game engines at the Director Online User's Group (DOUG) and the Macromedia DevNet Center. He is at work on his first text with Prentice Hall. He maintains a Web site at http://andysgi.rit.edu featuring his work as an educator, artist, programmer, and game addict. He teaches courses in multimedia programming, game engine development, 2D and 3D graphics, and information technology theory.

    For additional information see the ACM Digital Library Author Page for: Andrew M. Phelps
     

Comments

Leave this field empty

Post a Comment:

(Required)
(Required)
(Required - 4,000 character limit - HTML syntax is not allowed and will be removed)