nächstgelegenes Ziel anvisieren

Startseite Foren Deutsches LiveCode-Forum nächstgelegenes Ziel anvisieren

Schlagwörter: 

Ansicht von 40 Antwort-Themen
  • Autor
    Beiträge
    • #31374
      akrages
      Teilnehmer

      Hallo und guten Abend.
      Ich versuche mich gerade an einer Art „TowerDefense“ Spiel.
      Gibt es eine Möglichkeit, dem Tower zu sagen, dass er das nächstgelegene Ziel anvisieren soll?
      Und wenn dieses außer Reichweite ist, wieder das nächste Nächstgelegen Ziel… usw.?

    • #31378
      Torsten
      Teilnehmer

      Hi Akrages,

      die Lösung ist: Berechne für jedes Ziel den Abstand zum Turm und sortiere die Liste der Abstände.

      Nehmen wir an, die Namen aller Ziele (z.B. von Grafik-Objekten) sind in einer Liste vorhanden.
      Dann würde ich folgenden Code nehmen:

      put the loc of graphic tTower into tTowerLoc
      repeat for each line tTarget in tTargetList
         put the loc of graphic tTarget into tTargetLoc 
         -- an dieser Stelle kommt der gute alte Pythagoras hervor: a^2 + b^2 = c^2
         -- bitte zunächst selbst versuchen :-)
      end repeat 
      
      sort lines of tDistancesTargetTower numeric ascending

      Falls Du gar nicht weiterkommst, habe ich die Lösung schon mal programmiert, aber ich will Dir den Spass der Auffrischung der Schulmathematik (endlich mal eine sinnvoll Anwendung!) niocht nehmen 🙂

      Happy Coding!
      Torsten

    • #31484
      akrages
      Teilnehmer

      Vielen Dank für den Denkanstoß.
      Habe damit eine für mich gute Lösung gefunden.
      Nun stehe ich vor einer weiteren Herausforderung.
      Ich möchte gerne, dass sich die auf einem definierten Pfad bewegenden „Feinde“ bei einer Richtungsänderung, immer in Laufrichtung drehen.

      Also in etwa so etwas:

         if there is a grp ("TankA" & i) then
            if intersect(grp "TankA1", graphic "Knoten1", "opaque Pixels") then set the angle of img "Tank" of grp "TankA1" to 26 
            ##wait 1 milliseconds with messages
            if the loc of grp "TankA1" = 403,326 then set the angle of img "Tank" of grp "TankA1" to 85
            if the loc of grp "TankA1" = 409,232 then set the angle of img "Tank" of grp "TankA1" to 0
         end if

      Die graphic „Knoten befindet sich also immer an dem Punkt, an dem eine Richtungsänderung stattfindet.
      Das funktioniert zwar ganz gut, hat aber den Nachteil, das ich für derzeit fünf „Feinde“ für jeden Feind alle Knoten in einer neuen Zeile berücksichtigen muss.

      Und da ich mit:

      repeat with i = 1 to 5 ##Die zweite Ziffer ist die Anzahl der Feinde z.B. Ziffer ist 5 = 5 Feinde werden generiert!
            clone grp "TankA" 
            set the name of the last grp to ("TankA" & i)
            set the loc of the last grp to (-30),(383) ##Hier werden die geclonten Feinde plaziert!
            set the visible of the last grp to true
            set the layer of the last grp to 3
            wait .5 seconds with messages
         end repeat

      die fünf „Feinde generiere ist es auch ganz schön umständlich. Vor allem wenn ich später mal mehr als fünf „Feinde“ in das Spiel bringe.

      Hat jemand eine elegantere Idee zur Umsetzung?
      Am besten wäre es, wenn sich oben genannter Code im „Feind“ selber befände.
      Aber das funktioniert leider nicht.

    • #31542
      Torsten
      Teilnehmer

      Hallo akrages,

      ganz generell gesprochen baust Du gerade eine Simulation mit Objekten, die sich alle nach bestimmten Regeln verhalten sollen. In diesem Fall ist es, wie Du schon richtig bemerkt hast, am besten, das Verhalten = Code IM Objekt zu haben.
      Das geht auf zwei Weisen:

      1. Ein Objekt mit dem entsprechenden Objekt-Script erstellen und dieses dann entsprechend klonen.

      2. Das Objekt hat statt eines eigenen Skripts ein Behavior, d.h. es „erbt“ das Skript von einem anderen Objekt (typischerweise ein Button) mit dem Unterschied, dass in diesem Fall das Skript nur einmal existiert und daher auch nur einmal verändert werden muss, falls Du etwas neu machen willst. Auch die schon existierenden Objekte zeigen dann das neue Verhalten, bei 1. müsstest Du erstmal alle alten Objekte löschen und wieder neu klonen.

      Ich denke, die zweite Methode ist deshalb für Deine Zwecke besser geeignet.

      Happy Coding
      Torsten

    • #31544
      Klaus Major
      Verwalter

      Kleiner Tip:

      ...
      repeat with i = 1 to 5
         put ("TankA" & i) into tGruppenName
      
         ## Wir können CLONEN und UMBENENNEN in einem Rutsch!
         clone grp "TankA" AS tGruppenName
         set the loc of grp tGruppenName to (-30),(383)
         set the visible of grp tGruppenName to true
         set the layer of grp tGruppenName to 3
         wait .5 seconds with messages
      end repeat
      ...
    • #31546
      akrages
      Teilnehmer

      Hallo Torsten.

      Zu 1. Ich habe eine sogenannte (Schablonen-Gruppe) als „Feind“. Diese wird bei Spielstart fünfmal geclont. D.h. Die erste Lösung sollte keinen allzugroßen Aufwand bedeuten.
      Bis auf die Umsetzung….

      Die Türme (im Moment ist es, da ich noch am Testen bin nur einer) sollen dann auf die gleiche Weise geclont werden. Wenn sich jetzt das Script in der „Schablone befindet, dann befindet sich ja auch in jedem Clon das selbe Script und somit müsste jeder Turm eigenständig auf nahende „Feinde“ reagieren und deshalb glaube ich, dass das schon eine recht gute Lösung sein könnte.

      Zu 2. Hört sich auch interresant an bliebe vom Aufwand her aber in meinem Fall gleich oder?

      Aber um die erste Lösung umzusetzen brauche ich deine Hilfe.
      Wie muss das Script aussehen, damit der Turm bzw. der Feind auch darauf reagiert?

    • #31596
      Torsten
      Teilnehmer

      Die grundsätzliche Logik hat zwei Teile:

      1. Bewegen der Ziele auf einem festen Pfad / Route
      2. Entscheidung des Turms, ob und welches Ziel er attackiert

      zu 1:

      Eine der simpelsten Möglichkeiten, ein Objekt auf einer Strecke entlang zu bewegen ist:

      move OBJEKT to the points of CURVEDLINE in XX seconds
      OBJEKT = deine Graphic, Image etc.
      CURVEDLINE = eine Polyline, die man mir der Mouse zeichnen kann

      zu 2:

      Die Türme müssen in regelmäßigen Abständen prüfen, ob Feinde in der Nähe sind und wer davon am nähesten ist.
      Dazu brauchst Du die loc vom Turm und die locs der Feinde und musst dann mittels des guten alten Pythagoras die Entfernung von jedem Feind zum Turm bestimmen. Diese Liste wird dann nach Entfernung sortiert und der erste in der Liste ist das Ziel 🙂

      -- Ermittelt die Distanz zwischen zwei Livecode-Locations (deren Format ist ja jeweils x,y z.B. 123,23) mittels Pythagoras: a^2 + b^2 = c^2
      -- die Länge der Hypothenuse ist die Entfernung, da die jeweiligen Abstände der x und y-Werte ein rechtwinkliges Dreieck bilden
      ------------------------------------------------------------------
      function loc_distance pLoc_1, pLoc_2
         
         return round(sqrt(abs(item 1 of pLoc_1 - item 1 of pLoc_2)^2 + abs(item 2 of pLoc_1 - item 2 of pLoc_2)^2),2)
         
      end loc_distance

      Happy Coding
      Torsten

    • #31849
      akrages
      Teilnehmer

      Hallo Torsten.
      Deine Antwort #31542
      1. Ein Objekt mit dem entsprechenden Objekt-Script erstellen und dieses dann entsprechend klonen.

      Wie geht das?
      Also das klonen und plazieren des Turms ist kein Problem.
      das mache ich mit diesem Code:

      global lTowerXplaceOld, lTowerOffPlaceNeu
      global lCloneTowerOff, lCloneTowerOn
      on mouseDown
         put the loc grp "TowerX.png" into lTowerXplaceOld ## Der Loc der Vorlage
         lock screen
         grab me
         set the loc of me to the mouseloc
      unlock screen
      end mouseDown
      
      on mouseUp
         put the mouseloc into lToweOffPlaceNeu
         set the loc of Group "TowerX.png" to lTowerXplaceOld ##Die Vorlage wieder zurück auf ihren Ursprungsloc
         clone grp "TowerOffVorlage"
         add 1 to lCloneTowerOff
         set the name of the last grp to ("TowerOff" & lCloneTowerOff)
         set the loc of last grp to lToweOffPlaceNeu
         
         ##Den Geschützturm clonen.
         clone img "TowerOnVorlage"
         add 1 to lCloneTowerOn
         ##Das geclonte img "TowerOn" in "TowerOn1" umbenennen
         set the name of the last img to ("TowerOn" & lCloneTowerOn) ##img TowerOn heißt jetzt TowerOn1
         
         if there is a img ("TowerOn" & lCloneTowerOn) then 
            ####portiere den geclonten Tower zur entsprechenden Plattform. 
            set the visible of img ("TowerOn" & lCloneTowerOn) to false
            set the loc of img ("TowerOn" & lCloneTowerOn) to lToweOffPlaceNeu
            set the loc of img "Beam" to lToweOffPlaceNeu
            set the loc of img "Beam2" to lToweOffPlaceNeu
            show btn "Start"
         end if
      end mouseUp

      Aber wie muss der Code im Turm aussehen, damit der geclonte Turm dann auch eigenständig reagiert?

    • #31864
      akrages
      Teilnehmer

      Kaum fragt man…

      Habs jetzt rausgefunden.
      Ich habe diesen Code in der „Vorlagen-Gruppe“

      global lCloneTowerOff, lCloneTowerOn, gRadar, gFeuerFrei
      global i, x, z

      on checkLocation  --checks if the tower is in range at stops on the path. this is in the img script
         if there is a grp ("TankA" & i) then
            ##answer "Yes there is a group of Tanks"
            ## Wenn der Feind sich im Erfassungsbereich des Radars des Turms befindet,
            ## dann wird der Turm "ausgefahren" (sichtbar).
            if distance (the loc of grp ("TankA" & i),the loc of me) < gRadar  then
               ##answer "Yes there is a group of Tanks"
               set the visible of img ("TowerOn" & lCloneTowerOn) to true
               TankATarget1  
               
               ## Wenn der Feind sich im Feuerbereich der Türme befindet, dann Feuer frei auf den
               ## nächstgelegenen sichtbaren Feind.
               if distance(the loc of grp ("TankA" & i),the loc of me) < gFeuerFrei then
                  if the visible of grp ("TankA" & i) is true then
                     moveBeam1u2 ##Immo wir nur der letzte Feind beschossen!?
                  end if
               end if
            end if
         end if
      end checkLocation

      und im CardScript folgendes:

      on updateScreen 
         if sGameRunning is true then     
            detectCollisions
      call "checkLocation" of grp "TowerOff1" of cd "Welle_001"
         end if  
      end updateScreen

      Der Turm grp „TowerOff1“ macht jetzt was er soll.
      ABER…

      Wenn ich einen zweiten Turm clone, dann reagiert dieser nicht.
      d.h. Es reagiert immer nur der Turm, dem sich die Feinde zuerst nähern. Egal ob es sich dabei bei z.B. 2 gclonten Türmen um den ersten oder zweiten Clon handelt. Sobald die Gruppe der Feinde außer Reichweite des einen Turms ist und sich der Reichweite des anderen Turms nähert, reagiert dieser nicht.
      Woran kann das jetzt wieder liegen?

    • #31927
      Torsten
      Teilnehmer

      Hi,
      ich habe erstmal deinen Code etwas umstrukturiert, um ihn leichter lese- und wartbarer zu machen. Da hast eine Menge if-Strukturen, die nicht verzweigen, sondern den Handler beenden. Das ist übersichtlicher, wenn man diese nacheinander auflistet, anstatt sie immer weiter zu verschachteln.

      Meine Kommentare habe ich mit –> im Skript eingefügt, der wichtigste könnte die Frage sein, wer die Variable i eingentlich hochsetzt.

      
      global lCloneTowerOff, lCloneTowerOn, gRadar, gFeuerFrei
      global i, x, z
      
      on checkLocation  --checks if the tower is in range at stops on the path. this is in the img script
         
         --> Wer modifiziert die globale Variable i?
         
         if there is no grp ("TankA" & i) then
            exit checkLocation
         end if
         --> wenn kein TankA & i existiert, braucht der Rest nicht ausgeführt zu werden
         
         if the visible of grp ("TankA" & i) is false then
            exit checkLocation
         end if
         --> wenn der Tank unsichtbar ist, braucht der Rest nicht ausgeführt zu werden
         
         ## Wenn der Feind sich im Erfassungsbereich des Radars des Turms befindet,
         ## dann wird der Turm "ausgefahren" (sichtbar).
         if distance (the loc of grp ("TankA" & i),the loc of me) > gRadar  then
            exit checkLocation
         end if
         --> ist der Tank nicht im Range, braucht der Rest nicht ausgeführt zu werden
         
         set the visible of img ("TowerOn" & lCloneTowerOn) to true
         
         TankATarget1  --> ??? Was soll dieser Befehl bedeuten ???
         
         ## Wenn der Feind sich im Feuerbereich der Türme befindet, dann Feuer frei auf den
         ## nächstgelegenen sichtbaren Feind.
         if distance(the loc of grp ("TankA" & i),the loc of me) < gFeuerFrei then
            moveBeam1u2 ##Immo wir nur der letzte Feind beschossen!?
            --> seltsamer Befehl, was passiert da?
            
         end if
         
      end checkLocation
    • #31929
      Torsten
      Teilnehmer

      Fehler im ersten Skript?

      put the loc grp "TowerX.png" into lTowerXplaceOld ## Der Loc der Vorlage

      muss heissen:

      put the loc of grp "TowerX.png" into lTowerXplaceOld ## Der Loc der Vorlage

    • #31933
      Klaus Major
      Verwalter

      Eine Gruppe „Towerx.PNG“ zu nennen, halte ich für etwas verwirrend. 😎

    • #31935
      Torsten
      Teilnehmer
      on updateScreen 
         if sGameRunning is true then     
            detectCollisions
      call "checkLocation" of grp "TowerOff1" of cd "Welle_001"
         end if  
      end updateScreen

      und hier sprichst Du nur die group „TowerOff1“ an, obwohl Du ja schon eine „TowerOff2“ erzeugt hast. Diese bekommt aber die CheckLocation-Message nicht.

      Du brauchst eine Möglichkeit, dir zu merken, wieviele Tower auf der Karte sind und diesen jeweils die Nachricht checkLocation zu schicken. Das geht so:

      repeat with tControlNumber = 1 to the number of controls of the current card
        if "TowerOff" is in the name of control tControlNumber then
           put the short name of control tControlNumber of the current card & cr after tListOfTowers
        end if
      end repeat
      
      repeat for each line tTower in tListOfTowers
        call "checkLocation" of grp tTower of the current card
      end repeat
      

      Probiers mal aus!

    • #31937
      akrages
      Teilnehmer

      Hallo Torsten.
      Ganz schön viel. Ich weiß gar nicht worauf ich zuerst Antworten soll.

      Also:
      Eine Gruppe „Towerx.PNG“ zu nennen, halte ich für etwas verwirrend.
      —–> Stimmt! Habs geändert.

      on updateScreen 
         if sGameRunning is true then     
            detectCollisions
      call "checkLocation" of grp "TowerOff1" of cd "Welle_001"
         end if  
      end updateScreen

      —–> hatte ich zwischenzeitlich so geändert:

      on updateScreen 
         if sGameRunning is true then     
            detectCollisions
            detectEnemyLocs
       dreht sich zum Feind)
            call "checkLocation" of grp ("TowerOff" & lCloneTowerOff) of cd "Welle_001"
         end if  
      end updateScreen

      Hat aber auch nichts geändert.

      • #31951
        Torsten
        Teilnehmer

        call "checkLocation" of grp ("TowerOff" & lCloneTowerOff) of cd "Welle_001"

        Die Variable lCloneTowerOff hat ja in dem Fall immer nur einen Wert, wahrscheinlich 1, aber du musst dafür sorgen, dass er die Nummern der Türme durchrattert und somit an jeden Turm die Botschaft schickt.

    • #31938
      akrages
      Teilnehmer

      Habs ausprobiert.
      Leider bekomme ich folgende Fehlermeldung in der call Anweisung
      call "checkLocation" of grp tTower of the current card

      card „Welle_001“: execution error at line 93 (Chunk: can´t find background), char 1

      Die tListOfTowers enthält folgendes:
      TowerOffVorlage
      TowerOff
      TowerOff.png
      TowerOff1
      TowerOff
      TowerOff2
      TowerOff

      Und was ist die grp tTower ?

    • #31949
      Torsten
      Teilnehmer

      Ah, ok, da muss der Code natürlich angepasst werden, ich wusste nicht, wieviele Objekte Du mit fast gleichen Namen auf der Karte hast 😉

      repeat with tControlNumber = 1 to the number of controls of the current card
        if the name of control tControlNumber begins with "group" and the short name of control tControlNumber begins with "TowerOff" then
           put the short name of control tControlNumber of the current card & cr after tListOfTowers
        end if
      end repeat
      
      repeat for each line tTower in tListOfTowers
        call "checkLocation" of grp tTower of the current card
      end repeat

      Die grp tTower ist die Gruppe, deren Name gerade in der Liste tListOfTowers abgearbeitet wird. Repeat for each line tTower bedeutet, dass der Inhalt der jeweiligen Zeile in tListOfTowers als Inhalt der Variable tTower eingesetzt wird.
      In der Zeile call… wird dann die Message checkLocation eben an die group mit dem Namen in tTower gesendet, so wie du es vorher hardkodiert als TowerOff1 gemacht hast.

    • #31963
      akrages
      Teilnehmer

      Aha. ok. verstehe.
      Dein neuer Code bringt keine Fehlermeldung mehr.
      Aber jetzt reagiert nur der 2te Turm (Wenn ich 2 Türme auf die Karte ziehe).
      Der 1ste Turm macht gar nichts.

    • #31966
      akrages
      Teilnehmer

      Und der Turm der reagiert reagiert zu früh
      d.h. er hält sich nicht mehr an die Distanceregel.

    • #31967
      akrages
      Teilnehmer

      in tTower steht auch nur der TowerOff2

      müssten da nicht beide, also TowerOff1 und TowerOff2 stehen?

    • #31980
      Torsten
      Teilnehmer

      Wenn Du magst, schick mir einfach Deinen Stack: torsten.holmer@web.de
      Das geht manchmal schneller, als immer wieder Code-Schnipsel zu posten 🙂

      Liebe Grüße
      Torsten

    • #31982
      akrages
      Teilnehmer

      Mach ich gerne.
      Aber nicht wundern.
      Alles nur zum testen. ha ha…

    • #32144
      akrages
      Teilnehmer

      Hi Torsten.

      Vielen Dank für das Lob.
      Nein ich habe kein anderes Spiel abgewandelt. Das meiste ist „learning by doing“.
      Außerdem besitze ich das Buch „EIGENE APPS PROGRAMMIEREN“ von Hauke Fehr.
      Und das eine oder andere findet sich im „World Wide Web“.
      Leider aber, was Spiele betrifft sehr wenig. Deshalb bin ich ganz froh, auf dieses Forum gestoßen zu sein.

      Nun aber zurück zu meinem aktuellen Problem.
      Du empfiehlst die Verwendung einer globalen Feindesliste.

      Hiermit bekomme ich zumindest schon mal eine Auflistung der generierten Feinde.

      ## Die generierten Feinde in die Variable gTankList einlesen

         repeat with t = 1 to 5
            put the short name of grp ("TankA" & t) & return after gTanklist
         end repeat

      ##answer gTankList

      TankA1
      TankA2
      ..
      ..
      TankA5
      Aber wie geht es dann weiter?

      `if distance (the loc of line 1 of gTankList, the loc of me) > gRadar then
      exit checkLocation
      end if`
      funktioniert leider nicht. gibt folgende Fehlermeldung:

      group „TowerOff1“: execution error at line 24 (Chunk: error in object expression) near „TankA1“, char 17

      Scheint als könne die Anweisung den loc von TankA1 nicht finden. Oder?

    • #32145
      Klaus Major
      Verwalter

      Hi Akrages,

      kleiner Tip, spar Dir Tipparbeit. 🙂

      repeat with t = 1 to 5
            ## put the short name of grp ("TankA" & t) & return after gTanklist
            put ("TankA" & t) & return after gTanklist
      
            ## ("TankA" & t) IST the short name of grp ("TankA" & t) :-D
      end repeat

      Zu Deiner Frage:

      if distance (the loc of line 1 of gTankList, the loc of me) > gRadar then
        exit checkLocation
      end if

      Line 1 of gTankList ist erst mal nur der String -> TankA1
      Es fehlt GROUP!
      Daher:

      put line 1 of gTankList into tGruppe
      if distance (the loc of GROUP tGruppe, the loc of me) > gRadar then
        exit checkLocation
      end if

      Gruß

      Klaus

    • #32151
      akrages
      Teilnehmer

      Dein Code sollte jetzt eigentlich funktionieren.
      Tut er aber nicht. Es kommt folgende Fehlermeldung:
      group „TowerOff1“: execution error at line 25 (Chunk: source is not a container), char 1

    • #32157
      akrages
      Teilnehmer

      Hab den Fehler 🙂
      vorher
      if distance (the loc of GROUP tGruppe, the loc of me) > gRadar then

      nachher:
      if distance ((the loc of GROUP tGruppe), the loc of me) > gRadar then

      Die Klammern warn`s.

    • #32158
      akrages
      Teilnehmer

      Also ich bin jetzt soweit, dass das Radar vom „TowerOff1“ den ersten der fünf Feinde erkennt und das Geschütz ausfährt. Danach wird der erste Feind -sobald er in Schussreichweite kommt- aufs Korn genommen und beschossen. Nach fünf Treffern wird das visible dieses ersten Feindes auf false gesetzt.
      Soweit so gut.
      Nun sollen der 2te, respektive der 3te, 4te, und letztendlich der letzte Feind auf dieselbe Weise bekämpft werden.
      Reicht es, wenn ich -nach dem der erste Feind bekämpft wurde- und sein Visible auf false gesetzt wurde, diesen aus der Feindliste gTankList lösche?
      Oder gibt es eine bessere Lösung?

    • #32167
      akrages
      Teilnehmer

      Ich bin jetzt soweit, dass alle Feinde der Reihe nach bekämpft werden.
      Spät genug, aber zum Glück hab ich ja Urlaub. 🙂
      Danke Klaus und Torsten für die Hilfe.
      Als nächstes steht die Lösung für das Problem mit mehreren Türmen an.
      Aber für heute ist Schluss.
      Gute Nacht.

    • #32312
      akrages
      Teilnehmer

      Hallo Torsten.

      Ich habe mal dein Script „on checkLocationEnemys“ ausprobiert.

      — die Ermittlung der Tanks ist eigentlich nicht notwendig, wenn die Variable vorher gesetzt wurde.

      Stimmt! Und weil diese Variable ja schon existiert habe ich den Bereich auskommentiert.

      Hier das Script so wie ich es jetzt verwende:

      on checkLocationEnemys ##Feind dreht sich in Laufrichtung
         
         -- Anzahl der Knoten und Anzahl der Tanks ermitteln
         
         
         ##put empty into gTankList
         
         -- die Ermittlung der Tanks ist eigentlich nicht notwendig, wenn die Variable vorher gesetzt wurde
         
         -- diesen Handler habe ich vor der Idee geschrieben
         
         
         repeat with tControlNumber = 1 to the number of controls
            
            
            put word 1 of the name of control tControlNumber into tControlType
            
            put the short name of control tControlNumber into tControlName
            
            
            ##if tControlType is "group" and tControlName begins with "TankA" then
            
            ##if tControlName <> "TankA" then -- Vorlage nicht übernehmen
            
            ##put tControlName & cr after gTankList
            
            ##end if
            
            ##end if
            
            
            if tControlType is "field" and tControlName begins with "Knoten" then
               
               if tControlName <> "KnotenX" then -- Vorlage nicht übernehmen
                  
                  put tControlName & cr after tKnotenList
                  
               end if
               
            end if
            
            
         end repeat
         
         
         -- Iteration: für jeden Knoten für jeden Tank
         
         repeat for each line tKnoten in tKnotenList
            
            repeat for each line tTank in gTankList
               
               
               if the loc of grp tTank is within the rect of field tKnoten then set the angle of img "TankA" of grp tTank to the text of field tKnoten
               
            end repeat
            
         end repeat
         
         
         ## Runde beenden, wenn der letzte Tank im Ziel ist
         
         put field "MaxTanks" into tMaxTanks
         
         if there is a grp ("TankA" & tMaxTanks) then
            
            if intersect(grp ("TankA" & tMaxTanks), graphic "Ziel", "opaque Pixels") then send mouseUp to btn "Start"
            
         end if
         
         if there is a grp "Assault5" then
            
            if intersect(grp "Assault5", graphic "Ziel2", "opaque Pixels") then send mouseUp to btn "Start"
            
         end if
         
      end checkLocationEnemys

      Folgendes passiert:
      Beim ersten Start wird der letzte Tank anvissiert und erfolgreich bekämpft. Im Anschluss richtet sich der Turm auf den ersten Feind aus, schießt aber nicht mehr.
      Und wenn der letzte der verbliebenen 4 Feinde das Ziel erreicht hat kommt es zu folgender Fehlermeldung: card „Welle_001“: execution error at line 255 (Chunk: can’t find background), char 13

      In dieser Zeile:
      if the loc of grp tTank is within the rect of field tKnoten then set the angle of img "TankA" of grp tTank to the text of field tKnoten

      Und jetzt das merkwürdige an der ganzen Sache.

      Wenn ich das Spiel erneut starte, dann werden alle Feinde in der richtigen Reihenfolge bekämpft.
      Aber anschließend kommt es zur exakt selben Fehlermeldung.

      Und dann geht das ganze von vorne los.

      Ich kann nicht herausfinden, was da los ist.
      Hast Du ne Idee?

    • #32526
      Torsten
      Teilnehmer

      Hi,

      wenn “ can’t find background)“ kommt, bedeutet das immer, das eine Gruppe nicht existiert, die angesprochen werden soll. Früher zu Hypercard und Metacard-Zeiten gab es noch keine Gruppen, sondern das waren die Backgrounds der Karten (vielleicht könbte das Mutterschiff hier mal die Begriffe erneuern 🙂

      In so einem Fall musst Du unbedingt im Script-Editor nachschauen, was in den einzelnen Variablen tTank und tKnoten drin steht und im Projekt-Browser überprüfen, ob die Objekte existieren.

      In dem konkreten Fall scheint also die group tTank nicht zu existieren, es fragt sich also, was in tTank für ein Wert steht und warum dieses Objekt nicht da ist.

      Beste Grüße
      Torsten

    • #32528
      Klaus Major
      Verwalter

      Früher zu Hypercard und Metacard-Zeiten gab es noch keine Gruppen, sondern das waren die Backgrounds der Karten (vielleicht könnte das Mutterschiff hier mal die Begriffe erneuern

      Hypercard und Metacard sind über 20 Jahre tot!

      Livecode unterscheidet sehr wohl zwischen „group“ und „background“.
      Möglicherweise anders als HC, aber nicht anders als MC, daher wird
      es nicht passieren, daß diese Begriffe erneuert werden!
      Also gewöhnt euch dran. 😎

      GROUPS werden relativ zur Karte, BACKGROUNDS relativ zum Stack gezählt.

      ...
      put the num of grps
      ## Ergibt die Anzahl der Gruppen auf der aktuellen KARTE
      ...
      put the num of backgrounds
      ## Ergibt die Anzahl der Gruppen im aktuellen STACK
      ...
    • #32530
      Torsten
      Teilnehmer

      Hi Klaus,

      mein Kommentar ar bezogen auf die Fehlermeldung „(Chunk: can’t find background)“ und die erscheint immer, wenn man etwas mit einer Group machen will, die nicht existiert. Meine Anregung bezog sich darauf, dass diese Fehlermeldung korrigiert werden sollte, nämlich in „can’t find group“.

      Einverstanden?

      Liebe Grüße
      Torsten

    • #32532
      Klaus Major
      Verwalter

      Nein. 😀

      BACKGROUND ist der Sammelbegriff für Gruppen im Stack.
      Daher ist die Fehlermeldung korrekt, wenn man das Prinzip
      (oben erklärt) verstanden hat.

      Aber ich gebe zu, das ist hier nicht so einfach…

    • #32536
      Torsten
      Teilnehmer

      Aber es gibt keine Backgrounds als eigene Objekte, sondern nur Groups, deren backgroundBehavior als true gesetzt ist, oder?

      Das meine ich, die Terminologie aus HC ist aus Kompatibilität übernommen worden, aber das Konzept hat sich geändert. Du kannst ja auch mehrere „Hintergründe“ (Groups mit Backgroundbehavior) auf einer Karte haben, was aber missverständlich ist. Ich finden den Begriff Background in der jetzigen Form eher verwirrend.

    • #32538
      Klaus Major
      Verwalter

      Touché! 😀

    • #32540
      Torsten
      Teilnehmer

      Gab es im englischen Forum zu diesem Thema eigentlich schon Diskussionen?
      Im Hinblick auf Benutzerfreundlichkeit finde ich, ist das eine der Schwachstellen.

    • #32542
      Klaus Major
      Verwalter

      Gab es im englischen Forum zu diesem Thema eigentlich schon Diskussionen?

      Nein, gibt es nicht.
      Denke auch nicht, daß dort so etwas auftauchen wird.

    • #32546
      akrages
      Teilnehmer

      Hi.
      Hab jetzt eine Lösung gefunden, damit der Turm immer das nächstglegene Ziel anvisiert.

      Mit diesem Code in der Card „Welle_001“

      on detectEnemyLocs
         
         put line 1 of gTankList into gTank1
         put line 2 of gTankList into gTank2
         put line 3 of gTankList into gTank3
         put line 4 of gTankList into gTank4
         put line 5 of gTankList into gTank5
         
         if gTank1 <> empty then \ ## \ ist ein Zeilenumbruch
               put distance ((the loc of GROUP gTank1), the loc of grp "TowerOff1") & tab & gTank1 & cr into gDistanceList
         if gTank2 <> empty then \
               put distance ((the loc of GROUP gTank2), the loc of grp "TowerOff1") & tab & gTank2 & cr after gDistanceList
         if gTank3 <> empty then \
               put distance ((the loc of GROUP gTank3), the loc of grp "TowerOff1") & tab & gTank3 & cr after  gDistanceList
         if gTank4 <> empty then \
               put distance ((the loc of GROUP gTank4), the loc of grp "TowerOff1") & tab & gTank4 & cr after  gDistanceList
         if gTank5 <> empty then \
               put distance ((the loc of GROUP gTank5), the loc of grp "TowerOff1") & tab & gTank5 & cr after  gDistanceList
         
         sort lines of gDistanceList numeric ascending ## Die Liste numerisch aufsteigend sortieren.   
         put gDistanceList into fld "DistanceList" ##Nur zur Kontrolle!
         
      end detectEnemyLocs

      und dieser kleinen Änderung in der Group „TowerPlattform“

      on checkLocation

         set the itemdel to TAB
         put word 2 of gDistanceList into tGruppe

      funkts endlich.

    • #32547
      Torsten
      Teilnehmer

      Gut so,
      kleiner Wermutstropfen bei dieser Form ist, dass Du 1. nur einen Turm berücksichtigst und 2. alles nur für 5 Tanks geht. Besser wäre es, wenn Du die Distanzberechnung von jedem Turm selbst vorgenommen wird und er dabei alle sichtbaren (also noch existierenden) Tanks berücksichtigt (gTankList) und entsprechend auf SEINEN nächsten Tank feuert.

      In der jetzigen Form schiesst wieder nur Turm1, oder?

      Happy Coding
      Torsten

    • #32549
      akrages
      Teilnehmer

      Stimmt leider. 🙁

    • #32571
      akrages
      Teilnehmer

      Es ist zum Verzweifeln!
      Hab das jetzt in der Turmvorlage:

      Global lCloneTowerOff, lCloneTowerOn, gRadar, gFeuerFrei, gTanklist, tGruppe, gDistance, gDistanceList
      global i, x, z, tMaxTanks, gTank

      on detectEnemyLocs
         
         if gTanklist = empty then
            exit detectEnemyLocs
         end if   
       
         put line 1 of gTankList into gTank1
         put line 2 of gTankList into gTank2
         put line 3 of gTankList into gTank3
         put line 4 of gTankList into gTank4
         put line 5 of gTankList into gTank5
         
         put distance ((the loc of GROUP gTank1), the loc of me) & tab & gTank1 & cr into gDistanceList
         put distance ((the loc of GROUP gTank2), the loc of me) & tab & gTank2 & cr after gDistanceList
         put distance ((the loc of GROUP gTank3), the loc of me) & tab & gTank3 & cr after  gDistanceList
         put distance ((the loc of GROUP gTank4), the loc of me) & tab & gTank4 & cr after  gDistanceList
         put distance ((the loc of GROUP gTank5), the loc of me) & tab & gTank5 & cr after  gDistanceList
         
         sort lines of gDistanceList numeric ascending ## Die Liste numerisch aufsteigend sortieren.   
         put gDistanceList into fld "DistanceList" ##Nur zur Kontrolle!
         
      end detectEnemyLocs
      
      --------------------------------------------------------------------------------------------------------------------------
      
      --------------------------------------------------------------------------------------------------------------------------
      
      on checkLocation 
         
         set the itemdel to TAB
         put word 2 of gDistanceList into tGruppe
      
         --> Wer modifiziert die globale Variable i? damit werden 5 Feinde --TankA 1-5 (i)-- erstellt.
         ##answer tGruppe ##ist OK
         if there is no grp tGruppe then
            exit checkLocation
         end if
         --> wenn kein TankA & i existiert, braucht der Rest nicht ausgeführt zu werden
         
         if the visible of grp tGruppe is false then
            exit checkLocation
         end if
         --> wenn der Tank unsichtbar ist, braucht der Rest nicht ausgeführt zu werden
         ---------------------------------------------------------------------------------------------------------
         
         
         ---------------------------------------------------------------------------------------------------------
         ## Wenn der Feind sich im Erfassungsbereich des Radars des Turms befindet,
         ## dann wird der Turm "ausgefahren" (sichtbar).
         
         if distance ((the loc of GROUP tGruppe), the loc of me) > gRadar then ##Hier neuen Befehl einfügen!
            exit checkLocation
         end if
         --> ist der Tank nicht im Range, braucht der Rest nicht ausgeführt zu werden
         
         set the visible of img ("TowerOn" & lCloneTowerOn) to true
         
         TankATarget  --> ??? Was soll dieser Befehl bedeuten ??? Bedeutet, der Turm folgt dem anvisierten Ziel.
         ---------------------------------------------------------------------------------------------------------
         
         
         ---------------------------------------------------------------------------------------------------------
         ## Wenn der Feind sich im Feuerbereich der Türme befindet, dann Feuer frei auf den
         ## nächstgelegenen sichtbaren Feind.
         if distance ((the loc of GROUP tGruppe), the loc of me) > gFeuerFrei then ##Hier neuen Befehl einfügen!
            exit checkLocation
         end if
         
         moveBeam1u2
         --> seltsamer Befehl, was passiert da? ##Es wird der anvisierte Feind beschossen!
         
      end checkLocation

      Und trotzdem funktioniert es nicht mit 2 oder mehr Türmen.

      Es schießt immer nur der letzte der geclonten Türme.

      Was mache ich falsch?

    • #32578
      Torsten
      Teilnehmer

      Soweit ich in deinem Stack sehen kann, sind die Handler TankATarget und moveBeam1u2 auch noch nicht umgeschrieben. Ich glaube, am besten ist es, wenn auch diese Funktionen für jeden Turm extra sind ODER parametrisiert werden, so dass der Zielende Turm und das Ziel explizit als Parameter angegeben werden:

      TankATarget me, tTarget oder so…

      Happy Coding
      Torsten

Ansicht von 40 Antwort-Themen
  • Du musst angemeldet sein, um auf dieses Thema antworten zu können.