Manchmal kommt man an einen Punkt, wo es schön wäre, bestimmte Statuseffekte eines Spielers sichtbar zu machen. Besonders die Spiele, welche die Spielfigur aus der Vogel- oder einer isometrischen Perspektive zeigen, profitieren davon.
Ein Beispiel:

Im oben abgebildeten GIF kreisen Symbole um die Spielfigur. Was brauchen wir dafür?
1) Ein geeignetes 3D-Modell mit Textur

Wir generieren ein Objekt in Blender, das im Prinzip nur aus zwei Kreisen besteht. Wichtig ist, dass beide Kreise (auch wenn sie letztendlich weiß sind) unterschiedliche Materialien zugewiesen bekommen:

Im oben abgebildeten Bildschirmfoto wurde ein Material nur zur Veranschaulichung rot eingefärbt. Stellen Sie sicher, dass dieses Material im „Settings“-Bereich des Materials kein Backface-Culling verwendet (siehe eingekreister Bereich). Nur dann kann die KWEngine später ebenfalls Backface-Culling für dieses Modell deaktivieren.
Zusätzlich muss sichergestellt werden, dass die Texturkoordinaten vernünftig „unwrapped“ sind.
Alternativ kann auch einfach dieses fertig exportierte 3D-Modell direkt in der Engine verwendet werden:
https://math.kwengine.de/download/KWFXCircleWide.glb

2) Eine geeignete Klasse für den Effekt erstellen
internal class Aura : GameObject
{
private bool _enabled;
public Aura()
{
this.SetModel("Aura");
this.SetEnabled(true);
}
public void SetEnabled(bool enabled)
{
this._enabled = enabled;
// SetOpacity() wird für beide Teil-Meshes auf 1 gesetzt,
// wenn der aktuelle Status „enabled == true“ ist.
// Der letzte Parameter von SetOpacity() ist optional und
// gibt an, für welchen Teil-Mesh der Befehl gelten soll.
this.SetOpacity(this._enabled ? 1f : 0f, 0);
this.SetOpacity(this._enabled ? 1f : 0f, 1);
}
public override void Act()
{
// Mit dieser Hilfsfunktion kann man einzelne Teile (Meshes) des Modells
// einzeln um die jeweiligen Achsen rotieren lassen. Diese Rotationen
// haben keinen Einfluss auf die Hitbox des Modells.
// - Der erste Parameter gibt an, welches Objekt betrachtet werden soll.
// - Der zweite Parameter ist der Mesh-Index (0 = erster Teil-Mesh)
// - Die Parameter drei bis fünf sind für die Gradwerte der XYZ-Achsen
HelperRotation.SetMeshPreRotationYZX(this, 0, 0, MathF.Sin(WorldTime) * 360f, 0);
HelperRotation.SetMeshPreRotationYZX(this, 1, 0, MathF.Cos(WorldTime) * 360f, 0);
}
}
3) Player-Klasse definieren
internal class Player : GameObject
{
private Aura _aura;
public void SetAura(Aura aura)
{
_aura = aura;
}
public Aura GetAura()
{
return _aura;
}
public override void Act()
{
// Die folgenden Zeilen dienen lediglich einer simplen WASD-Steuerung:
Vector3 movement = Vector3.Zero;
if (Keyboard.IsKeyDown(Keys.A))
movement.X -= 1f;
if (Keyboard.IsKeyDown(Keys.D))
movement.X += 1f;
if (Keyboard.IsKeyDown(Keys.W))
movement.Z -= 1f;
if (Keyboard.IsKeyDown(Keys.S))
movement.Z += 1f;
// Nur wenn durch die Tastatureingaben überhaupt eine Bewegung
// festgelegt wurde, bewege die Spielfigur mit der Geschwindigkeit
// 0.05f in die entsprechende Richtung:
if (movement.LengthSquared > 0)
{
MoveAlongVector(Vector3.NormalizeFast(movement), 0.05f);
}
// Aktualisiert die Aura-Position nach jeder Bewegung, damit sich
// die Aura stets mit der Spielfigur mitbewegt:
UpdateAuraPosition();
}
private void UpdateAuraPosition()
{
if(this._aura != null)
{
// In diesem Beispiel wird die Aura auf der Y-Achse immer etwas
// höher als die Fußposition positioniert, damit sie nicht auf der
// exakt gleichen Höhe wie der Boden ist - dies könnte zu Grafikfehlern
// führen:
this._aura.SetPosition(
this.Position.X,
this.AABBLow + 0.0125f,
this.Position.Z);
}
}
}
4) Die Welt zusammenstellen
Jetzt müssen wir nur noch diese Klassen in einer Beispielwelt erzeugen:
public override void Prepare()
{
// Setzen der Kameraperspektive und Festlegung
// höchster Helligkeit (zu Testzwecken):
SetCameraPosition(0.0f, 1.5f, 3.0f);
SetCameraTarget(0.0f, 0.0f, 0.0f);
SetColorAmbient(1.0f, 1.0f, 1.0f);
// Import des oben verlinkten 3D-Modells:
KWEngine.LoadModel(
"Aura",
"./Models/KWFXCircleWide.glb");
// Erzeugen des Aura-Objekts:
Aura a = new Aura();
a.SetModel("Aura");
a.SetScale(2.0f);
a.SetTexture("./Textures/rune.png", // Setze die Textur für Mesh #0
TextureType.Albedo,
0);
a.SetTexture("./Textures/rune.png", // Setze die Textur für Mesh #1
TextureType.Albedo,
1);
a.SetTextureRepeat(15.0f, 1.0f, 0); // Wähle für beide Meshes geeignete
a.SetTextureRepeat(15.0f, 1.0f, 1); // Werte für die Texturwiederholung
a.SetColorEmissive(1.0f, 0.5f, 0.0f, 1); // Stelle für beide Meshes die Leuchtfarbe ein
a.DisableBackfaceCulling = true; // Rendere auch die Rückseite des Objekts
a.HasTransparencyTexture = true; // Die gesetzte Textur hat Transparenzwerte
AddGameObject(a);
Player player = new Player();
player.SetModel("KWCube");
player.SetPosition(0.0f, 0.0f, 0.0f);
player.SetScale(0.5f, 2.0f, 0.5f);
player.SetAura(a); // Weise der Spielfigur die Aura zu
AddGameObject(player);
}
Et voilà: Fertig ist der gewünschte Effekt!
Sollte die Kameraperspektive so gewählt sein, dass die Kamera die Szene von der Seite statt von oben betrachtet, muss DisableBackfaceCulling wieder auf true gesetzt werden, um Grafikfehler zu vermeiden.

Schreibe einen Kommentar