DescriptionThis is the library I'll use in my programs (if I ever make any). It's a collection of functions that provide:
Prime number generation/detection
Kinda fast dictionaries (associative arrays/arrays indexed by strings)
Bit and byte vectors with automatic resizing
LZS compression for GRPs (both slower and worse at compression than rei's, so it's useless)
Various math functions
Debug logger for outputting messages on top/bottom screen
Functions for basic character movement around a map
Menus (built from textboxes)
OK but seriously, it's not good.
I don't want any credit if you use this library. Instructions
How to use:
Run the above to make all functions available. You can make the slot whatever you like; it doesn't have to be 3.
ISPRIME(NUM) : determine if a number is prime (up to 16,383*)
NEXTPRIME(NUM) : get the closest prime larger than NUM (up to 16,383*)
PREVPRIME(NUM) : get the closest prime smaller than NUM (up to 16,383*)
CACHEPRIMES NUM : generate the prime data for numbers up to NUM
* = with default settings. Running CACHEPRIMES will change the upper range; for instance, CACHEPRIMES(100000) will change the upper bound to 100000 for ISPRIME, NEXTPRIME, and PREVPRIME
CACHEPRIMES 100000 'Takes a little bit
?ISPRIME(99999) ' FALSE
GETBIT(BIT,VECTOR%) : Get the bit (0 or 1) for the position BIT within the given bit vector*
SETBIT BIT,VALUE%,VECTOR% : Set the bit for the position BIT to the value VALUE (0 or 1) within the given bit vector*
GETBYTE(BYTE,VECTOR%) : Get the byte (0-255) for the position BYTE within the given byte vector*
SETBYTE BYTE,VALUE%,VECTOR%) : Set the byte for the position BIT to the value VALUE (0-255) within the given byte vector*
* = A bit/byte vector is just an integer array. You can use existing arrays; the data is treated as though it is packed.
Examples:DIM V% 'A bit/byte vector is just an integer array
?GETBIT(103,V%) '1 (we set that bit with the previous SETBYTE)
DICCREATE$(INITIALSIZE) : Create a dictionary with the given initial capacity (can be 0)
DICGET$(KEY$,DIC$) : Retrieve the value* from dictionary DIC$ at the given key (returns "" if key doesn't exist)
DICSET KEY$,VALUE$,DIC$) : Set the value* for the given key in dictionary DIC$ (adds key if key doesn't exist yet. Increases capacity automatically if dictionary is getting full)
DICHASKEY(KEY$,DIC$) : Return whether or not dictionary DIC$ has the given key.
DICRESIZE DIC$,NEWSIZE : NOT NECESSARY TO CALL. Increase capacity to at LEAST given size. Will only increase dictionary size. Actual size set may be different.
* = float and integer versions are available: DICGETI%, DICGETF#, DICSETI, DICSETF
Examples:DIM D$ 'A dictionary is just a string array.
D$=DICCREATE$(10) 'Set initial capacity to a large value for faster insertion. Resizes automatically regardless
?DICGET$("MYKEY",D$) 'Prints nothing
DICSET "MYKEY","HIHI", D$
?DICGET$("MYKEY",D$) 'Prints HIHI
?DICGETI%("MONKEYS",D$) 'Prints 53
DISTANCE(X1#,Y1#,X2#,Y2#) : Get the distance between two points
CLOSESTMULTIPLE(NUM,MULT) : Get the closest number to NUM that is a multiple of MULT.
LERP(A#,B#,T#) : Get the value for linear interpolation between A and B at point T.
BLENDCOLORS(COL1,COL2,SHIFT#) : Blend two colors together. SHIFT# tells how much of the second color to add (0 is all the first color, 1 is all the second color, 0.5 is a perfect blend)
BRIGHTENCOLOR(COL,AMT) : Brighten color by given amount. This is a linear shift: all channels are increased by the given amount. If the amount goes over 255, it is capped.
BRIGHTENCOLORM(COL,M#) : Bright color by given multiple. This is much more like the "brightening" you would expect: each channel is scaled by the given amount, which keeps the overall color roughly the same. Use this version if you expect real brightening.
SIGN(X) : Gives the sign of X. Returns 1 if X>0, -1 if X<0, and 0 if X==0.
?BLENDCOLORS(&HFF00FF00,&HFFFF0000,0.5) ' &HFF777700
STRINGJOIN$(ARRAY$,JOINCHR$) : Join an array of strings together and place JOINCHR$ between them.
STRINGSPLIT$(STRING$,DELIM$) : Split a string into an array using the given character as a delimiter.
SARRAYTOSTRING$(ARRAY$) : Convert a string array into a single string. This can be used to turn dictionaries into single strings.
STRINGTOARRAY$(STRING$) : Convert a string converted with SARRAYTOSTRING back into a string array. This can be used to unpack dictionaries (if you pack them into a single string with the above function).
A$=STRINGSPLIT$("DATA1/DATA2/SOMETHING/WHATEVER","/") 'An array with 4 elements: DATA1, DATA2, SOMETHING, WHATEVER
?STRINGJOIN$(A$,"%") ' DATA1%DATA2%SOMETHING%WHATEVER
Simple Game Engine
I've only just started this thing, so it's bound to change a lot. For now, you can see an example of what's done by loading "TESTMOVE". You should see that the code is very short; everything is done in the call to SGEBASIC (simple game engine). I designed to be as modular as possible while still being fairly easy to actually use. Right now, the functionality is split up into:
Player position update
Each of these functions can be easily replaced with your own function simply by changing the appropriate value in the dictionary. I'll explain it all later when it's actually done.
Textboxes are simple boxes which display formatted text with automatic line breaking and scrolling. They are drawn on the GRP layer of your choosing. They are nowhere near finished, but maybe they're a little usable... not really.
Textboxes are HIGHLY customizable, so there's a lot of settings and it might get confusing. I'll add a wrapper around customization in the future so it's easier, but for now, I would stick with the default settings.
Textboxes are OBJECTS, so you will need to create the textbox object, then pass that object around to all the functions. Keep this in mind when you're looking at the following examples:
'DICSETF "CHRSCL",2.0,TB$ 'Uncomment this to see text scaling in action
DIM TEXT$="Look at all this text that we're outputting to the screen! Too bad it's not enough to make it scroll."
TBSHOW TB$ 'Draw textbox
TBTEXT TBFIX$(TEXT$,TB$),TB$ 'Show text with automatically-inserted elements (such as the pause at the end)
You can also load TESTTB to see a test program for textboxes.
Every game needs a menu somewhere. Most of the time, unless it's the MAIN menu, you're just selecting from a small set of choices. Why program this every time you need it when you can have an automatic menu that matches your textboxes?
Menus work a lot like textboxes, except that they require more setup. Since they require more setup, I've created a "quick" function which does all the setup for you. Maybe one day I'll go over the ridiculous amount of customization, but for now, this'll have to do.
Menus can be placed anywhere on the screen, HOWEVER, unlike textboxes, they can be "anchored" to a corner other than the top left. For instance, if you set the menu's X and Y to 0 and you specify the anchor as the bottom left, the 0,0 will now mean the bottom left. Menus can be anchored to any of the four corners; the default is the lower right (for use with textboxes). Furthermore, even though menus are built from textboxes, they will ignore their width, height, and text location settings since menus are automatically sized to fit the text they are displaying.
IF SELECTED>=0 THEN PRINT "You've selected: "+OPT$[SELECTED] ELSE PRINT "You cancelled!"
You can also load TESTMENU to see it in action. I use STRINGSPLIT to create the list of options in that program.
I'll add the others later or something.Notes
Dictionaries are now much faster and should keep their constant access time for much larger dictionaries. Dictionaries up to 1000 elements now have roughly the same access time as dictionaries with 100.
Added menu system. Menus can be anchored to corners of the screen and use many of the same options as textboxes.
Added string functions for splitting/joining/etc.
Made dictionary work for single character keys (it would crash before)
Made dictionary lookup twice as fast for keys which resort to linear scan.
Added the textbox library
Fixed dictionary functions so it actually hashes correctly now