Beispiele: Draw3D

Weltkoordinaten sind nicht besonders aussagekräftig. Diese Paket soll dabei helfen und ermöglicht es, Weltkoordinaten in Form von Linien, Kugeln (als Kreise), Boundingboxen und orientierten Boundingboxen im dreidimensionalen Raum zu visualisieren.

Luftlinie zu einem NPC veranschaulichen

Um eine Linie zwischen zwei NPCs zu spannen, benötigt man nur die Koordinaten der beiden NPCs.
func void Example_1() {
// Koordinaten der Charaktere holen
var zCVob her; her = Hlp_GetNpc(hero);
var int punkt1[3];
punkt1[0] = her.trafoObjToWorld[3];
punkt1[1] = her.trafoObjToWorld[7];
punkt1[2] = her.trafoObjToWorld[11];

var zCVob oth; oth = Hlp_GetNpc(PC_ThiefOW);
var int punkt2[3];
punkt2[0] = oth.trafoObjToWorld[3];
punkt2[1] = oth.trafoObjToWorld[7];
punkt2[2] = oth.trafoObjToWorld[11];

// Handle der Linie
var int hndl;

// Beim ersten Aufruf muss die Linie erst einmal erstellt werden
if (!Hlp_IsValidHandle(hndl)) {
// Die Farbe wird als zCOLOR übergeben
hndl = DrawLine(_@(punkt1), _@(punkt2), zCOLOR_GREEN);
} else {
// Existiert die Linie schon, brauchen nur die Endpunkte anhand des Handles aktualisiert werden
UpdateLine(hndl, _@(punkt1), _@(punkt2));
};
};
Diese Funktion kann man nun per FrameFunction kontinuierlich aufrufen, um die Luftlinie immer den Positionen der Charaktere anzupassen.FF_Apply(Example_1);
Alternativ, kann man die Funktion auch so schreiben:
func void Example_1() {
var zCVob her; her = Hlp_GetNpc(hero);
var zCVob oth; oth = Hlp_GetNpc(PC_ThiefOW);

var int hndl;

// Beim ersten Aufruf muss die Linie erst einmal erstellt werden
if (!Hlp_IsValidHandle(hndl)) {
// Die Koordinaten einzeln übergeben mit der Funktion DrawLine3
hndl = DrawLine3(her.trafoObjToWorld[3], her.trafoObjToWorld[7], her.trafoObjToWorld[11],
oth.trafoObjToWorld[3], oth.trafoObjToWorld[7], oth.trafoObjToWorld[11],
zCOLOR_GREEN);
} else {
// Die selbe Methode gibt es auch fürs Aktualisieren
UpdateLine3(hndl, her.trafoObjToWorld[3], her.trafoObjToWorld[7], her.trafoObjToWorld[11],
oth.trafoObjToWorld[3], oth.trafoObjToWorld[7], oth.trafoObjToWorld[11]);
};
};

Einen Abstand von 5 Metern visualisieren

Interessanter wird es, wenn es um "abstraktere" Koordinaten geht. So kann man z.B. mit einer Boundingbox (oder auch einer Kugel) einen "Sicherheitsabstand" um den Spieler visualisieren, um Reaktionen der KI auf bestimmte Entfernungen zu überprüfungen.
func void Example_2() {
var zCVob her; her = Hlp_GetNpc(hero);

// Sicherheitsabstand um den Spieler (5 Meter)
var int abstand; abstand = mkf(500);

// Untere Ecke der Boundingbox
var int punkt1[3];
punkt1[0] = subf(her.trafoObjToWorld[3], abstand);
punkt1[1] = subf(her.trafoObjToWorld[7], abstand);
punkt1[2] = subf(her.trafoObjToWorld[11], abstand);

// Obere Ecke der Boundingbox (diagonal gegenüber)
var int punkt2[3];
punkt2[0] = addf(her.trafoObjToWorld[3], abstand);
punkt2[1] = addf(her.trafoObjToWorld[7], abstand);
punkt2[2] = addf(her.trafoObjToWorld[11], abstand);

var int hndl;

if (!Hlp_IsValidHandle(hndl)) {
hndl = DrawBBox(_@(punkt1), _@(punkt2), zCOLOR_BLUE);
} else {
UpdateBBox(hndl, _@(punkt1), _@(punkt2));
};
};
Ebenso könnte man hier die Boundingbox mit einer FrameFunction kontinuierlich aktualisieren.

Farbe ändern oder Draw-Element verstecken/löschen

Möchte man nun beispielsweise eine Reaktion der KI visualisieren, kann man die Farbe ändern. Farbwerte lassen sich mit der Funktion RGBA anhand der RGB-Werte erstellen.func void ObserveIntruder(var int hndl, var C_NPC oth) {
if (Npc_HasDetectedNpc(oth, hero)) {
// Farbe ist nun rot, Position und Größe der Boundingbox bleiben unverändert
SetBBoxColor(hndl, zCOLOR_RED); // zCOLOR_RED == RGBA(255, 0, 0, 255)
};
};

Auch lassen sich die Draw-Element leicht verstecken oder komplett löschen.
func void CheckDialog(var int hndl) {
if (!InfoManager_HasFinished()) {
// Boundingbox während Dialogen verstecken
HideBBox(hndl);

// EraseBBox(hndl); // Oder inklusive des Handles löschen
};
};