Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Wände im 2D - Spiel


Arbengie - Do 06.05.10 15:08
Titel: Wände im 2D - Spiel
Moin !

Ich frage mich, wie es in Spielen, in meinem Fall ein 2D - Spiel, möglich ist, Wände ins Spiel einzubauen, sodass eine Figur, wenn Sie dort anstößt sich halt nicht dadurch bewegen kann.
Bis jetzt habe ich etwas kleineres programmiert und die Wände einmach mit Labels dargestellt.

z.B.:


Delphi-Quelltext
1:
2:
If Figur. Left <= Label.Width then
Figur.Left := Label.Width;



Wenn ich jetz z.B. vorhabe ein kleines Labyrinth zu erstellen, is es ja total aufwenig für jede Wand (Label) eine If-Bedingung einzubauen.

Mein Frage nun, wie kann ich dieses Problem umgehen/bearbeiten. Bzw. wie wird das in "richtigen" Computerspielen gemacht?

MfG


Horschdware - Do 06.05.10 15:29

Versuche mal folgenden Ansatz:

Dein Spielelevel besteht aus einer Schwarz-Weiss Grafik die du auf dein Formular legst. Dein Spieler ist ein Roter Punkt, irgendwo auf dem weissen.
Diesen Startzustand kannst du noch problemlos herstellen.

Versucht der Spieler sich nun nach oben zu bewegen, dann prüfst du einfach ob an der Koordinate [x , y+1] der Untergrund weiss ist. Wenn ja, dann bewegen. Wenn nein, nicht bewegen / Kollision.
Das selbe dann nach unten [x,y-1], links [x-1,y] und rechts [x+1,y] prüfen.
Schon kannst du dich innerhalb des Levels bewegen ohne jede Wand einzeln prüfen zu müssen.


Wenn das zuverlässig klappt, dann kannst du eine Ebene größer arbeiten. Dein Spieler-Punkt wird durch eine richtige Figur ersetzt. Hier wird die Kollisionsabfrage ein wenig aufwändiger, da du zusätzlich noch die Dimensionen des Spielers beachten musst (Höhe / Breite).

Dann kannst du im nächsten Schritt deine Figur statt über eine Grafik über ein gedachtes Raster bewegen, welches du dir z.B. in Form eines Arrays im Speicher hältst. Dieses Array könnte u.a. Informationen für jede Position auf dem Spielfeld behalten, ob sie betretbar ist, eine Falle/Loch ist, die Bewegung verlangsamt, etc...


Arbengie - Do 06.05.10 18:16

Vielen Dank für deinen Vorschlag schonmal mit der Hintergrundfarbe überprüfen :).
Nur mit welchem Befehl kann ich genau überprüfen, welche Farbe der Hintergrund hat.

Delphi-Quelltext
1:
If Form1.Colort = clWhite then //...                    


Und die Form1 kann soweit ich weiß nur eine Hinetrgrundfarbe haben, also müsste ich doch wieder Labels benutzen um Wände darzustellen.
Aber wenn ich ein Label zum Wand darstellen benutze, wie genau kann ich dann überprüfen, ob z.B. die Figur bei dem Label "steht", bzw. welche Farbe der Unetrgrund hat?


Horschdware - Do 06.05.10 18:22

Leg eine Grafik (Bitmap), die du mit Paint erstellt hast auf das Formular. Wie du den Farbwert eines Pixels einer Bitmap bestimmen kannst findest du hier mehrfach im Forum.


F34r0fTh3D4rk - Do 06.05.10 18:25

Wie wäre es mit Suche in: Delphi-Forum, Delphi-Library ARRAYS?


Namenlosnameless - Do 06.05.10 21:03

ich würde da sowiso mit einer TileMap arbeiten!

du hast einen 2-Dim-Array! der dein Spielfeld darstellt!

Dort schreibst du Werte rein, die Objekte auf dem Spielfeld darstellen!

z.b. Wert [1,1]=Mauer!
wenn du jetzt das die zukünftige Koordinate des Spielers immer überprüfen lässt ob es eine Mauer ist, dann kannst du niemals über eine Mauer laufen!
Ist der "Spielzug" abgeschlossen kannst du das ganze ausgeben!


ffgorcky - Sa 15.05.10 19:50

Entschuldigung, ich würde das ganze mit einem zweidimensionalen Array of bool machen, in dem ich das dann eben immer in etwa so abfrage:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
if(nachrechts)and(levelArray[momentaneLinksRechtsPosition+1,momentaneObenUntenPosition]) then//also wenn die Figur nach rechts gehen soll und der Platz kein false(=gesperrt) hat
momentaneLinksRechtsPosition:=momentaneLinksRechtsPosition+1
else if (nachlinks)and(levelArray[momentaneLinksRechtsPosition-1,momentaneObenUntenPosition]) then//also wenn die Figur nach links gehen soll und der Platz kein false(=gesperrt) hat
momentaneLinksRechtsPosition:=momentaneLinksRechtsPosition-1
else if (nachoben)and(levelArray[momentaneLinksRechtsPosition,momentaneObenUntenPosition-1]) then//also wenn die Figur nach oben gehen soll und der Platz kein false(=gesperrt) hat
momentaneObenUntenPosition:=momentaneObenUntenPosition-1
else if (nachunten)and(levelArray[momentaneLinksRechtsPosition,momentaneObenUntenPosition+1]) then//also wenn die Figur nach oben gehen soll und der Platz kein false(=gesperrt) hat
momentaneObenUntenPosition:=momentaneObenUntenPosition+1;

Die Werte für die von mir entworfenden Variablen (nachLinks, nachRechts, nachOben und nachUnten) musst Du natürlich entsprechend festlegen, wann welcher Fall eintreten soll.
Ich hoffe, dass das so klappt - ich habe leider gerade keine Möglichkeit das nachzuprüfen.


elundril - So 16.05.10 13:53

Ich würd statt Boolean halt TSpielfeld nehmen dann kann man noch so lustige Sachen wie Fallen oder sonst andere Bodentypen einbauen.

lg elundril


Namenlosnameless - So 16.05.10 15:03

user profile iconffgorcky hat folgendes geschrieben Zum zitierten Posting springen:
Entschuldigung, ich würde das ganze mit einem zweidimensionalen Array of bool machen,


Sofern es nur um Wände geht ja... aber sobald mehrere Komponenten hinzukommen wirst du mit einem bool der 2 werte anzeigt nicht viel machen!


F34r0fTh3D4rk - So 16.05.10 15:58

Ein Enumerable (heißen die so in Delphi?) würde sich eher anbieten:

Delphi-Quelltext
1:
TField = (fnone, fwall, ffloor);                    

und dann:

Delphi-Quelltext
1:
array of array of TField;                    


Arbengie - Mo 17.05.10 15:39

Ich habs jetzt wie nach Horschdware's Idee gemacht, also mit Farben. Klappt auch alles gut, nur ein kleines Problem:

In meinem Spiel gibt es 2 "Panzer" die von jeweils einem Spieler mit W-A-S-D und Pfeiltasten gesteuert werden können.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TFrmGame.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  If Key = VK_Up then
  begin
    Figur1.Top := Figur1.Top - 1;
  end

  If Key = Key_W then
  begin
    Figur2.Top := Figur2.Top - 1;
  end
end;


Wenn jetzt der eine Spieler "Pfeil hoch" drückt, dan bewegt sich zwar dessen Figur1, aber von Spieler 2, der W grückt, dessen Figur2 bleibt stehen. Und umgekehrt...

Wie kann man das beheben, sodass sich beide gleichzeitig bewegen können? :?:

MfG


elundril - Mo 17.05.10 15:54

Du könntest in gewissen intervallabständen "GetAsyncKeyState()" aufrufen. Damit sollte man es lösen können, was ich so mitbekommen hab.

lg elundril


Arbengie - Mo 17.05.10 16:10

user profile iconelundril hat folgendes geschrieben Zum zitierten Posting springen:
Du könntest in gewissen intervallabständen "GetAsyncKeyState()" aufrufen. Damit sollte man es lösen können, was ich so mitbekommen hab.

lg elundril


Wie genau meinst du das?
Was bewirkt genau GetAsyncKeyState()?

Habe gegoogelt und hier gesucht, aber nichts brauchbares gefunden


elundril - Mo 17.05.10 16:13

http://www.google.at/search?q=GetAsyncKeyState%28%29+delphi&ie=utf-8&oe=utf-8&lr=lang_de

unter den top 10 sind ein paar themen die dir sicher weiterhelfen. ;)

lg elundril