# HG changeset patch # User Mohammed Khoory # Date 1278544298 14400 # Node ID bcf3d6f89c623f763dd017c5c6e53777ef7d3673 # Parent 6366beccd211d5bbfd3f263973e3a705abe66d54 Keyboard support, code movement, and TestManager Major Changes ============= - Added "testman.h" and "testman.cpp" to be used exclusively to test stuff (from a GameManager perspective) - Moved all the testing stuff to testman.cpp. 9game is just an empty class now to manage other GameManagers - Moved all the initializing stuff from 9Game to main. 9Game is like any other GameManager now (just that it manages other GameManagers) - Added keyboard.h and keyboard.c to handle keyboard interrupts (by replacing the keyboard ISR) - Keyboard is working :D can read more than one key at a time. (tested in TestManager with WASD) Minor Changes ============= - Removed the exception throwing in SpriteLoader::unloadFile() (because it just makes things unnecessarily complicated) - added finished() to GameManager to indicate whether a GameManager is finished or not - Animation test + key control test. Sprite moves around depending on wasd key input. (program ends when off screen to right) - Set 0x00 as transparency color with drawSprite (TODO: change to make this customizeable on runtime) - Edited Makefile to reflect new changes Notes ===== - Animation seems to work nice and smooth in dosbox, slow in dosemu, so maybe I should start testing in both dosemu and dosbox - TODO: fix bug with drawSprite. When a sprite is drawn on the right of the screen it "wraps around" to the other side by one pixel in width diff -r 6366beccd211 -r bcf3d6f89c62 9Game.cpp --- a/9Game.cpp Mon Jun 21 15:08:59 2010 -0400 +++ b/9Game.cpp Wed Jul 07 19:11:38 2010 -0400 @@ -10,98 +10,35 @@ Game9::Game9() { // graphics = GraphicsDevice(); + testman = new TestManager(); + currentManager = testman; + } Game9::~Game9() { - if(testSprite != NULL) + if(testman != NULL) { - delete[] testSprite->bitmap; - delete testSprite; - testSprite = NULL; + delete testman; + testman = NULL; } } int Game9::processKeys() { + currentManager->processKeys(); return 0; } int Game9::updateState() { + currentManager->updateState(); return 0; } int Game9::render(GraphicsDevice& graphics) { - // clear screen - graphics.clearScreen(); - - // make all objects render themselves in order - - graphics.drawPixel(100, 100, 0x0F); - graphics.drawHorizontalLine(100, 110, 50, 0x0F); - graphics.drawVerticalLine(100, 120, 50, 0x0F); - if(testSprite != NULL && testSprite->bitmap != NULL) - graphics.drawSprite(10,10, testSprite); - else - graphics.drawHorizontalLine(5,10,25,0x0F); - - //update buffer - graphics.updateBuffer(); - - return 0; -} - -int Game9::run() -{ - // load sprite from bmp file - SpriteLoader spriteloader; - try - { - spriteloader.loadFile("C:\\9game\\DJGPP\\sprites\\sprites"); - - - printf("debugging info:\n"); - printf("Width: %ld Height: %ld \n", spriteloader.getWidth(), spriteloader.getHeight()); - printf("Size: %lu\n" , spriteloader.getSize()); - - testSprite = spriteloader.getSprite(0,0,110,110); - - - GraphicsDevice::enter_mode13h(); - spriteloader.setPalette(graphics); - spriteloader.unloadFile(); - - - for(int i = 0; i < 120; i++){ - processKeys(); - updateState(); - render(graphics); - } - - GraphicsDevice::leave_mode13h(); - } - catch(int e) - { - printf("an exception has occurred\n"); - switch(e){ - case SpriteLoader::FileNotLoadedException: - printf("Tried to run a function when no file loaded\n"); - break; - case SpriteLoader::BadFileNameException: - printf("File name is not valid\n"); - break; - case SpriteLoader::BadFileException: - printf("This file is bad. makes no sense\n"); - break; - case SpriteLoader::CannotReadException: - printf("This file is not supported\n"); - break; - } - - - } + currentManager->render(graphics); return 0; } @@ -109,3 +46,7 @@ { return 0; } +int Game9::finished() +{ + return currentManager->finished(); +} diff -r 6366beccd211 -r bcf3d6f89c62 9Game.h --- a/9Game.h Mon Jun 21 15:08:59 2010 -0400 +++ b/9Game.h Wed Jul 07 19:11:38 2010 -0400 @@ -21,7 +21,7 @@ #include "gobject.h" //#include "bmpload.h" #include "sprload.h" - +#include "testman.h" class Game9 : public GameManager { @@ -31,21 +31,23 @@ protected: GraphicsDevice graphics; - struct sprite * testSprite; + GameManager * currentManager; + + TestManager * testman; + +// struct sprite * testSprite; public: Game9(void); ~Game9(void); - - int run(); // enters loops, starts the game - // inherited methods from GameManager virtual int processKeys(); // reads user input virtual int updateState(); // updates the object states virtual int render(GraphicsDevice& device); // renders ethe stuff on screen virtual int registerGameObject(GameObject * aGameObject); + virtual int finished(); }; diff -r 6366beccd211 -r bcf3d6f89c62 Makefile --- a/Makefile Mon Jun 21 15:08:59 2010 -0400 +++ b/Makefile Wed Jul 07 19:11:38 2010 -0400 @@ -3,14 +3,15 @@ # # Compiler command -CC=gxx +CXX=gxx +CC=gcc # # Flags # -g -- Enable debugging # -wall -- Turn on all warnings # -CFLAGS=-g +CFLAGS= #Redirection app for logging REDIR=redir -o build.txt -eo @@ -21,27 +22,33 @@ del *.o del *.exe -game.exe : 9game.o graphics.o main.o gobject.o movblobj.o sprload.o - $(CC) $(CFLAGS) -o game.exe 9game.o graphics.o gobject.o movblobj.o sprload.o main.o +game.exe : 9game.o graphics.o main.o gobject.o movblobj.o sprload.o testman.o keyboard.o + $(REDIR) $(CXX) $(CFLAGS) -o game.exe 9game.o graphics.o keyboard.o gobject.o movblobj.o sprload.o testman.o main.o #C:\DJGPP\LIB\LIBSTD~1.A graphics.o: graphics.cpp - $(REDIR) $(CC) $(CFLAGS) -c graphics.cpp + $(REDIR) $(CXX) $(CFLAGS) -c graphics.cpp 9game.o : 9game.cpp - $(REDIR) $(CC) $(CFLAGS) -c 9game.cpp + $(REDIR) $(CXX) $(CFLAGS) -c 9game.cpp main.o : main.cpp - $(REDIR) $(CC) $(CFLAGS) -c main.cpp + $(REDIR) $(CXX) $(CFLAGS) -c main.cpp gobject.o : gobject.cpp - $(REDIR) $(CC) $(CFLAGS) -c gobject.cpp + $(REDIR) $(CXX) $(CFLAGS) -c gobject.cpp movblobj.o : movblobj.cpp - $(REDIR) $(CC) $(CFLAGS) -c movblobj.cpp + $(REDIR) $(CXX) $(CFLAGS) -c movblobj.cpp bmpload.o : bmpload.cpp - $(REDIR) $(CC) $(CFLAGS) -c bmpload.cpp + $(REDIR) $(CXX) $(CFLAGS) -c bmpload.cpp sprload.o : sprload.cpp - $(REDIR) $(CC) $(CFLAGS) -c sprload.cpp \ No newline at end of file + $(REDIR) $(CXX) $(CFLAGS) -c sprload.cpp + +testman.o : testman.cpp + $(REDIR) $(CXX) $(CFLAGS) -c testman.cpp + +keyboard.o : keyboard.c + $(REDIR) $(CC) $(CFLAGS) -c keyboard.c diff -r 6366beccd211 -r bcf3d6f89c62 gmanager.h --- a/gmanager.h Mon Jun 21 15:08:59 2010 -0400 +++ b/gmanager.h Wed Jul 07 19:11:38 2010 -0400 @@ -19,6 +19,9 @@ public: virtual int registerGameObject(GameObject * aGameObject) = 0; // adds an object to the game + virtual int finished() = 0; // returns GameManager::NOT_FINISHED if not done, anything else otherwise + + static const int NOT_FINISHED = 0; }; #endif diff -r 6366beccd211 -r bcf3d6f89c62 graphics.cpp --- a/graphics.cpp Mon Jun 21 15:08:59 2010 -0400 +++ b/graphics.cpp Wed Jul 07 19:11:38 2010 -0400 @@ -76,6 +76,7 @@ *(buffer + (y*screen_width) + x) = color; } +//TODO fix bug when sprite is drawn on the right side of the screen void GraphicsDevice::drawSprite(int x, int y, struct sprite * aSprite) { for(int i = 0; i< aSprite->height; i++) @@ -83,7 +84,8 @@ for(int j = 0; j < aSprite->width; j++) { // if off-screen dont draw - if(!(x + j > screen_width || x + j < 0 || y + i > screen_height || y + i < 0)) + if(!(x + j > screen_width || x + j < 0 || y + i > screen_height || y + i < 0) + && !(*(aSprite->bitmap + (i*aSprite->width) + j) == 0)) *(buffer + ( (y+i) * screen_width) + (x+j)) = *(aSprite->bitmap + (i*aSprite->width) + j); } } diff -r 6366beccd211 -r bcf3d6f89c62 keyboard.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keyboard.c Wed Jul 07 19:11:38 2010 -0400 @@ -0,0 +1,65 @@ +#include "keyboard.h" +#include + +/* static methods and variables for handling the keyboard */ + +void handler() +{ + unsigned char key; // the key + + int i; + + // get the key from the keyboard port + key = inportb(0x60); + + if( (key & 0x80) == 0) // check if key is pressed + keys[key & 0x7f] = 1; // set the keys array to pressed + else + keys[ key & 0x7f ] = 0; // not pressed + + outportb(0x20, 0x20); + +} +// this dummy function simply indicates the end of the handler function +void handler_end(){} + +int attach_keyboard_handler() +{ + if( enabled == 0) + { + _go32_dpmi_lock_data( (char *) &keys, sizeof(keys) ); // locks storage reigon + + // lock code reigon x + _go32_dpmi_lock_code( (void *) handler, (unsigned long) handler_end - (unsigned long) handler); + + // store the old keyboard handling interrupt service routine + _go32_dpmi_get_protected_mode_interrupt_vector(9, &oldKeyboardHandlerSeginfo); + + // set the offset of the function that will be called + newKeyboardHandlerSeginfo.pm_offset = (int)handler; + + // register the function + if ( _go32_dpmi_allocate_iret_wrapper( &newKeyboardHandlerSeginfo ) != 0) + return 1; + if ( _go32_dpmi_set_protected_mode_interrupt_vector(9, &newKeyboardHandlerSeginfo) != 0) + return 1; + + enabled = 1; + } + return 0; +} + +void detach_keyboard_handler() +{ + if(enabled == 1) + { + _go32_dpmi_set_protected_mode_interrupt_vector(9, &oldKeyboardHandlerSeginfo); + _go32_dpmi_free_iret_wrapper(&newKeyboardHandlerSeginfo); + enabled = 0; + } +} + +inline char keyPressed(unsigned char key) +{ + return keys[key]; +} \ No newline at end of file diff -r 6366beccd211 -r bcf3d6f89c62 keyboard.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keyboard.h Wed Jul 07 19:11:38 2010 -0400 @@ -0,0 +1,40 @@ +#ifndef KEYBOARD +#define KEYBOARD + +/*#ifdef __cplusplus +extern "C" { +#endif*/ +/* functions and a custom ISR used to handle the keyboard + - DOS by itself can only handle one key at a time, so we need to + replace the interrupt service routine (ISR) to make it handle more + than one key at a time +*/ +#include +#include +#include +#include + +// insert some keyboard codes here as DEFINES (or static chars) + + +char enabled; +volatile char keys[256]; // stores keyboard state + +// keyboard ISRs +_go32_dpmi_seginfo oldKeyboardHandlerSeginfo; +_go32_dpmi_seginfo newKeyboardHandlerSeginfo; + +void handler(); +void handler_end(); + +int attach_keyboard_handler(); +void detach_keyboard_handler(); + +char keyPressed(unsigned char key); + +/* +#ifdef __cplusplus +} +#endif +*/ +#endif diff -r 6366beccd211 -r bcf3d6f89c62 main.cpp --- a/main.cpp Mon Jun 21 15:08:59 2010 -0400 +++ b/main.cpp Wed Jul 07 19:11:38 2010 -0400 @@ -2,17 +2,78 @@ --- main function is here --- */ - #include - #include "9Game.h" +#include +#include "9Game.h" +#include "sprload.h" +extern "C" { + #include "keyboard.h" +} int main(int argc, char ** argv) { int rc = 0; Game9 nineGame = Game9(); - rc = nineGame.run(); +// rc = nineGame.run(); + GraphicsDevice graphics; + SpriteLoader spriteloader; + + GraphicsDevice::enter_mode13h(); + try{ + spriteloader.loadFile("C:\\9game\\DJGPP\\sprites\\sprites"); + + + printf("debugging info:\n"); + printf("Width: %ld Height: %ld \n", spriteloader.getWidth(), spriteloader.getHeight()); + printf("Size: %lu\n" , spriteloader.getSize()); + +// testSprite = spriteloader.getSprite(0,0,110,110); + spriteloader.setPalette(graphics); + spriteloader.unloadFile(); + + } + catch(int e) + { + printf("an exception has occurred\n"); + switch(e){ + case SpriteLoader::FileNotLoadedException: + printf("Tried to run a function when no file loaded\n"); + break; + case SpriteLoader::BadFileNameException: + printf("File name is not valid\n"); + break; + case SpriteLoader::BadFileException: + printf("This file is bad. makes no sense\n"); + break; + case SpriteLoader::CannotReadException: + printf("This file is not supported\n"); + break; + } + rc = 1; + } + + if(rc != 0) + return rc; + + // attach keyboard ISR + rc = attach_keyboard_handler(); + if(rc !=0) + { + detach_keyboard_handler(); + return rc; + } + + while(nineGame.finished() == GameManager::NOT_FINISHED) + { + nineGame.processKeys(); + nineGame.updateState(); + nineGame.render(graphics); + } + + // detach keyboard ISR + detach_keyboard_handler(); // nineGame.~Game9(); - + GraphicsDevice::leave_mode13h(); return rc; } \ No newline at end of file diff -r 6366beccd211 -r bcf3d6f89c62 sprload.cpp --- a/sprload.cpp Mon Jun 21 15:08:59 2010 -0400 +++ b/sprload.cpp Wed Jul 07 19:11:38 2010 -0400 @@ -79,11 +79,8 @@ } -void SpriteLoader::unloadFile() throw(int) +void SpriteLoader::unloadFile() { - if(!paletteFile.is_open() && !rawBitmapFile.is_open()) - throw FileNotLoadedException; - if(paletteFile.is_open()) paletteFile.close(); diff -r 6366beccd211 -r bcf3d6f89c62 sprload.h --- a/sprload.h Mon Jun 21 15:08:59 2010 -0400 +++ b/sprload.h Wed Jul 07 19:11:38 2010 -0400 @@ -38,7 +38,7 @@ // opens all bitmap and palette and reads the header (filenames are passed in without extension) void loadFile(const string& filename) throw(int, ios_base::failure); - void unloadFile() throw (int); + void unloadFile(); // get methods (allocates memory!) // returns the entire bitmap as a char array diff -r 6366beccd211 -r bcf3d6f89c62 testman.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testman.cpp Wed Jul 07 19:11:38 2010 -0400 @@ -0,0 +1,123 @@ + +#include "testman.h" + +TestManager::TestManager() +{ + // load sprite + SpriteLoader spriteloader; + try{ + spriteloader.loadFile("C:\\9game\\DJGPP\\sprites\\sprites"); + + printf("debugging info from TestManager:\n"); + printf("Width: %ld Height: %ld \n", spriteloader.getWidth(), spriteloader.getHeight()); + printf("Size: %lu\n" , spriteloader.getSize()); + + testSprite = spriteloader.getSprite(0,0,110,110); + } + catch(int e) + { + printf("an exception has occurred\n"); + switch(e){ + case SpriteLoader::FileNotLoadedException: + printf("Tried to run a function when no file loaded\n"); + break; + case SpriteLoader::BadFileNameException: + printf("File name is not valid\n"); + break; + case SpriteLoader::BadFileException: + printf("This file is bad. makes no sense\n"); + break; + case SpriteLoader::CannotReadException: + printf("This file is not supported\n"); + break; + } + if(spriteloader.isLoaded()) + spriteloader.unloadFile(); + } + + spriteX = 20; + spriteY = 20; + + wKey = false; + aKey = false; + sKey = false; + dKey = false; +} + +TestManager::~TestManager() +{ + // free up memory from sprite + if(testSprite != NULL) + { + delete[] testSprite->bitmap; + delete testSprite; + testSprite = NULL; + } +} + +int TestManager::processKeys() +{ + wKey = keyPressed(0x11) > 0; + aKey = keyPressed(0x1E) > 0; + sKey = keyPressed(0x1F) > 0; + dKey = keyPressed(0x20) > 0; + return 0; +} + +int TestManager::updateState() +{ + if(wKey) + spriteY -= 1; + if(sKey) + spriteY += 1; + if(aKey) + spriteX -= 1; + if(dKey) + spriteX += 1; + return 0; +} + +int TestManager::render(GraphicsDevice& graphics) +{ + // clear screen + graphics.clearScreen(); + + // make all objects render themselves in order + + graphics.drawPixel(100, 100, 0x0F); + graphics.drawHorizontalLine(100, 110, 50, 0x0F); + graphics.drawVerticalLine(100, 120, 50, 0x0F); + if(testSprite != NULL && testSprite->bitmap != NULL) + graphics.drawSprite(spriteX,spriteY, testSprite); + else + graphics.drawHorizontalLine(5,10,25,0x0F); + + // display keyboard button presses + if(wKey) + graphics.drawPixel(50, 140, 0x0F); + if(aKey) + graphics.drawPixel(50, 150, 0x0F); + if(sKey) + graphics.drawPixel(50, 160, 0x0F); + if(dKey) + graphics.drawPixel(50, 170, 0x0F); + + + //update buffer + graphics.updateBuffer(); + + return 0; +} + +int TestManager::registerGameObject(GameObject * aGameObject) +{ + return 0; +} + +int TestManager::finished() +{ + if( spriteX > 320 ) + return FINISHED; + + return NOT_FINISHED; +} \ No newline at end of file diff -r 6366beccd211 -r bcf3d6f89c62 testman.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testman.h Wed Jul 07 19:11:38 2010 -0400 @@ -0,0 +1,40 @@ +/* + This gamemanager is used for testing +*/ + +#ifndef TESTMANAGER +#define TESTMANAGER + +#include "graphics.h" +#include "gmanager.h" +#include "gobject.h" +#include "sprload.h" +/*extern "C" { + #include "keyboard.h" +}*/ +extern "C" char keyPressed(unsigned char key); + +class TestManager : public GameManager +{ +private: + +protected: + struct sprite * testSprite; + int spriteX, spriteY; + bool wKey, aKey, sKey, dKey; + +public: + TestManager(); + ~TestManager(); + + // inherited methods + virtual int processKeys(); + virtual int updateState(); + virtual int render(GraphicsDevice& graphics); + virtual int registerGameObject(GameObject * aGameObject); + virtual int finished(); + + static const int FINISHED = 1; +}; + +#endif \ No newline at end of file