Soya/Python base 3

# -*- 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 3 : gestion du temps : un mouvement de sphère aléatoire.
# Dans cette leçon, nous allons créer une sphère qui bougera aléatoirement.
# Vous allez en apprendre plus sur la gestion du temps (seconde partie), ainsi que sur les vecteurs et le 
# système de conversion de coordonées.


# Importation des modules.

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

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

# Création d'une scène.

scene = soya.World()


# Création d'une classe qui gèrera les mouvements aléatoires de la sphère. Nous appellons ça "Head" ou tête car 
# nous allons utiliser un modèle de tête.
# Cette classe a  soya.Body comme classe parente, maintenant nous pouvons avoir un modèle (la tête).
                
class Head(soya.Body):
        
        # Voyons le constructeur de la classe.
        
        def __init__(self, parent):
                
                # Appel du constructeur soya.Body (rappelez vous, l'appel de cette super implémentation
                # est toujours une bonne idée), et utilisation du modèle appelé, 'caterpillar_head'.
                
                soya.Body.__init__(self, parent, soya.Model.get("caterpillar_head"))
                
                # Ajouter un attribut rapide pour notre nouvel objet.
                # La rapidité est un vecteur de l'objet. Un vecteur est un objet mathématique, utilisé pour
                # le calcul ; contrairement à d'autres objets (Lampe, Caméra, Body, World,...) qui ne sont pas 
                # modifiés durant le rendu.
                
                # Un vecteur est défini par un système de 3 coordonnées (X, Y, Z) ; ici la
                # vitesse est défini dans 'self', exemple : le Head, et avec les coordonnées 0.0, 0.0, -0.2.
                # Souvenez vous que dans Soya, la direction -Z est le devant. 
                # Ceci signifie que le vecteur de vitesse est parallèle à la direction de Head 
                # qui a une longueur de 0.2.
                
                self.speed = soya.Vector(self, 0.0, 0.0, -0.2)
                
                # La vitesse de rotation actuelle (sur l'axe Y)
                
                self.rotation_speed = 0.0
                
        # Tel que advance_time, begin_round est appellé par la boucle principale.
        # Mais contrairement à advance_time, begin_round est appellé régulièrement, au début de chaque round
        # ; celui ci recoit un argument non "proportionnel".
        # Les décisions doivent être prises dans le begin_round.
                
        def begin_round(self):
                
                # Appel de la super implémentation.
                
                soya.Body.begin_round(self)
                
                # Calcul de la nouvelle vitesse de rotation : un angle aléatoire entre -25.0 et 25.0 degrés.
                
                self.rotation_speed = random.uniform(-25.0, 25.0)
                
                # La vitesse des vecteurs n'a pas besoin d'être recalculée, tel qu'il est exprimé dans le 
                # système de coordonnées de Head
                # CoordSyst.
                
        # Dans advance_time, nous allons faire un head amélioré.
        
        def advance_time(self, proportion):
                soya.Body.advance_time(self, proportion)
                
                # Execution de la rotation, il faut tenir compte de l'argument de proportion.
                
                self.rotate_y(proportion * self.rotation_speed)
                
                # Déplaçons le Head grâce au vecteur de vitesse.
                # add_mul_vector est identique à self.add_vector(proportion * self.speed), mais plus rapide.
                
                # Le vecteur de vitesse et le Head ne sont pas dans le même système de coordonnées, mais
                # Soya fait automatiquement la conversion nécéssaire.
                
                self.add_mul_vector(proportion, self.speed)


# Création du Head dans la scène.

head = Head(scene)

# Création d'une lampe.

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

# Création d'une camera.

camera = soya.Camera(scene)
soya.set_root_widget(camera)
camera.set_xyz(0.0, 15.0, 15.0)

# On fait en sorte que la caméra montre la position initiale du Head.
# La méthode look_at est une autre méthode de rotation ; ca marche avec n'importe quel objet 3D 
# auquel nous donnons la position (un objet 3D ou un point), ou nous lui donnons une direction (si l'argument est 
# un vecteur).

camera.look_at(head)

#import time; main_loop = soya.MainLoop(scene)
#for i in range(3):
#       for j in range(5):
#               time.sleep(0.1); main_loop.update()
#       soya.render(); soya.screenshot().resize((320, 240)).save(os.path.join(os.path.dirname(sys.argv[0]), "results", os.path.basename(sys.argv[0])[:-3] + "_%s.jpeg" % i))

soya.MainLoop(scene).main_loop()