User Tools

Site Tools


public:t-vien-07-1:lab_6_materials

Lab 6 - Avatars and HUD

In-Class Excercises

Before You Start

Roaming Ralph with some HUDs

In this exercise you'll start with a fully working 3rd person world with Ralph as your avatar. You'll then add a couple of classic HUD features, namely the health bar and the overhead map.

  1. Get the advancedralph.py running and explore the controls, making sure you understand how to control both Ralph himself and the camera (rotating and tilting by approaching the edge of the screen with your mouse; zooming with the mouse wheel). Have the application run in Fullscreen mode, simply by changing False to True in the call to setFullscreen near the bottom of the code. It is easier to control the camera with the mouse in this mode, but the windowed mode might be better while debugging.
  2. The following code is a HealthBar object that can be attached to a scene graph. A health bar can display some fractional property in a graphical manner, such as the health or power of a character. Attach this bar to the Avatar so that the bar appears to be floating over the Avatars head. Make sure you can see it (but it may disappear when you start moving around - see below)
    class HealthBar(NodePath):
        """ Adapted from drwr's code on the Panda 3D forums """
     
        def __init__(self):
            NodePath.__init__(self, 'healthbar')
            self.group = self.attachNewNode('group')
            self.group.setPos(-0.5,0,0)
            cmfg = CardMaker('fg')
            cmfg.setFrame(0, 1, -0.1, 0.1)
            self.fg = self.group.attachNewNode(cmfg.generate())
            cmbg = CardMaker('bg')
            cmbg.setFrame(-1, 0, -0.1, 0.1)
            self.bg = self.group.attachNewNode(cmbg.generate())
            self.bg.setPos(1, 0, 0)
            self.fg.setColor(0, 1, 0, 1.0)
            self.bg.setColor(0.5, 0.5, 0.5, 1.0)
            self.value = 0.8
            self.update()
     
        def update(self):
            self.fg.setScale(self.value, 1, 1)
            self.bg.setScale(1.0 - self.value, 1, 1)        
     
        def setHealth(self, value):
            self.value = value
            self.update()
     
        def decrease(self, delta):
            if (self.value - delta) >= 0:
                self.value -= delta
                self.update()
  3. If your health bar rotates with your Avatar, you may notice that it fully disappears when you're looking at the Avatar from another angle. You can use the so called Billboard effect to ensure that the health bar always faces you, no matter how the Avatar is facing. You enable this effect on any nodepath by calling its setBillboardAxis method. Try using this to make your health bar always visible.
  4. The healthbar calls a little too much attention to itself on the display. Make it semi-transparent so that it blends in better. Don't forget to enable transparency in the scene graph (HINT: setTransparency).
  5. Now make the healthbar start decreasing while the Avatar is running and then gain full health when the Avatar stops running. HINT: For any FSM class, you can query the state member variable to see what state it is in.
  6. The following code is an OverheadMap object that can be attached to a scene graph. A good place for it would be the 2D scene graph, since it should be rendered on top of the 3D scene. Add this object and have it show you where your avatar is located any given moment. It is good for you to know that the world dimensions in the x-y plane are approximately (-128,-68,48,48). You may need to scale and reposition your map on the screen so that it doesn't occlude your view. Also, to enable transparency on the 2D scene graph, you'll need to call setTransparency again because it is a separate scene graph from render. Make sure this is all working fine.
    class OverheadMap(NodePath):
     
        def __init__(self, x1, y1, x2, y2):
            """ Create a square map with the given world corners in the x-y plane """
            NodePath.__init__(self, 'overheadmap')
     
            cmbg = CardMaker('bg')
            cmbg.setFrame(0,1,0,1)
            self.prime = self.attachNewNode(cmbg.generate())
            self.prime.setColor(0.5,0.5,0.5,0.5)
     
            self.setBoundary(x1,y1,x2,y2)
     
            cmav = CardMaker('am')
            cmav.setFrame(-0.02,0.02,-0.02,0.02)
            self.avatar = self.prime.attachNewNode(cmav.generate())
            self.avatar.setPos(0,0,0)
            self.avatar.setColor(0,1,0,1)  
     
        def addLandmarks(self, landmarks, color=P.Vec4(1,0,0,0.5)):
            """ Take in a list of (x,y) touples in world coordinates and place them
                as little dots on the map in the given color """
            ## To be filled in...
     
        def setBoundary(self, x1, y1, x2, y2):
            """ Define the extent of the map in world coordinates.  Create the proper
                offset and scaling values that transform world coordinates to map coordinates"""
            self.xoffset = x1
            self.xscale = 1.0/(x2-x1)
            self.yoffset = y1
            self.yscale = 1.0/(y2-y1)
     
        def setAvatarPos(self, x, y):
            """ Sets the position of the avatar marker to the given world coordinates """
            self.avatar.setPos((x-self.xoffset)*self.xscale,-0.01,(y-self.yoffset)*self.yscale)
  7. Now add some landmarks to your world and have them show up on your map as little red squares. You can use the Models/box.egg object. Initialize a few of these boxes by storing a list if (x,y) tuples and then iterate through the list to place them in the world. You should also be able to send the list directly into the map's addLandmarks method and have the locations of the boxes light up. You'll need to fill in the rest of that method. Test to see if this is all working.
  8. If you feel adventurous, change this application into a game where the health bar starts to drop as time passes and the only way to regain full health is to touch a box, which then disappears. You win the game if you reach all the boxes. By randomizing the initial box locations, you'll really need the map to help you play this game.
/var/www/ailab/WWW/wiki/data/pages/public/t-vien-07-1/lab_6_materials.txt · Last modified: 2008/01/03 11:04 by hannes