我制作了一个批处理文件游戏,它可以工作,但它是不稳定和丑陋的.我已经了解了线程,但我不想在我的第一个版本中实现它.在我开始用这个游戏做更高级的事情之前,我希望能够优化.我的问题是:我可以对这个游戏进行哪些优化,以便它不会变得不稳定,而且在显示屏上不会那么烦人.欢迎任何有关如何使其更快更清晰或占用更少内存的想法或意见,但是,请不要发布如下答案:"不要使用批处理""重写它(在这里插入语言)""用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 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 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 ( 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
预先感谢您的任何帮助.
PS我正在写这个游戏来说服朋友除了html之外还要学习一些东西,虽然批次不是最好的,但他使用的是Windows,他现在只会做一些简单的事情.他十二岁,所以我觉得批次是最好的选择.
一些优化
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 ( ...
5)按照dbenham的提示:-)
你绝对可以大大改善.我知道,因为我已经使用纯Windows批量生成了一个非常流畅且可玩的SNAKE版本!尝试一下 - 我想你会对那些发霉的老批可以做的事感到惊讶和印象:-)
当然链接有代码,但它也有一些指针,我曾经用过一些技术来表现得很好.仔细阅读整个第一篇文章,并阅读其余的重点发展.
优化是一个很大的主题.我将简单地总结一下,而不是重复这里的所有信息.请点击链接了解更多详情.
1)最小化GOTO和CALL语句.
对于传统批处理函数调用的主要速度改进,我们在DosTips 开发了带有参数的批处理宏.第一个宏观链接产生了许多重要概念.但是,我在游戏中实际使用的宏形式使用了附加参数的更优雅的解决方案.
GOTO循环可以由在新进程中运行的无限FOR循环替换.您可以通过退出子进程来摆脱循环.
2)以非阻塞方式大大改善按键检测.
批量的一个主要限制是无法在不阻碍游戏进程的情况下轻松检测按键.可以通过使用两个进程来解决问题,这两个进程都在同一个控制台窗口中运行.控制器进程读取按键并通过文本文件将它们发送到主游戏进程.控制器具有多种操作模式.游戏过程通过另一个文本文件向控制器发送命令.该技术需要仔细协调输入和输出重定向.
XP上没有CHOICE命令.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和基本数学进行解析和计算.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
还有更多可以讨论的内容.尝试SNAKE.BAT游戏,研究帖子和代码,看看你的想象力可以带你去哪里.