En fonction du type de jeu et du type d'interactivité, il est possible et parfois même souhaitable d'avoir plusieurs points de vues affichés dans la même fenêtre. Par exemple, lorsque le jeu propose à deux joueurs de s'affronter dans un mode appelé écran partagé ou que nous désirons afficher plusieurs points de vue sur une même scène pour créer des effets graphiques intéressants.
Dans les faits, nous installerons deux caméras dans notre scène avec l'intention d'afficher ces deux points de vue dans la fenêtre principale, qui pour l'occasion sera divisée verticalement en deux parties égales.
Le terme technique qui définit la zone d'affichage du jeu dans l'écran est le viewport. Il n'existe malheureusement pas de logic brick pour activer ces fonctionnalités, nous utiliserons donc un script Python.
Le script peut être activé à partir de n'importe quel objet et doit être exécuté juste une fois : une fois en place les viewport persistent jusqu'à ce qu'ils soit supprimés explicitement. Le script doit désigner les caméras qui se partageront l'écran et définir les zones d'affichage pour chacune.
Voici le script, que nous détaillerons ensuite ligne par ligne.
from bge import logic, render
# Recuperer la scene
scene = logic.getCurrentScene()# Recuperer les cameras a partir de leur nom
cam1 = scene.objects["Camera1"]
cam2 = scene.objects["Camera2"]# Recuperer la taille de la fenetre de jeu
largeur = int(render.getWindowWidth())
hauteur = int(render.getWindowHeight())# Activer le viewport sur la Camera1
cam1.useViewport = True
cam1.setViewport(0, 0, int(largeur/2), hauteur)# Activer le viewport sur la Camera2
cam2.useViewport = True
cam2.setViewport(int(largeur/2), 0, largeur, hauteur)
Après l'import des modules Python nécessaires, nous récupérons la scène dans laquelle se trouve l'objet.
scene = logic.getCurrentScene()
Cet objet scene
nous permet ensuite de récupérer les deux caméras grâce à leurs noms. Dans notre cas, nous avons au préalable choisi d'appeler les caméras Camera1 et Camera2.
cam1 = scene.objects["Camera1"]
cam2 = scene.objects["Camera2"]
Il faut ensuite récupérer la taille de la fenêtre dans laquelle s'affiche le jeu. Que que le joueur soit en plein écran ou pas et que nous ayons défini une taille de fenêtre fixe ou pas, il est préférable de récupérer cette valeur directement par du code Python. C'est une méthode plus souple et plus sûre pour avoir toujours un écran partagé proportionné.
largeur = int(render.getWindowWidth())
hauteur = int(render.getWindowHeight())
Dans l'exercice, nous cherchons à diviser l'écran verticalement en deux parties égales. Camera1 utilise le système de viewport et affiche son point de vue dans un rectangle qui occupe la moitié gauche de l'écran. Camera2 suit le même principe, mais dans la moitié droite.
La méthode setViewport() ne tolère que des nombres entiers dans ses paramètres, c'est-à-dire les mesures en pixel des limites du rectangle dans lequel s'affiche la caméra. Attention, ces paramètres doivent suivre un ordre très précis : gauche, bas, droite, haut. Ce script indique que la première caméra prend toute la moitié gauche de l'écran.
cam1.useViewport = True
cam1.setViewport(0, 0, int(largeur/2), hauteur)
La deuxième caméra remplit l'espace restant.
cam2.useViewport = True cam2.setViewport(int(largeur/2), 0, largeur, hauteur)
En utilisant les valeurs de hauteur et de largeur de notre fenêtre de jeu, nous nous assurons ainsi de remplir tout l'espace de cette même fenêtre.
Voici quelques détails techniques à propos des viewports qu'il est utile de connaître:
setOnTop
qui permet de placer cette caméra au sommet de l'empilement de viewports. En appliquant cette méthode sur toutes les caméras en commençant par celle qui doit être la plus en arrière, nous pouvons forcer un ordre de chevauchement.Pour supprimer un viewport, il suffit de mettre la propriété useViewport
de la caméra correspondante à False
.
Fichier référence : ecran_partage-panda.blend
Le miroir est un cas particulier qui peut être utile par exemple dans le cas d'un jeu de voiture pour simuler un rétroviseur. L'idée est d'afficher le point de vue d'une caméra de la scène comme une texture d'un objet.
Pour cela, nous utiliserons un script Python écrit comme suit :
from bge import texture from bge import logic def createMirror(cont): obj = cont.owner scene = logic.getCurrentScene() observer = scene.objects["Camera"] # Obtention de l'index de la texture initiale ID = texture.materialID(obj, 'IMoriginal.png') # Creation de la nouvelle texture object_texture = texture.Texture(obj, ID) # il faut garder une reference permanente obj.attrDict["tex"] = object_texture # creons le miroir mirror_source = texture.ImageMirror(scene,observer,obj,ID) # changeons la couleur de fond du miroir (RGBA) mirror_source.background = [50,0,0,255] # echange de texture object_texture.source = mirror_source # remplacement dans le GPU object_texture.refresh(True) def runMirror(cont): obj = cont.owner if "tex" in obj.attrDict: # rafraichissons l'image du miroir obj.attrDict["tex"].refresh(True) def removeMirror(cont): obj = cont.owner try: del obj.attrDict["tex"] except: pass
À deux différences près, ce script ressemble beaucoup à celui présenté dans le chapitre Matériaux dynamiques et textures animées de la section Développer l'univers du jeu.
L'objet image est de type ImageMirror :
mirror_source = texture.ImageMirror(scene,observer,obj,ID)
Le constructeur requiert les paramètres suivants :
Il est nécessaire de rafraîchir l'image du miroir fréquemment pour tenir compte du déplacement de l'observateur. Ceci est réalisé par la fonction runMirror
qui doit être exécuté à chaque frame ou chaque fois que l'observateur bouge.
Pour réaliser cet effet miroir, le BGE effectue un rendu spécial à partir d'un point symétriquement opposé à l'observateur par rapport au miroir. Ce rendu est appliqué à l'objet via la texture. Pour que le reflet ne soit pas déformé, il faut que la texture recouvre au mieux la surface de l'objet miroir. Nous obtiendrons ce résultat grâce à la fonction UV mapping > Project from View (Bounds).
Fichier référence : mirroir-panda.blend
Il y a une erreur de communication avec le serveur Booktype. Nous ne savons pas actuellement où est le problème.
Vous devriez rafraîchir la page.