Dos Batch Raycast - Maze3D/Explorer3D Beta

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
einstein1969
Expert
Posts: 961
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Dos Batch Raycast - Maze3D/Explorer3D Beta

#1 Post by einstein1969 » 09 Aug 2014 06:03


EDIT 16/10/2015 :Below the code of the latest version.
EDIT 31/08/2015 :For dbenham multithreading version look at viewtopic.php?p=42705#p42705


Improvements:

Code: Select all

vers.  frame time  FPS     Columns
0.01a   14890ms    0.06      40
0.01b    5870ms    0.17      40     swap out environment
0.1.0    3610ms    0.27      64     new algorithm (ray marching like, fixed step)
0.2.0    3840ms    0.26      64     Added moviment on left/ritgh and key "K" "L" for rotate.
0.3.0     750ms    1.33      64     jeb trick fast ray traversal
0.4.1     720ms    1.38*     64     dbenham multithread on monocore @2.00Ghz , 2-3 times faster on quad-core machine (4-5 frames per second)
0.5.1     400ms    2.50**    64     dda algorithm on monocore @2.00Ghz
0.5.2     300ms    3.33*     64     Using Aacini method for SIN(x). 6.25 FPS on quad-core @3.4Ghz

*: on monocore. In multicore the FPS are more
**: multicore performance data not avaible N/D :(

Get the code at pastebin:http://pastebin.com/16YHns0h

Code: Select all

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: Dos Batch Raycast ver. 0.5.3 BETA  by Francesco Poscetti aka einstein1969
::
::--------------------------------------------------------------------------
::
:: Ref: http://www.dostips.com/forum/viewtopic.php?f=3&t=5824
::
:: Thanks to Aacini, foxidrive, dbenham, penpen, jeb, neorobin, Liviu, aGerman
::
:: Tested on Windows 7
::
:: Changelog
::
:: ver. 0.5.3   2016-04-03 einstein1969
::  - Disabled parallel processing for a cuncurrent access problem see:
::    http://www.dostips.com/forum/viewtopic.php?f=3&t=7053
::
:: ver. 0.5.2   2016-03-22 einstein1969
::  - Add new SIN(x) calculus using Aacini method. Improved speed (~20%)
::
:: ver. 0.5.1   2015-10-17 einstein1969
::  - Add choice emulation. Now it should run on XP platform. Not tested.
::
:: ver. 0.5.0   2015-10-16 einstein1969
::  - Implemented DDA algorithm. Improved speed (~40%)
::  - Moved output of execution time on title + Add FPS counter.
::  - "H" now display Help.
::  - "M" now toggle the view of the Map
::  - Improved speed by clear the environment + other optimization (~10-15% on reference system)
::  - Map more readable.
::  - revert "reduce CALLs and rearrange code to minimize CALL distance" for easy code develop. TODO later. See ver. 0.4.x
::  - revert fast 3D clipping
::
:: ver. 0.4.1   2015-08-30  dbenham
::  - Limit number of processes to maximum of 8
::  - Move Transpose inside of :raycast
::  - Optionally use Aacini's CursorPos.exe to eliminate screen flicker
::    Implementation is the same as for SNAKE.BAT
::    Code is available at http://goo.gl/hr6Kkn
::
:: ver. 0.4     2015-08-30  dbenham
::  - Many minor optimizations:
::      - consolidate and minimize SET /A statements
::      - main loop is now an endless FOR /L loop running in a child process
::      - reduce CALLs and rearrange code to minimize CALL distance
::      - remove dynamic title
::  - Nearly instantaneous drawing of 2D map
::  - Player character now indicates orientation
::  - Implemented parallel processing of ray cast partitions based on NUMBER_OF_PROCESSORS
::  - "Z" now toggles between Old and New rendering algorithm
::  - "Q" quits the program
::  - New (fast) rendering now 2-3 times faster on quad-core machine (4-5 frames per second)
::  - Old (slow) rendering now 4+ times faster on quad-core machine  (1-2 frames per second)
::
:: ver. 0.3     jeb  2015-08-25
::  - Improved speed by inlining the Sinus calculation (~15% on reference system)
::  - Improved speed by direct calculating the next gridX/Y coordinates (~60%)
::
:: ver. 0.2     20/08/2015
::  - Not clear the screen until next.
::  - Added moviment on left/ritgh and key "K" "L" for rotate.
::  - Fixed bug on calculate distance
::  - Added partial clipping on Z (Distance)
::
:: ver. 0.1     04/07/2015
::  - New faster algorithm. Not optimizated for now.
::  - Use transpose trick of penpen
::  - Use new set of character for better visualize and fast antialiasing.
::  - Detect when a player slamming against the wall.
::  - You can use WASD for move!
::  - You can view the player in the MAP.
::  - You can modify the MAP more easily.
::
:: Ver. 0.01b   10/08/2014
::  - Added temporary dir and use swapout mechanism for manage env.
::
:: Ver. 0.01a   09/08/2014
::  - Initial version + some fixes
::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

@echo off
:: Multithread dispatcher
if "%~1" neq "" goto %1

setlocal EnableDelayedExpansion

:: Initialize some stuff...
call :Init

:: Load the Map grid. 1/2=wall ./0=empty 9=player position

Set /A MapsizeX=33, MapsizeY=10, y=1, MapWidth=MapsizeX+1, MapsizeX-=1

for %%D in (
"1212121212...2121212121.........."
"2........1...1........2..121....."
"1........21212....121.1.2...2...."
"2..................1..21.....1..."
"1...9.........................2.."
"2....1...12121................2.."
"1....2...2...2.....1..11.....1..."
"1....1...1...1....12..2.2...2...."
"2....2...2...2........1..121....."
"1212212121...1212121212.........."
) do (
  set Map[!y!]=%%~D
  for %%Y in (!y!) do for /L %%X in (0,1,!MapSizeX!) do (
    if "!Map[%%Y]:~%%X,1!" equ "9" (
      set /A nx=%%X+1
      for %%Z in (!nx!) do set Map[!y!]=!Map[%%Y]:~0,%%X!.!Map[%%Y]:~%%Z!
      set /A Playerx = %%X, Playery = !y!
      set nx=
    )
  )
  set /A y+=1
)
set y=

:: setting player position
set /A Playerx*=MulPlayer, Playery*=MulPlayer, OldPlayerx=Playerx, OldPlayery=Playery

:: prepare map for draw
call :prepareMap

:: Prepare for multithread engines
call :InitEngines

"%COMSPEC%" /d /v:on /c "%~f0" :mainLoop
exit /b

:mainLoop
for /l %%. in () do (
  set /a gridX=Playerx/MulPlayer, gridy=Playery/MulPlayer
  for %%X in (!gridx!) do for %%Y in (!gridy!) do if "!Map[%%Y]:~%%X,1!" geq "1" (
    set /A Playerx = OldPlayerx, Playery = OldPlayery
    set /P ".=%BEL%"<nul
  ) else (

    set /A "StepY=%SIN(x):x=!Angle! * PI / 180%, StepX=%SIN(x):x=PI_div_2-!Angle! * PI / 180%"

    call :raycast

    %= Draw Map =%
    if "!SeeMap!" equ "1" (
      set /a "pos=(PlayerY/MulPlayer-1)*mapWidth+PlayerX/MulPlayer, pos2=pos+1"
      for /f "tokens=1-3" %%1 in ("!pos! !pos2! !Angle!") do echo !map:~0,%%1!!P%%3!!map:~%%2,-1!
      set pos=&set pos2=
    )

    echo PlayerX/Y:!Playerx!/!Playery! OldplayerX/Y:!oldplayerX!/!oldplayerY!%space%& rem FastRotate=!Fastrotate!
    echo !method!: Angle:!Angle! GridX/Y:!gridx!/!gridy! StepX/Y=!StepX!/!StepY! wait=!wait!%space%

    set /A OldPlayerx = Playerx, OldPlayery = Playery

  )
  call :choice wksladhmfzqu >nul
  rem "%COMSPEC%\..\choice.exe" /N /C wksladhmfzqu >nul
  if errorlevel 12 (
    %= U - Redraw =%
    (call )
  ) else if errorlevel 11 (
    %= Q - Quit =%
    for /l %%N in (1 1 !childCnt!) do >"%base%%%N_job.bat.tmp" echo del "%%~f0"^&exit
    ren "%base%*_job.bat.tmp" *.
    for /l %%. in () do if not exist "%base%*_job.bat" del "%base%*.render"&exit
  ) else if errorlevel 10 (
    %= Z - Toggle oldSys =%
    set /a "oldSys=^!oldSys"
    if !oldSys!==0 (set "method=FAST") else set "method=SLOW"
  ) else if errorlevel 9 (
    %= F - Toggle Fastrotate =%
    set /a "fastRotate=^!fastrotate"
  ) else if errorlevel 8 (
    %= M - Toggle Map =%
    set /a "SeeMap=^!SeeMap"
    if "!SeeMap!" equ "0" cls
  ) else if errorlevel 7 (
    %= H - Help =%
    call :Help
  ) else if errorlevel 6 (
    %= D - Right =%
    set /A "PlayerX-=StepY/2, PlayerY+=StepX/2"
  ) else if errorlevel 5 (
    %= A - Left =%
    set /A "PlayerX+=StepY/2, PlayerY-=StepX/2"
  ) else if errorlevel 4 (
    %= L - Rotate Right =%
    set /A "Angle=(Angle+15+360) %% 360" & set Rotate=Right
  ) else if errorlevel 3 (
    %= S - Down - Backward =%
    set /A "PlayerX-=StepX/2, PlayerY-=StepY/2"
  ) else if errorlevel 2 (
    %= K - Rotate Left =%
    set /A "Angle=(Angle-15+360) %% 360" & set Rotate=Left
  ) else if errorlevel 1 (
    %= W - Up - Forward =%
    set /A "PlayerX+=StepX/1, PlayerY+=StepY/1"
  )
)


:raycast

  :: Save start time
  set "t1=!time: =0!"

  :: Create Jobs
  set/A  from=Angle-32, to=Angle+32, chunk=65/proc, end=from+chunk-1
  for /l %%N in (1 1 %childCnt%) do (
    >"%base%%%N_job.bat.tmp" echo set /a "from=!from!, to=!end!, Angle=!Angle!, playerX=!playerX!, playerY=!playerY!"
    set /a from+=chunk, end+=chunk
    ren "%base%%%N_job.bat.tmp" *.
  )

  :computeEngine
  setlocal & ( %= For Empty Environment =%
  %= Empty Environment =%
  for %%v in (MaxIter1 MaxIter2 Mul1 MulPlayer base file files childCnt comspec
    Angle MapSizeX MapSizeY MapWidth BEL OldPlayerX OldPlayerY TMP MM M10
    cls Number_of_Processors pathext proc seemap space t1 turbo wait pathext end
    formx formy grix gridy mul mulx muly chunk fastrotate dis files
    P345 P0 P15 P30 P45 P60 P75 P90 P105 P120 P135 P150 P165 P180 P195 method
    P210 P225 P240 P255 P270 P285 P300 P315 P330 PI PI32 PIx2 PI_div_2 SIN(x^) prompt
    GridX GridY LF MAP StepX StepY oldSys
  ) do set "%%v="
    rem (set&pause)>con
   
  %computeEngineBegin%
  >"%file%" (
    for /L %%Z in (!from!,1,!to!) do (

      set /A "Z=%%Z, aStepY=%SIN(x):x=Z * 31416 / 180%"
      set /A "aStepX=%SIN(x):x=15708-(Z * 31416 / 180)%"
      set/A  "A=%Angle%, corr=%SIN(x):x=15708-(Z-A) * 31416 / 180%"

      if "%oldSys%"=="1" (

        set "BREAK="
        set /A DistanceCount=%MaxIter1%, ax =PlayerX*%Mul1%, ay = PlayerY*%Mul1%

        %= Precompute how mulX/Y has to be computed =%
        if !aStepX! equ 0 (
          set "formX=set mul=%MaxIter1%"
          set mulX=%MaxIter1%
        ) else if !aStepX! GTR 0 (
          set "formX=set /a mulX=(aStepX+%MM%-(ax %% %MM%))/aStepX, mul=mulX"
        ) else if !aStepX! LSS 0 (
          set "formX=set /a mulX=-(ax %% %MM%)/aStepX+1, mul=mulX"
        )
        if !aStepY! equ 0 (
          set "formY="
          set mulY=%MaxIter1%
        ) else if !aStepY! GTR 0 (
          set "formY=set /a mulY=(aStepY+%MM%-(ay %% %MM%))/aStepY"
        ) else if !aStepY! LSS 0 (
          set "formY=set /a mulY=-(ay %% %MM%)/aStepY+1"
        )
        set dis=0
        for /L %%? in (1,1,20) do if not defined BREAK (
          !formX!
          !formY!           
          if !mulX! GEQ !mulY! set /a mul=mulY
          set /a ax+=aStepX*mul, ay+=aStepY*mul,dis+=mul, gridX=ax/%MM%, gridY=ay/%MM%
          for /f "tokens=1,2" %%X in ("!gridX! !gridY!") do if "!Map[%%Y]:~%%X,1!" geq "1" set BREAK=true & set /a DistanceCount=dis
        )
     
        %= Last Step =%
        set "BREAK="
        set /A "Zaccumul=DistanceCount*(10000/%Mul1%), ax=(ax-aStepX)*10, ay=(ay-aStepY)*10, DistanceCount=%MaxIter2%"
        set dis=0
        for /L %%? in (1,1,20) do if not defined BREAK (
          if !aStepX! equ 0 (set mulX=90) ELSE if !aStepX! GTR 0 (
            set /a "mulX=(aStepX+%M10%-(ax %% %MM%))/aStepX"
          ) else (
            set /a "mulX=((ax %% %M10%))/-aStepX+1"
          )
          if !aStepY! equ 0 (set mulY=90) ELSE if !aStepY! GTR 0 (
            set /a "mulY=(aStepY+%M10%-(ay %% %M10%))/aStepY"
          ) else (
            set /a "mulY=((ay %% %M10%))/-aStepY+1"
          )
               
          if !mulX! GEQ !mulY! (set /a mul=mulY) else set mul=!mulX!
          set /a ax+=aStepX*mul, ay+=aStepY*mul, dis+=mul, gridX=ax/%M10%, gridY=ay/%M10%
          for /f "tokens=1,2" %%X in ("!gridX! !gridY!") do if "!Map[%%Y]:~%%X,1!" geq "1" set BREAK=true & set /a DistanceCount=dis
        )
        for /f "tokens=1,2" %%X in ("!gridX! !gridY!") do set "C=!Map[%%Y]:~%%X,1!"
        set /A "distance=350/((((DistanceCount+Zaccumul)*corr/%Mulplayer%+555)/1000)+1), len=distance*2, st=(50-len)/2"

      ) else (

        set /A $X=%PlayerX%/10000, $Y=%PlayerY%/10000

        if !aStepX! equ 0 (
          set /A $tx=Dtx=100000000, $SX=0
        ) else if !aStepX! lss 0 (
                     set /A "$tx=($X*10000-PlayerX)*10000/aStepX, Dtx=-10000*10000/aStepX, $SX=-1"
              ) else set /A "$tx=(($X+1)*10000-PlayerX)*10000/aStepX, Dtx=10000*10000/aStepX, $SX=1"
        if !aStepY! equ 0 (
          set /A $ty=Dty=100000000, $SY=0
        ) else if !aStepY! lss 0 (
                     set /A "$ty=($Y*10000-PlayerY)*10000/aStepY, Dty=-10000*10000/aStepY, $SY=-1"
              ) else set /A "$ty=(($Y+1)*10000-PlayerY)*10000/aStepY, Dty=10000*10000/aStepY, $SY=1"

        set "$B=" & set /A "Distance=21*10000"

        for /L %%£ in (1,1,3) do if not defined $B for /L %%? in (1,1,7) do if not defined $B (
          if !$tx! lss !$ty! (
            set /A $tx+=Dtx, $X+=$SX
            for /f "tokens=1,2" %%X in ("!$X! !$Y!") do if "!Map[%%Y]:~%%X,1!" geq "1" (
              set /A Distance=$tx-Dtx, Side=0, $B=!Map[%%Y]:~%%X,1!
            )
          ) else (
            set /A $ty+=Dty, $Y+=$SY
            for /f "tokens=1,2" %%X in ("!$X! !$Y!") do if "!Map[%%Y]:~%%X,1!" geq "1" (
              set /A Distance=$ty-Dty, Side=1, $B=!Map[%%Y]:~%%X,1!
            )
          )
       )
       if not defined $B set "$B=1"
       set /A "distance=350/((((k=(Distance*corr))/%Mulplayer%+555)/1000)+1), len=distance*2, st=(50-len)/2"
       set /A C=$B
      )
      %= 2D-clipping =%
      if !st! lss 1 (set st=1) else if !st! gtr 50 set st=50
      for /f "tokens=1,2" %%X in ("!st! !len!") do (
        if !C! equ 1 (
            echo -!S_:~0,%%X!°±²Û²±°!SS:~0,%%Y!°±²Û²±°!SP:~0,%%X!-
        ) else (
          echo -!S_:~0,%%X!°±²Û²±°!S2:~0,%%Y!°±²Û²±°!SP:~0,%%X!-
        )
      )
      set C=&set Distance=&set len=&set st=&set ZAccumul=
    )
  )
  %computeEngineEnd%
  ) & endlocal %= For Empty Environment =%

  set /a wait=0
  :waitForJobCompletion
  if exist "%base%*_job.bat" (
    set /a wait+=1
    goto :waitForJobCompletion
  )

  :: Transpose and display results
  setlocal
  set /A LineN=0
  for /f usebackq^ delims^=^ eol^= %%A in (%files%) do (
    set /A LineN+=1
    set "N!LineN!=%%A"
  )

  set "transposedLine="
  for /L %%m in (1, 1, !LineN!) do set "transposedLine=!transposedLine!^!N%%m:~%%n,1^!"

  set/A MaxN=65
  %cls%
  echo(
  for /L %%n in (0, 1, !LineN!) do echo( ^|%transposedLine%^|
  endlocal
 
  :: Compute and display rendering time
  for /F "tokens=1-8 delims=:.," %%a in ("!t1!:!time: =0!") do set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31)&8640000, FPS=10000/a"
  Title Raycast Dos Batch  -  Press H for help  -  Time Elapsed:!a!0ms - FPS: !FPS:~0,-2!.!FPS:~-2!
  set a=&set t1=
exit /b

:choice
setlocal EnableDelayedExpansion
set "c=" &set "e=" &set "map=%~1"
if not defined map endlocal &exit /b 0
for /f "delims=" %%i in ('2^>nul %COMSPEC%\..\xcopy /lw "%~f0" "%~f0"') do if not defined c set "c=%%i"
set "c=%c:~-1%"
if defined c (
  For /L %%i in (0,1,127) do (
    set "e=!map:~%%i,1!"
    if not defined e endlocal &<nul set /p "=%BEL%" >CON&exit /b 0
    if /i "!e!"=="!c!" (
      echo(!c!
      set /A n=%%i+1
      for /f %%j in ("!n!") do endlocal &exit /b %%j
    )
  )
)
endlocal &<nul set /p "=%BEL%" >CON &goto choice
exit /b

:prepareMap
set ^"LF=^

^" The above empty line is critical - DO NOT REMOVE
  set "map="
  for /L %%Y in (1,1,!MapsizeY!) do (
    for /L %%X in (0,1,!MapsizeX!) do (
      if "!Map[%%Y]:~%%X,1!" geq "1" (
        set "map=!map!Û"
      ) else (
        set "map=!map! "
      )
    )
    set "map=!map!!LF!"
  )
exit /b

:Help
  cls
  echo(
  echo  For best view use raster font 8x8 or 16x8.
  echo(
  echo  Use keyboard:
  echo(
  echo   WASD for move
  echo   KL   for turn/rotate.
  echo   Z    for old rendering system.
  echo   U    for redraw
  echo   M    for view map ON/OFF
  echo   F    for Fastrotate ON/OFF (Not implemented)
  echo   Q    for quit
  echo   H    for Help
  echo(
  pause
exit /b


:InitEngines
:: Initialize and launch compute engines
  set "base=%tmp%\%~nx0"
  2>nul del "%base%*_job.bat"
  set ^"computeEngineBegin=for /l %%. in () do if exist "^!job^!" ( call "^!job^!"^"
  set ^"computeEngineEnd=del "^!job^!")^"
rem disabling parallel processing :
rem see http://www.dostips.com/forum/viewtopic.php?f=3&t=7053
rem  set /a proc=NUMBER_OF_PROCESSORS, childCnt=proc-1
  set /a proc=1, childCnt=proc-1
  if %proc% gtr 8 set /a proc=8
  for /l %%N in (1 1 !childCnt!) do (
    set "file=%base%%%N.render"
    set "job=%base%%%N_job.bat"
    >nul 2>nul <nul start "" /b "%comspec%" /d /v:on /c "%~f0" :computeEngine
  )
  set "file=%base%!proc!.render"
  set "files="
  for /l %%N in (1 1 !proc!) do set files=!files! "%base%%%N.render"
  set "computeEngineBegin="
  set "computeEngineEnd="
exit/b

:Init

  Title Raycast Dos Batch - Loading...
  mode 69,80
  color 0F
  cls

  :: capture del BEL char
  for /f %%i in ('forfiles /m "%~nx0" /c "cmd /c echo 0x07"') do set "BEL=%%i"

  :: empty environment
  set "preserve= TMP BEL COMSPEC NUMBER_OF_PROCESSORS preserve "
  for /f "delims==" %%v in ('set') do if "!preserve: %%v =!" equ "!preserve!" set "%%v="
  set "preserve="

  :: Setting output char
  set "SS=°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°"
  set "S_=úúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúú"
  set "S2=±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±"
  set "SP=__________________________"
  set "SC=///////////////////////////////////////////////////"

  :: Trigonometric variables
  set /a "PI=(35500000/113+5)/10, PI_div_2=(35500000/113/2+5)/10, PIx2=2*PI, PI32=PI+PI_div_2"
  set "SIN=(a - a*a/1920*a/312500 + a*a/1920*a/15625*a/15625*a/2560000 - a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000)"
  set "SIN(x)=(a=(x)%%62832, c=(a>>31|1)*a, a-=(((c-47125)>>31)+1)*((a>>31|1)*62832)  +  (-((c-47125)>>31))*( (((c-15709)>>31)+1)*(-(a>>31|1)*31416+2*a)  ), %SIN%)"
  set SIN=

  :: Define player characters:
  for %%# in (
    "345   0  15  >"
    " 30  45  60  \"
    " 75  90 105  v"
    "120 135 150  /"
    "165 180 195  <"
    "210 225 240  \"
    "255 270 285  ^"
    "300 315 330  /"
  ) do for /f "tokens=1-4" %%A in (%%#) do (
    set "P%%A=%%D"
    set "P%%B=%%D"
    set "P%%C=%%D"
  )

  set /A MulPlayer=10000, Mul1=25, MaxIter1=500, MaxIter2=50, MM=MulPlayer*Mul1, M10=MM*10
  set /A Angle=0, oldSys=0, FastRotate=0, SeeMap=1

  :: Define some screen management variables and macros
  if exist "%~dp0CursorPos.exe" (
    set "cls=CursorPos 0 0"
  ) else (
    set "cls=cls"
  )
  set "method=FAST"
  set "space=            " 

exit /b


5/7/2015 - Edit: For older version (ver 0.1) look viewtopic.php?p=41919#p41919

-------------------------------------------------------------
Original post

Hi to all,

It was a long time that I wanted to make something interactive 3D. This is my initial attempt. It's a porting from an c++ application. The beta is not interactive for now...

IT's a 3d graphics engine that allows you to perform various types of applications. Not just games.

The goal is to be able to make it fast enough, and possibly that work on multiple cores.

I hope in the help of everyone.

Soon I will comment the code, and if there are any questions I am available!

Use font raster 16x8

version 0.01b:

Code: Select all

::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Explorer3D by Francesco Poscetti aka einstein1969
::
:: Version 0.01b BETA
::
:: 10/8/2014 Added temporary dir and use swapout mechanism for manage env.
::
:: Version 0.01a BETA
::
:: 9/8/2014 initial version + some fixes
::
:: Developed on monocore seven 32bit system.
::
:: This type of Engine 3D is used by  Wolfentein 3D,
:: Rise Of The Triad, DOOM, Duke Nukem 3D, etc.
::
:: Thanks to Antonio Acini, penpen, foxidrive
::
::::::::::::::::::::::::::::::::::::::::::::::::::::

:: integer variables = UPPERCASE , fixed point variables = lowercase/Mixed

:: Use fonts raster 16x8

@echo off

setlocal EnableDelayedExpansion   

for /f "delims==" %%v in ('set') do if /I not "%%v" == "ComSpec" if /I not "%%v" == "USERPROFILE" if /I not "%%v" == "PATH" if /I not "%%v" == "TMP"  set %%v=

rem resolution
set /a SCREEN_W=40, SCREEN_H=30+4
(
  for /f "delims==" %%v in ('set') do echo Set %%v=
  mode %SCREEN_W%,%SCREEN_H%
  set /a SCREEN_H=%SCREEN_H%-4
)

rem use a temporary directory
md Explorer3d 2>nul
pushd Explorer3d
del *.$$$.tmp 2>nuls


call :LoadWorld

rem fov=0.66 = 66/100   , real to integer
set /a fov=66*10000/100

rem pi=3.1416
set /a pi=31416

rem stepD=MovSpeed=0.5, RotationSpeed=0.05
set /a MovSpeed=5*10000/10, RotSpeed=5*10000/100

rem init frame/canvas
set /a FRAME.WIDTH=SCREEN_W, FRAME.HEIGHT=SCREEN_H

rem initial state
set /a state.posx=3 * 10000
set /a state.posy=3 * 10000
set /a state.dirx=1 * 10000
set /a state.diry=0 * 10000
set /a state.camx=0 * 10000
set /a "state.camy=fov" & rem already fixed point format!

For /L %%r in (1,1,15) do (
  call :RenderScene
  set /a state.posx+=state.dirx*movSpeed/10000, state.posy+=state.diry*movSpeed/10000
)

del *.$$$.tmp
popd

exit /b

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:RenderScene

set /a LASTCOL=FRAME.WIDTH-1

rem for each column
For /L %%c in (0,1,!LASTCOL!) do (

  title %%c

  set /a cameraX=2 * %%c * 10000 / FRAME.WIDTH - 1 * 10000

  set /a rayPosX=state.posx, rayPosY=state.posy

  rem CHECK cameraX on second line!
  set /a rayDirX=state.dirx + state.camx * cameraX / 10000
  set /a rayDirY=state.diry + state.camy * cameraX / 10000

  rem integer part
  set /a MAPX=rayPosX/10000, MAPY=rayPosY/10000

  rem ray length
  rem set /a "_deltaDistX= 1 * 10000 + (rayDirY*rayDiry)/(rayDirX*rayDirX) * 10000"
  rem set /a "_deltaDistY= 1 * 10000 + (rayDirX*rayDirX)/(rayDirY*rayDirY) * 10000"

rem check raydirx ZERO!
  set /a "_deltaDistX= 1 * 10000 + (rayDirY*rayDiry)/rayDirX*10000/rayDirX"

rem check raydiry ZERO!
  set /a "_deltaDistY= 1 * 10000 + (rayDirX*rayDirX)/rayDirY*10000/rayDirY"

  rem CALCOLARE la radice quadrata dei due precedenti. by Antonio Acini
 
  call :sqrt _deltaDistX deltaDistX %%c

  call :sqrt _deltaDistY deltaDistY %%c

  if !rayDirX! lss 0 (
    set /a STEPX=-1
    set /a "sideDistX=(rayPosX - MAPX * 10000) * deltaDistX /10000"

  ) else (
    set /a STEPX=1
    set /a "sideDistX=(MAPX * 10000 + 1 * 10000 - rayPosX) * deltaDistX /10000"
  )

  if !rayDirY! lss 0 (
    set /a STEPY=-1
    set /a "sideDistY=(rayPosY-MAPY * 10000) * deltaDistY /10000"

  ) else (
    set /a STEPY=1
    set /a "sideDistY=(MAPY * 10000 + 1 * 10000 - rayPosY) * deltaDistY /10000"
  )

  rem ray casting

  rem implementazione while con massimo "dm" cicli. Trick by Antonio Aacini
  set dm=64*2
  set break=
  for /L %%w in (0,1,!dm!) do if not defined break (

    set /a CC=MAPX + MAPY * WORLD.WIDTH

    for %%C in ("!CC!") do if not defined WORLD.DATA[%%C] (
       set /p "WORLD.DATA[%%C]=" < WORLD.DATA[%%C].$$$.tmp
       set /a WD=!WORLD.DATA[%%C]!
    ) else set /a WD=!WORLD.DATA[%%C]!

    if !sideDistX! lss !sideDistY! (
           set /a sideDistX += deltaDistX, MAPX += STEPX, SIDE = 0
    ) else set /a sideDistY += deltaDistY, MAPY += STEPY, SIDE = 1

    if !wd! neq 0 set break=TRUE

  )   

  rem ray len.

  if !SIDE! == 0 (
    rem perpWallDist = fabs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX);
    set /a "perpWallDist = (MAPX * 10000 - rayPosX + (1 * 10000 - STEPX * 10000 ) / 2) * 10000 / rayDirX"
  ) else (
    set /a "perpWallDist = (MAPY *10000 - rayPosY + (1 * 10000 - STEPY * 10000 ) / 2) * 10000 / rayDirY"
  )

  if !perpWallDist! lss 0 set /A perpWallDist=-perpWallDist

  set /a "what.distance = perpWallDist"
  set /a what.MAPX = MAPX 
  set /a what.MAPY = MAPY 
  set /a what.SIDE = SIDE 
  set /a what.rayDirX = rayDirX 
  set /a what.rayDirY = rayDirY

  rem draw column:

   rem per ora un solo tipo di muro
   rem type = world.data[what.mapX + what.mapY * world.width];

   rem if type =1 then r,g,b=1 ....

   rem colh = abs(int(FRAME.HEIGHT / what.distance));

   if !what.distance! equ 0 (set /a COLH=FRAME.HEIGHT) else (

      set /a "COLH=FRAME.HEIGHT * 10000 / what.distance , COLH=(COLH>>31|1)*COLH"

   )

   set /a CROPUP=0, CROPDOWN=0, INDEX=0

   if !COLH! gtr !FRAME.HEIGHT! (

          set /a "index=%%c, cropup = (COLH - FRAME.HEIGHT) / 2, DROPDOWN = CROPUP + 1"

   ) else set /a "index=%%c + ((FRAME.HEIGHT - COLH) / 2) * FRAME.WIDTH, CROPUP = 0, CROPDOWN = 0"

   rem disegna colonna

   set /A "LASTC=(COLH - CROPDOWN)-1"

   call :color


   rem empty column. Si puo' ottimizzare ancora con 0-cropup, lastc-tot e mettere su file come singola stringa.

   set I=%%c

   set /a TOT=FRAME.HEIGHT-1, TOTM=FRAME.HEIGHT/2-1, TOTM2=TOTM+1

   For /L %%i in (0,1,!TOTM!) do (
        set FRAME.data[!I!]=ú
        set /a I+=FRAME.WIDTH
   )
   For /L %%i in (!TOTM2!,1,!TOT!) do (
        set FRAME.data[!I!]=_
        set /a I+=FRAME.WIDTH
   )

   for /L %%N in (!CROPUP!,1,!LASTC!) do (

       For %%C in (!dd!) do set frame.data[!INDEX!]=!g:~%%C,1!
       set /a INDEX+=FRAME.WIDTH
   )


  if 1==0 call :Debug %%c

  set /a n=%%c %% 8
  if !n! equ 0 call :swapout frame.data[ 0

)

  call :swapout frame.data[ 0
 
::DrawScene
 
  set /a TOT=FRAME.WIDTH*FRAME.HEIGHT

  set canvas=
  for /L %%C in (0,1,!TOT!) do (
     if not defined frame.data[%%C] set /p "frame.data[%%C]=" < frame.data[%%C].$$$.tmp
     set canvas=!canvas!!frame.data[%%C]!
     set frame.data[%%C]=
  )

  cls & set/p ".=!canvas!" <nul
  rem pause

exit /b


:color
   set g=Û²±°/:.....................................................
   set /a dd=what.distance /20000
exit /b

:sqrt

  set /a number=%1 * 100
  set /A iter1=number/2

  rem The maximum number of iterations to calculate sqrt of a 32 bits integer number is 20
  set "sqrt="

  for /L %%i in (1,1,20) do if not defined sqrt (

    set /A "iter2=number/iter1, iter1=(iter1+iter2)/2"

    if !iter2! geq !iter1! set /A "sqrt=(iter1+iter2)/2"

  )
 
  set /a %2= sqrt *10

exit /b

example of world/map

64
64
111111111111111111111111111   
1                 4       1
1 4 4 4 4 4 4 4 4 4 4 4 4 1
1                         1
1  3     22222   4        1
1        2       4        1
1  3     2       44444 4441
1  3   2222222       4    1
1            2            1
1444444444   2    222222221
14       4   2    2      21
14  222      2       44  21
14       4        2      21
1444444444        222222221
111111111111111111111111111


:LoadWorld

echo Creating random map/world.

set /a WORLD.WIDTH=64, WORLD.HEIGHT=64, ww=WORLD.WIDTH-1, wh=WORLD.HEIGHT-1

For /L %%h in (0,1, !wh!) do (

  set /p ".=." <nul

  For /L %%w in (0,1, !ww!) do (

    if !random! gtr 3276 (set F=0) else set F=1
 
    if %%h equ 0 set F=1
    if %%h equ !wh! set F=1
    if %%w equ 0 set F=1
    if %%w equ !wh! set F=1

    set /a cc=%%w + %%h * WORLD.WIDTH

    rem for %%C in ("!cc!") do if !F! equ 0 (set "WORLD.data[%%C]=0" & set /p ".=_" <nul) else (set "WORLD.data[%%C]=1" & set /p ".=*" <nul)
    for %%C in ("!cc!") do if !F! equ 0 (set "WORLD.data[%%C]=0") else set "WORLD.data[%%C]=1"

    rem empty env
    if !cc! gtr !_! call :swapout WORLD.data[ 400
  )
  rem echo(
)
call :swapout WORLD.data[ 0
set F=

exit /b

:swapout
(    for /f "delims==" %%A in ('2^>nul set %1') do (
       >%%A.$$$.tmp echo !%%A!
       set "%%A="
     )
     set /A _+=%2
exit /b )

:debug
echo(
echo DEBUG BreakPpoin Col=%1
set cameraX
set CC
set COLH
set CROPUP
set CROPDOWN
set deltaDistX
set deltaDistY
set fov
set FRAME.HEIGHT
set FRAME.WIDTH
set index
set LASTC
set MAPX
set MAPY
set perpWallDist
set rayDirX
set rayDirY
set rayPosX
set rayPosY
set state.camx
set state.camY
set state.dirx
set state.diry
set state.posx
set state.posy
set sideDistX
set sideDistY
set SIDE
set STEPX
set STEPY
set what.distance
set WD
set _deltaDistX
set _deltaDistY
pause
exit /b


version 0.01a:

Code: Select all

::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Explorer3D by Francesco Poscetti aka einstein1969
::
:: Version 0.01a BETA 9/8/2014
::
:: Developed on monocore seven 32bit system.
::
:: This type of Engine 3D is used by  Wolfentein 3D,
:: Rise Of The Triad, DOOM, Duke Nukem 3D, etc.
::
:: Thanks to Antonio Acini, penpen, foxidrive
::
::::::::::::::::::::::::::::::::::::::::::::::::::::

:: integer variables = UPPERCASE , fixed point variables LOWERCASE/Mixed

:: Use font 16x8

@echo off

setlocal EnableDelayedExpansion   

for /f "delims==" %%v in ('set') do if /I not "%%v" == "ComSpec" if /I not "%%v" == "USERPROFILE" if /I not "%%v" == "PATH" if /I not "%%v" == "TMP"  set %%v=

rem for /f "delims==" %%v in ('set') do echo Set %%v=

rem resolution
set /a SCREEN_W=64, SCREEN_H=84+4
set /a SCREEN_W=40, SCREEN_H=40+4
mode !SCREEN_W!,!SCREEN_H!
set /a SCREEN_H-=4

rem fov=0.66 = 66/100   , real to integer
set /a fov=66*10000/100

rem pi=3.1416
set /a pi=31416

rem stepD=MovSpeed=0.1, RotationSpeed=0.05
set /a MovSpeed=5*10000/10, RotSpeed=5*10000/100


rem init frame/canvas
set /a FRAME.WIDTH=SCREEN_W, FRAME.HEIGHT=SCREEN_H

rem initial state
set /a state.posx=3 * 10000
set /a state.posy=3 * 10000
set /a state.dirx=1 * 10000
set /a state.diry=0
set /a state.camx=0
set /a state.camy=fov

call :LoadWorld

For /L %%r in (1,1,50) do (
  call :RenderScene
  set /a state.posx+=state.dirx*movSpeed/10000, state.posy+=state.diry*movSpeed/10000
)

exit /b

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:RenderScene

rem empty
title Empty frame buffer ...
set /a TOT=FRAME.WIDTH*FRAME.HEIGHT-1, TOTM=FRAME.WIDTH*FRAME.HEIGHT/2-1, TOTM2=TOTM+1
For /L %%i in (0,1,!TOTM!) do set FRAME.data[%%i]=ú
For /L %%i in (!TOTM2!,1,!TOT!) do set FRAME.data[%%i]=_

set /a LASTCOL=FRAME.WIDTH-1

rem for each column
For /L %%c in (0,1,!LASTCOL!) do (

  title %%c

  set /a cameraX=2 * %%c * 10000 / FRAME.WIDTH - 1 * 10000

  set /a rayPosX=state.posx, rayPosY=state.posy

  rem CHECK cameraX on second line!
  set /a rayDirX=state.dirx + state.camx * cameraX / 10000
  set /a rayDirY=state.diry + state.camy * cameraX / 10000

  rem integer part
  set /a MAPX=rayPosX/10000, MAPY=rayPosY/10000

  rem ray length
  rem set /a "_deltaDistX= 1 * 10000 + (rayDirY*rayDiry)/(rayDirX*rayDirX) * 10000"
  rem set /a "_deltaDistY= 1 * 10000 + (rayDirX*rayDirX)/(rayDirY*rayDirY) * 10000"

  set /a "_deltaDistX= 1 * 10000 + (rayDirY*rayDiry)/rayDirX*10000/rayDirX"
  set /a "_deltaDistY= 1 * 10000 + (rayDirX*rayDirX)/rayDirY*10000/rayDirY"

  rem CALCOLARE la radice quadrata dei due precedenti.
 
  set /a number=_deltaDistX * 100
  set /A iter1=number/2

  rem The maximum number of iterations to calculate sqrt of a 32 bits integer number is 20
  set "sqrt="
  for /L %%i in (1,1,20) do if not defined sqrt (
    set /A "iter2=number/iter1, iter1=(iter1+iter2)/2"
    if !iter2! geq !iter1! set /A "sqrt=(iter1+iter2)/2"
  )
 
  set /a deltaDistX= sqrt * 10

  call :sqrt _deltaDistY deltaDistY %%c

rem echo .

  if !rayDirX! lss 0 (
    set /a STEPX=-1
    set /a "sideDistX=(rayPosX - MAPX * 10000) * deltaDistX /10000"

  ) else (
    set /a STEPX=1
    set /a "sideDistX=(MAPX * 10000 + 1 * 10000 - rayPosX) * deltaDistX /10000"
  )

rem echo ..

  if !rayDirY! lss 0 (
    set /a STEPY=-1
    set /a "sideDistY=(rayPosY-MAPY * 10000) * deltaDistY /10000"

  ) else (
    set /a STEPY=1
    set /a "sideDistY=(MAPY * 10000 + 1 * 10000 - rayPosY) * deltaDistY /10000"
  )

rem echo .._

  rem ray casting

  set /a CC=MAPX + MAPY * WORLD.WIDTH
  for %%C in ("!CC!") do set /a WD=!world.data[%%C]!

rem echo ...

  rem implementazione while con massimo "dm" cicli
  set dm=64*2
  set break=
  for /L %%w in (0,1,!dm!) do if not defined break (

    rem echo inner: !wd! %%w

    if !sideDistX! lss !sideDistY! (
           set /a sideDistX += deltaDistX, MAPX += STEPX, SIDE = 0
    ) else set /a sideDistY += deltaDistY, MAPY += STEPY, SIDE = 1

    set /a cc=MAPX + MAPY * WORLD.WIDTH
    for %%C in ("!cc!") do set /a wd=!world.data[%%C]!

    if !wd! neq 0 set break=TRUE

  )   


  rem ray len. CALCOLARE FABS=float abs

  if !SIDE! == 0 (
    rem perpWallDist = fabs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX);
    set /a "perpWallDist = (MAPX * 10000 - rayPosX + (1 * 10000 - STEPX * 10000 ) / 2) * 10000 / rayDirX"
  ) else (
    set /a "perpWallDist = (MAPY *10000 - rayPosY + (1 * 10000 - STEPY * 10000 ) / 2) * 10000 / rayDirY"
  )

  if !perpWallDist! lss 0 set /A perpWallDist=-perpWallDist

  set /a "what.distance = perpWallDist"
  set /a what.MAPX = MAPX 
  set /a what.MAPY = MAPY 
  set /a what.SIDE = SIDE 
  set /a what.rayDirX = rayDirX 
  set /a what.rayDirY = rayDirY

rem echo ....

  rem disegna la colonna:

   rem per ora un solo tipo di muro
   rem type = world.data[what.mapX + what.mapY * world.width];

   rem if type =1 then r,g,b=1 ....

   rem colh = abs(int(FRAME.HEIGHT / what.distance));

   if !what.distance! equ 0 (set /a COLH=FRAME.HEIGHT) else (

      set /a "COLH=FRAME.HEIGHT * 10000 / what.distance , COLH=(COLH>>31|1)*COLH"

   )

   set /a CROPUP=0, CROPDOWN=0, INDEX=0

   if !COLH! gtr !FRAME.HEIGHT! (

          set /a "index=%%c, cropup = (COLH - FRAME.HEIGHT) / 2, DROPDOWN = CROPUP + 1"

   ) else set /a "index=%%c + ((FRAME.HEIGHT - COLH) / 2) * FRAME.WIDTH, CROPUP = 0, CROPDOWN = 0"

   rem disegna colonna

   set /A "LASTC=(COLH - CROPDOWN)-1"

rem echo .....

   call :color

   for /L %%N in (!CROPUP!,1,!LASTC!) do (

       For %%C in (!dd!) do set frame.data[!INDEX!]=!g:~%%C,1!
       set /a INDEX+=FRAME.WIDTH
   )


if 1==0 (
echo(
echo DEBUG BP Col=%%c
set cameraX
set CC
set COLH
set CROPUP
set CROPDOWN
set deltaDistX
set deltaDistY
set fov
set FRAME.HEIGHT
set FRAME.WIDTH
set index
set LASTC
set MAPX
set MAPY
set perpWallDist
set rayDirX
set rayDirY
set rayPosX
set rayPosY
set state.camx
set state.camY
set state.dirx
set state.diry
set state.posx
set state.posy
set sideDistX
set sideDistY
set SIDE
set STEPX
set STEPY
set what.distance
set WD
set _deltaDistX
set _deltaDistY
pause
)

)

::DrawScene
 
  set /a TOT=FRAME.WIDTH*FRAME.HEIGHT

  set canvas=
  for /L %%C in (0,1,!TOT!) do set canvas=!canvas!!frame.data[%%C]!

  cls & set/p ".=!canvas!" <nul
  rem pause

exit /b


:color
   set g=Û²±°/:.....................................................
   set /a dd=what.distance /20000
exit /b

:sqrt



  set /a number=%1 * 100
  set /A iter1=number/2

  if %3 equ 999 (

  echo set /a number=%1 * 10000
  echo set /A iter1=number/2
  echo %1=!%1! number=!number! iter1=!iter1!
  pause

)


  rem The maximum number of iterations to calculate sqrt of a 32 bits integer number is 20
  set "sqrt="

  for /L %%i in (1,1,20) do if not defined sqrt (

    set /A "iter2=number/iter1, iter1=(iter1+iter2)/2"

    if !iter2! geq !iter1! set /A "sqrt=(iter1+iter2)/2"

  if %3 equ 999 (
    echo set /A "iter2=number/iter1, iter1=(iter1+iter2)/2"

    echo if !iter2! geq !iter1! set /A "sqrt=(iter1+iter2)/2"

    echo iter1=!iter1! iter2=!iter2! number=!number! sqrt=!sqrt!

    pause
  )

  )
 
  set /a %2= sqrt *10

exit /b


64
64
111111111111111111111111111   
1                 4       1
1 4 4 4 4 4 4 4 4 4 4 4 4 1
1                         1
1  3     22222   4        1
1        2       4        1
1  3     2       44444 4441
1  3   2222222       4    1
1            2            1
1444444444   2    222222221
14       4   2    2      21
14  222      2       44  21
14       4        2      21
1444444444        222222221
111111111111111111111111111


:LoadWorld

echo Creating random map/world...

set /a WORLD.WIDTH=64, WORLD.HEIGHT=64, ww=WORLD.WIDTH-1, wh=WORLD.HEIGHT-1
For /L %%h in (0,1, !wh!) do (

  For /L %%w in (0,1, !ww!) do (

    if !random! gtr 3276 (set F=0) else set F=1
 
    if %%h equ 0 set F=1
    if %%h equ !wh! set F=1
    if %%w equ 0 set F=1
    if %%w equ !wh! set F=1

    set /a cc=%%w + %%h * WORLD.WIDTH

    rem for %%C in ("!cc!") do if !F! equ 0 (set "WORLD.data[%%C]=0" & set /p ".=_" <nul) else (set "WORLD.data[%%C]=1" & set /p ".=*" <nul)
    for %%C in ("!cc!") do if !F! equ 0 (set "WORLD.data[%%C]=0") else set "WORLD.data[%%C]=1"

  )
  rem echo(
)
set F=

exit /b


EDIT 20/08/2015 changed Subject.

einstein1969
Last edited by einstein1969 on 03 Apr 2016 04:39, edited 21 times in total.

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Explorer3D Beta

#2 Post by foxidrive » 09 Aug 2014 06:53

I get what looks like a topdown view of a maze
and a press any key prompt.
It then says emptying frame buffer I think and counts up to 63 in the title bar.

Around 32 I get a

Code: Select all

Divide by zero error.

and then it displays a wolfenstein-like first person view of a view of walls in a maze, which looks good.

This last step repeats every time I press a key and the display looks the same.

einstein1969
Expert
Posts: 961
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Explorer3D Beta

#3 Post by einstein1969 » 09 Aug 2014 07:29

thanks foxidrive,

I have added auto walking forward 0,5 block at step. The new version Beta 0.01a is in the first post.

You can change the resolution at the TOP of code. Changing

Code: Select all

set /a SCREEN_W=40, SCREEN_H=40+4


for now there isn't performance optimization.

I'll DEBUG for division by zero. For the moment there is a little bug in visualization.

einstein1969

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Explorer3D Beta

#4 Post by foxidrive » 09 Aug 2014 08:14

It's working well.

einstein1969
Expert
Posts: 961
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Explorer3D Beta

#5 Post by einstein1969 » 10 Aug 2014 03:40

New version. Little mods. More Faster. See header for changes.

einstein1969

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Explorer3D Beta

#6 Post by foxidrive » 10 Aug 2014 03:55

There are a couple of these per frame

Code: Select all

Divide by zero error.


It's much faster, and it exits after 10 or so steps.

einstein1969
Expert
Posts: 961
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Explorer3D Beta

#7 Post by einstein1969 » 10 Aug 2014 11:34

Thanks firefox. (foxidrive :? :lol: )

The BETA version
I stop after 15 step, but in the final version there is no limit.

The speed
I search for optimization. My goal is 15 frames for second. If someone have any idea would be greatly appreciated. :idea:

The mode/resolution
The batch can work on tunnel/corridors/maze or rooms with doors. In the future we can double the resolution on the Y thanks to the graphic characters of the dos. You can also add the sprite to create a game in all respects. There are the possibility to apply simple textures at the walls! I will do!

The input
I would like to add the input engine that has the batchsnake, although I have not yet figured out how it works. And I do not know if they serve all those who use rendirects. Dbenham help welcome!

The test
When I do test on my monocore the CPU go to 60% only. I can't sature the CPU at the moment...
I know it's asking a lot but maybe someone can give me remote access to a multicore virtual machine for testing and developing a multicore version. I have developed HEARTBEAT for sincronizing fast processes via PIPE. I will demostrate but i don't have multicore for develop :(


einstein1969
Last edited by einstein1969 on 31 Aug 2015 15:19, edited 1 time in total.

einstein1969
Expert
Posts: 961
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Explorer3D Beta

#8 Post by einstein1969 » 04 Jul 2015 15:53

After an year..

I have rewritten from scratch the code. This version has:

- New faster algorithm. Not optimizated for now.
- Use a mix of transpose algorithm of penpen/dbenham/Aacini. THANK YOU GUYS!
- Use new set of character for better visualize and fast antialiasing.
- Detect when a player slamming against the wall.
- You can use WASD for move!
- You can view the player in the MAP.
- You can modify the MAP more easily.
- The code is small.

I have added control with Choice.exe but i have a problem when the player slams on the wall.
The Choice advances the line! It's possible control better? Any suggestions?

New code:

Code: Select all

@echo off

:: SimplyExplorer3D ver. 0.1

setlocal EnableDelayedExpansion

rem Init the console and some variables

call :Init

set /A y=1, MapsizeX=23, MapsizeY=10, MapsizeX-=1

rem Load and visualize the Map grid. 1/2=wall 0=empty 9=player position

for %%D in (
"12121212120002121212121"
"20000000010001000000002"
"10000000021212000012101"
"20000000000000000001002"
"10009000000000000000001"
"20000100012121000000002"
"10000200020002000001001"
"10000100010001000012002"
"20000200020002000000001"
"12122121210001212121212"
) do (
  set Map[!y!]=%%~D
  for %%Y in (!y!) do for /L %%X in (0,1,!MapSizeX!) do (
    if "!Map[%%Y]:~%%X,1!" equ "9" (
      set /A nx=%%X+1
      for %%Z in (!nx!) do set Map[!y!]=!Map[%%Y]:~0,%%X!0!Map[%%Y]:~%%Z!
      set /A Playerx = %%X, Playery = !y!
    )
  )
  set /A y+=1
  echo(
)
  set nx=
  set y=

  set /A MulPlayer=10000
  set /A Playerx*=MulPlayer, Playery*=MulPlayer, OldPlayerx=Playerx, OldPlayery=Playery, angle1=0

:loop

  set /a gridX=Playerx/MulPlayer, gridy=Playery/MulPlayer

  for %%X in (!gridx!) do for %%Y in (!gridy!) do if "!Map[%%Y]:~%%X,1!" geq "1" (

    set /A Playerx = OldPlayerx, Playery = OldPlayery
    set /P "=%BEL%" <nul

  ) else (
 
    cls
    call :raycast
    call :drawMap

    echo Playerx:!Playerx! Playery:!playery! oldplayerx:!oldplayerx! oldplayery=!oldplayery!
    echo Angle1:!angle1! gridx:!gridx! gridy:!gridy!

    set /A OldPlayerx = Playerx, OldPlayery = Playery

  )

  call :Sin_Cos "!angle1! * PI / 180" StepY StepX

  rem use "where choice" for localize choice.exe
  C:\Windows\System32\choice.exe /M "Use WASD for move" /N /C wasd 2>nul

  rem "w" UP
  if %errorlevel% == 1 set /A "PlayerX=PlayerX + StepX / 2, PlayerY=PlayerY + StepY / 2"

  rem "a" LEFT
  if %errorlevel% == 2 set /A angle1-=15
 
  rem "s" DOWN
  if %errorlevel% == 3 set /A "PlayerX=PlayerX - StepX / 2, PlayerY=PlayerY - StepY / 2"

  rem "d" RIGHT
  if %errorlevel% == 4 set /A angle1+=15
 
  goto :loop

goto :eof

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:raycast

  echo !time: =0!> "%tmp%\t1.txt"

  set /A from=angle1-32, to=angle1+32, Mul1=25, MaxIter1=500, MaxIter2=50
  setlocal
 (
  set from=
  set to=
  set MaxIter1=
  set MaxIter2=
  set Mul1=
  set PlayerX=
  set PlayerY=
  set MulPlayer=
  set Angle1=
  set MapSizeX=
  set MapSizeY=
  set BEL=
  set OldPlayerX=
  set OldPlayerY=
  set TMP=
 
  for /L %%Z in (%from%,1,%to%) do (

    title %%Z

    call :Sin_Cos_Cos "%%Z * PI / 180" aStepY aStepX "((%%Z-%Angle1%) * PI / 180)" corr

    set /A ax = %PlayerX%*%Mul1%, ay = %PlayerY%*%Mul1%

    set "BREAK=" & set "DistanceCount="

    for /L %%? in (1,1,%MaxIter1%) do if not defined BREAK (

        set /A ax=ax+aStepX, ay=ay+aStepY, gridX=ax/%MulPlayer%/%Mul1%, gridY=ay/%MulPlayer%/%Mul1%

        for %%X in (!gridX!) do for %%Y in (!gridY!) do if "!Map[%%Y]:~%%X,1!" geq "1" set BREAK=true & set DistanceCount=%%?

    )

    if not defined DistanceCount set /A Distancecount=%MaxIter1%

    set /A "accumul=DistanceCount*(10000/%Mul1%)"

    rem Last Step

    set /A "ax = (ax-aStepX)*10, ay = (ay-aStepY)*10"

    set "BREAK=" & set "DistanceCount="

    for /L %%? in (1,1,%MaxIter2%) do if not defined BREAK (

        set /A ax=ax+aStepX, ay=ay+aStepY, gridX=ax/%MulPlayer%/%Mul1%/10, gridY=ay/%MulPlayer%/%Mul1%/10

        for %%X in (!gridX!) do for %%Y in (!gridY!) do if "!Map[%%Y]:~%%X,1!" geq "1" set BREAK=true & set DistanceCount=%%?

    )

    if not defined DistanceCount set /A Distancecount=%MaxIter2%

    for %%X in (!gridX!) do for %%Y in (!gridY!) do set "C=!Map[%%Y]:~%%X,1!"

    set /A "distance=500/(K=((DistanceCount+accumul+1)*corr/%Mulplayer%+555)/1000), len=distance*2, st=(50-len)/2"

    if !st! lss 1 set st=1

    set SS=°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
    set S2=±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
    set S_=úúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúú
    set SP=\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

    for %%X in (!st!) do for %%Y in (!len!) do (
      if !C! equ 1 (
             echo -!S_:~0,%%X!°±²Û²±°!SS:~0,%%Y!°±²Û²±°!SP:~0,%%X!-
      ) else echo -!S_:~0,%%X!°±²Û²±°!S2:~0,%%Y!°±²Û²±°!SP:~0,%%X!-
    )

    set Accumul=
    set corr=
    set C=
    set Distance=
    set len=
    set st=
    set SS=
    set S2=
    set S_=

  )

 )> "%tmp%\test.txt"

  endlocal

  call :transpose
 
  set /P "t1=" < "%tmp%\t1.txt"
  for /F "tokens=1-8 delims=:.," %%a in ("!t1!:!time: =0!") do set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31)&8640000"
  echo Time Elapsed:!a!cs

goto :eof

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:transpose

setlocal

::dbenham/penpen/Aacini transpose
 
  set /A LineN=0

:: Load and transpose data
  for /f usebackq^ delims^=^ eol^= %%A in ("%tmp%\test.txt") do (
    set /A LineN+=1
    set "N!LineN!=%%A"
  )

  set /A "MaxN=LineN-1"
  set "transposedLine="
  for /L %%m in (1, 1, !LineN!) do set "transposedLine=!transposedLine!^!%%^A%%m:~%%n,1^!"

  for %%A in (N) do for /L %%n in (0, 1, !MaxN!) do echo(^|%transposedLine%^|

endlocal

goto :eof

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:drawMap

  set /A gridX=Playerx/MulPlayer, gridy=Playery/MulPlayer

  for /L %%Y in (1,1,!MapsizeY!) do (
    for /L %%X in (0,1,!MapsizeX!) do (

      if "!Map[%%Y]:~%%X,1!" geq "1" (
        set /p "=Û" <nul
      ) else (
        if !gridX! equ %%X (
          if !gridY! equ %%Y (set /p "=@" <nul) else set /p "=." <nul
        ) else set /p "=." <nul
      )
    )
    echo(
  )
goto :eof

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:Init

  mode 100,80
  echo For best view use raster font 8x8 or 16x8.
  pause

  for /f %%i in ('forfiles /m "%~nx0" /c "cmd /c echo 0x07"') do set BEL=%%i

  for /f "delims==" %%v in ('set') do if /I not "%%v" == "TMP" if /I not "%%v" == "BEL" set %%v=

goto :eof

::::::::::::::::::::::::::::::::::: TRIGONOMETRIC FUNCTIONS

:Sin_Cos_Cos
  setlocal

  set /a "PI=(35500000/113+5)/10, PI_div_2=(35500000/113/2+5)/10, PIx2=2*PI, PI32=PI+PI_div_2"
  set "SIN=(a-a*a/1920*a/312500+a*a/1920*a/15625*a/15625*a/2560000-a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000)"

    set /a "a=(%~1) %% %PIx2%, b=(a>>31|1)*a"
    if !b! gtr %PI32% (set /a "a=a-(a>>31|1)*%PIx2%, c=%SIN%")  else (
      if !b! gtr %PI_div_2% (set /a "a=(a>>31|1)*%PI%-a, c=%SIN%") else set /a "c=%SIN%")

    set /a "a=(%PI_div_2%-%~1) %% %PIx2%, b=(a>>31|1)*a"
    if !b! gtr %PI32% (set /a "a=a-(a>>31|1)*%PIx2%, d=%SIN%")  else (
      if !b! gtr %PI_div_2% (set /a "a=(a>>31|1)*%PI%-a, d=%SIN%") else set /a "d=%SIN%")

    set /a "a=(%PI_div_2%-%4) %% %PIx2%, b=(a>>31|1)*a"
    if !b! gtr %PI32% (set /a "a=a-(a>>31|1)*%PIx2%, b=%SIN%")  else (
      if !b! gtr %PI_div_2% (set /a "a=(a>>31|1)*%PI%-a, b=%SIN%") else set /a "b=%SIN%")

 
  (endlocal & set "%2=%c%" & set "%3=%d%" & set "%5=%b%")
goto :eof

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:Sin_Cos
  setlocal

  set /a "PI=(35500000/113+5)/10, PI_div_2=(35500000/113/2+5)/10, PIx2=2*PI, PI32=PI+PI_div_2"
  set "SIN=(a-a*a/1920*a/312500+a*a/1920*a/15625*a/15625*a/2560000-a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000)"

    set /a "a=(%~1) %% %PIx2%, b=(a>>31|1)*a"
    if !b! gtr %PI32% (set /a "a=a-(a>>31|1)*%PIx2%, c=%SIN%")  else (
      if !b! gtr %PI_div_2% (set /a "a=(a>>31|1)*%PI%-a, c=%SIN%") else set /a "c=%SIN%")

    set /a "a=(%PI_div_2%-%~1) %% %PIx2%, b=(a>>31|1)*a"
    if !b! gtr %PI32% (set /a "a=a-(a>>31|1)*%PIx2%, a=%SIN%")  else (
      if !b! gtr %PI_div_2% (set /a "a=(a>>31|1)*%PI%-a, a=%SIN%") else set /a "a=%SIN%")
 
  (endlocal & set "%2=%c%" & set "%3=%a%")
goto :eof


einstein1969
Last edited by einstein1969 on 05 Jul 2015 03:45, edited 2 times in total.

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Explorer3D Beta

#9 Post by Ed Dyreen » 04 Jul 2015 16:56

einstein1969 wrote:I have added control with Choice.exe but i have a problem when the player slams on the wall.
The Choice advances the line! It's possible control better? Any suggestions?
Do you know how to retrieve keyboard input using xcopy ?

Code: Select all

for /F eol^=1delims^= %%? in ( 'xcopy/WQL "!comspec!" \' ) do set "k=%%?" &set "k=!k:~-1!" &echo.k=!k!_
But if you don't want xcopy to wait for input which I imagine you don't then this is problematic.

I did not run your batch, but I believe it's possible to prevent choice from printing anything at all, did you try choice in a for loop ?

I remember dave's snake batch game, I would look there.

einstein1969
Expert
Posts: 961
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Explorer3D Beta

#10 Post by einstein1969 » 05 Jul 2015 02:39

Hi Ed,

I know the xcopy method, but for me is difficult implement the algorithm because i need a loop inside another loop
for exclude other (not WASD) key pressed. And there is the problem of break a For /L loop inside another loop...

I add a screenshot for view the nice result. :)

Image


einstein1969

einstein1969
Expert
Posts: 961
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Dos Batch Raycast - Explorer3D Beta

#11 Post by einstein1969 » 19 Aug 2015 17:32

I have released a new version @ viewtopic.php?f=3&t=5824.

Code: Select all

:: ver. 0.2     20/08/2015
::  - Not clear the screen until next.
::  - Added moviment on left/ritgh and key "K" "L" for rotate.
::  - Fixed bug on calculate distance
::  - Added partial clipping on Z (Distance)


einstein1969

jeb
Expert
Posts: 1055
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: Dos Batch Raycast - Explorer3D Beta

#12 Post by jeb » 25 Aug 2015 11:09

Hi,

I was fascinated by your batch :o
But on my system it's very slow (~2000ms), so I decided to optimized it a bit.
The new version needs ~800ms for the same picture.

The main improvements are in the raycast function.
I inlined the call :Sin_Cos_Cos function.

And the both ray loops are changed so that always the next gridX/Y pair is directly calculated instead of iterating in small steps.


Code: Select all

:::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: Dos Batch Raycast ver. 0.3 BETA  by Francesco Poscetti aka einstein1969
::
:: This type of Engine 3D is used by  Wolfentein 3D,
:: Rise Of The Triad, DOOM, Duke Nukem 3D, etc.
::
:: Ref: http://www.dostips.com/forum/viewtopic.php?f=3&t=5824
::
:: Thanks to Aacini, foxidrive, dbenham, penpen
::
:: Tested on Windows 7
::
:: Changelog
:: ver. 0.3     jeb  2015-08-25
::  - Improved speed by inlining the Sinus calculation (~15% on reference system)
::  - Improved speed by direct calculating the next gridX/Y coordinates (~60%)
::
:: ver. 0.2     20/08/2015
::  - Not clear the screen until next.
::  - Added moviment on left/ritgh and key "K" "L" for rotate.
::  - Fixed bug on calculate distance
::  - Added partial clipping on Z (Distance)
::
:: ver. 0.1     04/07/2015
::  - New faster algorithm. Not optimizated for now.
::  - Use transpose trick of penpen
::  - Use new set of character for better visualize and fast antialiasing.
::  - Detect when a player slamming against the wall.
::  - You can use WASD for move!
::  - You can view the player in the MAP.
::  - You can modify the MAP more easily.
::
:: Ver. 0.01b   10/08/2014
::  - Added temporary dir and use swapout mechanism for manage env.
::
:: Ver. 0.01a   09/08/2014
::  - Initial version + some fixes
::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::

@echo off
setlocal

setlocal EnableDelayedExpansion
call :Init
del test.txt 2> nul
set /A y=1, MapsizeX=23, MapsizeY=10, MapsizeX-=1

rem Load the Map grid. 1/2=wall 0=empty 9=player position

for %%D in (
"12121212120002121212121"
"20000000010001000000002"
"10000000021212000012101"
"20000000000000000001002"
"10009000000000000000001"
"20000100012121000000002"
"10000200020002000001001"
"10000100010001000012002"
"20000200020002000000001"
"12122121210001212121212"
) do (
  set Map[!y!]=%%~D
  for %%Y in (!y!) do for /L %%X in (0,1,!MapSizeX!) do (
    if "!Map[%%Y]:~%%X,1!" equ "9" (
      set /A nx=%%X+1
      for %%Z in (!nx!) do set Map[!y!]=!Map[%%Y]:~0,%%X!0!Map[%%Y]:~%%Z!
      set /A Playerx = %%X, Playery = !y!
    )
  )
  set /A y+=1
)
  set nx=
  set y=

  set /A MulPlayer=10000
  set /A Playerx*=MulPlayer, Playery*=MulPlayer, OldPlayerx=Playerx, OldPlayery=Playery, angle1=0

:loop

  set /a gridX=Playerx/MulPlayer, gridy=Playery/MulPlayer

  for %%X in (!gridx!) do for %%Y in (!gridy!) do if "!Map[%%Y]:~%%X,1!" geq "1" (

    set /A Playerx = OldPlayerx, Playery = OldPlayery
    set /P ".=%BEL%"<nul

  ) else (

    call :Sin_Cos_Cos "!angle1! * PI / 180" StepY StepX dummy dummy

    call :raycast
    call :drawMap

    echo Playerx:!Playerx! Playery:!playery! oldplayerx:!oldplayerx! oldplayery=!oldplayery!
    echo Angle1:!angle1! gridx:!gridx! gridy:!gridy! StepX=!StepX! StepY=!StepY!

    set /A OldPlayerx = Playerx, OldPlayery = Playery

  )


  rem use 'where choice' for localize choice.exe
  C:\Windows\System32\choice.exe /N /C wksladzu >nul


  rem "w" UP-FORWARD
  if %errorlevel% == 1 set /A "PlayerX=PlayerX + StepX / 2, PlayerY=PlayerY + StepY / 2"

  rem "s" DOWN-BACKWARD
  if %errorlevel% == 3 set /A "PlayerX=PlayerX - StepX / 2, PlayerY=PlayerY - StepY / 2"

  rem "k" ROTATE LEFT
  if %errorlevel% == 2 set /A angle1-=15
 
  rem "l" ROTATE RIGHT
  if %errorlevel% == 4 set /A angle1+=15
 
  rem "a" LEFT
  if %errorlevel% == 5 set /A "PlayerX=PlayerX + StepY / 2, PlayerY=PlayerY - StepX / 2"

  rem "d" RIGHT
  if %errorlevel% == 6 set /A "PlayerX=PlayerX - StepY / 2, PlayerY=PlayerY + StepX / 2"

  set "oldSys=0"
  if %errorlevel% == 7 set "oldSys=1"

  goto :loop

goto :eof

:raycast

echo !time: =0!> "%tmp%\t1.txt"

set /A from=angle1-32, to=angle1+32, Mul1=25, MaxIter1=500, MaxIter2=50, ti=0
set /a MM=%MulPlayer%*%Mul1%
set /A M10=%MulPlayer%*%Mul1%*10

setlocal
(

    set /A ti=0
    for /L %%Z in (%from%,1,%to%) do (

        set /A ti+=1
        for %%t in (!ti!) do (
            set sts=!sti:~0,%%t!
            REM !si[%%t]!
        )

        title !sts!

        rem     call :Sin_Cos_Cos "%%Z * PI / 180" aStepY aStepX "((%%Z-%Angle1%) * PI / 180)" corr
        REM Sin_Cos inline for speed
        (
            setlocal
            set "p1=%%Z * PI / 180"
            set "p4=((%%Z-%Angle1%) * PI / 180)"

            set /a "a=(!p1!) %% %PIx2%, b=(a>>31|1)*a"
            if !b! gtr %PI32% (set /a "a=a-(a>>31|1)*%PIx2%, c=%SIN%")  else (
            if !b! gtr %PI_div_2% (set /a "a=(a>>31|1)*%PI%-a, c=%SIN%") else set /a "c=%SIN%")

            set /a "a=(%PI_div_2%-!p1!) %% %PIx2%, b=(a>>31|1)*a"
            if !b! gtr %PI32% (set /a "a=a-(a>>31|1)*%PIx2%, d=%SIN%")  else (
            if !b! gtr %PI_div_2% (set /a "a=(a>>31|1)*%PI%-a, d=%SIN%") else set /a "d=%SIN%")

            set /a "a=(%PI_div_2%-!p4!) %% %PIx2%, b=(a>>31|1)*a"
            if !b! gtr %PI32% (set /a "a=a-(a>>31|1)*%PIx2%, b=%SIN%")  else (
            if !b! gtr %PI_div_2% (set /a "a=(a>>31|1)*%PI%-a, b=%SIN%") else set /a "b=%SIN%")

            for /F "tokens=1,2,3" %%A in ("!c! !d! !b!") do (
                endlocal
                set "aStepY=%%A"
                set "aStepX=%%B"
                set "corr=%%C"
            )
        )

        REM   Precompute how mulX/Y has to be computed
        if !aStepX! equ 0 (set "formX=set mul=%MaxIter1%" & set mulX=%MaxIter1%) else if !aStepX! GTR 0 (
            set "formX=set /a mulX=(aStepX+%MM%-(ax %% %MM%))/aStepX, mul=mulX"
        ) ELSE if !aStepX! LSS 0 (
            set "formX=set /a mulX=-(ax %% %MM%)/aStepX+1,mul=mulX"
        )
        if !aStepY! equ 0 (set "formY=" & set mulY=%MaxIter1%) else if !aStepY! GTR 0 (
            set "formY=set /a mulY=(aStepY+%MM%-(ay %% %MM%))/aStepY"
        ) ELSE if !aStepY! LSS 0 (
            set "formY=set /a mulY=-(ay %% %MM%)/aStepY+1"
        )

        set /A ax=%PlayerX%*%Mul1%, ay=%PlayerY%*%Mul1%
        set "fir=(!ax!,!ay!)"
        set "BREAK=" & set /A Distancecount=%MaxIter1%

        if "%oldSys%"=="1" (
            for /L %%? in (1,1,%MaxIter1%) do if not defined BREAK (
                set /a cnt+=1
                set /A ax=ax+aStepX, ay=ay+aStepY, gridX=ax/%MulPlayer%/%Mul1%, gridY=ay/%MulPlayer%/%Mul1%
                for /f "tokens=1,2" %%X in ("!gridX! !gridY!") do if "!Map[%%Y]:~%%X,1!" geq "1" set BREAK=true & set DistanceCount=%%?
            )   
        ) ELSE (
            set dis=0
            for /L %%? in (1,1,20) do if not defined BREAK (
                set /a cnt+=1
               
                !formX!
                !formY!           
                if !mulX! GEQ !mulY! (
                    set /a mul=mulY
                )
                set /a ax+=aStepX*mul, ay+=aStepY*mul,dis+=mul
                set /a gridX=ax/%MM%, gridY=ay/%MM%
                for /f "tokens=1,2" %%X in ("!gridX! !gridY!") do if "!Map[%%Y]:~%%X,1!" geq "1" set BREAK=true & set /a DistanceCount=dis
            )
        )

        rem if !ti! == 63 set "out=!fir! (!ax!,!ay!) (!gridX!,!gridY!) (!aStepX!,!aStepY!)"
        set /A "accumul=DistanceCount*(10000/%Mul1%)"

        rem Last Step
        set /A "ax = (ax-aStepX)*10, ay = (ay-aStepY)*10"

        set "BREAK=" & set /A Distancecount=%MaxIter2%

        if "%oldSys%"=="1" (
            for /L %%? in (1,1,%MaxIter2%) do if not defined BREAK (

                set /A ax=ax+aStepX, ay=ay+aStepY, gridX=ax/%M10%, gridY=ay/%M10%

                for /f "tokens=1,2" %%X in ("!gridX! !gridY!") do if "!Map[%%Y]:~%%X,1!" geq "1" set BREAK=true & set DistanceCount=%%?
            )
        ) ELSE (
            set dis=0
            for /L %%? in (1,1,20) do if not defined BREAK (
                if !aStepX! equ 0 (set mulX=90) ELSE if !aStepX! GTR 0 (
                    set /a "mulX=(aStepX+%M10%-(ax %% %MM%))/aStepX"
                ) ELSE (
                    set /a "mulX=((ax %% %M10%))/-aStepX+1"
                )
               
                if !aStepY! equ 0 (set mulY=90) ELSE if !aStepY! GTR 0 (
                    set /a "mulY=(aStepY+%M10%-(ay %% %M10%))/aStepY"
                ) ELSE (
                    set /a "mulY=((ay %% %M10%))/-aStepY+1"
                )
                set mul=!mulX!
                if !mulX! GEQ !mulY! (
                    set /a mul=mulY
                )
                set /a ax+=aStepX*mul, ay+=aStepY*mul,dis+=mul
                set /a gridX=ax/%M10%, gridY=ay/%M10%
               
                for /f "tokens=1,2" %%X in ("!gridX! !gridY!") do if "!Map[%%Y]:~%%X,1!" geq "1" set BREAK=true & set /a DistanceCount=dis
            )
        )

        for /f "tokens=1,2" %%X in ("!gridX! !gridY!") do set "C=!Map[%%Y]:~%%X,1!"

        set /A "distance=350/((((DistanceCount+accumul)*corr/%Mulplayer%+555)/1000)+1), len=distance*2, st=(50-len)/2"

        rem 2D-clipping
        if !st! lss 1 set st=1
        if !st! gtr 50 set st=50

        for /f "tokens=1,2" %%X in ("!st! !len!") do (
          if !C! equ 1 (
                 if !st! gtr 23 (echo -!S_:~0,%%X!úúúúúúú!S_:~0,%%Y!_______!SP:~0,%%X!-) else (
                 echo -!S_:~0,%%X!°±²Û²±°!SS:~0,%%Y!°±²Û²±°!SP:~0,%%X!-
                 )
          ) else if !st! gtr 23 (echo -!S_:~0,%%X!úúúúúúú!S_:~0,%%Y!_______!SP:~0,%%X!-) else (
                   echo -!S_:~0,%%X!°±²Û²±°!S2:~0,%%Y!°±²Û²±°!SP:~0,%%X!-
                 )
        )
       
    )

)> "%tmp%\test.txt"

endlocal

call :transpose

set /P "t1=" < "%tmp%\t1.txt"
for /F "tokens=1-8 delims=:.," %%a in ("!t1!:!time: =0!") do set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31)&8640000"
echo Time Elapsed:!a!0ms

goto :eof

:transpose

setlocal
 
  set /A LineN=0

:: Load and transpose data
  for /f usebackq^ delims^=^ eol^= %%A in ("%tmp%\test.txt") do (
    set /A LineN+=1
    set "N!LineN!=%%A"
  )

  set /A "MaxN=LineN-1"
  set "transposedLine="
  for /L %%m in (1, 1, !LineN!) do set "transposedLine=!transposedLine!^!%%^A%%m:~%%n,1^!"

  cls
  rem to FIX
  set/A MaxN=65
  for %%A in (N) do for /L %%n in (0, 1, !MaxN!) do echo(^|%transposedLine%^| %%n

endlocal

goto :eof

:drawMap

  set /A gridX=Playerx/MulPlayer, gridy=Playery/MulPlayer

  for /L %%Y in (1,1,!MapsizeY!) do (
    for /L %%X in (0,1,!MapsizeX!) do (

      if "!Map[%%Y]:~%%X,1!" geq "1" (
        set /p "=Û" <nul
      ) else (
        if !gridX! equ %%X (
          if !gridY! equ %%Y (set /p "=@" <nul) else set /p "=." <nul
        ) else set /p "=." <nul
      )
    )
    echo(
  )
goto :eof


:Init
    mode 80,80
    color 0F
    echo For best view use raster font 8x8 or 16x8.
    echo(
    echo Use WASD for move and KL for turn/rotate.
    echo(
    rem pause
    cls&echo Loading...

    for /f %%i in ('forfiles /m "%~nx0" /c "cmd /c echo 0x07"') do set BEL=%%i
    set bel=Z
    for /f "delims==" %%v in ('set') do if /I not "%%v" == "TMP" if /I not "%%v" == "BEL" set %%v=

    set "sti=|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"
    set "SS=°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°"
    set "SC=/////////////////////////////////////////////////////////////////////////////////////////////"
    set "S2=±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±"
    set "S_=úúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúú"
    set "SP=_____________________________________________________________________________________________"
    set /a "PI=(35500000/113+5)/10, PI_div_2=(35500000/113/2+5)/10, PIx2=2*PI, PI32=PI+PI_div_2"
    set "SIN=(a-a*a/1920*a/312500   +a*a/1920*a/15625*a/15625*a/2560000   -a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000)"

goto :eof

::::::::::::::::::::::::::::::::::: TRIGONOMETRIC FUNCTIONS

:Sin_Cos_Cos rad*10000 return_var*10000     rem RADIANT
  setlocal

    set "SIN=(a-a*a/1920*a/312500   +a*a/1920*a/15625*a/15625*a/2560000   -a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000)"
   
 
    set /a "a=(%~1) %% %PIx2%, b=(a>>31|1)*a"
    if !b! gtr %PI32% (set /a "a=a-(a>>31|1)*%PIx2%, c=%SIN%")  else (
      if !b! gtr %PI_div_2% (set /a "a=(a>>31|1)*%PI%-a, c=%SIN%") else set /a "c=%SIN%")

    set /a "a=(%PI_div_2%-%~1) %% %PIx2%, b=(a>>31|1)*a"
    if !b! gtr %PI32% (set /a "a=a-(a>>31|1)*%PIx2%, d=%SIN%")  else (
      if !b! gtr %PI_div_2% (set /a "a=(a>>31|1)*%PI%-a, d=%SIN%") else set /a "d=%SIN%")

    set /a "a=(%PI_div_2%-%4) %% %PIx2%, b=(a>>31|1)*a"
    if !b! gtr %PI32% (set /a "a=a-(a>>31|1)*%PIx2%, b=%SIN%")  else (
      if !b! gtr %PI_div_2% (set /a "a=(a>>31|1)*%PI%-a, b=%SIN%") else set /a "b=%SIN%")

 
  (endlocal & set "%2=%c%" & set "%3=%d%" & set "%5=%b%")
goto :eof

einstein1969
Expert
Posts: 961
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Dos Batch Raycast - Explorer3D Beta

#13 Post by einstein1969 » 27 Aug 2015 14:02

Thanks jeb! Now is fast. 8)

It's taking quite a while to understand your code. :shock:

EDIT: I have update the first post.

Einstein1969

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: Dos Batch Raycast - Explorer3D Beta

#14 Post by npocmaka_ » 27 Aug 2015 14:40

this is amazing!

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Dos Batch Raycast - Explorer3D Beta

#15 Post by dbenham » 27 Aug 2015 15:52

Yes, this is really impressive and cool :shock: 8)

Currently the Angle1 can be less than 0 and greater than 360. It would be nice if the angle is always recomputed and displayed as

Code: Select all

set /a Angle1=(Angle1+360)%%360

That will keep the value between 0 and 359.

Also, it would be nice if the character used to represent the Player in the top view map was updated to indicate the angle as follows:

Code: Select all

345   0  15  >
 30  45  60  \
 75  90 105  v
120 135 150  /
165 180 195  <
210 225 240  \
255 270 285  ^
300 315 330  /


EDIT:

The following minor changes implement the recommendations above:

Code: Select all


:: ------ Near top during initialization
:: Define player characters:
for %%# in (
  "345   0  15  >"
  " 30  45  60  \"
  " 75  90 105  v"
  "120 135 150  /"
  "165 180 195  <"
  "210 225 240  \"
  "255 270 285  ^"
  "300 315 330  /"
) do for /f "tokens=1-4" %%A in (%%#) do (
  set "P%%A=%%D"
  set "P%%B=%%D"
  set "P%%C=%%D"
)

:: In Main loop -----------------------
set /a "angle1=(angle1+360)%%360"
    call :raycast
    call :drawMap


:: In :drawMap   ------------------

        if !gridX! equ %%X (
          if !gridY! equ %%Y (set /p "=!P%angle1%!" <nul) else set /p "=." <nul
        ) else set /p "=." <nul



Dave Benham

Post Reply