240 likes | 443 Views
Developing 3D Games with Macromedia Director. Brian Robbins Director, Online Gaming Fuel Industries, Inc. www.fuelindustries.com . My Background. Director developer since 1999 Worked on over 70 games Developing 3D games since 8.5 Beta Previous Projects Lots of games for CleverMedia
E N D
Developing 3D Games with Macromedia Director Brian Robbins Director, Online Gaming Fuel Industries, Inc. www.fuelindustries.com
My Background • Director developer since 1999 • Worked on over 70 games • Developing 3D games since 8.5 Beta • Previous Projects • Lots of games for CleverMedia • The Lord of the Rings Online Trading Card Game
Recent Projects • Coors Golf • My first use of shadows and other enhanced visual effects • Cowboys & Engines • Multi-user Junkyard • Wakeboarding • Crazy wakeboarding game
Today’s Topics • Graphics • Production workflow • Using user-data • Power to the artists • Shadows • Overlays • Skyboxes
Today’s Topics • Programming • Time-based • Character “Add Ons” • Collisions with MUR • Billboard sprites
Graphics • <<big cool screenshot goes here>>
Project Workflow • Model the world in 3D Application • Maya, MAX, etc • Export to .w3d • Public exporters or your own custom exporter • Import into Director • Put it on stage
The joys of .userData • Lets the artist become a level designer • The best way to add information in modeling for run-time repeat with i=g3d.model.count down to 1 mdl = g3d.model[i] usrData = mdl.userData tmp = usrData[#textureTransparent] if not voidp(tmp) then --Set the texture's renderformat to rgba8888 mdl.shader.texture.renderFormat = #rgba8888 end if end repeat
Let artists worry about the visuals • We should be providing tools to the artists • They are the visual people, let them do the visuals • Make an engine, and let them use it • NEVER underestimate an artist
Shadow Maps • What is a shadow map? • But .w3d doesn’t support multiple texture layers! • Example generateLightMap(member("Source Scene"), member("lightmap scene")) getLightmap(member("source scene"))
Other Shadows • Simple circle • Can be effective • Barry Swan’s shadow controller • Lots of overhead, but looks the best right now • inludo.com/rd/d85/tuts/shadows01.htm gCharShadow = script("[P] Shadows").new(g3d, g3d.model("character"), lightVector, floorPos, shadowColor, true) • Noisecrime’s real-time shadows • noisecrime.com/develop/techdemo/dmx/shadowmapping11.htm
Better Overlays • Built-in overlays suck • We use multiple cameras • Gives us much more control • Now we have an overlay controller
Create Overlay Camera --Make it an ortho camera pCam.projection = #orthographic --Set the cam not to clearAtRender pCam.colorBuffer.clearAtRender = false --Set the cam's rootNode to itself pCam.rootNode = pCam --Remove the cam from the world pCam.removeFromWorld() --Set the hither and yon pCam.hither = 1 pCam.yon = 10000 --Add the camera to the sprite p3dSprite.addCamera(pCam, pCamIndex) --Set the orthoHeight to the sprite height pCam.orthoHeight = height --Update cam rect too pCam.rect = rect(0,0, width, height)
Creating Skyboxes that work • This is the same theory as the overlays • Instead the camera goes first • Now we can have fog and a backdrop! baseCam = pSprite.camera(1) pTargetCam = baseCam pMyCam = baseCam.clone("SkyboxCam”) --Turn off the base clearAtRender baseCam.colorBuffer.clearAtRender = false --Add our camera to the sprite pSprite.addCamera(pMyCam, 1)
Programming • <<big cool screenshot goes here>>
Time-based is the Key • Absolutely critical for 3D games • When planned from the start it’s easy • Once you go timed, you’ll never go back on newFrame me currTime = the Milliseconds timeElapsed = currTime - pLastTime pLastTime = currTime if timeElapsed > 100 then timeElapsed = 100 end if return timeElapsed end
Character “Add Ons” • How to attach objects to a skeleton? • Useful in all sorts of character games • Clothes • Weapons • etc on updatePosition me --Get the transform of our parent bone if pBoneID > 0 then trans = pParentModel.bonesPlayer.bone[pBoneID].worldTransform pMyGroup.transform = trans end if
Collision Detection • This makes (or breaks) your world • ModelsUnderRay works well • Collision resolution can be tricky
Collision Resolution --Slide the char along the object --First get the normal Angle normalAngle = pCollisionInfo.isectNormal --Next get the vector that's parallel to the normal parallelVec = normalAngle.cross(vector(0,0,1)) --Now get the amount we need to move (this takes into account whether to slide left or right) dotProd = pDirectionRay.dot(parallelVec) --Get the moveVector to be the appropriate length moveVec = parallelVec*dotProd --Now 0 out the moveVec's zAxis (so we don't go up or down) moveVec.z = 0 --Check to see if we can actually move to that point if me.checkMove(moveVec, true) then --Actually move the character this way pMyParent.translate(moveVec, #world) else --There's another object preventing us from sliding there so just stop end if
Billboard Sprites • They always face the camera • Character names • Signs • Trees • Etc • Easy to do! --Get the cam rotation camRot = pSprite.camera.getWorldTransform().rotation -- Update the model position (optional) pMyModel.transform.position = pModelParent.transform.position + pOffset --Update the model rotation pMyModel.transform.rotation.z = camRot.z
Conclusion • Graphics • Workflow • .userData • Artists are visual • Shadows • Overlays • Skyboxes
Conclusion • Programming • Time-based • Character “Add Ons” • MUR and Collisions • Billboard Sprites
Links / Resources • dubane.com/cons • noisecrime.com/develop • inludo.com/rd/d85/ • director-online.com • blog.fuelindustries.com