Ok, so I think it's ready
or at least it's playable enough for field testing!
My
v0.2 engine sketch size is
29,172 bytes out of 30,592 max, and it uses
1,441 bytes of SRAM out of 2,048 max.
So who is interested to beta-test
The Warlock of Firetop Mountain on his/her Gamebuino
The working book I have is in French actually, so until I adapt the English book (I have it, just need to format it, shouldn't take long...) it would be a beta-test of
Le Sorcier de la Montagne de Feu!
Next improvement I want to push before releasing the code is EEPROM save! Current engine doesn't have it, so if you want to play the book seriously, make sure to remember your last paragraph (and stats) before switching off your Gamebuino.
What you'll find in the Gamebook engine:
- stats management (skill, stamina, luck): randomly calculated when you start the adventure, then totally editable, and of course actions in the book have direct incidence on your stats!
- management of gold, provisions (give +4 of stamina), and potions (choice of 3 potions at the beginning of the adventure: Potion of Skill - restores skill points ; Potion of Strength - restores stamina points ; Potion of Fortune - restores luck points and adds 1 to Initial luck)
- dynamic equipment: you start your adventure with a sword, a leather armour, a rucksack and a lantern, then you can edit (add or remove) any item to your equipment!
- special actions: roll 1 or 2 dice, test your luck, fight! and goto paragraph (can be used for cheating, but sometimes it's actually needed by the book)
In the book, use
RIGHT and
LEFT arrows to scroll through the pages, and use
UP and
DOWN to move the selection, or to scroll by a single line.
Button
A is used to validate,
B to go to Adventure Sheet (or back to the Book), or to cancel in all other screens.
I use a modified version of the Gamebuino library with sound and keyboard stripped off to save memory, and an enhanced
gb.popup() that takes a (variable) SRAM char array as a parameter (the original one only takes a PROGMEM const char[] which I find too restrictive):
- Code: Select all
void Gamebuino::popup(const char* text, uint8_t duration){
#if (ENABLE_GUI > 0)
popupText = (reinterpret_cast <const __FlashStringHelper*> (text));
popupTimeLeft = duration+12;
#endif
}
I also removed the
gb.keyboard() and replaced it with 2 more ergonomic keyboards (but that's only my opinion!) a numeric keyboard, already seen a few posts back, and a new Qwerty keyboard (or Azerty for French users):
For those interested, here is the code of this keyboard (less than 70 lines):
- Code: Select all
PROGMEM const char keyboard[] =
#ifdef FRENCH
"azertyuiopqsdfghjklmwxcvbn_\030<";
#else
"qwertyuiopasdfghjkl<zxcvbnm_\030";
#endif
void printAlpha(boolean caps, byte i) {
char c=(char)pgm_read_byte(&(keyboard[i])); // read char array in PROGMEM
if(caps && c>='a' && c<='z') c=c&~(0x20); // if(caps) convert to upper case
gb.display.print(c); gb.display.print(F(" "));
}
void alphaKeyboard(char* tgt, byte lmax) {
byte x=0, y=0;
boolean caps=false;
while(1) {
if (gb.update()) {
// draw input bar
gb.display.cursorY++; if(strlen(tgt)) gb.display.print(tgt);
gb.display.cursorY--; if((gb.frameCount/4)%2) gb.display.print(F("_"));
gb.display.drawFastHLine(0,gb.display.fontHeight+1,LCDWIDTH);
// draw keyboard
moveCursor(3, gb.display.fontHeight+5);
for(byte i=0; i<10; i++) printAlpha(caps, i);
moveCursor(3, CURRENT+gb.display.fontHeight+2);
for(byte i=10; i<20; i++) printAlpha(caps, i);
moveCursor(3, CURRENT+gb.display.fontHeight+2);
for(byte i=20; i<29; i++) printAlpha(caps, i);
gb.display.println(F("ok"));
moveCursor(3, CURRENT+2);
for(char c='0'; c<='9'; c++) { gb.display.print(c); gb.display.print(F(" ")); }
// draw select box
gb.display.drawRoundRect(2*x*gb.display.fontWidth+1, (y+1)*(gb.display.fontHeight+2)+(y?1:2), ((x==9 && y==2)?2:1)*gb.display.fontWidth+3, gb.display.fontHeight+3, 3);
// draw legend
#ifdef FRENCH
moveCursor(LCDWIDTH-7*gb.display.fontWidth-6, LCDHEIGHT-gb.display.fontHeight+1);
gb.display.print(F("annuler"));
#else
moveCursor(LCDWIDTH-6*gb.display.fontWidth-6, LCDHEIGHT-gb.display.fontHeight+1);
gb.display.print(F("cancel"));
#endif
gb.display.print(F("\026"));
// handle user input
if(gb.buttons.pressed(BTN_RIGHT)) x=(x+1)%10;
if(gb.buttons.pressed(BTN_LEFT)) { x--; if(x==255) x=9; }
if(gb.buttons.pressed(BTN_DOWN)) y=(y+1)%4;
if(gb.buttons.pressed(BTN_UP)) { y--; if(y==255) y=3; }
if(gb.buttons.pressed(BTN_B)) { tgt[0]=NULL; break; } // Cancelled by user
if(gb.buttons.pressed(BTN_A)) {
byte l=strlen(tgt);
if(x==9 && y==2) { // Ok
break;
} else if(y==3) { // 0-9
if(l<lmax) { tgt[l++]=(char)'0'+x; tgt[l]=NULL; }
} else { // Other key
char c=(char)pgm_read_byte(&(keyboard[10*y+x])); // read char array in PROGMEM
if(c=='<') { // Del
if(l) tgt[l-1]=NULL;
} else if(c=='\030' || c=='\031') { // Shift
caps=!caps;
} else if(l<lmax) { // a-z, A-Z
if(c=='_') c=' '; else if(caps) c=c&~(0x20); // convert space +if(caps) put in upper case
tgt[l++]=(char)c; tgt[l]=NULL;
} // if(l<lmax)
} // Other key
} // if(gb.buttons.pressed(BTN_A))
} // if (gb.update())
} // while(1)
} // alphaKeyboard()
Among other interesting things: some functions to convert a char array to an int, and an int to a char array, other functions to build a char array by concatenating other char arrays to it (either from SRAM or from PROGMEM) or also concatenate integers... And a lot of other fun stuff
So I'm waiting for applicants
As I'm not sure about the legality of making public a raw copy of a copyrighted gamebook, I'll just send the app (INF+HEX+LDV) by private message to people who are interested in beta-testing (remember: French-speaking people only so far! désolé!)
Cheers,
Nicolas