Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save frainfreeze/06834c755931da264b27 to your computer and use it in GitHub Desktop.
Save frainfreeze/06834c755931da264b27 to your computer and use it in GitHub Desktop.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<script type="text/javascript" src="/static/js/analytics.js"></script>
<script type="text/javascript">archive_analytics.values.server_name="wwwb-app13.us.archive.org";archive_analytics.values.server_ms=151;</script>
<link type="text/css" rel="stylesheet" href="/static/css/banner-styles.css"/>
<title>Panda3D</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<!-- BEGIN WAYBACK TOOLBAR INSERT -->
<script type="text/javascript" src="/static/js/disclaim-element.js" ></script>
<script type="text/javascript" src="/static/js/graph-calc.js" ></script>
<script type="text/javascript" src="/static/jflot/jquery.min.js" ></script>
<script type="text/javascript">//<![CDATA[
var __wm = (function(){
var wbPrefix = "/web/";
var wbCurrentUrl = "http://www.python.org/pycon/dc2004/papers/29/";
var firstYear = 1996;
var imgWidth = 500,imgHeight = 27;
var yearImgWidth = 25,monthImgWidth = 2;
var displayDay = "1";
var displayMonth = "ožu";
var displayYear = "2007";
var prettyMonths = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
var $D=document,$=function(n){return document.getElementById(n)};
var trackerVal,curYear = -1,curMonth = -1;
var yearTracker,monthTracker;
function showTrackers(val) {
if (val===trackerVal) return;
var $ipp=$("wm-ipp");
var $y=$("displayYearEl"),$m=$("displayMonthEl"),$d=$("displayDayEl");
if (val) {
$ipp.className="hi";
} else {
$ipp.className="";
$y.innerHTML=displayYear;$m.innerHTML=displayMonth;$d.innerHTML=displayDay;
}
yearTracker.style.display=val?"inline":"none";
monthTracker.style.display=val?"inline":"none";
trackerVal = val;
}
function getElementX2(obj) {
var $e=jQuery(obj);
return (typeof $e=="undefined"||typeof $e.offset=="undefined")?
getElementX(obj):Math.round($e.offset().left);
}
function trackMouseMove(event,element) {
var eventX = getEventX(event);
var elementX = getElementX2(element);
var xOff = Math.min(Math.max(0, eventX - elementX),imgWidth);
var monthOff = xOff % yearImgWidth;
var year = Math.floor(xOff / yearImgWidth);
var monthOfYear = Math.min(11,Math.floor(monthOff / monthImgWidth));
// 1 extra border pixel at the left edge of the year:
var month = (year * 12) + monthOfYear;
var day = monthOff % 2==1?15:1;
var dateString = zeroPad(year + firstYear) + zeroPad(monthOfYear+1,2) +
zeroPad(day,2) + "000000";
$("displayYearEl").innerHTML=year+firstYear;
$("displayMonthEl").innerHTML=prettyMonths[monthOfYear];
// looks too jarring when it changes..
//$("displayDayEl").innerHTML=zeroPad(day,2);
var url = wbPrefix + dateString + '/' + wbCurrentUrl;
$("wm-graph-anchor").href=url;
if(curYear != year) {
var yrOff = year * yearImgWidth;
yearTracker.style.left = yrOff + "px";
curYear = year;
}
if(curMonth != month) {
var mtOff = year + (month * monthImgWidth) + 1;
monthTracker.style.left = mtOff + "px";
curMonth = month;
}
}
function hideToolbar() {
$("wm-ipp").style.display="none";
}
function bootstrap() {
var $spk=$("wm-ipp-sparkline");
yearTracker=$D.createElement('div');
yearTracker.className='yt';
with(yearTracker.style){
display='none';width=yearImgWidth+"px";height=imgHeight+"px";
}
monthTracker=$D.createElement('div');
monthTracker.className='mt';
with(monthTracker.style){
display='none';width=monthImgWidth+"px";height=imgHeight+"px";
}
$spk.appendChild(yearTracker);
$spk.appendChild(monthTracker);
var $ipp=$("wm-ipp");
$ipp&&disclaimElement($ipp);
}
return{st:showTrackers,mv:trackMouseMove,h:hideToolbar,bt:bootstrap};
})();//]]>
</script>
<style type="text/css">
body {
margin-top:0 !important;
padding-top:0 !important;
min-width:800px !important;
}
</style>
<div id="wm-ipp" lang="en" style="display:none;">
<div style="position:fixed;left:0;top:0;width:100%!important">
<div id="wm-ipp-inside">
<table style="width:100%;"><tbody><tr>
<td id="wm-logo">
<a href="/web/" title="Wayback Machine home page"><img src="/static/images/toolbar/wayback-toolbar-logo.png" alt="Wayback Machine" width="110" height="39" border="0" /></a>
</td>
<td class="c">
<table style="margin:0 auto;"><tbody><tr>
<td class="u" colspan="2">
<form target="_top" method="get" action="/web/form-submit.jsp" name="wmtb" id="wmtb"><input type="text" name="url" id="wmtbURL" value="http://www.python.org/pycon/dc2004/papers/29/" style="width:400px;" onfocus="this.focus();this.select();" /><input type="hidden" name="type" value="replay" /><input type="hidden" name="date" value="20070301060938" /><input type="submit" value="Go" /><span id="wm_tb_options" style="display:block;"></span></form>
</td>
<td class="n" rowspan="2">
<table><tbody>
<!-- NEXT/PREV MONTH NAV AND MONTH INDICATOR -->
<tr class="m">
<td class="b" nowrap="nowrap">
<a href="/web/20061221154254/http://www.python.org/pycon/dc2004/papers/29/" title="21 pro 2006">PRO</a>
</td>
<td class="c" id="displayMonthEl" title="You are here: 6:09:38 ožu 1, 2007">OŽU</td>
<td class="f" nowrap="nowrap">
<a href="/web/20070412145038/http://python.org/pycon/dc2004/papers/29/" title="12 tra 2007"><strong>TRA</strong></a>
</td>
</tr>
<!-- NEXT/PREV CAPTURE NAV AND DAY OF MONTH INDICATOR -->
<tr class="d">
<td class="b" nowrap="nowrap">
<a href="/web/20061221154254/http://www.python.org/pycon/dc2004/papers/29/" title="15:42:54 pro 21, 2006"><img src="/static/images/toolbar/wm_tb_prv_on.png" alt="Previous capture" width="14" height="16" border="0" /></a>
</td>
<td class="c" id="displayDayEl" style="width:34px;font-size:24px;" title="You are here: 6:09:38 ožu 1, 2007">1</td>
<td class="f" nowrap="nowrap">
<a href="/web/20070412145038/http://python.org/pycon/dc2004/papers/29/" title="14:50:38 tra 12, 2007"><img src="/static/images/toolbar/wm_tb_nxt_on.png" alt="Next capture" width="14" height="16" border="0" /></a>
</td>
</tr>
<!-- NEXT/PREV YEAR NAV AND YEAR INDICATOR -->
<tr class="y">
<td class="b" nowrap="nowrap">
<a href="/web/20050909231821/http://www.python.org/pycon/dc2004/papers/29/" title="9 ruj 2005"><strong>2005</strong></a>
</td>
<td class="c" id="displayYearEl" title="You are here: 6:09:38 ožu 1, 2007">2007</td>
<td class="f" nowrap="nowrap">
2008
</td>
</tr>
</tbody></table>
</td>
</tr>
<tr>
<td class="s">
<a class="t" href="/web/20070301060938*/http://www.python.org/pycon/dc2004/papers/29/" title="See a list of every capture for this URL">34 captures</a>
<div class="r" title="Timespan for captures of this URL">16 tra 04 - 23 pro 07</div>
</td>
<td class="k">
<a href="" id="wm-graph-anchor">
<div id="wm-ipp-sparkline" title="Explore captures for this URL">
<img id="sparklineImgId" alt="sparklines"
onmouseover="__wm.st(1)" onmouseout="__wm.st(0)"
onmousemove="__wm.mv(event,this)"
width="500"
height="27"
border="0"
src="/web/jsp/graph.jsp?graphdata=500_27_1996:-1:000000000000_1997:-1:000000000000_1998:-1:000000000000_1999:-1:000000000000_2000:-1:000000000000_2001:-1:000000000000_2002:-1:000000000000_2003:-1:000000000000_2004:-1:000101010101_2005:-1:020100002000_2006:-1:000001201232_2007:2:001111112212_2008:-1:000000000000_2009:-1:000000000000_2010:-1:000000000000_2011:-1:000000000000_2012:-1:000000000000_2013:-1:000000000000_2014:-1:000000000000_2015:-1:000000000000" />
</div>
</a>
</td>
</tr></tbody></table>
</td>
<td class="r">
<a href="#close" onclick="__wm.h();return false;" style="background-image:url(/static/images/toolbar/wm_tb_close.png);top:5px;" title="Close the toolbar">Close</a>
<a href="http://faq.web.archive.org/" style="background-image:url(/static/images/toolbar/wm_tb_help.png);bottom:5px;" title="Get some help using the Wayback Machine">Help</a>
</td>
</tr></tbody></table>
</div>
</div>
</div>
<script type="text/javascript">__wm.bt();</script>
<!-- END WAYBACK TOOLBAR INSERT -->
<div align="center"><strong>The Panda3D Engine - Python Scripting for Game and
Simulation Development </strong> </div>
<p><strong>Acknowledgements:</strong></p>
<p>Walt Disney Internet Group- VR Studio<br>
Mike Goslin<br>
David Rose <br>
Joe Shochet</p>
<p>Entertainment Technology Center, Carnegie Mellon University<br>
Jesse Schell <br>
Yi Hong Lin<br>
Shana Markham<br>
Jason Pratt<br>
Shalin Shodhan <br>
Joshua Taylor</p>
<p></p>
<p><strong>Abstract:</strong></p>
<p>Panda3D, or Platform Agnostic Networked Display Architecture, is a powerful
rendering engine for SGI, Linux, Sun, and Windows. It was originally developed
by the Walt Disney Imagineering VR Studio and has been used for their massively
multiplayer online game Toontown Online. It has since been generously made available
to the open source community. The core of the engine is in C++. Panda3D/DIRECT
provides a Python scripting interface and utility code.</p>
<p>In this paper, we present an overview of Panda3D technology for developing
real time interactive games and VR experiences using Python scripting. We also
delineate the various tools and features of the engine and describe some notable
projects based in Panda3D as case studies. In conclusion, we discuss plans for
the future development of Panda3D.</p>
<p><br>
<strong>Contents:</strong></p>
<p>1) Introduction<br>
2) Panda3D Technology<br>
3) Panda and Python<br>
4) Case Studies<br>
5) Future Plans</p>
<p><br>
<strong>1) Introduction:</strong></p>
<p>Panda3D was originally developed at the Disney VR Studio. The VR Studio used
a proprietary IRIX-specific system called DWD (Disney's World Designer) to create
several DisneyQuest Virtual Reality Attractions, such as &quot;Aladdin's Magic
Carpet VR Adventure,&quot; &quot;Hercules in the Underworld,&quot; and &quot;Pirates
of the Caribbean: Battle for the Buccaneer Gold,&quot; between 1997 and 2000.
In 2000, the VR Studio embarked on the Toontown Online project, and decided
to build a new engine that contained many of the DWD design principles, but
would be more modular. This would let it be ported to more platforms and more
easily changed over time. The new engine was dubbed &quot;Panda3D,&quot; ostensibly
standing for &quot;Platform Agnostic Networked Display Architecture.&quot;</p>
<p>In 2002, the VR Studio decided to make the engine open source, so they could
more easily work with universities on Virtual Reality research projects. The
system, although quite usable by the team that developed it, was not quite &quot;open
source ready.&quot; There were several interested users, but building and installing
the system was incredibly complex, and there was little in the way of documentation
or sample code, so there was no significant open source community right away.</p>
<p>In 2002, Jesse Schell left the VR Studio to join the faculty of the Carnegie
Mellon Entertainment Technology Center (ETC). The ETC was looking for something
like Panda3D: a 3D engine powerful enough to create compelling experiences,
but also open and flexible. Since then, ETC students have been working to make
Panda3D usable at the ETC and by the world at large.</p>
<p>Panda3D&#8217;s official web site is http://www.etc.cmu.edu/panda3d.</p>
<p><strong>2) Panda3D Technology:</strong></p>
<p>Panda leverages the power of underlying C/C++ framework and a higher level
Python-based scripting interface to provide a best of both worlds. Python's
late-binding architecture allows programmers to edit their code while it is
running. This gives Panda3D its basis for rapid prototyping. Also, it is possible
to extend Panda3D's features by using other Python modules in your program.
This lets programmers find an already-created module to add the features they
want, without having to re-invent the wheel.</p>
<p>Here is a feature list:</p>
<p>- Multiple underlying rendering APIs: DirectX/OpenGL<br>
- Python scripting interface<br>
- Programming on the fly using interactive scripting in the Python shell<br>
- Extensibility using Python modules<br>
- Custom 3D file format, Egg, with exporters for 3D Studio Max and Maya<br>
- Soft skin animation and a sophisticated actor interface for character animation<br>
- DIRECT Tools for GUI-based scene editing<br>
- Particle Effects API and GUI-based particle panel<br>
- Lighting, fog, and animated textures<br>
- Sound using the FMOD library <br>
- Multithreading, event handling, message passing, and finite state machines<br>
- Functions for interpolation, sequencing, and parallelization<br>
- Modules for magnetic tracking for virtual reality<br>
- Input device interfaces<br>
- Extensive scenegraph manipulation modules</p>
<p><br>
<strong>3) Panda and Python</strong></p>
<p>There are a number of Panda features that are built on top of Python as augmented
tools to assist in rapidly building games and simulations. We briefly discuss
them below. We also discuss how the original C/C++ code is built into Python
modules, specifically the &quot;Interrogate&quot; program.</p>
<p><strong>Tasks:</strong></p>
<p>Panda3D includes a simple Task scheduling system for the developer's convenience.
A Task consists of a function and its associated data that may be called for
each frame of the simulation. It is not related to multithreading; the entire
Python process is single-threaded, and each scheduled Task is simply run once
per frame in round-robin fashion, with &quot;do-later&quot; Tasks deferred in
a priority queue.</p>
<p><strong>Events:</strong></p>
<p>Events such as mouse clicks or keyboard strokes are managed through one global
messenger. Events are used for broadcasting capability through code and as a
guarding mechanism to control when responses will be executed. Mouse and keyboard
events may be accepted on depression and release. One may also send user-defined
events and pass a parameter list with them.</p>
<p><strong>Sequences and Parallels:</strong></p>
<p>Sequences and Parallels allow for more control over when interpolations and
functions begin. Any Interval may be included in a Sequence or Parallel. Sequences
start the Intervals in the order they are called. The next Interval in line
will not begin until the one before it is complete. Parallels run several Intervals
at the same time. Interval objects can be played with specific durations or
combined into a series of effects performed on a timeline. Intervals can also
be paused, resumed, and restarted. It is even possible to jump to any point
in the Interval instead of playing them straight through. </p>
<p>There various types of intervals are defined below:</p>
<p>- Lerp Interval &#8211; Interval for linearly interpolating NodePaths or functions
(position, rotation, scale, color, etc)<br>
- Actor Interval &#8211; Interval for playing animations on Actors<br>
- Mopath Interval &#8211; Interval for moving an object along a spline motion
path<br>
- Sound Interval &#8211; Interval for playing back a sound effect<br>
- Particle Interval &#8211; Interval for playing back particle effects<br>
- Function Interval &#8211; Interval for executing functions<br>
- Wait Interval &#8211; Interval that waits for a specified time and is useful
for complex sequences</p>
<p><strong>Tcl/Tk/Pmw Usage:</strong></p>
<p>DIRECT, Panda's level editing and tools system, uses Tk and Pmw extensively
for its panel based GUI. It also has features for rendering GUI widgets with
Panda itself. Tk and Pmw are used to build all the parameter panels for the
various utilities such as the particle panel and the motion path recorder.</p>
<p><strong>Redefining methods:</strong></p>
<p>One of the truly powerful features of Panda3D is that you can stop a simulation,
redefine a method, and start from that point again. This is done using Python
features. Panda3D recursively digs through namespaces to find the definition
of the class or methods and then swaps them for the new, thus rebinding the
new version. There is also special code written to dig out all the stored function
pointers, such as events and tasks, and replace those as well.</p>
<p><strong>Interrogate:</strong></p>
<p>A key advantage of Panda3D is that it provides developers with the ability
to use both C++ and Python simultaneously. Essentially, Panda3D gives programmers
the best of both worlds, as they are able to take advantage of the high performance
and low-level programming found in C++ in addition to the flexibility, interactive
scripting, and rapid-prototyping capabilities of Python. This feature is made
possible due to Python&#8217;s ability to call C libraries, and ultimately make
use of Panda3D&#8217;s Interrogate System: an automated C++ Extension Module
generation utility similar to SWIG. Although Python is the favored scripting
language of Panda3D, the engine is highly extensible in this aspect, as any
language that has a foreign function interface can make use of the Interrogate
System.</p>
<p>The Interrogate System works like a compiler by scanning and parsing C++ code
for the Panda3D-specific, &#8220;PUBLISHED&#8221; keyword. This keyword marks
the particular methods of a class that are to be exposed within a C++ Extension
Module for that class which is eventually generated. One benefit of using the
&#8220;PUBLISHED&#8221; keyword is that it alleviates the need for an interface
file that provides function prototypes for the class methods that will be exposed
within the extension module, as is the case with SWIG. Interrogate turns a class
into a loose collection of Python interface wrapper functions that make up the
C++ Extension Module. In addition to creating the module, Interrogate generates
a table of class relationships, which is then read by the Python FFI (Foreign
Function Interface) layer that automatically generates a true object-oriented
interface and makes the C++ classes appear to be Python classes. </p>
<p>There are a number of reasons why Interrogate was chosen over SWIG when Panda3D
moved to Python as its scripting language of choice. First and foremost, Interrogate
had already been written at the time of the change, and it was already capable
of reading the existing C++ code and generating object-oriented interfaces within
Squeak. When the decision was made to change languages, SWIG was looked at;
however, its support for C++ was not quite as robust as Interrogate at the time.
Namely, it was not able to support all of the complicated C++ features that
were being used, such as templates, nested classes, and function overloading.
Another issue that cropped up was that SWIG requires an interface file for each
class that needs to expose functions within the C++ Extension Module, and it
would have been a daunting task to build an interface file for each Panda class.
Overall, it seemed easier to write the Python-based FFI layer that was needed
for interrogate than to deal with a new set of issues that would be encountered
with a new parser.</p>
<p><strong>Squeeze:</strong></p>
<p>Once all of the Python classes have been generated by the Python FFI layer,
the Squeeze utility is used to create one single package to store all of the
Panda modules. Loading python modules on the Win32 platforms introduces certain
amount of latency depending on the CPU. Panda has some 800 python modules. Since
these latencies accrue to an unacceptable delay, Squeeze is used to create one
large module, greatly reducing the hit. In addition, every file is hashed via
md5 when Tootown starts in order to detect hacked, corrupted, or out-of-date
files. It is much quicker to md5 one huge file than 800 small files, which is
certainly an added benefit.</p>
<p><br>
<strong>4) Case Studies:</strong></p>
<p><strong>Toontown Online:</strong></p>
<p align="center"><img src="screen1.jpg" width="337" height="253"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="screen11.jpg" width="337" height="253"></p>
<p align="center"><strong> Screenshots from Toontown Online</strong></p>
<p align="center"><strong><img src="LevelEditorScreen.jpg" width="450" height="288"></strong></p>
<p align="center"><strong> Level Editor and DIRECT Tools for Toontown</strong></p>
<p>Disney's massively multiplayer online role playing game (MMORPG) Toontown Online
was built using Panda3D. It was developed using Python scripting. Toontown can
be downloaded online and is less than 30MB compressed. The users are typically
able to play the game after the first few megabytes have been downloaded. The
decision to change over to Python as the scripting language was made some 6
months into the project. These reasons are:<br>
- Well documented, mature language with a well established community.<br>
- Clean syntax and familiar concepts (to C++)<br>
- Easy to extend/embed<br>
- Dynamic/late binding/typeless, making it easy to prototype quickly with it<br>
- No performance or code management problems<br>
- Small and modular <br>
- Cross platform<br>
Toontown was named MMORPG of the year 2003 by Computer Gaming World.</p>
<p></p>
<p><strong>Building Virtual Worlds:</strong></p>
<p align="center"><img src="HelloWorld_joyjoy.jpg" width="350" height="228">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="goodshot.jpg" width="350" height="228"></p>
<p align="center"><strong>Student projects from the Building Virtual Worlds class</strong></p>
<p> In the Building Virtual Worlds class at the Entertainment Technology Center,
interdisciplinary teams of 4 or 5 students build interactive virtual reality
experiences in two or three weeks. These experiences use Head-Mounted Displays
and magnetic tracking. While 3DS Max, Maya, Deep UV and Deep Paint 3D are used
for content creation, the experience is based in Panda3D. All the scripting
is done in Python. Issues tackled in scripting are:<br>
- Interfacing with the head mount tracking system<br>
- Loading and rendering digital content such as models, animations and sounds<br>
- Collision detection<br>
- Programming interactivity<br>
- Scripting events, states, message handling, input device interfacing etc.<br>
The use of Panda3D produced stunning results in the class.</p>
<p><br>
<strong>Airblade:</strong></p>
<p align="center"><strong><img src="TitleScreen.jpg" width="450" height="400"></strong></p>
<p align="center"><strong>Airblade- A game demo built by 3 students in 8 weeks
with Panda3D</strong></p>
<p>Airblade is a game demo built in Panda by a group of three students in 8 weeks
at the Entertainment Technology Center. It demonstrates the basics of developing
sophisticated games using Panda3D. Some of the Panda3D features it showcases
are <br>
- Finite state machines<br>
- Animated texture map explosions<br>
- Particle effects<br>
- Complex collision detection and raycasting<br>
- Lighting<br>
- Using a model pool<br>
- Creating a heads-up display using GUI features<br>
- Using tasks for interactive animation<br>
- Using the interval system for prototyping the experience<br>
The demo and source code for Airblade are available at http://www.etc.cmu.edu/panda3d/projects/Airblade</p>
<p><br>
<strong>5) Future Plans:</strong></p>
<p>At the Entertainment Technology Center, the Panda project is trying to make
Panda3D an out-of-the-box development tool for games and simulations. It works
closely with Walt Disney VR Studio in improving Panda3D. A major part of the
Panda project at the ETC is also to create extensive documentation for Panda3D
and develop a comprehensive set of tutorials for it.<br>
Some future developments may include:<br>
- Integrating state of the art rendering technology, such as programmable shaders
<br>
- General-purpose server side networking code to complement existing client
side code released by Disney.<br>
- An easy to use but powerful and generic scene/level editing tool <br>
Panda is also being used at the ETC for a number of game and simulation projects.
At the same time the folks at Walt Disney VR Studio are using Panda to develop
new content for Toontown Online and their new massively multiplayer online game.
We hope that strong interest from the Python community and the open source movement
will help make Panda the rapid prototyping tool of choice for games and simulations.</p>
<p><br>
<strong>References:</strong></p>
<p>[1] Panda 3D Website, Entertainment Technology Center, Carnegie Mellon University,
http://www.etc.cmu.edu/panda3d.</p>
<p>[2] Goslin M.,&quot;Postmortem: Disney Online's Toontown by Mike Goslin [01.28.04]&quot;,
http://www.gamasutra.com/features/20040128/goslin_01.shtml.</p>
<p>[3] Goslin M., Shochet J. and Schell J.,&quot;Toontown Online:Building Massively
Multiplayer Games for the Masses.&quot;</p>
<p>[4] Designing Interactive Theme Park Rides. Jesse Schell and Joe Shochet. IEEE
Computer Graphics and Applications. July/August 2001.</p>
<p>[5] Designing Interactive Theme Park Rides: Lessons Learned Creating Disney&#8217;s
Pirates of the Caribbean: Battle for the Buccaneer Gold. Jesse Schell and Joe
Shochet. Game Developer&#8217;s Conference 2001.</p>
<p>[6] Building an LBE Attraction: Hercules in the Underworld, A Case Study. Joe
Shochet and Noah Dudley. Game Developer&#8217;s Conference, 1999.</p>
<p></p>
</body>
</html>
<!--
FILE ARCHIVED ON 6:09:38 ožu 1, 2007 AND RETRIEVED FROM THE
INTERNET ARCHIVE ON 18:31:57 vel 26, 2015.
JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE.
ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C.
SECTION 108(a)(3)).
-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment