#=====================
# shoot.py
#
# This script places a "hitspot" object where
# a ray sensor hits a face, oriented along
# the face normal, then it handles shooting.
#
# Randall Rickert
# randall@blender.nl
#=====================
from math import sqrt
#=====================
# Functions
#
# These first 3 are standard vector math
# (if used a lot, might be faster in C).
#=====================
def normalize(x):
length = sqrt(x[0]*x[0]+x[1]*x[1]+x[2]*x[2])
return [x[0]/length,x[1]/length,x[2]/length]
def cross(x,y):
return [ x[1]*y[2] - x[2]*y[1],
x[2]*y[0] - x[0]*y[2],
x[0]*y[1] - x[1]*y[0]]
def dot(x,y):
return x[0]*y[0] + x[1]*y[1]+x[2]*y[2]
def mul(s,x):
return [s*x[0],s*x[1],s*x[2]]
#=====================
# Given any two vectors, vecToMat3 will return
# a 3x3 matrix having z aligned to the first
# vector and y tracking as near as possible
# to the second.
#=====================
def vecToMat3(vec, track):
z = normalize(vec)
dotprod = dot(z, normalize(track))
if abs(dotprod) == 1: #prevent gimbol lock
track.append(track[0])
del track[0]
x = normalize(cross(track, vec))
y = cross(z, x)
return [
[x[0],y[0],z[0]],
[x[1],y[1],z[1]],
[x[2],y[2],z[2]]]
#=====================
# Game logic
#=====================
controller = GameLogic.getCurrentController()
raySensor = controller.getSensor("raySensor")
hitspot = controller.getOwner()
addFlash = controller.getActuator("addFlash")
addMark = controller.getActuator("addMark")
if hitspot.shoot == 1:
if raySensor.isPositive():
position = raySensor.getHitPosition()
hitspot.setPosition(position)
normal = raySensor.getHitNormal()
up = [0, 0, 1]
orientation = vecToMat3(normal, up)
hitspot.setOrientation(orientation)
hitObject = raySensor.getHitObject()
if hasattr(hitObject, "is_dynamic"):
rayVector = raySensor.getRayDirection()
force = mul(hitspot.k_gunForce, rayVector)
hitObject.applyImpulse(position, force)
else:
GameLogic.addActiveActuator(addMark, 1)
if hasattr(hitObject, "hits"):
hitObject.hits = hitObject.hits + hitspot.k_gunDamage
GameLogic.addActiveActuator(addFlash, 1)
hitspot.shoot = 0