Hi.
Ich bin gerade dabei mich in die GLBasic-Typestrukturen einzuarbeiten und habe es auch soweit verstanden. Ein Problem habe ich allerdings noch, welches bissl schlecht zu erklären ist. Ich versuche es mal am beliebten Beispiel eines Weltraumshooters(Multiplayer).
Nehmen wir an wir haben eine Typestruktur namens 'Player'. Darin befinden sich die Daten für alle Spielerobjekte.
Type Player
PosX
PosY
usw...
End Type
Gehen wir weiterhin davon aus, daß wir 4 Spieler-Raumschiffe erstellt haben. Es sind also 4 Einträge vorhanden.
Jedem der zwei Teams sollen nun jeweils 2 Raumschiffe zugeteilt werden. Dafür gibt es eine weitere Typestruktur namens 'Teams'. Darin wird festgelegt welche Raumschiffe zu welchem Team gehören.
Es sollen zum Beispiel die Raumschiffe mit der Nummer 0 und 1 dem Team Rot und die Raumschiffe 2 und 3 dem Team Blau zugeteilt werden.
Wenn man jetzt in einer Schleife die Teams abfragt, aber nur die Blauen berechnen will, so müsste man in der Struktur 'Teams' abfragen welche 'Player'-Nummern zum blauen Team gehören und dessen PosX, PosY etc. aktualisieren. Wie kann man dies bewerkstelligen ? Also wie kann man von einer Typestruktur aus auf eine andere zugreifen ?
Es ist ein bissl blöd zu erklären, aber ich hoffe das es trotzdem halbwegs verständlich ist. ;)
PS:
Ich programmiere mittlerweile seit über 22 Jahren und eigentlich durchgängig im Basic-Dialekt (Html, PHP, etc. mal ausgenommen). Dadurch habe ich schon viele Typestrukturen kennengelernt und frage mich wieso das bei GLBasic so extrem kompliziert gemacht wurde !? Wenn man mal die Umsetzung bei Blitzbasic betrachtet, so erkennt man, daß es da um einiges einfacher, aber dennoch sehr effektiv ist. Wieso ist das bei GLBasic denn so umständlich mit den Types ?
TYPE TPlayer
x;y
blablabla...
ENDTYPE
TYPE TTeam
bla...
players[] AS TPlayer
ENDTYPE
Danke Schranz0r, aber kannst Du das eventuell kurz erläutern ?
Die Zuweisung kannst du folgendermaßen vornehmen. Mit verschachtelten TYPEs wirds aber sehr schnell unübersichtlich meiner Meinung nach. Nur was ist daran komplizierter als in anderen Basic-Dialekten? Der Zugriff erfolgt dort doch ebenso.
TYPE TPlayer
x
y
ENDTYPE
TYPE TTeam
player[2] AS TPlayer
ENDTYPE
GLOBAL teams[] AS TTeam
DIM teams[2]
// 1. Spieler des 1. Teams Werte zuweisen
teams[0].player[0].x = 10
teams[0].player[0].y = 20
// 2. Spieler des 1. Teams Werte zuweisen
teams[0].player[1].x = 50
teams[0].player[1].y = 40
// 1. Spieler des 2. Teams Werte zuweisen
teams[1].player[0].x = 70
teams[1].player[0].y = 10
// 2. Spieler des 2. Teams Werte zuweisen
teams[1].player[1].x = 15
teams[1].player[1].y = 16
Also du musst als erstes das TPlayer machen damit GLB weiß, dass es TPlayer gibt.
TYPE TTeam
bla...
players[] AS TPlayer
ENDTYPE
das erstellt ein Array für Spieler in einem Team.
also erstellt du als erstes ein Team:
LOCAL Team1 AS TTeam
nun einen Spieler:
LOCAL player1 AS TPlayer
jetzt kannst du den Team1 den Player1 zuweisen
DIMPUSH Team1.players[], Player1
Jetzt könntest du sogar noch auf die Playerwerte zugreifen z.B x und y mit;
Team1.players[0].x
Team.player[0].y
wenn du jetzt aber am Player1 was änderst musst du das an Team1 übergeben!
Sprich:
Team1.players[0] = Player1
Vielen Dank für die Erklärungen. Dennoch bin ich trotz intensiven Rumprobierens noch nicht ganz hinter die Logik des Ganzen gekommen.
Ich denke ich habe mir auch ein zu kompliziertes Beispiel ausgedacht. Mittlerweile ist mir ein einfacheres eingefallen. Ich hoffe ich verstehs dann. :D
Nehmen wir einfach an wir haben in einer Typestruktur ein paar Punkte (X;Y):
TYPE Punkte
x
y
ENDTYPE
Und in der zweiten Typestruktur steht, welche Punkte zusammengehören. Also Beispielsweise soll Punkt 1 und Punkt 2 mit einer Linie verbunden werden. Das Gleiche mit den Punkten 2 und 3, aber nicht Punkt 1 und 3.
Kann mir das vielleicht jemand erklären ? Ich hoffe dann steig ich besser hinter das Geheimnis von Types in GLBasic. :)
Ich mach dir mal ein Beispiel ;)
Also ne "art Drawline" nur das man mit mehrern Punkten arbeiten kann, um eine Krümmung zu erzeugen.
Easy to do xD
EDIT:
Mal sehen ob du selber daraus schlauer wirst :P
// --------------------------------- //
// Project: Lines Type
// Start: Monday, January 18, 2010
// IDE Version: 7.237
TYPE TVector
x%; y% // position
ENDTYPE
TYPE TLine
vec[] AS TVector // vector-array
color% // linecolor
ENDTYPE
GLOBAL _TLine[] AS TLine // Line-array
LOCAL Line1 AS TLine
Line1 = CreateLine(RGB(0xff, 0x00, 0x00))
AddPointToLine(Line1,10,10)
AddPointToLine(Line1,20,20)
AddPointToLine(Line1,30,10)
AddPointToLine(Line1,40,20)
AddPointToLine(Line1,50,10)
LOCAL Line2 AS TLine
Line2 = CreateLine(RGB(0x00, 0xff, 0x00))
AddPointToLine(Line2,100,100)
AddPointToLine(Line2,200,100)
AddPointToLine(Line2,200,200)
AddPointToLine(Line2,100,200)
WHILE TRUE
DrawPointLine(Line1)
DrawPointLine(Line2)
SHOWSCREEN
WEND
END
FUNCTION CreateLine AS TLine: color%
LOCAL L AS TLine
L.color = color
DIMPUSH _TLine[], L
RETURN L
ENDFUNCTION
FUNCTION AddPointToLine: L AS TLine, x%, y%
LOCAL V AS TVector
V.x = x
V.y = y
DIMPUSH L.vec[], V
ENDFUNCTION
FUNCTION DrawPointLine: L AS TLine
FOR i = 0 TO LEN(L.vec[])-1
IF i < LEN(L.vec[])-1
DRAWLINE L.vec[i].x, L.vec[i].y, L.vec[i+1].x, L.vec[i+1].y, L.color
ENDIF
NEXT
ENDFUNCTION
Danke Schranz0r.
Also Dein Beispiel habe ich soweit verstanden. Allerdings löst es nicht mein Verständnisproblem. Man kann ja mit einer FOREACH-Schleife jeden Eintrag einer Typestruktur durchgehen, aber wie kann man auf einen bestimmten Eintrag zugreifen ? Also wenn ich zum Beispiel 20 Einträge habe und den Eintrag 15 auslesen möchte, aber eben ohne alle Einträge durchgehen zu müssen. Wie mach ich das ?
feld[15]
Mit LEN(_TLine[]) bekommst du die Anzahl der Einträge
Wenn du weißt wieviele Einträge du hast, kannst du auch _TLine[2].color oder _TLine[2].vec[0].x usw verwenden!
Oh man...Da hab ich mal wieder den Wald vor lauter Bäumen nicht gesehen und viel komplizierter gedacht als es eigentlich ist. ;/ :whistle:
Jetzt wo ich es verstanden habe, nehm ich auch meine Behauptung zurück, daß es komplizierter wäre als bei Blitzbasic und behaupte das Gegenteil. =D
Eine Frage habe ich allerdings noch. ;)
Kann man in einer FOREACH-Schleife abfragen welcher Eintrag gerade abgefragt wird ? Also man kann das natürlich mit einer fortlaufenden Variable machen, aber gibt es vielleicht auch einen Befehl der eben diese Nummer ausgibt ?
Ne gibts nicht, ich mach sowas über eine ID-Nummer im Type :D
Das ist natürlich auch eine Möglichkeit, aber ist die nicht um einiges uneffektiver ? :blink:
Wenn man eine ID-Nummer anlegt, dann kostet das ja Speicher und je mehr Einträge in der Typestruktur vorhanden sind, desto mehr Speicher wird benötigt. Außerdem braucht man dafür ja trotzdem eine fortlaufende Variable um den Wert der ID zu bestimmen. Wenn man allerdings nur bei der Ausgabe eine fortlaufende Variable hat, so ist das Ganze doch speicherschonender und somit effizienter, oder !?
Bei heutigen PC's wohl kein Problem mehr :D
Wenn ich beim programmieren schon auf sowas achten müsste, würde ich sofort aufhören ;)
Ne ich mach das eh nur, um einen festen Bezug auf den Eintrag im Typearray zu haben, falls ich es benötige, wenn nicht, dann braach ich das auch net ;)
aber naja du kannst machen:
TYPE Test
id
x
y
ENDTYPE
GLOBAL _Test[] AS Test
LOCAL bla AS Test
bla.id = LEN(_Test[]) // Hier geht man einfach von der Arraygröße aus :)
usw...
Mag sein das heutige Computer kein Problem damit haben, aber wieso unnötig Speicher verschenken, wenn es doch gar nicht nötig wäre ? Und was ist mit den Usern die nicht für den PC compilieren ? Ich zum Beispiel bin WIZ-User und auch wenn der WIZ ausreichend Speicher hat, so stößt man auch da irgendwann an seine Grenzen. ;) Deswegen finde ich meine Version effektiver.
Hier mal ein Pseudobeispiel wie ich das meine:
TYPE WERT
Wert1
Wert2
...
END TYPE
Werte eintragen usw...
blablablubb...
FUNCTION Auslesen:
LOCAL ID=0
FOREACH W IN Wert[]
Print Wert[ID],0,ID*20
ID=ID+1
NEXT
ENDFUNCTION
fein, aber wirst du so nicht immer wert[0] ausgeben? müsstest halt noch ID innerhalb der Schleife hochzählen.
Außerdem musst du ja nicht zwangsläufig FOREACH nehmen. Wenn du den Index unbedingt brauchst, nimm halt eine "normale" FOR-NEXT-Schleife. Ich bin mir nicht sicher, wieviel Geschwindigkeitsvorteil FOREACH gegenüber FOR hat, wenn man solche Konstrukte mit Hilfsvariablen oder Zählern hat. Könnte man mal probieren :)
Ups, sorry. Das hatte ich in meinem Pseudocode vergessen, aber mir ist natürlich klar das man die ID hochzählen muss. Hab den Code soeben berichtigt. ;)
Eine For-Next-Schleife würde nur dann Sinn machen, wenn man die Anzahl der Einträge kennt, was allerdings nicht immer der Fall ist. Ob die schneller wäre als eine FOREACH-Schleife weiß ich allerdings auch nicht. So viel dürfte das aber nicht ausmachen.
FOREACH ist schon um einiges schneller als FOR, weil es intern nur einen Zeiger auf das aktuelle Element setzt. Der Geschwindigkeitsvorteil dürfte sich vor allem bei komplexeren TYPEs bemerkbar machen.
Die Anzahl der Einträge ermittelt man ganz einfach mit LEN(array[]) für eindimensionale Arrays bzw. mit BOUNDS für mehrdimensonale. Das kann man vor der eigentlichen Schleife erledigen. Somit verstehe ich dein Problem immer noch nicht so ganz. :)
Bingo Quentin!
@Quentin
Ein Problem gibt es nicht und es ist auch kein Problem selber abzufragen welcher Eintrag gerade aktuell ist, aber es hätte ja sein können das es dafür einen bestimmten Befehl gibt, den ich einfach noch nicht gefunden habe. ;)
Genau wie Du's gemacht hast:
LOCAL i% = -1
FOREACH n in NN[]
INC i
....
NEXT
Dann hab ich es ja richtig gemacht. ;)
Viele wege führen nach Rom ;)
Recht haste Schranz0r...auch wenn ich gar nicht nach Rom, sondern nur die Types verstehen wollte. :D
Aber das habe ich ja nun, dank Eurer Hilfe geschafft. ;) :nw:
So muss es sein :P