Delphi-PRAXiS
Seite 2 von 4     12 34      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Problem mit Multiplikation (https://www.delphipraxis.net/176104-problem-mit-multiplikation.html)

Aviator 12. Aug 2013 23:19

AW: Problem mit Multiplikation
 
Sei doch so gut und setze deinen Code in Delphi Tags, damit die Formatierung (sofern eine vorhanden) beibehalten bleibt. Das ist der Delphi-Helm in der Mitte von den Editor-Symbolen.

Dan sieht dein Quellcode nämlich so aus:

Delphi-Quellcode:
procedure TForm1.Testprocedure;
begin
  ShowMessage('Delphi TagsTest');
end;

Perlsau 12. Aug 2013 23:19

AW: Problem mit Multiplikation
 
Zitat:

Zitat von Pfusch (Beitrag 1224519)
Liegt es am Single das es nicht funktioniert, weil ich nämlich einen Float Wert bräuchte, deswegen ist es mit Integer nicht möglich.

Es geht doch aber offensichtlich um Bildschirm-Koordinaten, und dafür benötigt man keine Float-, sondern Integer-Werte. Dennoch, bei mir funktioniert das einwandfrei:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
Var
   Zahl : Single;
   S   : String;

begin
   S := Label1.Caption;
   Zahl := StrToFloat(S);
   Zahl := Zahl * -1;
   S := FloatToStr(Zahl);
   Label1.Caption := S;
end;
Wieso funktioniert dein Beispiel nicht?

Bjoerk 12. Aug 2013 23:33

AW: Problem mit Multiplikation
 
Zitat:

Zitat von Pfusch (Beitrag 1224519)
@Bjoerk
Weiß zwar nicht von welchem Buch du redest aber der Quellcode ist nur von mir selbst^^.

Ok, Sorry, wollte dich nicht vollquatschen, hatte das nur vermutet.

In deinem Code muß es aber heißen:

Delphi-Quellcode:
 Ball := TBall.Create(0,-1);

Medium 12. Aug 2013 23:48

AW: Problem mit Multiplikation
 
Ob nun Integer oder Float macht doch hier überhaupt keinen Unterschied. Es wird ja nirgends ein Vergleich mit Konstanten gemacht, sondern nur gerechnet. Leider ist das noch immer ein wenig wenig Code. Es ist z.B. nicht ersichtlich, in welchem Scope sich die Variable "Ball" befindet, und beim fehlenden "end;" der Klassendeklaration hoffe ich, dass es wirklich einfach nur nicht mit kopiert wurde. Ich denke Bjoerk liegt schon mal ganz gut, seltsam ist jedoch, dass es bei dir dann keine Zugriffsfehler hagelt. Fazit: Die Erzeugung ist definitiv schon mal ein Fehler, aber leider immer noch zu wenig Kontext.

Zum Schluss noch ein kleiner Tipp. Man kann in case-Statements ganz nett Dinge zusammenfassen:
Delphi-Quellcode:
procedure TBrick.onCollision(Edge: Integer; Ball: TBall);
begin
  case Edge of
    1, 2: Ball.YSpeed := Ball.YSpeed * -1;
    3, 4: Ball.XSpeed := Ball.XSpeed * -1;
  end;
end;
Ist Kosmetik, reduziert aber Arbeit bei Änderungen :)

Pfusch 13. Aug 2013 00:39

AW: Problem mit Multiplikation
 
So habe jetzt einige Umschichtungen bei meinem Code vorgenommen, das hat das Problem aber leider nicht gelöst, aber dafür ist er jetzt etwas übersichtlicher. Habe jetzt mal meine ganzen Units bis auf ein paar unwichtige Kommentare etc. reinkopiert. Wenn ich ein Integer statt Single verwende funktioniert es übrigens auch nicht.
Nochmal vielen Dank für die bisherigen Vorschläge.

Delphi-Quellcode:
unit ufrmBreakout;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, uCoords, uBrick, UPaddle, UBall;

type
  TfrmBreakout = class(TForm)
    lblTime: TLabel;
    lblScore: TLabel;
    ptbGame: TPaintBox;
    TmrGame: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure TimerTick(Sender: TObject);

  private
    bricks : TList;
    paddle : TPaddle;
    balls : TList;

  end;

const
  BrickColumn = 8;
  BrickRows = 5;
  PaddleStartX = 192;
  PaddleStartY = 380;
  BallStartAngle = 90;

var
  frmBreakout: TfrmBreakout;

implementation

{$R *.dfm}

  procedure TfrmBreakout.FormCreate(Sender: TObject);

  var
    Coords: TCoords;
    Brick: TBrick;
    x,y: Integer;
    xBall, yBall : Integer;

  begin
       //create the bricks
       bricks := TList.Create;
       for x := 0 to (BrickColumn-1) do
       begin
            for y := 0 to (BrickRows-1) do
            begin
                 Coords := TCoords.Create(x*uBrick.BrickWidth,y*uBrick.BrickHeight);
                 Brick := TBrick.Create(Coords);
                 bricks.Add(Brick);
            end;
       end;

       //create the paddle
       Coords := TCoords.Create(PaddleStartX,PaddleStartY);
       paddle := TPaddle.Create(Coords);

       //create the ball
       xBall := PaddleStartX + (uPaddle.PaddleWidth div 2);
       yBall := PaddleStartY - UBall.BallRadius;
       Coords := TCoords.Create(xBall,yBall);
       balls := TList.Create;
       balls.Add(TBall.Create(Coords,BallStartAngle,0,-1));

  end;

  procedure TfrmBreakout.TimerTick(Sender: TObject);
  var
    i, j : Integer;
    Ball: TBall;
    Brick: TBrick;

  begin
       for i := 0 to balls.Count-1 do
       begin
            Ball := balls[i];
            for j := 0 to bricks.Count-1 do
            begin
                 Brick := bricks[j];
                 Brick.Collide(Ball);
            end;
            Ball.Coords.X := Ball.Coords.X+round(Ball.XSpeed);
            Ball.Coords.Y := Ball.Coords.Y+round(Ball.YSpeed);
            lblScore.Caption := 'y: ' + FloatToStr(Ball.YSpeed);
       end;

  end;

  end.
Delphi-Quellcode:
unit uBrick;

interface

uses uCoords, uBall;

const
  BrickHeight = 32;
  BrickWidth = 64;

type
  TBrick = Class

  private
    fCoords : TCoords;

  public
    Constructor Create(coords: TCoords);
    Destructor Destroy(); override;
    property Coords: TCoords read fCoords;
    procedure Collide(Ball: TBall);
    procedure onCollision(Edge: Integer; Ball: TBall);
    function RightX : Integer;
    function BottomY : Integer;

end;

implementation

  constructor TBrick.Create(coords: TCoords);
  begin
       self.fCoords := coords;
  end;

  destructor TBrick.Destroy;
  begin
       fCoords.Destroy();
       inherited;
  end;

  function TBrick.RightX() : Integer;
  begin
       Result := (self.fCoords.X + BrickWidth);
  end;

  function TBrick.BottomY() : Integer;
  begin
       Result := (self.fCoords.Y +  BrickHeight);
  end;

  procedure TBrick.Collide(Ball: TBall);
  begin
       if (Ball.Coords.X <= self.RightX()) and (Ball.Coords.X >= self.fCoords.X) and (Ball.Coords.Y = self.BottomY()) then
       begin
            OnCollision(1,Ball);
       end
       else if (Ball.Coords.X <= self.RightX()) and (Ball.Coords.X >= self.fCoords.X) and (Ball.Coords.Y = self.fCoords.Y) then
       begin
            OnCollision(2,Ball);
       end
       else if (Ball.Coords.Y <= self.BottomY()) and (Ball.Coords.Y >= self.fCoords.Y) and (Ball.Coords.X = self.fCoords.X) then
       begin
            OnCollision(3,Ball);
       end
       else if (Ball.Coords.Y <= self.BottomY()) and (Ball.Coords.Y >= self.fCoords.Y) and (Ball.Coords.X = self.RightX()) then
       begin
            OnCollision(4,Ball);
       end;
  end;

  procedure TBrick.onCollision(Edge : Integer; Ball : TBall);
  begin
       case Edge of
           1: Ball.YSpeed := Ball.YSpeed * (-1);
           2: Ball.YSpeed := Ball.YSpeed * (-1);
           3: Ball.XSpeed := Ball.XSpeed * (-1);
           4: Ball.XSpeed := Ball.XSpeed * (-1);
       end;
  end;

end.
Delphi-Quellcode:
unit uBall;

interface

uses uCoords, uCalculate;

const
  BallRadius = 8;

type
  TBall = Class

  private
    fCoords : TCoords;
    fDestCoords : TCoords;
    fAngle : Integer;
    fXSpeed : Single;
    fYSpeed : Single;

  public
    Constructor Create(coords: TCoords; angle: Integer; xspeed, yspeed : Single);
    Destructor Destroy(); override;
    property Coords: TCoords read fCoords;
    property DestCoords: TCoords read fDestCoords;
    property XSpeed: Single read fXSpeed write fXSpeed;
    property YSpeed: Single read fYSpeed write fYSpeed;

end;

implementation

  constructor TBall.Create(coords: TCoords; angle : Integer; xspeed, yspeed : Single);
  begin
       self.fCoords := coords;
       self.fAngle := angle;
       self.fXSpeed := xspeed;
       self.fYSpeed := yspeed;
  end;

  destructor TBall.Destroy;
  begin
       fCoords.Destroy();
       inherited;
  end;

end.
Delphi-Quellcode:
unit uCoords;

interface

type
  TCoords = Class

  private
    fx : Integer;
    fy : Integer;

  public
    Constructor Create(x,y: Integer);
    Destructor Destroy(); override;
    property X: Integer read fx write fx;
    property Y: Integer read fy write fy;

end;

implementation

  constructor TCoords.Create(x,y: Integer);
  begin
       self.fx := x;
       self.fy := y;
  end;

  destructor TCoords.Destroy;
  begin
       inherited;
  end;

end.

Volker Z. 13. Aug 2013 01:53

AW: Problem mit Multiplikation
 
Hallo,

Dein Problem ist sicher nicht die Multiplikation; die arbeitet - wie schon gezeigt - korrekt.
Das kannst Du auch leicht sehen, dazu musst Du nur Deinen Timercode etwas abändern:
Delphi-Quellcode:
procedure TfrmBreakout.TimerTick(Sender: TObject);
  var
    i, j : Integer;
    Ball: TBall;
    Brick: TBrick;

  begin
       for i := 0 to balls.Count-1 do
       begin
            Ball := balls[i];
            for j := 0 to bricks.Count-1 do
            begin
                 Brick := bricks[j];
                 Brick.Collide(Ball);
                 lblScore.Caption := 'y: ' + FloatToStr(Ball.YSpeed);
                 Application.ProcessMessages
            end;
            Ball.Coords.X := Ball.Coords.X+round(Ball.XSpeed);
            Ball.Coords.Y := Ball.Coords.Y+round(Ball.YSpeed);
       end;

  end;
Dann steht da auch irgendwann eine 1 - anstatt einer -1.

Gruß

Angel4585 13. Aug 2013 09:03

AW: Problem mit Multiplikation
 
Ich bin mir nicht sicher, hab grad keine IDE zum testen da, aber das da sieht für mich aus wie Durchfall:

Delphi-Quellcode:
  procedure TBrick.onCollision(Edge : Integer; Ball : TBall);
  begin
       case Edge of
           1: Ball.YSpeed := Ball.YSpeed * (-1);
           2: Ball.YSpeed := Ball.YSpeed * (-1);
           3: Ball.XSpeed := Ball.XSpeed * (-1);
           4: Ball.XSpeed := Ball.XSpeed * (-1);
       end;
  end;
Also in Java zumindest wird ohne ein break zwischendrin 1: und 2: (und 3: und 4: ) ausgeführt, was dann zur Folge hätte, dass es wieder das selbe Ergebnis wie davor ist.
Oder gabs das in Delphi garnicht?

Der schöne Günther 13. Aug 2013 09:07

AW: Problem mit Multiplikation
 
Nope, das ist schon richtig so.

Union 13. Aug 2013 09:09

AW: Problem mit Multiplikation
 
Zitat:

Zitat von Angel4585 (Beitrag 1224555)
Also in Java zumindest wird ohne ein break zwischendrin 1: und 2: (und 3: und 4: ) ausgeführt, was dann zur Folge hätte, dass es wieder das selbe Ergebnis wie davor ist.
Oder gabs das in Delphi garnicht?

Delphi-Referenz durchsuchencase stellt eine Lookuptabelle dar. Es wird nur eine Zeile ausgeführt und bereits der Compiler weigert sich zu kompilieren (Doppeltes case-Label) falls es Duplikate oder Überschneidungen gibt:
Delphi-Quellcode:
case x of
0..2 : y := -1;
1..3 : y := +1;
end;

Namenloser 13. Aug 2013 09:17

AW: Problem mit Multiplikation
 
Zitat:

Zitat von Angel4585 (Beitrag 1224555)
Oder gabs das in Delphi garnicht?

Zum Glück nicht!

Das ist einer der größten Designfehler in C/C++/Java/PHP meiner Meinung nach... Wann braucht man das Fallthrough schon mal? Einmal in hundert Jahren? Und wie oft vergisst man auf der anderen Seite einfach ein break und hat einen schwer zu findenden Bug?

Aber die Vermutung, dass der Code irgendwie doppelt ausgeführt wird, ist naheliegend.

Ich habe in der Vergangenheit auch die Erfahrung gemacht, dass es keine gute Kollisionsbehandlungs-Strategie ist, einfach blind die Geschwindigkeit zu negieren... nicht immer hebt sich die Negation auf wie hier, aber manchmal passiert es auch, dass ein Objekt an einer Kante kleben bleibt, weil ein Simulationsschritt nicht ausreicht, dass es das Objekt, mit dem es kollidiert, wieder verlässt, und so kehrt sich mit jedem Frame das Vorzeichen um und es bewegt sich effektiv gar nicht mehr. Problematisch sind auch Kollisionen mit mehreren Objekten gleichzeitig (könnt hier auch die Ursache sein).

Setz mal einen Breakpoint auf deine Kollisionsbehandlung, dann siehst du wahrscheinlich, was Sache ist.


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:25 Uhr.
Seite 2 von 4     12 34      

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