Code-Beispiel
RayCaster (Untexturiert)
Lizenz: | Erster Autor: | Letzte Bearbeitung: |
k. A. | PMedia | 19.06.2007 |
''Copyright (c) 2004-2007, Lode Vandevenne (converted from C to FreeBasic by PMedia in 2007)
''All rights reserved.
''
''This software is provided 'as-is', without any express or implied
''warranty. In no event will the authors be held liable for any damages
''arising from the use of this software.
''
''Permission is granted to anyone to use this software for any purpose,
''including commercial applications, and to alter it and redistribute it
''freely, subject to the following restrictions:
''
'' 1. The origin of this software must not be misrepresented; you must not
'' claim that you wrote the original software. If you use this software
'' in a product, an acknowledgment in the product documentation would be
'' appreciated but is not required.
''
'' 2. Altered source versions must be plainly marked as such, and must not be
'' misrepresented as being the original software.
''
'' 3. This notice may not be removed or altered from any source
'' distribution.
'' sure, the original had some includes more, but FB doesn't need them ^^
#include "fbgfx.bi"
'' fbc raycaster_flat.bas
#define mapWidth 24
#define mapHeight 24
dim shared as integer worldmap(mapWidth, mapHeight) = _
{ _
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, _
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1}, _
{1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1}, _
{1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1}, _
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, _
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} _
}
Sub Main(argc As UInteger = 0, argv As String = "")
''x and y start position
Dim As Double posX = 22
Dim As Double posY = 12
'' initial direction vector
Dim As Double dirX = -1
Dim As Double dirY = -1
'' the 2d raycaster version of camera plane
Dim As Double planeX = 0
Dim As Double planeY = 0.66
'' time of current frame
Dim As Double curtime = 0
''time of previous frame
Dim As Double oldTime = 0
'' (PMedia)
'' code-cleaned here:
Dim As Integer X
Dim As Double cameraX
Dim As Double rayPosX
Dim As Double rayPosY
Dim As Double rayDirX
Dim As Double rayDirY
Dim As Integer mapX
Dim As Integer mapY
Dim As Double sideDistX
Dim As Double sideDistY
Dim As Double deltaDistX
Dim As Double deltaDistY
Dim As Double perpWallDist
Dim As Integer stepX
Dim As Integer stepY
Dim As Integer hit
Dim As Integer side
Dim As Integer lineHeight
Dim As Integer drawStart
Dim As Integer drawEnd
Dim As UInteger ColorRGB
Dim As Double frameTime
Dim As Double moveSpeed
Dim As Double rotSpeed
Dim As Double oldDirX
Dim As Double oldDirY
Dim As Double oldPlaneX
Dim As Double oldPlaneY
ScreenRes 512, 384, 32
WindowTitle "RayCaster"
Do Until (multikey(fb.sc_escape))
'' sacrifice 5 milliseconds per frame to free some CPU time
Sleep 5
screenlock
cls
for x = 0 to 512 step 1
'' calculate ray position and direction
cameraX = 2 * x / 512 - 1 '' x-coordinate in camera space
rayPosX = posX
rayPosY = posY
rayDirX = dirX + planeX * cameraX
rayDirY = dirY + planeY * cameraX
mapX = rayPosX
mapY = rayPosY
'' length of ray from current position to next x or y-side
' --
'' length of ray from one x or y-side to next x or y-side
deltaDistX = sqr(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
deltaDistY = sqr(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
'' what direction to step in x or y-direction (either +1 or -1)
'' was there a wall hit?
hit = 0
'' was a NS or a EW wall hit?
'' calculate step and initial sideDist
if (rayDirX < 0) then
stepX = -1
sideDistX = (rayPosX - mapX) * deltaDistX
else
stepX = 1
sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX
end if
if (rayDirY < 0) then
stepY = -1
sideDistY = (rayPosY - mapY) * deltaDistY
else
stepY = 1
sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY
end if
'' Perform DDA
do while (hit = 0)
'' jump to next map square, OR in x-direction OR in y-direction
if (sideDistX < sideDistY) then
sideDistX += deltaDistX
mapX += stepX
side = 0
else
sideDistY += deltaDistY
mapY += stepY
side = 1
end if
'' Check if ray has hit a wall
if (worldMap(mapX, mapY) > 0) then hit = 1
loop
'' Calculate distance projected on camera direction (oblique distance will give fisheye effect!)
if (side = 0) then
perpWallDist = abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX)
else
perpWallDist = abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY)
end if
'' calculate height of line to draw on screen
lineHeight = abs(int(384/perpWallDist))
'' Calculate lowest and highest Pixel to fill in current stripe
drawstart = -lineHeight / 2 + 384 / 2
if (drawstart < 0) then drawStart = 0
drawEnd = lineHeight / 2 + 384 / 2
if (drawEnd < 0) then drawEnd = 0
select case worldmap(mapX, mapY)
case 1
colorRGB = rgb(255, 0, 0) '' red
case 2
colorRGB = rgb(0, 255, 0) '' green
case 3
colorRGB = rgb(0, 0, 255) '' blue
case 4
colorRGB = rgb(255,255,255) '' white
case else
colorRGB = rgb(255, 255, 0) '' yellow
end select
'' Give x and y sides different brightness
if (side = 1) then colorRGB = colorRGB / 2
'' draw the pixels of the stripe as a vertical line
line (x, drawStart) - (x, drawEnd), colorRGB
next
print (1.0 / frameTime)
screenunlock
'' timing for input and FPS counter
oldtime = curtime
curtime = timer * 1000
frametime = (curtime - oldTime) / 1000.0 ''frameTime is the time this frame has taken, in seconds
'' frametime = 1 / 60
'' speed modifiers
movespeed = frameTime * 5.0 '' the constant value is in squares/second
rotspeed = frameTime * 3.0 '' the constant value is in radians/second
'' move forward if no wall in front of you
if multikey(fb.sc_up) then
if worldMap(int(posX + dirX * moveSpeed),int(posy)) = 0 then posX += dirX * moveSpeed
if worldMap(int(posX),int(posY + dirY * moveSpeed)) = 0 then posY += dirY * moveSpeed
end if
'' move backwards if no wall behind you
if multikey(fb.sc_down) then
if(worldMap(int(posX - dirX * moveSpeed),int(posY)) = 0) then posX -= dirX * moveSpeed
if(worldMap(int(posX),int(posY - dirY * moveSpeed)) = 0) then posY -= dirY * moveSpeed
end if
'' rotate to the right
if multikey(fb.sc_right) then
''both camera direction and camera plane must be rotated
oldDirX = dirX
dirX = dirX * cos(-rotSpeed) - dirY * sin(-rotSpeed)
dirY = oldDirX * sin(-rotSpeed) + dirY * cos(-rotSpeed)
oldPlaneX = planeX
planeX = planeX * cos(-rotSpeed) - planeY * sin(-rotSpeed)
planeY = oldPlaneX * sin(-rotSpeed) + planeY * cos(-rotSpeed)
end if
'' rotate to the left
if multikey(fb.sc_left) then
''both camera direction and camera plane must be rotated
oldDirX = dirX
dirX = dirX * cos(rotSpeed) - dirY * sin(rotSpeed)
dirY = oldDirX * sin(rotSpeed) + dirY * cos(rotSpeed)
oldPlaneX = planeX
planeX = planeX * cos(rotSpeed) - planeY * sin(rotSpeed)
planeY = oldPlaneX * sin(rotSpeed) + planeY * cos(rotSpeed)
endif
Loop
End Sub
Main()
Zusätzliche Informationen und Funktionen | |||||||
---|---|---|---|---|---|---|---|
|