windows - Windows批处理文件街机游戏的优化

标签 windows batch-file optimization

我制作了一个批处理文件游戏,它可以运行,但它不稳定且丑陋。我已经了解线程,但我不想在我的第一个版本中实现它。我希望在我开始用这个游戏做更高级的事情之前降低优化。我的问题是:我可以对这款游戏进行哪些优化,使其 1. 不会断断续续 2. 显示效果不会那么烦人。欢迎任何有关如何使其更快更清晰或占用更少内存的想法或评论,但是,请不要发布以下答案:“不要使用批处理”“重写(在此处插入语言)”“用 vb 执行此部分-script”等...因为它们没有帮助,也没有回答问题。欢迎任何和所有非批量仇恨的批评。

代码如下:

@setlocal enableextensions enabledelayedexpansion
@echo off
color 0a
mode con lines=35 cols=50
cls
set instructions=use a and d to move left and right, w to fire. use q to quit and p to pause.
set height=30
set length=         
set screen=50
set swidth=20
set amo=8
set lives=3
set 1=0
set 2=1
set 3=2
set 4=3
set 5=4
set 6=0
set 7=1
set 8=2
set 9=3
set 10=4

echo. What quality would you like?
echo.   1. fast, but the graphics suck!
echo.   2. medium both ways.
echo.   3. slow, but the graphics are better!
choice /n /c:123
set firequal=%errorlevel%00
cls
echo %instructions%
echo.
pause
cls

::main
:controls
cls
if %height% EQU 2 goto gameover
if %lives% LSS 1 goto gameover
cls
set /a shouldbomb+=1
set /a whenbomb=shouldbomb%%15
if %whenbomb% == 9 call :bomb
if '%ret%'=='1' exit /b
set ret=
cls
set alive=
for /l %%i in (1,1,10) do if defined %%i set alive=true
if not defined alive goto win
cls
for /l %%i in (1,1,5) do (
      if defined %%i (
     set /p a=[_]  <nul
      ) else (
     set /p a=...  <nul
      )
)
echo.
for /l %%i in (6,1,10) do (
      if defined %%i (
     set /p a=[_]  <nul
      ) else (
     set /p a=...  <nul
      )
)
for /l %%a in (1,1,%height%) do echo.
echo %length%[]
echo.
for /l %%i in (1,1,%amo%) do set /p a=^|<nul
echo.
choice /c adwqp0 /n /t 1 /d 0
if %errorlevel% equ 1 goto :left
if %errorlevel% equ 2 goto :right
if %errorlevel% equ 3 goto :fire
if %errorlevel% equ 4 (cls&exit /b)
if %errorlevel% equ 5 pause&goto controls
if %errorlevel% equ 6 goto :inactive
goto controls

::move player left
:left
if '!length!' NEQ '' set length=!length:~0,-1!
goto controls

::move player right
:right
call :strlen shiplen length
if %shiplen% GTR %swidth% goto controls
set length=%length% 
goto controls

::fire a shot upwards
:fire
if '!amo!' LSS '1' goto controls
cls
set /a amo-=1
for /l %%i in (%height%,-1,2) do (
   cls
   for /l %%i in (1,1,5) do (
     if defined %%i (
        set /p a=[_]  <nul
     ) else (
        set /p a=...  <nul
     )
   )
   echo.
   for /l %%i in (6,1,10) do (
     if defined %%i (
        set /p a=[_]  <nul
     ) else (
        set /p a=...  <nul
     )
   )
   for /l %%j in (1,1,%%i) do echo.
   echo %length% ^
   set /a ship=height-%%i-1
   for /l %%b in (1,1,!ship!) do echo.
   echo %length%[]
   echo.
   for /l %%i in (1,1,%amo%) do set /p a=^|<nul
   echo.
   for /l %%a in (1,1,%firequal%) do call >nul 2>&1
)
call :checkshot
set /a shouldbomb+=1
set /a whenbomb=shouldbomb%%2
if %whenbomb% == 0 call :bomb
goto controls

:inactive
if %amo% LSS 10 set /a amo+=1
if !height! NEQ 2 set /a height-=1
call :bomb
goto controls

:bomb
:btop
set bombx=
for /l %%a in (1,1,10) do (
   if defined %%a (
     set /a randomnum=%random%%%5
     if '!%%a!'=='%randomnum%' (
        set /a "bombx=5*(!%%a!)"
     )
      )
   )
)
if not defined bombx goto btop
cls
set bomb= 
for /l %%b in (1,1,!bombx!) do (
      set bomb=!bomb! 
)
set /a bombh=height-1
for /l %%c in (1,1,!bombh!) do (
   cls
   for /l %%i in (1,1,5) do (
     if defined %%i (
        set /p a=[_]  <nul
     ) else (
        set /p a=...  <nul
     )
   )
   echo.
   for /l %%i in (6,1,10) do (
     if defined %%i (
        set /p a=[_]  <nul
     ) else (
        set /p a=...  <nul
     )
   )
   for /l %%b in (1,1,%%c) do echo.
   echo !bomb!x
   set /a ship=height-%%c-1
   for /l %%b in (1,1,!ship!) do echo.
   echo %length%[]
   echo.
   for /l %%i in (1,1,%amo%) do set /p a=^|<nul
   echo.
   for /l %%a in (1,1,%firequal%) do call >nul 2>&1
)
if "%bomb%"   == "%length%"   call :looselife
if "%bomb% "  == "%length%"   call :looselife
if "%bomb%"   == "%length% "  call :looselife
if "%bomb%  " == "%length%"   call :looselife
if "%bomb%"   == "%length%  " call :looselife
exit /b

:strlen <resultVar> <stringVar>
(   
    setlocal EnableDelayedExpansion
    set "s=!%~2!#"
    set "len=0"
    for %%P in (1024 512 256 128 64 32 16 8 4 2 1) do (
    if "!s:~%%P,1!" NEQ "" ( 
        set /a "len+=%%P"
        set "s=!s:~%%P!"
    )
    )
)
( 
    endlocal
    set "%~1=%len%"
    exit /b
)

:checkshot
call :strlen slen length
for /l %%i in (0,5,20) do (
   if '!slen!' == '%%i' (
      set /a hit=%%i
      set /a hit=hit/5+1
      set /a hit2=hit+5
      if not defined !hit2! set !hit!=
      if defined !hit2! set !hit2!=
   )
)
exit /b

:looselife
set /a lives-=1
set length=         
set 1=0
set 2=1
set 3=2
set 4=3
set 5=4
if %lives% GTR 1 timeout /nobreak 1 >nul 2>&1
exit /b

:win
cls
echo YOU WIN^!^!^!^!
echo.
echo GOOD JOB^!^!^!
echo.
pause
cls
exit /b

:gameover
cls
echo YOU LOOSE.
echo.
echo PLEASE TRY AGAIN.
echo.
pause
cls
set ret=1

提前感谢您的帮助。

附言我写这个游戏是为了说服一个 friend 学习 html 以外的东西,虽然批处理不是最好的,但他使用 windows,他现在只会做一些简单的事情。他十二岁,所以我认为批量是最好的选择。

最佳答案

您绝对可以大大改善事情。我知道,因为我已经制作了一个非常流畅且可玩的版本 SNAKE using pure Windows batch !试一试 - 我想你会对发霉的旧批处理的功能感到惊讶和印象深刻:-)

当然,该链接有代码,但它也有一些关于我用来使 came 表现如此出色的技术的指针。仔细阅读整个第一篇文章,并阅读该主题的其余部分以了解一些其他重要的进展。

优化是一个很大的话题。这里不再重复所有信息,我将简单地总结一下。点击链接了解更多详情。

1) 尽量减少 GOTO 和 CALL 语句。

  • 与传统的批处理函数调用相比,为了显着提高速度,我们开发了 batch macros with arguments在 DosTips。第一个宏链接发展了许多重要的概念。然而,我在游戏中实际使用的宏形式使用了更多的elegant solution with arguments appended。 .

  • GOTO 循环可以替换为在新进程中运行的无限 FOR 循环。您可以通过退出子进程来跳出循环。

2) 以非阻塞方式极大地改进了按键检测。

  • 批处理的一个主要限制是无法在不阻止游戏进程的情况下轻松检测到按键。这个问题可以通过使用两个进程来解决,这两个进程都在同一个控制台窗口中运行。 Controller 进程读取按键并通过文本文件将它们发送到主游戏进程。 Controller 具有多种操作模式。游戏进程通过另一个文本文件向 Controller 发送命令。此技术需要仔细协调输入和输出重定向。

  • CHOICE 命令在 XP 上不可用。 DosTips 的一些人发现了如何使用 XCOPY 来模拟 CHOICE 的大部分功能,并且它适用于所有版本的 Windows。非常酷!

3)屏幕绘画

  • 一个字符一个字符地构建屏幕极其缓慢。使用固定长度的字符串“数组”一次构建初始屏幕要快得多。字符串中的每个字符代表一个“像素”。字符串中的位置表示 X 坐标,字符串行号表示 Y 坐标。通常,对于任何给定的屏幕刷新,只有几个像素发生变化。可以通过使用 SET 和简单的子字符串操作来“绘制”像素。然后可以使用 CLS 快速刷新整个屏幕,然后使用屏幕阵列中每一行的 ECHO。

4)流畅的动画

  • 执行游戏逻辑和屏幕绘图所需的工作量可能会因当前游戏环境的不同而有很大差异。但是您希望动画流畅。与其在每轮移动之间设置固定延迟,不如测量自上次屏幕更新以来的时间。只有在预定的时间过去后才继续。只要所有的游戏逻辑和剧情都能在延迟时间段内发生,那么动画就会一直很流畅。

这是描述时序逻辑的伪代码:

initialize delayTime
initialize previousTime
loop (
  get currentTime
  set diffTime = currentTime - previousTime
  if diffTime >= delayTime (
    set previousTime = currentTime
    perform user input, game logic, and screen refresh
  )
)

这里是计算自上次移动以来耗时的实际代码。 currentTime (t2) 是从午夜开始计算的厘秒(1/100 秒)。它使用 FOR/F 和基础数学进行解析和计算。如果前一个时间 (t1) 在午夜之前而当前时间 (t2) 在午夜之后,则 diffTime (tDiff) 将为负数。如果为负数,则将 1 天添加到 diffTime 以获得正确的时间间隔。

%=== compute time since last move ===%
for /f "tokens=1-4 delims=:.," %%a in ("!time: =0!") do set /a "t2=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100, tDiff=t2-t1"
if !tDiff! lss 0 set /a tDiff+=24*60*60*100

还有很多可以讨论的。尝试 SNAKE.BAT 游戏,研究帖子和代码,看看您的想象力可以带您到哪里去。

关于windows - Windows批处理文件街机游戏的优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20306683/

相关文章:

batch-file - 为什么我既不能批量也不能在cmd中调用 “IF”和 “FOR”?

PHP 为什么 unset 不释放内存?

windows - 使用批处理文件在 .txt 文件中搜索双字

batch-file - 等待多个应用程序从批处理文件异步运行完成

windows - 追踪在 Windbg 中创建对象的堆栈跟踪

窗口/命令 |如果例如,如何断线字符数达到?

php - MySQL PHP 查询优化 - 反馈

Java:优化代码

python - 安装 Python 时出现问题

windows - 如何在重复分隔符处分割大型文本文件,而不是按行号或确切大小