Seite 1 von 1

BloopIt spawn Kollision

Verfasst: 25.01.2012, 06:51
von Raidenkk
Hey,
ich habe nach langen mal wieder an meinem Projekt weiter gemacht und bin auf folgenden Fehler drauf zu gelaufen ^^:
Interator not incrementable.
1 Kugel lässt sich spawnen aber sobald er an dem Interator kommt kommt halt die Fehlermeldung.
Da ich schon seit Stunden nach einer Lösung suche wollte ich mal schauen was ihr davon haltet :)

std::vector<CBall>::iterator m_i;

Code: Alles auswählen

void CBloopIt::CreateBalls ()
{
	if (m_Player.GetSpawnBall () == true)
	{
		m_Player.SetSpawnBall (false);
		if (m_vBalls.size() > 0)
		{
			for (m_i=m_vBalls.begin(); m_i!=m_vBalls.end(); m_i++)
			{
				if (m_i->GetX() != m_Player.GetX ())
				{
					m_vBalls.push_back (CBall(m_Player.GetX()*64, m_Player.GetY()*64));
					std::cout << "Ball Spawned!" << std::endl;
				}
			}
		}
		else
		{
			m_vBalls.push_back (CBall(m_Player.GetX()*64, m_Player.GetY()*64));
			std::cout << "Ball Spawned!" << std::endl;
		}
	}
}

Re: BloopIt spawn Kollision

Verfasst: 25.01.2012, 07:05
von simbad
Ähnliches hatten wir hier schonmal.

Wenn man einen Iterator hat und der Container verändert wird, ist der iterator ungültig. push_back verändert den vector.

Re: BloopIt spawn Kollision

Verfasst: 25.01.2012, 07:18
von Raidenkk
Hmm soll ich den interator weglassen und mir selber nen Zähler basteln?

Re: BloopIt spawn Kollision

Verfasst: 25.01.2012, 09:31
von simbad
Nein.

Aber du benutzt den iterator ja im for-statement nachdem du ihn gespawnt hast. Einfach ein break einbauen. Du musst doch den vector eh nicht weiter ablaufen, oder?
Und selbst wenn, dann müsste man den iterator wieder auf den Anfang setzen und neu anfangen.

Re: BloopIt spawn Kollision

Verfasst: 25.01.2012, 12:29
von Raidenkk
habe das jetzt mal ausprobiert und festgestellt das es zwar klappt doch leider nur begrenzt. Die erste Kugel wird überprüft doch die anderen nicht die lassen sich überlappen.
Wenn ich den interator vor dem break wider auf begin setze will es nicht so ganz dann lässt sich auch nicht die erste Kugel mehr überprüfen und Zeichnet eine neue Kugel darauf.
Oder habe ich was falsch gemacht :X?

Code: Alles auswählen

void CBloopIt::CreateBalls ()
{
	if (m_Player.GetSpawnBall () == true)
	{
		m_Player.SetSpawnBall (false);
		if (m_vBalls.size() > 0)
		{
			for (m_i=m_vBalls.begin(); m_i!=m_vBalls.end(); m_i++)
			{
				if (m_i->GetX() != m_Player.GetX ())
				{
					m_vBalls.push_back (CBall(m_Player.GetX()*64, m_Player.GetY()*64));
					std::cout << "Ball Spawned!" << std::endl;
					m_i = m_vBalls.begin();
					break;
				}
			}
		}
		else
		{
			m_vBalls.push_back (CBall(m_Player.GetX()*64, m_Player.GetY()*64));
			std::cout << "Ball Spawned!" << std::endl;
		}
	}
}

Re: BloopIt spawn Kollision

Verfasst: 26.01.2012, 09:38
von Jonathan
Ich versteh überhaupt nicht den Sinn, von dem Programmfetzen da. Du willst einen Ball erstellen und gehts dafür die Liste der vorhandenen Bälle durch und erstellst immer dann einen neuen, wenn der aktuelle Ball nicht an der Spielerposition ist? Das ist so wirr, das muss eigentlich falsch sein und wenn nicht gehört da mal mindestens ein erklärendes Kommentar dazu.

Willst du prüfen, ob vor dem Spieler platz ist? Da tu das doch einfach. Durchlauf die Liste und speichere in einem boolean, ob vor dem Spieler Platz ist. Wenn 'ja', erstellst du NACH der Schleife einen Ball, wenn 'nein' eben nicht.

Re: BloopIt spawn Kollision

Verfasst: 26.01.2012, 12:46
von Raidenkk
Ich möchte beim Spawnen prüfen ob da schon ein ball ist weil die nicht übereinander spawnen sollen ^^

Re: BloopIt spawn Kollision

Verfasst: 26.01.2012, 14:03
von Bergmon
Hi, ich reformatiere auch ein Mal den Code ;):

Code: Alles auswählen

void CBloopIt::CreateBalls ()
{
    if (m_Player.GetSpawnBall () == true)
    {
        m_Player.SetSpawnBall (false);
        if (m_vBalls.size() > 0)
        {
            for (m_i=m_vBalls.begin(); m_i!=m_vBalls.end(); m_i++)
            {
                if (m_i->GetX() != m_Player.GetX ())
                {
                    m_vBalls.push_back (CBall(m_Player.GetX()*64, m_Player.GetY()*64));
                    std::cout << "Ball Spawned!" << std::endl;
                    m_i = m_vBalls.begin();
                    break;
                }
            }
        }
        else
        {
            m_vBalls.push_back (CBall(m_Player.GetX()*64, m_Player.GetY()*64));
            std::cout << "Ball Spawned!" << std::endl;
        }
    }
}
Und da fallen einem mehrere Sachen ein: Du schreibst leider nichts über die Kollisionsabfrage bzw. die Geometrie. Aus

Code: Alles auswählen

CBall(m_Player.GetX()*64, m_Player.GetY()*64)
nehme ich an, dass du auf einem Gitter mit quadratischen Zellen der Größe 64 arbeitest.
Wenn du einen Ball erzeugen möchtest, dann darf das immer in der Diagonal-Spieler-Zelle passieren. Das passiert immer, wenn es noch keinen gab oder wenn die aktuelle X-Zelle eines Balles nicht mit der Spieler-X-Zelle übereinstimmt. Im letzteren Fall fügst du einen neuen Ball wieder an der Diagonal-Spieler-Zelle ein und fängst die Einfügeprozedur von neuem an.
Fragen:
  • Warum überprüfst du nur die X-Zelle, was ist mit der Y-Zelle?
    Kann es passieren, dass du mehrere Bälle in der Diagonal-Spieler-Zelle einfügst? (Ich denke ja.)
Ich denke, wenn du die beiden Fragen beantwortet hast, wirst du dein Problem lösen können.

Viele Grüße
Bergmon

Re: BloopIt spawn Kollision

Verfasst: 27.01.2012, 04:34
von Raidenkk
Hier ist meine Kollision leider habe ich noch Schwierigkeiten einen Ball1 auf Ball2 Stoppen zu lassen weil die sich irgendwie verhaken und einfach in der Luft stehen bleiben.

Code: Alles auswählen

void CBloopIt::Gravity (sf::RenderWindow &Game)
{
	for (std::vector<CBall>::iterator i=m_vBalls.begin(); i!=m_vBalls.end(); i++)
	{
		i->SetFall (true);
		for (std::vector<CBall>::iterator k=m_vBalls.begin(); k!=m_vBalls.end(); k++)
		{
			if (i != k)
			{
				if (i->GetAnimX() == k->GetAnimX() && i->GetAnimY() >= k->GetAnimY()-64)
				{
					i->SetFall (false);
				}
			}
		}

		if (i->GetFall () == true)
		{
			float Fallspeed = i->GetAnimY();
			Fallspeed += 150*Game.GetFrameTime ();
			i->SetAnimY(Fallspeed);

			if (i->GetAnimY() > 448)
			{
				i->SetAnimY(448);
			}
		}

		if (i->GetAnimY() > i->GetY()*64)
		{
			float Temp;
			Temp = i->GetAnimY ();
			i->SetAnimY (Temp);
		}
	}
}
Ich bedanke mich für die Hilfe :)

Re: BloopIt spawn Kollision

Verfasst: 27.01.2012, 13:07
von Bergmon
Bitte verwende doch eine gute Formatierung für Programmcode (z.B. mit Tabulatoren siehe Post oben und mit [ code=cpp ][ /code ]-Tag, sonst kann das Lesen des Post wirklich eine Mühe sein.

Ich habe dieses Mal nicht alles genau angeschaut, doch was auffällt: In einem jeder mit jedem Vergleich reicht es, wenn du

Code: Alles auswählen

for (std::vector<CBall>::iterator i = m_vBalls.begin(); i != m_vBalls.end(); i++)
{
    i->SetFall (true);
    for (std::vector<CBall>::iterator k = i + 1; k != m_vBalls.end(); k++)
    {...

prüfst. Das ist dann nur eine Dreiecksmatrix ohne Diagonale. Damit fällt deine If-Abfrage weg und auch die restliche doppelte Interaktion. Vielleicht verursacht sie diese Probleme? Wenn es Bälle sind, dann musst du sie nach der Kollision um den gemeinsamen physikalischen Mindestabstand verrücken (hier schätze ich die Summe der beiden Radien der interagierenden Bälle, bzw. der Durchmesser), da sonst gleich wieder eine Kollision mit dem selben Objekt stattfindet.

Viele Grüße
Bergmon

p.s.:
Was hat

Code: Alles auswählen

float Temp;
Temp = i->GetAnimY ();
i->SetAnimY (Temp);
für eine Funktion? :lol:

Re: BloopIt spawn Kollision

Verfasst: 28.01.2012, 15:33
von Raidenkk
Es gibt ein mal X und dann gibt es AnimX das ist wie X nur *64.
Und meine Funktion oben ist nicht vollständig ^^.

Code: Alles auswählen

float Temp;
Temp = i->GetAnimY ();
++ Temp;
i->SetAnimY (Temp);