Entwickler-Ecke

Multimedia / Grafik - Springen?


breakdancer1111 - Di 10.06.03 10:48
Titel: Springen?
Hallo!
Ich bin dabei ein Jump'n Run Spiel in
Delphi zuschreiben. Nun häng ich an
der stelle fest, wo das mit dem Sprung kommt.

Wie kann man eine Person springen lassen
(es sollte möglichst echt aussehen), also nicht
einfach nur die Person hoch und wieder
runter setzen.

cYa


Tweafis - Di 10.06.03 10:52

Du machst ne var

spungy die machst du beim start auf z.b. 3 und ziehst jeden frame 0.x davon ab und wenn man wieder auf dem boden steht setzt du sie auf null damit hast du gravitation mit eingebaut...

Mein Tipp...


breakdancer1111 - Di 10.06.03 14:10

Zitat:
Du machst ne var

spungy die machst du beim start auf z.b. 3 und ziehst jeden frame 0.x davon ab und wenn man wieder auf dem boden steht setzt du sie auf null damit hast du gravitation mit eingebaut...

Mein Tipp...


Kannst du mir vielleicht einen Codeschnipsel
posten?! :oops: [/quote]


Tweafis - Di 10.06.03 16:04

Nein, da ich eine Ahnung von DelphiX hab

beim Sprunganfang:

yvel := 1;

bei jedem Sprungframe:

yvel := yvel-0.05;

Du kannst aber auch immer testen ob die Sprungtaste gedrückt ist (dann speichern um sprung im sprung zu verhindern) und solange hochhüpfen bis sie losgelassen wird, die Decke erreicht oder eine bestimmte Zeit gesprungen worden ist und dann erst die yvel verringern.

Dann die Y Position immer um yvel erhöhen und dann per kollisionserkennung testen ob die figur im boden drinsteckt und falls ja yvel auf 0 stellen und die Figur solange hochschieben (per whileschleife) bis sie wieder auf dem Boden ist. Die X Koordinate kannst du ganz normal weiter machen.


breakdancer1111 - Di 10.06.03 17:24

Also ungefähr so?

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procdure TPlayer.DoMove(MoveCount: Integer);
begin
  if isButton1 in Form1.Input.States then
  begin
     Player.Y := Y-1;
     if Player.Y = 25 then
       Player.Y := Player.Y+1;
   end;
end;



Oder hab ich da was falsch verstanden?


Moderiert von user profile icontommie-lie: Code- durch Delphi-Tags ersetzt


Tweafis - Di 10.06.03 20:23

weiß ich nicht, blick bei deinem Code nicht durch

<-- DelphiX nixwisser


breakdancer1111 - Di 10.06.03 20:41

Zitat:
<-- DelphiX nixwisser


Biste nicht alleine. Ist hier vielleicht jemand
der ahnung hat? :?: [/quote]


Tweafis - Di 10.06.03 20:47

Veringer einfach jeden Frame eine globale Variable und füge sie zum Y Wert deiner Figut hinzu (dann noch das in den Boden rammen vermeiden) oder halt die Variable erst veringern anfangen wenn eine bestimmte höhe erreicht/eine bestimmte Taste nicht mehr gedrückt/die decke erreicht ist.

Dann musst du noch aufpassen, dass man nich wenn man schon aufgehört hat zu springen nochmal springen kann. also ne sprung vari auf true setzen wenn man auföhrt zu springen und anfängt zu fallen (wenn eine bestimmte höhe erreicht/eine bestimmte Taste nicht mehr gedrückt/die decke erreicht ist) und beim antreffen auf den Boden wieder auf false. Die testest du dann bei jedem Sprungtastenklick und falls sie true ist kann man nicht springen und falls false schon.


Sieht ziemlich verwirrend aus, Ich weiß, und hört sich auch so an...


Elayla - Di 10.06.03 22:08

Ok ich hab mal schnell was kleines getippt, das sieht zwar nicht so wirklich wie ein sprung aus, aber da kannst ja selber dran feilen oder ich probier noch bissl:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
var
  Form1: TForm1;
  xorig:integer = 150;
  yorig:integer = 150;
  x,y:integer;
  druck:boolean;



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure TForm1.FormCreate(Sender: TObject);
begin
  x:=xorig;
  y:=yorig;
  druck:=true;
end;



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
procedure TForm1.DXTimer1Timer(Sender: TObject; LagCount: Integer);
begin
  DXDraw1.Surface.Fill(0);
  DXImageList1.Items[0].Draw(DXDraw1.Surface,x,y,0);
  DXDraw1.Flip;
  DXInput1.Update;
  If isUp in DXInput1.States Then
  Begin
    if druck = true Then
    Begin
       Repeat
         DXDraw1.Surface.Fill(0);
         y:=y-3;
         DXImageList1.Items[0].Draw(DXDraw1.Surface,x,y,0);
         DXDraw1.Flip;
       Until y<=yorig-100;
      druck:=false;
    End;
    if y<=yorig-90 Then
      Begin
        Repeat
          DXDraw1.Surface.Fill(0);
          y:=y+3;
          DXImageList1.Items[0].Draw(DXDraw1.Surface,x,y,0);
          DXDraw1.Flip;
        Until y>=yorig;
      druck:=true;    
      End;
  End;
  DXDraw1.Flip;
end;


Dafür brauchste ein DXDraw-Feld, 1 DXTimer intervall 0 DXInput-Komponente.
Timer auf OnTimer einstellen und das wars.
Musste bei dir halt in entsprechender Weise einprogrammieren.
Hoffe das hilft dir ein büsschen weiter :wink:

Moderiert von user profile iconUGrohne: Quote- durch Delphi-Tags ersetzt


Elayla - Di 10.06.03 22:13

Um während des laufes zu springen muss das noch bissl anders aussehen, mal sehen ob ich das heut noch hinbekomme :wink:


umpani - Di 10.06.03 22:49

So wie ich das verstanden habe, möchtest du einen möglichst realistischen sprung zu bekommen.

Hierbei geht es also nicht um die technik der Grafischen Umsetzung, sondern um pure Mathematik :twisted:

Ich habe also die Kenntnisse aus meiner Schulzeit herausgekramt:

Bitte schnall dich an :wink:

y(x) = - (g / (2*V0²*cos²*@0))*x²+(tan@0)*x+H0


y(x) ist dié momentane Höhe des Sprungesan der Postition x (x = 0 bei Beginn des Sprunges und dan Pixelweise weiter)
g ist die Gravitation - auf der erde ca 9,8 oder so.
V0 ist die Anfangsgeschwindigkeit des Sprunges
@0 ist der Absprungwinkel

Aber nun genug der Schnöden Mathematik.

Ich habe auch mal ein kleines Progreamm geschrieben: ein springender Ball. Ich hoffe, dass hilft Dir.
http://www.cbs-shop.de/webser/parabel.zip


Elayla - Di 10.06.03 22:54

Jup das is nett, ich war auch schon dran mit der Parabelgleichung vom schrägeb Wurf zu hantieren, aber irgendwas ging bei mir nicht, was ich nicht so verstehe ist der Teil im Timer bei dir :roll:
Kannste den mal kurz erklären? :oops:


umpani - Di 10.06.03 23:05

Klar:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  kreis.Top := 300-parabelfunct(ix);
  kreis.Left := ix+abs;
  ix := ix + 3;
  if parabelfunct(ix) < 0 then
    begin
      abs := abs+ix;
      ix := 1;
    end;
end;


Alle 20 ms wird die Funktion Timer1Timer aufgerufen (es muss natürlich auch ein Timerobjekt plaziert sein).

kreis.Top := 300-parabelfunct(ix);
Der y Koordinate des Kreises wird der Wert der Parabelgleichung zugewiesen. "300-" bewirkt nur, dass sich Die Springbewegung spiegelt. sonst hätte man einen "tauchenden" Kreis.

kreis.Left := ix+abs;
die X koordinate bekommt den wert x zugewiesen. (abs ist nur der x-Wert des Sprungausgangspunktes. Der Ball so ja mehrere prünge machen)

ix := ix + 3;
Damit der Ball von der Stelle kommt.

if parabelfunct(ix) < 0 then
begin
abs := abs+ix;
ix := 1;
end;


Wenn der ball unter die Null-linie kommt ist bei mir der prung vorbei und der Ball hüpft wieder hoch. (Bei einem Jump'n Run müsste hier eine Kollisionsabfrage rein.
Der prungausgangspunkt abs wird auf den aktuellen x-wert gesetzt.
ix wird wieder auf 1 Gesetzt.




[/quote]


Elayla - Di 10.06.03 23:07

Ahh ok jetzt is mir alles klar, danke :)


Tweafis - Mi 11.06.03 07:36

Sorry, meins war eher so ne Vereinfachte Version...


breakdancer1111 - Do 12.06.03 19:35

Elayla hat folgendes geschrieben:
Ok ich hab mal schnell was kleines getippt, das sieht zwar nicht so wirklich wie ein sprung aus, aber da kannst ja selber dran feilen oder ich probier noch bissl:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
var
  Form1: TForm1;
  xorig:integer = 150;
  yorig:integer = 150;
  x,y:integer;
  druck:boolean;



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure TForm1.FormCreate(Sender: TObject);
begin
  x:=xorig;
  y:=yorig;
  druck:=true;
end;



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
procedure TForm1.DXTimer1Timer(Sender: TObject; LagCount: Integer);
begin
  DXDraw1.Surface.Fill(0);
  DXImageList1.Items[0].Draw(DXDraw1.Surface,x,y,0);
  DXDraw1.Flip;
  DXInput1.Update;
  If isUp in DXInput1.States Then
  Begin
    if druck = true Then
    Begin
       Repeat
         DXDraw1.Surface.Fill(0);
         y:=y-3;
         DXImageList1.Items[0].Draw(DXDraw1.Surface,x,y,0);
         DXDraw1.Flip;
       Until y<=yorig-100;
      druck:=false;
    End;
    if y<=yorig-90 Then
      Begin
        Repeat
          DXDraw1.Surface.Fill(0);
          y:=y+3;
          DXImageList1.Items[0].Draw(DXDraw1.Surface,x,y,0);
          DXDraw1.Flip;
        Until y>=yorig;
      druck:=true;    
      End;
  End;
  DXDraw1.Flip;
end;


Dafür brauchste ein DXDraw-Feld, 1 DXTimer intervall 0 DXInput-Komponente.
Timer auf OnTimer einstellen und das wars.
Musste bei dir halt in entsprechender Weise einprogrammieren.
Hoffe das hilft dir ein büsschen weiter :wink:

Moderiert von user profile iconUGrohne: Quote- durch Delphi-Tags ersetzt




Danke für deine Hilfe, leider klapts nicht so ganz. Gibt es
eine möglichkeit das ganze als animation zu machen
und diese mit der Leertaste oder hochfeil Taste zu
starten? Wäre vielleicht erst mal ne bessere Lösung.


Elayla - Do 12.06.03 19:41

Schau mal hier rein, das dürfte dir hoffentlich helfen :)
http://www.delphi-treff.de/content/tutorials/delphixkurs/index.php4?kat=4


breakdancer1111 - Do 12.06.03 20:20

Hilft mir nicht wirklich weiter, da ich schon
ne animation verwende. Würde der Code
fürs springen dann folgendermaßen aussehen?


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
if isButton1 in Form1.Input1.States then
         begin
            // Animation starten      
            Player.Image := Form1.DXImageList1.Items.Find('1');
            Player.X := 0;
            Player.Y := 0;
            Player.Width := Player.Image.Width;
            Player.Height := Player.Image.Height;
            Player.AnimCount := 5;
            Player.AnimLooped := True;
            Player.AnimSpeed := 20/1000;
            Player.AnimStart := 0;
       end;


Oder liege ich mal wieder komplett daneben?


umpani - Do 12.06.03 22:31

Ich glaube, da will jemand den Quelltext su seinem Spiel geschrieben haben? :wink:

Aber ich will mal nicht so sein.

Zunächst würde ich perönlich die Animations-Sprite Engine von Delphi X nicht benutzen. Sie mag zwar einfacher zu bedienen sein, aber schränkt einen auch sehr ein.

Und nun zum Springen.

Ich habe mich noch mal ne halbe Stunde an meinen Kasten gesetzt und aus meinem Springenden Kreis einen mit der tastatur steuerbaren Super Mario gemacht. Natürlich nur ganz Simpel und der Quellcode ist auch nicht gerade optimiert. Schau es Dir einfach an.
Man kann nach vorne und zurücklaufen und springen.

Guckst Du Hier;
http://www.cbs-shop.de/webser/mario.zip


Wenn Du noch fragen hast...ich bin hier.

Gruß Umpani[/url]


breakdancer1111 - Fr 13.06.03 15:09

Geht das auch mit Sprites?


umpani - Fr 13.06.03 16:31

Bestimmt,

habe aber noch nie mit Sprites gearbeitet. Das musst du mal jmd. anderen Fragen. Sorry :oops:


breakdancer1111 - Fr 13.06.03 17:45

Aso, naja ist ja auch nicht so schlimm.
Ist den jemand hier der mit Sprites arbeitet?
:oops:


Da_Knuddelbaer - Sa 14.06.03 09:26

Ich arbeite zur Zeit ziemlich viel mit 2D-Sprites, wie kann ich helfen?


umpani - Sa 14.06.03 11:12

breakdancer1111 hatte das Problem, eine Figur realistisch springen zu lassen.
Ich habe ihm darum ein kleines, unoptimiertes Programm geschrieben, in dem man eine Figur rechts und links laufen und dazu auch noch springen lassen kann.

Zu breakdanver1111s Bedauern habe ich jedoch keine Sprites bzw. die Animationsengine/TDXSprites benutzt, sondern eine eigene Animation mittels DXImagelist / Patterns aufgebaut (haltge ich persönlich auch für flexibler als die DXSprites).

Nun will breakdancer dieses Programm ([url]http://www.cbs-shop.de/webser/mario.zip [/url]) mit einer Sprite-engine haben.

Nocht verwundert sein. Ich habe das Programm wirklich nicht optimiert.


Da_Knuddelbaer - Sa 14.06.03 12:33

Also einfach das ganze Gedöns nur mit Sprites, richtig ja?

...

Dein Beispiel ist doch schon ein guter Anfang dafür :shock:
Jetzt ersetzt du den simplen Timer einfach durch den DXTimer, setz das Intervall auf 20, dann trägst du eine Spriteklasse ein (was du mit deinem PlayerSprite wahrscheinlich eh schon hast @breakdancer).
Ich nehme jetzt auch mal an das du die SpriteEngine von DelphiX verwendest. Wenn dem so sein sollte, dann ist es recht simpel:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
{$R *.DFM}

type
  TSpielerSprite = class(TImageSprite)
  protected
    procedure DoMove(MoveCount: Integer); override;
  public
    constructor Create(AParent: TSprite); override;
  end;



constructor TPlayerSprite.Create(AParent: TSprite);
begin
  inherited Create(AParent);
  Image := MainForm.ImageList.Items.Find('Player1.bmp');
  Width := Image.Width;
  Height := Image.Height;

  X := MapSize;
  Y := MapSize;
  Z := 2// schlicht die Z-Koordinate, bei mehreren Sprites nützlich
end;


procedure TPlayerSprite.DoMove(MoveCount: Integer);
begin
  inherited DoMove(MoveCount);

      if isUp in Form1.DXInput.States then Y := Y - (250/1000)*MoveCount;
      if isLeft in Form1.DXInput.States then X := X - (250/1000)*MoveCount;
      if isRight in Form1.DXInput.States then X := X + (250/1000)*MoveCount;
end;


Und anstelle von dem angegebenen isUp verwendest du jetzt einfach den wirklich guten Quellcode von Umpani, animierst es noch schön und dann müsste es eigentlich klappen. In der DXImageList musst du vor dem Animieren aber noch die Größe jedes Sprites einstellen, so wie Umpani es gemacht hat, also die PatternHeight und PatternWidth. Die Animation spielst du aber am besten nicht komplett ab, sondern nur inwieweit man sich bewegt, danach setzt du den animation-start auf den aktuellen Frame des Sprites... und mach das looped aus!
Ach ja und stopf die beiden Richtungen in einen Sprite rein.
Tjoa, und ansonsten so: Mach das DXDraw.Flip nur am Ende des DXTimers einmal hin, das genügt vollkommen.

Greetz,
Knuddelbaer


umpani - Sa 14.06.03 12:42

Eine Korrektur noch von mir:

Ich habe bei der Parabelfunktion eine Konstante mit dem Absprungwinkel.
Dieser Konstante habe ich einen wert "45" zugewiesen.

Dies ist falsch. Der Absprungwinkel wird im Bogenmaß angegeben also von "0" bis "1" z.b. "0.6"


Nur zur Information


Da_Knuddelbaer - Sa 14.06.03 12:58

Deswegen siehts auch leicht komisch aus am anfang vom sprung, wa?


umpani - Sa 14.06.03 13:08

Mag sein.

Wie gesagt, ich habe mich nicht lange damit beschäftigt (max. ne Stunde). Es sollte ja auch nur ne Anegung sein. :)


Da_Knuddelbaer - Sa 14.06.03 13:13

jo aber eine gute Anregung ;)
Ab und zu wackelt die Figur auch nen bissel und blinkt für ganz kurze Zeit ausserhalb des Fensters... aber naja, was solls *g* Ist trotzdem ein gutes Beispiel.