PDA

View Full Version : Face Hits


betancourtb82
05-17-2006, 12:04 PM
I'm having a problem using faces on my avatars. I define my avatars using the following code:
#Avatars
for x in range(0,3):
if x == 0:
male = viz.add(people[0])
male.face(faces[0])
male.scale(.1,.1,.1)
link = viz.add(viz.GROUP)
myphone = link.add(objects[0])
myphone.scale(.001,.001,.001)
male.linkbone(link,'skel_HandR')
male.tag = 0
male.threatening = TRUE

elif x == 1:
male = viz.add(people[1])
male.face(faces[1])
# link = viz.add(viz.GROUP)
# myphone = link.add(objects[1])
# myphone.scale(.0005,.0005,.0005)
# myphone.translate(0,-.25,.17)
# myphone.rotate(180)
# male.linkbone(link,'skel_Neck')
link = viz.add(viz.GROUP)
myphone = link.add(objects[0])
myphone.scale(.001,.001,.001)
male.linkbone(link,'skel_HandR')
male.tag = 1
male.threatening = FALSE
elif x ==2:
male = viz.add(people[2])
male.face(faces[2])
link = viz.add(viz.GROUP)
myphone = link.add(objects[0])
myphone.scale(.001,.001,.001)
male.linkbone(link,'skel_HandR')
# link = viz.add(viz.GROUP)
# myphone = link.add(objects[2])
# myphone.scale(.0008,.0008,.0008)
# myphone.rotate(66.51,151.49,86.01)
# myphone.translate(-0.02,0.04,0.02)
# male.linkbone(link,'skel_HandRF')
male.tag = 2
male.threatening = FALSE
male.translate(3*x,-10,10)
male.rotate(180)
#Add the avatar to the waiting and lemming list
waitlist.append(male)
characters.append(male)

When they get hit, they perform a falling action with the following code:
if info.intersected:
if info.object in faces:
print 'Face hit'
if info.object in characters:
#print "in characters"
if info.object.tag == 0:
soldierCount += 1
if info.object.threatening == TRUE:
threatCount += 1
elif info.threatening == FALSE:
nonthreatCount += 1
elif info.object.tag == 1:
maleCount += 1
if info.object.threatening == TRUE:
threatCount += 1
elif info.object.threatening == FALSE:
nonthreatCount += 1
elif info.object.tag == 2:
femaleCount += 1
if info.object.threatening == TRUE:
threatCount += 1
elif info.object.threatening == FALSE:
nonthreatCount += 1
avatarsHit = avatarsHit + 1
viz.playsound('arrgh.wav')
WaitThenFreeze = vizact.sequence( vizact.waittime(info.object.getduration(7)-.85), vizact.speed_node(0) )
info.object.execute(7)
info.object.clear(viz.ALL)
info.object.clear(viz.CURRENT_ACTION)
info.object.add(WaitThenFreeze) #Add the action to the avatar
RemoveAvatarAction = vizact.call(RemoveAvatar,info.object)
info.object.add(RemoveAvatarAction) #Add action to remove avatar

The problem I'm having is when I shoot them in the face (yes, i know it's a bit violent :)), they don't respond. Is there anyway to correct this? I want them to perform the same action as when they are shot in the body and also be able to keep track of how many face hits there are.

Gladsomebeast
05-17-2006, 02:13 PM
Is 'Face Hit' ever printed? If so, try printing the info.object when you know you've made a headshot. Can you identify the node in your world that is the info.object?

If ‘Face Hit’ is not printed, check your viz.intersect() points and verify that they create a line passing through the head geometry.

If viz.intersect() is not getting the faces you can also try creating an invisible child boxes as children of the avatar’s heads and use them as the intersection targets.
box = face.add( 'box.wrl' )
box.scale( .5, .5, .5 )
box.visible( viz.OFF )

betancourtb82
05-18-2006, 10:59 AM
Is there a way to name the faces (e.g. info.object.faces) or something like that? I don't want to have to add the box because it will add another object to have to worry about, but if that's the only way I will.

Thanks

Gladsomebeast
05-18-2006, 11:19 AM
Is info.object a valid node when you shoot the face? I suggest that you identify what this object is, and use that object to check if the face is hit.

My experiments have found that the face is quite hard to get viz.intersect to detect. I would recommend you use the box solution if the above solution goes nowhere.

betancourtb82
05-18-2006, 11:49 AM
Ok, I did the box tactic, however now i'm not sure how to reference the boxes. When an avatar gets hit I say "if info.object in characters (the character array of avatars). How Can I do this with the boxes?

Also, I had another question regarding avatar hits. I'm having a problem that when a bullet hits the avatar, the avatar is still able to be hit, thus incrementing the hit count. I want the avatar hit count to only be incremented once for every avatar that gets hit. It is not important to know whether an avatar gets hit multiple times. I added a info.object.disable(viz.COLLISION) to disable collisions as soon as they get hit.

info = viz.intersect(pos,futurePos)
if info.intersected:
if info.object in characters:
info.object.disable(viz.COLLISION)
#print "in characters"
if info.object.tag == 0:
soldierCount += 1
if info.object.threatening == TRUE:
threatCount += 1
elif info.threatening == FALSE:
nonthreatCount += 1
elif info.object.tag == 1:
maleCount += 1
if info.object.threatening == TRUE:
threatCount += 1
elif info.object.threatening == FALSE:
nonthreatCount += 1
elif info.object.tag == 2:
femaleCount += 1
if info.object.threatening == TRUE:
threatCount += 1
elif info.object.threatening == FALSE:
nonthreatCount += 1
avatarsHit = avatarsHit + 1
viz.playsound('arrgh.wav')
WaitThenFreeze = vizact.sequence( vizact.waittime(info.object.getduration(7)-.85), vizact.speed_node(0) )
info.object.execute(7)
info.object.clear(viz.ALL)
info.object.clear(viz.CURRENT_ACTION)
info.object.add(WaitThenFreeze) #Add the action to the avatar
RemoveAvatarAction = vizact.call(RemoveAvatar,info.object)
info.object.add(RemoveAvatarAction) #Add action to remove avatar

This solves the problem of the multiple hits, however I don't know where to enable the collision again for the next time they walk out. I have two functions that are called (RemoveAvatar and RestoreAvatar). Would I be able to put insert an enable(viz.COLLISION) anywhere in these two functions. I hope this is making sense.

def RemoveAvatar(avatar):
global avatarCount
avatar.visible(0) #Hide avatar
avatar.speed(1) #Restore speed
characters.remove(avatar) #Remove from list
dead_list.append(avatar) #Add to dead list
avatarCount += 1
print 'avatar count is: ', avatarCount
def RestoreAvatar():
global keyindex
if len(dead_list):
print "avatar restored"
avatar = dead_list.pop() #Ressurrect dead avatar
avatar.visible(1) #Make it visible
characters.append(avatar) #Add it to avatar list

Gladsomebeast
05-18-2006, 02:23 PM
You could add the box objects to a list and then do “if info.object in boxList:” to check if a box has been hit.

It looks like you would want to call enable(viz.COLLISION) in your RestoreAvatar() function.

betancourtb82
05-19-2006, 09:02 AM
I tried doing that, but unfortunately the enable command comes back too quickly. If I just disable the collisions then it works but if I try to enable them again in RestoreAvatar, then I am still able to get multiple shots on the avatars before they "die". Is there anyway I can delay the enabling of the collisions until they walk out again?

Gladsomebeast
05-19-2006, 09:19 AM
I see a few solutions. Pick the best for your code structure: 1.) Simply call enable(viz.COLLISION), in whatever code tells the avatar to “walk out again.” 2.) Leave enable(viz.COLLISION) in the RestoreAvatar function and call RestoreAvatar when you want the character to walk out again. 3.) You could delete the object (I assume it is a bullet?) that is intersecting with the character with bullet.remove() in your intersection handling function.

betancourtb82
05-19-2006, 09:34 AM
Worked Great! I used your first suggestion. THANKS A BUNCH!!!

betancourtb82
05-23-2006, 11:02 AM
I have a question that is related to this topic. Each avatar that enters the room is holding one of three objects (a gun, a camera, or a phone). When I define the avatar, I put in a function called getWeapon
def getWeapon(avatar,number):
global link
if number == 0:
link = viz.add(viz.GROUP)
myphone = link.add(objects[0])
myphone.scale(.001,.001,.001)
avatar.linkbone(link,'skel_HandR')
elif number == 1:
link = viz.add(viz.GROUP)
myphone = link.add(objects[1])
myphone.scale(.0005,.0005,.0005)
myphone.translate(0,-.25,.17)
myphone.rotate(180)
male.linkbone(link,'skel_Neck')
else:
link = viz.add(viz.GROUP)
myphone = link.add(objects[2])
myphone.scale(.0008,.0008,.0008)
myphone.rotate(66.51,151.49,86.01)
myphone.translate(-0.02,0.04,0.02)
male.linkbone(link,'skel_HandRF')
I'm thinking of making the avatar run through the getWeapon function each time they go through RestoreAvatar, however I'm not sure how to get them to "drop" the object they are holding when they get shot. I tried unlink() but I am unsure where and how to use it. Any ideas?

Gladsomebeast
05-23-2006, 12:12 PM
Call <node>.remove() on the varable named link when you want to eliminate the old weapon.

betancourtb82
05-23-2006, 01:37 PM
I tried adding link.remove() but it gave me errors. I added it in the RemoveAvatar() function. Can I have an example of how to do this in the remove avatar function?

Gladsomebeast
05-23-2006, 02:24 PM
You need to call <node>.remove() on the weapon object. Save the weapon object handle somewhere and call remove() on it in the removeAvatar() function. You can save a weapon handle by calling avatar.weapon = myphone in your getWeapon() function. When you need to remove the weapon call avatar.weapon.remove().

betancourtb82
06-07-2006, 12:00 PM
If I create a handle using avatar.weapon = myphone, is that a global variable? How would I get the RemoveAvatar function to recognize that handle?