Seite 1 von 2
2d Karte, skalierung....
Verfasst: 01.09.2008 09:21
von Toshy
Hallo,
im Grafikbereich habe ich fast noch nie was gemacht. Außer einfach mal ne Box, Image, eliplse oder so zu Zeichen hab ich noch nichts gemacht. Nur die normalen Gadgets halt ein wenig verwendet.
Ich habe jetzt eine Karte bzw. Daten dazu. Ähnlich einem Schachbrett.
Sagen wir mal 200x200 Felder. Nun will ich diese Karte ausgeben. Ein Pixel je Feld reicht zu beginn, villeicht auf 4 Pixel (2x2). Nun will ich natürlich wenn ich mit der Maus über diese Karte fahre oder Klicke bestimmte Daten anzeigen lassen.
Die Karte soll auch in der Größe anpassbar sein also vergrößert werden (komplett) oder auch nur ein Teil davon (damit nicht der ganze Bildschirm ausgefüllt wird). Natürlich will ich dann weiterhin durch die Mausposition Daten anzeigen lassen können.
Auf der Karte will ich natürlich bestimmte markieren, farblich oder mit Grafik.
Ein tolles Extra wäre es, wenn die 2dKarte sich auch noch drehen lassen würde (45 Grad schritte oder so).
Kann man sowas realisieren oder besser gesagt geht das auf relativ einfache Art und Weise. Klar, etwas einarbeiten muß man sich, aber ich will jetzt nicht einen Monat damit verbringen nur zu lernen wie man ein Schachbrett darstellt
Ein paar Grundlegende Infos von euch wie man sowas angehen kann währen echt toll. Ich habe mir in der Hilfe mal ganz kurz die Grafikdinge überflogen, aber keine Ahnung wie man das angehen sollte.
Gruß
Toshy
Verfasst: 01.09.2008 10:00
von gnasen
Die wohl einfachste Lösung wäre eine Kombination von ImageGadget und einem Array.
Du nimmst als Arrayindex die Koordinaten und gibts als Wert die Eigenschaften, quasi:
Wenn du nun die Felder 100-150 der Karte darstellen willst, gehste die Felder entsprechend mit einer for Schleife durch (von 100 bis 150) und zeichnest die mit
Auf dein ImageGadget. Kannst alles auch mit einem Screen machen, braucht allerdings mehr Ressourcen. Das Drehen der Map ist kein Problem, du musst dann nur die zu lesenden X und Y Bereiche entsrpechend ändern (bei 90 und 270 grad wird zB X zu Y und umgekehrt)
Verfasst: 01.09.2008 11:22
von Vermilion
Die beste Lösung für dieses Problem wäre das Benutzen von der Sprite3D Bibliothek (Screen und so).
Verfasst: 01.09.2008 18:03
von Toshy
Hi.
Ich hab mich in einer Sache sehr unklar ausgedrückt. Ich bekomme den Code bzw. Mapcode schon hin, was ich nicht weiß ist welche Grafikfunktionen ich nutzen sollte. 3d, Libaray, 2d libary, die einfachen 2dGrafikfunktionen die in der Hilfe ganz oben stehen UND auf welche Art man halt eine Map einfach vergrößern oder / und drehen kann und gleichzeitig die Positionsabfragen korrekt hinbekommt.
Solange ich ein einfach Image nehme und die größe der Map einfach nur m it einem Faktor malnehme und das dann in Pixeln zeichne geht es auch mit der Abfrage sicher einfach, aber was ist wenn ich die karte Drehen will, oder die Map "grafik resizen" will oder wenn ich an bestimmten Punkten grafische Elemente einbauen will die nicht dem Maßstab entsprechen (um bestimmte Punkte leicher erkennbar zu machen).
Ich will das zwar für mehrere Dinge nutzen, zum testen aber nutze ich Daten aus einem Onlinebrowserspiel. Im GANZ GROBEN ähnlich wie auf der Website
http://spawen.dyndns.org/travian.w3/TMap2
(hat auch eine Zoomfunktion)
Grafisch soll es sogar sehr schlicht sein, fast minimalistisch

aber ich will halt eine Karte die ich im ganzen sehe aber jederzeit zoomen oder Scrollen kann und dennoch klar und wenn möglich einfach identifizieren wo auf der Karte sich z.B. die Maus gerade befindet (für Zusatzinfos zu dem Punkt).
Grafisch bin ich wirklich ahnungslos und stehe bei den Funktionen in der Hilfe vor einem großen Wald und sehe dahe irgendwie die Bäume nicht.
Verfasst: 01.09.2008 18:51
von Kaeru Gaman
> Ich bekomme den Code bzw. Mapcode schon hin
also, das Grundprinzip einer tileengine ist dir bekannt....
( http://www.purebasic.fr/german/viewtopi ... 634#116634 )
das Zoomen ist im endeffekt mehr Mathematik als Grafikeffekte:
du brauchst eigentlich nur ZoomSprite3D, aber du musst natürlich die koordinaten sehr genau berechnen.
beim Drehen wird das nur wenig komplizierter: mit RotateSprite3D kannst du 45° weise drehen,
und die Anzeigekoordinaten kannst du auch dementsprechend recht einfach ausrechnen.
wenn dir das ein bissel ungenau ist, wäre vielleicht TransformSprite3D die bessere Lösung...
Verfasst: 01.09.2008 21:28
von Toshy
weiß nicht. "tileengine" sagt mir zwar nichts, aber ne einfache Map auf Basis von z.B. einem Array oder was zu erstellen sollte nicht so daß Problem sein. Einzig die mit Grafikfunktionen kenne ich mich nicht aus.
Ich kenne nur Gadgetevents und sonst noch Mauspositionen auslesen. Daher meine Fragen
Mit der Mathematik hab ich mir schon gedacht. Da es aber heutzutage recht viele "fertige Libs" gibt oder so, dachte ich das es da was gibt was mir das abnimmt und eher wie Gadgets funktioniert.
Also Theoretisch x mal x Felder je ein Gadget (oder was es das grafischtechnisch gibt) und wenn ich das übergeordnete Grafikelement vergrößere diese anderen untergeördnenen das automatisch mitmachen und jeder klick oder so automatisch einem Objekt, Handle oder so zugeordnet wird. Natürlich nur da wo auch "Punkte / Daten" in der Map liegen, beim Rest reicht die Position.
Ich schaue mir den Beitrag unter deinem Link mal etwas an.
Verfasst: 01.09.2008 21:38
von Kaeru Gaman
verstehe.
also grundsätzlich solltest du für so etwas mit nem Screen arbeiten, wenn du denn so etwas wie ein Game machen willst.
Einfach aus dem grund, weil sprites und double-buffering wesentlich performanter
und flexibler sind als jedes rumgespiele mit Images und Gadgets.
ja es gibt Libs die dir Gadgets auf nem screen simulieren, aber das wäre ein ziemlich umständlicher weg hier,
da diese libs dafür gemacht sind, eine GUI auf einem Screen zu erstellen,
aber eine GUI benutzen um eine Map umzusetzen ist sehr umständlich und langsam,
also hättest du da zwei Bremsen drin, mach sowas lieber direkt.
nimm dir in dem verlinkten thread mal den zweiten code vor, da ist ein MouseOver schon implementiert.
auch wenn die Map nicht dreht und nicht zoomt, kannst du vielleicht schon das prinzip erkennen, wie man direkt über die koordinaten vorgeht.
solche sachen sind immer sehr zeitkritisch und sehr problemspezifisch,
und wenn man die mathematik einmal verstanden hat, ist der code nicht umfangreich, lediglich komplex.
es ist also eigentlich meistens das beste (für kleine, performante Projekte)
so etwas from the scratch absolut auf das problem zugeschnitten zu coden,
anstatt auf umständliche bibliotheken zurückzugreifen und hohe performance-verluste in kauf zu nehmen.
(zumal es für PB gar nicht so viele und umfangreiche bibliotheken gibt)
Verfasst: 01.09.2008 22:33
von Toshy
Ich schauer mir gerade mal die 2d-Dinge mit Sprites an, createsprite usw.
Wenn ich das richtig sehe muß ich hier im Gegensatz zum Gadget ständig die Grafik neu kopieren wenn ich was ändere. Also Fenster / Screen leeren, und mit neuer Position alles neu machen. Bei Gadget kann ich ja einfach ein Gadget verschieben.
Wäre so aber ok.
Aber es gibt auch was mit Kollisonen und einiges andere.
Wenn ich nun Grafiken habe die auf verschiedenen Ebenen laufen, also Hintergrund, dann irgendwelche statischen Elemente (Sprites) die sich nicht bewegen und einige die sich bewegen aber oben drauf sein sollen, wie mache ich das. Ist das einfach eine Sache der Reihenfolge in der ich die Sprites kopiere? Ich frage nur damit ich das gleich richtig verstehe.
Das würde dann heißen, ich müßte also auch ein "Sprite" für den Hintergrund erstellen, sprich einfach eine Hintergrundgrafik die ich jeden Aufruf (z.b. einige male in der Sekunde) die ich neu kopieren muß und daruaf dann die Elemente?
Was zum Zoom und drehen. Wenn die Karte nun normal gezeichnet wird, dann wäre ein Zoom der Grafiken / Map ja nur ne multiplikationssache und ebenso die Mausposition anzupassen. Also dargestellten Bereich und zoom Faktor "merken" und dem ensprechen coden. Ich müßte also alles selbst machen. Soweit ist das hoffentlich richtig.
Aber was ist wenn ich z.B. die ganze Karte und die Zugriffe drehen wollte. Sagen wir mal, ich hätte die Map / Karte auf dem Bildschirm erstellt und dort sagen wir mal "Bäume" drauf kopiert.l So kann ich klicks darauf wohl anhand der Mauspositon in erfahrung bringen oder was es da gibt. Aber wenn ich dir Karte z.B. um 45% drehen will damit sie auf der Kante steht, wie könnte ich dann die Positionen usw. in erfahrung bringen?
Der zweite Teil mit dem Drehen ist mir nicht so wichtig, aber wenn ich das später vielleicht doch nachrüsten will, dann will ich nicht auf einmal erleben das ich dafür komplett alles hätte anders machen müssen.
Anmerkung:
Aktuell geht es mir um das Verständniss des grafischen Dinge, die erste Karte die ich erstelle und brauche wird was einfaches sein und da Frage ich dann direkt auf das jeweilige Problem bezogen.
Verfasst: 01.09.2008 22:49
von Kaeru Gaman
> Ist das einfach eine Sache der Reihenfolge in der ich die Sprites kopiere?
völlig richtig.
ein screen wird immer von hinten nach vorne aufgebaut.
übrigens würde ich nicht den begriff "kopieren" verwenden, sondern "darstellen",
weil der zuständige Befehl DisplaySprite ist.
CopySprite dient zum kopieren von einem sprite in ein anderes.
einen screen immer komplett neu aufzubaun ist völlig normal, das ist sinn der sache.
ein screen wird auch immer in jedem durchgang erstmal gelöscht, um den alten Inhalt zu verwerfen.
das ist nötig, weil mit doppeltem Buffer gearbeitet wird, sonst würde man immer den vorletzten Inhalt nochmal darstellen.
es wird also immer auf einen Buffer im Hintergrund die Sprites dargestellt,
während der andere fertige Buffer auf dem Bildschirm dargestellt wird.
der Sinn dabei ist, dass man keine halbfertigen Komplettbilder zu sehen bekommt.
> einfach eine Hintergrundgrafik die ich jeden Aufruf (z.b. einige male in der Sekunde) die ich neu kopieren muß und daruaf dann die Elemente?
wenn du eine hintergrundgrafik brauchst?
aber oft wählt man den kartenausschnitt so groß, dass er den Screen komplett ausfüllt,
man braucht also keinen Hintergrund dahinter eigentlich nichtmal ein Clear.
oder man wählt eine feste farbe für den hintersten Hintergrund, die man dann direkt bei ClearScreen angibt.
> Sagen wir mal, ich hätte die Map / Karte auf dem Bildschirm erstellt und dort sagen wir mal "Bäume" drauf kopiert.l So kann ich klicks darauf wohl anhand der Mauspositon in erfahrung bringen oder was es da gibt.
genau, im grunde analog zu dem Beispiel.
man würde sogar (meistens) die objekte direkt im selben Array notieren, und in der selben doppelschleife darstellen,
also unmittelbar nach der Tile auf der sich das Objekt befindet, noch vor er nachbartile.
> Aber wenn ich dir Karte z.B. um 45% drehen will damit sie auf der Kante steht, wie könnte ich dann die Positionen usw. in erfahrung bringen?
ja, da wird die Mathematik dahinter um einiges komplizierter, aber machbar ist es.
am praktischsten wäre es, die koordinaten direkt im moment der darstellung zu vergleichen,
da man ja für die darstellung ausrechnen muss, wo man momentan grad das tile und das objekt hin Displayt,
da kann man auch mit den Mauskoordinaten vergleichen und die schleifenposition rückpuffern.
eventuell wäre es lohnender für dich, erst mal mit nur 90° drehungen zu arbeiten, weil 45° gleich nen ganzen schub komplizierter ist.
außerdem solltest du dir über mögliche perspektive gedanken machen,
weil das gegenüber reiner draufsicht noch "eine komplette kompliziertheit" dazupackt.
Verfasst: 02.09.2008 16:53
von kswb73
Hallo, Ich hab hier mal eine Feldbasierende Karte zusammengecodet. Die Daten sind in einem Strukturierten Array abgespeichert. Die Karte kann gezoomt und in 45° Schritten rotiert werden.
Das Rotieren ist recht einfach. Rotate ist die Rotation (von 0 bis 3). Seh dir einfach Zeile 113 bis 121 an. Gedreht wird mit den Tasten x und y. Wenn du unförmige Felder hast (also nicht wie hier die bei allen rotatioen gleich ausehen) müsstes du noch die Felder rotieren.
Das Zoomen ist etwas komplexer. Hier wird in Zoom.f der Zoomfaktor gespeichert (ist ein Float fals du gennauer zoomen möchtes). Alle Bildgrößen werden durch diesen Faktor dividiert um die größe zu erhalten. Die Feldpositionen auf dem Bildschirm ist (X-viewX)/Zoom. Also die X-Kordinate (wird im Code mit a*50 berechnet) minus viewX. viewX gibt an wo sich deine "Kamera" befindet. Das ganze wird zum Schluss nochmal durch den Zoomfaktor dividiert.
Die Mausposition wird MouseX()*Zoom+viewX berechnet.
Ich hoffe du hast alles verstanden und bist jezt wunschlos glücklich. Hier der Code:
PS:
Wird bei größeren Felder leider etwas langsam.
Code: Alles auswählen
#MapX=50
#MapY=50
InitSprite()
InitSprite3D()
InitMouse()
InitKeyboard()
Structure Map
typ.b
EndStructure
Dim Map.Map(#MapX,#MapY)
OpenScreen(1024,768,32,"Map-Test")
CreateSprite(1,50,50,#PB_Sprite_Texture)
StartDrawing(SpriteOutput(1))
Box(0,0,50,50,0)
Box(1,1,48,48,$00FF00)
StopDrawing()
CreateSprite3D(1,1)
CreateSprite(2,50,50,#PB_Sprite_Texture)
StartDrawing(SpriteOutput(2))
Box(0,0,50,50,0)
Box(1,1,48,48,$0000FF)
StopDrawing()
CreateSprite3D(2,2)
CreateSprite(3,10,20)
StartDrawing(SpriteOutput(3))
Line(0,0,0,20,$FF0000)
Line(0,0,10,20,$FF0000)
StopDrawing()
viewX=-100
viewY=-100
Zoom.f=1
Repeat
If IsScreenActive()
ClearScreen(0):ExamineKeyboard():ExamineMouse()
If KeyboardReleased(#PB_Key_Escape)
End
EndIf
If KeyboardPushed(#PB_Key_Left)
viewX-5*Zoom
EndIf
If KeyboardPushed(#PB_Key_Right)
viewX+5*Zoom
EndIf
If KeyboardPushed(#PB_Key_Up)
viewY-5*Zoom
EndIf
If KeyboardPushed(#PB_Key_Down)
viewY+5*Zoom
EndIf
If KeyboardReleased(#PB_Key_Y)
rotate-1
If rotate<0
rotate+4
EndIf
EndIf
If KeyboardReleased(#PB_Key_X)
rotate+1
If rotate>3
rotate-4
EndIf
endif
Start3D()
If MouseWheel()
Debug MouseWheel()
Debug "Zoom:"+Str(Zoom)
If MouseWheel()<0
Zoom*2
Else
Zoom/2
EndIf
If Zoom<1
Zoom=1
ElseIf Zoom>16
Zoom=16
EndIf
ZoomSprite3D(1,50/Zoom,50/Zoom)
ZoomSprite3D(2,50/Zoom,50/Zoom)
EndIf
MouseMapX=MouseX()*Zoom+viewX
MouseMapY=MouseY()*Zoom+viewY
If MouseMapX>0 And MouseMapY<#MapX*50 And MouseMapY>0 And MouseMapY<#MapY*50
If MouseButton(2)
Map(MouseMapX/50,MouseMapY/50)\Typ=1
ElseIf MouseButton(1)
Map(MouseMapX/50,MouseMapY/50)\Typ=0
EndIf
EndIf
For a=0 To #MapX
For b=0 To #MapY
If rotate=0
c=Map(a,b)\Typ
ElseIf rotate=1
c=Map(#MapX-a,b)\Typ
ElseIf rotate=2
c=Map(#MapX-a,#MapY-b)\Typ
ElseIf rotate=3
c=Map(a,#MapX-b)\Typ
EndIf
Select c
Case 0
DisplaySprite3D(1,(a*50-viewX)/Zoom , (b*50-viewY)/Zoom)
Case 1
DisplaySprite3D(2,(a*50-viewX)/Zoom , (b*50-viewY)/Zoom)
EndSelect
Next b
Next a
Stop3D()
DisplayTransparentSprite(3,MouseX(),MouseY())
EndIf
FlipBuffers()
ForEver