PlayCanvas    

-:|:- www.pastorpixel.de -:|:- Experiment Michael Albers -:|:-

 


PlayCanvas ist eine Online Game Engine. Programmiersprache Javascript. https://playcanvas.com

Veröffentlichung auf verschiedenen Plattformen möglich.

Tutorials bei Youtube / schon etwas älter, aber durchaus hilfreich.

Desweiteren gibt es viele Tutorials und Dokumentationen direkt bei playcanvas

Ansicht / Nutzeroberfläche

Shortcuts

Scrollrad Ansicht vergrößern

Linke Maus Ansicht drehen

Shift Ansicht verschieben

rechte Maus Look around

Pfeiltasten ändern die Ansicht

Alle Entities sind in der Hierachie. Dort kann man sie auswählen.

Augenwerkzeug, setzt das Entity in den Focus

Entity

siehe User Manual

Alle Objekte sind Entities, also Instanzen. Diese kann man mit add Entity zuweisen.
Ein Entity kann vieles sein, ein Würfel, eine Figur oder einfach ein Punkt im Raum.

Entities erben einen Großteil ihrer Eigenschaften von pc.GraphNode. Alle Manipulationen kann man auch über pc.GraphNode programmieren. Über die lokale Transform Matrix kann man die Position, Orientierung und Größe des Entity und all seiner Child Entities bestimmen. Um das zu beherrschen muss man verstehen, dass es ein globales und lokales Koordinatensystem gibt.

World Coordinate System / Local Coordinate System

World Coordinate System
Local Coordinate System

Das World Coordinate System wird von allen Entities geteilt. Sein fester Nullpunkt liegt bei (0,0,0) und es hat eine feste Orientierung, dabei ist (0,1,0) oben. Das Local Coordinate System bezieht sich auf das Entity selbst. Hier liegt der Nullpunkt im Zentrum des Entities selber und die Orientierung folgt der Orientierung des Entities.

Hierachie

Entities sind eine Art pc.GraphNode. Sie werden zusammengefasst in parents und children. Jedes Entity kann ein parent haben und mehrere children. Die child- Entities erben ihre Transformation Information von ihren parents.

Die Word Transformation Matrix eines Entities mulitpliziert die lokale Transformation mit der World Tranformation des parents.

Zum Beispiel wenn ein child die translation (1, 0, 0) besitzt und dessen parent die translation (0, 1, 0) besitzt, so ist die world position des child (1, 1, 0).

Über die Schlüsselwort parent kann man auf das Elternelement zugreifen

parent / children

Über das Schlüsselwort parent, kann man auf das Elternelement zugreifen.

this.entity.parent.setPosition(0,0,0);
		

Auch die Kindelemente lassen sich ansprechen. Dazu gibt es einige Methoden.

find, findByName, findByPath, findByTag

findByName("Name");

Wenn man jedem Entitie einen einmaligen Namen vergibt, kann man ihn über die Methode findByName(String) leicht finden. Die Methode liefert das erste Kindelement diesen Namens. Im folgenden Beispiel wird das Kindelement namens "wheel_front_left" auf der x Achse um 90 Grad gedreht.

this.entity.findByName("wheel_front_left").rotateLocal(90, 0, 0);

 

findByPath("child/subchild")

Nehmen wir an, in einem entity auto befindet sich ein Entity namens "Achse1" und darin befinden sich die beiden Kindelemente "rad1" und "rad2". Über findByPath, kann ich folgendermaßen auf rad1 zugreifen.

this.entity.findByPath("Achse1/rad1").rotateLocal(30,0,0);

Position

		
//Liefert die Position eines Entity relativ zum Koordinatensystem des parent
var lp = this.entity.getLocalPosition();

//Liefert die Position im World Space
var wp = this.entity.getPosition();
		

Es wird eine Methode pc.Vec3([x,y,z]) geliefert. Ein Vektormenge in Form eines Arrays.
Im obigen Beispiel liefert wp.x die X-Position

Das Setzen der Position ist geschieht auf ähnlich, einfache Weise.

//  Die Position relativ zum Koordinatensystem des parent Entity
this.entity.setLocalPosition(x, y, z);

//Die Entity Position im World Space
this.entity.setPosition(x, y, z);			
		     

Bewegung des Entity

Anstatt einen vorhandenen Positionswert zu erhöhen oder zu verringern, kann man auch folgende Hilfsfunktionen nutzen.

// Versetze das Entity eine Einheit herab auf der position X-Achse des World Space.
this.entity.translate(1, 0, 0);

// Versetze das Entity eine Eiheit herauf auf der lokalen z-Achse.
this.entity.translateLocal(0, 0, 1);		
		

 

Orientierung / Drehung

Die Orientierung oder Drehung auf den 3 Achsen kann man auf 2 Arten definieren, Euler Angles oder Quaternions.

Euler Angles

Euler Angles ist die Drehung auf den 3 Achsen x,y,z. Wenn man von oben auf die Achse schaut, ist ein Anstieg des Wertes eine Drehung gegen den Uhrzeigersinn. Einfach zu verstehen und zu nutzen.

 

// Eine Drehung um 30 Grad gegen den Uhrzeigersinn um die x Achse des parent Elements.
entity.setLocalEulerAngles(30, 0, 0);

// Eine Drehung um die x-Achse gegen den Uhrzeiger im World Space
entity.setEulerAngles(30, 45, 60);
		

Quaternions

Quaternions bestimmt die Orientierung aller Achsen im Raum über eine Matrix mit 4 Werten.

// Create an identity rotation
var q = new pc.Quat();
// Die gleiche Rotation wie das parent Element, äquivalent zu
// entity.setLocalEulerAngles(0, 0, 0)
entity.setLocalRotation(q);

// Keine Rotation in Bezug auf den  World- Space, äquivalent zu
//entity.setEulerAngles(0, 0, 0)
entity.setRotation(q);
		

Schrittweise Drehung / increment, decrement

local

this.entity.rotateLocal(90, 0, 0);
	

world space

this.entity.rotate(0, 180, 0);
		

In einer update Funktion

WheelScript.prototype.update = function(dt) {
     this.entity.rotateLocal(0, 0, 40* dt);
}	

Größe Scale

Mit folgender Funktion wird die Höhe des Entity verdoppelt, oder anders ausgedrückt mit 2 multipliziert.

Man kann die Größe nicht über den World Space definieren.

this.entity.setLocalScale(1, 2, 1);

Beispiel Entity, Hierachie Position & Drehwinkel

In diesem geht es darum mit verschachtelten Entities und deren Koordinatensystem zu arbeiten. Es gibt einen Cube und darin einen Cylinder. Der Cylinder ist ein Kind vom Cube und dreht sich ständig um sich selbt. Außerdem bewegt er sich rauf und runter.

Der Cube kann mit den Pfeiltasten rauf und runter bewegt werden. Mit der A- Taste dreht er sich um sich selbst.

Erzeuge ein Primitive Cube durch klicken auf Pluszeichen "Add Entity". Wähle den Cube aus und erzeuge darin auf gleiche Weise ein Primitive Cylinder. Die Position des Cubes sowie des Cylinders im Cube befinden sich auf allen Koordinaten im Nullpunkt. Erzeuge ein Script für den Cube, um diesen mit Tastaurereignis zu bewegen. Pfeiltasten rauf und runter. A- Taste für die Drehung.


// initialize code called once per entity
BoxMover.prototype.initialize = function() {
    
};
 
// update code called every frame
BoxMover.prototype.update = function(dt) {
    
   
    
    if(this.app.keyboard.wasPressed(pc.KEY_UP)){  
    this.entity.translate(0, this.upMove, 0); 
    }
    /*
    wasPressed reagiert auf jeden neuen Tastendruck
    isPressed wird ausgeführt, wenn die die Taste gedrückt ist
    */
    
    if(this.app.keyboard.isPressed(pc.KEY_DOWN)){  
    this.entity.translate(0,-0.04,0); 
    }
    
    
    // is pressed wird ständig ausgeführt, solange die Taste gedrückt ist
    if(this.app.keyboard.isPressed(pc.KEY_A)){  
    this.entity.rotateLocal(0,0, 10); 
    }
 
};
        

Erzeuge ein Script für den Cylinder, um diesen im lokalen Koordinatensytem zu bewegen.

var WheelScript = pc.createScript('wheelScript');

// initialize code called once per entity
WheelScript.prototype.initialize = function() {
    
};

// update code called every frame
WheelScript.prototype.update = function(dt) {
    
    
    this.entity.rotateLocal(0,10, 0); 
    
     lp = this.entity.getLocalPosition();
    
    
    if(lp.y > 1){
        this.entity.setLocalPosition(0,0,0);
    }else{
       this.entity.translateLocal(0, 0.01,0);  
    }
   
};
	    

Components

Diesen Entities kann man Components zuweisen.

Assets

sind Dateien und Elemente die man einem oder mehreren Entities zuweisen kann.

Material

Erstelle ein neues Material Asset und weise diesem Eigenschaften zu. Das können verschiedene UV Maps sein und / oder Farben.

Collision / Rigidbody / Physic

Hierbei geht es darum, dass Objekte physikalische Eigenschaften bekommen. Nehmen wir als Beispiel ein Objekt "Box" und ein Objekt "Ground". Diese erstelle ich mit mittels add Entity box

Beide Objekte bekommen die Komponenten Collision und Rigid Body

Die Collision Komponente dient dazu eine Form zu definieren, die ein Ereignis auslöst, wenn eine Berührung stattfindet. Dabei wird unterschieden zwischen Ein - und Austritt der Berührung oder Überschneidung. Im Zusammenhang mit der Rigidbody Komponente lassen sich so physikalische Simulationen erstellen.

  • Box soll ein Objekt sein, welches auf den Boden fällt, daher bekommt es die Rigid Body Eigenschaft Dynamic

Static bedeutet, es bewegt sich nicht, diese Eigenschaft kann man dem Ground zuweisen, denn dieser sollte nicht fallen.

  • Static es bewegt sich nicht
  • Dynamic es bewegt aufgrund von Schwerkraft und aufgrund anderer Kräfte
  • Kinematic Bewegung durch Positionierung oder Geschwindigkeit

Beide Objekte benötigen eine Collision Komponente. Dort wird unter type ein ein Vekorobjekt ausgewählt welches die Kollisionsgrenzen definiert. Cube, Sphere, Capsule, Mesh. Man weist diesem die halbe Größe des Originalobjekts zu, wenn es genauso groß sein soll.

Rigid Body

  • Mass Masse, spezifisches Gewicht
  • Friction Reibung
  • Restitution Widerstand (Gummiball)

Bewegung Impulse, Force, Torque

Wenn ein Objekt physikalische Eigenschaften bekommt, sollte man nicht einfach die Positionswert und Drehwinkel bestimmen um es zu bewegen.

Beispiel für Forces und Impulses

In diesem Beispiel wird das Objekt im Worldspace in eine Richtung bewegt.

Wenn man jedoch das Objekt in seine eigene Drehrichtung bewegen will, kann man folgendermaßen vorgehen. this.speed ist ein Geschwindigkeitswert, der zuvor definiert wurde. Mittels applyTorque(x,y,z) wird ein Drehimpuls definiert.

DriveCar.prototype.update = function(dt) {  
    
//alternative Syntax für die Bewegung in Richtung Vorwärts Achse
//this.impulse = new pc.Vec3();
//this.impulse.copy(this.entity.forward).scale(-this.speed);

var backForce = this.entity.forward.clone().scale(this.speed);
var forwardForce = this.entity.forward.clone().scale(-this.speed);

     if(this.app.keyboard.isPressed(pc.KEY_UP)){    
        this.entity.rigidbody.applyImpulse(forwardForce);   
    }
      if(this.app.keyboard.isPressed(pc.KEY_DOWN)){         
              this.entity.rigidbody.applyImpulse(backForce); 
    }  
    
       if(this.app.keyboard.isPressed(pc.KEY_RIGHT)){  
         this.entity.rigidbody.applyTorque(0,-0.2, 0);
    }
    
     if(this.app.keyboard.isPressed(pc.KEY_LEFT)){  
         this.entity.rigidbody.applyTorque(0, 0.2, 0);
     }    
};
		

 

Scripts

In den Beispielen befinden sich Scripte unter Assets. Diese kann man sich anschauen oder Editieren und auch herunterladen, beispielsweise um Sie zu ändern.

Neues Script

Um ein neues Script zu erstellen, reicht es nicht aus, dieses hochzuladen, vielmehr muss ein neues Asset hinzufügen und diesem einen Namen vergeben, der sozusagen als Klassenname fungiert und sich im Grundgerüst eines neuen Scripts wiederfindet.

Script Variablen im Editor / Script Attibutes

siehe Manual

Mittels Script Attributes kann man im Editor Variablenwerte eintragen. So haben auch Nichtprogrammierer die Möglichkeit im Editor Werte zu ändern.

Siehe dazu das User Manual Script Attributes

Im Script wird ganz oben nach der Deklaration der Scriptinstanz

var MyScript = pc.createScript('myScript');

ein Script Attribute erzeugt.

MyScript.attributes.add('speed', { type: 'number', default: 80 });

Auf die hier erzeugte Variable speed kann man dann im weiteren Code mit this.speed zugreifen.

Wenn man anschließend im Editor im Scriptfenster auf das Parse-Symbol klickt (Loop Pfeil), sollte die Variable erscheinen.

Entity Attribute / Verbindung zwischen Entities

Über die Script Attribute kann man auf ein anderes Entity zugreifen

MyScript.attributes.add('target', { type: 'entity' })

Tastaturbefehle

 

Bewegungen und Rotationen

Manipulating Entities

Drehungen und Impulse

Szenenwechsel

Das Script für einen Szenenwechsel weist man einer Kamera zu.
Siehe dazu Chaning Scenes

Math

radians to degree

Radians in Winkel pc.math.DEG_TO_RAD

Winkel in Radians pc.math.RAD_TO_DEG

Beispiel 90 Grad in Radians umwandeln.

this.angelRad = 90 * pc.math.DEG_TO_RAD;

Lineare Interpolation

pc.math.lerp(a,b,alpha);

Hiermit lässt sich ein Wert zwischen a und b ermitteln. Mittels alpha gibt man an, wo der Wert liegt. alpha erwartet einen Wert von 0 bis 1, dabei ist 0 = a und 1 = b und 0.5 läge genau in er Mitte zwischen a und b.

pc.math.lerp(0, 20, 0.5) // 10

Lineare Interpolation zwischen 2 Winkeln

lerpAngle(a, b, alpha)

 

Modelle Importieren

dae von Scetchup

Wähle das Objekt in Sketchup aus und wähle Bearbeiten / Entsperren. Entferne alle ungewünschten Elemente. Bei Häusern auch den Boden.

Exportiere ein Modell in Scetchup als dae Datei. Es entsteht eine dae Datei und ein Ordner mit Bildern.

Erstelle dir einen neuen Ordner im Assets Ordner für das Modell. Wähle den Ordner aus, und importiere die dae Datei. In diesem Ordner erscheint eine dae Datei sowie eine json Datei und einige Materialien. Den Materiealien sind keine Bilder zugewiesen, das muss händisch gemacht werden.

Importiere dir in den gleichen Ordner alle Bilder, die beim Export von Scetchup entstanden sind. Wähle ein Material aus, wähle im Inspector "Diffuse" und weise das Bild gleichen Namens zu. Verfahre so mit allen anderen Materialien.

Ziehe das json Modell auf die Bühne. Um es für Collision Detection einzurichten, wähle, im Inspector, "Add Component" " Rigid Body" und "Collision". Unter Collision wähle als "type" Eigenschaft "mesh" und weise die entstandene json Datei aus dem Assets Ordner zu.

Cubemap

siehe Manual

Erstelle eine Cubemap (siehe Toast Map), klicke oben auf den Namen deiner Scene, wähle Rendering, Skybox und weise die Cubemap zu.



zur Startseite