rem ================================================================== rem ================================================================== rem DU kan plocka bort en massa från beräkningen av u i wallcast, rem eftersom texturens bredd inte längre är aktuell i naalaa. 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[][] 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_X 2 RC_OBJ_Z 3 RC_OBJ_Y 4 RC_OBJ_TX 5 RC_OBJ_TZ 6 RC_OBJ_W 7 RC_OBJ_H 8 RC_OBJ_D 9 RC_OBJ_IXY 10 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][11] 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] proc RC_ClearObjects proc RC_ClearDoors endproc function RC_GetMapWidth() return rc_MapW endproc function RC_GetMapHeight() return rc_MapH endfunc 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 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 rc_ObjOrder[RC_MAX_OBJECTS] for i = 0 to RC_MAX_OBJECTS - 1 MOV# @0 rc_Objects MOV @1 i MUL @1 11 STP# @0 @1 MOV [@0] 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# 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 MOV# dzdx_inv dz DIV# dzdx_inv dx MOV# hdzdx_inv dzdx_inv MUL# hdzdx_inv 0.5 endif if dz <> 0.0 MOV# dxdz_inv dx DIV# dxdz_inv dz MOV# hdxdz_inv dxdz_inv MUL# hdxdz_inv 0.5 endif MOV# xdistance 0.0 MOV# zdistance 0.0 rem Cast x ray. xposi = int(xpos) if dx = 0.0 JMP dx_failed elseif dx < 0.0 SUB xposi 1 MOV @0 xposi ITF @0 ADD# @0 1.0 MOV# xposf @0 MOV# zposf xposf SUB# zposf xpos MUL# zposf dzdx_inv ADD# zposf zpos rem zposi = int(zposf) MOV# @0 zposf FTI @0 MOV zposi @0 CMP zposi 0 JL dx_failed CMP zposi rc_MapH JGE dx_failed rem if zposi < 0 or zposi >= rc_MapH rem JMP dx_failed rem else MOV @2 xposi MOV @3 zposi MOV @0 rc_Map MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] MOV# @5 0.0 @dxn_loop: CMP id 0 JG dxn_end rem ========== MOV @0 0 SUB @0 1 CMP id @0 JNE dxn_no_door MOV# @4 zposf SUB# @4 hdzdx_inv MOV# @0 @4 FTI @0 CMP @3 @0 JNE dxn_no_door rem get door param MOV# @0 @4 MOV# @5 rc_ItemParams MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP# @5 @1 MOV# @5 [@5] SUB# @0 @5 FTI @0 CMP @3 @0 JNE dxn_no_door MOV# zposf @4 MOV @0 @2 ADD @0 1 ITF @0 MOV# xposf @0 SUB# xposf 0.5 MOV @0 rc_Items MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] MOV xposi @2 MOV zposi @3 JMP dxn_door_hit @dxn_no_door: MOV# @5 0.0; rem no offset rem ========== SUB @2 1 SUB# zposf dzdx_inv MOV# @0 zposf FTI @0 MOV @3 @0 CMP @3 0 JL dx_failed CMP @3 rc_MapH JGE dx_failed MOV @0 rc_Map MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] JMP dxn_loop @dxn_end: MOV xposi @2 MOV zposi @3 rem xposf = float(xposi) + 1.0 MOV @0 xposi ADD @0 1 ITF @0 MOV# xposf @0 @dxn_door_hit: MOV xtexture id rem xutex = int((zposf - float(zposi))*float(width(xtexture))) xutex = width(xtexture) MOV @1 zposi ITF @1 MOV# @0 zposf SUB# @0 @5 SUB# @0 @1 MOV @1 xutex ITF @1 MUL# @0 @1 FTI @0 SUB xutex 1 SUB xutex @0 MOV# @0 xposf SUB# @0 xpos MUL# @0 @0 MOV# @1 zposf SUB# @1 zpos MUL# @1 @1 ADD# @0 @1 MOV# xdistance @0 JMP dx_done else ADD xposi 1 xposf = float(xposi) MOV# @0 xposf SUB# @0 xpos MUL# @0 dzdx_inv ADD# @0 zpos MOV# zposf @0 MOV# @0 zposf FTI @0 MOV zposi @0 rem if zposi < 0 or zposi >= rc_MapH rem JMP dx_failed rem else CMP zposi 0 JL dx_failed CMP zposi rc_MapH JGE dx_failed MOV @2 xposi MOV @3 zposi MOV @0 rc_Map MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] MOV# @5 0.0 @dxp_loop: CMP id 0 JG dxp_end rem ========== MOV @0 0 SUB @0 1 CMP id @0 JNE dxp_no_door MOV# @4 zposf ADD# @4 hdzdx_inv MOV# @0 @4 FTI @0 CMP @3 @0 JNE dxp_no_door rem get door param MOV# @0 @4 MOV# @5 rc_ItemParams MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP# @5 @1 MOV# @5 [@5] SUB# @0 @5 FTI @0 CMP @3 @0 JNE dxp_no_door MOV# zposf @4 MOV @0 @2 ADD @0 1 ITF @0 MOV# xposf @0 SUB# xposf 0.5 MOV @0 rc_Items MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] MOV xposi @2 MOV zposi @3 JMP dxp_door_hit @dxp_no_door: MOV# @5 0.0; rem no offset rem ========== ADD @2 1 ADD# zposf dzdx_inv MOV# @0 zposf FTI @0 MOV @3 @0 CMP @3 0 JL dx_failed CMP @3 rc_MapH JGE dx_failed MOV @0 rc_Map MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] JMP dxp_loop @dxp_end: MOV xposi @2 MOV zposi @3 rem xposf = float(xposi) MOV @0 xposi ITF @0 MOV# xposf @0 @dxp_door_hit: MOV xtexture id rem xutex = width(xtexture) - 1 - int((zposf - float(zposi))*float(width(xtexture))) xutex = width(xtexture) MOV @0 xutex ITF @0 MOV# @1 zposf SUB# @1 @5; rem !!!!!!!!!!! MOV @2 zposi ITF @2 SUB# @1 @2 MUL# @0 @1 FTI @0 MOV xutex @0 MOV# xdistance xposf SUB# xdistance xpos MUL# xdistance xdistance MOV# @0 zposf SUB# @0 zpos MUL# @0 @0 ADD# xdistance @0 JMP dx_done rem endif endif @dx_failed: MOV# xdistance 100000.0 @dx_done: rem Cast z ray zposi = int(zpos) if dz = 0.0 rem MOV# zdistance 100000.0 JMP dz_failed elseif dz < 0.0 SUB zposi 1 rem zposf = float(zposi) + 1.0 MOV @0 zposi ADD @0 1 ITF @0 MOV# zposf @0 MOV# xposf zposf SUB# xposf zpos MUL# xposf dxdz_inv ADD# xposf xpos rem xposi = int(xposf) MOV# @0 xposf FTI @0 MOV xposi @0 rem if xposi < 0 or xposi >= rc_MapW rem JMP dz_failed rem else CMP xposi 0 JL dz_failed CMP xposi rc_MapW JGE dz_failed MOV @2 xposi MOV @3 zposi MOV @0 rc_Map MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] MOV# @5 0.0 @dzn_loop: CMP id 0 JG dzn_end rem ========== MOV @0 0 SUB @0 2 CMP id @0 JNE dzn_no_door MOV# @4 xposf SUB# @4 hdxdz_inv MOV# @0 @4 FTI @0 CMP @2 @0 JNE dzn_no_door rem get door param MOV# @0 @4 MOV# @5 rc_ItemParams MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP# @5 @1 MOV# @5 [@5] SUB# @0 @5 FTI @0 CMP @2 @0 JNE dzn_no_door MOV# xposf @4 MOV @0 @3 ADD @0 1 ITF @0 MOV# zposf @0 SUB# zposf 0.5 MOV @0 rc_Items MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] MOV xposi @2 MOV zposi @3 JMP dzn_door_hit @dzn_no_door: MOV# @5 0.0; rem no offset rem ========== SUB @3 1 SUB# xposf dxdz_inv MOV# @0 xposf FTI @0 MOV @2 @0 CMP @2 0 JL dz_failed CMP @2 rc_MapW JGE dz_failed MOV @0 rc_Map MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] JMP dzn_loop @dzn_end: MOV xposi @2 MOV zposi @3 MOV @0 zposi ADD @0 1 ITF @0 MOV# zposf @0 @dzn_door_hit: MOV ztexture id zutex = width(ztexture) MOV @0 zutex ITF @0 MOV# @1 xposf SUB# @1 @5 MOV @2 xposi ITF @2 SUB# @1 @2 MUL# @0 @1 FTI @0 MOV zutex @0 MOV# zdistance xposf SUB# zdistance xpos MUL# zdistance zdistance MOV# @0 zposf SUB# @0 zpos MUL# @0 @0 ADD# zdistance @0 JMP dz_done rem endif else ADD zposi 1 rem zposf = float(zposi) MOV @0 zposi ITF @0 MOV# zposf @0 MOV# xposf zposf SUB# xposf zpos MUL# xposf dxdz_inv ADD# xposf xpos rem xposi = int(xposf) MOV# @0 xposf FTI @0 MOV xposi @0 rem if xposi < 0 or xposi >= rc_MapW rem JMP dz_failed rem else CMP xposi 0 JL dz_failed CMP xposi rc_MapW JGE dz_failed MOV @2 xposi MOV @3 zposi MOV @0 rc_Map MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] MOV# @5 0.0 @dzp_loop: CMP id 0 JG dzp_end rem ========== MOV @0 0 SUB @0 2 CMP id @0 JNE dzp_no_door MOV# @4 xposf ADD# @4 hdxdz_inv MOV# @0 @4 FTI @0 CMP @2 @0 JNE dzp_no_door rem get door param MOV# @0 @4 MOV# @5 rc_ItemParams MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP# @5 @1 MOV# @5 [@5] SUB# @0 @5 FTI @0 CMP @2 @0 JNE dzp_no_door MOV# xposf @4 MOV @0 @3 ADD @0 1 ITF @0 MOV# zposf @0 SUB# zposf 0.5 MOV @0 rc_Items MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] MOV xposi @2 MOV zposi @3 JMP dzp_door_hit @dzp_no_door: MOV# @5 0.0; rem no offset rem ========== ADD @3 1 ADD# xposf dxdz_inv MOV# @0 xposf FTI @0 MOV @2 @0 CMP @2 0 JL dz_failed CMP @2 rc_MapW JGE dz_failed MOV @0 rc_Map MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] JMP dzp_loop @dzp_end: MOV xposi @2 MOV zposi @3 rem zposf = float(zposi) MOV @0 zposi ITF @0 MOV# zposf @0 @dzp_door_hit: MOV ztexture id rem zutex = int((xposf - float(xposi))*float(width(ztexture))) zutex = width(ztexture) MOV @1 xposi ITF @1 MOV# @0 xposf SUB# @0 @5 SUB# @0 @1 MOV @1 zutex ITF @1 MUL# @0 @1 FTI @0 SUB zutex 1 SUB zutex @0 MOV# zdistance xposf SUB# zdistance xpos MUL# zdistance zdistance MOV# @0 zposf SUB# @0 zpos MUL# @0 @0 ADD# zdistance @0 JMP dz_done endif @dz_failed: MOV# zdistance 100000.0 @dz_done: if xdistance < zdistance MOV t xtexture xdistance = sqr(xdistance)*rc_AngleOffsetCos[col] rc_ZBuffer[col] = xdistance rem ysize = int(rc_Unit/xdistance)/2 MOV# @0 rc_Unit DIV# @0 xdistance FTI @0 DIV @0 2 MOV ysize @0 MOV texu xutex rem Darkness. MOV# @1 xdistance SUB# @1 rc_FogMin MUL# @1 rc_FogSpread FTI @1 rem MOV alpha 255 rem SUB alpha @1 MOV alpha @1 else MOV t ztexture zdistance = sqr(zdistance)*rc_AngleOffsetCos[col] rc_ZBuffer[col] = zdistance rem ysize = int(rc_Unit/zdistance)/2 MOV# @0 rc_Unit DIV# @0 zdistance FTI @0 DIV @0 2 MOV ysize @0 MOV texu zutex rem Darkness MOV# @1 zdistance SUB# @1 rc_FogMin MUL# @1 rc_FogSpread FTI @1 rem MOV alpha 255 rem SUB alpha @1 MOV alpha @1 endif if alpha < 255 set color rc_FogR, rc_FogG, rc_FogB, alpha MOV y rc_Height DIV y 2 SUB y ysize rem draw vraster t, texu, col, y, ysize*2 rem procedure VRASTER(img, ustart#, vstart#, uend#, vend#, x, ystart, yend) draw vraster t, col, y, y +ysize*2, float(texu)/float(width(t)), 0.0, float(texu)/float(width(t)), 1.0 endif ADD 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]) MOV# dx xend SUB# dx xstart MOV# dz zend SUB# dz zstart rem d# = sqr(dx*dx + dz*dz) MOV# d dx MUL# d d MOV# @0 dz MUL# @0 @0 ADD# d @0 d# = sqr(d) MOV# @0 1.0 DIV# @0 d MUL# dx @0 MUL# dz @0 MOV# screenxstart 0.0 MOV @0 w ITF @0 DIV# @0 d MOV# screendx @0 MOV# @0 xstart FTI @0 MOV xi @0 MOV# @0 zstart FTI @0 MOV zi @0 MOV# ustart xstart MOV# @0 xstart FTI @0 ITF @0 SUB# ustart @0 MOV# vstart zstart MOV# @0 zstart FTI @0 ITF @0 SUB# vstart @0 rem Fog. MOV @3 rc_Height DIV @3 2 MOV @2 rc_Width DIV @2 2 MUL @2 @3 ADD @2 y MOV# @1 rc_Distance STP# @1 @2 MOV# @1 [@1] SUB# @1 rc_FogMin MUL# @1 rc_FogSpread FTI @1 MOV alpha @1 if y >= hh or alpha >= 255 break else set color rc_FogR, rc_FogG, rc_FogB, alpha endif rem MOVE SOME STUFF TO REGISTERS, YOU FOOL!! @fc_row_loop: MOV oldxi xi MOV oldzi zi rem dx step. CMP# dx 0.0 JE# no_dx JG# dxp rem dx < 0 CMP oldxi 0 JL fc_row_loop_end SUB xi 1 MOV @0 xi ADD @0 1 ITF @0 MOV# xf @0 MOV# xk xf SUB# xk xstart DIV# xk dx JMP dx_end @dxp: rem dx > 0 CMP oldxi rc_MapW JGE fc_row_loop_end ADD xi 1 MOV @0 xi ITF @0 MOV# xf @0 MOV# xk xf SUB# xk xstart DIV# xk dx JMP dx_end @no_dx: MOV# xk 100000.0 @dx_end: rem dz step. CMP# dz 0.0 JE# no_dz JG# dzp rem dz < 0 CMP oldzi 0 JL fc_row_loop_end SUB zi 1 MOV @0 zi ADD @0 1 ITF @0 MOV# zf @0 MOV# zk zf SUB# zk zstart DIV# zk dz JMP dz_end @dzp: rem dz > 0 CMP oldzi rc_MapH JGE fc_row_loop_end ADD zi 1 MOV @0 zi ITF @0 MOV# zf @0 MOV# zk zf SUB# zk zstart DIV# zk dz JMP dz_end @no_dz: MOV# zk 100000.0 @dz_end: CMP# xk zk JG# fc_zk rem if xk < zk CMP# dz 0.0 JE# fc_dz_no_step JGE# fc_dz_neg_step ADD zi 1 JMP fc_dz_no_step @fc_dz_neg_step: SUB zi 1 @fc_dz_no_step: CMP# dx 0.0 JG# fc_uone MOV# uend 0.0 JMP fc_udone @fc_uone: MOV# uend 1.0 @fc_udone: MOV# xend xf MOV# zend xk MUL# zend dz ADD# zend zstart MOV# vend zend MOV# @0 zend FTI @0 ITF @0 SUB# vend @0 MOV# screenxend xk MUL# screenxend screendx ADD# screenxend screenxstart JMP fc_zdone rem else @fc_zk: CMP# dx 0.0 JE# fc_dx_no_step JGE# fc_dx_neg_step ADD xi 1 JMP fc_dx_no_step @fc_dx_neg_step: SUB xi 1 @fc_dx_no_step: CMP# dz 0.0 JG# fc_vone MOV# vend 0.0 JMP fc_vdone @fc_vone: MOV# vend 1.0 @fc_vdone: MOV# zend zf MOV# xend zk MUL# xend dx ADD# xend xstart MOV# uend xend MOV# @0 xend FTI @0 ITF @0 SUB# uend @0 MOV# screenxend zk MUL# screenxend screendx ADD# screenxend screenxstart rem endif @fc_zdone: CMP oldxi 0 JL no_ceiling_draw CMP oldxi rc_MapW JGE no_ceiling_draw CMP oldzi 0 JL no_ceiling_draw CMP oldzi rc_MapH JGE no_ceiling_draw { MOV @0 rc_Map MOV @1 oldxi MUL @1 rc_MapH ADD @1 oldzi STP @0 @1 CMP [@0] 0} MOV @1 oldxi MUL @1 rc_MapH ADD @1 oldzi MOV @0 rc_Floor STP @0 @1 CMP [@0] 0 JLE no_floor_draw PSH @1 MOV id [@0] draw hraster id, h - 1 - y, int(screenxstart), int(screenxend), ustart, vstart, uend, vend POP @1 @no_floor_draw: MOV @0 rc_Ceiling STP @0 @1 CMP [@0] 0 JLE no_ceiling_draw MOV id [@0] draw hraster id, y, int(screenxstart), int(screenxend), ustart, vstart, uend, vend @no_ceiling_draw: MOV# xstart xend MOV# zstart zend MOV# screenxstart screenxend rem Wrap u texture coordinate. CMP# uend 0.0 JE# fc_u_zero CMP# uend 1.0 JE# fc_u_one MOV# ustart uend JMP fc_u_done @fc_u_zero: MOV# ustart 1.0 JMP fc_u_done @fc_u_one: MOV# ustart 0.0 @fc_u_done: rem Wrap v texture coordinate. CMP# vend 0.0 JE# fc_v_zero CMP# vend 1.0 JE# fc_v_one MOV# vstart vend JMP fc_v_done @fc_v_zero: MOV# vstart 1.0 JMP fc_v_done @fc_v_one: MOV# vstart 0.0 @fc_v_done: MOV @0 w ITF @0 CMP# screenxend @0 JGE# fc_row_loop_end JMP fc_row_loop @fc_row_loop_end: ADD 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 rem En objektbeskrivning, bara info om en bild, behöver: rem x rem z rem xtransformed rem ztransformed rem y rem avstånd rem bredd rem höjd rem bild rem rem Det är inte den typen av data man bara skyflar runt och rem kan sortera i naalaa. rem Jag föreslår att alla objekt ligger statiskt i en lista. rem Givetvis kan användaren plocka bort, lägga till och flytta rem objekt. Många objekt är dock bundna till items på något rem vis. rem Du har, som i SimpleWidget, en lista som sorteras rem vid varje rendering med index till den statiska listan. rem rem En fundering: Om ett objekt inte får vara större än 1.0 och rem varken dess vänstra eller högra kant har ett synligt distance, rem kan då någon del av objektet vara synligt? Nej, jag tror rem fanimig inte det. rem Vid sorteringen skall du: rem Plocka bort objekt som har ett distance >= fogMax rem Plocka bort objekt där både höger och vänster är osynliga, rem och här ingår givetvis sådant som faller utanför syn- rem vinkeln rem Sortera efter avstånd rem Så, orörliga objekt kommer från levelfilen. rem Användaren kan lägga till, ändra och ta bort objekt, vilket rem kräver ID. rem Ev lägger användaren redan från början in alla de objekt rem som behövs, typ fiender och spelarskott men kan sedan av- rem aktivera dem o.s.v.via deras ID. Då slipper du böka runt i rem listan. rem Eller nej. Ej bestämma i förväg. Man kan lägga till och rem plocka bort. Men listan "defragmenteras" aldrig, utan det rem finns ett utrymme efter de statiska objekten där objekt rem helt enkelt får första bästa plats ... procedure RC_AddObject(id, img, x#, z#, y#, s#, ix, iz) rem Nödvändigt att kolla efter dubletter? 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 for i = 0 to RC_MAX_OBJECTS - 1 MOV# @0 rc_Objects MOV @1 i MUL @1 11 STP# @0 @1 CMP [@0] 0 JNE rc_ao_no_obj MOV index i break @rc_ao_no_obj: next if index >= 0 rem Move to index. MOV# @0 rc_Objects MOV @1 index MUL @1 11 STP# @0 @1 rem Set values. MOV [@0] id STP# @0 1 MOV [@0] img STP# @0 1 MOV# [@0] x STP# @0 1 MOV# [@0] z STP# @0 1 MOV# [@0] y STP# @0 3 MOV# [@0] w STP# @0 1 MOV# [@0] h STP# @0 2 MOV @2 iz MUL @2 rc_MapW ADD @2 ix MOV [@0] @2 rc_ObjOrder[rc_ObjCount] = index ADD rc_ObjCount 1 endif endproc procedure RC_ModifyObject(id, img, x#, z#, y#) index = -1 for i = 0 to RC_MAX_OBJECTS - 1 MOV# @0 rc_Objects MOV @1 i MUL @1 11 STP# @0 @1 CMP [@0] id JNE rc_mo_no_obj MOV index i break @rc_mo_no_obj: next if index >= 0 y = 0.5 - y - rc_Objects[index][RC_OBJ_H] rem Move to index. MOV# @0 rc_Objects MOV @1 index MUL @1 11 ADD @1 1 STP# @0 @1 rem Set values. MOV [@0] img STP# @0 1 MOV# [@0] x STP# @0 1 MOV# [@0] z STP# @0 1 MOV# [@0] y endif endproc procedure RC_SetObjectImage(id, img) index = -1 for i = 0 to RC_MAX_OBJECTS - 1 MOV# @0 rc_Objects MOV @1 i MUL @1 11 STP# @0 @1 CMP [@0] id JNE rc_soi_no_obj MOV index i break @rc_soi_no_obj: next if index >= 0 rem Move to index. MOV# @0 rc_Objects MOV @1 index MUL @1 11 ADD @1 1 STP# @0 @1 rem Set values. MOV [@0] img endif endproc procedure RC_SetObjectPos(id, x#, z#, y#) index = -1 for i = 0 to RC_MAX_OBJECTS - 1 MOV# @0 rc_Objects MOV @1 i MUL @1 11 STP# @0 @1 CMP [@0] id JNE rc_sop_no_obj MOV index i break @rc_sop_no_obj: next if index >= 0 y = 0.5 - y - rc_Objects[index][RC_OBJ_H] rem Move to index. MOV# @0 rc_Objects MOV @1 index MUL @1 11 ADD @1 2 STP# @0 @1 rem Set values. MOV# [@0] x STP# @0 1 MOV# [@0] z STP# @0 1 MOV# [@0] y endif 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 MOV# @0 rc_Objects MOV @1 i MUL @1 11 ADD @1 10 STP# @0 @1 CMP [@0] xz JNE rc_ri_no_obj MOV index i break @rc_ri_no_obj: next if index >= 0 MOV# @0 rc_Objects MOV @1 index MUL @1 11 STP# @0 @1 MOV [@0] 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 MOV# @0 rc_Objects MOV @1 i MUL @1 11 STP# @0 @1 CMP [@0] id JNE rc_ro_no_obj MOV index i break @rc_ro_no_obj: next if index >= 0 rem Move to index. MOV# @0 rc_Objects MOV @1 index MUL @1 11 STP# @0 @1 MOV [@0] 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 MOV# @0 rc_Objects MOV @1 i MUL @1 11 STP# @0 @1 CMP [@0] id JNE rc_ho_no_obj MOV index i break @rc_ho_no_obj: 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 MOV# @0 rc_Objects MOV @1 i MUL @1 11 STP# @0 @1 CMP [@0] 0 JE rc_po_d_no_obj rem dx. STP# @0 2 MOV# @1 [@0]; rem obj x. SUB# @1 xpos MUL# @1 @1 rem dy. STP# @0 1 MOV# @2 [@0]; rem obj y. SUB# @2 zpos MUL# @2 @2 ADD# @1 @2 rem d. STP# @0 6 MOV# [@0] @1 @rc_po_d_no_obj: 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_Objects[rc_ObjOrder[i]][RC_OBJ_D] < rc_Objects[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 } beg = 0 endi = rc_ObjCount - 2 noswap @rc_so_loop: MOV noswap 1 MOV @5 beg @rc_so_sort: MOV @1 rc_ObjOrder STP @1 @5 PSH @1 MOV @1 [@1] MUL @1 11 ADD @1 9 MOV @2 rc_ObjOrder STP @2 @5 STP @2 1 PSH @2 MOV @2 [@2] MUL @2 11 ADD @2 9 MOV# @0 rc_Objects STP# @0 @1 MOV# @1 [@0] MOV# @0 rc_Objects STP# @0 @2 MOV# @2 [@0] CMP# @1 @2 JGE# rc_so_no_swap MOV noswap 0 POP @2 POP @1 MOV @3 [@2] MOV [@2] [@1] MOV [@1] @3 JMP rc_so_swap_done @rc_so_no_swap: POP @0 POP @0 @rc_so_swap_done: ADD @5 1 CMP @5 endi JLE rc_so_sort ADD beg 1 CMP noswap 1 JNE rc_so_loop 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 MOV @1 rc_ObjOrder STP @1 i MOV @1 [@1] MOV index @1 MUL @1 11 MOV# @0 rc_Objects STP# @0 @1 rem Check if object is active. CMP [@0] 0 JE rc_ro_break rem Transform. STP# @0 1 MOV img [@0] u_x = cos(angle) u_z = sin(angle) v_x = rc_Objects[index][RC_OBJ_X] - xpos v_z = rc_Objects[index][RC_OBJ_Z] - zpos hyp = sqr(v_x*v_x + v_z*v_z) CMP# hyp 0.0 JE rc_ro_continue k = 1.0/hyp MUL# v_x k MUL# v_z k dp = v_x*u_x + v_z*u_z if dp <= 0.1 JMP rc_ro_continue endif if dp >= 1.0 a = 0.0 else a = acos(dp) endif if u_x*v_z - u_z*v_x < 0.0 rc_Objects[index][RC_OBJ_TX] = float(rc_Width/2) - rc_Unit*tan(a) else rc_Objects[index][RC_OBJ_TX] = float(rc_Width/2) + rc_Unit*tan(a) endif rc_Objects[index][RC_OBJ_D] = hyp*cos(a) if rc_Objects[index][RC_OBJ_D] >= rc_FogMax JMP rc_ro_continue endif size# = rc_Unit/rc_Objects[index][RC_OBJ_D] x = int(rc_Objects[index][RC_OBJ_TX] - size*rc_Objects[index][RC_OBJ_W]*0.5) y = int(float(rc_Height/2) + size*rc_Objects[index][RC_OBJ_Y]) d = rc_Objects[index][RC_OBJ_D] w = int(size*rc_Objects[index][RC_OBJ_W]) h = int(size*rc_Objects[index][RC_OBJ_H]) if x + w < 0 or x >= rc_Width JMP rc_ro_continue endif proc RC_DrawImage img, x, y, w, h, d JMP rc_ro_continue @rc_ro_break: break @rc_ro_continue: next endproc procedure RC_DrawImage(img, imgx, imgy, w, h, d#) alpha MOV# @1 d SUB# @1 rc_FogMin MUL# @1 rc_FogSpread FTI @1 MOV alpha @1 set color rc_FogR, rc_FogG, rc_FogB, alpha rem uStep# = float(width(img))/float(w) uStep# = 1.0/float(w) u# = 0.0 if imgx < 0 u = u + uStep*float(-imgx) w = w + imgx imgx = 0 endif xend = min(imgx + w, rc_Width) h = imgy + h x MOV @0 imgx MOV# @1 rc_ZBuffer STP# @1 @0 @rc_di_loop: CMP @0 xend JGE rc_di_loop_end CMP# d [@1] JG# rc_di_no_draw MOV x @0 PSH @0 PSH @1 rem draw vraster img, int(u), x, imgy, h rem draw vraster t, col, y, y +ysize*2, float(texu)/float(width(t)), 0.0, float(texu)/float(width(t)), 1.0 draw vraster img, x, imgy, h, u, 0.0, u, 1.0 POP @1 POP @0 @rc_di_no_draw: ADD @0 1 STP# @1 1 ADD# u uStep JMP rc_di_loop @rc_di_loop_end: 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 rem rcOpenDoorCount = 0 rem rc_OpenDoors[RC_MAX_DOORS][2] 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 ADD 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 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) = "/" or 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) load image index + 1000, path + read$(0) 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#) dzdx_inv# hdzdx_inv# dxdz_inv# hdxdz_inv# xdistance# zdistance# xposi zposi xposf# zposf# id dx# = dstx - xpos dz# = dstz - zpos distance# = dx*dx + dz*dz k# = 1.0/sqr(distance) dx = dx*k dz = dz*k if dx <> 0.0 MOV# dzdx_inv dz DIV# dzdx_inv dx MOV# hdzdx_inv dzdx_inv MUL# hdzdx_inv 0.5 endif if dz <> 0.0 MOV# dxdz_inv dx DIV# dxdz_inv dz MOV# hdxdz_inv dxdz_inv MUL# hdxdz_inv 0.5 endif MOV# xdistance 0.0 MOV# zdistance 0.0 rem Cast x ray. xposi = int(xpos) if dx = 0.0 JMP v_dx_failed elseif dx < 0.0 SUB xposi 1 MOV @0 xposi ITF @0 ADD# @0 1.0 MOV# xposf @0 MOV# zposf xposf SUB# zposf xpos MUL# zposf dzdx_inv ADD# zposf zpos rem zposi = int(zposf) MOV# @0 zposf FTI @0 MOV zposi @0 CMP zposi 0 JL v_dx_failed CMP zposi rc_MapH JGE v_dx_failed MOV @2 xposi MOV @3 zposi MOV @0 rc_Map MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] MOV# @5 0.0 @v_dxn_loop: CMP id 0 JG v_dxn_end rem ========== MOV @0 0 SUB @0 1 CMP id @0 JNE v_dxn_no_door MOV# @4 zposf SUB# @4 hdzdx_inv MOV# @0 @4 FTI @0 CMP @3 @0 JNE v_dxn_no_door rem get door param MOV# @0 @4 MOV# @5 rc_ItemParams MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP# @5 @1 MOV# @5 [@5] SUB# @0 @5 FTI @0 CMP @3 @0 JNE v_dxn_no_door MOV# zposf @4 MOV @0 @2 ADD @0 1 ITF @0 MOV# xposf @0 SUB# xposf 0.5 MOV @0 rc_Items MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] MOV xposi @2 MOV zposi @3 JMP v_dxn_door_hit @v_dxn_no_door: MOV# @5 0.0; rem no offset rem ========== SUB @2 1 SUB# zposf dzdx_inv MOV# @0 zposf FTI @0 MOV @3 @0 CMP @3 0 JL v_dx_failed CMP @3 rc_MapH JGE v_dx_failed MOV @0 rc_Map MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] JMP v_dxn_loop @v_dxn_end: MOV xposi @2 MOV zposi @3 rem xposf = float(xposi) + 1.0 MOV @0 xposi ADD @0 1 ITF @0 MOV# xposf @0 @v_dxn_door_hit: MOV# @0 xposf SUB# @0 xpos MUL# @0 @0 MOV# @1 zposf SUB# @1 zpos MUL# @1 @1 ADD# @0 @1 MOV# xdistance @0 JMP v_dx_done else ADD xposi 1 xposf = float(xposi) MOV# @0 xposf SUB# @0 xpos MUL# @0 dzdx_inv ADD# @0 zpos MOV# zposf @0 MOV# @0 zposf FTI @0 MOV zposi @0 CMP zposi 0 JL v_dx_failed CMP zposi rc_MapH JGE v_dx_failed MOV @2 xposi MOV @3 zposi MOV @0 rc_Map MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] MOV# @5 0.0 @v_dxp_loop: CMP id 0 JG v_dxp_end MOV @0 0 SUB @0 1 CMP id @0 JNE v_dxp_no_door MOV# @4 zposf ADD# @4 hdzdx_inv MOV# @0 @4 FTI @0 CMP @3 @0 JNE v_dxp_no_door rem get door param MOV# @0 @4 MOV# @5 rc_ItemParams MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP# @5 @1 MOV# @5 [@5] SUB# @0 @5 FTI @0 CMP @3 @0 JNE v_dxp_no_door MOV# zposf @4 MOV @0 @2 ADD @0 1 ITF @0 MOV# xposf @0 SUB# xposf 0.5 MOV @0 rc_Items MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] MOV xposi @2 MOV zposi @3 JMP v_dxp_door_hit @v_dxp_no_door: MOV# @5 0.0; rem no offset rem ========== ADD @2 1 ADD# zposf dzdx_inv MOV# @0 zposf FTI @0 MOV @3 @0 CMP @3 0 JL v_dx_failed CMP @3 rc_MapH JGE v_dx_failed MOV @0 rc_Map MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] JMP v_dxp_loop @v_dxp_end: MOV xposi @2 MOV zposi @3 rem xposf = float(xposi) MOV @0 xposi ITF @0 MOV# xposf @0 @v_dxp_door_hit: MOV# xdistance xposf SUB# xdistance xpos MUL# xdistance xdistance MOV# @0 zposf SUB# @0 zpos MUL# @0 @0 ADD# xdistance @0 JMP v_dx_done rem endif endif @v_dx_failed: MOV# xdistance 100000.0 @v_dx_done: rem Cast z ray zposi = int(zpos) if dz = 0.0 JMP v_dz_failed elseif dz < 0.0 SUB zposi 1 MOV @0 zposi ADD @0 1 ITF @0 MOV# zposf @0 MOV# xposf zposf SUB# xposf zpos MUL# xposf dxdz_inv ADD# xposf xpos MOV# @0 xposf FTI @0 MOV xposi @0 CMP xposi 0 JL v_dz_failed CMP xposi rc_MapW JGE v_dz_failed MOV @2 xposi MOV @3 zposi MOV @0 rc_Map MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] MOV# @5 0.0 @v_dzn_loop: CMP id 0 JG v_dzn_end MOV @0 0 SUB @0 2 CMP id @0 JNE v_dzn_no_door MOV# @4 xposf SUB# @4 hdxdz_inv MOV# @0 @4 FTI @0 CMP @2 @0 JNE v_dzn_no_door rem get door param MOV# @0 @4 MOV# @5 rc_ItemParams MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP# @5 @1 MOV# @5 [@5] SUB# @0 @5 FTI @0 CMP @2 @0 JNE v_dzn_no_door MOV# xposf @4 MOV @0 @3 ADD @0 1 ITF @0 MOV# zposf @0 SUB# zposf 0.5 MOV @0 rc_Items MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] MOV xposi @2 MOV zposi @3 JMP v_dzn_door_hit @v_dzn_no_door: MOV# @5 0.0; rem no offset rem ========== SUB @3 1 SUB# xposf dxdz_inv MOV# @0 xposf FTI @0 MOV @2 @0 CMP @2 0 JL v_dz_failed CMP @2 rc_MapW JGE v_dz_failed MOV @0 rc_Map MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] JMP v_dzn_loop @v_dzn_end: MOV xposi @2 MOV zposi @3 MOV @0 zposi ADD @0 1 ITF @0 MOV# zposf @0 @v_dzn_door_hit: MOV# zdistance xposf SUB# zdistance xpos MUL# zdistance zdistance MOV# @0 zposf SUB# @0 zpos MUL# @0 @0 ADD# zdistance @0 JMP v_dz_done else ADD zposi 1 MOV @0 zposi ITF @0 MOV# zposf @0 MOV# xposf zposf SUB# xposf zpos MUL# xposf dxdz_inv ADD# xposf xpos MOV# @0 xposf FTI @0 MOV xposi @0 CMP xposi 0 JL v_dz_failed CMP xposi rc_MapW JGE v_dz_failed MOV @2 xposi MOV @3 zposi MOV @0 rc_Map MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] MOV# @5 0.0 @v_dzp_loop: CMP id 0 JG v_dzp_end rem ========== MOV @0 0 SUB @0 2 CMP id @0 JNE v_dzp_no_door MOV# @4 xposf ADD# @4 hdxdz_inv MOV# @0 @4 FTI @0 CMP @2 @0 JNE v_dzp_no_door rem get door param MOV# @0 @4 MOV# @5 rc_ItemParams MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP# @5 @1 MOV# @5 [@5] SUB# @0 @5 FTI @0 CMP @2 @0 JNE v_dzp_no_door MOV# xposf @4 MOV @0 @3 ADD @0 1 ITF @0 MOV# zposf @0 SUB# zposf 0.5 MOV @0 rc_Items MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] MOV xposi @2 MOV zposi @3 JMP v_dzp_door_hit @v_dzp_no_door: MOV# @5 0.0; rem no offset rem ========== ADD @3 1 ADD# xposf dxdz_inv MOV# @0 xposf FTI @0 MOV @2 @0 CMP @2 0 JL v_dz_failed CMP @2 rc_MapW JGE v_dz_failed MOV @0 rc_Map MOV @1 @2 MUL @1 rc_MapH ADD @1 @3 STP @0 @1 MOV id [@0] JMP v_dzp_loop @v_dzp_end: MOV xposi @2 MOV zposi @3 rem zposf = float(zposi) MOV @0 zposi ITF @0 MOV# zposf @0 @v_dzp_door_hit: MOV# zdistance xposf SUB# zdistance xpos MUL# zdistance zdistance MOV# @0 zposf SUB# @0 zpos MUL# @0 @0 ADD# zdistance @0 JMP v_dz_done endif @v_dz_failed: MOV# zdistance 100000.0 @v_dz_done: if xdistance < distance or zdistance < distance return false else return true endif 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