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

1

30.11.2013, 15:33

Iterator funktioniert nicht wie gewollt

Hey,

ich versuche gerade in QT einen TileEditor zu implementieren. Momentan lade ich ein Bild in eine Pixmap und kopiere dann die einzelzeile in weitere pixmaps und füge sie einer Liste hinzu
Das klappt auch soweit ganz gut. Jetzt versuche ich die tileID herauszufinden wenn ich auf das entsprechende Tile in der Scene klicke:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
void tileScene::getTileID(std::map<int,QPixmap> &map, std::map<int,QPixmap>::iterator &it)
{
    for(it = map.begin(); it != map.end();++it)
    {
        if(x - it->second.rect().x() < 32 && y - it->second.rect().y() < 32 &&
            x - it->second.rect().x() >-32 && y - it->second.rect().y() >-32)
        {
            std::cout << "test";
        }          
    }
}


x und y sind die Mauskoordinaten und 32 ist die größe eines Tiles.

Wenn ich die Tilemap lade und auf das erste Tile klicke erscheint der text wie gewünscht, aber wenn ich auf ein anderes Teil klicke passiert nichts.
Ich habe außerdem noch nicht viel mit Iteratoren gearbeitet deswegen denke ich irgentwo einen doofen Fehler gemacht habe.

LG

Sylence

Community-Fossil

Beiträge: 1 663

Beruf: Softwareentwickler

  • Private Nachricht senden

2

30.11.2013, 15:45

Meine C++ Zeit liegt zwar schon eine Weile zurück, aber für mich sieht der Iterator eigentlich richtig aus.
Was du aber mal machen könntest: QRect hat eine contains() Methode, die genau das machst, was du da versuchst.

Was ich mich aber gerade frage: Warum übergibst du den Iterator als Parameter an die Funktion?

3

30.11.2013, 16:01

Debug mal und schau ob da wirklich mehrere Elemente in der Map sind.
Sind die Mauskoordinaten korrekt?
Bei deiner if-Bedingung ist ein Tile jedoch nicht 32 Einheiten, sondern 62 Einheiten groß!
Dank C++11 kannst du das Ganze übrigens auch auf folgendes kürzen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
void tileScene::getTileID(const std::map<int,QPixmap> &map) //const hinzugefügt, da nur ausgelesen wird
{
    for(auto it : map)
    {
        if(x - it.second.rect().x() < 32 && y - it.second.rect().y() < 32 &&
            x - it.second.rect().x() >-32 && y - it.second.rect().y() >-32)
        {
            std::cout << "test";
        }          
    }
}

Der Name der Fuktion irritiert mich im Übrigen, wenn ich auf ihren Typen gucke.

MfG
Check

4

30.11.2013, 16:12

Zitat


Was ich mich aber gerade frage: Warum übergibst du den Iterator als Parameter an die Funktion?
Das habe ich bis jetzt immerso gemacht, ich weiß das ich das auch mit auto it = liste.begin() lösen könnte.

Zitat

Debug mal und schau ob da wirklich mehrere Elemente in der Map sind.
Ja, die Elemente sind alle in der Map drin.

Zitat

Sind die Mauskoordinaten korrekt?
Ja sind sie.

Zitat


Dank C++11 kannst du das Ganze übrigens auch auf folgendes kürzen:
Ich probiers mal aus danke :)

Zitat


Der Name der Fuktion irritiert mich im Übrigen, wenn ich auf ihren Typen gucke.
Die Funktion ist auch noch nicht fertig und ich war zu faul return zu schreiben deshalb habe ich void genommen ^^


Edit: Der Code von dir funktioniert leider nicht, kann aber daran liegen das ich noch einen 2010er compiler benutze.

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

5

03.12.2013, 11:51

Du weißt, wie groß deine Tiles sind. Warum errechnest du nicht einfach die Koordinaten und darüber den Index?
das würde dann ungefähr so aussehen:
tileX = mouseX / tileWidth
tileY = mouseY / tileHeight

Sollte der Klick auch für Bereiche abgefangen werden, auf dem keine Tiles dargestellt werden, muss außerdem noch eine Prüfung durchgeführt werden, ob die Tilekoordinaten sich im gültigen Bereich befinden.
Auch wäre es sinnvoll zu gucken, ob man nicht Events für das Klicken auf einen bestimmten Tile bekommen könnte, statt für den Klick auf die Fläche, auf der alle dargestellt werden. (Dann müsste diese Umrechnung oben nicht durchgeführt werden.)

Da bei dir die Tiles in einer Datenstruktur mit einem int-Index liegen, sollten alle Tiles auch geordnet hintereinander liegen (ansonsten solltest du ohnehin überdenken, was du bisher gemacht hast...)
An den Index würdest du dann entweder über
index = tileX + tileY * columns
oder
index = tileX * rows + tileY
kommen.

Die Methode "GetTileId" sollte als Parameter die Koordinaten des Tiles (nicht der Maus o. ä.) erwarten und dann die ID zurückliefern (wobei es sich wohl anbieten würde, die Informationen über ein Tile in bspw. einer struct oder einer Klasse zusammenzufassen und diese zurückzuliefern).
Die Umrechnung der Mauskoordinate in die Tilekoordinate sollte von der Oberfläche durchgeführt werden. Die Datenstrukturen im Hintergrund haben rein gar nichts mit der Visualisierung zu tun. Sollte an der Oberfläche mal ein Zoom eingebaut werden, muss so auch wirklich nur die Oberfläche (in dem Fall die Umrechnung der Mauskoordinate) angepasst werden und der Rest würde weiterhin funktionieren.

Und was das zu faul sein im Zusammenhang mit dem Rückgabetyp angeht:
Ich fange auch oft an, eine Methode zu schreiben, ohne eine sinnvolle Rückgabe zu haben.
ABER: es ist bereits die Rückgabe eines "Standardwerts" vom richtigen Typ vorhanden (null, 0, -1, Leerstring, ...)
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

6

03.12.2013, 12:13

Vielleicht nicht ganz zum Problem passend, aber: Warum übergibts du den Iterator als Parameter?
Er wird eh überschrieben und zum Ende hochgezählt. Die aufrufende Funktion hat dann einen Iterator
der aufs Ende zeigt bei sich rumfliegen. Darin sehe ich gerade keinen potenziellen Sinn.
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

7

03.12.2013, 14:26

Ich habe es jetzt anders gelöst und die TileMap in ein QTableWidget geladen, dadurch kann ich dann die aktuelle zeile und spalte herausfinden und damit dann den Index ausrechnen.
Danke für die ganzen Antworten :)

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

8

04.12.2013, 00:35

Klingt nicht so gut, weil du damit Logik und Darstellung vermischst.

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

9

04.12.2013, 09:28

Ich habe es jetzt anders gelöst und die TileMap in ein QTableWidget geladen, dadurch kann ich dann die aktuelle zeile und spalte herausfinden und damit dann den Index ausrechnen.
Danke für die ganzen Antworten :)

Klingt nicht so gut, weil du damit Logik und Darstellung vermischst.

Das wiederum kann ich nicht ganz nachvollziehen. Liegt es an dem QTableWidget und irgendwelcher Magie, die dieses im Hintergrund anwendet? (Ich habe noch nicht mit Qt gearbeitet also könnte ich nur anhand vergleichbarer Konstrukte herleiten, was das Verhalten ist.) Oder an der Ermittlung des Index?

Wenn es die Tabelle sein soll, dann wäre es auch ganz gut zu wissen, was eine bessere Alternative darstellen soll. Wenn man sich um das Zeichnen gänzlich selbst kümmert und ein Element nimmt, welches beim Anklicken nicht zwischen Unterelementen unterscheidet, muss man sich wieder selbst um die Umrechnung der Mausposition zu Tile-Koordinate kümmern. (Bei einer Tabelle gehe ich auch davon aus, dass man den Inhalt der Zellen separat zeichnet und nicht die Tiles als Tabellenhintergrund, um dann die Zellen nur für den Input zu verwenden.)

Sollte es die Umrechnung (Tilekoordinate zu Index) sein, so sehe ich nicht, dass die Beschreibung seinerseits auf eine Vermischung schließen lässt. Das Ding, was die ganzen Tiles verwaltet, sollte nur über die Tilekoordinaten angesprochen werden, die Formulierung lässt aber nicht eindeutig darauf schließen, dass die Ermittlung des intern verwendeten Index nach außen verlagert werden soll.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

10

04.12.2013, 13:04

Zitat

(Bei einer Tabelle gehe ich auch davon aus, dass man den Inhalt der
Zellen separat zeichnet und nicht die Tiles als Tabellenhintergrund, um
dann die Zellen nur für den Input zu verwenden.)
Genau so ist es.

Werbeanzeige