Soya/Python base 6
< Soya
# -*- indent-tabs-mode: t -*-
# Soya 3D tutorial
# Copyright (C) 2004 Jean-Baptiste LAMY
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# base 6 : gestion des évenements, controler la chenille avec la souris
# Nous allons voir comment contrôler la chenille avec la souris.
# Importation des modules.
import sys, os, os.path, soya, soya.sdlconst
soya.init()
soya.path.append(os.path.join(os.path.dirname(sys.argv[0]), "data"))
# Création d'une scène.
scene = soya.World()
# La classe CaterpillarHead est similaire à celle du tutorial précédent.
class CaterpillarHead(soya.Body):
def __init__(self, parent):
soya.Body.__init__(self, parent, soya.Model.get("caterpillar_head"))
self.speed = soya.Vector(self, 0.0, 0.0, 0.0)
self.rotation_y_speed = 0.0
self.mouse_x = 0
self.mouse_y = 0
def begin_round(self):
soya.Body.begin_round(self)
# Boucle pour tous les évenements Soya / SDL.
for event in soya.process_event():
# Verification des évenements de la souris, et conservation des coordonnées X et Y du curseur.
if event[0] == soya.sdlconst.MOUSEMOTION:
self.mouse_x = event[1]
self.mouse_y = event[2]
# Le calcul des coordonnées de la souris est en 3D, Camera.coord2d_to_3d renvoie les coordonnées X et Y d'une souris en 2D
# et une coordonnée optionnel Z (puisqu'il ne peut pas bien le gérer, la valeur de Z par défaut est -1.0).
# Maintenant, nous utilisons pour Z les coordonnées Z de la chenille dans les coordonnées du système de la caméra :
# nous considérons que le curseur est à la même hauteur que la chenille.
# l'opérateur % est utilisé pour la conversion des coordonnées :
# position % coordinate_system
# retourne la position convertie dans coordinate_system (possibly position itself if it
# is already in the right coordinate system).
mouse_pos = camera.coord2d_to_3d(self.mouse_x, self.mouse_y, (self % camera).z)
# Alors ca convertit la position de la souris en système de coordonnées pour la scène, et met les
# coordonnées de Y à 0.0, car nous ne voulons pas d'une chenille qui vole
# (souvenez vous que Y est l'axe de la hauteur).
mouse_pos.convert_to(scene)
mouse_pos.y = 0.0
# Calcul de la vitesse de coordonnée Z ; nous ne voulons pas une vitesse constante : plus le curseur est loin
# et plus la chenille va vite.
# Ainsi, la vitesse de coordonnée Z est la distance entre la chenille et la souris, et doit être négative
# (car -Z est vers le haut).
self.speed.z = -self.distance_to(mouse_pos)
# Rotations vers la souris.
self.look_at(mouse_pos)
def advance_time(self, proportion):
soya.Body.advance_time(self, proportion)
self.add_mul_vector(proportion, self.speed)
# Nous changeons CaterpillarPiece, afin qu'il puisse gérer la variable de vitesse du Head.
class CaterpillarPiece(soya.Body):
def __init__(self, parent, previous):
soya.Body.__init__(self, parent, soya.Model.get("caterpillar"))
self.previous = previous
self.speed = soya.Vector(self, 0.0, 0.0, -0.2)
def begin_round(self):
soya.Body.begin_round(self)
# Comme la vitesse peut être très élevée, nous avons besoin de prendre en compte
# la vitesse précédente (celle que l'on avait lors du mouvement).
# On calcule ensuite la future position de la pièce par la translation de la piece
# par le vecteur vitesse de cette même pièce.
previous_next_pos = self.previous + self.previous.speed
# La chenille regarde vers la futur position de la pièce.
self.look_at(previous_next_pos)
# Calcul de la coordonnée Z de vitesse. Nous utilisons un espace entre une pièce et
# sa prochaine position, et nous supprimons 1.5 car nous avons besoin que chaque piece
# soit séparé par une distance de 1.5 unités.
self.speed.z = -(self.distance_to(previous_next_pos) - 1.5)
def advance_time(self, proportion):
soya.Body.advance_time(self, proportion)
self.add_mul_vector(proportion, self.speed)
# Creation du Head de la chenille ainsi que 10 pièces de son corps.
caterpillar_head = CaterpillarHead(scene)
caterpillar_head.rotate_y(90.0)
previous_caterpillar_piece = caterpillar_head
for i in range(10):
previous_caterpillar_piece = CaterpillarPiece(scene, previous_caterpillar_piece)
previous_caterpillar_piece.x = i + 1
# Création d'une lampe.
light = soya.Light(scene)
light.set_xyz(2.0, 5.0, 1.0)
# Création d'une caméra.
camera = soya.Camera(scene)
camera.set_xyz(0.0, 15.0, 15.0)
camera.look_at(caterpillar_head)
soya.set_root_widget(camera)
soya.MainLoop(scene).main_loop()