Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

TigerClaw25

unregistriert

1

18.04.2013, 10:50

Die Klasse EnemyShot

Hallo,

arbeite ja momentan dran, dass mein Gegner, der sich Konstant auf der x-Achse hin und her bewegt auf mich schießt, sobald bestimmte Koordinaten übereinstimmen. Dazu habe ich mir einfach in der Shot-Klasse eine kleine Funktion geschrieben, die ein bool-Wert erwartet. Darüber bestimme ich dann, ob die Variable in der Klasse Shot true oder false ist.

Das Problem ist nur, dass mein Gegner sich immer hin und her bewegt, aber seine Koordinaten immer gleich bleiben. Obwohl dieser an einer anderen Position ist, steht immer die selbe Koordinate für die x-Achse da!

Hier mal meine COpponent Klasse:

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#include "Opponent.h"

// Konstruktor
//
// Aufgabe: Allgemeine Initialisierungen
//
COpponent::COpponent ()
{
    m_pSpriteOpponent = NULL;
    m_pSpriteShot = NULL;

    m_Health = 10;

} // Konstruktor

// Init
//
// Aufgabe: Sprites erzeugen und laden
//
void COpponent::Init ()
{
    // Spielersprite erstellen
    m_pSpriteOpponent = new CSprite;

    m_pSpriteOpponent->Load ("Data/Opponent.bmp", 11, 64,64);
    m_pSpriteOpponent->SetColorKey (255, 0, 255);

    // Schuss-Sprite erstellen
    m_pSpriteShot = new CSprite;

    m_pSpriteShot->Load ("Data/Laser.bmp", 0, 64, 64);
    m_pSpriteShot->SetColorKey (255, 0, 255);

        // Bewegung initialisieren
    m_moving = true;
    
} // Init

// Quit
//
// Aufgabe: Sprites freigeben
//
void COpponent::Quit ()
{
    // Spieler-Sprite freigeben
    if (m_pSpriteOpponent != NULL)
    {
        delete (m_pSpriteOpponent);
        m_pSpriteOpponent = NULL;
    }

    // Schuss-Sprite freigeben
    if (m_pSpriteShot != NULL)
    {
        delete (m_pSpriteShot);
        m_pSpriteShot = NULL;
    }

} // Quit

// Reset
//
// Aufgabe: Spielerwerte auf Standard setzen
//
void COpponent::Reset ()
{
    // Startposition des Spielers
    m_fXPos = 520.0f;
    m_fYPos = 100.0f;

    // Animationsphase
    m_fAnimPhase = 5.0f;

    // Es darf geschossen werden
    m_bShotLock = false;

    // Rect initialisieren (Erweiterung für Kollision zwischen Asteroid und Spieler)
    m_Rect.x = static_cast<int>(m_fXPos);
    m_Rect.y = static_cast<int>(m_fYPos);
    m_Rect.w = m_pSpriteOpponent->GetRect().w;
    m_Rect.h = m_pSpriteOpponent->GetRect().h;

} // Reset

// Render
//
// Aufgabe: Spieler und Schüsse rendern
//
void COpponent::Render ()
{
    // Position des Spielers setzen und Sprite rendern
    m_pSpriteOpponent->SetPos (m_fXPos, m_fYPos);
    m_pSpriteOpponent->Render (m_fAnimPhase);

    // Iterator für Schussliste
    list<CShot>::iterator it = m_ShotList.begin ();

    // Schussliste durchlaufen
    while (it != m_ShotList.end ())
    {
        // Schuss updaten
        it->Update2 ();

        // Ist der Schuss noch aktiv?
        if (it->IsAlive ())
        {
            // Ja, dann rendern
            it->Render ();
            it++;
        }
        else
        {
            // Nein, dann aus der Liste entfernen
            it = m_ShotList.erase (it);
        }

    }

} // Render

// Update
//
// Aufgabe: Spieler updaten
//
void COpponent::Update ()
{
    // Prüfen, ob geschossen wurde
    ProcessShooting ();

// Nach links?
    if (m_moving == true)
    {
        m_fXPos += 200.0f * g_pTimer->GetElapsed ();
        m_fAnimPhase += 20.0f * g_pTimer->GetElapsed ();
        
        if (m_fXPos > 730.0f)
        {
            m_fXPos = 730.0f;
            m_moving = false;
        }

    }
    // Nach rechts?
    if (m_moving == false)
    {   
        m_fXPos -= 200.0f * g_pTimer->GetElapsed ();
        m_fAnimPhase -= 20.0f * g_pTimer->GetElapsed ();
        if (m_fXPos < 0.0f)
        {
            m_fXPos = 0.0f;
            m_moving = true;
        }

    }
// Animationsphase prüfen
        if (m_fAnimPhase < 0.0f)
            m_fAnimPhase = 0.0f;
        else if (m_fAnimPhase > 10.0f)
            m_fAnimPhase = 10.0f;

} // Update


// ProcessShooting
//
// Aufgabe: Waffe abfeuern
//
void COpponent::ProcessShooting ()
{
    // Wurde Space gedrückt und darf geschossen werden?
    if (m_bShotLock == false)
    {
        // Neuen Schuss erzeugen und initialisieren
        CShot Shot;

        Shot.Init (m_pSpriteShot, m_fXPos, m_fYPos);

        // Schuss in Liste einfügen
        m_ShotList.push_back (Shot);

        // Schießen erst wieder erlaubt, wenn Space losgelassen
        m_bShotLock = true;

    }


} // ProcessShooting



EDIT: Könnte es eventuell daran liegen, dass ich nach jedem Update der Bewegung m_fXPos meinem m_Rect.x zuweisen muss und natürlich vorher in int casten? Sonst bleibt mein Enemy Rect, dass ich mir in der CGame-Klasse hole ja immer gleich, zumindest der Wert ...

Ist es überhaupt sinnvoll in meiner COpponent Klasse über eine bool Funktion die Variable, die für die Schüsse verantwortlich ist, zu verändern?

C-/C++-Quelltext

1
bool ShotLock(bool x) {m_bShotLock = x; return m_bShotLock;}

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »TigerClaw25« (18.04.2013, 11:02)


2

18.04.2013, 13:13

Siehst du, jetzt hast du wieder zuerst gefragt und dann nachgedacht. In deinem Edit hast du dir die Antwort selbst gegeben.

Anstelle die Variable shotLock von Außen zu setzen, versetz dich mal in die Sicht deines Gegeners. Er sieht den Spieler und entscheidet danach, ob er schießt oder nicht. Der Opponent braucht also die Koordinaten des Spielers und sollte dann sebstständig entscheiden, ob er feuert oder nicht.

3

18.04.2013, 13:15

Keine Ahnung, geh mal mit dem Debugger drüber! "-.-
Im Ernst, solche Themen kann man sich mit ein wenig Mühe und Einsatz komplett sparen. Aber nein, beim erstbesten Problem überfliegt man den Code und fragt hier nach.
Gawd. Ist ja nicht böse gemeint, aber benutze doch bitte endlich den Debugger! ;(
So schwer ists doch nicht.

MfG
Check

TigerClaw25

unregistriert

4

18.04.2013, 14:17

Was bringt mir aber der Debugger, wenn beispielsweise der Gegner mehrmals hintereinander schießen soll? Das wäre z.B. das naechste Problem. Ich habe mir erst überlegt eine Verzögerung einzufügen, da sonst ununterbrochen geschossen wird. Eine Möglichkeit besteht darin, den Gegner erst schießen zu lassen, wenn er die selbe x Koordinate hat wie der Spieler. Dann beispielsweise 5 Schüsse abgeben und weiter fliegen. Aber wie ich sowas realisiere, sagt mir der debugger leider nicht ;)

Zitat

Anstelle die Variable shotLock von Außen zu setzen, versetz dich mal in
die Sicht deines Gegeners. Er sieht den Spieler und entscheidet danach,
ob er schießt oder nicht. Der Opponent braucht also die Koordinaten des
Spielers und sollte dann sebstständig entscheiden, ob er feuert oder
nicht.
Stimmt, die Koordinaten zu übergeben ist auch übersichtlicher, da dies nicht die Aufgabe der Game-Klasse sein sollte. Danke!

Einziges Problem. Meine Instanz CFont ist in CGame. Müsste also auch in CEnemy wieder eine INstanz von CFont erstellen :(

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »TigerClaw25« (18.04.2013, 14:36)


Nimelrian

Alter Hase

Beiträge: 1 216

Beruf: Softwareentwickler (aktuell Web/Node); Freiberuflicher Google Proxy

  • Private Nachricht senden

5

18.04.2013, 14:27

In der Tat, sowas sagt dir der Debugger nicht, der ist aber auch nicht dafür da, dir Code-Vorschläge zu geben. Dafür ist normalerweise das Ding zwischen deinen Ohren zuständig.
Ich bin kein UserSideGoogleProxy. Und nein, dieses Forum ist kein UserSideGoogleProxyAbstractFactorySingleton.

TigerClaw25

unregistriert

6

18.04.2013, 14:37

Hat bei mir vorhin mit den Werten nicht geklappt. Als Notlösung hab ich mir das Ganze einfach mitten im Spiel ausgeben lassen. So konnte ich zumindest die Koordinaten der beiden Schiffe verfolgen :)

Ich habe das nun so gelöst.

Meine Klasse CEnemy enthält folgende Funktion:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// EnemyShot
//
// Aufgabe: Schuss des Gegners abfeuern, wenn Spieler in Reichweite
//
void CEnemy::EnemyShot(int X)
{
// Schuss des Gegners steuern:

        if (X == m_Rect.x)      
            m_bShotLock = false;
                
        else 
            m_bShotLock = true;
        

} // EnemyShot


Diese Rufe ich in meiner CGame::Run wie folgt auf:

C-/C++-Quelltext

1
2
3
4
5
6
7
    // Gegner updaten und rendern
        m_pEnemy->Update ();
        m_pEnemy->Render ();

        SDL_Rect RectPlayer;
        RectPlayer = m_pPlayer->GetRect();
        m_pEnemy->EnemyShot (static_cast<int>(RectPlayer.x));


Ist das auch technischer Sicht OK?

Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von »TigerClaw25« (18.04.2013, 15:06)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

7

18.04.2013, 15:38

Quellcode

1
2
3
4
5
        if (X == m_Rect.x)      
            m_bShotLock = false;
                
        else 
            m_bShotLock = true;


Quellcode

1
m_bShotLock = x != m_Rect.X


Ob das semantisch Sinn macht, ist aber fraglich.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Tobiking

1x Rätselkönig

  • Private Nachricht senden

8

18.04.2013, 15:38

Da stellt sich immer noch die Frage, warum das EnemyShot von außen aufgerufen werden soll. EnemyShot wird jedes Frame aufgerufen, genau wie Update. Und der in EnemyShot gesetzt Wert, wird anschließend nur in Update verwendet. Warum ruft dann nicht einfach Update das EnemyShot auf?

Wenn du zudem in CEnemy einen Zeiger auf das Spielerobjekt (oder dessen Position) hinzufügst, brauchst du nicht jedes mal die Position des Spielers extra übergeben.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

9

18.04.2013, 16:07

Du solltest dich vielleicht noch ein wenig mit den Grundlegenden Dingen beschäftigen. Der Debugger ist eins der Werkzeuge die man als Entwickler kennen muss. Ein gewissen Grundverständnis sollte da schon vorhanden sein. Natürlich schreibt dir der Debugger keinen Code, aber du kannst damit wunderbar Fehler finden. Deine Ausgangsfrage hättest du damit zum Beispiel recht schnell lösen können. Wie du dir deine KI strukturierst kann dir der Debugger natürlich nicht sagen. Da sollte man aber auch vielleicht überlegen welchen Stand man aktuell hat. Man kann sich auch einfach erst mal an einfacheren Dingen versuchen. Vor allem wenn du mal einige Spiele analysierst, wird dir sicher auffallen, dass Gegner gar nicht unbedingt sinnvollen Logiken folgen. Oft folgen sie einfach einem festgelegten Bewegungsmuster. Zusätzlich könnten auch die Schüsse in dem Muster untergebracht sein. So ist das Verhalten recht simpel zu entwickeln und der Spieler hat die Chance das Verhalten vorauszusehen. Der Schwierigkeitsgrad kann hier einfach durch die Kombination der Muster/Gegner bestimmt werden. Und selbst das gestaltet sich einfach.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

TigerClaw25

unregistriert

10

18.04.2013, 16:35

Da stellt sich immer noch die Frage, warum das EnemyShot von außen aufgerufen werden soll.
Weil ich die Koordinaten an die Funktion übergeben möchte. Wäre es sinnvoller die Rects direkt über eine Spielerinstanz, die ich in CEnemy deklariere, zu initialisieren?

Zitat

Oft folgen sie einfach einem festgelegten Bewegungsmuster. Zusätzlich
könnten auch die Schüsse in dem Muster untergebracht sein. So ist das
Verhalten recht simpel zu entwickeln und der Spieler hat die Chance das
Verhalten vorauszusehen. Der Schwierigkeitsgrad kann hier einfach durch
die Kombination der Muster/Gegner bestimmt werden. Und selbst das
gestaltet sich einfach.
Da hast du natürlich Recht. Ich wollte aber erst einmal den Gegner dem Spieler folgen lassen und sobald dieser sich in einem bestimmten Radius befindet, soll geschossen werden. So zumindest die Idee :) Werde mir aber bei anderen Games Anregungen holen. Bei youtube steht sogar ein gutes SFML Tutorial zu einem 2D Weltraum-Shooter-Spiel

Werbeanzeige