Banner left   Banner center   Banner right

Germanenglish Home · News · Diary · Screenshots · Documentation (Wiki) · Downloads · Guestbook · Forum

Home · Benutzer registrieren · Suchen · Statistik · FAQ · Benutzerliste

Zur Zeit online: keiner ausser dir

 X-Force - Fight For Destiny - Forum —› X-Skript / Developer-Pack —› Kann man Bodeneinsätze auf der Karte bewegen?

Autor Mitteilung
verfasst am: 09.06.2011, 01:41 · Edited by: Aropretim
Registrierdatum: 06.06.2011, 12:20

 Beiträge: 50
Ich würde gern wissen, ob es möglich ist, einen Bodeneinsatz auf dem Geoscape zu verschieben.

Sinn: Ich möchte einen Bodeneinsatz als Eroberungs-/Sabotageeinsatz für ein feindliches, langsam bewegendes Mutterschiff zweckentfremden.

Hier einmal der derzeit komplette Code zum nachvollziehen:
program MothershipSabotage;
var
  DirX, DirY: Integer;  // Richtung, in der das Mutterschiff fliegt
  MothershipMission: TGround;  // Der Bodeneinsatz
  negativeY: boolean;  // Zur Generierung einer Bewegung bei negativer y-Achse
const
  Speed = 20;  // Zur Berechnung
  
function calcY(x, s: integer): integer;  //
var                                      // Satz des Pythagoras
  xQuad, yQuad, sQuad: integer;          // zur Berechnung der
begin                                    // Bewegung auf der
  xQuad := x*x;                          // Y-Achse, anhand der
  sQuad := s*s;                          // Bewegung auf der
  yQuad := sQuad - xQuad;                // X-Achse (x) und der
  result := round(sqrt(yQuad));          // Geschwindigkeit (s)
end;

procedure MoveMothership(Sender: TObject);
begin
  MothershipMission.Position.x := MothershipMission.Position.x + DirX;  // Bewegung auf der X-Achse
  MothershipMission.Position.y := MothershipMission.Position.y + DirY;  // Bewegung auf der Y-Achse
  DirX := DirX + random(5)-2;   // Das Mutterschiff
  if (DirX > Speed) then
  begin
    DirX := Speed - (DirX-Speed);  // Falls mehr als [Speed] Schritte auf der X-Achse gemacht werden
    if (negativeY) then            // werden die überschüssigen Schritte von [Speed] abgezogen
      negativeY := false           //
    else                           // und die Negierung der Y-Achse "getoggled"
      negativeY := true;           //
  end
  else if (DirX < -Speed) then
  begin
    DirX := -Speed - (DirX+Speed);
    if (negativeY) then
      negativeY := false           // Selbiges auch wenn mehr als [Speed] Schritte "rückwärts"
    else                           // auf der X-Achse gemacht werden
      negativeY := true;
  end;
  DirY := calcY(DirX, Speed);
  if (negativeY) then              // Berechnung der nächsten Bewegung auf der Y-Achse
    DirY := DirY * -1;
  register_timed_event(@MoveMothership,nil,1);
end;

procedure StartMission;
var
  temp: integer;
begin
  MothershipMission := ground_api_generateGround;       // erzeugt einen Bodeneinsatz
  MothershipMission.AddAlien(alien_api_GetRandomAlien); // ein zufälliges Alien zum Bodeneinsatz hinzufügen
  MothershipMission.MapName := 'data\maps\aropretim\mothership.m3d';
  MothershipMission.Position.x := 0;  // zu Testzwecken
  MothershipMission.Position.y := 0;  // zu Testzwecken
  MothershipMission.Show;
  temp := random(1);           // Zufallsgenerator für
  if (temp=1) then             // eine evtl negative
    negativeY := true;         // Bewegung auf der Y-Achse
  DirX := random(Speed*2+1)-Speed;       // Zufallsgenerator für die Bewegung auf der X-Achse
  DirY := calcY(DirX, Speed);  // Berechnung der Y-Achse
  if (negativeY) then
    DirY := DirY * -1;         // Bei negativeY Y-Achse negieren
  register_timed_event(@MoveMothership,nil,1);  // Damit sich das Mutterschiff minütlich bewegt (s.o.)
end;

begin
  MissionName := 'MothershipSabotage';
  MissionType := mzUser;
end.
etwaige Formfehler seien mir zu verzeihen. Hab erst vor einigen Tagen wieder mit Programmieren angefangen.

Lässt sich da was machen oder muss ich das Mutterschiff landen lassen?
verfasst am: 09.06.2011, 02:28 · Edited by: Natter
Programmierer, allgemeines

Registrierdatum: 06.06.2004, 17:19

 Beiträge: 3186
Was klappt denn nicht? Übrigens kannst du ein Event automatisch wiederholen lassen, indem du beim Aufruf register_timed_event(...).repeated:=true; setzt (falls ich das gerade richtig im Kopf habe, ansonsten nochmal nachfragen).
verfasst am: 09.06.2011, 09:50
Admin, Spielsatz GalWar

Registrierdatum: 31.08.2005, 21:51

 Beiträge: 5595
Ich habe es zwar noch nicht ausprobiert, aber es sollte klappen (und ich plane schon lange, das selber für etwas anderes auszunutzen).

Allerdings könntest Du bei dem Code oben Probleme mit den Koordinaten bekommen - Du setzt den Bodeneinsatz zu Testzwecken genau auf einen der Pole, und an den Polen sind die Koordinatenverzerrungen am größten. Viele Bewegungen dort kann man nicht mit dem bloßen Auge erkennen, weil die Punkte in der Koordinatenverzerrung auf den Pol fallen und optisch nicht mehr zu unterscheiden sind.

Besser mit Y-Koordinate 90 oder so testen...
verfasst am: 09.06.2011, 10:42 · Edited by: DirkF
Admin, Spielsatz GalWar

Registrierdatum: 31.08.2005, 21:51

 Beiträge: 5595
Zitat: Aropretim
temp := random(1); // Zufallsgenerator für
if (temp=1) then // eine evtl negative
negativeY := true; // Bewegung auf der Y-Achse

das könnte auch noch für Ärger sorgen.
Zum einen bist Du mit der random-Funktion kritisch und eventuell im undefinierten Bereich (die müsste eigendlich immer 0 zurückgeben, temp kann niemals 1 werden).

Zum anderen gibt es auf dem X-Force-Globus keine negativen Koordinaten - wenn Du bei Null startest und eine negative Richtung gehst, dann wird das auf der Y-Achse sowieso ignoriert (südlicher als Südpol geht's nunmal nicht) und bei der X-Achse in einen Überlauf auf 360 führen.


Und kontrolliere mal Deine logik bei den Bedingungen mit den Zusammenhängen zwischen DirX und Speed etc - die Kommentare dort entsprechen nicht dem was programmiert wurde - z.B. ist Speed eine Konstante, von der nie etwas abgezogen werden kann
verfasst am: 10.06.2011, 03:39 · Edited by: Aropretim
Registrierdatum: 06.06.2011, 12:20

 Beiträge: 50
Zitat: Natter
Was klappt denn nicht? Übrigens kannst du ein Event automatisch wiederholen lassen, indem du beim Aufruf register_timed_event(...).repeated:=true; setzt (falls ich das gerade richtig im Kopf habe, ansonsten nochmal nachfragen).

Also zunächst einmal erscheint der Einsatz bei jedem Ingame-Test woanders, egal welche Koordinaten ich zum Testen nehme. Hinzu kommt, dass sich dieser Einsatz leider nicht bewegt.

Wenn ich das Script im Debug-Modus ausführe fällt mir folgendes auf:
1) MothershipMission.Position enthält den Wert "Unknown Identifier"
2) MothershipMission.Country wird bei jedem Einsatz zufällig gewählt.

Das repeated:=true habe ich in der Referenz nicht gefunden. Werde ich aber testen. Danke :)

Edit:
Eben getestet und funktioniert.


Zitat: DirkF
Allerdings könntest Du bei dem Code oben Probleme mit den Koordinaten bekommen - Du setzt den Bodeneinsatz zu Testzwecken genau auf einen der Pole, und an den Polen sind die Koordinatenverzerrungen am größten. Viele Bewegungen dort kann man nicht mit dem bloßen Auge erkennen, weil die Punkte in der Koordinatenverzerrung auf den Pol fallen und optisch nicht mehr zu unterscheiden sind.

Zitat: DirkF
Zum anderen gibt es auf dem X-Force-Globus keine negativen Koordinaten - wenn Du bei Null startest und eine negative Richtung gehst, dann wird das auf der Y-Achse sowieso ignoriert (südlicher als Südpol geht's nunmal nicht) und bei der X-Achse in einen Überlauf auf 360 führen.


Was das angeht, weiß ich nicht, wie die Koordinaten aufgebaut sind. Dachte eigentlich dass ich das mit ein paar Tests herausfinden würde. Natürlich werde ich dann die Fälle mit negativen Koordinaten und überlauf auffangen und verarbeiten.

Zitat: DirkF
das könnte auch noch für Ärger sorgen.
Zum einen bist Du mit der random-Funktion kritisch und eventuell im undefinierten Bereich (die müsste eigendlich immer 0 zurückgeben, temp kann niemals 1 werden).

Stimmt, da hat sich ein Fehler eingeschlichen. Danke :)

Zitat: DirkF
Und kontrolliere mal Deine logik bei den Bedingungen mit den Zusammenhängen zwischen DirX und Speed etc - die Kommentare dort entsprechen nicht dem was programmiert wurde - z.B. ist Speed eine Konstante, von der nie etwas abgezogen werden kann

Ich wüsste nicht, wo da ein Fehler drin stecken sollte. Natürlich wird die Konstante Speed nie verändert (sonst wär sie ja nicht konstant). ;)
Jedoch kann man eine Zahl davon abziehen, sofern mit dem neuen Wert eine Variable überschrieben wird. Meine Idee war die: Speed entspricht die Entfernung, die der Einsatz (Mutterschiff) pro Minute zurücklegen kann. den Einsatz kann man ja nicht drehen und vorwärts fliegen lassen, also musste ich mir dafür was anderes einfallen lassen - den Satz des Pythagoras (Rechtwinkliges Dreieck, Katheten, Hypothenuse, usw.). Die Entfernung (Hypothenuse) ist die Konstante Speed, während DirX und DirY die beiden Katheten darstellen. DirX und DirY entsprechen also nicht der neuen Position, sondern nur die Richtung, in der das Mutterschiff fliegt. Damit das Mutterschiff nicht nur geradeaus fliegt wird DirX jede Minute ein wenig (-2..2) verändert und DirY so berechnet, dass die Entfernung zur neuen Position der Konstante Speed entspricht. Sollte DirX größer als Speed oder kleiner als -Speed werden, so wird die Differenz von Speed subtrahiert:
Im positiven Fall: DirX = Speed-(DirX-Speed)
bsp mit DirX=21 (19+2):
DirX = 20-(21-20) = 20-1 = 19
Im negativen Fall: DirX = -Speed-(DirX+Speed)
bsp mit DirX=-22 (-20-2)
DirX = -20-(-22+20) = -20+2 = -18

Sollte einer der beiden Fälle passieren, nähert sich das Mutterschiff dem anderen Pol (negativeY wird dabei also geswitcht).

Ich kann auch im Nachhinein keinen gröberen Denkfehler darin erkennen. Falls ich aber dennoch einen habe, lasst es mich wissen.


Edit: Ich habe den Fehler in meinem Script gefunden.
TGround.Position.x und TGround.Position.y kann man nicht ohne weiteres einfach ändern. Mann muss erst eine Variable vom Typ TFloatPoint erstellen und damit dann TGround.Position überschreiben.
Logikfehler habe ich noch 2 entdeckt: Zum einen bewegt sich das Mutterschiff viel zu schnell. Lässt sich aber ganz leicht runterschrauben, indem ich die Konstante Speed verringer.
Zum Anderen bewegt sich das Mutterschiff entlang der X-Achse in Pol-Nähe wesentlich langsamer als in Äquator-Nähe. Werd da wohl noch was bearbeiten müssen.
Was mich überrascht hat, ist dass das Mutterschiff einfach über die Pole hinweg geflogen ist, ohne Probleme wegen einem Überlauf zu verursachen.
verfasst am: 10.06.2011, 09:55
Admin, Spielsatz GalWar

Registrierdatum: 31.08.2005, 21:51

 Beiträge: 5595
Zu den Koordinaten:
Rufe einfach den Alphatron-Generator auf. Wenn Du dort mit der Maus zu einem Kartenpunkt gehst, werden die dazu gehörenden Koordinaten unten links eingeblendet. Habe dabei gerade auch festgestellt, dass ich selber die Koordinaten verwechselt habe - 0 ist der Nordpol, und es wird nach unten hochgezählt.

Zu Speed/DirX:
Da war eine sprachliche Ungenauigkeit schuld an dem Mißverständnis.
Von Speed selber kann man nichts abziehen, denn dann würde man ja die Konstante verändern. Du benutzt die Konstante Speed dagegen, um Abzüge von anderen Variablen zu berechnen.

Oder mit anderen Worten: der Programmcode ist schon richtig, nur die Beschreibung was dort gemacht wird ist ungenau. Und ich hatte keine Zeit um den Code genauer zu analysieren und festzustellen, ob Du den Code oder nur die Beschreibung was dort gemacht werden soll falsch hattest.

Zitat: Aropretim
Das repeated:=true habe ich in der Referenz nicht gefunden. Werde ich aber testen. Danke :)

XSkriptReferenz.TypTTimerEvent
XSkriptReferenz.Registertimedevent

Die Registerfunktion erzeugt eine Variable vom Typ TTimerEvent - wenn dieses wie in Deinem Fall nicht benannt und festgehalten wird, dann wird es nur intern gespeichert und verfällt erst bei Speicherbereinigungen, während jeder erneute Aufruf der Registerfunktion eine neue Variable erzeugt.

Wenn das Event häufiger benötigt wird, dann sollte man eine Variable erzeugen und das Event darin speichern, z.B.
MothershipEvent:=Register_timed_Event(...);

Die von Natter vorgeschlagene Variante ist eine Mischfunktion, bei der man einmalig bei der Erstellung eine der Teilvariablen des Events ändern kann. Nachträglich kann man dann keine Änderungen mehr vornehmen.

Um mehrere der Teilvariablen zu ändern oder z.B. das Repeated nachträglich ein- und ausschalten zu können, muss man das erzeugte Event ausdrücklich bei der Erzeugung einer Variable zuweisen.
verfasst am: 10.06.2011, 15:43
Registrierdatum: 06.06.2011, 12:20

 Beiträge: 50
Mein ursprüngliches Script erzeugte also pro Ingame-Minute eine neue Variable vom Typ TTimerEvent. Muss mal probieren meine 4GB-RAM voll zu kriegen. :D

Sehe ich das richtig, dass man mit TTimerEvent.CalledScript auch Prozeduren aus anderen Scripts ansprechen kann? Oder wird damit das ganze Script gestartet?
verfasst am: 10.06.2011, 16:49
Admin, Spielsatz GalWar

Registrierdatum: 31.08.2005, 21:51

 Beiträge: 5595
calledscript ist read-Only, das geht nicht.

Für den Aufruf von Prozeduren in anderen Skripten siehe:
XSkriptReferenz.MissionapiStartScript

XSkriptReferenz.MissionapiStartScriptWithObject

XSkriptReferenz.TypTMission

Der GalWar-Spielsatz enthält in seiner letzten (leider defekten) Version aus 0.915 Beispiele, wie man das CallProzedure aus dem dritten Link zum wechselseitigen Aufruf und Datenaustausch zwischen laufenden Skripten benutzt.
(Diese Beispiele funktionieren, die Skriptfehler liegen an einer anderen Stelle)



Du musst dich registrieren um auf dieses Thema zu antworten.
Login :: » Name » Passwort

Ladezeit (sec.): 0.015 · Powered by miniBB 1.6 with parts of 1.7 © 2001-2003