-Der Code könnte sicherlich schöner/besser geschrieben werden (wollte bloß nicht zu viel Zeit investieren)
-Es ist auch mit Sicherheit nicht der beste Lösungsansatz...
-Da tauchen immer wieder "+1" und "-1" in den Berechnungen auf. Die sind nicht zum Spaß da, sondern sollen den Umstand ausgleichen,
das man ein Objekt mit gerader Pixelbreite schlecht durch den idealen Mittelpunkt beschreiben kann, sondern immer 0.5 Pixel links oder
rechts davon liegt. Bsp: OOOOXOOOOO (= 10 Pixel)
Warum ich das so genau genommen habe? Weil bei mir der Spieler genauso groß ist, wie ein Tile und es demzufolge ständig zu
ungewollten Kollisionen kommen würde.
-Nicht wundern, dass da bei den Abfragen auf Kollision scheinbar die gleichen Schrittfolgen zweimal hintereinander auftauchen.
Das liegt daran, dass ich immer BEIDE relevanten Körperecken auf Kollision überprüfe. (Wenn z.B. beim nach links Bewegen die untere
-Ich habe aus Zeitgründen auf Kommentare verzichtet - aber versucht, selbsterklärende Namen zu verwenden; wenn was unklar ist:
Code: Alles auswählen
InitSprite()
InitKeyboard()
Global max_x = 19
Global max_y = 19
Structure struc_tile_info
breite.l
hoehe.l
*sprite
EndStructure
Global tile_info.struc_tile_info
Restore tile_info
Read.l tile_info\breite
Read.l tile_info\hoehe
Global Dim welt(max_x,max_y)
Restore welt
For y = 0 To max_y
For x = 0 To max_x
Read.b welt(x,y)
Next
Next
Global hindernis.POINT
Structure struc_spieler
x.l
y.l
*sprite
breite.l
hoehe.l
fallgeschwindigkeit.f
EndStructure
Global spieler.struc_spieler
Restore spieler_pos
Read.l spieler\x
Read.l spieler\y
Restore spieler_dim
Read.l spieler\breite
Read.l spieler\hoehe
OpenWindow(0,0,100,800,600,"")
OpenWindowedScreen(WindowID(0),0,0,800,600,-1,0,0)
spieler\sprite = CreateSprite(#PB_Any,spieler\breite,spieler\hoehe)
StartDrawing(SpriteOutput(spieler\sprite))
FillArea(1,1,-1,RGB(186, 5, 5))
StopDrawing()
tile_info\sprite = CreateSprite(#PB_Any,tile_info\breite,tile_info\hoehe)
StartDrawing(SpriteOutput(tile_info\sprite))
FillArea(1,1,-1,RGB(33, 182, 12))
StopDrawing()
Procedure Display_welt()
For y = 0 To max_y
For x = 0 To max_x
If welt(x,y)
DisplaySprite(tile_info\sprite,x * tile_info\breite,y * tile_info\hoehe)
EndIf
Next
Next
EndProcedure
Procedure display_spieler()
DisplaySprite(spieler\sprite,spieler\x-spieler\breite/2+1,spieler\y-spieler\hoehe/2+1)
EndProcedure
Procedure teste_horizontale_strecke_auf_naechstes_hindernis(x1,x2,y)
startblock.POINT\x = x1/tile_info\breite
startblock\y = y/tile_info\hoehe
endblock.POINT\x = x2/tile_info\breite
hindernis.POINT\x = -1
If startblock\x < endblock\x
For x = startblock\x To endblock\x
If welt(x,startblock\y)
hindernis\x = x
hindernis\y = startblock\y
Break
EndIf
Next
Else
For x = startblock\x To endblock\x Step -1
If welt(x,startblock\y)
hindernis\x = x
hindernis\y = startblock\y
Break
EndIf
Next
EndIf
ProcedureReturn hindernis
EndProcedure
Procedure teste_vertikale_strecke_auf_naechstes_hindernis(x,y1,y2)
startblock.POINT\x = x/tile_info\breite
startblock\y = y1/tile_info\hoehe
endblock.POINT\y = y2/tile_info\hoehe
hindernis.POINT\x = -1
If startblock\y < endblock\y
For y = startblock\y To endblock\y
If welt(startblock\x,y)
hindernis\x = startblock\x
hindernis\y = y
Break
EndIf
Next
Else
For y = startblock\y To endblock\y Step -1
If welt(startblock\x,y)
hindernis\x = startblock\x
hindernis\y = y
Break
EndIf
Next
EndIf
ProcedureReturn hindernis
EndProcedure
Procedure steht_spieler_auf_boden()
If welt((spieler\x-spieler\breite/2+1)/tile_info\breite,(spieler\y+spieler\hoehe/2+1)/tile_info\hoehe) Or welt((spieler\x+spieler\breite/2)/tile_info\breite,(spieler\y+spieler\hoehe/2+1)/tile_info\hoehe)
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
Procedure Gravitation_spieler()
If Not steht_spieler_auf_boden() Or spieler\fallgeschwindigkeit < 0
spieler\fallgeschwindigkeit + 0.4
koerpery = spieler\hoehe/2
If Sign(spieler\fallgeschwindigkeit) < 0
koerpery * -1 + 1
EndIf
teste_vertikale_strecke_auf_naechstes_hindernis(spieler\x-spieler\breite/2+1,spieler\y+koerpery,spieler\y+koerpery+spieler\fallgeschwindigkeit)
If hindernis\x = -1
If spieler\fallgeschwindigkeit <> 0
teste_vertikale_strecke_auf_naechstes_hindernis(spieler\x+spieler\breite/2,spieler\y+koerpery,spieler\y+koerpery+spieler\fallgeschwindigkeit)
If hindernis\x = -1
spieler\y + spieler\fallgeschwindigkeit
ElseIf spieler\fallgeschwindigkeit < 0
If spieler\y-spieler\hoehe/2 +1> hindernis\y*tile_info\hoehe
spieler\y = hindernis\y * tile_info\hoehe + tile_info\hoehe + spieler\hoehe/2
EndIf
spieler\fallgeschwindigkeit = 0
Else
If spieler\y+spieler\hoehe/2 < hindernis\y*tile_info\hoehe
spieler\y = hindernis\y * tile_info\hoehe - spieler\hoehe/2 -1
EndIf
spieler\fallgeschwindigkeit = 0
EndIf
EndIf
ElseIf spieler\fallgeschwindigkeit < 0
If spieler\y-spieler\hoehe/2 +1> hindernis\y*tile_info\hoehe
spieler\y = hindernis\y * tile_info\hoehe + tile_info\hoehe + spieler\hoehe/2
EndIf
spieler\fallgeschwindigkeit = 0
Else
If spieler\y+spieler\hoehe/2 < hindernis\y*tile_info\hoehe
spieler\y = hindernis\y * tile_info\hoehe - spieler\hoehe/2 -1
EndIf
spieler\fallgeschwindigkeit = 0
EndIf
EndIf
EndProcedure
Procedure Bewege_spieler()
If steht_spieler_auf_boden() And KeyboardPushed(#PB_Key_W)
spieler\fallgeschwindigkeit = -10
EndIf
If KeyboardPushed(#PB_Key_A)
schrittweite = 3
teste_horizontale_strecke_auf_naechstes_hindernis(spieler\x-spieler\breite/2+1,spieler\x-spieler\breite/2-schrittweite+1,spieler\y-spieler\hoehe/2+1)
If hindernis\x = -1
teste_horizontale_strecke_auf_naechstes_hindernis(spieler\x-spieler\breite/2+1,spieler\x-spieler\breite/2-schrittweite+1,spieler\y+spieler\hoehe/2)
If hindernis\x = -1
spieler\x - schrittweite
ElseIf spieler\x-spieler\breite/2 > hindernis\x*tile_info\breite
spieler\x = hindernis\x*tile_info\breite+tile_info\breite + spieler\breite/2 -1
EndIf
ElseIf spieler\x-spieler\breite/2 > hindernis\x*tile_info\breite
spieler\x = hindernis\x*tile_info\breite+tile_info\breite + spieler\breite/2 -1
EndIf
ElseIf KeyboardPushed(#PB_Key_D)
schrittweite = 3
teste_horizontale_strecke_auf_naechstes_hindernis(spieler\x+spieler\breite/2,spieler\x+spieler\breite/2+schrittweite,spieler\y-spieler\hoehe/2+1)
If hindernis\x = -1
teste_horizontale_strecke_auf_naechstes_hindernis(spieler\x+spieler\breite/2,spieler\x+spieler\breite/2+schrittweite,spieler\y+spieler\hoehe/2)
If hindernis\x = -1
spieler\x + schrittweite
ElseIf spieler\x+spieler\breite/2 < hindernis\x*tile_info\breite + tile_info\breite
spieler\x = hindernis\x*tile_info\breite - spieler\breite/2 -1
EndIf
ElseIf spieler\x-spieler\breite/2 < hindernis\x*tile_info\breite + tile_info\breite
spieler\x = hindernis\x*tile_info\breite - spieler\breite/2 -1
EndIf
EndIf
EndProcedure
Repeat
WindowEvent()
ClearScreen(0)
Display_welt()
display_spieler()
FlipBuffers()
Gravitation_spieler()
ExamineKeyboard()
Bewege_spieler()
Until KeyboardPushed(1)
DataSection
welt:
Data.b 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data.b 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data.b 1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1
Data.b 1,0,0,0,1,1,1,1,1,1,0,0,0,0,0,1,0,0,1,1
Data.b 1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,1,1
Data.b 1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1
Data.b 1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,1,1,1
Data.b 1,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,1,1
Data.b 1,0,0,0,0,0,1,1,1,1,1,1,0,0,1,0,1,1,1,1
Data.b 1,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1
Data.b 1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,0,1
Data.b 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data.b 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1
Data.b 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1
Data.b 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1
Data.b 1,1,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1
Data.b 1,1,1,0,1,1,1,1,1,0,0,1,1,0,0,0,1,1,1,1
Data.b 1,1,1,0,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1
Data.b 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1
Data.b 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
spieler_pos:
Data.l 64,64
spieler_dim:
Data.l 20,20
tile_info:
Data.l 20,20
EndDataSection
Hoffe, das war jetzt nicht zu viel Code. Wenn doch, dann lad ich das als Datei hoch.
[EDIT: das mit dem Speichertyp gefixt; Fehler ausgebessert, um problemlos mit den Daten der Datasection rumspielen zu können]