Cmdgfx - draw 3d and graphic primitives (polygons,circles etc) in cmd window (now with 24-bit RGB support!)
I'm actually a little perplexed that nobody seems to be using this stuff I mean, it might not be that great but it's certainly not that bad. Of course I know far from everybody is doing graphics stuff, but if you do, then why not try it? And if you did, what was it you didn't like about it? Too cryptic, too difficult, not working properly, not fast enough, prefer another external tool (why?), or you simply don't like "non-pure" batch?
Anyway, just some thoughts. If you do decide to try it and run into issues, feel free to let me know.
I have applied quite a few of your cmdwiz operations for my new text oriented graphics script, MChoice.bat, at Mouse-Selectable Menu from a data file - a/la CHOICE. where I found some of your collaborator Antonio's "Auxiliary .exe" programs easier to work with, especially when dealing with text. I do like the smooth changes to the screen and buffer properties using cmdwiz. But, again, this was not really a graphics application. My compliments anyway.misol101 wrote:I'm actually a little perplexed that nobody seems to be using this stuff I mean, it might not be that great but it's certainly not that bad. Of course I know far from everybody is doing graphics stuff, but if you do, then why not try it? And if you did, what was it you didn't like about it? Too cryptic, too difficult, not working properly, not fast enough, prefer another external tool (why?
One day I realized the simplest thing: why not run cmdgfx with start "" /B ? This starts a separate process in the same window, leaving the batch script to run uninterrupted while the graphics is rendered. It is certainly not without its problems doing things this way, but it does increase FPS radically in many cases.
Here is plasma3.bat:
Not only does this script run at a much higher frame rate than plasma2.bat (which does not use the start /B technique), but it can even load/draw a complex 3d model such as hulk.obj over the plasma and still retain a very high framerate!
So, what are the problems/things to think about with this method?
1. First of all, since start /B runs cmdgfx in the background and returns immediately, you will not be able to get the errorlevel from the program. This means that you cannot check for keys and mouse input this way. There are a few ways to deal with this:
1.1 Right after calling cmdgfx with start /B, call "cmdwiz getch noWait", and get the errorlevel. Remember not to use the k flag in the previous call to cmdgfx
1.2 For even more speed, you can use Aacini's "Getkey.exe /N" instead. Unfortunately it doesn't use the same errorlevel output as cmdwiz, but for "basic" standard keys the codes are the same.
1.3 It is also possible to specify the new flag 'o' in the start /B call to cmdgfx. This will save the errorlevel to a file called EL.dat. You can then get the input in the script using something like: set /p KEY=<EL.dat 2>nul . This is the fastest of all these methods since no extra external program needs to be called, but it is unfortunately not reliable. Several cmdgfx might execute simultaneously and overwrite EL.dat, which means key presses might get lost. If maximum speed is needed and input is not needed at the moment, this can still be used. As an example, "bezier-col-hires-nowait.bat" uses this (you may have to press Escape a few times to quit)
1.4 To get both input AND the possiblity to synch better, a slightly cryptic call to cmdgfx_gdi is needed, see (2).
2. One problem with the start /B method is that things now sometimes runs *too fast*! The old 'W' flag was unfortunately rather useless since it measured only the time from the beginning of starting cmdgfx to the end. I changed this so that the W flag now writes a file called CGXMS.dat with the current tick count on each frame, and the wait value is then re-read on the next frame, which means the entire processing is regarded in the wait, providing a much smoother result. This way we can ensure both smooth animation and that it doesn't run too fast on faster machines.
So, to use this, this is needed (after the start /B call with cmdgfx):
cmdgfx_gdi "" kf0:0,0,0,0W10
This means: "" use no operations, report key (k), don't actually write any output (by specifying a screen with width and height of 0), and wait a MAXIMUM of 10 ms (counting from the last time the tick count was saved to file), and finally write the current tick count to file.
One more thing to note: pretty much all scripts get a higher speed using this "start /B" technique, EXCEPT the ones that need to use the non-gdi version of cmdgfx, because the effect builds the current screen output based on the previous one (like fire.bat and rotate-expr.bat). This seems to be because of my old nemesis Windows API WriteConsoleOutput, which is just soo slow when the output has many colors that the frame rate is not noticeably improved by running cmdgfx concurrently).
Many of the old scripts were updated to run with start /B, some with synching (W), some not. For some comparisons, run 3dmaze.bat then 3dmaze-noWait.bat, or bezier-col-hires.bat compared to bezier-col-hires-noWait.bat. Other new scripts are hulk.bat (spinning quite nicely in 1280x680 resolution), loader.bat, curve.bat, plasma2.bat, plasma3.bat
Final important note: Start /B can be dangerous! Even more so if combining with the /High or /realtime switches. I have managed to freeze my computer using this, forcing a reboot. In general, only use this technique as a final optimization step (if extra speed is needed) when everything else is functioning in the script, not during development.
The only new functionality of cmdgfx.exe is the possibility to make a second translation/move for the 3d operation.
Below is 3dGUI.bat. It was primarily meant to be mouse-controlled (drag left-right to scroll among items, click to select an item), but keys are also supported (left/right to scroll, SPACE to select the item in focus). If you get tired of the "swinging" effect of the items while scrolling, press RETURN to disable/enable.
Screens (it obviously looks better when actually moving):
The script takes as input a data file of the form:
Code: Select all
backgroundimage ; scale
image ; scale ; text ; action
Example file with 3 items:
img\dos_shade4.pcx ; 45
emma.txt ; 9 ;Emma; echo Emma
fract.txt ; 9 ;Fractal; echo Fractal
glass.txt ; 9 ;Glass; echo Glass
Also, I've experimented more with the block operation and managed to get multiple 2d objects moving independently, which means it's posssible to do e.g. bob-flags without precalculation. Also, I tried out jelly-like effects with images, also using the block operation.
See scripts: bob3d2.bat, bob-flag2.bat, bob-flag3.bat, dot-flag2.bat, wave-cube.bat, wave-face.bat, wave-face2.bat
1. The current version in the repo and Mediafire does not have any server capabilities. It came to my attention lately that on many machines, many of the scripts in the current archive run quite slowly. This will be remedied in the new version by using server functionalIty (though I don't think I will have the patience to convert all scripts to running with server (and in fact it is not possible in all cases at the moment either)
For an (undocumented) version with server support, you can currently use the cmdgfx executable in the Blockout archive (it may differ slightly from later "officially" released version)
2. It also came to my attention that on Win10 machines (at least), the "setfont" operation of cmdwiz.exe does not work. This means that on some machines, the scripts in the current cmdgfx archive will use the wrong font and/or window size. To remedy this (in the meantime), modify scripts to use carlos utility bg.exe instead (so where it says e.g. "cmdwiz setfont 1" change to "bg font 1" )
As a very last-minute thing I decided it would be fun to post the new Cmdgfx version before going on vacation
Repo and archive was updated (http://www.mediafire.com/download/x2lrkla93bd149o/cmdgfx.zip)
The major new thing is the possibility to run as server. This will speed things up greatly in most cases on most computers. There is also a new input server called cmdgfx_input.exe.
Look at/run the scripts called server-????.bat, those are all new server examples.
Most scripts respond to Space, p, Esc, and often to Enter and more. For example the server-gfxtest4-pixelfont scripts listen to 'Space, b, n/N, w, Enter+cursor keys, p, D/d). Also some scripts like server-alpha and server-basic-spaceship have extra effects when pressing Esc.
Will be posting much more info soon about how the new stuff works (some of it will get a bit messy )
einstein1969 wrote:last examples are beautiful. Thanks misol101!
Cmdgfx new functionality and fixes as of version 0.999, part 1:
Server functionality and server input will be covered in the next post. The following is the new non-server stuff (hopefully a bit less messy):
1. New 'operations': skip/rem. These new "operations" are simply used to nop out operations that are not needed at the moment. Useful for testing purposes and switches. While 'skip' skips a single operation, 'rem' skips all further operations on the given line.
2. Aspect value for 3d operation is now "buffer size independent". Aspect ratio previously varied with the size of the buffer. To determine the correct width/height ratio, divide the width in pixels of the font you are using with the height (so for example, for bitmap font 0, the correct aspect ratio is given by taking font pixel width (4) and dividing with height (6) = 0.6666667
3. New flags:
Several new flags are useful only for the new server functionality. I mention here only those new flags that are useful also outside of running as a server:
'n' flag for no output. Useful for reading key or mouse input without clearing the screen. Not needed for the server, but the n flag has another use in that case.
'f' flag to specify font and screen size/position for cmdgfx_gdi now has two extra parameters (so the full syntax of this "flag" is f:[x,y,w,h[,output w, output h]]. The two last parameters specify the "visible" part of the screen (the one to turn into a bitmap). This is useful when the screen buffer is purposely bigger than the visible screen to have a bigger canvas, but only a part of that canvas actually needs to be shown in the end (sometimes the case with e.g. the "block" operation)
'O' flag to write errorlevel to EL.dat only if 'something happened' (i.e key was pressed or mouse was moved), as opposed to 'o' which writes every frame (which can be quite inefficient on some drives)
'T' enables support for repeated textures for 3d operation (only for mode 0). Bit of a hack, but used in the server-zoom.bat script.
'c'[:x,y,w,h[,encode[,index]]] saves screenshot of the current buffer to file (after all operations have been rendered). The first screenshot is automatically named capture-0.gxy, the index is then increased and next screenshot is called capture-1.gxy etc. The index can also be set specifically (parameter 6), in which case counting re-starts from this number. Parameter 5 indicates if the capture should be gxy or txt file. Use 1 for gxy (default), and 0 for txt. In the second case, output will be called capture-?.txt, and contain no color code information.
'z' to sleep wait instead of waiting in a cpu busy loop. Used in conjunction with the 'w' or 'W' flags. This frees up CPU time, but unfortunately I've found it's not quite as reliable for precise realtime timing as S busy-wait-loop. For longer waits (more than ~50ms?) or when total accuracy is not needed it is definitely good to use to give the CPU some rest.
'm' is like 'M', (i.e. reports about mouse and key events), but does not report mouse events unless a mouse button is also pressed (left/right or mouse wheel). Important note: previously, 'M' (and 'm') would send info about key-UP events in addition to key-down events, but this behavior is changed. Only key-down events are reported, unless the 'u' flag is also used (see below)
'u', as mentioned above, enables sending info about key-UP events when using the 'M' or 'm' flags. Note that this was previously the default. Also note that 'u' has no effect with the 'k' flag. In order to read key-UP events, m or M must be used with 'u'.
'P' load/save buffer from file. This flag is actually superceded by the new server functionality. Perhaps it should be removed? The idea is to save the buffer contents at the end of each run and then re-read the contents when running next time. This allows cmdgfx_gdi to have a "memory", similar to the text memory of regular cmdgfx (where the cmd window's text buffer itself is the "memory", which in turn enables "progressive" effects (the new frame builds on the last) such as matrix.bat, fire.bat, life.bat, shadebobs.bat etc. Anyway, when using cmdgfx_gdi as a server, there is no need for this flag since the server is persistent in memory and thus does not need to save/load the buffer between frames.
Bug fix: move for block operation had stopped working
Bug fix: second rotation for "3d" operation had a bug
Bug fix: affine texture mapping was crashing if texture repetition was set very high
Bug fix: 'p' flag in combo with 'f' flag was crashing
To set the font in scripts, carlos BG utility is used instead of "cmdwiz setfont", since it was recently revealed that "cmdwiz setfont" does not work on Win10 machines, and the issue has not been fixed yet.
Removed all dependencies on the old lookup table sintable.bat. Instead, Aacini's and einstein1969's sin macro is used throughout, for increased speed. Thanks!
As mentioned earlier, cmdgfx can now run as a server. In essence, it means that cmdgfx stays resident and runs in the background, waiting for input from stdin through a pipe. Thanks to TSnake41 for giving me this idea. Running as server has a number of advantages, mostly regarding speed:
1. On some machines/Windows versions, the overhead of running an external executable each frame (in this case cmdgfx) has a considerable overhead. By running as a server and taking input through the echo command, the overhead disappears.
2. Objects such as 3d models, images etc don't have to be read and parsed each frame, since they are resident (and already parsed) in memory after their first use
3. The batch script sending operations to cmdgfx does not need to wait for cmdgfx to finish before continuing. This asynchronicity increases speed, but it is a double-edged sword which also increases complexity and causes issues (see below)
4. The buffer does not start from blank each frame but lives on between runs. This makes it easier to make certain kind of effects and also makes it possible to progressively build a frame step by step.
In order to run cmdgfx as a server, it needs to be last in a pipe chain, such as:
Code: Select all
call program.bat | cmdgfx.exe "" S
The S flag tells cmdgfx to stay resident and run as server.
Since it's a bit cumbersome to have to write this every time, a better approach is for the script to call itself, like:
Code: Select all
if defined __ goto :START
call %0 %* | cmdgfx "" S
Sending operations to the server
Sending operations to the server looks very similar to running cmdgfx regularly, except it's done with the echo command, and all strings meant for cmdgfx should be prefixed with "cmdgfx:". As well as operations, flags can be set (or clerared, see info on flags below) as well as setting the palette for foreground and background.
Code: Select all
echo "cmdgfx: pixel 9 0 A 2,2" W10
Tells the server to draw an A and enable a waiting time per frame of 10ms
Any string sent to the server that is not prefixed with "cmdgfx:" is simply printed to stdout and otherwise ignored by the server.
Exiting the server:
When the script ends, the server should be notified by sending:
Code: Select all
echo "cmdgfx: quit"
If not, the server will complain when the client script ends. If this somehow causes problems, the complaint can be disabled by setting the 'e' flag in the server.
While running as a server, it is still possible to read keys/mouse from the script using a separate call to cmdgfx (or another external program such as cmdwiz, GetInput etc). However as mentioned earlier, to maximize speed while using a server we want to avoid making any calls to external programs.
There are a few ways of doing this. The method I describe here has a disadvantage in that it reports input back to the script by writing to a file. While this works just fine on most drives, slow drives such as eMMC might get performance problem when writing to a file every frame when the update frequency is high. By using the 'O' flag instead of the 'o' flag, the file is only written when an event actually takes place, instead of every frame. Still, if a high key repeat is on or the mouse is moved continously, slow SSD/eMMC drives might be affected.
Anyway, to read e.g. keys using this method, start the server like:
Code: Select all
call program.bat | cmdgfx.exe "" SOk
The output from 'O' flag is written to the current folder as 'EL.dat' (short for errorlevel), and as the name implies the file will simply contain the same form of ErrorLevel that cmdgfx would return if it was run separately.
To read it from within the script, use something like:
Code: Select all
if exist EL.dat set /p KEY=<EL.dat & del /Q EL.dat >nul 2>nul
set /a KEY=0
It's also recommended to delete EL.dat at the start of the script in case there is a leftover EL.dat in the folder which would then be seen as input.
There is another potential pitfall of the 'O' flag method: if the server runs faster than the script each frame, it might overwrite the existing EL.dat file before the script can read it, thus potentially missing input. In practice, this does not seem to be a big issue as far as I have seen, but it might happen...
To try to deal with both these problems (drive speed and possible missed events), the new separate executable cmdgfx_input.exe can be used as an input server. I will write about cmdgfx_input in the next post.
Asynchronicity and lag:
The client makes asynchronous calls to the server by using the echo command. In other words, the client keeps running immediately, without waiting for the server to finish rendering. What this actually means in practice is that each request is put in a queue in the buffer between the client and the server, and the server then attempts to finish these request as quick as possible (but within its timing contraints, for example if W10 has been set then the server will not render frames faster than 1 per 10ms)
The server is perfectly capable of timing how fast it can run at maximum with the W flag, but it is important to keep in mind that this is not true for the client script! Since we do not want to run any external command (this will affect speed badly), there is no control of how fast the client runs. If the client loop producing frames for the server is simple, it may very well execute much faster than the server, especially since the server is timing frames to keep a smooth frame rate. The problem with this is that the server will start lagging behind, which unfortunately also means that for example response to key presses will seem sluggish, since when the server informs the client of a key press, it may still have a long queue of images to render before it gets to the point where the key press actually changed something.
So how to (try to) deal with this? I'll start with the strangest but so far most successful method:
1. Fill up each call to the server with junk
Basically, there seems to be a limit to the size of the buffer between the client and the server. Someone else probably knows more about this, but essentially, it seems than when the buffer is full, the client will not run until the server has actually consumed some of the input on stdin. In effect, the lag is heavily diminished, because the client no longer "runs off" even if it executes its loop much faster than the server. This in turn means that input lag is reduced a lot.
Here is what I have done in several of the example server scripts:
Code: Select all
:: Create 400 chars long string
set EXTRA=&for /l %%a in (1,1,100) do set EXTRA=!EXTRA!xtra
:: In every call to server, send 2000 extra characters per frame. 'skip' is used to make cmdgfx ignore the extra input
echo "cmdgfx: do something & skip %EXTRA% %EXTRA% %EXTRA% %EXTRA% %EXTRA%"
2. The F flag
The F flag (which is only effective one frame) tells the server to flush the buffer and drop all following input that might have accumulated over stdin. While this decreases lag, it needs to be combined with the 1st method above if used, because otherwise the client might render frames way too fast and the movement will become jerky.
Also, if you want to use this flag to flush stdin right *now* it is actually counterproductive because the server has no knowledge of this wish until this line is processed, which may be several frames from now.
If you want to make sure that the next command run by the server is actually what you send *now*, you can write to a file called 'servercmd.dat' instead of sending strings into the queue over the pipe.
On each run, the server checks for the existence of this file in the current folder. If it exists, the server reads the file, and treats the input just as it would input over stdin. The only difference is that you should not include the prefix "cmdgfx:" in the string. The server then deletes the file 'servercmd.dat', before executing the operation(s) given in the file.
So, if for example, there was a need to flush the buffer as quick as possible to ensure a fast jump to the next "scene" or similar, this could be used in the script:
Code: Select all
echo "" F>servercmd.dat
EDIT: It's worth noting that if there is no input available, cmdgfx server blocks until there is. In this case, writing to servercmd.dat will achieve nothing until the client places some output on stdout. In other words, to be completely sure that the above command would execute directly, it should actually be:
Code: Select all
echo "" F>servercmd.dat
echo "cmdgfx: "
Persistent and non-persistent flags:
When running cmdgfx externally, all flags are initially Off, and we might want to turn them On. However, when running as a server, flags may already be On and we might want to turn them Off at some point. To turn off a previously set flag, simply prefix the flag with - . E.g:
Code: Select all
echo "cmdgfx: " -e
to disable the e flag.
However, some flags are "non-persistent", i.e. their "effect" last only one frame. These flags are 'c' (to take a a screenshot), 'F' (to flush the buffer), 'D' to clear objects, 'C' to reset frame counter, 'n' to produce no output, 'K' to wait for a key press. Also, the 'f' flag to set the buffer size cannot be disabled, but the buffer size/position can be changed.
If a flag is not persistent it has no effect to prefix it with -.
'S' : run as server. Has no meaning if server is already running.
'F': As discussed in the previous section, F is used to flush the input buffer that the server uses (stdin). All unprocessed echoed operations already sent to the server will be flushed, i.e removed and ignored. This ensures that the server doesn't lag behind, but take note that if the script runs much faster than the server, motion will probably be jerky and uncontrolled.
'C': Since first being started, the server keeps track of how many frames it has rendered so far. Using this flag, you can reset the frame count to 0. At the moment, the only practical use for the frame counter is to write it out using the 'text' operation. Just include the text [FRAMECOUNT] in the string and it will be replaced while running by the actual frame count. It's useful for debugging and crude FPS measurements.
'c': This flag was discussed in the previous post (it saves the buffer to file as a screenshot). I'm mentioning it here because, again, it is important to think of the asynchronicity if using this with a server and the saved image should actually be used for something within the script.
For example, this will most likely not work:
Code: Select all
echo "cmdgfx: do stuff" c:0,0,100,100,1,10
copy capture-10.gxy test.gxy
because at the time the copy command is run, the server did not yet have the time to run the given operation and save the file, due to not running synchronously. In this case, you either have to wait for a while before copying (using e.g cmdwiz delay 500 or whatnot), or enter some sort of busy-wait loop with IF EXIST which ends whenever capture-10.gxy has actually been created.
'D' is used to clear all 3d objects from memory, so that they may be re-read from file. The main reason that would be desired is if a script occasionally dynamically re-creates one or more 3d object files with the same name as was previously used. In that case, the old object(s) must be cleared so that the new 3d object with the same name may actually be seen as a new file and not re-used from memory. There is currently no way to erase only a single 3d object from memory.
'n': using the server, it is possible to build a frame gradually in the buffer before finally showing it. In order to do this, set the 'n' flag to disable output, and also disable any w or W flags that are active. When ready to show the image, set the W flag again. Building a frame gradually may sometimes be easier, and in some cases more efficient as it can save you from building very long strings for a single cmdgfx call (having very long strings in environment variables is bad for batch performance)
'I' flag is another more crude method of dealing with the asynchronous lag problem. What it does is to immediately flush the stdin buffer if there was something written to EL.dat, i.e. if an input event happened. This will improve key response time, but it has the disadvantage that there might be a visible "jump" when the server suddenly skips a bunch of frames. This would most likely not be acceptable in e.g. an action game, but might be ok for some applications.
Ok, that was way too much text that only very few will ever read... Anyway, finished soon...
Oh, and to add, I think the easiest way to understand this stuff is just to try out the different server examples and poke around with them
Input from cmdgfx_input.exe
As described in the previous post, using files to communicate input between the batch script and the server is not always optimal. Drives may be slow, and files may in rare cases be overwritten before the receiver had a chance to read them. Cmdgfx_input instead uses a pipe to communicate input to the batch script.
See the scripts called testinput?.bat for basic usage of cmdgfx_input. Several of the server-???.bat scripts also use it.
cmdgfx_input can be used on its own (quit with Ctrl-C), which is a good way to see the kind of output it produces using various flags, e.g:
Code: Select all
Using the cmdgfx server with cmdgfx_input requires a three-step chain, with cmdgfx_input first, the script second, and cmdgfx last, like:
Code: Select all
cmdgfx_input.exe m0nW10 | call program.bat | cmdgfx "" S
Ofcourse, it can also be used as input for any script without using the cmdgfx server. In that case, just skip the last part of the chain.
To conveniently start this chain from a script, use the same approach as in the previous post by having the script call itself. This can also be seen in any of the testinput-?.bat scripts.
Output format and parsing:
The basic output format in the default case looks like:
KEY_EVENT 0 DOWN 0 VALUE 0 MOUSE_EVENT 0 X 0 Y 0 LEFT 0 RIGHT 0 LEFT_DOUBLE 0 RIGHT_DOUBLE 0 WHEEL 0
This means that the text is the same whether or not it was a key event, mouse event or both. If the value after "KEY_EVENT" was a 1, a key event was sent, similarly to "MOUSE_EVENT" for the mouse.
To read these values in the script, use something like:
Code: Select all
set /p INPUT=
for /f "tokens=1,2,4,6, 8,10,12,14,16,18,20,22" %%A in ("%INPUT%") do (
set /a K_EVENT=%%B, K_DOWN=%%C, K_KEY=%%D, M_EVENT=%%E, M_X=%%F, M_Y=%%G, M_LB=%%H, M_RB=%%I, M_DBL_LB=%%J, M_DBL_RB=%%K, M_WHEEL=%%L
As seen above, each frame reads from stdin with "set /p". But what if there is no input, will the script not stop? That is exactly correct, which is why cmdgfx_input can send NO_EVENT events as well, in order to drive animations when there is no input. That is accomplished with the 'n' flag, described below. The format of a NO_EVENT is:
NO_EVENT 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
For a NO_EVENT, all values are always 0. It is written this way to make it possible to use exactly the same for loop as above to parse it as for real events. Just check the first token, and ignore the results in case it is a "NO_EVENT".
There is also the 'A' and the 'x' flags, which both modify the way output is written, see below.
Setting flags during runtime:
Cmdgfx_input communicates with the script over the pipe, but there is no direct communication going the other way. In order to communicate back to cmdgfx_input, write to a file called 'inputflags.dat', which cmdgfx_input continously looks for. If found, the flag settings are read, and then the file is deleted. This is also the only way to quit the input server in a clean way, using the 'q' flag.
Code: Select all
All flags for cmdgfx_input are persistent, i.e. if they are set they are always on, or until they are disabled with -.
The following flags have the same function as they do for cmdgfx:
'k' (read/report keys), 'K' (wait for key), 'M' (read/report mouse and key, 'm' (read/report mouse and key, only report mouse if key pressed), 'W' (await up to n ms), 'w' (wait n ms), 'z' (sleep instead of busy wait loop, used with 'w' or 'W'), 'u' (also report key-UP events when using the 'M' and 'm' flags)
'n': Set this to send "NO_EVENT" events, to drive animations without needing input, as explained above. Also, if using the M or m flag, a timeout value MUST be specified in order for NO_EVENT events to be sent.
NO_EVENT events are sent at the speed set by the W or w flags. If these are not set, NO_EVENT events are sent at the maximum rate possible, which is not advisable.
'x': Similar to what was described in the previous post, in order to prevent a situation where the (input) server runs ahead of the script it gives input to (in case the script runs slowly), it can help to send extra data with each event. This is especially true if using cmdgfx_input without the cmdgfx server. The 'x' flag pads each sent event with up to 1024 '-' characters, making each sent event 1024 bytes long.
'A': The 'A' flag enables a mode where events are sent in a different manner. Intead of "summarizing" the events that happened during waiting, all events are sent immediately as they happen. To some extent, this is more "correct", but it may lead to problems in the receiving script since several events can be sent per wait. The output format is also different: for key events it is 'KEY_EVENT 1 DOWN 0 VALUE 0' and for mouse events it is 'MOUSE_EVENT 1 X 0 Y 0 LEFT 0 RIGHT 0 LEFT_DOUBLE 0 RIGHT_DOUBLE 0 WHEEL 0'. To be able to handle the fact that several events may be sent per frame, in 'A' mode the end of events for a frame is also marked by the output "END_EVENTS 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0". In general, the 'A' mode takes more work for a script to use, so avoid it unless there is a reason to use it.
'q': Quit the input server.
Ok, that's all for the new version of cmdgfx... phew
If you haven't already, check out server-checkerbox-transitions.bat, which has a lot of nice screen transitions (though the expression ones may be slow if your computer is old and/or slow)
1. Fixed a bug in the servercmd.dat handling that could lead to crashes
2. Added server-alpha2.bat, and updated several of the existing server example scripts with help texts. Unfortunately, for the pixel font effects, it's much harder to add help texts. So why not add some here instead:
server-3dmaze/3dworld: mouse=look around, mouse wheel=turn 180, cursor keys=rotate/move OR w/s/j/k, a/d=strafe, PgUp/PgDown=go up/down, Home/End=look up/down, SPACE=restore view
server-gfxtest4: n/N=object, SPACE=mode, ENTER=auto/manual(cursor,z/Z), d/D=distance, h=help, w=wireframe on/off, b=bit operator (only mode 0 and 1)
server-bezier: SPACE=new pattern, ENTER=single/mirrored, c=color, o=operation, c=bit operator (for poly operation), cursor up/down=increase/decrease linegap
server-mouse-blocktransform: Mouse left/right key+drag=paint/erase, mouse wheel=set brush size, SPACE=palette
I was trying out the A flag (to send All events, one by one), and realized that: 1. It is currently the only way to check if the user is holding down more than one key at once 2. It was not working anyway, because there was a bug.
So I fixed that, and made a little shootem-up game (in the folder games/shootem). The purpose of this game is actually to test if you can move the player in two directions at once (e.g up-right) while frenetically pressing space bar to shoot. I could not be bothered to make graphics but re-used stuff from my Mariorun game.
1. Server: 'n' and 'K' are no longer persistent flags. Also, setting k flag now disables m/M.
2. image and tpoly operations: can now force a foreground or background color by putting a - in front of the color. The shootem-up game has an example of this: when hitting an enemy, the enemy temporarily goes white by forcing a single color.
3. Using [FRAMECOUNT] in the text for the text operation now also prints the actual FPS. Wait ~5 s for the FPS to stabilize.
4. mvx,mvy,mvw,mvh params for block op. This is an optimization that makes it possible to run (on my computer at least) scripts like server-bobflag3.bat with a decent framerate.
New scripts/script changes:
1. server-zoom-maximized.bat runs at fullscreen, with the help of carlos' excellent FSCREEN.EXE program.
2. All server examples now have centered screens. The same goes for all games.
3. Moved out sin to sindef.bat and call it everywhere
4. Even more server examples. Pretty much all non-server scripts have now been converted.
And here is some code (from the shootem.bat script) which shows how to read multiple keys held down simultaneously using cmdgfx_input.exe and the A flag active.
Code: Select all
set STOPCHK= for /L %%2 in (1,1,8) do if not defined STOPCHK ( set /p INPUT= for /f "tokens=1,2,4,6" %%A in ("!INPUT!") do ( set EV_BASE=%%A& set /a K_EVENT=%%B, K_DOWN=%%C, KEY=%%D 2>nul ) if "!EV_BASE!"=="END_EVENTS" set /a STOPCHK=1 if !K_DOWN! == 1 ( for %%a in (331 333 328 336) do if !KEY! == %%a set /a ACTIVE_KEY%%a=1 if !KEY! == 27 set STOP=1 ) if !K_DOWN! == 0 ( for %%a in (331 333 328 336) do if !KEY! == %%a set /a ACTIVE_KEY%%a=0 ) ) if !ACTIVE_KEY328!==1 set /a PLYPOS-=2 & if !PLYPOS! lss 3 set /a PLYPOS=3 if !ACTIVE_KEY336!==1 set /a PLYPOS+=2 & if !PLYPOS! gtr 77 set /a PLYPOS=77 if !ACTIVE_KEY331!==1 set /a PLXPOS-=2 & if !PLXPOS! lss 15 set /a PLXPOS=15 if !ACTIVE_KEY333!==1 set /a PLXPOS+=2 & if !PLXPOS! gtr 150 set /a PLXPOS=150
EDIT: oh, and I did realize there was one other way to check for simultaneously held down buttons, using not cmdgfx but "cmdwiz getkeystate" run with 'start /B'. The script 'shootem-altinput.bat' shows this, but I would not recommend this metod. It requires constant writing to file and is probably slow on some computers.
As I wrote about in my other thread (viewtopic.php?f=3&t=8018), I ran my cmdgfx scripts on a Windows10 computer for the first time the other day...
It was not a nice sight! Somebody should have told me.... To start with I had to disable two warning popups that showed every time I double-clicked a bat script. After that:
1. All the window sizes were wrong (as described in the above thread)
2. All file writes were horribly slow (it seems that writing many small file to SSD drive is just a really bad idea. I think this SSD was actually fairly decent, and still...). This affected mostly user input by file write. (It also did not help that every time a file was written, bloody McAffe started running and ate 20% CPU to see if the new file was ok....)
3. CPU seemed sluggish (maybe they focus more on the GPU now, I really don't know. Expression based scripts were slooow...)
(4. Fullscreen mode for the zoom-fullscreen wasn't working properly either)
Ok, so to start off with, I have fixed issue number 1 by using font6 instead of font 0 (8x12 instead of 4x6) and font8 instead of font1 (12x16 instead of 6x8) when setting up the screen, because these fonts have the same pixel size regardless of whether the "new console mode" (see above thread) is set. So I can just use the old sizes but divide them by 2.
All server examples and all game scripts have been converted! (The other scripts have not, but it is actually easy to fix all scripts on Win10 should you want: go to a cmd window's properties, and enable 'Use legacy console ')
I will have to get back to the rest of it. Basically, no server scripts should have user input by writing to file unless input is *very* limited and definitely not for key-repeat.
If you have never downloaded this archive or did but found it slow, now would be a good time to try/retry it.
As mentioned above, I was annoyed to see how slowly many effects ran on the Win10 machine I tried. The non-server scripts were absolutely painful, and for the server effects it was obvious that writing to file to communicate key presses was a bad idea for an SSD drive.
So, the following was done:
1. Moved ALL non-server effect scripts to its own "legacy" folder.
2. Converted ALL server effects to run with cmdgfx_input as server. They should all run smoothly now...
3. BUT, in the cases where this might still not always be true, I renamed the script to "servH-???.bat" to indicate that it might have speed problems on some machines
4. Optimized the included games, they now run fine on the Win10 machine EXCEPT cmdrunner which I have given up on. The bottleneck there is the batch processing itself, cause batch simply seems to run slower on Win10 than Win7
5. The fullscreen zoom effect (servH-zoom-maximized.bat) should now look as expected on all(?) machines
Not even Win10, slow SSD drives and invasive McAffe can stop me now
Nothing major really, just some addons. Biggest one is probably the possibility to set (i.e. scroll) the texture offset in 3d objects. This makes it easy to do effects such as the Star Wars Scroller depicted above.
Scripts in image, top-left to bottom-right:
1. server-StarWarsScroller.bat (control speed with s/S, rotate with cursor keys/z, also try m)
2. server-zoom-custom-palette.bat (custom palette zoomer)
3. server-sphere-texture.bat (texture offset changed on a sphere object. Also in a pixel version: servH-sphere-texture-pixel.bat)
4. servH-terrain-pixel.bat (text mapped on top of terrain 3d object, try rotating with keys, also try 's' and 'm' keys. Also text version: server-terrain.bat)
5. server-moveabs.bat (all 10 fonts on same screen moved by pixeloffset)
8. server-trails.bat (clearing screen gradually with block op)
9. server-splitscreen.bat (3 font sizes/scenes on same screen)
Whole list of changes:
1. Texture offsetting and texture scaling for 3d command.
2. Now working as stand-alone command when cmdgfx is running as output server (creating conin/conout)
3. R flag sets the granularity of rotations, keeping default at 4
4. New flag (i) to ignore servercmd.dat. For cmdgfx_input, 'i' is used to ignore inputflags.dat, and 'I' can be used to ignore title flags
5. Repeated textures for perspective mapper too (if T flag set)
6. GDI only: New flag ('a') to place f:?? at pixel level placement
7. Allow block to use color for transparency (new mode 2 and 3)
8. Flag (G) to set gxy max width/height
9. Flag (N) auto-center (and optionally auto-normalize size of) 3d objects
10. Bug fix: Image op with pcx: bgcolor no longer ignored, possible to force a color with -