visible: rem Map =========================================================== rem Width and height. rc_MapW rc_MapH rem Walls. rc_Map[][] rc_Floor[][] rc_Ceiling[][] rc_Flag[][] rc_Items[][] rc_ItemParams#[][] rc_Doors[][] rc_Darkness[][] rc_UseDarkness = false rem View ========================================================== rc_Unit# rc_AngleOffset#[] rc_AngleOffsetCos#[] rc_Distance#[][] rc_ZBuffer#[] rc_Width = 320 rc_Height = 240 rc_FogR rc_FogG rc_FogB rc_FogMin# rc_FogMax# rc_FogSpread# constant: RC_MAX_OBJECTS 200 RC_OBJ_ID 0 RC_OBJ_IMG 1 RC_OBJ_IXY 2 RC_OBJ_X 0 RC_OBJ_Z 1 RC_OBJ_Y 2 RC_OBJ_TX 3 RC_OBJ_TZ 4 RC_OBJ_W 5 RC_OBJ_H 6 RC_OBJ_D 7 RC_X 0 RC_Z 1 RC_ANGLE 2 RC_FLAG 2 RC_NORTH 0 RC_SOUTH 1 RC_WEST 2 RC_EAST 3 visible: RC_MAX_DOORS = 100 rc_Objects[RC_MAX_OBJECTS][3] rc_ObjectsF#[RC_MAX_OBJECTS][8] rc_ObjOrder[RC_MAX_OBJECTS] rc_ObjCount = 0 rc_OpenDoorCount = 0 rc_OpenDoors[RC_MAX_DOORS][2] rc_DoorSpeed# = 0.025 rc_CollisionInfo[4] hidden: rem ================================================================== rem Init view with specified field of view. rem ================================================================== procedure RC_InitView(fov#, renderW, renderH) rc_Width = renderW rc_Height = renderH w = rc_Width h = rc_Height hw = w/2 hh = h/2 rc_Unit = float(hw)/tan(fov*0.5) rc_AngleOffset#[w] rc_AngleOffsetCos#[w] rc_ZBuffer#[w] for x = 0 to hw - 1 rc_AngleOffset[hw + x] = atan(float(x)/rc_Unit) rc_AngleOffset[hw - 1 - x] = -rc_AngleOffset[hw + x] rc_AngleOffsetCos[hw + x] = cos(rc_AngleOffset[hw + x]) rc_AngleOffsetCos[hw - 1 - x] = cos(rc_AngleOffset[hw - 1 - x]) next rc_Distance[w][hh] for x = 0 to w - 1 dconv# = 1.0/cos(rc_AngleOffset[x]) for y = 0 to hh - 1 d# = rc_Unit/float(h - 2*y) d = d*dconv rc_Distance[x][y] = d next next endproc rem ================================================================== rem Init map. rem ================================================================== procedure RC_InitMap(w, h) rc_MapW = w rc_MapH = h rc_Map[rc_MapW][rc_MapH] rc_Floor[rc_MapW][rc_MapH] rc_Ceiling[rc_MapW][rc_MapH] rc_Flag[rc_MapW][rc_MapH] rc_Items[rc_MapW][rc_MapH] rc_ItemParams#[rc_MapW][rc_MapH] rc_Doors[rc_MapW][rc_MapH] rc_Darkness[rc_MapW][rc_MapH] proc RC_ClearObjects proc RC_ClearDoors endproc procedure RC_SetDarkness(x, z, value#) value = min#(value, 1.0) value = max#(value, 0.0) rc_Darkness[x][z] = int(value*255.0) endproc function RC_GetDarkness#(x, z) return float(rc_Darkness[x][z])/255.0 endproc function RC_GetMapWidth() return rc_MapW endfunc function RC_GetMapHeight() return rc_MapH endfunc procedure RC_EnableDarkness() rc_UseDarkness = true endproc procedure RC_DisableDarkness() rc_UseDarkness = false endproc rem ================================================================== rem Set wall. rem ================================================================== procedure RC_SetWall(x, z, img) if sizeof(rc_Map) = 0 then return rc_Map[x][z] = img endproc rem ================================================================== rem Set floor. rem ================================================================== procedure RC_SetFloor(x, z, img) if sizeof(rc_Map) = 0 then return rc_Floor[x][z] = img endproc rem ================================================================== rem Set ceiling. rem ================================================================== procedure RC_SetCeiling(x, z, img) if sizeof(rc_Map) = 0 then return rc_Ceiling[x][z] = img endproc rem ================================================================== rem Set flag. rem ================================================================== procedure RC_SetFlag(x, z, flag) if sizeof(rc_Map) = 0 then return rc_Flag[x][z] = flag endproc procedure RC_SetItem(x, z, item, obstacle) if sizeof(rc_Map) = 0 then return rc_Items[x][z] = item if obstacle then rc_Map[x][z] = -3 endproc rem ================================================================== rem Return type of item at x, z. rem ================================================================== function RC_GetItem(x, z) if sizeof(rc_Map) = 0 then return 0 return rc_Items[x][z] endfunc rem ================================================================== rem Get wall. rem ================================================================== function RC_GetWall(x, z) if sizeof(rc_Map) = 0 then return 0 if rc_Map[x][z] = 0 then return 0 return rc_Map[x][z] - 1000 endfunc function RC_GetWallImage(x, z) if x < 0 or x >= rc_MapW then return 0 if z < 0 or z >= rc_MapH then return 0 return rc_Map[x][z] endfunc function RC_GetFloorImage(x, z) if x < 0 or x >= rc_MapW then return 0 if z < 0 or z >= rc_MapH then return 0 return rc_Floor[x][z] endfunc function RC_GetCeilingImage(x, z) if x < 0 or x >= rc_MapW then return 0 if z < 0 or z >= rc_MapH then return 0 return rc_Ceiling[x][z] endfunc rem ================================================================== rem Get floor. rem ================================================================== function RC_GetFloor(x, z) if sizeof(rc_Map) = 0 then return 0 return rc_Floor[x][z] - 1000 endfunc rem ================================================================== rem Get ceiling. rem ================================================================== function RC_GetCeiling(x, z) if sizeof(rc_Map) = 0 then return 0 return rc_Ceiling[x][z] - 1000 endfunc rem ================================================================== rem Get flag. rem ================================================================== function RC_GetFlag(x, z) if sizeof(rc_Map) = 0 then return 0 return rc_Flag[x][z] endfunc function RC_GetFlagPos[](flag) pos[] if sizeof(rc_Map) = 0 then return pos for z = 0 to rc_MapH - 1 for x = 0 to rc_MapH - 1 if rc_Flag[x][z] = flag pos[] = [x, z] break endif next if sizeof(pos) then break next return pos endfunc rem ================================================================== rem Clear objects. rem ================================================================== procedure RC_ClearObjects() rc_ObjCount = 0 for i = 0 to RC_MAX_OBJECTS - 1 rc_Objects[i][RC_OBJ_ID] = 0 rc_ObjOrder[i] = 0 next endproc rem ================================================================== rem Clear doors. rem ================================================================== procedure RC_ClearDoors() rc_OpenDoorCount = 0 endproc rem ================================================================== rem Set door speed. rem ================================================================== procedure RC_SetDoorSpeed(speed#) rc_DoorSpeed# = speed endproc rem ================================================================== rem Render view. rem ================================================================== procedure RC_Render(xpos#, zpos#, angle#) if sizeof(rc_Map) = 0 then return xdistance# zdistance# xposi zposi xposf# zposf# dzdx_inv# dxdz_inv# hdzdx_inv# hdxdz_inv# xtexture ztexture xutex# zutex# y t texu# wt dzdx_inv# dxdz_inv# xfailed zfailed xoffs# zoffs# ysize set color rc_FogR, rc_FogG, rc_FogB draw rect 0, 0, rc_Width, rc_Height, true proc RC_DrawFloorAndCeiling xpos, zpos, angle alpha id itm col = 0 do dx# = cos(angle + rc_AngleOffset[col]) dz# = sin(angle + rc_AngleOffset[col]) if dx <> 0.0 dzdx_inv = dz/dx hdzdx_inv = dzdx_inv*0.5 endif if dz <> 0.0 dxdz_inv = dx/dz hdxdz_inv = dxdz_inv*0.5 endif xdistance = 0.0 zdistance = 0.0 rem Cast x ray. xposi = int(xpos) xfailed = false if dx < 0.0 xposi = xposi - 1 xposf = float(xposi) + 1.0 zposf = (xposf - xpos)*dzdx_inv + zpos zposi = int(zposf) if zposi < 0 or zposi >= rc_MapH xfailed = true xdistance = 100000.0 else id = rc_Map[xposi][zposi] xoffs = 0.0 while id <= 0 door = false if id = -1 reg4# = zposf - hdzdx_inv if int(reg4) = zposi xoffs# = rc_ItemParams[xposi][zposi] if int(reg4 - xoffs) = zposi door = true zposf = reg4 xposf = float(xposi + 1) - 0.5 id = rc_Items[xposi][zposi] break endif endif endif xoffs# = 0.0 xposi = xposi - 1 zposf = zposf - dzdx_inv zposi = int(zposf) if zposi < 0 or zposi >= rc_MapH or xposi < 0 xfailed = true xdistance = 100000.0 break endif id = rc_Map[xposi][zposi] wend if not door xposf = float(xposi) + 1.0 endif if not xfailed xtexture = id xutex = 1.0 - ((zposf - xoffs) - float(zposi)) xdistance = (xposf - xpos)*(xposf - xpos) + (zposf - zpos)*(zposf - zpos) xdarkness = rc_Darkness[xposi][zposi] endif endif elseif dx > 0.0 xposi = xposi + 1 xposf = float(xposi) zposf = (xposf - xpos)*dzdx_inv + zpos zposi = int(zposf) if zposi < 0 or zposi >= rc_MapH xfailed = true xdistance = 100000.0 else id = rc_Map[xposi][zposi] xoffs = 0.0 while id <= 0 door = false if id = -1 reg4# = zposf + hdzdx_inv if int(reg4) = zposi xoffs# = rc_ItemParams[xposi][zposi] if int(reg4 - xoffs) = zposi door = true zposf = reg4 xposf = float(xposi + 1) - 0.5 id = rc_Items[xposi][zposi] break endif endif endif xoffs = 0.0 xposi = xposi + 1 zposf = zposf + dzdx_inv zposi = int(zposf) if zposi < 0 or zposi >= rc_MapH or xposi >= rc_MapW xfailed = true xdistance = 100000.0 break endif id = rc_Map[xposi][zposi] wend if not door xposf = float(xposi) endif if not xfailed xtexture = id xutex = (zposf - xoffs) - float(zposi) xdistance = (xposf - xpos)*(xposf - xpos) + (zposf - zpos)*(zposf - zpos) xdarkness = rc_Darkness[xposi][zposi] endif endif else xfailed = true xdistance = 100000.0 endif rem Cast z ray zposi = int(zpos) zfailed = false if dz < 0.0 zposi = zposi - 1 zposf = float(zposi) + 1.0 xposf = (zposf - zpos)*dxdz_inv + xpos xposi = int(xposf) if xposi < 0 or xposi >= rc_MapW zfailed = true zdistance = 100000.0 else id = rc_Map[xposi][zposi] zoffs = 0.0 while id <= 0 door = false if id = -2 reg4# = xposf - hdxdz_inv if int(reg4) = xposi zoffs# = rc_ItemParams[xposi][zposi] if int(reg4 - zoffs) = xposi door = true xposf = reg4 zposf = float(zposi + 1) - 0.5 id = rc_Items[xposi][zposi] break endif endif endif zoffs# = 0.0 zposi = zposi - 1 xposf = xposf - dxdz_inv xposi = int(xposf) if xposi < 0 or xposi >= rc_MapW or zposi < 0 zfailed = true zdistance = 100000.0 break endif id = rc_Map[xposi][zposi] wend if not door zposf = float(zposi) + 1.0 endif if not zfailed ztexture = id zutex = xposf - zoffs - float(xposi) zdistance = (xposf - xpos)*(xposf - xpos) + (zposf - zpos)*(zposf - zpos) zdarkness = rc_Darkness[xposi][zposi] endif endif elseif dz > 0.0 zposi = zposi + 1 zposf = float(zposi) xposf = (zposf - zpos)*dxdz_inv + xpos xposi = int(xposf) if xposi < 0 or xposi >= rc_MapW zfailed = true zdistance = 100000.0 else id = rc_Map[xposi][zposi] zoffs = 0.0 while id <= 0 door = false if id = -2 reg4# = xposf + hdxdz_inv if int(reg4) = xposi zoffs# = rc_ItemParams[xposi][zposi] if int(reg4 - zoffs) = xposi door = true xposf = reg4 zposf = float(zposi + 1) - 0.5 id = rc_Items[xposi][zposi] break endif endif endif zoffs = 0.0 zposi = zposi + 1 xposf = xposf + dxdz_inv xposi = int(xposf) if xposi < 0 or xposi >= rc_MapW or zposi >= rc_MapH zfailed = true zdistance = 100000.0 break endif id = rc_Map[xposi][zposi] wend if not door zposf = float(zposi) endif if not zfailed ztexture = id zutex = 1.0 - (xposf - zoffs - float(xposi)) zdistance = (xposf - xpos)*(xposf - xpos) + (zposf - zpos)*(zposf - zpos) zdarkness = rc_Darkness[xposi][zposi] endif endif else zfailed = true zdistance = 100000.0 endif if xdistance < zdistance t = xtexture xdistance = sqr(xdistance)*rc_AngleOffsetCos[col] rc_ZBuffer[col] = xdistance ysize = int(rc_Unit/xdistance)/2 texu = xutex if rc_UseDarkness alpha = max(int((xdistance - rc_FogMin)*rc_FogSpread), 0) + xdarkness else alpha = int((xdistance - rc_FogMin)*rc_FogSpread) endif else t = ztexture zdistance = sqr(zdistance)*rc_AngleOffsetCos[col] rc_ZBuffer[col] = zdistance ysize = int(rc_Unit/zdistance)/2 texu = zutex if rc_UseDarkness alpha = max(int((zdistance - rc_FogMin)*rc_FogSpread), 0) + zdarkness else alpha = int((zdistance - rc_FogMin)*rc_FogSpread) endif endif if alpha < 255 set color rc_FogR, rc_FogG, rc_FogB, alpha y = (rc_Height/2) - ysize draw vraster t, col, y, y + ysize*2, texu, 0.0, texu, 1.0 endif col = col + 1 until col = rc_Width proc RC_RenderObjects xpos, zpos, angle endproc procedure RC_DrawFloorAndCeiling(xpos#, zpos#, angle#) xk# zk# xf# zf# xi zi ustart# vstart# uend# vend# dstart# xstart# zstart# dend# xend# dx# dz# screenxstart# screendx# screenxend# oldxi oldzi xk# zk# d# h = rc_Height hh = rc_Height/2 - 4 w = rc_Width - 1 y = 0 alpha id do dstart# = rc_Distance[0][y] xstart# = xpos + dstart*cos(angle + rc_AngleOffset[0]) zstart# = zpos + dstart*sin(angle + rc_AngleOffset[0]) dend# = rc_Distance[w][y] xend# = xpos + dend*cos(angle + rc_AngleOffset[w]) zend# = zpos + dend*sin(angle + rc_AngleOffset[w]) dx = xend - xstart dz = zend - zstart d# = sqr(dx*dx + dz*dz) k# = 1.0/d dx = dx*k dz = dz*k screenxstart = 0.0 screendx = float(w)/d xi = int(xstart) zi = int(zstart) ustart = xstart - float(int(xstart)) vstart = zstart - float(int(zstart)) alpha = max(int((rc_Distance[rc_Width/2][y] - rc_FogMin)*rc_FogSpread), 0) if y >= hh or alpha >= 255 break else set color rc_FogR, rc_FogG, rc_FogB, alpha endif do oldxi = xi oldzi = zi rem dx step. if dx < 0.0 if oldxi < 0 then break xi = xi - 1 xf = float(xi + 1) xk = (xf - xstart)/dx elseif dx > 0.0 if oldxi >= rc_MapW then break xi = xi + 1 xf = float(xi) xk = (xf - xstart)/dx else xk = 100000.0 endif rem dz step. if dz < 0.0 if oldzi < 0 then break zi = zi - 1 zf = float(zi + 1) zk = (zf - zstart)/dz elseif dz > 0.0 if oldzi >= rc_MapH then break zi = zi + 1 zf = float(zi) zk = (zf - zstart)/dz else zk = 100000.0 endif if xk < zk if dz < 0.0 zi = zi + 1 elseif dz > 0.0 zi = zi - 1 endif if dx < 0.0 uend = 0.0 else uend = 1.0 endif xend = xf zend = xk*dz + zstart vend = zend - float(int(zend)) screenxend = xk*screendx + screenxstart else if dx < 0.0 xi = xi + 1 elseif dx > 0.0 xi = xi - 1 endif if dz < 0.0 vend = 0.0 else vend = 1.0 endif zend = zf xend = zk*dx + xstart uend = xend - float(int(xend)) screenxend = zk*screendx + screenxstart endif if oldxi >= 0 and oldxi < rc_MapW and oldzi >= 0 and oldzi < rc_MapH if rc_UseDarkness set color rc_FogR, rc_FogG, rc_FogB, alpha + rc_Darkness[oldxi][oldzi] endif flr = rc_Floor[oldxi][oldzi] if flr > 0 draw hraster flr, h - 1 - y, int(screenxstart), int(screenxend), ustart, vstart, uend, vend endif cl = rc_Ceiling[oldxi][oldzi] if cl > 0 draw hraster cl, y, int(screenxstart), int(screenxend), ustart, vstart, uend, vend endif endif xstart = xend zstart = zend screenxstart = screenxend if uend = 0.0 ustart = 1.0 elseif uend = 1.0 ustart = 0.0 else ustart = uend endif if vend = 0.0 vstart = 1.0 elseif vend = 1.0 vstart = 0.0 else vstart = vend endif if screenxend >= float(w) then break loop y = y + 1 loop endproc function RC_ObstacleAt(x, z) m = rc_Map[x][z] if m > 0 then return true if m < 0 and rc_ItemParams[x][z] < 1.0 then return true return false endfunc function RC_Move#[](dist#, xpos#, zpos#, dx#, dz#) x = int(xpos) z = int(zpos) upperdist# = 1.0 - dist xnocol# = xpos + dx znocol# = zpos + dz xnew# = xnocol znew# = znocol r = RC_ObstacleAt(x + 1, z) br = RC_ObstacleAt(x + 1, z - 1) b = RC_ObstacleAt(x, z-1) bl = RC_ObstacleAt(x - 1, z - 1) l = RC_ObstacleAt(x - 1, z) tl = RC_ObstacleAt(x - 1, z + 1) t = RC_ObstacleAt(x, z + 1) tr = RC_ObstacleAt(x + 1, z + 1) rc_CollisionInfo[RC_EAST] = false rc_CollisionInfo[RC_WEST] = false rc_CollisionInfo[RC_NORTH] = false rc_CollisionInfo[RC_SOUTH] = false if xpos + dx > float(x) + upperdist if r or (t = 0 and tr and zpos > float(z) + upperdist) or (b = 0 and br and zpos < float(z) + dist) xnew = float(x) + upperdist rc_CollisionInfo[RC_EAST] = true endif endif if xpos + dx < float(x) + dist if l or (t = 0 and tl and zpos > float(z) + upperdist) or (b = 0 and bl and zpos < float(z) + dist) xnew = float(x) + dist rc_CollisionInfo[RC_WEST] = true endif endif if zpos + dz > float(z) + upperdist if t or (r = 0 and tr and xpos > float(x) + upperdist) or (l = 0 and tl and xpos < float(x) + dist) znew = float(z) + upperdist rc_CollisionInfo[RC_NORTH] = true endif endif if zpos + dz < float(z) + dist if b or (r = 0 and br and xpos > float(x) + upperdist) or (l = 0 and bl and xpos < float(x) + dist) znew = float(z) + dist rc_CollisionInfo[RC_SOUTH] = true endif endif return [xnew, znew] endproc function RC_GetCollisionInfo[]() return rc_CollisionInfo endfunc rem Set fog. procedure RC_SetFog(r, g, b, zMin#, zMax#) rc_FogR = r rc_FogG = g rc_FogB = b rc_FogMin = zMin# rc_FogMax = zMax# rc_FogSpread = 255.0/(zMax - zMin) endproc procedure RC_AddObject(id, img, x#, z#, y#, s#, ix, iz) if width(img) > height(img) w# = s h# = s*float(height(img))/float(width(img)) else h# = s w# = s*float(width(img))/float(height(img)) endif y = 0.5 - y - h index = -1 if width(img) > height(img) w# = s h# = s*float(height(img))/float(width(img)) else h# = s w# = s*float(width(img))/float(height(img)) endif for i = 0 to RC_MAX_OBJECTS - 1 if rc_Objects[i][RC_OBJ_ID] = 0 index = i break endif next if index >= 0 rc_Objects[index][RC_OBJ_ID] = id rc_Objects[index][RC_OBJ_IMG] = img rc_Objects[index][RC_OBJ_IXY] = iz*rc_MapW + ix rc_ObjectsF[index][RC_OBJ_X] = x rc_ObjectsF[index][RC_OBJ_Z] = z rc_ObjectsF[index][RC_OBJ_Y] = y rc_ObjectsF[index][RC_OBJ_W] = w rc_ObjectsF[index][RC_OBJ_H] = h rc_ObjOrder[rc_ObjCount] = index rc_ObjCount = rc_ObjCount + 1 endif endproc procedure RC_ModifyObject(id, img, x#, z#, y#) index = -1 for i = 0 to RC_MAX_OBJECTS - 1 if rc_Objects[i][RC_OBJ_ID] = id index = i break endif next if index >= 0 y = 0.5 - y - rc_ObjectsF[index][RC_OBJ_H] rc_Objects[index][RC_OBJ_IMG] = img rc_ObjectsF[index][RC_OBJ_X] = x rc_ObjectsF[index][RC_OBJ_Z] = z rc_ObjectsF[index][RC_OBJ_Y] = y endif endproc procedure RC_SetObjectImage(id, img) index = -1 for i = 0 to RC_MAX_OBJECTS - 1 if rc_Objects[i][RC_OBJ_ID] = id index = i break endif next if index >= 0 then rc_Objects[index][RC_OBJ_IMG] = img endproc procedure RC_SetObjectPos(id, x#, z#, y#) index = -1 for i = 0 to RC_MAX_OBJECTS - 1 if rc_Objects[i][RC_OBJ_ID] = id index = i break endif next if index < 0 then return rc_ObjectsF[index][RC_OBJ_X] = x rc_ObjectsF[index][RC_OBJ_Z] = z rc_ObjectsF[index][RC_OBJ_Y] = y endproc rem Remove item at (x, z) and its corresponding object. procedure RC_RemoveItem(x, z) if rc_Items[x][z] = 0 then return rc_Items[x][z] = 0 xz = z*rc_MapW + x index = -1 for i = 0 to RC_MAX_OBJECTS - 1 if rc_Objects[i][RC_OBJ_IXY] = xz index = i break endif next if index >= 0 rc_Objects[index][RC_OBJ_ID] = 0 for i = 0 to RC_MAX_OBJECTS - 1 if rc_ObjOrder[i] = index for j = i to rc_ObjCount - 2 rc_ObjOrder[j] = rc_ObjOrder[j + 1] next rc_ObjCount = rc_ObjCount - 1 break endif next rc_Map[x][z] = 0 endif endproc procedure RC_RemoveObject(id) index = -1 for i = 0 to RC_MAX_OBJECTS - 1 if rc_Objects[i][RC_OBJ_ID] = id index = i break endif next if index >= 0 rc_Objects[i][RC_OBJ_ID] = 0 for i = 0 to RC_MAX_OBJECTS - 1 if rc_ObjOrder[i] = index for j = i to rc_ObjCount - 2 rc_ObjOrder[j] = rc_ObjOrder[j + 1] next rc_ObjCount = rc_ObjCount - 1 break endif next endif endproc function RC_HasObject(id) index = -1 for i = 0 to RC_MAX_OBJECTS - 1 if rc_Objects[i][RC_OBJ_ID] = id index = i break endif next if index >= 0 then return true return false endfunc rem ================================================================== rem Process objects before rendering. rem ================================================================== procedure RC_ProcessObjects(xpos#, zpos#, angle#) rem Calculate distance between objects and view point. dx# dz# for i = 0 to RC_MAX_OBJECTS - 1 if rc_Objects[i][RC_OBJ_ID] <> 0 dx = rc_ObjectsF[i][RC_OBJ_X] - xpos dz = rc_ObjectsF[i][RC_OBJ_Z] - zpos rc_ObjectsF[i][RC_OBJ_D] = dx*dx + dz*dz endif next rem Sort the objects. proc RC_SortObjects endproc rem ================================================================== rem Sort objects. rem Yes, bubble sort is used, since the changes in the list are rem usually very small. rem ================================================================== procedure RC_SortObjects() beg = 0 endi = rc_ObjCount - 2 do noswap = true for i = beg to endi if rc_ObjectsF[rc_ObjOrder[i]][RC_OBJ_D] < rc_ObjectsF[rc_ObjOrder[i + 1]][RC_OBJ_D] tmp = rc_ObjOrder[i] rc_ObjOrder[i] = rc_ObjOrder[i + 1] rc_ObjOrder[i + 1] = tmp noswap = false endif next beg = beg + 1 until noswap endproc rem ================================================================== rem Render objects. rem ================================================================== procedure RC_RenderObjects(xpos#, zpos#, angle#) rem Process objects before rendering. proc RC_ProcessObjects xpos, zpos, angle img x y w h d# u_x# u_z# v_x# v_z# hyp# k# dp# a# index for i = 0 to rc_ObjCount - 1 index = rc_ObjOrder[i] if rc_Objects[index][RC_OBJ_ID] = 0 break else img = rc_Objects[index][RC_OBJ_IMG] u_x = cos(angle) u_z = sin(angle) v_x = rc_ObjectsF[index][RC_OBJ_X] - xpos v_z = rc_ObjectsF[index][RC_OBJ_Z] - zpos hyp = sqr(v_x*v_x + v_z*v_z) if not hyp = 0.0 k = 1.0/hyp v_x = v_x*k v_z = v_z*k dp = v_x*u_x + v_z*u_z if dp > 0.1 if dp >= 1.0 a = 0.0 else a = acos(dp) endif if u_x*v_z - u_z*v_x < 0.0 rc_ObjectsF[index][RC_OBJ_TX] = float(rc_Width/2) - rc_Unit*tan(a) else rc_ObjectsF[index][RC_OBJ_TX] = float(rc_Width/2) + rc_Unit*tan(a) endif rc_ObjectsF[index][RC_OBJ_D] = hyp*cos(a) if rc_ObjectsF[index][RC_OBJ_D] < rc_FogMax size# = rc_Unit/rc_ObjectsF[index][RC_OBJ_D] x = int(rc_ObjectsF[index][RC_OBJ_TX] - size*rc_ObjectsF[index][RC_OBJ_W]*0.5) y = int(float(rc_Height/2) + size*rc_ObjectsF[index][RC_OBJ_Y]) d = rc_ObjectsF[index][RC_OBJ_D] w = int(size*rc_ObjectsF[index][RC_OBJ_W]) h = int(size*rc_ObjectsF[index][RC_OBJ_H]) if rc_UseDarkness ix = int(rc_ObjectsF[index][RC_OBJ_X]) iz = int(rc_ObjectsF[index][RC_OBJ_Z]) if ix < 0 or ix >= rc_MapW or iz < 0 or iz >= rc_MapH dark = 0 else dark = rc_Darkness[ix][iz] endif else dark = 0 endif if x + w >= 0 and x < rc_Width proc RC_DrawImage img, x, y, w, h, d, dark endif endif endif endif endif next endproc procedure RC_DrawImage(img, imgx, imgy, w, h, d#, a) alpha = max(int((d - rc_FogMin)*rc_FogSpread), 0) + a set color rc_FogR, rc_FogG, rc_FogB, alpha uStep# = 1.0/float(w) u# = 0.0 if imgx < 0 u = u - uStep*float(imgx); rem hade minus före imgx tidigare. w = w + imgx imgx = 0 endif xend = min(imgx + w, rc_Width) - 1 h = imgy + h for x = imgx to xend if d < rc_ZBuffer[x] draw vraster img, x, imgy, h, u, 0.0, u, 1.0 endif u = u + uStep next endproc rem ================================================================== rem Return wall in front of position. rem ================================================================== function RC_FacingWall(x#, z#, angle#) x# = x# + cos(angle) z# = z# + sin(angle) ix = int(x) iz = int(z) if ix < 0 then return 0 if ix >= rc_MapW then return 0 if iz < 0 then return 0 if iz >= rc_MapH then return 0 return rc_Map[ix][iz] endfunc function RC_FacingPos[](x#, z#, angle#) x# = x# + cos(angle) z# = z# + sin(angle) ix = int(x) iz = int(z) return [ix, iz] endfunc function RC_GetDoor(x, z) if sizeof(rc_Map) = 0 then return 0 if rc_Map[x][z] = -1 or rc_Map[x][z] = -2 return rc_Doors[x][z] endif return 0 endfunc procedure RC_OpenDoor(x, y) isopen = false if RC_GetDoor(x, y) = 0 then return if rc_OpenDoorCount > 0 for i = 0 to rc_OpenDoorCount - 1 if rc_OpenDoors[i][0] = x and rc_OpenDoors[i][1] = y isopen = true break endif next endif if not isopen rc_OpenDoors[rc_OpenDoorCount][0] = x rc_OpenDoors[rc_OpenDoorCount][1] = y rc_OpenDoorCount = rc_OpenDoorCount + 1 endif endproc procedure RC_Update(k#) if rc_OpenDoorCount > 0 for i = 0 to rc_OpenDoorCount - 1 x = rc_OpenDoors[i][0] y = rc_OpenDoors[i][1] if rc_ItemParams[x][y] < 1.0 rc_ItemParams[x][y] = min#(rc_ItemParams[x][y] + rc_DoorSpeed*k, 1.0) endif next endif endproc procedure RC_DrawScaledImage(img, imgx, imgy, w, h) uStep# = 1.0/float(w) u# = 0.0 if imgx < 0 u = u + uStep*float(-imgx) w = w + imgx imgx = 0 endif h = imgy + h - 1 set color 255, 255, 255, 0 for x = imgx to imgx + w - 1 draw vraster img, x, imgy, h, u, 0.0, u, 1.0 u = u + uStep next endproc procedure RC_SetDoor(x, z, type, img, alongZ) if sizeof(rc_Map) = 0 then return if type = 0 rc_Map[x][z] = 0 rc_Items[x][z] = 0 rc_Doors[x][z] = 0 else if alongZ rc_Map[x][z] = -1 else rc_Map[x][z] = -2 endif rc_Items[x][z] = img rc_Doors[x][z] = type endif endproc procedure DebugMsg(msg$) set color 0, 0, 0 cls set color 255, 255, 255 set caret 0, 0 set font 0 wln msg$ redraw wait keydown endproc function RC_LoadMap[][](filename$) flags[][] open file 0, filename$ if not file(0) then return flags for i = len(filename) - 1 downto 0 if mid$(filename, i) = "/" pos = i + 1 break endif next path$ = left$(filename, pos) rem Images. count = read(0) for i = 0 to count - 1 index = read(0) fn$ = read$(0) load image index + 1000, path + fn$ ck = read(0) ckr = read(0) ckg = read(0) ckb = read(0) if ck then set image colorkey index + 1000, ckr, ckg, ckb next rem Objects. objects[64][4] count = read(0) for i = 0 to count - 1 index = read(0) objects[index][0] = read(0) objects[index][1] = read(0) objects[index][2] = read(0) objects[index][3] = read(0) next rem Fog. fogActive = read(0) fogR = read(0) fogG = read(0) fogB = read(0) fogZMin# = read#(0) fogZMax# = read#(0) rem Map. mapW = read(0) mapH = read(0) map[mapW][mapH][6] for i = 0 to 5 for z = 0 to mapH - 1 for x = 0 to mapW - 1 map[x][z][i] = read(0) next next next playerX = read(0) playerZ = read(0) playerAngle = read(0) free file 0 proc RC_SetFog fogR, fogG, fogB, fogZMin, fogZMax proc RC_InitMap mapW, mapH WALL = 0 FLOOR = 1 CEILING = 2 OBJECT = 3 GAME_FLAG = 4 LOADER_FLAG = 5 flagCount = 0 for z = 0 to mapH - 1 for x = 0 to mapW - 1 if map[x][z][LOADER_FLAG] then flagCount = flagCount + 1 if map[x][z][WALL] if map[x][z][WALL] = -1 proc RC_SetDoor x, z, -map[x][z][OBJECT], 1000 - map[x][z][OBJECT], true elseif map[x][z][WALL] = -2 proc RC_SetDoor x, z, -map[x][z][OBJECT], 1000 - map[x][z][OBJECT], false else proc RC_SetWall x, z, map[x][z][WALL] + 1000 endif endif if map[x][z][FLOOR] proc RC_SetFloor x, z, map[x][z][FLOOR] + 1000 endif if map[x][z][CEILING] proc RC_SetCeiling x, z, map[x][z][CEILING] + 1000 endif proc RC_SetFlag x, z, map[x][z][GAME_FLAG] if map[x][z][OBJECT] and map[x][z][WALL] = 0 obj = map[x][z][OBJECT] rem [index][image, align, obstacle, size] img = objects[obj][0] if img and image(img + 1000) img = img + 1000 s# = float(objects[obj][3])/1000.0 if width(img) > height(img) h# = s*float(height(img))/float(width(img)) w# = s*1.0 else w# = s*float(width(img))/float(height(img)) h# = s*1.0 endif if objects[obj][1] = 0; rem Floor. y# = 0.0 elseif objects[obj][1] = 1; rem Centered. y# = 0.5 + h*0.5 else; rem Ceiling. y# = 1.0 + h endif if objects[obj][2] then proc RC_SetWall x, z, -3 proc RC_AddObject -1, img, float(x) + 0.5, float(z) + 0.5, y, s, x, z proc RC_SetItem x, z, map[x][z][OBJECT], false endif endif next next flags[flagCount + 1][3] flags[0][0] = playerX flags[0][1] = playerZ flags[0][2] = playerAngle index = 1 for z = 0 to mapH - 1 for x = 0 to mapW - 1 if map[x][z][LOADER_FLAG] flags[index][0] = x flags[index][1] = z flags[index][2] = map[x][z][LOADER_FLAG] index = index + 1 endif next next return flags endfunc function RC_GetImage(id) return id + 1000 endfunc rem ================================================================== rem Return true if there's no obstacle between (x0, z0) and (x1, z1). rem ================================================================== function RC_Visible(xpos#, zpos#, dstx#, dstz#) if sizeof(rc_Map) = 0 then return false xdistance# zdistance# xposi zposi xposf# zposf# dzdx_inv# dxdz_inv# hdzdx_inv# hdxdz_inv# y wt dzdx_inv# dxdz_inv# xfailed zfailed xoffs# zoffs# ysize alpha id itm col = 0 dx# = dstx - xpos dz# = dstz - zpos distance# = sqr(dx*dx + dz*dz) if distance <= 0.0 then return true k# = 1.0/distance dx = dx*k dz = dz*k if dx <> 0.0 dzdx_inv = dz/dx hdzdx_inv = dzdx_inv*0.5 endif if dz <> 0.0 dxdz_inv = dx/dz hdxdz_inv = dxdz_inv*0.5 endif xdistance = 0.0 zdistance = 0.0 rem Cast x ray. xposi = int(xpos) xfailed = false if dx < 0.0 xposi = xposi - 1 xposf = float(xposi) + 1.0 zposf = (xposf - xpos)*dzdx_inv + zpos zposi = int(zposf) if zposi < 0 or zposi >= rc_MapH xfailed = true xdistance = 100000.0 else id = rc_Map[xposi][zposi] xoffs = 0.0 while id <= 0 door = false if id = -1 reg4# = zposf - hdzdx_inv if int(reg4) = zposi xoffs# = rc_ItemParams[xposi][zposi] if int(reg4 - xoffs) = zposi door = true zposf = reg4 xposf = float(xposi + 1) - 0.5 id = rc_Items[xposi][zposi] break endif endif endif xoffs# = 0.0 xposi = xposi - 1 zposf = zposf - dzdx_inv zposi = int(zposf) if zposi < 0 or zposi >= rc_MapH or xposi < 0 xfailed = true xdistance = 100000.0 break endif id = rc_Map[xposi][zposi] wend if not door xposf = float(xposi) + 1.0 endif if not xfailed xdistance = (xposf - xpos)*(xposf - xpos) + (zposf - zpos)*(zposf - zpos) endif endif elseif dx > 0.0 xposi = xposi + 1 xposf = float(xposi) zposf = (xposf - xpos)*dzdx_inv + zpos zposi = int(zposf) if zposi < 0 or zposi >= rc_MapH xfailed = true xdistance = 100000.0 else id = rc_Map[xposi][zposi] xoffs = 0.0 while id <= 0 door = false if id = -1 reg4# = zposf + hdzdx_inv if int(reg4) = zposi xoffs# = rc_ItemParams[xposi][zposi] if int(reg4 - xoffs) = zposi door = true zposf = reg4 xposf = float(xposi + 1) - 0.5 id = rc_Items[xposi][zposi] break endif endif endif xoffs = 0.0 xposi = xposi + 1 zposf = zposf + dzdx_inv zposi = int(zposf) if zposi < 0 or zposi >= rc_MapH or xposi >= rc_MapW xfailed = true xdistance = 100000.0 break endif id = rc_Map[xposi][zposi] wend if not door xposf = float(xposi) endif if not xfailed xdistance = (xposf - xpos)*(xposf - xpos) + (zposf - zpos)*(zposf - zpos) endif endif else xfailed = true xdistance = 100000.0 endif rem Cast z ray zposi = int(zpos) zfailed = false if dz < 0.0 zposi = zposi - 1 zposf = float(zposi) + 1.0 xposf = (zposf - zpos)*dxdz_inv + xpos xposi = int(xposf) if xposi < 0 or xposi >= rc_MapW zfailed = true zdistance = 100000.0 else id = rc_Map[xposi][zposi] zoffs = 0.0 while id <= 0 door = false if id = -2 reg4# = xposf - hdxdz_inv if int(reg4) = xposi zoffs# = rc_ItemParams[xposi][zposi] if int(reg4 - zoffs) = xposi door = true xposf = reg4 zposf = float(zposi + 1) - 0.5 id = rc_Items[xposi][zposi] break endif endif endif zoffs# = 0.0 zposi = zposi - 1 xposf = xposf - dxdz_inv xposi = int(xposf) if xposi < 0 or xposi >= rc_MapW or zposi < 0 zfailed = true zdistance = 100000.0 break endif id = rc_Map[xposi][zposi] wend if not door zposf = float(zposi) + 1.0 endif if not zfailed zdistance = (xposf - xpos)*(xposf - xpos) + (zposf - zpos)*(zposf - zpos) endif endif elseif dz > 0.0 zposi = zposi + 1 zposf = float(zposi) xposf = (zposf - zpos)*dxdz_inv + xpos xposi = int(xposf) if xposi < 0 or xposi >= rc_MapW zfailed = true zdistance = 100000.0 else id = rc_Map[xposi][zposi] zoffs = 0.0 while id <= 0 door = false if id = -2 reg4# = xposf + hdxdz_inv if int(reg4) = xposi zoffs# = rc_ItemParams[xposi][zposi] if int(reg4 - zoffs) = xposi door = true xposf = reg4 zposf = float(zposi + 1) - 0.5 id = rc_Items[xposi][zposi] break endif endif endif zoffs = 0.0 zposi = zposi + 1 xposf = xposf + dxdz_inv xposi = int(xposf) if xposi < 0 or xposi >= rc_MapW or zposi >= rc_MapH zfailed = true zdistance = 100000.0 break endif id = rc_Map[xposi][zposi] wend if not door zposf = float(zposi) endif if not zfailed zdistance = (xposf - xpos)*(xposf - xpos) + (zposf - zpos)*(zposf - zpos) endif endif else zfailed = true zdistance = 100000.0 endif if xdistance < zdistance if sqr(xdistance) < distance then return false else if sqr(zdistance) < distance then return false endif return true endfunc