Raycasting

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
AndyX
Beiträge: 1272
Registriert: 17.12.2004 20:10
Wohnort: Niederösterreich
Kontaktdaten:

Raycasting

Beitrag von AndyX »

Hab den C++-Source aus diesem Tutorial nach PB übersetzt. Für alle die so Dinge mögen ^_^ hat sicherlich noch Platz für Optimierungen, aber er funktioniert auf jeden Fall.

Code: Alles auswählen

;eine kleine Raycasting Engine (Flat shaded)
;Controls: Pfeiltasten (gehen/drehen)
;  A,D: strafen

#mapWidth = 24
#mapHeight = 24

Global Dim worldMap.l(#mapWidth,#mapHeight)
For j = 0 To 24
  For i = 0 To 24
    If j = 0 Or j = 24 Or i = 0 Or i = 24
      worldMap(i,j) = 1
    EndIf
    If i = 12 And j = 12
      worldMap(i,j) = 2
    EndIf
  Next i
Next j

posX.f = 22
posY.f = 12
dirX.f = -1
dirY.f = 0
planeX.f = 0
planeY.f = 0.66
time = 0
oldTime = 0

InitKeyboard()
InitSprite()
OpenScreen(512,384,32,"3D")

Repeat
  Delay(0)
  ClearScreen(0)
  StartDrawing(ScreenOutput())
  Box(0,0,512,192,RGB(90,150,220))
  Box(0,192,512,192,RGB(160,160,160))
  For x = 0 To 512
    cameraX.f = 2 * x / 512 - 1
    rayPosX.f = posX
    rayPosY.f = posY
    rayDirX.f = dirX + planeX * cameraX
    rayDirY.f = dirY + planeY * cameraX
    mapx = Int(rayPosX)
    mapy = Int(rayPosY)
    sideDistX.f
    sideDistY.f
    deltaDistX.f = Sqr(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
    deltaDistY.f = Sqr(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
    perpWallDist.f
    stepX.l
    stepY.l
    hit.l = 0
    side.l
    If rayDirX < 0
      stepX = -1
      sideDistX = (rayPosX - mapx) * deltaDistX
    Else
      stepX = 1
      sideDistX = (mapx + 1.0 - rayPosX) * deltaDistX
    EndIf
    If rayDirY < 0
      stepY = -1
      sideDistY = (rayPosY - mapy) * deltaDistY
    Else
      stepY = 1
      sideDistY = (mapy + 1.0 - rayPosY) * deltaDistY
    EndIf
    While hit = 0 
      If sideDistX < sideDistY
        sideDistX + deltaDistX
        mapx + stepX
        side = 0
      Else
        sideDistY + deltaDistY
        mapy + stepY
        side = 1
      EndIf               
      If worldMap(mapx,mapy) > 0
        hit = 1
      EndIf
    Wend
    If side = 0
      perpWallDist = Abs((mapx - rayPosX + (1 - stepX) / 2) / rayDirX)
    Else
      perpWallDist = Abs((mapy - rayPosY + (1 - stepY) / 2) / rayDirY)
    EndIf
    lineHeight = Abs(Int(384 / perpWallDist))
    drawStart = -lineHeight / 2 + 384 / 2
    If drawStart < 0
      drawStart = 0
    EndIf
    drawEnd = lineHeight / 2 + 384 / 2
    If drawEnd >= 384
      drawEnd = 384 - 1
    EndIf
    If worldMap(mapx,mapy) = 1
      color = RGB(255,0,0)
    ElseIf worldMap(mapx,mapy) = 2
      color = RGB(0,255,0)
    Else
      color = RGB(0,0,255)
    EndIf
    If side = 1
      color = RGB(Red(color)/2,Green(color)/2,Blue(color)/2)
    EndIf
    LineXY(x,drawStart,x,drawEnd,color)
  Next x
  oldTime = time
  time = ElapsedMilliseconds()
  frameTime.f = (time - oldTime) / 1000.0
  DrawingMode(1)
  DrawText(0,0,StrF(1.0 / frameTime),RGB(255,255,255))
  StopDrawing()
  FlipBuffers()
  moveSpeed.f = frameTime * 5.0
  rotSpeed.f = frameTime * 3.0 
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Up)
    If(worldMap(Int(posX + dirX * moveSpeed),Int(posY)) = #False)
      posX + dirX * moveSpeed
    EndIf
    If(worldMap(Int(posX),Int(posY + dirY * moveSpeed)) = #False)
      posY + dirY * moveSpeed
    EndIf
  EndIf
  If KeyboardPushed(#PB_Key_Down)
    If(worldMap(Int(posX - dirX * moveSpeed),Int(posY)) = #False)
      posX - dirX * moveSpeed
    EndIf
    If(worldMap(Int(posX),Int(posY - dirY * moveSpeed)) = #False)
      posY - dirY * moveSpeed
    EndIf
  EndIf
  If KeyboardPushed(#PB_Key_A)
    If(worldMap(Int(posX - planeX * moveSpeed),Int(posY)) = #False)
      posX - planeX * moveSpeed
    EndIf
    If(worldMap(Int(posX),Int(posY - planeY * moveSpeed)) = #False)
      posY - planeY * moveSpeed
    EndIf
  ElseIf KeyboardPushed(#PB_Key_D)
    If(worldMap(Int(posX + planeX * moveSpeed),Int(posY)) = #False)
      posX + planeX * moveSpeed
    EndIf
    If(worldMap(Int(posX),Int(posY + planeY * moveSpeed)) = #False)
      posY + planeY * moveSpeed
    EndIf
  EndIf
  If KeyboardPushed(#PB_Key_Right)
    oldDirX.f = dirX
    dirX = dirX * Cos(-rotSpeed) - dirY * Sin(-rotSpeed)
    dirY = oldDirX * Sin(-rotSpeed) + dirY * Cos(-rotSpeed)
    oldPlaneX.f = planeX
    planeX = planeX * Cos(-rotSpeed) - planeY * Sin(-rotSpeed)
    planeY = oldPlaneX * Sin(-rotSpeed) + planeY * Cos(-rotSpeed)
  EndIf
  If KeyboardPushed(#PB_Key_Left)
    oldDirX.f = dirX
    dirX = dirX * Cos(rotSpeed) - dirY * Sin(rotSpeed)
    dirY = oldDirX * Sin(rotSpeed) + dirY * Cos(rotSpeed)
    oldPlaneX.f = planeX
    planeX = planeX * Cos(rotSpeed) - planeY * Sin(rotSpeed)
    planeY = oldPlaneX * Sin(rotSpeed) + planeY * Cos(rotSpeed)
  EndIf
Until KeyboardPushed(1)
viel Spaß :D
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

Beitrag von Kekskiller »

Nett. Ich hatte auch von dem Tutorial gelernt. Aber leider hab ich dann mit fortschreitender selfmade-Engine nur noch Spaghetticode fabriziert :) . Versuch dich dochmal an Texturen oder gar an Wänden auf Vektorbasis. Bei mir hat das fast Jahr gedauert, bis ich alles hinbekommen habe.
Benutzeravatar
Zaphod
Beiträge: 2875
Registriert: 29.08.2004 00:40

Beitrag von Zaphod »

Wände auf Vektorbasis würde man mit einem etwas anderen Algorithmus Raycasten, es macht deswegen keinen Sinn einen Blockbasierten algorithmus zu schreiben mit der Absicht ihn zu erweitern.

Das einfügen von Texturen ist aber kein großes Problem, ich hab dafür ohne Tutorial etwa 3 Stunden gebraucht und ich bin alles andere als ein Matheass.
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

Beitrag von Kekskiller »

Ich selber habe meinen Raycaster von Block auf Vektor umgebaut. Es war nur ein Vorschlag, was es anderes probieren könnte. Sei nicht so grantig.
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

Beitrag von Kekskiller »

Bitte löschen, Board nölt.
Benutzeravatar
AndyX
Beiträge: 1272
Registriert: 17.12.2004 20:10
Wohnort: Niederösterreich
Kontaktdaten:

Beitrag von AndyX »

Texturen :)

Code: Alles auswählen

Procedure floor(x.f)
  ProcedureReturn Round(x,0)
EndProcedure

#mapWidth = 23
#mapHeight = 23
#texWidth = 128
#texHeight = 128
w = 800
h = 600

Global Dim worldMap.l(#mapWidth,#mapHeight)
Global Dim buffer.l(w,h)
Global Dim texture.l(8,#texWidth,#texHeight)

Restore wrldmap
For j = 0 To #mapHeight
  For i = 0 To #mapWidth
    Read worldMap(i,j)
  Next i
Next j

posX.f = 22
posY.f = 12
dirX.f = -1
dirY.f = 0
planeX.f = 0
planeY.f = 0.66
time = 0
oldTime = 0

For x = 0 To #texWidth
  For y = 0 To #texHeight
    xorcolor = (x * 256 / #texWidth) ! (y * 256 / #texHeight)
    xcolor = x * 256 / #texWidth
    ycolor = y * 256 / #texHeight
    xycolor = y * 128 / #texHeight + x * 128 / #texWidth
    texture(0,x,y) = (65536 * 254 * (x <> y And x <> #texWidth - y))
    texture(1,x,y) = (xycolor + 256 * xycolor + 65536 * xycolor)
    texture(2,x,y) = (256 * xycolor + 65536 * xycolor)
    texture(3,x,y) = (xorcolor + 256 * xorcolor + 65536 * xorcolor)
    texture(4,x,y) = (256 * xorcolor)
    texture(5,x,y) = (65536 * 192 * (x % 16 And y % 16))
    texture(6,x,y) = (65536 * ycolor)
    texture(7,x,y) = (128 + 256 * 128 + 65536 * 128)
  Next y
Next x

InitKeyboard()
InitSprite()
OpenScreen(w,h,32,"3D")

Repeat
  Delay(0)
  ClearScreen(0)
  For x = 0 To w
    cameraX.f = 2 * x / w - 1
    rayPosX.f = posX
    rayPosY.f = posY
    rayDirX.f = dirX + planeX * cameraX
    rayDirY.f = dirY + planeY * cameraX
    mapx = Int(rayPosX)
    mapy = Int(rayPosY)
    sideDistX.f
    sideDistY.f
    deltaDistX.f = Sqr(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
    deltaDistY.f = Sqr(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
    perpWallDist.f
    stepX.l
    stepY.l
    hit.l = 0
    side.l
    If rayDirX < 0
      stepX = -1
      sideDistX = (rayPosX - mapx) * deltaDistX
    Else
      stepX = 1
      sideDistX = (mapx + 1.0 - rayPosX) * deltaDistX
    EndIf
    If rayDirY < 0
      stepY = -1
      sideDistY = (rayPosY - mapy) * deltaDistY
    Else
      stepY = 1
      sideDistY = (mapy + 1.0 - rayPosY) * deltaDistY
    EndIf
    While hit = 0 
      If sideDistX < sideDistY
        sideDistX + deltaDistX
        mapx + stepX
        side = 0
      Else
        sideDistY + deltaDistY
        mapy + stepY
        side = 1
      EndIf               
      If worldMap(mapx,mapy) > 0
        hit = 1
      EndIf
    Wend
    If side = 0
      perpWallDist = Abs((mapx - rayPosX + (1 - stepX) / 2) / rayDirX)
    Else
      perpWallDist = Abs((mapy - rayPosY + (1 - stepY) / 2) / rayDirY)
    EndIf
    lineHeight = Abs(Int(h / perpWallDist))
    drawStart = -lineHeight / 2 + h / 2
    If drawStart < 0
      drawStart = 0
    EndIf
    drawEnd = lineHeight / 2 + h / 2
    If drawEnd >= h
      drawEnd = h - 1
    EndIf
    texNum = worldMap(mapx,mapy) - 1
    wallX.f
    If side = 1
      wallX = rayPosX + ((mapy - rayPosY + (1 - stepY) / 2) / rayDirY) * rayDirX
    Else
      wallX = rayPosY + ((mapx - rayPosX + (1 - stepX) / 2) / rayDirX) * rayDirY
    EndIf
    wallX - floor(wallX)
    texX = Int(wallX * #texWidth)
    If(side = 0 And rayDirX > 0)
      texX = #texWidth - texX - 1
    EndIf
    If(side = 1 And rayDirY < 0)
      texX = #texWidth - texX - 1
    EndIf
    For y = drawStart To drawEnd 
      d = y * 256 - h * 128 + lineHeight * 128
      texY = ((d * #texHeight) / lineHeight) / 256
      color = texture(texNum,texX,texY)
      If side = 1
        color = (color >> 1) & 8355711
      EndIf
      buffer(x,y) = color            
    Next y
  Next x
  StartDrawing(ScreenOutput())
  For x = 0 To w-1
    For y = 0 To h-1
      Plot(x,y,buffer(x,y))
      buffer(x,y) = 0
    Next y
  Next x
  oldTime = time
  time = ElapsedMilliseconds()
  frameTime.f = (time - oldTime) / 1000.0
  DrawingMode(1)
  DrawText(0,0,StrF(1.0 / frameTime),RGB(255,255,255))
  StopDrawing()
  FlipBuffers()
  moveSpeed.f = frameTime * 5.0
  rotSpeed.f = frameTime * 3.0 
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Up)
    If(worldMap(Int(posX + dirX * moveSpeed),Int(posY)) = #False)
      posX + dirX * moveSpeed
    EndIf
    If(worldMap(Int(posX),Int(posY + dirY * moveSpeed)) = #False)
      posY + dirY * moveSpeed
    EndIf
  EndIf
  If KeyboardPushed(#PB_Key_Down)
    If(worldMap(Int(posX - dirX * moveSpeed),Int(posY)) = #False)
      posX - dirX * moveSpeed
    EndIf
    If(worldMap(Int(posX),Int(posY - dirY * moveSpeed)) = #False)
      posY - dirY * moveSpeed
    EndIf
  EndIf
  If KeyboardPushed(#PB_Key_A)
    If(worldMap(Int(posX - planeX * moveSpeed),Int(posY)) = #False)
      posX - planeX * moveSpeed
    EndIf
    If(worldMap(Int(posX),Int(posY - planeY * moveSpeed)) = #False)
      posY - planeY * moveSpeed
    EndIf
  ElseIf KeyboardPushed(#PB_Key_D)
    If(worldMap(Int(posX + planeX * moveSpeed),Int(posY)) = #False)
      posX + planeX * moveSpeed
    EndIf
    If(worldMap(Int(posX),Int(posY + planeY * moveSpeed)) = #False)
      posY + planeY * moveSpeed
    EndIf
  EndIf
  If KeyboardPushed(#PB_Key_Right)
    oldDirX.f = dirX
    dirX = dirX * Cos(-rotSpeed) - dirY * Sin(-rotSpeed)
    dirY = oldDirX * Sin(-rotSpeed) + dirY * Cos(-rotSpeed)
    oldPlaneX.f = planeX
    planeX = planeX * Cos(-rotSpeed) - planeY * Sin(-rotSpeed)
    planeY = oldPlaneX * Sin(-rotSpeed) + planeY * Cos(-rotSpeed)
  EndIf
  If KeyboardPushed(#PB_Key_Left)
    oldDirX.f = dirX
    dirX = dirX * Cos(rotSpeed) - dirY * Sin(rotSpeed)
    dirY = oldDirX * Sin(rotSpeed) + dirY * Cos(rotSpeed)
    oldPlaneX.f = planeX
    planeX = planeX * Cos(rotSpeed) - planeY * Sin(rotSpeed)
    planeY = oldPlaneX * Sin(rotSpeed) + planeY * Cos(rotSpeed)
  EndIf
Until KeyboardPushed(1)

End
DataSection
wrldmap:
Data.l 4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2
Data.l 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,3,0,0,0,5,8,0,5,8,0,5,8,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,8,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,7,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,6,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,5,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,4,4,4,4,4,0,4,4,4,0,0,0,2,2,2,2,2,2,2,3,3,3,2
Data.l 4,0,0,0,0,0,0,0,0,4,0,0,0,2,0,0,0,0,0,2,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,4,0,0,0,2,0,0,0,0,0,2,2,0,2,2
Data.l 4,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,4,0,0,0,2,0,0,0,0,0,2,2,0,2,2
Data.l 4,0,0,0,0,0,0,0,0,4,0,0,0,2,0,0,0,0,0,2,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,4,0,0,0,2,0,0,0,0,0,2,0,0,0,2
Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
EndDataSection
Benutzeravatar
Zaphod
Beiträge: 2875
Registriert: 29.08.2004 00:40

Beitrag von Zaphod »

Garnicht übel ;)
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

Danke AndyX, das ist exzellenter code! Ich wollte ähnliches auch schon mal schreiben bin aber nie dazu gekommen bzw. hatte keinen Bock mich damit zu befassen. :mrgreen:

PS: Woher kenn ich diese graue Textur bloß? Ach ja! Das ist das "Xor Checker" preset für den "Expression" Generator in TextureMaker! :wink:
Benutzeravatar
AndyX
Beiträge: 1272
Registriert: 17.12.2004 20:10
Wohnort: Niederösterreich
Kontaktdaten:

Beitrag von AndyX »

Texturiert mit Boden u. Decke:

(benötigt das Texturpaket von hier -> Paket)

Code: Alles auswählen

Macro floor(x)
  Round(x,0)
EndMacro
Macro ColorRGB(r,g,b)
  ((r&$FF)+((g&$FF)<<8)+((b&$FF)<<16))
EndMacro

#mapWidth = 23
#mapHeight = 23
#texWidth = 63
#texHeight = 63
w = 512
h = 384

Global Dim worldMap.l(#mapWidth,#mapHeight)
Global Dim buffer.l(w,h)
Global Dim texture.l(8,#texWidth,#texHeight)

Restore wrldmap
For j = 0 To #mapHeight
  For i = 0 To #mapWidth
    Read worldMap(i,j)
  Next i
Next j

posX.f = 20
posY.f = 12
dirX.f = -1
dirY.f = 0
planeX.f = 0
planeY.f = 0.66
time = 0
oldTime = 0

InitKeyboard()
InitSprite()
OpenScreen(w,h,32,"3D")
StartDrawing(ScreenOutput())
DrawingMode(1)
DrawText(10,10,"wird geladen...",RGB(0,255,0))
StopDrawing()
FlipBuffers()

LoadSprite(8,"barrel.bmp")
LoadSprite(0,"bluestone.bmp")
LoadSprite(1,"colorstone.bmp")
LoadSprite(2,"eagle.bmp")
LoadSprite(9,"greenlight.bmp")
LoadSprite(3,"greystone.bmp")
LoadSprite(4,"mossy.bmp")
LoadSprite(10,"pillar.bmp")
LoadSprite(5,"purplestone.bmp")
LoadSprite(6,"redbrick.bmp")
LoadSprite(7,"wood.bmp")

For i = 0 To 7
  StartDrawing(SpriteOutput(i))
  For x = 0 To #texWidth
    For y = 0 To #texHeight
      c = Point(x,y)
      texture(i,x,y) = c
    Next y
  Next x
  StopDrawing()
Next i

Repeat
  For x = 0 To w
    cameraX.f = 2 * x / w - 1
    rayPosX.f = posX
    rayPosY.f = posY
    rayDirX.f = dirX + planeX * cameraX
    rayDirY.f = dirY + planeY * cameraX
    mapx = Int(rayPosX)
    mapy = Int(rayPosY)
    sideDistX.f
    sideDistY.f
    deltaDistX.f = Sqr(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
    deltaDistY.f = Sqr(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
    perpWallDist.f
    stepX.l
    stepY.l
    hit.l = 0
    side.l
    If rayDirX < 0
      stepX = -1
      sideDistX = (rayPosX - mapx) * deltaDistX
    Else
      stepX = 1
      sideDistX = (mapx + 1.0 - rayPosX) * deltaDistX
    EndIf
    If rayDirY < 0
      stepY = -1
      sideDistY = (rayPosY - mapy) * deltaDistY
    Else
      stepY = 1
      sideDistY = (mapy + 1.0 - rayPosY) * deltaDistY
    EndIf
    While hit = 0 
      If sideDistX < sideDistY
        sideDistX + deltaDistX
        mapx + stepX
        side = 0
      Else
        sideDistY + deltaDistY
        mapy + stepY
        side = 1
      EndIf               
      If worldMap(mapx,mapy) > 0
        hit = 1
      EndIf
    Wend
    If side = 0
      perpWallDist = Abs((mapx - rayPosX + (1 - stepX) / 2) / rayDirX)
    Else
      perpWallDist = Abs((mapy - rayPosY + (1 - stepY) / 2) / rayDirY)
    EndIf
    lineHeight = Abs(Int(h / perpWallDist))
    drawStart = -lineHeight / 2 + h / 2
    If drawStart < 0
      drawStart = 0
    EndIf
    drawEnd = lineHeight / 2 + h / 2
    If drawEnd >= h
      drawEnd = h - 1
    EndIf
    texNum = worldMap(mapx,mapy) - 1
    wallX.f
    If side = 1
      wallX = rayPosX + ((mapy - rayPosY + (1 - stepY) / 2) / rayDirY) * rayDirX
    Else
      wallX = rayPosY + ((mapx - rayPosX + (1 - stepX) / 2) / rayDirX) * rayDirY
    EndIf
    wallX - floor(wallX)
    texX = Int(wallX * #texWidth)
    If(side = 0 And rayDirX > 0)
      texX = #texWidth - texX - 1
    EndIf
    If(side = 1 And rayDirY < 0)
      texX = #texWidth - texX - 1
    EndIf
    For y = drawStart To drawEnd 
      d = y * 256 - h * 128 + lineHeight * 128
      texY = ((d * #texHeight) / lineHeight) / 256
      color = texture(texNum,texX,texY)
      If side = 1
        color = (color >> 1) & 8355711
      EndIf
      buffer(x,y) = color            
    Next y
    floorXWall.f
    floorYWall.f
    If side = 0 And rayDirX > 0
      floorXWall = mapx
      floorYWall = mapy + wallX
    ElseIf side = 0 And rayDirX < 0
      floorXWall = mapx + 1.0
      floorYWall = mapy + wallX
    ElseIf side = 1 And rayDirY > 0
      floorXWall = mapx + wallX
      floorYWall = mapy
    Else
      floorXWall = mapx + wallX
      floorYWall = mapy + 1.0
    EndIf
    distWall.f
    distPlayer.f
    currentDist.f  
    distWall = perpWallDist
    distPlayer = 0.0
    If drawEnd < 0
      drawEnd = h
    EndIf
    For y = drawEnd + 1 To h
      currentDist = h / (2.0 * y - h)
      weight.f = (currentDist - distPlayer) / (distWall - distPlayer)
      currentFloorX.f = weight * floorXWall + (1.0 - weight) * posX
      currentFloorY.f = weight * floorYWall + (1.0 - weight) * posY
      floorTexX.l
      floorTexY.l
      floorTexX = Int(currentFloorX * #texWidth) % #texWidth
      floorTexY = Int(currentFloorY * #texHeight) % #texHeight
      buffer(x,y) = (texture(3,floorTexX,floorTexY) >> 1) & 8355711
      buffer(x,h - y) = texture(7,floorTexX,floorTexY)
    Next y
  Next x
  StartDrawing(ScreenOutput())
  For x = 0 To w-1
    For y = 0 To h-1
      Plot(x,y,buffer(x,y))
      buffer(x,y) = 0
    Next y
  Next x
  oldTime = time
  time = ElapsedMilliseconds()
  frameTime.f = (time - oldTime) / 1000.0
  DrawingMode(1)
  DrawText(0,0,StrF(1.0 / frameTime),RGB(255,255,255))
  StopDrawing()
  FlipBuffers()
  moveSpeed.f = frameTime * 5.0
  rotSpeed.f = frameTime * 3.0 
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Up)
    If(worldMap(Int(posX + dirX * moveSpeed),Int(posY)) = #False)
      posX + dirX * moveSpeed
    EndIf
    If(worldMap(Int(posX),Int(posY + dirY * moveSpeed)) = #False)
      posY + dirY * moveSpeed
    EndIf
  EndIf
  If KeyboardPushed(#PB_Key_Down)
    If(worldMap(Int(posX - dirX * moveSpeed),Int(posY)) = #False)
      posX - dirX * moveSpeed
    EndIf
    If(worldMap(Int(posX),Int(posY - dirY * moveSpeed)) = #False)
      posY - dirY * moveSpeed
    EndIf
  EndIf
  If KeyboardPushed(#PB_Key_A)
    If(worldMap(Int(posX - planeX * moveSpeed),Int(posY)) = #False)
      posX - planeX * moveSpeed
    EndIf
    If(worldMap(Int(posX),Int(posY - planeY * moveSpeed)) = #False)
      posY - planeY * moveSpeed
    EndIf
  ElseIf KeyboardPushed(#PB_Key_D)
    If(worldMap(Int(posX + planeX * moveSpeed),Int(posY)) = #False)
      posX + planeX * moveSpeed
    EndIf
    If(worldMap(Int(posX),Int(posY + planeY * moveSpeed)) = #False)
      posY + planeY * moveSpeed
    EndIf
  EndIf
  If KeyboardPushed(#PB_Key_Right)
    oldDirX.f = dirX
    dirX = dirX * Cos(-rotSpeed) - dirY * Sin(-rotSpeed)
    dirY = oldDirX * Sin(-rotSpeed) + dirY * Cos(-rotSpeed)
    oldPlaneX.f = planeX
    planeX = planeX * Cos(-rotSpeed) - planeY * Sin(-rotSpeed)
    planeY = oldPlaneX * Sin(-rotSpeed) + planeY * Cos(-rotSpeed)
  EndIf
  If KeyboardPushed(#PB_Key_Left)
    oldDirX.f = dirX
    dirX = dirX * Cos(rotSpeed) - dirY * Sin(rotSpeed)
    dirY = oldDirX * Sin(rotSpeed) + dirY * Cos(rotSpeed)
    oldPlaneX.f = planeX
    planeX = planeX * Cos(rotSpeed) - planeY * Sin(rotSpeed)
    planeY = oldPlaneX * Sin(rotSpeed) + planeY * Cos(rotSpeed)
  EndIf
Until KeyboardPushed(1)

End
DataSection
wrldmap:
Data.l 4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2
Data.l 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,3,0,0,0,5,8,0,5,8,0,5,8,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,8,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,7,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,6,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,5,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,4,4,4,4,4,0,4,4,4,0,0,0,2,2,2,2,2,2,2,3,3,3,2
Data.l 4,0,0,0,0,0,0,0,0,4,0,0,0,2,0,0,0,0,0,2,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,4,0,0,0,2,0,0,0,0,0,2,2,0,2,2
Data.l 4,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,4,0,0,0,2,0,0,0,0,0,2,2,0,2,2
Data.l 4,0,0,0,0,0,0,0,0,4,0,0,0,2,0,0,0,0,0,2,0,0,0,2
Data.l 4,0,0,0,0,0,0,0,0,4,0,0,0,2,0,0,0,0,0,2,0,0,0,2
Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
EndDataSection
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

Beitrag von Kekskiller »

Coole Sache, aber wie bei allen Raycastern leider nur mit halber Framerate. Zu blöde, dass man diese Alghos nur bedingt optimieren kann.
Antworten