BCB - Spiel Beispiel kommentiert (wie mach ich das mit Canvas) 2D Game
-
Hallo Leute,
da in letzter Zeit hier mehrfach die Spieleprogrammierung mit dem BCB
erfragt und diskutiert wurde. Habe ich mir mal die (kleine) Mühe
gemacht und ein "Pong" Klone erstellt.Um mal zu Verhindern das hier noch mehr Fragen, ala wie scrolle ich ein Hintergrund
Bild usw. auftauchen (gruß an Ag3nt
)
Die Kommentare im Quellcode lesen sich zwar als hätte es ein "Nicht Deutscher" geschrieben,
aber ich wollte mich nicht besonders lange damit aufhalten und hab es auf die Schnelle
runtergesabert, aber ich denke man kann es schon verstehen.Das Projekt ist mit dem BCB6pro erstellt worden, um es auch in älteren
Versionen zu Verwenden braucht man nur ein neues Projekt zu erstellen
und die Grafiken sowie die "Resourcen.rc" in eurem Projekt-Ordner kopieren.
Auf der Form erstellt ihr 2 Buttons (Button1,Button2), Button1 erhält den
Text "Start in Window" und Button2 "Start in Fullscreen", doppelklickt dann
bei Button1 auf das Ereigniss "OnClick" damit in der Unit1.cpp automatisch
"void __fastcall TForm1::Button1Click(TObject *Sender)" erscheint.
In dieser Funktion kopiert ihr dann den Code von meine Unit1.cpp aus der
Gleichnamiegen Funktion. Ordnet diese Funktion ebenfalls dem Button2 zu.
Nun benötigt ihr noch die Ereignissfunktionen "OnKeyDown" und OnMouseMove der
Form, und kopiert den dafür vorgesehenden Code aus meiner Unit1.cpp dort hinein.
Nun müßt ihr noch die Resourcendatei "Resourcen.rc" dem Projekt hinzu fügen und
fertig ist das Ganze.Hier könnt ihr euch das Projekt herunterladen http://bcb.24day.de/SoloPong.zip
Und Hier nur die Ausführbare EXE, also das Spiel zum Zocken http://bcb.24day.de/SoloPong.exeMein Ziel ist es euch und gerade den Anfängern, die Canvas Methoden nähr zu bringen und
eine ungefähre Vorstellung wie man ein Spiel mit dem BCB auch ohne DirectX oder OpenGL
und Co erstellen kann.Damit man auch nur mal ebend schauen kann wie man wo und was machen kann, habe ich dazu
den Quellcode auch mal hier mit hinein gepostet.Zum Spiel: Das Spiel läuft in einer Form mit 640x480 Pixel ab, diese kann als Fenster
angezeigt werden oder auch Fullscreen, dazu wird die Bildschirmauflösung auf 640x480
umgeschaltet. Pong ist eigentlich jedem Bekannt, nur bei dieser Variante müßt ihr
alleine den Puk (Ball) im Spielfeld halten. Dazu habt ihr 3 Puk´s. Die Punkte werden
als Millisekunden aufgezählt, somit ergiebt eine Sekunde 1000 Punkte hinzu.
Der Puk wird nach und nach immer schneller. Die Pannels steuert ihr hoch und runter
mit der Maus, dabei ist zu beachten das nur das rechte Pannel sich in gleicher Richtung
wie die Maus bewegt und das linke exakt entgegen gesezt. Viel spass beim Spielen.Nun der Quellcode:
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "jpeg.hpp" //jpeg unterstützung mit einbinden, Hintergrund ist Jpeg-Bild #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //Einige Globale Variablen die wir brauchen werden bool ende = false; //ist Spiel ende? ja/nein (true/false) bool fullscreen = false; //ist Spiel in Fullscreen? int panelY=170; //Y-koordinate der rechten Pannels int NW,NH,NC; //Variablen um die Standart-Breite/-Höhe/-Farbtiefe zu speichern //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { //Hier setzten wir unsere Form erstmal in die Mitte //des Bildschirms Form1->Left = (Screen->Width - 640) / 2; Form1->Top = (Screen->Height - 480) / 2; } //--------------------------------------------------------------------------- void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift) { //sollte man die Escape Taste oder "q" drücken, wir ende auf true //gesetzt damit die Spielschleife beendet wird if (Key == VK_ESCAPE || char(Key) == 'Q') ende = true; } //--------------------------------------------------------------------------- void __fastcall TForm1::ListBox1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { //Hier setzten wir die neue Koordinate "Y" für das rechte Pannel //wir ziehen aber 70 Pixel ab, da unser Pannel 140 groß ist und //wir die Mitte erhalten möchten panelY = Y-70; } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { // So nun gehts zum Spiel, der Zocker hat auf ein der Buttons geklickt Form1->DoubleBuffered = true; //Hier nicht unbedingt notwendig, schadet aber nicht Button1->Visible = false; //Button1 unsichtbar machen Button2->Visible = false; //Button2 unsichtbar machen Form1->BorderStyle = bsNone; //Die Titelleiste der Form ausblenden (kein Border) //Nun erfragen wir mit dynmic_cast die Caption des Buttons, welcher gedrückt wurde, //da es ein AnsiString ist können wir mit ".Pos() erfragen ob das Wort "Fullscreen" //drinsteht, wenn ja (größer 0) und Bildschirmbreite größer 640, dann schalten wir //den Bildschirm in die Auflösung 640x480, die Farbtiefe behalten wir bei if (dynamic_cast<TButton*>(Sender)->Caption.Pos("Fullscreen")>0 && Screen->Width>640) { fullscreen = true; // damit wir wissen das wir Fullscreen haben NW = Screen->Width; // alte Breite der Bildschirmauflösung NH = Screen->Height; // und alte Höhe, das brauchen wir zum Zurückschalten NC = GetDeviceCaps(Canvas->Handle,BITSPIXEL); //Farbtiefe erfragen //-- BildschirmModus für 640x480xjetzigeFarbtiefe suchen // Darauf möchte ich jetzt nicht nähr eingehen, das kann man dann mal Seperat machen DEVMODE Modus; bool Modok = false; int loop = 0; while (EnumDisplaySettings(NULL, loop, &Modus)) { if (Modus.dmBitsPerPel == DWORD(NC) && Modus.dmPelsHeight == DWORD(480) && Modus.dmPelsWidth == DWORD(640)) { Modok = true; break; } loop++; } // wemm Gefunden, dann Umschalten bool AllOK = false; if (Modok) { int Status = ChangeDisplaySettings(&Modus, CDS_UPDATEREGISTRY); if (Status == DISP_CHANGE_SUCCESSFUL) { AllOK = true; fullscreen = true; } } if (!AllOK) { ShowMessage("Konnte Bildschirmauflösung nicht ändern!"); Form1->Close(); } // Nun Schalten wir die Form in den Vollbildmodus // Das ist ähnlich Form1->Top/Left/Width/Height nur das man damit den ganzen Screen bedeckt SetWindowPos(Form1->Handle, HWND_TOPMOST, 0, 0, 640, 480, NULL); } //Jetzt gehts los //Eine neue Instance von TJPEGImage erstellen (jpeg.hpp) also ein neues JPG Bild TJPEGImage *BGjpg = new TJPEGImage(); //mit TResourceStream, einer ableitung von TStream erstellen wir ein Stream von //dem JPG-Bild (backpic(Hintergundbild)) aus der Resource (siehe "Resourcen.rc") TResourceStream *temp = new TResourceStream((int)HInstance,"backpic",RT_RCDATA); //Nun laden wir den Stream in das JPGImage BGjpg->LoadFromStream(temp); //jetzt erstellen wir ein Bitmap für unser Hintergrund-JPEG, da wir mit Bitmaps arbeiten Graphics::TBitmap *BGquelle = new Graphics::TBitmap; //Größen setzten, der eigentliche Hintergrund ist 640x960 gemalt worden mit einem Grafikprog. //dann habe ich im Grafikp. ein neues Blatt erstellt mit 640x1440(3x480) und das Bild auf //die unteren beiden Drittel kopiert, aus dem unteren Drittel (640x480) habe raus kopiert //und auf das obere Drittel gesetzt, wir scrollen dann immer um 960 Punkte und fangen von //vorne an somit hat man einen sauberen Übergang //Nochmal Kurz und Bündig, vom Hintergrund mit 640x960, die untere Hälfte (640x480) kopieren //und oben drauf setzten, gesamt dann 640x1440 BGquelle->Width = 640; BGquelle->Height = 1440; //und der Bitmap das JPEG-Bild zu ordnen, so haben wir JPG nach Bitmap konvertiert BGquelle->Assign(BGjpg); //das JPGbild und der Stream werden nicht mehr benötigt daher, freigegeben. delete temp; delete BGjpg; //nun erstellen wir weitere Bitmaps und laden diese aus der Resource, TBitmap unterstützt das laden aus der resource Graphics::TBitmap *panel = new Graphics::TBitmap(); panel->LoadFromResourceName((int)HInstance,"panel"); Graphics::TBitmap *pcpanel = new Graphics::TBitmap(); pcpanel->LoadFromResourceName((int)HInstance,"pcpanel"); Graphics::TBitmap *puk = new Graphics::TBitmap(); puk->LoadFromResourceName((int)HInstance,"puk"); //Da das Bild des Puk´s Rechteckig ist, aber der Puk rund, müßen wir den Rest durchsichtig machen // Zum Glück unterstützt TBitmap Transparents, der Puk wurde auf ein schwarzen Hintergrund // gemalt, so stellen wir die Transparentfarbe des TBitmap auf schwarz (clBlack - TColor) puk->TransparentColor = clBlack; // und aktivieren die transparents für den Puk puk->Transparent = true; // das gleiche mit dem Mittelpunkt Strich, bzw PingPong-netz Graphics::TBitmap *midline = new Graphics::TBitmap(); midline->LoadFromResourceName((int)HInstance,"midline"); midline->TransparentColor = clBlack; midline->Transparent = true; //Nun erstellen wir eine Bitmap in der wir die Spielscene rein malen und später in die form kopieren // wir nennen es puffer (zwischenspeicher) Graphics::TBitmap *Puffer = new Graphics::TBitmap; //unsere Form ist ja 640x480 groß, also muß auch der puffer diese Werte bekommen Puffer->Width = 640; Puffer->Height = 480; //NUN, kommen die ersten Canvas Methoden //Mit Canvas kann man auch Texte schreiben, dazu stehen uns alle Möglichkeiten von TFont //zur Verfügung: Puffer->Canvas->Font->Color = clYellow; //Schriftfarbe setzten TColor hier Gelb Puffer->Canvas->Font->Size = 16; // Schriftgröße Puffer->Canvas->Font->Name = "Arial"; //Schrifttyp Puffer->Canvas->Font->Style << fsBold; // Fettschrift dem Style "Zufügen" (<<) //Einem Canvas ist auch TBrush (Pinsel) untergeordnet, mit dem man malen kann, //wenn man Text schreibt wir der brush als Hintergrund des Textes verwendet //das wollen wir aber nicht, wir wollen den Hintergrund des Textes transparent //daher schalten wir den Style des TBrush auf "bsClear" (Leer-durchsichtig) Puffer->Canvas->Brush->Style = bsClear; //Nun setzten wir eine Integer Variable, die uns die Y-Koordinate des Hintergrund //Bildes angiebt, welches gescrollt wird, wir fangen im unteren Drittel an und //wenn wir oben sind, springen wir wieder nach unten, also start ab 960 (1440-480=960) int screen = 960; //Spielende setzten wir auf Unwahr (false) da wir ja gleich mit dem Spiel beginnen ende = false; //wir benötigen eine Variable in der wir Millisekundenzeit zwischenspeichern //auf der in einer Warteschleif verglichen wird, damit unser spiel mit ca. 25 Bilder //pro Sekunde läuft (wie im Film) DWORD idleTime; //einen Integer für die Y-Koordinate des linken Pannels int pcY=170; //einen zum Runterzählen wie lange GameOver angezeigt wird, bevor man aus dem Spiel, zur normalen Form kommt int GOshow = 100; //Damit unser Puk auch richtig fliegt, benötigen wir noch angaben über seine Richtung //wenn der Puk sich nach Rechts bewegt, PukGoRight=true, sonst nach Links =false bool pukGoRight = true; //das Gleiche auch mit oben und unten bool pukGoDown = false; //wenn der Puk am Panel oder am Rand die Richtung wechselt, soll ein Ping Ton //über den PC-Lautsprecher erfolgen und wenn er Fehrloren geht (Tor) ein Pong Ton !?! bool PongSound = false; bool PingSound = false; //Für den jeweiligen Ton brauchen wir eine Frequenz, daher Integer frq int frq; //Der Puk brauch ja auch noch seine Koordinaten, daher folgende 2 Variablen mit dem //Startpunkt in der Mitte int pukX=320,pukY=240; //Die Geschwindigkeit des Puk´s, diese wird im Spielverlauf erhöht int speed = 4; //Unsere Punkte, gemesen anhand von Millisekunden brauchen wir auch DWORD Punkte = 0; //Anzahl Bälle, also Puk´s die wir zur verfügung haben bis Spielende, das kann man auch erhöhen int baelle = 3; //Nun setzten wir noch die Startzeit anhand von Millisekunden, dies benötigen wir um //die Punkte zu Berechnen mittels GetTickCount() DWORD StartTime = GetTickCount(); //Für den Sound prüfen wir noch welches System hier ist (NT,2000,XP oder 98,98se,95) // das brauchen wir um Festzustellen ob wir per Beep() nen Ton machen müßen oder per //Assembler code unsigned long dwVersion = GetVersion(); //................................................................... //................................................................... // NUN GEHTS LOS MIT DER SPIELSCHLEIFE //. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . //Die Spielschleife ist eine WHILE-Schleife die Ausgeführt wird, solange wie ende=false ist while (!ende) { //Wenn PongSound auf true gesetzt wurde, also beim Tor, Beep mit Frequenz 500 abspielen if (PongSound) { frq = 500; PongSound = false; } //Wenn PingSpund true, da Puk am Panel oder Rand die Richtung wechselt, Beep mit 800 if (PingSound) { frq = 800; PingSound = false; } //Wenn frq einen wert erhielt, also größer 0, PC-Lautsprecher mit der frequenz aus frq einschalten // hier aber nur wenn dwVersion kleiner 0x80000000 also 98,98se,95 if (frq > 0 && dwVersion > 0x80000000) { //Auf dem Assemblercode gehe ich nicht nähr ein, man kann auch ein WAVE-Sample verwenden //und mit PlaySound abspielen unsigned short pitch = (unsigned short) (frq); frq = 0; asm mov bx, pitch asm mov ax, 34DDh asm mov dx, 0012h asm cmp dx, bx asm jnb Stop asm div bx asm mov bx,ax asm in al, 61h asm test al, 3 asm jne J1 asm or al, 3 asm out 61h, al asm mov al, 0B6h asm out 43h, al J1: asm mov al, bl asm out 42h, al asm mov al, bh asm out 42h, al Stop: //ansonsten, wenn NT basiert (NT,2000,XP) verwenden wir Beep() } else { Beep(frq,40); frq = 0; } //Nun setzten wir die Wartezeit bevor die Schleife ihren Code erneut ausführt //dazu schreiben wir die Aktuelle Millisekundenzeit in idleTime + 38 Millisekunden //wenn das ereicht wird am Ende der Schleife wird darauf geprüft, so kann er //weitermachen, normal sinds 40ms (25Bilder x 40ms = 1000ms = 1 Sekunde) aber wir //schenken noch 2ms für Programm-Events (mehr dazu unten) idleTime = GetTickCount()+38; //Nun berechen wir die Punkte indem wir von der aktuellen Zeit(+38) idleTime die //Startzeit (StartTime) abziehen und als Punkte zu ordnen Punkte = idleTime - StartTime; //Hier erhöhen wir die Geschwindigkeit des Puks, wenn eine Punktzahl ereicht oder //überschritten wurde if (Punkte >= 8000) speed = 6; if (Punkte >= 15000) speed = 8; if (Punkte >= 20000) speed = 10; if (Punkte >= 25000) speed = 12; if (Punkte >= 28000) speed = 14; if (Punkte >= 31000) speed = 16; if (Punkte >= 33000) speed = 18; if (Punkte >= 40000) speed = 20; if (Punkte >= 60000) speed = 26; // NUN kommt eine Wichtige Canvas Funktion, die nähmlich uns als erstes den // Hintergrund erstellt (der scrollt), dazu benutzen wir die Methode // CopyRect(TRect ziel,Quelle->Canvas,TRect quelle) // ein TRect beinhaltet die Koordinaten von links-oben und rechts-unten (x1,y1,x2,y2) // das kann man auch mittels der Funktion Rect(int x1, int y1, int x2, int y2) schreiben // so braucht man kein TRect erstellen // Bei uns ist das Ziel das gesamte Bild also 0,0,640,480 // aber wir gehen bei der Quelle immer einen Punkt je Durchlauf nach oben // das halten wir in der Variable "screen" fest, die zu Anfang mit 960 beginnt // daher lautet das Quell-TRect 0,screen,640,screen+480 (0,960,640,1440 zu beginn) Puffer->Canvas->CopyRect(Rect(0,0,640,480),BGquelle->Canvas,Rect(0,screen,640,screen+480)); // nun setzten wir den wert in screen um 1 nach unten (auf 959) beim nächsten // durchlauf wäre es dann 0,959,640,1439 und so weiter screen--; // und wenn unser Bildausschnitt oben angelangt ist (screen=0) setzten wir es auf 960 // zurück und beginnen von vorne if (screen <= 0) { screen = 960; } // Nun kommt eine Canvas methode namens Draw(int x, int y, TBitmap) **bzw TGraphic // mit ihr kann man kleinere grafiken ab einer x,y koordinate in ein Canvas kopieren // hier mit der Mittellinie und dem rechten Panel, desen koordinate-Y Global verändert // wir bei OnMousMove Puffer->Canvas->Draw(292,0,midline); Puffer->Canvas->Draw(590,panelY,panel); // Jetzt erechnen wir die Entgegengesetzte Y-Koordinate für das linke Pannel, anhand // der Y-Koordinate des rechten Pannels, so das sich das linke Pannel immer entgegengesetzt // des rechten Pannels bewegt if (panelY > 170) { pcY = panelY-170; pcY = 170-pcY; } else if(panelY < 170) { pcY = 170-panelY; pcY = 170+pcY; } else { pcY = 170; } // Nun wird auch das linke Pannel mit Draw() ins Spielfeld gezeichnet Puffer->Canvas->Draw(25,pcY,pcpanel); //Nun kommt die Kollisionsabfrage für den Puk // zunächst prüfen wir ob der Puk auf das linke Pannel getroffen ist // wenn ja wird die X richtung geändert und ein PingSound gestartet if (pukX <= 50 && pukY >= pcY && pukY <= pcY+140) { pukGoRight = !pukGoRight; PingSound = true; //Das gleiche für das rechte Pannel } else if (pukX >= 590 && pukY >= panelY && pukY <= panelY+140) { pukGoRight = !pukGoRight; PingSound = true; //ansonsten wenn der Puk aus dem rechten oder linken Rand (Tor) ist //wird auch die X richtung geändert aber ab der Mitte des Feldes aus wieder (320) //und es wird ein Ball (Puk) abgezählt, sowie ein Pongsound gestartet //sollte der Ballzähler 0 ereicht haben wird GOshow auf 40 gesetzt // so wird Game over eingeblendet 40 Schleifen durchgänge lang } else if (pukX <= 0 || pukX >= 640) { pukGoRight = !pukGoRight; pukX = 320; baelle--; PongSound = true; if (baelle == 0) { GOshow = 40; } } //Wenn der Puk am oberen oder unteren Rand trifft, wird die Y-richtung geändert //und auch ein Pingsound gestartet if (pukY <= 0 || pukY >= 480) { pukGoDown = !pukGoDown; PingSound = true; } //Hier werden jetzt die neuen Positionen des Puk gesetzt mit dem Wert in speed if (pukGoDown) { pukY = pukY+speed; } else { pukY = pukY-speed; } if (pukGoRight) { pukX = pukX+speed; } else { pukX = pukX-speed; } //Zum Schluß wird der Puk mittels Draw() gezeichnet Puffer->Canvas->Draw(pukX-13,pukY-13,puk); //Nun kommt das mit dem Text schreiben mittels Canvas, ihr erinnert euch an //den Angaben von oben mit der Schrifteinstellung //mit textOut kan man ab einer X,Y-Koordinate einen AnsiString schreiben Puffer->Canvas->TextOutA(350,10,"Punkte: "+IntToStr(Punkte)); Puffer->Canvas->TextOutA(50,10,"Puk´s: "+IntToStr(baelle)); //So wenn Game Over ist und GOshow auf 40 gesetzt wurde //wird das nun je Schleifendurchlauf um eins verringert und //der Text "Game over" ausgegeben mit TextOut() wie gerade beschrieben if (GOshow<=40 && GOshow >=1) { GOshow--; Puffer->Canvas->TextOutA(250,220,"GAME OVER"); //und wenn GOshow die 0 ereicht hat //werden wir die Spielschleife entgültig beenden in dem wir ende auf true setzen } else if (GOshow == 0) { ende = true; } //Soooo unser aktuelles Bild unseres Spielfeld wurde im puffer neu gezeichnet //und kann nun zur Anzeige auf die Canvas der Form übertragen werden //das können wir auch mit Draw() machen, da der puffer 640x480 ist wie die Form auch Form1->Canvas->Draw(0,0,Puffer); //oder man macht es auch mittels CopyRect() //Form1->Canvas->CopyRect(Rect(0,0,640,480),puffer->Canvas,Rect(0,0,640,480)); //Nun warten wir noch bis die knapp 40ms abgelaufen sind //als Ausführung in dieser while-Schleiffe benutzen wir Sleep(), was das Programm //für Anzahl Millisekunden anhält, wir verwenden aber 0 damit das nicht bremst while (GetTickCount() < idleTime) ::Sleep(0); //nun Schalten wir den PC-Lautsprecher wieder ab, wenn ein Pong oder Ping sound //gestartet wurde wir er jetzt wieder angehalten, sofern es ungleich NT Basiert ist if (dwVersion > 0x80000000) { asm in al, 61h asm and al, 0fch asm out 61h, al } //Nun kommt was ganz Wichtiges, damit der Rest des Programms (Mausabfrage, Tastatur, etc) //überhaupt Arbeiten kann, und das Programm nicht einfriert, muß der Windows Nachrichtendienst //aufgerufen werden, also die Messages werden behandelt Application->ProcessMessages(); } //Und ab nach oben das gleiche von vorne mit neuen Koordinaten //------------------------------------ //Da das Spiel nun zu Ende ist können wir alle Bitmaps wieder freigeben delete BGquelle; delete Puffer; delete panel; delete midline; delete puk; //nun setzen wir die Pinselfarbe der Form-Canvas auf die Ursprungsfarbe Form1->Canvas->Brush->Color = clBtnFace; //Und füllen mittels Canvas->FillRect die komplette Form mit dieser Farbe (640x480) Form1->Canvas->FillRect(Rect(0,0,640,480)); //zu letzt noch die Punktzahl in die Caption (Titelleiste) der form schreiben Form1->Caption = "Letzte Punktzahl: "+IntToStr(Punkte); //und die Buttons wieder sichtbar machen Button1->Visible = true; Button2->Visible = true; //wenn das Spiel in Fullscreen lief (fullscreen = true) dann setzten wir //die alte Bildschirmauflösung wieder zurück, die Werte dazu stehen ja in // NW,NH,NC die wir beim Start gesetzt haben if (fullscreen) { DEVMODE Modus; int loop = 0; while (EnumDisplaySettings(NULL, loop, &Modus)) { if (Modus.dmBitsPerPel == (DWORD)NC && Modus.dmPelsHeight == (DWORD)NH && Modus.dmPelsWidth == (DWORD)NW) { break; } loop++; } int Status = ChangeDisplaySettings(&Modus, CDS_UPDATEREGISTRY); fullscreen = false; } //Nun noch die Standart größen der Form, wieder in die Mitte setzten und den Border //auf bsSingle zurück setzten, damit wir die Titelleiste sehen Form1->Width = 640; Form1->Height = 480; Form1->Left = (Screen->Width - 640) / 2; Form1->Top = (Screen->Height - 480) / 2; Form1->BorderStyle = bsSingle; // UND FERTIG } //---------------------------------------------------------------------------Ich hoffe ich kann damit noch mehr Fragen zur einfachen Spiele Programmierung
mit dem BCB bremsen, damit das Forum nicht noch mehr damit Bombadiert wird.Viele Grüße und viel Spass beim Nachmachen und Zocken
euer Micha (promicha)
-
1000000000000000000000000000 x Danke

Genial nun versteh auch ich den kompletten Code

Gleich mal ausdrucken und min 100x durchlesen

-
Aber nimm dir bitte keine Beispiel am Stil.

Das "alles in den Buttonclick" ist nämlich ein erschütterndes Beispiel für die dem BCB gern nachgesagten Nachteile.
-
Jansen schrieb:
Aber nimm dir bitte keine Beispiel am Stil.

Das "alles in den Buttonclick" ist nämlich ein erschütterndes Beispiel für die dem BCB gern nachgesagten Nachteile.Dem kann ich nur Zustimmen, eine gute Möglichkeit einer Game-schleife kann
man z.B. mit Application->OnIdle erstellen, vor allem wenn das Spiel länger dauertIch möchte daher nochmals drauf hinweisen, wie in den andere Threads zu diesem
Thema, das ich es auf die Schnelle runterprogge und kein Spiele-Entwickler bin,
ich möchte mit dem Beispiel nur die Möglichkeiten des BCB vorzeigen.Ihr sollt auch nicht den Code einfach Kopieren und abändern, sondern die
Methoden verstehen und mit diesem Wissen euer Spiel erstellen. Schaut euch
auch das Beispiel im Example-Ordner des BCB an unter Games "Earth Pong"
dort wird es auch in dem Application->OnIdle Event gesetzt.Und Alles Andere zum Thema Spieleentwicklung bitte in das entsprechende Board.
In diesem Sinne, Micha.
-
Bitte einmal jede Zeile kommentieren und sagen, was sie macht. Ich stell es bewusst nicht ins Assembler-Forum, weil ich es von ihm erklärt haben möchte, nicht von irgendjemanden. Sorry.
Und warum?
//Auf dem Assemblercode gehe ich nicht nähr ein, man kann auch ein WAVE-Sample verwenden
//und mit PlaySound abspielen
unsigned short pitch = (unsigned short) (frq);
frq = 0;
asm mov bx, pitch
asm mov ax, 34DDh
....Hast du nicht gelesen das ich das nicht näher erkläre?
Ansonsten frag doch "W. Posur", den er hat diesen FAQ-Beitrag gepostet!
gruß Micha
-
Zur Assemblerfrage siehe hier.
-
promicha schrieb:
Hier könnt ihr euch das Projekt herunterladen http://bcb.24day.de/SoloPong.zip
Und Hier nur die Ausführbare EXE, also das Spiel zum Zocken http://bcb.24day.de/SoloPong.exeHi die links gehen leider nicht, ich würde aber sehr gerne bischen rum probieren, da ich ein Schul projekt habe was in diese richtung geht.
könntest du die files vieleicht an meine e-mail schicken ?
MfG djcccp
-
Hallo
bei mir gehen die Links auch nicht ?
besser waere zu klaeren warum nicht anstatt sowas jedem per Mail zu senden
MfG
Klaus
-
Ja stimmt. Kennt jemand promicha's e-mail....oder wie man sonst mit ihm in kontak tretten kann ?
MfG djcccp
-
hi,
hier hab ich mal ein paar interessante Links zusammengesucht, vieleicht hilft dir das weiter

http://cc.borland.com/cc/ccweb.exe/listing?id=17289
http://www.monroeccc.edu/ckelly/game_programming.htm
MFG Fregger
-
djcccp schrieb:
Kennt jemand promicha's e-mail....oder wie man sonst mit ihm in kontak tretten kann ?
Warum wirst du nicht mal einen Blick in sein Benutzerprofil?
PS.
Katastrophenalarm!