Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Anfängerhilfe Labyrinth (https://www.delphipraxis.net/124471-anfaengerhilfe-labyrinth.html)

skaot 19. Nov 2008 14:49


Anfängerhilfe Labyrinth
 
So als aller erstes bin blutiger Anfänger. Ich würde gerne ein kleines Labyrinth programieren, also das man mit den Tasten wasd eine Kugel bewegt, welche sobald eine Wand im weg ist sich nicht weiter bewegt.

So weit bin ich.
Delphi-Quellcode:
unit Pong;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    procedure FormKeyPress(Sender: TObject; var Key: Char);


  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  dicke, x, y: integer;

implementation

{$R *.dfm}



procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);

begin
dicke := 20;


if key = 's' then
begin
form1.Refresh;
y := y+5;
canvas.brush.color := clnavy;
canvas.ellipse (x,y,x+dicke,y+dicke);
canvas.MoveTo(50,0);
canvas.lineto(50,350);
canvas.MoveTo(50,400);
canvas.lineto(50,500);
label1.Caption := inttostr(x);
label2.caption := inttostr(y);
end;


if key = 'd' then
begin
form1.Refresh;
x := x+5;
canvas.brush.color := clnavy;
canvas.ellipse (x,y,x+dicke,y+dicke);
canvas.MoveTo(50,0);
canvas.lineto(50,350);
canvas.MoveTo(50,400);
canvas.lineto(50,500);
label1.Caption := inttostr(x);
label2.caption := inttostr(y);
if (x > 30) and (x < 50) then
end;


if key = 'a' then
begin
form1.Refresh;
x := x-5;
canvas.brush.color := clnavy;
canvas.ellipse (x,y,x+dicke,y+dicke);
canvas.MoveTo(50,0);
canvas.lineto(50,350);
canvas.MoveTo(50,400);
canvas.lineto(50,500);
label1.Caption := inttostr(x);
label2.caption := inttostr(y);
end;

if key = 'w' then
begin
form1.Refresh;
y := y-5;
canvas.brush.color := clnavy;
canvas.ellipse (x,y,x+dicke,y+dicke);
canvas.MoveTo(50,0);
canvas.lineto(50,350);
canvas.MoveTo(50,400);
canvas.lineto(50,500);
label1.Caption := inttostr(x);
label2.caption := inttostr(y);
end
end;
end.

Könnte sein das noch ein paar unsinnige Sachen drin sind, wie gesagt totaler Anfänger.

[edit=Sharky]Delphi-Tags gesetzt. Mfg, Sharky[/edit]

Corpsman 19. Nov 2008 15:07

Re: Anfängerhilfe Labyrinth
 
Ja man sieht das du neu bist, bitte nutze die Code Tags dann sieht das ganze schon viel Hübscher aus. ( Trotzdem Herzlich willkommen in der DP )

und dein Code könnte etwas Struktur gebrauchen.

Delphi-Quellcode:
Procedure TForm1.FormKeyPress(Sender: TObject; Var Key: Char);

Begin
  dicke := 20;

  If key = 's' Then Begin
    form1.Refresh;
    y := y + 5;
  End;

  If key = 'd' Then Begin
    form1.Refresh;
    x := x + 5;
  End;

  If key = 'a' Then Begin
    form1.Refresh;
    x := x - 5;
  End;

  If key = 'w' Then Begin
    form1.Refresh;
    y := y - 5;
  End;
  canvas.brush.color := clnavy;
  canvas.ellipse(x, y, x + dicke, y + dicke);
  canvas.MoveTo(50, 0);
  canvas.lineto(50, 350);
  canvas.MoveTo(50, 400);
  canvas.lineto(50, 500);
  label1.Caption := inttostr(x);
  label2.caption := inttostr(y);

End;
bei diesem Code ist die Semantik die selbe wie bei deinem, nur ist der Code deutlich kürzer.

und zu guter letzt ein Hinweis auf deine Lösung :

Delphi-Quellcode:
Procedure TForm1.FormKeyPress(Sender: TObject; Var Key: Char);

Begin
  dicke := 20;

  If key = 's' Then Begin
    form1.Refresh;
    y := y + 5;
  End;

  If key = 'd' Then Begin
    form1.Refresh;
    x := x + 5;
  End;

  If key = 'a' Then Begin
    form1.Refresh;
    x := x - 5;
  End;

  If key = 'w' Then Begin
    form1.Refresh;
    y := y - 5;
  End;
  If x < 0 Then x := 0;
  If x > width - dicke Then x := width - dicke;
  If y < 0 Then y := 0;
  If y > width - dicke Then y := height - dicke;

  canvas.brush.color := clnavy;
  canvas.ellipse(x, y, x + dicke, y + dicke);
  canvas.MoveTo(50, 0);
  canvas.lineto(50, 350);
  canvas.MoveTo(50, 400);
  canvas.lineto(50, 500);
  label1.Caption := inttostr(x);
  label2.caption := inttostr(y);

End;
Dieser Teil beschränkt das Feld deiner "Kugel" auf die Form und man kann nicht mehr raus laufen, evtl hilft dir das schon ein bischen weiter ;)

skaot 19. Nov 2008 15:21

Re: Anfängerhilfe Labyrinth
 
Danke für die schnelle antwort. Ich werde in Zukunft drauf achten.

Deine Hilfe hilft soweit, dass man nichtmehr links oder oben aus dem Bild herausaufen kann. Rechts ann man noch soweit das man noch die hälfte der Kugel sieht und unten kann man soweit herauslaufen wie man will.

Noedel 19. Nov 2008 15:43

Re: Anfängerhilfe Labyrinth
 
bei corpsman hat sich leider n kleiner fehler eingeschlichen
Delphi-Quellcode:
  If y > width - dicke Then y := height - dicke;
(findest du ziemlich weit unten im zweiten sourcecode.)

das muss ersetzt werden durch
Delphi-Quellcode:
  If y > height - dicke Then y := height - dicke;
damit läuft die kugel nicht mehr nach unten raus :)

dass die kugel n stück nach rechts aus dem feld flutscht, leigt daran, dass "x" wohl imkugel.left ist, oder?!
dann füg doch hier noch ein

Delphi-Quellcode:
 If (x+imkugel.width) > (width - dicke) Then x := width - dicke;

Corpsman 19. Nov 2008 15:51

Re: Anfängerhilfe Labyrinth
 
lol die Copy Paste Fehler.

das "Rauslaufen" liegt an was anderem.


du darfst nicht Widht und Height nehmen sondern must

ClientWidth und ClientHeigt stattdessen nehmen. Dann müste es stimmen.

skaot 19. Nov 2008 16:37

Re: Anfängerhilfe Labyrinth
 
Danke habs jetzt glaube ich :-D .

Hier mein Fertiger Quellcode
Delphi-Quellcode:
unit Pong;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    procedure FormKeyPress(Sender: TObject; var Key: Char);


  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  dicke, x, y: integer;

implementation

{$R *.dfm}



procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);

begin
  dicke := 20;


  if key = 's' then begin    // Bewegung nach unten
    form1.Refresh;
    y := y+10;
  end;


  if key = 'd' then begin    // Bewegung nach rechts
    form1.Refresh;
  x := x+10;
  end;


  if key = 'a' then begin   // Bewegung nach links
    form1.Refresh;
    x := x-10;
  end;

  if key = 'w' then begin   // Bewegung nach oben
    form1.Refresh;
    y := y-10;
  end;

  If x < 0 Then x := 0;                                     // Spielfeldbegrenzungen
  If x > clientwidth - dicke Then x := clientwidth - dicke;
  If y < 0 Then y := 0;
  If y > clientheight - dicke Then y := clientheight- dicke;


  if (x = 40) and ((y < 350) or (y > 380)) then x := 30;      // Stoppen des Balles an Barikaden
  if (x = 90) and ((y < 50) or (y > 80)) then x := 80;
  if (x = 140) and ((y < 200) or (y > 230)) then x := 130;
  if (x = 190) and ((y < 400) or (y > 430)) then x := 180;

  if ((x > 380) and (x < 450)) and ((y > 180) and (y < 250)) then Label3.Caption := 'sieger'; // Betreten des Zielfeldes

  canvas.MoveTo(50,0);              // Barrikaden
  canvas.lineto(50,350);
  canvas.MoveTo(50,400);
  canvas.lineto(50,clientheight);
  canvas.moveto(100,0);
  canvas.LineTo(100,50);
  canvas.moveto(100,100);
  canvas.Lineto(100,clientheight);
  canvas.moveto(150,0);
  canvas.LineTo(150,200);
  canvas.moveto(150,250);
  canvas.Lineto(150,clientheight);
  canvas.moveto(200,0);
  canvas.LineTo(200,400);
  canvas.moveto(200,450);
  canvas.Lineto(200,clientheight);
 
  canvas.Brush.Color := clgreen;  // Zielfeld
  canvas.Rectangle(400,200,450,250);

  label1.Caption := inttostr(x);  // Punktkoordinaten
  label2.caption := inttostr(y);

  canvas.brush.color := clnavy;      // Kugel
  canvas.ellipse (x,y,x+dicke,y+dicke)
  end;
end.

skaot 19. Nov 2008 17:22

Re: Anfängerhilfe Labyrinth
 
Hab noch ne kleine Änderung gemacht aus den canvas.moveto und canvas.lineto hab ich canvas.rectangle gemacht.
Kann man irgendetwie das Flackern verhindern?

Corpsman 19. Nov 2008 17:34

Re: Anfängerhilfe Labyrinth
 
Ja kannst du,

in meiner ursprünglichen Verbesserung sollte das Form1.refresh sowieso raus.

Wenn du es aber ganz richtig machen willst machst du es Double Buffered.

Dazu gehst du her und nimmst ein TBitmap das du immer genau gleich groß hälst wie deine Form.

und am Anfang vom OnKey machst du dann was in der Art :

Delphi-Quellcode:
var b:Tbitmap;

Procedure Tform1.OnKeyIrgendwas(..);
begin
b.canvas.rectangle(-1,-1,clientwidth+1,clientheight+1);
with b.canvas do begin

(*
Der Ganze Alte Code
*)


// Am Schluss
form1.canvas.draw(0,0,b);
end;
Dann flackert nichts mehr.

Sir Rufo 19. Nov 2008 17:36

Re: Anfängerhilfe Labyrinth
 
Noch etws kürzer und übersichtlicher ...
Delphi-Quellcode:
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
const
  Step = 10;
begin
  dicke := 20;

  // Auf dem Form hat sich bis hier nix geändert, also

  form1.Refresh; // <--- ist das wirklich notwendig?

  // es geht noch kürzer

  if key = 's' then Inc( y, Step );   // Bewegung nach unten
  if key = 'd' then Inc( x, Step );   // Bewegung nach rechts
  if key = 'a' then Inc( x, -Step );   // Bewegung nach links
  if key = 'w' then Inc( y, -Step );   // Bewegung nach oben

  // der rest bleibt wie gehabt
cu

Oliver

@Corpsman: genau

skaot 19. Nov 2008 17:56

Re: Anfängerhilfe Labyrinth
 
Zitat:

Zitat von Corpsman


Delphi-Quellcode:
var b:Tbitmap;

Procedure Tform1.OnKeyIrgendwas(..);
begin
b.canvas.rectangle(-1,-1,clientwidth+1,clientheight+1);
with b.canvas do begin

(*
Der Ganze Alte Code
*)


// Am Schluss
form1.canvas.draw(0,0,b);
end;
Dann flackert nichts mehr.

Mhh das sagt der mir was vonwegen Zugriffsverletzung.

guidok 19. Nov 2008 18:57

Re: Anfängerhilfe Labyrinth
 
Die Variable b ist zwar vom Typ TBitmap, aber du musst natürlich eine Instanz davon erzeugen, bevor du sie benutzen kannst.

Delphi-Quellcode:
b := TBitmap.Create;
Damit wird ein Objekt vom Typ TBitmap erzeugt, d.h. unter anderem wird der dafür benötigte Speicher reserviert. Um diesen Speicher auch wieder freizugeben musst du, wenn du "b" nicht mehr brauchst auch noch


Delphi-Quellcode:
b.Free;
einfügen. Damit wird die Instanz wieder freigegeben.

Wo du das jetzt machen musst, hängt davon ab wo du "b" deklarierst. In diesem Fall wäre es OK "b" als lokale Variable in deiner "KeyPress" Prozedur zu deklarieren. Demnach erzeugst du "b" bevor du es verwenden willst und gibst es am Ende wieder frei.

Übrigens: Ich halte es für sehr wichtig, dass du auch verstehst, was dir hier gezeigt wird. Einfaches Abtippen bringt dir rein gar nichts. Im Zweifelsfall frag lieber mal nach, was "b" überhaupt bewirken soll.

skaot 19. Nov 2008 20:18

Re: Anfängerhilfe Labyrinth
 
Liste der Anhänge anzeigen (Anzahl: 1)
Also das mit dem Bitmap check ich grad gar nicht :lol: Werde mal im internet nach ein paar anständigen Tutorials suchen.
Und ich hab noch ne kleine Frage. Wie schaffe ich es das wenn ich auf Vollbild schalte nicht nur das formular größer wird sondern alles "gestreckt" wird?

Aber schon ermutigend was man als Anfänger schon so alles anstellen kann.

Corpsman 20. Nov 2008 06:47

Re: Anfängerhilfe Labyrinth
 
Also wenn du die TBitmap vairante hast dann ist das mit dem "Größer" werden Kein Problem

du kannst dann anstatt

Delphi-Quellcode:
Form1.canvas.draw(0,0,b);
einfach

Delphi-Quellcode:
Form1.canvas.stretchdraw( ... );
nehmen. Für die Genaue parametriesierung hilft die F1 Taste ;).

skaot 20. Nov 2008 14:50

Re: Anfängerhilfe Labyrinth
 
Ich glaube ich lass das mit Bitmap erstmal weg versteh das nicht so wirklich.

Noedel 20. Nov 2008 15:32

Re: Anfängerhilfe Labyrinth
 
noch zwei fragen:

1) warum zeichnest du die barrikaden immer wieder bei jedem knopfdruck?
2) Ich werde aus dem obigen Code nicht schlau, wie die zweite Kugel bewegt werden soll!?

Corpsman 20. Nov 2008 15:32

Re: Anfängerhilfe Labyrinth
 
Du kannst dir ja mal mein PingPong Sample anschaun, da habe ich diese BMP Technik benutzt.

Evtl wirds dann verständlicher ;).

skaot 20. Nov 2008 18:38

Re: Anfängerhilfe Labyrinth
 
Zitat:

Zitat von Noedel
noch zwei fragen:

1) warum zeichnest du die barrikaden immer wieder bei jedem knopfdruck?
2) Ich werde aus dem obigen Code nicht schlau, wie die zweite Kugel bewegt werden soll!?

1) Habs bestimmt zu kompliziert gemacht aber bei jedem Knopdruck wird erst einmal das gesamte bild gelöscht, damit das die alte position der Kugel gelöscht wird. Dann rstelle ich alles neu mit der neuen Position der Kugel.
2) Indem man mit der 1. dagegen "läuft".( Am Anfang 1mal J drücken hatte ich vergessen mit rein zuschreiben)

guidok 21. Nov 2008 06:25

Re: Anfängerhilfe Labyrinth
 
Zitat:

Zitat von skaot
Ich glaube ich lass das mit Bitmap erstmal weg versteh das nicht so wirklich.

Der Sinn des Ganzen sollte klar sein. So wie du es machst, löscht du die Zeichenfläche (Canvas) und zeichnest sie neu und zwar zeichnest du auf der sichtbaren Zeichenfläche (Canvas des Formular). Das führt dann zum Flackern.

Die Lösung ist es zunächst einmal auf einem anderen, nicht sichtbaren, Canvas zu zeichnen und dies dann mittels einer schnellen Methode auf das sichtbare Canvas zu legen.

Also erzeugst du ein Bitmap, das dir ein Canvas bereitstellt, auf dem du zeichnen kannst. Sobald du damit fertig bist, zeigst du dein frisch (unsichtbar) gezeichnetes Canvas an.

Soweit klar?

Das Erzeugen, Zuweisen und Entfernen von Objekten sind Grundlagen, die du völlig unabhängig von deiner Lösung unbedingt verstehen solltest. Ich verweise, wie so oft, auf diesen sehr guten Delphi Crashkurs.


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:48 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz