Hallo alle zusammen
Da das mein erster Thread hier im Forum ist, möchte ich mich erstmal vorstellen. Ich bin 18 Jahre alt und lerne seit mehren Jahren C++ (4 wenn ich mich recht erinnere, wobei es natürlich auch lustlose Phasen gab
). Ich habe mich demletzt mit wxWidgets sowie Netzwerkprogrammierung befasst. Nun befasse ich mich eben mit Spieleprogrammierung. Ich besitze das Buch "C++ für Spieleprogrammierer" wie auch "3D-Spieleprogrammierung mit DirectX und C++", doch da mir das alles mit 3D dann doch zu hoch ist, versuche ich verzweifelt ein gescheites 2D Spiel zusammenzubasteln, was jedoch nicht wirklich klappt
Das Spiel: Ich versuche ein Spiel zu proggen, bei dem es 2 Mutterschiffe gibt, unbeweglich und dient als "Hauptquatier". Dieses Mutterschiff kann 3 Arten von Schiffen erstellen. Die Karte ist mit einem "Nebel" zugedeckt. Je nach Schiff kann man den Nebel mit einem größeren Radius aufdecken. Ziel des Spiels ist es, das gegnerische Mutterschiff zu zerstören.
Der "Rahmen" in dem das Spiel läuft: Im großen und ganzen hab ich das System aus dem Buch übernommen, also die Klassen CGame, CFramework, CTimer... Gestartet wird das Spiel jedoch nicht von einer Konsole, sondern einfach von wxWidgets, wobei es einfach eine Applikation ohne Fenster ist, die alles initialisiert, auf Fehlern prüft und dann startet und bei Game.Run() dann eben stehen bleibt, was nicht weiter tragisch ist, da man eh nichts davon mitbekommt
Das Problem: Für den Hintergrund habe ich eine PNG Datei. Ich nutze SDL_BlitSurface um den Ausschnitt dort herauszunehmen und auf den Bildschirm zu zeichnen. Dabei sanken meine FPS (Berechnet mit 1 / Timer->GetElapsed()) von 500 auf ca 25. Nachdem ich dann eben vorher bei der Initialisierung den Background-Surface auf das selbe Format gebracht habe wie der Bildschirm, konnte ich dann doch 333 FPS erreichen. Ich hab auch noch die Einstellung hinzugefügt, dass man durch drücken von "B" den Hintergrund ein oder ausschalten kann, falls es zu viel laggt.
Das Nächste Problem war, dass ich die Schiffe mit einem Rahmen markieren wollte. Die eigentliche Auswertung erfolgt in einer Funktion: HandleMouseClick, HandleMouseMotion oder HandleMouseRelease, die in der Eventschleife aufgerufen werden. Danach wird der Rahmen, den man gezogen hat, auf eine Surface gerendert (SDL_Surface *speciallayer), und dieser wird dann bei allen Renderfunktionen noch dazugemacht. Dies drückte meine FPS aber wieder runter. Das Problem habe ich.. "gelöst" (wobei man es nicht wirklich so nennen könnte), indem ich den speciallayer einfach überspringe, wenn die Maustaste nicht gedrückt ist.
Nun kommt das größte Problem: Der Nebel. Ich hab momentan eine 10.000 x 10.000 Surface (Spielfeldgröße), der Anfangs komplett grau gezeichnet ist. Dort werden dann Alpha-Kreise gezogen, wo sich die Schiffe befinden, falls sie sich bewegen (Mir ist nichts anderes eingefallen, wie ich das machen könnte). Den nebel kann ich ja nicht Konvertieren, da der Bildschirm über keinen Alphawert verfügt. Der Nebel ist auch nicht verzichtbar, da er ein wichtiges Merkmal für das Spiel ist. Doch der Nebel drückt die FPS auf 25 runter, wenn ich dann doch etwas markiere, dann wird es noch schlimmer
Von der Spiellogik her hab ich keine Probleme, nur die FPS bereiten mir Kopfschmerzen :/
Mithilfe von Google hab ich nur Tipps herausgefunden wie "Use HWSURFACE" oder "SDL_DOUBLEBUFF", was ich jedoch von Anfang an drin hatte
Ich bedanke mich im Voraus
Mit freundlichen Grüßen, MatStorm
------------------------------------------------------------------------------------------------
Codeausschnitte:
|
C-/C++-Quelltext
|
1
2
3
4
5
|
//[in CGame::Init()]//Speciallayer konfigurieren
speciallayer = SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_SRCALPHA, Framework->GetScreen()->w,Framework->GetScreen()->h, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
//Nebel konfigurieren
fog = SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_SRCALPHA, 10000, 10000, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
SDL_FillRect(fog, 0, SDL_MapRGBA(fog->format, 50, 50, 50, 255));
|
|
C-/C++-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
|
int CGame::Run()
{
InitMotherships();
//Spielschleife
while(GameRun)
{
try
{
ProcessEvents();
Framework->Update();
Framework->Clear();
Update();
Render();
Check();
Framework->Flip();
}
catch(...)
{
return ECR_UNKNOWN;
}
}
return 0;
}
|
|
C-/C++-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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
void CGame::Render()
{
switch(GameState)
{
case 0:///////////////////////////////////////////////////////////////////////////////// MENÜ
{
}
break;
case 1:///////////////////////////////////////////////////////////////////////////////// SPIEL
{
//Render Background
if(RenderBackground) SDL_BlitSurface(background, 0, Framework->GetScreen(), 0);
//Render Gegner
emship.Render();
for(list<Ship1>::iterator i = elist1.begin(); i != elist1.end(); i++) i->Render();
for(list<Ship2>::iterator i = elist2.begin(); i != elist2.end(); i++) i->Render();
for(list<Ship3>::iterator i = elist3.begin(); i != elist3.end(); i++) i->Render();
//Rendere Nebel
RenderFog();
//Rendere eigene Schiffe
mship.Render();
for(list<Ship1>::iterator i = slist1.begin(); i != slist1.end(); i++) i->Render();
for(list<Ship2>::iterator i = slist2.begin(); i != slist2.end(); i++) i->Render();
for(list<Ship3>::iterator i = slist3.begin(); i != slist3.end(); i++) i->Render();
//Render Menüleiste
RenderMenu();
RenderButtons();
//Speciallayer zeichnen
if(RendSpecLay) SDL_BlitSurface(speciallayer, 0, Framework->GetScreen(), 0);
}
break;
case 2:///////////////////////////////////////////////////////////////////////////////// OPTIONEN
{
}
break;
case 3:///////////////////////////////////////////////////////////////////////////////// PAUSE
{
//Render Background
if(RenderBackground) SDL_BlitSurface(background, 0, Framework->GetScreen(), 0);
//Rendere Mutterschiffe
mship.Render();
emship.Render();
//Rendere Schiffe
for(list<Ship1>::iterator i = slist1.begin(); i != slist1.end(); i++) i->Render();
for(list<Ship1>::iterator i = elist1.begin(); i != elist1.end(); i++) i->Render();
for(list<Ship2>::iterator i = slist2.begin(); i != slist2.end(); i++) i->Render();
for(list<Ship2>::iterator i = elist2.begin(); i != elist2.end(); i++) i->Render();
for(list<Ship3>::iterator i = slist3.begin(); i != slist3.end(); i++) i->Render();
for(list<Ship3>::iterator i = elist3.begin(); i != elist3.end(); i++) i->Render();
//Render Menüleiste
RenderMenu();
RenderButtons();
//Schwärzen und beschriften
SDL_FillRect(speciallayer, 0, SDL_MapRGBA(speciallayer->format, 0, 0, 0, 128));
SDL_BlitSurface(speciallayer, 0, Framework->GetScreen(), 0);
}
break;
}
RenderMouse();
RenderFPS();
}
|
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
|
void CGame::RenderFog()
{
SDL_Rect Rect;
Rect.x = Welt->WorldX;
Rect.y = Welt->WorldY;
Rect.w = Framework->GetScreen()->w - 200;
Rect.h = Framework->GetScreen()->h;
SDL_BlitSurface(fog, &Rect, Framework->GetScreen(), 0);
}
|