Seite 2 von 3

Verfasst: 25.02.2008 14:46
von KeyKon
Meine Rede^^

Verfasst: 25.02.2008 14:51
von Emily
Stimmt, ist mir aus deinen Erläuterungen nicht ganz aufgegangen.

Verfasst: 25.02.2008 15:22
von #NULL
ich hab mal versucht aus nem game von mir das scrolling halbwegs zu isolieren:

Code: Alles auswählen

InitSprite()
InitKeyboard()
ww=400
wh=300
hWin=OpenWindow(0, 50,100,ww,wh, "")
OpenWindowedScreen( hWin, 0,0,ww,wh, 0,0,0)

#scollborder = 70
#scrollspeed = 0.06

; screen area, where the map is displayed (scolling will stop at these borders)
mapwin.RECT
mapwin\left  =40
mapwin\top   =40
mapwin\right =ww-40
mapwin\bottom=wh-40

; player pixel position
youX.l = ww/2
youY.l = wh/2

; map offset
offXf.f ;(for calculation)
offYf.f
offX.l  ;(for further use)
offY.l

xmax= 60
ymax= 60
Dim map.l(xmax,ymax)
For i=0 To xmax
  For k=0 To ymax
    map(i,k) = Random(1)
  Next
Next


Repeat
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Right) :: youX+4  ::  If youX>=(xmax+1)*16 : youX=(xmax+1)*16-1 : EndIf :: EndIf
  If KeyboardPushed(#PB_Key_Left ) :: youX-4  ::  If youX<0            : youX=0             : EndIf :: EndIf
  If KeyboardPushed(#PB_Key_Up   ) :: youY-4  ::  If youY<0            : youY=0             : EndIf :: EndIf
  If KeyboardPushed(#PB_Key_Down ) :: youY+4  ::  If youY>=(ymax+1)*16 : youY=(ymax+1)*16-1 : EndIf :: EndIf
  youMapI=((youX)/16)
  youMapK=((youY)/16)
  
  ;{ scrolling
  If offXf+youX > (mapwin\right-#scollborder)
    offXf- #scrollspeed*( (offXf+youX) - (mapwin\right-#scollborder) )
    If offXf < - (((xmax+1)*16)-mapwin\right)
      offXf= -(((xmax+1)*16)-mapwin\right)
    EndIf
  ElseIf offXf+youX < (mapwin\left+#scollborder-16)
    offXf+ #scrollspeed*( (mapwin\left+#scollborder-16) - (offXf+youX) )
    If offXf>mapwin\left
      offXf=mapwin\left
    EndIf
  EndIf
  If offYf+youY > (mapwin\bottom-#scollborder)
    offYf- #scrollspeed*( (offYf+youY) - (mapwin\bottom-#scollborder) )
    If offYf < - (((ymax+1)*16)-(mapwin\bottom))
      offYf= -(((ymax+1)*16)-(mapwin\bottom))
    EndIf
  ElseIf offYf+youY < (mapwin\top+#scollborder)
    offYf+ #scrollspeed*( (mapwin\top+#scollborder) - (offYf+youY) )
    If offYf>mapwin\top
      offYf=mapwin\top
    EndIf
  EndIf
  offX=offXf 
  offY=offYf
  ;}
  ; end scrolling
  
  
  StartDrawing(ScreenOutput())
    DrawingMode(#PB_2DDrawing_Outlined)
    For i=0 To xmax
      For k=0 To ymax
        If map(i,k)
          Box(offX+16*i +1,offY+16*k +1, 14,14,$ff2222)
        EndIf
      Next
    Next
    
    DrawingMode(#PB_2DDrawing_Default)
    Box(offX+youMapI*16 ,offY+youMapK*16 , 15,15, $ff2222)
    
    DrawingMode(#PB_2DDrawing_Outlined)
    Circle(offX+youX,offY+youY,2,$88ff88)
    
    ;DrawingMode(#PB_2DDrawing_Outlined)
    Box(offX,offY,(xmax+1)*16,(ymax+1)*16,$00ff00)
    Box(mapwin\left+#scollborder, mapwin\top+#scollborder, (mapwin\right-mapwin\left)-2*#scollborder, (mapwin\bottom-mapwin\top)-2*#scollborder, $666666)
  StopDrawing()
  
  FlipBuffers()
  ClearScreen($333333)
  Delay(3)
Until KeyboardPushed(#PB_Key_Escape) Or WindowEvent()=#PB_Event_CloseWindow

..falls es zu wirr ist, kann ich auch noch was dazu brabbeln 8) .
mapwin\.. ist auch nicht unbedingt nötig.

Verfasst: 27.02.2008 17:56
von Rubiko
@#NULL

Ist das nicht eher für Jump 'n' Runs?
Andere Frage an dich, hab mich mal ein bisschen mehr zum Thema
Kollision schlau gemacht und dabei folgenden Code von dir gefunden
(http://www.purebasic.fr/german/viewtopic.php?t=15363):

Code: Alles auswählen

;
;       Test-Animation
;   mit Umgebungs-Kollision
;
;*****************************
;** Konstanten
;*****************************
#ResX                   = 800
#ResY                   = 600
#BPP                    = 32
#TileSize               = 32
#playerWidth            = 27
#playerHeight           = 41

;*****************************
;** Define variablen
;*****************************
Global playerX.l    = 400 ;- #playerWidth/2
Global playerY.l    = 300 ;- #playerHeight/2
Global AnimFrame.l  = 111
Global counter.l    = 0
Global MapX.l       = 0
Global MapY.l       = 0
Global uPath.s
Global FineX.l
Global FineY.l

Global frametimer.l = 0
Global framedelay.l = 60

;*****************************
;** Enumuration
;*****************************
Enumeration
  #Test00     = 0
  #Test01 
  #Test02 
  #Test03 
  #Test04 
  #Test05 
  #Test06 
  #Test07 
  #Test08 
  #Test09 
  #Test10 
  #Test11 
  #Maus   = 500
  EndEnumeration
 
  Enumeration
  #Test12     = 12
  #Test13
  #Test14
EndEnumeration
;*****************************
;** Daten Laden
;*****************************
UsePNGImageDecoder()

;*****************************
;** Struktur & Arrays
;*****************************
Structure _Object
  TileID.b
  objID.b
  objWalk.b
  objAction.b
  objSound.b
EndStructure




;*****************************
;** Proceduren
;*****************************
Procedure check(value.l, text.s)
   If Value = 0
      MessageRequester("error", text, 0)
      End
   EndIf
EndProcedure

Procedure Init()
  check(InitSound(),    "InitSound() failed")
  check(InitKeyboard(), "InitKeyboard() failed")
  check(InitMouse(),    "InitMouse() failed")
  check(InitSprite(),   "InitSprite() failed")
  SetRefreshRate(60)
  win1Nr.l = OpenScreen(#ResX, #ResY, #BPP, "")
  check( win1Nr, "OpenScreen() failed")
EndProcedure

Procedure initmap()
      Global mapWidth.l 
      Global mapHeight.l   
      Global Dim map._Object(mapWidth, mapHeight)     
EndProcedure

Procedure ShowLand(x.l, y.l)
  Static grid.l = 0
  If grid = 0
    grid = CreateSprite(#PB_Any,32,32)
    StartDrawing(SpriteOutput(grid))
      DrawingMode(#PB_2DDrawing_Outlined)
      Box(0,0,#TileSize,#TileSize,$444444)
    StopDrawing()
  EndIf
 
  Protected t.l, n.l, k.l, i.l
    ;
    ; Zeigt den Mapauschnitt an
    ;
    For t=0 To mapHeight
        For n=0 To mapWidth
        DisplaySprite(map(n,t)\TileID, (mapX + #TileSize*n),(mapY + #TileSize*t) )
        If map(n,t)\objID > 0
          DisplayTransparentSprite(map(n,t)\objID, 8+(mapX + #TileSize*n),8+(mapY + #TileSize*t) )
        EndIf
       
        DisplayTransparentSprite(grid, (mapX + #TileSize*n),(mapY + #TileSize*t) )
;         StartDrawing(ScreenOutput())
;           DrawingMode(#PB_2DDrawing_Transparent)
;           DrawText( (#TileSize * n) - FineX, (#TileSize * t) - FineY, Str(map(MapX+n,MapY+t)\TileID) +","+ Str(map(MapX+n,MapY+t)\ObjID) +","+ Str(map(MapX+n,MapY+t)\ObjWalk) )
;         StopDrawing()
      Next
    Next   
EndProcedure

Procedure displayAnimation(startAnim.b, stopAnim.b)
  While ElapsedMilliseconds() - frametimer > framedelay
    frametimer = ElapsedMilliseconds()
    AnimFrame + 1
    If AnimFrame > stopAnim
      AnimFrame = startAnim
    EndIf 
  Wend
EndProcedure


Procedure isAccessible(x.l, y.l)
  Static i.l, k.l
  i = ((playerX-mapX+x)/#TileSize)
  k = ((playerY-mapY+y)/#TileSize)
  If i>=0  And  i<=mapWidth  And k>=0  And  k<=mapHeight  And  map(i,k)\TileID < 10
    ProcedureReturn 1
  EndIf
  ProcedureReturn 0
EndProcedure

Procedure Steuerung()
  Static speed.l = 2
 
 
  If KeyboardPushed(#PB_Key_Left) ;{
    If AnimFrame > 114 And AnimFrame <= 118
      If isAccessible(-speed-8,-6) And isAccessible(-speed+8,-6) And isAccessible(-speed-8,4) And isAccessible(-speed+8,4)
        mapX+speed
      EndIf
      displayAnimation(115, 118)
    Else
      AnimFrame = 115
    EndIf    ;}
  EndIf
 
  If KeyboardPushed(#PB_Key_Right) ;{
    If AnimFrame > 118 And AnimFrame <= 122
      If isAccessible( speed-8,-6) And isAccessible( speed+8,-6) And isAccessible( speed-8,4) And isAccessible( speed+8,4)
        mapX-speed
      EndIf
      displayAnimation(119, 122)
    Else
      AnimFrame = 119
    EndIf ;}
  EndIf   
 
  If KeyboardPushed(#PB_Key_Up) ;{
    If AnimFrame > 122 And AnimFrame <= 126   
      If isAccessible(-8,-speed-6) And isAccessible(8,-speed-6) And isAccessible(-8,-speed+4) And isAccessible(8,-speed+4)
        mapY+speed
      EndIf
      displayAnimation(123, 126)
    Else
      AnimFrame = 123
    EndIf ;}
  EndIf   
     
  If KeyboardPushed(#PB_Key_Down) ;{
    If AnimFrame > 110 And AnimFrame <= 114
      If isAccessible(-8, speed-6) And isAccessible(8, speed-6) And isAccessible(-8, speed+4) And isAccessible(8, speed+4)
        mapY-speed
      EndIf
      displayAnimation(111, 114)
    Else
      AnimFrame = 111
    EndIf   ;}
  EndIf
 
  If KeyboardPushed(#PB_Key_LeftControl)
  ; #PB_Key_LeftControl
  EndIf
 
   
  If KeyboardPushed(#PB_Key_Escape)
    End ;ProgrammAbbruch
  EndIf 

EndProcedure

Procedure.l mapLoad(mapName.s)
  Protected t.l, n.l
  ;
  ; Level Laden
  ;
  If OpenFile(0,mapName+".map")
    mapWidth = ReadLong(0)
    mapHeight = ReadLong(0)
    objAnzahl = ReadLong(0)
    initmap()
    For t = 0 To mapHeight
      For n = 0 To mapWidth
        map(n,t)\tileID = ReadLong(0)
       
        If Random(10) ::: map(n,t)\tileID = 1
        Else          ::: map(n,t)\tileID = 11
        EndIf
       
        map(n,t)\objID = ReadLong(0)
        map(n,t)\objWalk = ReadLong(0)
      Next
    Next
    CloseFile(0)
  EndIf
EndProcedure





;*****************************
;** Sprites Laden
;*****************************
Init()


For i = 111 To 126
  LoadSprite(i, ".\Grafik\" + Str(i) + ".png")
  TransparentSpriteColor(i, RGB(0,255,255)) 
Next


uPath = GetCurrentDirectory()
LoadSprite(#Test00,  uPath+"Grafik\000.png") ;{
LoadSprite(#Test01,  uPath+"Grafik\001.png")
LoadSprite(#Test02,  uPath+"Grafik\002.png")
LoadSprite(#Test03,  uPath+"Grafik\003.png")
LoadSprite(#Test04,  uPath+"Grafik\004.png")
LoadSprite(#Test05,  uPath+"Grafik\005.png")
LoadSprite(#Test06,  uPath+"Grafik\006.png")
LoadSprite(#Test07,  uPath+"Grafik\007.png")
LoadSprite(#Test08,  uPath+"Grafik\008.png")
LoadSprite(#Test09,  uPath+"Grafik\009.png")
LoadSprite(#Test10,  uPath+"Grafik\010.png")
LoadSprite(#Test11,  uPath+"Grafik\011.png")

LoadSprite(#Test12,  upath+"Grafik\Hag.png")
LoadSprite(#Test13,  upath+"Grafik\Hag2.png")
LoadSprite(#Test14,  upath+"Grafik\Schild.png")

TransparentSpriteColor(#Test12, RGB(255,103,139))
TransparentSpriteColor(#Test13, RGB(255,103,139)) ;}
TransparentSpriteColor(#Test14, RGB(255,103,139))
;*****************************
;** Loop
;*****************************

mapload("oli10")


Repeat
  ClearScreen(0)
  ExamineKeyboard()
  Steuerung()
  ShowLand(0,0)   
 
  DisplayTransparentSprite(AnimFrame,playerX-#playerWidth/2, playerY-#playerHeight+5)
  StartDrawing(ScreenOutput())
    Circle(playerX   , playerY   , 2,$ffffff)
    Circle(playerX-8, playerY-6, 2,$0000ff)
    Circle(playerX+8, playerY-6, 2,$0000ff)
    Circle(playerX-8, playerY+4, 2,$0000ff)
    Circle(playerX+8, playerY+4, 2,$0000ff)
  StopDrawing()
 
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)

End
Du machst das doch genau so wie Kaeru Gaman, oder?
Zumindest konnte ich das so rauslesen... eben die
Kollisionspunkte an der Grafik überprüfen, aber wie
genau regelst du das mit dem Array? Wenn ich nämlich
anfange die Spielerkoordinaten für die Kollision durch
32 zuteilen, um dann im Map Array zu überprüfen ob
sich an den Kollisionspunkten ein nicht-passierbares Tile
befindet, krieg ich nur Fehlermeldungen, was wohl daran
liegt, dass so etwas wie 556 / 32 nicht aufgeht, und man
im Array keine Floats verwenden kann...

Da der Uploaded.to Link des Users im Thread nicht mehr
geht, kann ich das leider nicht genauer testen :/

Frage richtet sich natürlich auch an andere...
Wie kann ich überprüfen, ob an den Eckpunkten eine Kollision
stattfindet, wenn (in diesem Fall) bei (PlayerX+MapX)/32
ungerade Zahlen rauskommen? Lassen sich ja nicht im Array
benutzen

Verfasst: 27.02.2008 19:08
von Kaeru Gaman
Wie kann ich überprüfen, ob an den Eckpunkten eine Kollision
stattfindet, wenn (in diesem Fall) bei (PlayerX+MapX)/32
ungerade Zahlen rauskommen? Lassen sich ja nicht im Array
benutzen
nicht "ungerade"....
Wenn ich nämlich
anfange die Spielerkoordinaten für die Kollision durch
32 zuteilen, um dann im Map Array zu überprüfen ob
sich an den Kollisionspunkten ein nicht-passierbares Tile
befindet, krieg ich nur Fehlermeldungen, was wohl daran
liegt, dass so etwas wie 556 / 32 nicht aufgeht, und man
im Array keine Floats verwenden kann...
dann verwende keine floats :roll:

du brauchst und willst die nachkommastellen doch auch garnicht.
du willst wissen, auf der wievielten tile sich etwas befindet.
Int( 556 / 32 ) = 17 => also auf der 17ten tile.

PlayerX ist integer, MapX ist integer;
das ergebnis von (PlayerX+MapX)/32 ist integer weil du es als index für ein array verwenden willst.

wenn du ungenauigkeiten reinbekommst, das deine spielfigur zu früh reagiert (oder zu spät)
dann musst du halt noch ein offset einbaun, damit regulierst du pixelweise,
wann rechnerisch das nächste tile betrachtet wird.

Code: Alles auswählen

TestX = ( PlayerX + MapX + OffsetX ) / 32
TestY = ( PlayerY + MapY + OffsetY ) / 32
TestTile = TileMap( TestX, TestY )

Verfasst: 27.02.2008 19:30
von Rubiko
Wupps, meinte natürlich nicht ungerade...
Aber jetzt geht mir wirklich ein Licht auf... irgendwie meinte ich,
dass bei Verwendung von Floats (die zwangsweise rauskommen)
keine pixelgenaue Kollision mehr stattfinden kann,
jedenfalls vielen Dank ;)

*peinlich* :roll:

Verfasst: 27.02.2008 19:33
von Kaeru Gaman
> dass bei Verwendung von Floats (die zwangsweise rauskommen)

da kommen nicht zwangsweise floats raus!

weise das ergebnis einer Long zu, und alles ist wölkchen. ;)

Verfasst: 27.02.2008 21:45
von Rubiko
Habs jetzt so gemacht, wie du gesagt hast, d.h.
den Wert einer Long-Variable zugeordnet.
Klappt erstmal super, der Array-Fehler ist behoben.

Aber ein neues Problem hat es mit sich gebracht:
bei 575 / 32 kommt z.B.
17,96875 raus, die Variable geht aber immer
noch vom 17. Tile aus, bei 576 kommt das erste
mal 18 raus und ab hier geht er (logischerweise)
dann auch vom 18. aus, übrigens auch, wenn ich
deine 'Routinen' kopiere.
TestX und TestY gehen dabei natürlich auch nur
alle 32 Pixel 1 höher... 'ne Idee wie man da
Abhilfe schaffen könnte?

Code ist im Grunde der selbe

Vielen Dank im Voraus ;)
Rubiko

Verfasst: 28.02.2008 06:33
von Kaeru Gaman
das ist das, was ich mit dem Offset meinte....

wenn du ab 17.5 eine 18 haben willst, dann mach dein offset halb so groß wie die tilebreite, also hier 16.

letztendlich hängt das aber auch mit der breite des objekts zusammen,
weil ja die objektkoordinaten nicht in der mitte sondern an der linken oberen ecke sitzen...
also in den meisten fällen wirst du wohl nicht 16 nehmen sondern vllt 8 oder 6...

Verfasst: 28.02.2008 15:05
von #NULL
@rubiko
ich weiß leider nicht genau ob ich dich richtig verstehe, aber hier noch ein paar sachen, die du vielleicht übersehen hast:
- die procedure isAccessible(x,y) rechnet die player-position auf der map in pixel noch selbst hinzu. parameter x/y sind also nur die koordinaten / punkte auf dem tile, unabhängig davon wo player sich gerade befindet.
- playerX ist die position auf dem screen. auf der map ist die pixel position 'playerX-mapX'. die player-position auf der map in indices berechnest du also immer genau wie es auch in isAccessible() für i und k gemacht wird.

ich hoffe die das stimmt so. war ja auch nicht mein code, hatte ihn nur bearbeitet.
>> Da der Uploaded.to Link des Users im Thread nicht mehr
>> geht, kann ich das leider nicht genauer testen :/
ich hab bei mir noch das zip gefunden. kann ich dir schicken oder hochladen wenn du willst :)