nep*_*i12 1 windows optimization batch-file
我制作了一个批处理文件游戏,它可以工作,但它是不稳定和丑陋的.我已经了解了线程,但我不想在我的第一个版本中实现它.在我开始用这个游戏做更高级的事情之前,我希望能够优化.我的问题是:我可以对这个游戏进行哪些优化,以便它不会变得不稳定,而且在显示屏上不会那么烦人.欢迎任何有关如何使其更快更清晰或占用更少内存的想法或意见,但是,请不要发布如下答案:"不要使用批处理""重写它(在这里插入语言)""用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
Run Code Online (Sandbox Code Playgroud)
预先感谢您的任何帮助.
PS我正在写这个游戏来说服朋友除了html之外还要学习一些东西,虽然批次不是最好的,但他使用的是Windows,他现在只会做一些简单的事情.他十二岁,所以我觉得批次是最好的选择.
你绝对可以大大改善.我知道,因为我已经使用纯Windows批量生成了一个非常流畅且可玩的SNAKE版本!尝试一下 - 我想你会对那些发霉的老批可以做的事感到惊讶和印象:-)
当然链接有代码,但它也有一些指针,我曾经用过一些技术来表现得很好.仔细阅读整个第一篇文章,并阅读其余的重点发展.
优化是一个很大的主题.我将简单地总结一下,而不是重复这里的所有信息.请点击链接了解更多详情.
1)最小化GOTO和CALL语句.
对于传统批处理函数调用的主要速度改进,我们在DosTips 开发了带有参数的批处理宏.第一个宏观链接产生了许多重要概念.但是,我在游戏中实际使用的宏形式使用了附加参数的更优雅的解决方案.
GOTO循环可以由在新进程中运行的无限FOR循环替换.您可以通过退出子进程来摆脱循环.
2)以非阻塞方式大大改善按键检测.
批量的一个主要限制是无法在不阻碍游戏进程的情况下轻松检测按键.可以通过使用两个进程来解决问题,这两个进程都在同一个控制台窗口中运行.控制器进程读取按键并通过文本文件将它们发送到主游戏进程.控制器具有多种操作模式.游戏过程通过另一个文本文件向控制器发送命令.该技术需要仔细协调输入和输出重定向.
XP上没有CHOICE命令.DosTips的一些人发现了如何使用XCOPY来模拟CHOICE的大部分功能,它适用于所有版本的Windows.很酷!
3)屏幕画
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
)
)
Run Code Online (Sandbox Code Playgroud)
这是实际的代码,用于计算自上次移动以来经过的时间.currentTime(t2
)从午夜开始测量为厘秒(1/100秒).它使用FOR/F和基本数学进行解析和计算.tDiff
如果previousTime(t1
)在午夜之前并且currentTime(t2
)在午夜之后,则diffTime()将为负.如果为负数,则将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
Run Code Online (Sandbox Code Playgroud)
还有更多可以讨论的内容.尝试SNAKE.BAT游戏,研究帖子和代码,看看你的想象力可以带你去哪里.
一些优化
1)最好使用好的变量名.
名称,如1
,2
...... 10
是非常糟糕的,没有人知道他们是什么好,连你自己也不会在一个月内记住.
然后它也是一个坏主意,因为它可能有许多副作用,使用以数字开头的变量,批处理中有许多这些只会失败.
2)您应该在输出之前将输出组合成完整的行.
那你就不需要set/p
了echo
,而且速度更快.
3)对:strlen
应该避免的函数调用,调用都很昂贵,在你的情况下,应该可以在没有strlen的情况下解决相同的问题.
4)该功能:checkshot
不需要for循环.
我不明白你在那里尝试做什么,但你测试slen
它是否是5的多重.
这可以解决
set /a remainder=slen %% 5
if !remainder! EQU 0 (
...
Run Code Online (Sandbox Code Playgroud)
5)按照dbenham的提示:-)