Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Der Klassiker Pong & die Winkel... (https://www.delphipraxis.net/13153-der-klassiker-pong-die-winkel.html)

Corelgott 11. Dez 2003 22:35


Der Klassiker Pong & die Winkel...
 
Hi Leute,

ich versuche mich gerade ein bisschen mit Pong (falls es einner nicht kennt so ne Art Tennis: Ein Ball zwei Schläger... :wall: )

Ist auch eigentlich nicht weiter schwierig aber, ich würde gerne das orginal Pong nachbauen und bei dem war der Schläger in acht Sengmente unterteilt. Je nach Segment prallte der Winkel in einem anderen Winkel ab (45 am Rand und 180 in der Mitte).

Das heist aber ich muss mich mal wieder mit Trigonometrie herrum schlagen....
:kotz:
*würg*

Das ist für mich eins der Themen, die ich noch nie verstanden habe und es vermutlich auch nicht mehr werde...

Also mein Ball kommt an, und soll dann vom Schläger abprallen. Der neue winkel soll aber nicht der einfallswinke sein, sonder so, als wäre der Schläger kein rechteck sondern eher eine art Ellipse (so glaube ich ist das mit den verschienden Winkel deutlicher...)

kann da mal vielleicht jemand in seiner "Code Kiste" kramen und nachsehen, ob er da so was rumliegen hat...

Falls ja kann man mir das mit Strg + C und Strg + V zukommen lassen?

THX
CU
Corelgott
:dp:

supermuckl 12. Dez 2003 00:19

Re: Der Klassiker Pong & die Winkel...
 
berechnung des winkels von einer koordinate zur anderen
Delphi-Quellcode:

function cortowink(x,y,x2,y2:single):single ;  // winkelfunktion umkehrung ( xy ---winkel?--> x2y2 )


//------------------------------------------------------------------------------
                                // x/y = anfangspunkt 0 // x2/y2 = endpunkt zu dem der winkel berechnet werden soll
function cortowink(x,y,x2,y2:single ):single ;   // funktion zum berechnen des winkels für x y -> x2 y2
var
wurzel: single;
begin
result := 0.1; // falls garnix von dem da unten funzt

//rechts oben kreishälfte - winkel berechnen   ( 360 - arcsin )
if ( (x2 > x) AND (y2 < y) ) then result := 360-radtodeg(arcsin((y-y2) / sqrt( ((x2-x)*(x2-x))+((y-y2)*(y-y2)) )));

// links unten kreishälfte
if ( (x2 < x) AND (y2 > y) ) then result := 180-radtodeg(arccos((x-x2) / sqrt( (x-x2)*(x-x2)+(y2-y)*(y2-y) ) ));

// links oben kreishälfte (  180 + arccos )
if ( (x2 < x) AND (y2 < y) ) then result := 180+radtodeg(arccos((x-x2) / sqrt( (x-x2)*(x-x2)+(y-y2)*(y-y2) ) ));

// rechts unten kreishälfte
if ( (x2 > x) AND (y2 > y) ) then result := radtodeg(arcsin((y2-y) / sqrt( ((x2-x)*(x2-x))+((y2-y)*(y2-y)) )));

// gerade werte  ( komma werte adden damit die flieger nicht haargenau geradeaus fliegen können )
// hoch
if ( (x2 = x) AND (y2 < y) ) then result := 270.1;
//runter
if ( (x2 = x) AND (y2 > y) ) then result := 90.1;
//links
if ( (x2 < x) AND (y2 = y) ) then result := 180.1;
//rechts
if ( (x2 > x) AND (y2 = y) ) then result := 0.1;
// punkt auf punkt
if ( (x2 = x) AND (y2 = y) ) then result := 0.1;
end;



//------------------------------------------------------------------------------
vielleicht hilfts ja bissi

zu deinem problem noch:

ball fliegt in einem winkel zum schläger
ball trifft schläger ( berechnen wieviel % am rand oder zur mitte hin )
winkel vom ball je nach flugrichtung nun verändern um 90° ( austrittswinkel )
und dazu noch x% - oder + damit der "ellypsenschläger" auch seine wirkung zeigt
-> ball mit neuem winkel weiterfliegen lassen bis er wieder irgendwo abprallt usw

supermuckl 12. Dez 2003 00:29

Re: Der Klassiker Pong & die Winkel...
 
achja für die funktionen wo man braucht um ball flugwinkel + geschwindigkeit = neue position von ball ( sin / cos )
hab ich auch den code.. aber der müsste eigentlich auch noch zu schaffen sein ;)

hier noch n paar funktionen:

vorberechnung der cos/sin ergebnisse:
Delphi-Quellcode:

  sina: array[0..360] of real;                 // vorberechnete werte für sin
  cosa: array[0..360] of real;                 // vorberechnete werte für cos

procedure initfunc;
var
i: integer;
begin
for i := 0 to 360 do begin
sina[i] := Sin(cycletorad( i / 360));
cosa[i] := Cos(cycletorad( i / 360));

end;
end;
hier noch bissi code wo ich fürs schiffe begewen mal gehabt habe:
Delphi-Quellcode:

              // BEWEGEN ( x/y verschieben )
                         if (sh[i].mode >= 1) then begin   // fliegt er ?
                         if (sh[i].typ = 1) then begin // jäger
                         sh[i].x := ( cosa[round(sh[i].a)] * (sh[i].v*1.1) )  + sh[i].x;
                         sh[i].y := ( sina[round(sh[i].a)] * (sh[i].v*1.1) )  + sh[i].y;
                         end;
                         if (sh[i].typ = 2) then begin // advjäger
                         sh[i].x := ( cosa[round(sh[i].a)] * (sh[i].v*1.8) )  + sh[i].x;
                         sh[i].y := ( sina[round(sh[i].a)] * (sh[i].v*1.8) )  + sh[i].y;
                         end;
                         if (sh[i].typ = 3) then begin // bomber
                         sh[i].x := ( cosa[round(sh[i].a)] * (sh[i].v*1.4) )  + sh[i].x;
                         sh[i].y := ( sina[round(sh[i].a)] * (sh[i].v*1.4) )  + sh[i].y;
                         end;
                         if (sh[i].typ = 4) then begin // trans
                         sh[i].x := ( cosa[round(sh[i].a)] * sh[i].v )  + sh[i].x;
                         sh[i].y := ( sina[round(sh[i].a)] * sh[i].v )  + sh[i].y;
                         end;
sh[] is array mit schiffen
sh[].x is x position
sh[].y is y position
sh[].a ist winkel in ° ( 0 -360 )
sh[].v ist geschwindigkeit ( pixel pro bild )

alles klar ? :>

Jens Schumann 12. Dez 2003 07:41

Re: Der Klassiker Pong & die Winkel...
 
Hallo,
da sich der Ball auf einer zweidimensionalen Fläche auf einer Geraden bewegt kann man die Bewegung auch mit einer Geradegleichung beschreiben:
Zitat:

y=m*x+b
Da gilt:
Zitat:

Einfallswinkel = Ausfallwinkel
muss die Steigung m mit -1 multipliziert werden und der neue Wert b für den Schnittpunkt mit der Y-Achse berechnet werden.
Im Falle eine Kollision ist also folgendes zu tun
Code:
m:=m-1
b:=y-m*x
wobei x und y die aktuelle Position des Ball's ist.

Habe gerade gelesen, dass der Schläger kein Rechteck sein soll.
Kein Problem. Dann multiplizierst Du die Steigung m nicht mit -1 sondern mit einem anderen aber negativen Wert. Den Multiplikator kannst Du in abhängig der Y-Koordinate des Auftreffpunktes des Ball's auf den Schläger berechnen.

supermuckl 13. Dez 2003 03:31

Re: Der Klassiker Pong & die Winkel...
 
genau so mit der steigung ( x oder y dazu zählen ) hab ich schon ein pong programmiert ( sogar netzwerkfähig )
aber das is total kacke weil da die geschwindigkeit auch noch verändert wird usw.. also bissi heikel
mit winkelberechnung wars dann besser ( in meinem 2. spieleversuch (weltraum ballerspiel wir das bekannte "USI") mit directx in 2D )

SirThornberry 13. Dez 2003 06:39

Re: Der Klassiker Pong & die Winkel...
 
Liste der Anhänge anzeigen (Anzahl: 1)
hab mal ne unit in den anhang gepackt mit der Klasse T2DMove. Da braucht man dann nur noch sagen Drehen um 2 Grad und dann vorwärts1 und der gibt einem die neue koordinate aus.

Jens Schumann 13. Dez 2003 08:49

Re: Der Klassiker Pong & die Winkel...
 
Hallo supermuckel,
Zitat:

is total kacke weil da die geschwindigkeit auch noch verändert wird usw..
Wo ändert sich denn die Geschwindigkeit ?

Mr.Dollar2k3 13. Dez 2003 09:10

Re: Der Klassiker Pong & die Winkel...
 
hi hab auch ne frage zu diesen thema wie machst du das mit der grafik in delphi???
gibs da so was wie opengl für delphi oder wie proggst du dass , würd mich mal interessieren da ich bis jetzt nur an programmen mich ausgetobt hab . :thuimb:

Corelgott 13. Dez 2003 15:09

Re: Der Klassiker Pong & die Winkel...
 
Hi Leute,

erst mal vielen Dank :thuimb: für die vielen tollen Antworten und Ideen :!:

Das hat echt geholfen... (Ich komm blos leider nur schleppend hinter her die einzelden Antworten aus zu probieren .... Zeitprobleme) :!:

Das mit dem Winkel bekomme ich so langsam in Griff... Es fehlen mir anscheidnen bei ein paar Rechnungen nur noch ein paar Faktoren :?

Wenn der Ball jetzt abprallt, fliegt er immer mit dem Winkel von 0 bzw. 180 Grad weg, aber das bekomme ich schon noch hin...

Wen 's interessiert hier der Code:

Code:
procedure TBall.ReverseX(X, Y, Degrees : Integer);
var
    arc : Real;

begin
    arc := 0.1; // Backup

    //rechts oben kreishälfte - winkel berechnen   ( 360 - arcsin )
    if ( (X > MyX) AND (Y < MyY) ) then
        arc := 360-radtodeg(arcsin((MyY-Y) / sqrt( ((X-MyX)*(X-MyX))+((MyY-Y)*(MyY-Y)) )));

    // links unten kreishälfte
    if ( (X < MyX) AND (Y > MyY) ) then
        arc := 180-radtodeg(arccos((MyX-X) / sqrt( (MyX-X)*(MyX-X)+(Y-MyY)*(Y-MyY) ) ));

    // links oben kreishälfte (  180 + arccos )
    if ( (X < MyX) AND (Y < MyY) ) then
        arc := 180+radtodeg(arccos((MyX-X) / sqrt( (MyX-X)*(MyX-X)+(MyY-Y)*(MyY-Y) ) ));

    // rechts unten kreishälfte
    if ( (X > MyX) AND (Y > MyY) ) then
        arc := radtodeg(arcsin((Y-MyY) / sqrt( ((X-MyX)*(X-MyX))+((Y-MyY)*(Y-MyY)) )));

    // gerade werte vermeiden

    if ( (X = MyX) AND (Y < MyY) ) then arc := 270.1;// hoch
    if ( (X = MyX) AND (Y > MyY) ) then arc := 90.1; //runter
    if ( (X < MyX) AND (Y = MyY) ) then arc := 180.1; //links
    if ( (X > MyX) AND (Y = MyY) ) then arc := 0.1; //rechts
    if ( (X = MyX) AND (Y = MyY) ) then arc := 0.1; // punkt auf punkt

    Arc := Arc + sign(StepY) * (90 + Degrees);



    StepX := ( cosa[round(arc)] * StepX);
    StepY := ( sina[round(arc)] * StepY);
end;
X und Y sind die Kooerdinaten des Punkets wo der Ball hin soll. So zu sagen der Bezugspunkt im Raum.
MyX und MyY sind Kooerdinaten des Balls
StepX und StepY ist die Geschwindigkeit in Pixel in X bzw. Y Richtung.

Na ja werde da noch ein bisschen weiterbasteln...

Ach ja an dieser Stelle ein ganz großes Dankeschön an Supermuckl bei dem ich den Code "klauen" und abwandel durfte!!!

So!!

Nun zu deiner Frage Mr.Dollar2k3:

mit dem Zeichen bin ich zwar auch noch nicht so ganz zu frieden aber ich mache das zur Zeit noch "per Hand". Ich schnappe mir das Bild und gehe es, im interessanten Bereich, in den das bilds des Balls, nachher rein soll, Pixel für Pixel durch und kombiniere den Ball mit dem Hintergrundbild.

das Sieht dann so auch:

Code:
procedure TDraw.Merge(Target : TBitmap; Source : TBitmap; Strength : Byte; Left, Top : Integer);
var
    X, Y : integer;
    pt, ps: ^PixArray;

begin
  Target.PixelFormat := pf24bit;

  for Y := 0 to Source.height - 1 do
  begin

    pt := Target.ScanLine[Top + Y]; //Get the Targetpicture's Line of Pixels
    inc(pt, Left); //Move focus to the interessting Area
    ps := Source.ScanLine[Y]; //Get the Sourcepicture's Line of Pixel

    for X := 0 to Source.width - 1 do begin

      if ((ps^[2] <> 255) or (ps^[0] <> 0) or (ps^[1] <> 0)) then //Dont add if Color is red
      begin
          pt^[2] := Round(ps^[2] * (Strength / 255 ) + pt^[2] * (1 - (Strength /  255))); //Red
          pt^[0] := Round(ps^[0] * (Strength / 255 ) + pt^[0] * (1 - (Strength /  255))); //Green
          pt^[1] := Round(ps^[1] * (Strength / 255 ) + pt^[1] * (1 - (Strength /  255))); //Blue
      end;

      inc(pt); //Next Pixel of the Target Picture
      inc(ps); //Next Pixel of the Source Picture
    end;
  end;
end;
Ich hole mir nen Pointer auf ein Pixel des Bildes
Code:
pt := Target.ScanLine[Top + Y];
Sehe mir die drei RGB werte an:
pt^[2] für Rot
pt^[0] für Grün
pt^[1] für Blau

und verändere sie entsprechend.
Strenght gibt dabei den Alpha werde des zu zeichnenden Bildes an.
falls du das genauer nachleden willst:
MSN Library

Aber das wird je nach der Menge der Objekte die ich zeichne auch ein bisschen langsam.... Ich bin auf der Suche nach was schnelleren... OpenGL, Direct Draw?
Bin noch nicht so ganz sicher..
Ein bisschen schwierig oder?
Kennt da jemand was flinkes angenehmeres?

Erst mal thx so weit

cya Corelgott


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:14 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