Ein Forum, in dem sich neue Clonk Entwickler untereinander austauschen können.
 
StartseiteStartseite  PortalPortal  FAQFAQ  SuchenSuchen  AnmeldenAnmelden  MitgliederMitglieder  LoginLogin  

Austausch | 
 

 Flinti Tutorial 2.1: Von pCmdTarget und idCmdTarget, globalen Effekten und Fx*Stop

Vorheriges Thema anzeigen Nächstes Thema anzeigen Nach unten 
AutorNachricht
Flinti
Kadett
Kadett


Männlich Alter : 24
Anmeldedatum : 07.04.09

BeitragThema: Flinti Tutorial 2.1: Von pCmdTarget und idCmdTarget, globalen Effekten und Fx*Stop   Mo Nov 09, 2009 1:38 pm

Willkommen zu meinem zweiten Tutorial über Effekte. Ihr erwartet jetzt sicherlich ein Tutorial über Zauber, aber ich schiebe erstmal noch ein Tutorial über allgemeine Grundlagen der Effekte dazwischen. Dieses Tutorial ist sehr komplex, daher habe ich mich entschieden, Beispielobjekte zu erstellen. Auch ist es wieder nur der erste Teil eines großen Tutorials, da dieses Tutorial einmal "sacken" muss, weil es so komplex ist, und weil ich aus Zeitgründen nicht das vollständige Tutorial fertigstellen kann und ich euch nicht zu lange(bzw ist es ja schon zu lange) vorenthalten möchte. Seht dieses Tutorial als das erste Kapitel eines großen Tutorials. Sollte auch nur der klitzekleinste Problem bestehen, bitte ich nachzufragen, damit ich Unklarheiten schnell beseitigen kann. Irgendwelche Morddrohungen oder Lobgesänge sind hier fehl am Platz Wink

GRUNDVORAUSSETZUNGEN:
-Evtl.: Effekte als Timer
-Funktionsdefinition und -aufruf, Rückgabewerte
-bestenfalls Schleifen (for, for in)
-Objektdefinition vs Objektinstanz
-und natürlich: #STRICT 2!

(Ich verwende Variablen- bzw. Parameternamen als Synonyme für das, was sie bedeuten; so steht idCmdTarget z.B. für eine dort angegebene ID und dementsprechend auch für die damit verbundene Definition)

Einer der größten Vorteile der Effekte ist, dass Effekte theoretisch vollkommen Objektunabhängig sind. Einmal erzeugt, sind sie, falls gewünscht, vollkommen von der Existenz des erzeugenden Objektes unabhängig(genauer: Von der Existenz der Objektinstanz). Selbstverständlich können sie aber auch abhängig vom erzeugenden Objekt sein, falls gewünscht, und sind dann immer noch praktischer als Aktionen, da ein Objekt nahezu unendlich Effekte erhalten kann. Betrachten wir dazu folgende Beispiele, jeweils ein Partikelkreis-Flint, der um alle Objekte im Partikelkreisradius einen Partikelkreis zeichnet, und dies 3 mal im Abstand von 10 Frames:



1. Objekt, Partikelkreisflint mit objektabhängigem Effekt:

Code:

#strict 2


public func Hit()
{
   DrawParticleCircle(this, 70, RGB(0, 255));
   for(var obj in FindObjects(Find_Distance(70), Find_NoContainer(), Find_Exclude(this)))
      AddEffect("IntParticleRing", obj, 1, 90, this, 0);
}

public func DrawParticleCircle(object pTarget, int iRadius, int iClr)
{
   for(var i=1; i <= 360; i+=2)
      pTarget->CreateParticle("NoGravSpark", Cos(i, iRadius), Sin(i, iRadius), 0, 0, 50, iClr, pTarget);
}

protected func FxIntParticleRingTimer(object pTarget, int iEffectNumber, int iEffectTime)
{
   if(iEffectTime > 90*3)
      return -1;
   
   DrawParticleCircle(pTarget, 20, RGB(255));
}


2. Objekt, Partikelkreisflint mit objektunabhängigem Effekt:

Code:

#strict 2


public func Hit()
{
   DrawParticleCircle(this, 70, RGB(0, 255));
   for(var obj in FindObjects(Find_Distance(70), Find_NoContainer(), Find_Exclude(this)))
      AddEffect("IntParticleRing", obj, 1, 90, 0, GetID());
}

public func DrawParticleCircle(object pTarget, int iRadius, int iClr)
{
   for(var i=1; i <= 360; i+=2)
      pTarget->CreateParticle("NoGravSpark", Cos(i, iRadius), Sin(i, iRadius), 0, 0, 50, iClr, pTarget);
}

protected func FxIntParticleRingTimer(object pTarget, int iEffectNumber, int iEffectTime)
{
   if(iEffectTime > 90*3)
      return -1;
   
   DrawParticleCircle(pTarget, 20, RGB(255));
}


probiert beide Flints aus. Ihr werdet keinen Unterschied in der Funktionsweise bemerken. Fügt nun aber am Ende der Hit-Funktion ein 'RemoveObject();' hinzu; sonst wäre das ganze ja auch kein Flint. Bemerkt ihr jetzt den Unterschied?

Überlegt mal, woran das wohl liegen könnte. Solltet ihr nicht darauf kommen: Die Lösung kommt später!


Im letzten Tutorial hatte ich die Parameter von AddEffect erwähnt. Dies waren aber noch nicht alle. Seht nun das:

AddEffect (string szEffectName, object pTarget, int iPrio, int iTimerIntervall, object pCmdTarget, id idCmdTarget, any var1, any var2, any var3, any var4)


...die ersten Parameter sind und natürlich bereits geläufig(oder werden uns vom C4-scripter angezeigt Very Happy)

idCmdTarget: Bestimmt das Objekt, in dem die Fx*-Funktionen aufgerufen werden sollen. Diesmal allerdings als ID, sodass die Funktionen so ausgeführt werden, als wäre das Objekt gar nicht da. Das heißt, man kann dann nicht auf lokale Variablen zugreifen oder 'this' benutzen.

Die restlichen Parameter sind vorerst noch unwichtig.


Ihr bemerkt, dass der Parameter 'idCmdTarget' anstatt 'pCmdTarget' benutzt wurde. Genau das ist der Unterschied. Einzig und allein dieser Parameterwechsel. Ist nämlich 'pCmdTarget' angegeben, wird der Effekt entfernt, wenn pCmdTarget gelöscht wird(wo sollen auch die Funktionen aufgerufen werden, wenn das Funktionszielobjekt nicht mal mehr existiert? =O), der Timer wird nicht mehr aufgerufen. Natürlich wird der Effekt auch gelöscht, wenn pTarget gelöscht wird (oder stirbt) ist, denn was soll der Effekt dann ohne Zielobjekt? Dies kann man zu seinem Vorteil nutzen: Es gibt eine spezielle Effektfunktion, die beim Löschen des Effektes aufgerufen wird, Fx*Stop. Erweitern wir also das script der beiden Flints um einen Fx*Stop-Callback, sodass jedes Objekt nach dem Erzeugen der Partikelkreise einen Feuerwerksstein abschießt(dieser funktioniert auch wieder mithilfe eines Effektes, dessen AddEffect-Parameter euch sicherlich leicht verwirren):

Code:

protected func FxIntParticleRingStop(object pTarget, int iEffectNumber, int iReason, bool fTemp)
{
   var rock = CreateContents(ROCK, pTarget);
   AddEffect("IntFireworkRock", rock, 1, 1, 0, 0);
   pTarget->Exit(rock, 0, 0, Random(360), RandomX(-2,2), -12);
}

// Zusätzlich Beispiel für globale Effekte
global func FxIntFireworkRockTimer(object pTarget, int iEffectNumber, int iEffectTime)
{
   if(iEffectTime > 30)
      return -1;
   pTarget->CastParticles("SparkL", 4, 2, RandomX(-1,1), RandomX(-1,1), 7*5, 9*5, RGB(255), RGB(255), pTarget);
}

//Die Parameter iReason und fTemp werden später erklärt, da sie für die absoluten Grundlagen unwichtig sind
global func FxIntFireworkRockStop(object pTarget, int iEffectNumber, int iReason, bool fTemp)
{
   pTarget->Explode(10);
}

Zusätzlich seht ihr globale Fx*-Funktionen. Solche Funktionen werden aufgerufen, wenn sowohl idCmdTarget als auch pCmdTarget 0 sind(Also ist der Effekt keinem Objekt zugeordnet, sondern halt einfach global). Jedes Objekt, sowie das Szenarioscript(sowie natürlich die Engine-Konsole), kann also einen Effekt, der global ist, erzeugen. Es reicht also, wenn ihr in einem der Beiden Beispielflints die globalen Funktionen für den Feuerwerksstein angebt, und in dem anderen nur den Effekt "IntFireworkRock" erzeugt. Die Beispielflints sind auf genau diesem Stand. Jetzt könnt ihr Beispielsweise auch testen, ob Fx*Stop() aufgerufen wird, wenn pCmdTarget gelöscht wird(Überlegt zuerst aber - kann eine Funktion in einem gelöschten Objekt aufgerufen werden? Wink ).


Aber gehen wir weiter auf idCmdTarget und pCmdTarget ein. Wird pCmdTarget angegeben, werden die Fx*-Funktionen als Object-Calls ausgeführt. Das heißt, dass die Funktionen ganz simpel im angegebenen Objekt ausgeführt werden, wie z.B. Hit. Man kann auf lokale Variablen zugreifen und this verwenden. Wird allerdings idCmdTarget angegeben, werden die Fx*-Funktionen als Definition-Call ausgeführt: Die Funnktionen stehen in dem Objekt, haben aber keinerlei Zugriff auf den this-Zeiger oder lokale Variablen, da sie aufgerufen werden, ohne dass sie irgendeinen Bezug zu einer Objektinstanz hätten, sie haben nur etwas mit der Definition gemeinsam, nämlich dass sie im script der Definition stehen XD.
Der Vorteil von Definition-Calls gegenüber Objekt-Calls liegt auf der Hand: Es interessiert weder die Engine, noch irgendeinen Toten, ob irgendein Objekt vom Typ des idCmdTargets im Szenario existiert (Um es genauer zu sagen: Ob irgendeine Instanz dieses Objektes existiert).


Soweit also zu id- und pCmdTarget, globalen Effekten und (teilweise) Fx*Stop.

Darüberhinaus entschuldige ich mich schonmal für die Rächtschraipfeela. Ich werde sie mit der Zeit beseitigen Smile


-> Tutorial 2.2: Effektvariablen - Effekte als Datenspeicher und Blindeffekte ohne Fx*-Funktionen - sinnlos?
Nach oben Nach unten
Benutzerprofil anzeigen
Flinti
Kadett
Kadett


Männlich Alter : 24
Anmeldedatum : 07.04.09

BeitragThema: Re: Flinti Tutorial 2.1: Von pCmdTarget und idCmdTarget, globalen Effekten und Fx*Stop   Di Nov 10, 2009 3:00 pm

Arg, wie dämlich. Hab doch gleich die Beispiele vergessen. Hier sind sie;:

http://cndg-hochlader.bplaced.net/Partikelflints.c4d



EDIT: Außerdem fällt mir auf, dass manche Grundvoraussetzungen gar nicht in irgendeinem Tutorial behandelt werden - doof :/
Nach oben Nach unten
Benutzerprofil anzeigen
 
Flinti Tutorial 2.1: Von pCmdTarget und idCmdTarget, globalen Effekten und Fx*Stop
Vorheriges Thema anzeigen Nächstes Thema anzeigen Nach oben 
Seite 1 von 1
 Ähnliche Themen
-
» [Tutorial] Wie mache ich ein Backup?
» Tutorial-Forum für forumieren Administratoren.
» [Tutorial] Die Internet Adresse des Forums ändern!
» Forumieren.com Tutorial
» Tutorial | Gründerwechsel - einvernehmlich -

Befugnisse in diesem ForumSie können in diesem Forum nicht antworten
CNDG :: Fortgeschrittene :: Tutorials-
Gehe zu: