# -*- indent-tabs-mode: t -*-
INTRO = """
the hit function take arguments, the first one is the body you collide and the
second is a list of Contact object containing information about the Point of contact
In this tutorial you will learn to use the second argument.
this argument are the list of all Contact betwen self and other this contact
have many usefull attribut descripting the Contact. This time We are using the
pos attribut to find the position of the contact and create some particule
"""
print '===== Control ====='
print 'arrows: move'
print 'espace: up'
print 'left: down'
print 'mouse: look'
print 'clic: firing laser'
print 'right: clic for stronger single shot'
print "return: center the camera when you're lost"
print 'escape: quit'
import sys, os
from random import choice, gauss as normalvariate, randint, random, expovariate
from math import sqrt, pi
import soya
import soya.widget
import soya.sphere
import soya.laser
from soya import Vector, Point
if '-f' in sys.argv:
soya.init("ode-collision-7-hit_func-3-contacts",width=1280,height=854,fullscreen=True)
else:
soya.init("ode-collision-7-hit_func-3-contacts",width=1024,height=768)
soya.cursor_set_visible(False)
soya.set_mouse_pos(1280/2,854/2)
soya.path.append(os.path.join(os.path.dirname(sys.argv[0]), "data"))
scene = soya.World()
class Nova(soya.Smoke):
def __init__(self,parent,nb_particles=12):
soya.Smoke.__init__(self,parent,nb_particles=nb_particles)
#self.set_colors((1.0, 1.0, 1.0, 1.0), (1.0, 0.0, 0.0,0.5),(1.0,1.0,0.,0.5),(0.5,0.5,0.5,0.5),(0.,0.,0.,0.5))
#self.set_sizes ((0.19, 0.19), (0.35, 0.35))
#self.auto_generate_particle=1
def added_into(self,parent):
#print 'former:',self.parent
if self.parent is not None:
self.parent.parent.remove(self.parent)
soya.Smoke.added_into(self,parent)
def generate(self, index):
sx = (random()- 0.5)
sy = (random()-0.5)
sz = (normalvariate(0,0.1))
l = self.speed * (0.2 * (1.0 + random())) / sqrt(sx * sx + sy * sy + sz * sz) * 0.4 * self.matrix[16]
lb = self.life
lf = self.life_function
a = self.acceleration
sx=sx*l
sy=sy*l
sz=sz*l
#print sz
self.set_particle(index, (1 + lf())*lb, sx, sy, sz, sx*a, sy*a, sz*a)
materials = (
(soya.Material(soya.Image.get("block2.png")), (0.188235,0.141176,0.086275)),
(soya.Material(soya.Image.get("metal1.png")), (0.329412,0.321569,0.345098)),
(soya.Material(soya.Image.get( "grass.png")), (0.231373,0.380392,0.149020)),
(soya.Material(soya.Image.get("ground.png")), (0.768627,0.654902,0.443137)),
(soya.Material(soya.Image.get( "snow.png")), (0.886275,0.901961,0.894118)),
(soya.Material(soya.Image.get( "lava.png")), (0.894118,0.184314,0.011765)),
#(soya.Material(soya.Image.get( "blood.png")), (0.141186,0.000000,0.000000)),
#(soya.Material(soya.Image.get( "soustoit.png")), (0.5,0.5,0.5)),
)
models = []
for material,color in materials:
models.append((soya.sphere.Sphere(None,material).shapify(),color))
class Ball(soya.Body):
#ball_model = soya.Model.get("caterpillar_head")
ball_model = ball_world = soya.sphere.Sphere(None).shapify()
tmp_vect = Vector(scene)
def __init__(self,parent):
model,color=choice(models)
soya.Body.__init__(self,parent,model)
self.dust_color = color
def begin_round(self):
soya.Body.begin_round(self)
self.tmp_vect.set_xyz(-self.x,-self.y,-self.z)
self.add_force(self.tmp_vect)
def hit(self,other,contacts):
s = self.linear_velocity.length()
s = (s**2/200.)
es= 0.1+(s**2)
l = 1+(150*s)
a = -0.0001/(1+l)
#print s
for contact in contacts:
w=soya.World(scene)
w.look_at(contact.normal)
w.move(contact.pos)
p = Nova(w)
p.particle_coordsyst = w
#p = soya.Fountain(scene)
p.removable = True
p.speed = es
p.life = l
p.acceleration = a
p.set_sizes((0.1, 0.1), (0.15, 0.15))
p.set_colors(self.dust_color+(0.9,),self.dust_color+(0,))
heads = []
for i in range(100):
r = (0.4+abs(normalvariate(1,1)))
b = Ball(scene)
b.mass = soya.SphericalMass(20*4*pi*(r**2),1,"total_mass")
b.scale(r,r,r)
soya.GeomSphere(b,r)#.bounce = random()
b.set_xyz(normalvariate(0,150),normalvariate(0,150),normalvariate(0,150))
b.look_at(scene)
heads.append(b)
light = soya.Light(scene)
light.set_xyz(30,30,30)
class LaserCamera(soya.Camera):
def __init__(self, parent):
soya.Camera.__init__(self, parent)
self.speed = soya.Vector(self)
self.mouse_sensivity =2
self.laser_vector = Vector(self,0,0.01,-1)
self.laser_pos = Point(self,0,-1,0)
self.laser = soya.laser.Laser(self.parent)
self.laser.visible = self.laser_on = False
self.laser_power = 1000
self.single_blast = False
self.laser.color=(1,0,0,0.5)
def begin_round(self):
soya.Camera.begin_round(self)
events = soya.MAIN_LOOP.events
for evenement in soya.coalesce_motion_event(events) :
# mouvement de la souris
if evenement[0] == soya.sdlconst.MOUSEMOTION and (evenement[1] != self.get_screen_width()/2 and evenement[2] != self.get_screen_height()/2):
left = (evenement[1] - self.get_screen_width()/2) * (self.mouse_sensivity-1) + evenement[1]
top = (evenement[2] - self.get_screen_height()/2) * (self.mouse_sensivity-1) + evenement[2]
self.look_at(self.coord2d_to_3d( left, top ))
soya.set_mouse_pos(self.get_screen_width()/2,self.get_screen_height()/2)
for event in events:
if event[0] == soya.sdlconst.KEYDOWN:
if event[1] == soya.sdlconst.K_UP: self.speed.z = -1.0
elif event[1] == soya.sdlconst.K_DOWN: self.speed.z = 1.0
elif event[1] == soya.sdlconst.K_LEFT: self.speed.x = -1.0
elif event[1] == soya.sdlconst.K_RIGHT: self.speed.x = 1.0
elif event[1] == soya.sdlconst.K_SPACE: self.speed.y = 1.0
elif event[1] == soya.sdlconst.K_LCTRL: self.speed.y = -1.0
elif event[1] == soya.sdlconst.K_q: soya.MAIN_LOOP.stop()
elif event[1] == soya.sdlconst.K_ESCAPE: soya.MAIN_LOOP.stop()
elif event[1] == soya.sdlconst.K_RETURN:
self.set_xyz(0,0,70),
self.look_at(Point(self.parent,0,0,0))
elif event[0] == soya.sdlconst.KEYUP:
if event[1] == soya.sdlconst.K_UP: self.speed.z = 0.0
elif event[1] == soya.sdlconst.K_DOWN: self.speed.z = 0.0
elif event[1] == soya.sdlconst.K_LEFT: self.speed.x = 0.0
elif event[1] == soya.sdlconst.K_RIGHT: self.speed.x = 0.0
elif event[1] == soya.sdlconst.K_SPACE: self.speed.y = 0.0
elif event[1] == soya.sdlconst.K_LCTRL: self.speed.y = 0.0
elif event[0] == soya.sdlconst.MOUSEBUTTONDOWN:
self.laser_on = True
self.laser.visible = True
if event[1] == soya.sdlconst.BUTTON_RIGHT:
self.laser_power=100000
self.single_blast = True
self.laser.color=(0,0.4,1,0.9)
elif event[0] == soya.sdlconst.MOUSEBUTTONUP:
self.laser_on = False
self.laser.visible = False
if self.laser_on:
if self.laser_on:
self.laser.move(self.laser_pos)
self.laser.look_at(self.laser_vector)
result = self.parent.raypick(self.laser_pos, self.laser_vector)
if result:
impact,normal = result
#apply force
target = impact.parent
target.add_force(self.laser_vector*self.laser_power,impact)
l = sqrt(self.laser_power/1000.)
nl = int(sqrt(l))
#create particle
# first corresponding to the dust of the planet
s = soya.Smoke(self.parent,nb_particles=12*nl)
s.move(impact)
s.removable = True
s.set_colors(target.dust_color+(0.5,),target.dust_color+(0,))
s.set_sizes((0.3, 0.3), (0.7, 0.7))
s.life = 1
#second the lazer beam
s = soya.Smoke(self.parent,nb_particles=12*nl)
s.move(impact)
s.removable = True
s.life = 0.4*l
s.speed = 1
s.set_colors((0.121569,0.431373,0.792157,0.8),(0.121569,0.431373,0.792157,0.5+l/20.))
s.set_sizes((0.2, 0.2), (0, 0))
def advance_time(self, proportion):
self.add_mul_vector(proportion, self.speed)
if self.laser_on:
self.laser.move(self.laser_pos)
self.laser.look_at(self.laser_vector)
def end_round(self):
if self.single_blast:
self.laser_on = False
self.laser.visible = False
self.single_blast = False
self.laser_power = 1000
self.laser.color=(1,0,0,0.5)
main = soya.widget.Group()
camera = LaserCamera(scene)
camera.set_xyz(0,0,100)
camera.back = 500
fps = soya.widget.FPSLabel(main)
print fps.get_color()
fps.set_color((0.5,0.5,0.5,0.5))
main.add(camera)
main.add(fps)
print "scene built"
soya.set_root_widget(main)
ml = soya.MainLoop(scene)
ml.main_loop()
Tutorials : basic-1 - basic-2 - basic-3 - basic-4 - basic-5 - basic-6 - basic-loadingfile-1 - basic-savingfile-cerealizer-1 - basic-savingfile-pickle-1 - blender-auto-exporter-1 - bsp-game_skel - character-animation-1 - character-animation-2 - character-animation-shadow-cellshading-1 - deform-1 - facecutter-1 - fullscreen-1 - game_skel-1 - game_skel-2 - game_skel-3 - game_skel-4 - game_skel-5 - gui-1 - gui-2 - gui-background-1 - label3D-1 - modeling-1 - modeling-2 - modeling-3 - modeling-cellshading-1 - modeling-env-mapping-1 - modeling-material-1 - modeling-material-2 - modeling-shadow-1 - modeling-smoothlit-1 - modeling-solid-model-1 - modeling-transparency-1 - mouse-1 - multiple-cameras-1 - nested-world-1 - ode-collision-1-base - ode-collision-2-base - ode-collision-3-mass_influence - ode-collision-4-pushable - ode-collision-5-hit_func - ode-collision-6-hit_func-2-other - ode-collision-7-hit_func-3-contacts - ode-collision-8-terrain - ode-collision-9-box - ode-gravity - ode-join - ode-mass - ode-test - particle-1 - portal-1 - pudding-1 - pudding-2 - pudding-buttonbar-1 - pudding-buttonbar-2 - pudding-console-1 - pudding-console-2 - pudding-game_skel-5 - pudding-image-1 - pudding-image-slicing-1 - pudding-input-1 - pudding-listbox-1 - pudding-menu-1 - pudding-meter-1 - pudding-svgelements-1 - pudding-z-index-1 - ray-1 - raypicking-1 - raypicking-2 - raypicking-3 - sound-1 - soya-with-tk-1 - speed-1 - state-1 - static-shadows-1 - terrain-1 - terrain-2 - test - traveling-camera-1 - widget-1 - widget-background-1