Soya/Python base 4

Un livre de Wikilivres.
# -*- 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


# basic-4: Gestion du temps : un mouvement aléatoire de chenille.

# Dans cette leçon, nous allons créer une chenille composée d'une tête (Nous avons déjà vu ça 
# dans une précédente leçon ; maintenant vous comprenez pourquoi j'ai appelé ça 'head' (= tête)) 
# et 10 sphères d'un corps. Chaque pièce du corps suit le précédent, ou le head pour
# première pièce.

# Démarrez le tutorial si vous ne comprennez pas ce qu'est la chenille.


# Importation du module de Soya.

import sys, os, os.path, random, soya

soya.init()
soya.path.append(os.path.join(os.path.dirname(sys.argv[0]), "data"))

# Création de la scène.

scene = soya.World()

# CaterpillarHead est la classe pour la tête de la chenille.
# C'est identique à la classe Head de la leçon base 3, excepté le nom de la classe.
# Alors je ne commente pas !

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.2)
                
        def begin_round(self):
                soya.Body.begin_round(self)
                
                self.rotate_y((random.random() - 0.5) * 50.0)
                
        def advance_time(self, proportion):
                soya.Body.advance_time(self, proportion)
                
                self.add_mul_vector(proportion, self.speed)


# Une CaterpillarPiece est une pièce du corps de la chenille.
# Ça suit d'autres objets -- la pièce précédente, ou là tête pour la première.

class CaterpillarPiece(soya.Body):
        
        # Le constructeur prend 2 arguments : le parent et la précédente pièce du corps
        # que nous devons suivre.
        # Similaire à la tête, nous définissons un vecteur de vitesse.
        
        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)
                
                # Nous tournons une pièce de la chenille pour qu'il regarde le morceau précédent.
                
                self.look_at(self.previous)
                
                # La méthode distance_to retourne une distance entre 2 positions.
                # Si nous sommes trop près du morceau précédent du corps, nous paramétrons la vitesse à Z = 0.0,
                # et ainsi la vitesse du vecteur est nulle : cette pièce n'a pas de longs mouvements.
                
                # Sinon, nous remettons la vitesse à Z = -0.2.
                
                if self.distance_to(self.previous) < 1.5: self.speed.z =  0.0
                else:                                     self.speed.z = -0.2
                
        # advance_time est identique a CaterpillarHead.
        
        def advance_time(self, proportion):
                soya.Body.advance_time(self, proportion)
                
                self.add_mul_vector(proportion, self.speed)
                

# Création de la tête de la chenille.

caterpillar_head = CaterpillarHead(scene)
caterpillar_head.rotate_y(90.0)

# Création de 10 pièces de corps de la chenille.

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 de la lampe.

light = soya.Light(scene)
light.set_xyz(2.0, 5.0, 0.0)

# Création de la 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()


# Pour information, la texture de la chenille à été réalisée avec Gimp et le modèle a été généré 
# avec ce code (regardez le tutoriel sur le modelage pour le comprendre) :

# import soya.sphere
# caterpillar_material      = soya.Material(soya.Image.get("chenille.png"))
# caterpillar_head_material = soya.Material(soya.Image.get("chenille_tete.png"))
# caterpillar_material     .filename = "caterpillar"
# caterpillar_head_material.filename = "caterpillar_head"
# caterpillar_material     .save()
# caterpillar_head_material.save()

# caterpillar      = soya.sphere.Sphere(slices = 12, stacks = 12, material = caterpillar_material)
# caterpillar_head = soya.sphere.Sphere(slices = 12, stacks = 12, material = caterpillar_head_material)
# caterpillar_head.scale(1.2, 1.2, 1.2)
# caterpillar     .filename = "caterpillar"
# caterpillar_head.filename = "caterpillar_head"
# caterpillar     .save()
# caterpillar_head.save()








# XXX put this elsewhere

# Lots of Soya methods have also an operator :
#
# Position +  Vector    => Point
# Position += Vector     Position.add_vector(Vector)
# Position >> Position   Position.vector_to (Position) => Vector 
# Position %= CoordSyst  Position.convert_to(CoordSyst)
# Vector   *  float      

# Position +  Vector => Point

# Position += Vector
# Position.add_vector(Vector)
# Translation or vectorial addition (if the Position is a Vector).

# Position >> Position => Vector
# Position.vector_to (Position) => Vector 
# Creates a vector from a strating and an ending position.

# Position %= CoordSyst  Position.convert_to(CoordSyst)
# Vector   *  float