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

20.02.2017, 13:43

Mausklick mit folgen

Hallo,

ich übe mich gerade in Lua mit dem Framework Löve, aber das tut vielleicht eher weniger zu Sache. Zur Übung erstelle ich ein Tower Defense Spiel.

Wenn ich einen Mausklick mache um einen der aktuell 3 versch. Tower auszuwählen, dann läuft im Hintergrund eine Kollisionsabfrage ab. Ich habe also auf X und Y sowieso geklickt und dann läuft eine if Anweisung eine Tabelle (in C++ wäre es ein Arry) durch und prüft alle möglichen Button. Aber nicht nur die 3 möglichen Button. Es prüft auch die Türme die bereits platziert wurden und alle anderen möglichen Schaltflächen die ich anklicken könnte.

Meine Frage nun: das kommt mir so umständlich und aufwendig vor, bei jedem Mausklick alle Möglichkeiten prüfen zu lassen. Mache ich hier etwas falsch?

Eine zweite Frage habe ich auch noch. Wenn ich mich demnächst daran machen würde meine Tower zu bewaffnen, das findet ja eigentlich pro Tower pro deltaTime eine kollisionsabfrage statt, ob ein Gegner in Reichweite ist, richtig? Oder habe ich mich jetzt zu sehr auf Kollisionsabfragen gestürtzt?

Frage drei ist, ich habe keine Ahnung wie ich das Spielfeld machen soll. Meine einzige Idee wäre es ein Tabelle zu nutzen und dann per Hand jedes mögliche Tile mit einer 0, 1, 2, 3 oder was auch immer zu füllen ... ziemlich aufwendig wie ich finde.

Wäre schön ein paar Antworten zu bekommen. Vielen Dank schon mal :-)

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

20.02.2017, 13:48

Üblicherweise verwendet man das "Listener" / "Event" Prinzip. Das heißt man hängt eine optionale Callback an ein Element und eine zentrale Stelle prüft auf Treffer ruft dann alle Callbacks von den Elementen auf, die angeklickt wurden.

How to make levels - ASCII Art:
####~~~###
##+~~~~`##
###~o~~~##
###~~~~/##
##########
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]

equinox

Frischling

Beiträge: 56

Beruf: Student

  • Private Nachricht senden

3

20.02.2017, 14:43

Also wenn du die X und Y Koordinaten hast, kannst du mit diesen doch direkt auf dein Array zugreifen und das entsprechende Tile überprüfen.

Ich verstehe das so, dass du zurzeit ungefähr folgendes machst:

C#-Quelltext

1
2
3
4
5
6
7
8
9
int mouseX = mouse.getX(); //greife auf die Mauskoordinaten zu, wie auch immer das bei dir gemacht wird
int mouseY = mouse.getY();
for(int i = 0; i < mapHeight; i++) {
for(int j = 0; j < mapWidth; j++) {
if(i == mouseY && j == mouseX) {
   map[i][j].clicked(); //Auf den Click reagieren
}
}
}


Statt dessen könntest du es gleich so machen:

C#-Quelltext

1
map[mouseY][mouseX].clicked();


Das ist natürlich alles nur Pseudo-Code und jetzt gedanklich von mir eher nach Java-Art geschrieben.

Ich hoffe ich konnte dir damit weiterhelfen. :)


Edit: Ich glaube ich habe den Text etwas falsch verstanden...

4

20.02.2017, 15:20

Das mit dem Listener / Event Prinzip hört sich besser an, als das was ich mache. Belese ich mich nachher mal zu :-)

Hier mal kurz was ich mache

Zitat


-- Table/Button für alle möglichen Tower
Tower = {}
Tower[1] = {x=625, y= 75, breite=20, länge=20, R=200, G=100, B=100}
Tower[2] = {x=625, y=115, breite=20, länge=20, R= 80, G=120, B= 80}
Tower[3] = {x=625, y=155, breite=20, länge=20, R=100, G=100, B=200}

Zitat


function love.mousepressed(x, y, button)
if button == 1 then
for i=1, #Tower do
if x >= Tower.x and x <= Tower[i].x + Tower[i].länge then
if y >= Tower[i].y and y <= Tower[i].y + Tower[i].breite then
table.insert(listOfTowers, createEaraser(Tower[i].R,Tower[i].G,Tower[i].B))
globalStick = true
end
end
end
end
end


In dem ersten Zitat ist eine Tabelle (wie ein Arry) wo von jedem Button die x und y koordinate gespeichert ist.
Die funktion love.mousepressed ließt die x und y koordinate aus wenn ich die Maustaste 1 drücke (Linke Maustaste).
Die folgende If anweisung vergleicht dann und sucht mir aus der Liste den angeklickten Turm.

Soweit, so gut. Aber wenn ich jetzt später mal 10.000 Türme platziert habe scheint mir das eine schlechte Lösung.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

5

20.02.2017, 16:10

Du verstehst das falsch. Wenn du eine Tilemap hast und sich deine Türme nur direkt auf dem Kachelraster befinden dann kannst du von deiner Mausposition zu Tilekoordinaten umrechnen. Sagen wir deine Tiles sind 64 Pixel Breit und Hoch und deine Mausposition ist 1337, 42 in Pixeln. Dann sind deine Tilekoordinaten 1337/64, 42/64 wobei abgerundet wird. Die Koordinaten auf der Tilemap sind also 20, 0. Jetzt guckst du in deiner Tabelle was sich an der Position befindet. Befindet sich dort ein Turm führst du den Code aus der ausgeführt werden soll wenn der Turm angeklickt wurde. Du musst also nicht alle Türme durchlaufen sondern nur gucken was sich an der Position befindet. Für GUI kannst du das an sich auch so machen. Es gibt aber allgemein viele verschiedene Ansätze. Ich habe zum Beispiel mal einen Ansatz gesehen bei welchem eine Grafik mit der Größe des Fensters erstellt wurde. Die Pixelfarben der Grafik bekommen eine bestimmte Bedeutung. Du kannst zum Beispiel reines Weiß für nichts nehmen, und andere Farben für verschiedene Buttons. Das ganze läuft jetzt so an. Die Flächen die von einem Button bedeckt werden werden nun mit der passenden Farbe eingefärbt. Jeder Button bekommt seine eigene Farbe. Wenn du jetzt mit der Maus klickst wird geguckt welche Farbe an der Position in dieser Grafik ist. Ist die Farbe Weiß wurde kein Button angeklickt. Die anderen Farben ordnen eben den passenden Button zu. Da kannst du dann zum Beispiel per Dictionary auf den passenden Button verweisen. Das ganze ist natürlich aufwendig sobald verschiedene Auflösungen oder dynamische Buttonpositionen ins Spiel kommen.
Alternativ kannst du deine GUI auch in eine Baumstruktur unter bringen. Guck vielleicht mal wie GUI Frameworks sowas lösen.
„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.“

6

20.02.2017, 21:37

Das mit dem Tile verstehe ich :-) trotzdem habe ich schnell mal über 100 Tiles für eine Map, wovon ich zumindest die Tiles "per Hand beschriften" muss die Pfad sein sollen.

Das Stichwort GUI hat mir weiter geholfen.

Kurz zusammengefasst wie ich gerade ans das Thema ran gehe:
Ich klicke irgendwo hin, lese die Koordinaten ein.
Die Funktion vergleicht dann meine X,Y Koordinate mit allen im Spiel befindlichen Objekten die mit der linken Maustaste anklickbar sind.
Zb. sind alle Türme die ich kaufe kann in einer Tabelle, in einer anderen Tabelle sind alle platzierten Türme, in wieder einer anderen die Upgrade Buttons.
Je nachdem in welcher Tabelle er nun fündig geworden ist folgt eine andere Reaktion. Ist er in der kaufbaren Türme Tabelle fündig geworden, wird der Turm gekauft. Ist er in der platzierten Türme Tabelle fündig geworden, wir dieser ausgewählt usw.

Wie ich das von Schorsch verstanden habe:
Ich klicke irgendwo hin, lese die Koordinaten ein.
Dann wandle ich die Koordinaten in ein Tile um.
Dann schaue ich nur was in dem einen Tile ist. Das hört sich definitiv besser an. Aber ich habe keine Ahnung wie das gehen soll xD

melde mich nochmal wenn ich schlauer geworden bin ....

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

7

21.02.2017, 04:49

Du hast ein zweidimensionales Array von Tiles. Wenn du jetzt weißt dass deine Maus das dritte Tile von links und das 5te von oben angeklickt hat dann weißt du doch an welcher Position es sich in deinem Array befindet. Per Index greifst du dann direkt auf das Tile zu. An sich musst du nur mal nach Tilemap Tutorial oder vergleichbarem googlen. Sowas sollte eigentlich in so gut wie jedem grundlegenden Tilemap Tutorial erklärt werden.
„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.“

8

21.02.2017, 16:39

Ok ok weiß nun wie :-)

Öhm .. ma noch ne andere Frage ... wie mache ich das mit der Auflösung? Aktuell gebe ich die Position eines Buttons mit einem festen Wert an .. wir wissen wohl alle was passiert wenn sich die Auflösung nun ändert...

Ich hab überlegt die Auflösung durch einen festen Wert zu teilen, so erhöht sich das Ergebnis der Division bei steigender Auflösung und der Button wandert (hoffentlich) im passenden Verhältnis. Aber es gibt ja auch noch das Bildverhältnis (16:9, 16:10 ..) ...

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

9

21.02.2017, 19:06

Wichtig ist doch wie das Verhalten sein soll. Um dir da erst mal selbst sicher zu werden was du möchtest kann es wieder hilfreich sein wenn du dir fertige Frameworks für GUIs ansiehst.
„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.“

Werbeanzeige