From ab08ab3fa234b84897a386a6947815e564c84646 Mon Sep 17 00:00:00 2001 From: kju Date: Thu, 21 Jan 2010 20:15:05 +0000 Subject: [PATCH] first person tetris added --- games/config.in | 11 ++--- games/tetris/input.c | 48 ++++++++++++++++++-- games/tetris/input.h | 3 +- games/tetris/logic.c | 75 ++++++++++++++++++++++++------- games/tetris/logic.h | 18 +++++++- games/tetris/tetrisfp.h | 6 +++ games/tetris/view.c | 98 ++++++++++++++++++++++++++++++++++++----- games/tetris/view.h | 10 ++++- 8 files changed, 230 insertions(+), 39 deletions(-) create mode 100644 games/tetris/tetrisfp.h diff --git a/games/config.in b/games/config.in index 6b8d000..4acc79c 100644 --- a/games/config.in +++ b/games/config.in @@ -1,11 +1,12 @@ mainmenu_option next_comment comment "Games" -dep_bool "tetris" GAME_TETRIS $JOYSTICK_SUPPORT $RANDOM_SUPPORT -dep_bool "bastet" GAME_BASTET $GAME_TETRIS -dep_bool "space invaders" GAME_SPACE_INVADERS $JOYSTICK_SUPPORT $RANDOM_SUPPORT -dep_bool "snake" GAME_SNAKE $JOYSTICK_SUPPORT $RANDOM_SUPPORT -dep_bool "breakout" GAME_BREAKOUT $JOYSTICK_SUPPORT $RANDOM_SUPPORT +dep_bool "tetris" GAME_TETRIS $JOYSTICK_SUPPORT $RANDOM_SUPPORT +dep_bool "bastet" GAME_BASTET $GAME_TETRIS +dep_bool "first person tetris" GAME_TETRIS_FP $GAME_TETRIS +dep_bool "space invaders" GAME_SPACE_INVADERS $JOYSTICK_SUPPORT $RANDOM_SUPPORT +dep_bool "snake" GAME_SNAKE $JOYSTICK_SUPPORT $RANDOM_SUPPORT +dep_bool "breakout" GAME_BREAKOUT $JOYSTICK_SUPPORT $RANDOM_SUPPORT endmenu diff --git a/games/tetris/input.c b/games/tetris/input.c index d4b4ec9..258708a 100644 --- a/games/tetris/input.c +++ b/games/tetris/input.c @@ -7,6 +7,10 @@ #include "../../util.h" #include "input.h" +#ifdef GAME_TETRIS_FP +#include "tetrisfp.h" +#endif + #include "../../compat/pgmspace.h" #define WAIT(ms) wait(ms) #define PM(value) pgm_read_word(&value) @@ -117,7 +121,7 @@ void tetris_input_chatterProtect (tetris_input_t *pIn, * Argument pIn: pointer to an input object * Return value: see definition of tetris_input_command_t */ -tetris_input_command_t tetris_input_queryJoystick() +tetris_input_command_t tetris_input_queryJoystick(uint8_t nFirstPerson) { tetris_input_command_t cmdReturn; @@ -127,11 +131,30 @@ tetris_input_command_t tetris_input_queryJoystick() } else if (JOYISLEFT) { +#ifdef GAME_TETRIS_FP + switch (tetris_screendir) { + case 0: cmdReturn = TETRIS_INCMD_LEFT; break; + case 1: cmdReturn = TETRIS_INCMD_DOWN; break; + case 2: cmdReturn = TETRIS_INCMD_RIGHT; break; + case 3: cmdReturn = TETRIS_INCMD_ROT_CW; break; + } +#else cmdReturn = TETRIS_INCMD_LEFT; +#endif + } else if (JOYISRIGHT) { +#ifdef GAME_TETRIS_FP + switch (tetris_screendir) { + case 0: cmdReturn = TETRIS_INCMD_RIGHT; break; + case 1: cmdReturn = TETRIS_INCMD_ROT_CW; break; + case 2: cmdReturn = TETRIS_INCMD_LEFT; break; + case 3: cmdReturn = TETRIS_INCMD_DOWN; break; + } +#else cmdReturn = TETRIS_INCMD_RIGHT; +#endif } else if (JOYISUP && JOYISDOWN) { @@ -140,11 +163,29 @@ tetris_input_command_t tetris_input_queryJoystick() } else if (JOYISDOWN) { +#ifdef GAME_TETRIS_FP + switch (tetris_screendir) { + case 0: cmdReturn = TETRIS_INCMD_DOWN; break; + case 1: cmdReturn = TETRIS_INCMD_RIGHT; break; + case 2: cmdReturn = TETRIS_INCMD_ROT_CW; break; + case 3: cmdReturn = TETRIS_INCMD_LEFT; break; + } +#else cmdReturn = TETRIS_INCMD_DOWN; +#endif } else if (JOYISUP) { +#ifdef GAME_TETRIS_FP + switch (tetris_screendir) { + case 0: cmdReturn = TETRIS_INCMD_ROT_CW; break; + case 1: cmdReturn = TETRIS_INCMD_LEFT; break; + case 2: cmdReturn = TETRIS_INCMD_DOWN; break; + case 3: cmdReturn = TETRIS_INCMD_RIGHT; break; + } +#else cmdReturn = TETRIS_INCMD_ROT_CW; +#endif } else { @@ -203,7 +244,8 @@ void tetris_input_destruct(tetris_input_t *pIn) * Return value: see definition of tetris_input_command_t */ tetris_input_command_t tetris_input_getCommand(tetris_input_t *pIn, - tetris_input_pace_t nPace) + tetris_input_pace_t nPace, + uint8_t nFirstPerson) { assert (pIn != NULL); @@ -230,7 +272,7 @@ tetris_input_command_t tetris_input_getCommand(tetris_input_t *pIn, while (pIn->nLoopCycles < nMaxCycles) { - cmdJoystick = tetris_input_queryJoystick(); + cmdJoystick = tetris_input_queryJoystick(nFirstPerson); // only obey current command if it is not considered as chattering if (((cmdJoystick < TETRIS_INCMD_NONE) ? diff --git a/games/tetris/input.h b/games/tetris/input.h index 26602bf..4a62f49 100644 --- a/games/tetris/input.h +++ b/games/tetris/input.h @@ -112,7 +112,8 @@ void tetris_input_destruct(tetris_input_t *pIn); * Return value: see definition of tetris_input_command_t */ tetris_input_command_t tetris_input_getCommand(tetris_input_t *pIn, - tetris_input_pace_t nPace); + tetris_input_pace_t nPace, + uint8_t nFirstPerson); /* Function: tetris_input_setLevel diff --git a/games/tetris/logic.c b/games/tetris/logic.c index 03db325..4fe3f41 100644 --- a/games/tetris/logic.c +++ b/games/tetris/logic.c @@ -13,6 +13,7 @@ #include "../../compat/pgmspace.h" #include "../../menu/menu.h" #include "../../random/prng.h" +#include "../../pixel.h" #include "logic.h" #include "piece.h" @@ -21,13 +22,15 @@ #include "input.h" #include "highscore.h" +#define NUMHIGHSCORES 3 + #ifdef GAME_BASTET #include "bast.h" -#define NUMHIGHSCORES 2 -#else -#define NUMHIGHSCORES 1 #endif +#ifdef GAME_TETRIS_FP +#include "tetrisfp.h" +#endif #ifdef EEMEM /*********************** @@ -51,6 +54,19 @@ game_descriptor_t tetris_game_descriptor tetris_icon, }; + +#ifdef GAME_TETRIS_FP +// Bastet icon, MSB is leftmost pixel +static uint8_t tetrisfp_icon[8] PROGMEM = + { 0xee, 0x89, 0xee, 0x88, 0x88, 0x20, 0x2c, 0x6c }; +game_descriptor_t tetrisfp_game_descriptor + __attribute__((section(".game_descriptors"))) = +{ + &tetris_fp, + tetrisfp_icon, +}; +#endif + #ifdef GAME_BASTET // Bastet icon, MSB is leftmost pixel static uint8_t bastet_icon[8] PROGMEM = @@ -62,6 +78,8 @@ game_descriptor_t bastet_game_descriptor bastet_icon, }; #endif + + #endif /*MENU_SUPPORT*/ /*************************** @@ -227,12 +245,23 @@ void tetris_bastet() } +/* Function: tetris_fp + * Description: runs the tetris first person game + * Return value: void + */ +void tetris_fp() +{ + tetris_main(2); +} + + /* Function: tetris_main * Description: runs the tetris game - * Argument nBastet: 0 for normal Tetris, 1 for Bastet + * Argument nMode: 0 for normal Tetris, 1 for Bastet + * 2 for first person tetris * Return value: void */ -void tetris_main(int8_t nBastet) +void tetris_main(int8_t nMode) { // get view dependent dimensions of the playfield int8_t nWidth; @@ -242,11 +271,15 @@ void tetris_main(int8_t nBastet) // holds the current user command which should be processed tetris_input_command_t inCmd; +#ifdef GAME_TETRIS_FP + tetris_screendir = 0; +#endif + // prepare data structures that drive the game... - tetris_logic_t *pLogic = tetris_logic_construct(nBastet); + tetris_logic_t *pLogic = tetris_logic_construct((nMode==1)); tetris_playfield_t *pPl = tetris_playfield_construct(nWidth, nHeight); tetris_input_t *pIn = tetris_input_construct(); - tetris_view_t *pView = tetris_view_construct(pLogic, pPl); + tetris_view_t *pView = tetris_view_construct(pLogic, pPl, (nMode==2)); #ifdef GAME_BASTET tetris_bastet_t *pBastet; #endif @@ -261,8 +294,8 @@ void tetris_main(int8_t nBastet) if (nHighscore == 0) { #endif - nHighscore = tetris_logic_retrieveHighscore(nBastet); - nHighscoreName = tetris_logic_retrieveHighscoreName(nBastet); + nHighscore = tetris_logic_retrieveHighscore(nMode); + nHighscoreName = tetris_logic_retrieveHighscoreName(nMode); #ifndef GAME_BASTET } #endif @@ -271,7 +304,7 @@ void tetris_main(int8_t nBastet) tetris_piece_t *pPiece; tetris_piece_t *pNextPiece; #ifdef GAME_BASTET - if (nBastet) + if (nMode == 1) { pBastet = tetris_bastet_construct(pPl); pNextPiece = pPiece = NULL; @@ -304,7 +337,7 @@ void tetris_main(int8_t nBastet) // the playfield awaits a new piece case TETRIS_PFS_READY: #ifdef GAME_BASTET - if (nBastet) + if (nMode == 1) { if (pPiece != NULL) { @@ -361,7 +394,7 @@ void tetris_main(int8_t nBastet) } // ensure correct view mode if the game isn't paused - if ((inCmd = tetris_input_getCommand(pIn, inPace)) + if ((inCmd = tetris_input_getCommand(pIn, inPace, (nMode==2))) != TETRIS_INCMD_PAUSE) { tetris_view_setViewMode(pView, TETRIS_VIMO_RUNNING); @@ -403,7 +436,17 @@ void tetris_main(int8_t nBastet) // player rotated the piece clockwise case TETRIS_INCMD_ROT_CW: - tetris_playfield_rotatePiece(pPl, TETRIS_PC_ROT_CW); +#ifdef GAME_TETRIS_FP + if (nMode == 2) { + tetris_view_rotate(); + tetris_playfield_rotatePiece(pPl, TETRIS_PC_ROT_CCW); + } else + { +#endif + tetris_playfield_rotatePiece(pPl, TETRIS_PC_ROT_CW); +#ifdef GAME_TETRIS_FP + } +#endif break; // player rotated the piece counter clockwise @@ -466,13 +509,13 @@ void tetris_main(int8_t nBastet) { nHighscore = nScore; nHighscoreName = tetris_highscore_inputName(); - tetris_logic_saveHighscore(nBastet, nHighscore); - tetris_logic_saveHighscoreName(nBastet, nHighscoreName); + tetris_logic_saveHighscore(nMode, nHighscore); + tetris_logic_saveHighscoreName(nMode, nHighscoreName); } // clean up #ifdef GAME_BASTET - if (nBastet) + if (nMode == 1) { tetris_bastet_destruct(pBastet); } diff --git a/games/tetris/logic.h b/games/tetris/logic.h index 0adb3a3..874b17d 100644 --- a/games/tetris/logic.h +++ b/games/tetris/logic.h @@ -55,13 +55,20 @@ void tetris(); */ void tetris_bastet(); +/* Function: tetris_fp + * Description: runs the tetris first person game + * Return value: void + */ +void tetris_fp(); + /* Function: tetris_main * Description: runs the tetris game - * Argument nBastet: 0 for normal Tetris, 1 for Bastet + * Argument nMode: 0 for normal Tetris, 1 for Bastet, + * 2 for first person tetris * Return value: void */ -void tetris_main(int8_t nBastet); +void tetris_main(int8_t nMode); /* Function: tetris_logic_singleDrop * Description: add points which result from single step dropping @@ -172,5 +179,12 @@ void tetris_logic_setPreviewPiece(tetris_logic_t *pLogic, */ tetris_piece_t* tetris_logic_getPreviewPiece(tetris_logic_t *pLogic); +#ifdef GAME_TETRIS_FP +/* Function: tetris_view_rotate + * Description: rotate view for first person mode + * Return value: void + */ +void tetris_view_rotate(void); +#endif #endif /*TETRIS_LOGIC_H_*/ diff --git a/games/tetris/tetrisfp.h b/games/tetris/tetrisfp.h new file mode 100644 index 0000000..5e873fc --- /dev/null +++ b/games/tetris/tetrisfp.h @@ -0,0 +1,6 @@ +#ifndef TETRISFP_H_ +#define TETRISFP_H_ + +extern uint8_t tetris_screendir; + +#endif /* BAST_H_ */ diff --git a/games/tetris/view.c b/games/tetris/view.c index 4fa8dd8..89a8a15 100644 --- a/games/tetris/view.c +++ b/games/tetris/view.c @@ -14,6 +14,12 @@ #define WAIT(ms) wait(ms) +#ifdef GAME_TETRIS_FP +uint8_t tetris_screendir; +#endif + +void (*setpixel_wrapper)(pixel p, unsigned char value); + /*********** * defines * @@ -38,6 +44,9 @@ #define TETRIS_VIEW_COLORCOUNTER 2 + + + /*************************** * non-interface functions * ***************************/ @@ -136,7 +145,7 @@ void tetris_view_drawDump(tetris_view_t *pV) { nColor = TETRIS_VIEW_COLORSPACE; } - setpixel((pixel){14-x,nRow}, nColor); + setpixel_wrapper((pixel){14-x,nRow}, nColor); nElementMask <<= 1; } } @@ -177,7 +186,7 @@ void tetris_view_drawPreviewPiece(tetris_view_t *pV, tetris_piece_t *pPc) { nColor = TETRIS_VIEW_COLORSPACE; } - setpixel((pixel) {3 - x, y + 6}, nColor); + setpixel_wrapper((pixel) {3 - x, y + 6}, nColor); nElementMask <<= 1; } } @@ -188,7 +197,7 @@ void tetris_view_drawPreviewPiece(tetris_view_t *pV, tetris_piece_t *pPc) { for (uint8_t x = 0; x < 4; ++x) { - setpixel((pixel) {3 - x, y + 6}, TETRIS_VIEW_COLORSPACE); + setpixel_wrapper((pixel) {3 - x, y + 6}, TETRIS_VIEW_COLORSPACE); } } } @@ -206,8 +215,8 @@ void tetris_view_drawBorders(uint8_t nColor) uint8_t x, y; for (y = 0; y < 16; ++y) { - setpixel((pixel){4, y}, nColor); - setpixel((pixel){15, y}, nColor); + setpixel_wrapper((pixel){4, y}, nColor); + setpixel_wrapper((pixel){15, y}, nColor); } for (y = 0; y < 5; ++y) @@ -216,8 +225,8 @@ void tetris_view_drawBorders(uint8_t nColor) { if ((y < 1 || y > 3) || (x < 1 || y > 3)) { - setpixel((pixel){x, y}, nColor); - setpixel((pixel){x, y + 11}, nColor); + setpixel_wrapper((pixel){x, y}, nColor); + setpixel_wrapper((pixel){x, y + 11}, nColor); } } } @@ -276,7 +285,7 @@ void tetris_view_blinkLines(tetris_playfield_t *pPl) uint8_t nColor = (nColIdx == 0 ? TETRIS_VIEW_COLORFADE : TETRIS_VIEW_COLORPIECE); - setpixel((pixel){14 - x, y}, nColor); + setpixel_wrapper((pixel){14 - x, y}, nColor); } } } @@ -316,9 +325,9 @@ void tetris_view_showLineNumbers(tetris_view_t *pV) x = 1; } // ones - setpixel((pixel){x, y}, nOnesPen); + setpixel_wrapper((pixel){x, y}, nOnesPen); // tens (increment x, add vertical offset for lower part of the border) - setpixel((pixel){x++, y + 11}, nTensPen); + setpixel_wrapper((pixel){x++, y + 11}, nTensPen); } } @@ -334,7 +343,8 @@ void tetris_view_showLineNumbers(tetris_view_t *pV) * Return value: pointer to a newly created view */ tetris_view_t *tetris_view_construct(tetris_logic_t *pLogic, - tetris_playfield_t *pPl) + tetris_playfield_t *pPl, + uint8_t nFirstPerson) { // memory allocation assert((pLogic != NULL) && (pPl != NULL)); @@ -349,6 +359,16 @@ tetris_view_t *tetris_view_construct(tetris_logic_t *pLogic, pView->modeCurrent = TETRIS_VIMO_RUNNING; pView->modeOld = TETRIS_VIMO_RUNNING; +#ifdef GAME_TETRIS_FP + // set setpixel wrapper + if (nFirstPerson) + setpixel_wrapper = tetris_view_setpixel_fp; + else + setpixel_wrapper = setpixel; +#else + setpixel_wrapper = setpixel; +#endif + // drawing some first stuff clear_screen(0); tetris_view_drawBorders(TETRIS_VIEW_COLORBORDER); @@ -487,3 +507,59 @@ void tetris_view_showResults(tetris_view_t *pV) #endif } + +#ifdef GAME_TETRIS_FP +/* Function: tetris_view_setpixel_fp + * Description: own setpixel wrapper for first person mode + * Return value: void + */ +void tetris_view_setpixel_fp(pixel p, unsigned char value) { + switch (tetris_screendir) { + case 0: setpixel(p,value); break; + case 1: setpixel((pixel){p.y,15-p.x}, value); break; + case 2: setpixel((pixel){15-p.x,15-p.y}, value); break; + case 3: setpixel((pixel){15-p.y,p.x}, value); break; + } +} + +/* Function: tetris_view_rotate + * Description: rotate view for first person mode + * Return value: void + */ +void tetris_view_rotate(void) { + unsigned char plane, row, byte, shift, off, sbyte, hrow; + unsigned char new_pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; + + tetris_screendir = (tetris_screendir+1)%4; + +// if ( NUM_ROWS != 16 || LINEBYTES != 2 ) return; + + memset(&new_pixmap, 0, sizeof(new_pixmap)); + for(plane=0; plane> shift)&1) << 7 ) | + ( ((pixmap[plane][off-1][sbyte] >> shift)&1) << 6 ) | + ( ((pixmap[plane][off-2][sbyte] >> shift)&1) << 5 ) | + ( ((pixmap[plane][off-3][sbyte] >> shift)&1) << 4 ) | + ( ((pixmap[plane][off-4][sbyte] >> shift)&1) << 3 ) | + ( ((pixmap[plane][off-5][sbyte] >> shift)&1) << 2 ) | + ( ((pixmap[plane][off-6][sbyte] >> shift)&1) << 1 ) | + ( ((pixmap[plane][off-7][sbyte] >> shift)&1) << 0 ) + ); + + } + } + } + + memcpy(&pixmap, &new_pixmap, sizeof(pixmap)); +} + +#endif \ No newline at end of file diff --git a/games/tetris/view.h b/games/tetris/view.h index 6daabd8..2872d02 100644 --- a/games/tetris/view.h +++ b/games/tetris/view.h @@ -42,7 +42,8 @@ tetris_view_t; * Return value: pointer to a newly created view */ tetris_view_t *tetris_view_construct(tetris_logic_t *pLogic, - tetris_playfield_t *pPl); + tetris_playfield_t *pPl, + uint8_t nFirstPerson); /* Function: tetris_view_destruct @@ -91,6 +92,13 @@ void tetris_view_update(tetris_view_t *pV); */ void tetris_view_showResults(tetris_view_t *pV); +#ifdef GAME_TETRIS_FP +/* Function: tetris_view_setpixel_fp + * Description: own setpixel wrapper for first person mode + * Return value: void + */ +void tetris_view_setpixel_fp(pixel p, unsigned char value); +#endif #endif /*TETRIS_VIEW_H_*/