Raum bei 2D-spielen

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Benutzeravatar
#NULL
Beiträge: 2238
Registriert: 20.04.2006 09:50

Beitrag von #NULL »

hier nochmal ein cödchen.
ohne scrolling.

Code: Alles auswählen

EnableExplicit

Define w.l            = 12 ; -- kartengoesse
Define h.l            = 9  ; _/

Define playerIndexX.l      ; -- player position (array-index)
Define playerIndexy.l      ; _/

Define offX.l         = 60 ; -- offset der gesamten darstellung (pixel)
Define offY.l         = 40 ; _/

Define i.l,k.l

InitSprite()
InitKeyboard()
OpenScreen(1024,768,32,"fllscrn")

Enumeration
  #sprPlayer
  #sprDunkel
  #sprHell
EndEnumeration

CreateSprite(#sprPlayer,64,64)
  StartDrawing( SpriteOutput(#sprPlayer) )
    Circle(32,32,16,$ff0000)
  StopDrawing()
CreateSprite(#sprDunkel,64,64)
  StartDrawing( SpriteOutput(#sprDunkel) )
    Box(2,2,60,60,$aa3333)
  StopDrawing()
CreateSprite(#sprHell,64,64)
  StartDrawing( SpriteOutput(#sprHell) )
    Box(2,2,60,60,$aa6666)
  StopDrawing()

Dim map.l(w,h)
For i=0 To w
  For k=0 To h
    If Random(3)
      map(i,k)=#sprHell
      playerIndexX = i  ; -- nur damit der spieler auch wirklich auf einem hellen feld steht
      playerIndexy = k  ; _/
    Else
      map(i,k)=#sprDunkel
    EndIf
  Next
Next



Procedure ERLAUBT(indexX.l, indexY.l)
  Shared map(), w, h
  If indexX>=0 And indexY>=0 And indexX<=w And indexY<=h And map(indexX,indexY)=#sprHell
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure




Repeat
  ExamineKeyboard()
  StartDrawing( ScreenOutput() )
    ;DrawText(100,100, Str(MouseDeltaX())+", "+Str(MouseDeltaY()) )
    ;Circle(MouseX(),MouseY(),5,$770000)
  StopDrawing()
  
  If KeyboardPushed(#PB_Key_Right) And ERLAUBT(playerIndexX+1, playerIndexY)
    playerIndexX+1
  EndIf
  If KeyboardPushed(#PB_Key_Left) And ERLAUBT(playerIndexX-1, playerIndexY)
    playerIndexX-1
  EndIf
  If KeyboardPushed(#PB_Key_Up) And ERLAUBT(playerIndexX, playerIndexY-1)
    playerIndexY-1
  EndIf
  If KeyboardPushed(#PB_Key_Down) And ERLAUBT(playerIndexX, playerIndexY+1)
    playerIndexY+1
  EndIf
  
  For i=0 To w
    For k=0 To h
      DisplaySprite( map(i,k),  offX+ i*64,  offY + k*64)
    Next
  Next
  DisplayTransparentSprite(0,  offX + playerIndexX*64,  offY + playerIndexY*64)


  FlipBuffers()
  ClearScreen(0)
  Delay(50)
Until KeyboardReleased(#PB_Key_Escape) 
my pb stuff..
Bild..jedenfalls war das mal so.
Benutzeravatar
C4rizz
Beiträge: 223
Registriert: 01.05.2006 12:43
Computerausstattung: Desktop : Amd Athlon X2 3,2 ghz Black Edition. 4GB Corsair XMS DDR2, nVidia 460 gtx Sonic Extreme

Notebook : [Asus] i5 @ 2,9 ghz, 8GB Corsair DDR3, nVidia gt 540m

Internet : DSL - 16 Mbit | HSDPA - 7,2 Mbit
Wohnort: Celle

Beitrag von C4rizz »

Heureka
Tausend Dank genau das war gesucht :allright:
PB 3.94/4.10
Meine Hompage
Benutzeravatar
C4rizz
Beiträge: 223
Registriert: 01.05.2006 12:43
Computerausstattung: Desktop : Amd Athlon X2 3,2 ghz Black Edition. 4GB Corsair XMS DDR2, nVidia 460 gtx Sonic Extreme

Notebook : [Asus] i5 @ 2,9 ghz, 8GB Corsair DDR3, nVidia gt 540m

Internet : DSL - 16 Mbit | HSDPA - 7,2 Mbit
Wohnort: Celle

Beitrag von C4rizz »

Obwohl sich jetzt noch die Frage stellt ist es denn auch bei dem andern code möglich?
Ich mein der andere code bietet viel mehr flexiblität, denn ich kann den player stufenlos lenken , ausserdem bleibt er stehts im Mittelpunkt.
Also perfekt wäre es wenn ich auf dem ersten code eine Kollision hinbekommen würde, aber ich hab kein plan wie :(
Kannst mir da vileicht auchnoch helfen??
PB 3.94/4.10
Meine Hompage
Benutzeravatar
#NULL
Beiträge: 2238
Registriert: 20.04.2006 09:50

Beitrag von #NULL »

also stufenlos ging es mit dem anderen code genausowenig wie mit dem letzten.
aber wenn du den spieler immer im mittelpunkt haben willst (beim letzten code):
die offX/Y variablen sind ja schon drin. mit denen versetzt du einfach alles
zusätzlich, wenn sich der spieler bewegt:

Code: Alles auswählen

  If KeyboardPushed(#PB_Key_Right) And ERLAUBT(playerIndexX+1, playerIndexY)
    playerIndexX+1
    offX-64
  EndIf
der spieler kommt am anfang in die mitte auf ein begehbares feld:

Code: Alles auswählen

;player kommt in die mitte..
playerIndexX = w/2
playerIndexy = h/2
;..und das feld muss weiß sein
map(playerIndexX,playerIndexy) = #sprHell
dann noch die karte am anfang mittig setzten..

das sieht dann so aus:

Code: Alles auswählen

EnableExplicit

Define w.l            = 16 ; -- kartengoesse
Define h.l            = 12 ; _/

Define playerIndexX.l      ; -- player position (array-index)
Define playerIndexy.l      ; _/

Define screenWidth  = 1024
Define screenHeight = 768

Define offX.l = screenWidth /2 - 64*w/2  ; -- offset der gesamten darstellung (pixel)
Define offY.l = screenHeight/2 - 64*h/2  ; _/ ..hier so gesetz, dass die karte mittig ist

Define i.l,k.l

InitSprite()
InitKeyboard()
OpenScreen(screenWidth,screenHeight,32,"fllscrn")

Enumeration
  #sprPlayer
  #sprDunkel
  #sprHell
EndEnumeration

CreateSprite(#sprPlayer,64,64)
  StartDrawing( SpriteOutput(#sprPlayer) )
    Circle(32,32,16,$ff0000)
  StopDrawing()
CreateSprite(#sprDunkel,64,64)
  StartDrawing( SpriteOutput(#sprDunkel) )
    Box(2,2,60,60,$aa3333)
  StopDrawing()
CreateSprite(#sprHell,64,64)
  StartDrawing( SpriteOutput(#sprHell) )
    Box(2,2,60,60,$aa6666)
  StopDrawing()

Dim map.l(w,h)
For i=0 To w
  For k=0 To h
    If Random(3)
      map(i,k)=#sprHell
    Else
      map(i,k)=#sprDunkel
    EndIf
  Next
Next


;player kommt in die mitte..
playerIndexX = w/2
playerIndexy = h/2
;..und das feld muss weiß sein
map(playerIndexX,playerIndexy) = #sprHell




Procedure ERLAUBT(indexX.l, indexY.l)
  Shared map(), w, h
  If indexX>=0 And indexY>=0 And indexX<=w And indexY<=h And map(indexX,indexY)=#sprHell
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure



Repeat
  ExamineKeyboard()
  StartDrawing( ScreenOutput() )
    ;DrawText(100,100, Str(MouseDeltaX())+", "+Str(MouseDeltaY()) )
    ;Circle(MouseX(),MouseY(),5,$770000)
  StopDrawing()
 
  If KeyboardPushed(#PB_Key_Right) And ERLAUBT(playerIndexX+1, playerIndexY)
    playerIndexX+1
    offX-64
  EndIf
  If KeyboardPushed(#PB_Key_Left) And ERLAUBT(playerIndexX-1, playerIndexY)
    playerIndexX-1
    offX+64
  EndIf
  If KeyboardPushed(#PB_Key_Up) And ERLAUBT(playerIndexX, playerIndexY-1)
    playerIndexY-1
    offY+64
  EndIf
  If KeyboardPushed(#PB_Key_Down) And ERLAUBT(playerIndexX, playerIndexY+1)
    playerIndexY+1
    offY-64
  EndIf
 
  For i=0 To w
    For k=0 To h
      DisplaySprite( map(i,k),  offX+ i*64,  offY + k*64)
    Next
  Next
  DisplayTransparentSprite(0,  offX + playerIndexX*64,  offY + playerIndexY*64)


  FlipBuffers()
  ClearScreen(0)
  Delay(50)
Until KeyboardReleased(#PB_Key_Escape)
my pb stuff..
Bild..jedenfalls war das mal so.
Benutzeravatar
C4rizz
Beiträge: 223
Registriert: 01.05.2006 12:43
Computerausstattung: Desktop : Amd Athlon X2 3,2 ghz Black Edition. 4GB Corsair XMS DDR2, nVidia 460 gtx Sonic Extreme

Notebook : [Asus] i5 @ 2,9 ghz, 8GB Corsair DDR3, nVidia gt 540m

Internet : DSL - 16 Mbit | HSDPA - 7,2 Mbit
Wohnort: Celle

Beitrag von C4rizz »

Ok alles klärchen Danke
PB 3.94/4.10
Meine Hompage
Benutzeravatar
ZeHa
Beiträge: 4760
Registriert: 15.09.2004 23:57
Wohnort: Friedrichshafen
Kontaktdaten:

Beitrag von ZeHa »

Meiner Meinung nach sollte der Code immer so aufgebaut sein:

- Eine Map, die aus Tiles besteht, in Form eines Arrays
- Jedes Objekt hat absolute X/Y-Koordinaten, die sich immer auf die tatsächliche Position beziehen, und nicht auf den Mittelpunkt des Bildschirms oder so etwas
- Es gibt eine "Kamera", die ebenfalls ein X und ein Y hat, das wäre im obigen Beispiel das "Offset"
- Die Kamera wird an ein Objekt gebunden, z.B. an den Spieler, sprich, nach jedem Update werden die Kamera-Koordinaten erstmal vom Spieler übernommen
- Vor demRendern wird von der Kameraposition noch entsprechend die Hälfte der Bildschirmbreite und die Hälfte der Bildschirmhöhe abgezogen
- Danach wird allerdings geprüft, ob die Kamera sich noch so auf der Karte befindet, daß der Bildschirm noch vollständig gefüllt ist. Wenn nicht, werden die Kamera-Koordinaten entsprechend korrigiert
- Nun wird alles gerendert, indem bei jedem Objekt, das auf den Schirm kommt, sei es ein Tile oder ein bewegliches Objekt, die Kamera-Koordinaten abgezogen werden

Mit dieser Vorgehensweise hat man a) den Vorteil, daß man die Kamera auch an andere Objekte binden kann, je nachdem, was man halt vorhat, und b) scrollt die Karte nur so lange, bis man am Rand ankommt. Wenn man sich also Richtung Rand bewegt, wird die Spielfigur letztendlich doch nicht mehr in der Mitte des Bildes angezeigt, sondern die Karte hört auf zu scrollen und die Figur läuft einfach noch bis an den Rand. Und das funktioniert dann auch problemlos bei jeder Map-Größe und bei jeder Bildschirm-Auflösung.
Bild     Bild

ZeHa hat bisher kein Danke erhalten.
Klicke hier, wenn Du wissen möchtest, woran ihm das vorbeigeht.
Antworten