- This language is a derivative of Befunge.
As its name suggests, befunge-with-graphics is befunge-93 but with graphics. Its name can be shortened to bwg and will be for the rest of this article. It adds two more regular commands, however, which help with the graphics programming.
Changes and additions to befunge, excluding graphics
On top of the befunge instruction set, bwg adds two extra commands;:
|j||Jump command - pops y then x off the stack, pushes the current instruction pointer and direction to the return stack and sets the ip to x,y and the direction to right.|
|r||Return command - pops the x, y and direction off of the return stack and sets the instruction pointer to those values.|
On top of this, bwg extends the playfield almost indefinitely. Although not mentioned on the befunge wiki page, bwg makes it clear that every cell in the playfield and the stack can hold up to the `signed long` datatype on the system it's running on.
The reference interpreter uses SDL2 to render graphics and as such the graphics commands are similar to that of SDL.
|s||Pops y then x off of the stack and uses them as dimensions to create a screen. This must be run before any other graphics command or an error will occur.|
|f||Pops three values, b, g, then r, and sets the render colour to those values. This is used for clearing the screen and drawing.|
|x||Pops y then x off the stack and sets the pixel at those coords to the current colour.|
|c||Fills screen with current colour.|
|u||Updates the screen after it's been drawn|
|l||Pops y2, x2, y1, x1 off of the stack and draws a line from x1y1 to x2y2.|
|z||Polls SDL for an event, if one is present then push it to the stack along with any data accompanying the event. See the events section.|
Future features and bug fixes
The main reason jumps were added is so that "virtual jumps" can be used. These are jumps where the x, the y, or both are negative. These will be processed by the interpreter into graphics commands, such as drawing circles, rects, and other higher level things like that. They may support other operations in the future, depending on how I implement this.
So far there is no error handling in the graphics commands, other than to check that the screen has been initialised before a graphics command. This should probably be changed because it is possible to crash the interpreter with bad code.
In addition, there is no check to see if the instruction pointer is going too far: this will crash the interpreter. Needless to say this is a bug.
The event handling is rather simple but can be quirky. The z command polls SDL for an event and pushes any relevant data to the stack. Currently, there are only two events supported: keydown and quit. This will be expanded. An example event handler is shown here.
>v >v >z:1-|>:2-|> > > @$< >$"a"-| >"do something"^
This works by first polling for events, then duplicating the event ID (below) which will always be at the top of the stack. The event ID is then compared to the first kind of event (ID 1, Window close event) and if it matches it pops the duplicated event ID off of the stack and exits. If not, it duplicates and compares again, taking into account any data that might be pushed and making sure to pop it to avoid a stackoverflow. The default size of the stack is 1,048,576 stack entries. (This should probably be dynamically sized.)
The events are currently as follows.
|Event||What is pushed to the stack|
|Window close event||1|
|Key down event||Key code, 2|
A basic program that opens a window and closes it if you so wish.
68*52**88*52**sv vcf000< < < >uz:1-|>^ @$<
Example with drawing and keyboard input
This code moves one pixel around using the wasd keys.
vXY >010p020p052*j "jump to initialisation" "draw()" >10g20gxr "keyboard events" >v >v >v >v >: "d" -|>: "s" -|>: "a" -|>: "w" -|>r v1+1g01$<vp02+1g02$<vp01-1g01$<vp02-1g02$< >0p > > > ^ "initialisation" >68*52**88*52**sv v ucf000< v f::-1*4*88 cf000 < >03jv v < >v >v >u >z:1-|>:2-|> ^ @$< v$< vj60< > ^