Scrollen mit View(s)

Übersicht BlitzBasic FAQ und Tutorials

Neue Antwort erstellen

 

Soul Reaver

Betreff: Scrollen mit View(s)

BeitragMo, Feb 16, 2009 0:09
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi,

da ihr mir so schön bei meinen BB-Problemchen helft, hab ich entschlossen ein Tutorial zu schreiben.
Es geht um die Verwendung von Views und dem sog. Scrolling.

Oft kommt es vor, dass die Welt in seinem Spiel größer sein soll als die Bildschirmauflösung. Doch wie soll man das machen? Views sind die Antwort. Zuerst sollte man festlegen wie groß der View und der Raum werden soll:

Code: [AUSKLAPPEN]

Graphics 800,600
SetBuffer BackBuffer()
AppTitle "Views"
fpstimer=CreateTimer(60)

Global roomwidth=1000
Global roomheight=1000 ;Raumgröße
Global viewwidth=800
Global viewheight=600 ;Viewgröße
Global viewx=0
Global viewy=0 ;Viewposition

;Main Loop
While Not KeyHit(1)
  WaitTimer fpstimer
  Cls

  Flip 0
Wend
End


Man sollte immer die Viewgröße der Graphics-einstellung anpassen!

So jetzt sollten wir natürlich ein paar Objekte erstellen und eine Funktion zum Bewegen des Views einbauen.

Code: [AUSKLAPPEN]

Graphics 800,600
SetBuffer BackBuffer()
AppTitle "Views"
SeedRnd MilliSecs()
fpstimer=CreateTimer(60)

Global roomwidth=1000
Global roomheight=1000 ;Raumgröße
Global viewwidth=800
Global viewheight=600 ;Viewgröße
Global viewx=0
Global viewy=0 ;Viewposition

Type obj
  Field x,y
End Type

;Zufällig ein paar Objekte erstellen... Da fällt mir auf, dass ich SeedRnd vergessen hab ;D
For i=0 To 19
  o.obj=New obj
  o\x=Rnd(roomwidth)
  o\y=Rnd(roomheight)
Next

;Main Loop
While Not KeyHit(1)
  WaitTimer fpstimer
  Cls

  Move() ;Funktion zum Bewegen des Views
  Draw() ;Funktion zum Zeichnen der Objekte

  Flip 0
Wend
End

;Funktionen
Function Move()
  If KeyDown(200) viewy=Max(0,viewy-3)
  If KeyDown(205) viewx=Min(roomwidth-viewwidth,viewx+3)
  If KeyDown(208) viewy=Min(roomheight-viewheight,viewy+3)
  If KeyDown(203) viewx=Max(0,viewx-3)

  ;Min() und Max() verwende ich dass der View nicht Gebiete außerhalb des Raumes zeigen kann... Ist aber nicht nötig
End Function

Function Draw()
  For o.obj=Each obj
    Rect o\x-viewx,o\y-viewy,10,10 ; Eigentlich sollte man Abfragen ob das Objekt im view ist!!!
  Next
End Function

Function Min(x,y) ;Gibt die kleinere Zahl zurück
  If x>y
   Return y
  Else
   Return x
  EndIf
End Function

Function Max(x,y) ;Gibt die größer Zahl zurück
  If x>y
   Return x
  Else
   Return y
  EndIf
End Function


Das ganze sollte jetzt so aussehen. Ich hoffe ich konnte einigen Anfängern helfen.

hectic

Sieger des IS Talentwettbewerb 2006

BeitragMo, Feb 16, 2009 2:40
Antworten mit Zitat
Benutzer-Profile anzeigen
Eine Tilemap sollte man in den wenigsten Fällen über Types erstellen. Das Problem ist einfach, dass bei großen Maps zuviel gezeichnet bzw. bei einer Überprüfung jedes mögliche Tile jedes Frame überprüft werden muß. Bei einem 2D-Array dagegen, kann man den sichtbaren Bereich einfach über eine doppelte Schleife eingrenzen. Das auslesen der Map geschieht also direkt was sehr recourcenschonend ist.

Damit besser sichtbar ist, wie ein sichtbarer Bereich eingegrenz wird, habe ich die Schleifen jeweils ab 1 und nicht bis zum Bildschirmrand laufen lassen.

Hier mal ein Beispiel:

Code: [AUSKLAPPEN]
Graphics 600,600,0,2
SetBuffer BackBuffer()

Const TILESIZE=40

Local Timer=CreateTimer(60)
Local X,Y,Block
Local MapXPos
Local MapYPos
Dim Map(63,63)

;EINE ZUFALLS-MAP ERSTELLEN
For Y=0 To 63
   For X=0 To 63
      Map(X,Y)=Rand(9)
   Next
Next


While Not KeyDown(1)
   
   MapXPos=MouseX()
   MapYPos=MouseY()
   
   ;DIE SICHTBARE MAP EINGRENZEN
   For Y=1 To 10
      For X=1 To 10
         
         ;DIE TILE-ID (HIER FARBE) ZWISCHENSPEICHERN
         Block=Map(X+(MapXPos/TILESIZE),Y+MapYPos/TILESIZE)
         
         ;WENN DIE TILE-ID GÜLTIG IST (ALSO VORHANDEN)
         If Block>0 Then
            
            ;IN DIESEM FALL (WEIL KEIN BILD GELADEN) DIE FARBE ANPASSEN
            Color Block*20,0,0
            
            ;IN DIESEM FALL (WEIL KEIN BILD GELADEN) EIN RECT EINZEICHNEN
            Rect (Int(MapXPos/TILESIZE)*TILESIZE)-MapXPos+X*TILESIZE,(Int(MapYPos/TILESIZE)*TILESIZE)-MapYPos+Y*TILESIZE,TILESIZE,TILESIZE,1
            
         End If
         
      Next
   Next
   
   WaitTimer Timer
   Flip 0
   Cls
Wend
End


Ich will allerdings dein Code auch nicht schlecht machen. Eine auf Types basierende Tilemap hat gewiss in seltenen Fällen ihre Vorteile. Man sollte allerdings diese Vorteile kennen und auch speziel darauf eingehen. Das Array-Beispiel dagegen kann nahezu beliebig groß und vor allem dicht besiedelt sein, es wird nicht langsamer, als nur mehr Speicher für die Map drauf geht. Der Speichergebrauch ist bei einem Type aber auch nicht viel weniger.

Grundsätzlich würde ich auch jeden Schritt genau erklären. Ein so fertiger Code hätte sonst auch genauso gut ins Codearchiv kopiert werden können. Sachen wie ''Eigentlich sollte man Abfragen ob das Objekt im view ist!!!'' machen es nicht gerade besser. Dieses ist ein wichtiger Schritt und sollte auf jeden Fall drauf eingegangen werden.
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D
 

Soul Reaver

BeitragMo, Feb 16, 2009 11:58
Antworten mit Zitat
Benutzer-Profile anzeigen
EDIT: Quote entfernt. MfG BladeRunner
Ich muss gestehen, dass ich es in der Engine, an der ich gerade arbeite, mit Arrays regle, aber ich habe hier Types verwendet, da es so meiner Meinung einfacher geht und das Tutorial für Anfänger ist.
Ich werde das Tutorial noch verbessern, wenn ich Zeit habe.
Danke für deine Antwort Wink
 

Sliver

BeitragMo, Feb 16, 2009 14:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Types und Anfänger... ist ne böse Kombination!
Wenn man anfängt, sollte man lieber erstmal mit Arrays experimentieren, bevor man mit Types jongliert. Wink

Edit:

hectic's Code ist um Welten besser!
  • Zuletzt bearbeitet von Sliver am Mo, Feb 16, 2009 14:09, insgesamt einmal bearbeitet

BladeRunner

Moderator

BeitragMo, Feb 16, 2009 14:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Bitte zitiert doch nicht immer ganze Beiträge die direkt über eurer Antwort stehen. Das ist einfach nur störend.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Firstdeathmaker

BeitragMo, Feb 16, 2009 16:59
Antworten mit Zitat
Benutzer-Profile anzeigen
Hmm, ich würde mal sagen beides sind spezielle Lösungen zu speziellen Problemen. Was ist z.B. wenn man ein Space-Game mit sehr großen Ausmaßen hat (mapsize=100.000 x 100.000 px)? Und sich die Raumschiffe und Objekte nicht auf Tiles bewegen? Dann wäre vllt. das erste besser. Allerdings fällt dann wieder die langwierige Prüfung auf Sichtbarkeit auf. Die Lösung: Kombiniert doch einfach die Tilemap mit der andern Methode (wird für massenhafte Kollision sowieso nötig):


Eine sehr großtilige Map (tiles von vllt. 200x200 pixel) in denen jeweils eine liste existiert in welche sich objekte, die sich dort befinden, reinhängen. Bei einzeichnen der Cam (=View) muss man nicht mehr alle Objekte überprüfen, sondern zeichnet einfach alle ein, die sich auf den gerade für die Kamera sichtbaren tiles befinden. Man muss allerdings beim einzeichnen darauf achten, nicht einfach hintereinander alle listen einzuzeichnen, sondern die Listen zusammen zu legen und zu sortieren.

Ebenso kann man dann auch die Kollisionsprüfung nur über Objekte laufen lassen, welche sich im eigenen Tile befinden.
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon
Gewinner des BCC #57 User posted image

Neue Antwort erstellen


Übersicht BlitzBasic FAQ und Tutorials

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group