Tetris: Add separate highscore counters for standard and bastet. Add input

and display of three character nick name for highscore achiever.
This commit is contained in:
kju 2010-01-11 21:47:56 +00:00
parent 521b73e6ae
commit 187765a1ef
6 changed files with 240 additions and 24 deletions

View File

@ -4,9 +4,9 @@ TOPDIR = ../..
include $(TOPDIR)/defaults.mk
ifeq ($(GAME_BASTET),y)
SRC = piece.c playfield.c view.c logic.c input.c bast.c
SRC = piece.c playfield.c view.c logic.c input.c highscore.c bast.c
else
SRC = piece.c playfield.c view.c logic.c input.c
SRC = piece.c playfield.c view.c logic.c input.c highscore.c
endif
include $(TOPDIR)/rules.mk

85
games/tetris/highscore.c Normal file
View File

@ -0,0 +1,85 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <inttypes.h>
#include "../../config.h"
#include "../../scrolltext/scrolltext.h"
#include "../../joystick/joystick.h"
#include "highscore.h"
/* Function: tetris_highscore_inputName
* Description: let user input a three character name
* Return value: name packed into a uint16_t
*/
uint16_t tetris_highscore_inputName(void)
{
char nick[4], tmp[40];
uint8_t xpos;
uint8_t pos=0, blink=0, done=0, hadfire=0;
sprintf(nick, "AAA");
while(!done)
{
// We need to do our own blink interval
blink = (blink+1) % 4;
// Determine start position on screen
// depending on active character
switch (pos)
{
case 0: xpos = 15; break;
case 1: xpos = 19; break;
case 2: xpos = 23; break;
}
// Construct command for scrolltext and execute
sprintf(tmp, "x%d+p1#%c#x%d+p1#%c#x%dp1#%c",
xpos, (!blink && pos == 0) ? ' ' : nick[0],
xpos-8, (!blink && pos == 1 ) ? ' ' : nick[1],
xpos-15, (!blink && pos == 2 ) ? ' ' : nick[2]);
scrolltext(tmp);
// up and down control current char
if (JOYISUP)
{
nick[pos]++;
if (nick[pos] == '`') nick[pos] = 'A';
if (nick[pos] == '[') nick[pos] = '_';
}
if (JOYISDOWN)
{
nick[pos]--;
if (nick[pos] == '@') nick[pos] = '_';
if (nick[pos] == '^') nick[pos] = 'Z';
}
// left and right control char selections
if (JOYISLEFT && pos > 0) pos--;
if (JOYISRIGHT && pos < 2) pos++;
// fire switches to next char or exits
if (JOYISFIRE&&!hadfire)
{
hadfire=1;
switch (pos)
{
case 0: pos=1; break;
case 1: pos=2; break;
case 2: done=1; break;
}
}
if (hadfire&&!JOYISFIRE)
hadfire=0;
}
// return result
return(
(nick[0]-65)<<10 |
(nick[1]-65)<<5 |
(nick[2]-65)
);
}

6
games/tetris/highscore.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef TETRIS_HIGHSCORE_H_
#define TETRIS_HIGHSCORE_H_
uint16_t tetris_highscore_inputName(void);
#endif /*TETRIS_HIGHSCORE_H_*/

View File

@ -19,9 +19,13 @@
#include "playfield.h"
#include "view.h"
#include "input.h"
#include "highscore.h"
#ifdef GAME_BASTET
#include "bast.h"
#define NUMHIGHSCORES 2
#else
#define NUMHIGHSCORES 1
#endif
@ -30,7 +34,8 @@
* Highscore in EEPROM *
***********************/
uint16_t tetris_logic_nHighscore EEMEM;
uint16_t tetris_logic_nHighscore[NUMHIGHSCORES] EEMEM;
uint16_t tetris_logic_nHighscoreName[NUMHIGHSCORES] EEMEM;
#endif
// Tetris icon, MSB is leftmost pixel
@ -82,11 +87,11 @@ uint8_t tetris_logic_calculateLines(uint8_t nRowMask)
return nLines;
}
uint16_t tetris_logic_retrieveHighscore(void)
uint16_t tetris_logic_retrieveHighscore(uint8_t nHighscoreIndex)
{
#ifdef EEMEM
uint16_t nHighscore = 0;
nHighscore = eeprom_read_word(&tetris_logic_nHighscore);
nHighscore = eeprom_read_word(&tetris_logic_nHighscore[nHighscoreIndex]);
// a score of 65535 is most likely caused by uninitialized EEPROM addresses
if (nHighscore == 65535)
@ -100,30 +105,57 @@ uint16_t tetris_logic_retrieveHighscore(void)
#endif
}
void tetris_logic_saveHighscore(uint16_t nHighscore)
void tetris_logic_saveHighscore(uint8_t nHighscoreIndex, uint16_t nHighscore)
{
#ifdef EEMEM
if (nHighscore > tetris_logic_retrieveHighscore())
if (nHighscore > tetris_logic_retrieveHighscore(nHighscoreIndex))
{
eeprom_write_word(&tetris_logic_nHighscore, nHighscore);
eeprom_write_word(&tetris_logic_nHighscore[nHighscoreIndex], nHighscore);
}
#endif
}
uint16_t tetris_logic_retrieveHighscoreName(uint8_t nHighscoreIndex)
{
#ifdef EEMEM
uint16_t nHighscoreName = 0;
nHighscoreName = eeprom_read_word(&tetris_logic_nHighscoreName[nHighscoreIndex]);
// a score of 65535 is most likely caused by uninitialized EEPROM addresses
if (nHighscoreName == 65535)
{
nHighscoreName = 0;
}
return nHighscoreName;
#else
return 0;
#endif
}
void tetris_logic_saveHighscoreName(uint8_t nHighscoreIndex, uint16_t nHighscoreName)
{
#ifdef EEMEM
eeprom_write_word(&tetris_logic_nHighscoreName[nHighscoreIndex], nHighscoreName);
#endif
}
/****************************
* construction/destruction *
****************************/
/* Function: tetris_logic_construct
* Description: constructs a logic object
* Return value: pointer to a newly created logic object
/* Function: tetris_logic_construct
* Description: constructs a logic object
* Argument nBastet: 0 for normal tetris, 1 for bastet
* Return value: pointer to a newly created logic object
*/
tetris_logic_t *tetris_logic_construct()
tetris_logic_t *tetris_logic_construct(uint8_t nBastet)
{
tetris_logic_t *pLogic = (tetris_logic_t *) malloc(sizeof(tetris_logic_t));
assert(pLogic != NULL);
memset(pLogic, 0, sizeof(tetris_logic_t));
pLogic->nBastet = nBastet;
return pLogic;
}
@ -179,7 +211,7 @@ void tetris_main(int8_t nBastet)
tetris_input_command_t inCmd;
// prepare data structures that drive the game...
tetris_logic_t *pLogic = tetris_logic_construct();
tetris_logic_t *pLogic = tetris_logic_construct(nBastet);
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);
@ -192,10 +224,16 @@ void tetris_main(int8_t nBastet)
// retrieve highscore
static uint16_t nHighscore = 0;
static uint16_t nHighscoreName = 0;
#ifndef GAME_BASTET
if (nHighscore == 0)
{
nHighscore = tetris_logic_retrieveHighscore();
#endif
nHighscore = tetris_logic_retrieveHighscore(nBastet);
nHighscoreName = tetris_logic_retrieveHighscoreName(nBastet);
#ifndef GAME_BASTET
}
#endif
// initialize current and next piece
tetris_piece_t *pPiece;
@ -220,6 +258,7 @@ void tetris_main(int8_t nBastet)
// status so we must put information like the next piece or the current
// highscore to a place where the view can find it
tetris_logic_setHighscore(pLogic, nHighscore);
tetris_logic_setHighscoreName(pLogic, nHighscoreName);
// pace flag
tetris_input_pace_t inPace;
@ -392,7 +431,9 @@ void tetris_main(int8_t nBastet)
if (nScore > nHighscore)
{
nHighscore = nScore;
tetris_logic_saveHighscore(nHighscore);
nHighscoreName = tetris_highscore_inputName();
tetris_logic_saveHighscore(nBastet, nHighscore);
tetris_logic_saveHighscoreName(nBastet, nHighscoreName);
}
// clean up
@ -421,6 +462,9 @@ void tetris_logic_singleDrop(tetris_logic_t *pLogic,
uint8_t nLines)
{
assert(pLogic != 0);
#ifdef GAME_BASTET
if (pLogic->nBastet) return;
#endif
pLogic->nScore += nLines;
}
@ -435,6 +479,9 @@ void tetris_logic_completeDrop(tetris_logic_t *pLogic,
uint8_t nLines)
{
assert(pLogic != 0);
#ifdef GAME_BASTET
if (pLogic->nBastet) return;
#endif
pLogic->nScore += nLines * 2;
}
@ -454,6 +501,13 @@ void tetris_logic_removedLines(tetris_logic_t *pLogic,
pLogic->nLevel = ((pLogic->nLines / 10) < TETRIS_INPUT_LEVELS) ?
(pLogic->nLines / 10) : (TETRIS_INPUT_LEVELS - 1);
#ifdef GAME_BASTET
if (pLogic->nBastet)
{
pLogic->nScore += nLines;
return;
}
#endif
switch (nLines)
{
case 1:
@ -514,6 +568,32 @@ void tetris_logic_setHighscore(tetris_logic_t *pLogic,
}
/* Function: tetris_logic_getHighscoreName
* Description: returns the current highscore name
* Argument pLogic: the logic object we want information from
* Return value: the highscore name packed as uint16_t
*/
uint16_t tetris_logic_getHighscoreName(tetris_logic_t *pLogic)
{
assert(pLogic != NULL);
return pLogic->nHighscoreName;
}
/* Function: tetris_logic_setHighscoreName
* Description: set highscore name
* Argument pLogic: the logic object we want to modify
* Argmument nHighscoreName: highscore name
*/
void tetris_logic_setHighscoreName(tetris_logic_t *pLogic,
uint16_t nHighscoreName)
{
assert(pLogic != NULL);
pLogic->nHighscoreName = nHighscoreName;
}
/* Function: tetris_logic_getLevel
* Description: returns the current level
* Argument pLogic: the logic object we want information from

View File

@ -10,8 +10,10 @@
typedef struct tetris_logic_t
{
uint8_t nBastet; // is gametype bastet?
uint16_t nScore; // score of the player
uint16_t nHighscore; // highscore
uint16_t nHighscoreName; // name of the person who achieved highscore
uint8_t nLevel; // current level
uint16_t nLines; // number of completed lines
tetris_piece_t *pPreviewPiece; // the piece intended to be the next one
@ -22,11 +24,12 @@ tetris_logic_t;
* construction/destruction *
****************************/
/* Function: tetris_logic_construct
* Description: constructs a logic object
* Return value: pointer to a newly created logic object
/* Function: tetris_logic_construct
* Description: constructs a logic object
* Argument nBastet: 0 for normal tetris, 1 for bastet
* Return value: pointer to a newly created logic object
*/
tetris_logic_t *tetris_logic_construct();
tetris_logic_t *tetris_logic_construct(uint8_t nBastet);
/* Function: tetris_logic_destruct
* Description: destructs a logic object
@ -119,6 +122,23 @@ void tetris_logic_setHighscore(tetris_logic_t *pLogic,
uint16_t nHighscore);
/* Function: tetris_logic_getHighscoreName
* Description: returns the current highscore name
* Argument pLogic: the logic object we want information from
* Return value: the highscore name packed as uint16_t
*/
uint16_t tetris_logic_getHighscoreName(tetris_logic_t *pLogic);
/* Function: tetris_logic_setHighscoreName
* Description: set highscore name
* Argument pLogic: the logic object we want to modify
* Argmument nHighscoreName: highscore name
*/
void tetris_logic_setHighscoreName(tetris_logic_t *pLogic,
uint16_t nHighscoreName);
/* Function: tetris_logic_getLevel
* Description: returns the current level
* Argument pLogic: the logic object we want information from

View File

@ -434,6 +434,28 @@ void tetris_view_update(tetris_view_t *pV)
}
/* Function: tetris_view_formatHighscoreName
* Description: convert uint16_t into ascii Highscore
* (only used internally in view.c)
* Argument nHighscoreName: packed integer with highscoreName
* Argument pszName: pointer to a char array where result is stored
* Return value: void
*/
void tetris_view_formatHighscoreName(uint16_t nHighscoreName, char *pszName)
{
pszName[0] = ((nHighscoreName>>10)&0x1F) + 65;
if (pszName[0] == '_') pszName[0] = ' ';
pszName[1] = ((nHighscoreName>> 5)&0x1F) + 65;
if (pszName[1] == '_') pszName[1] = ' ';
pszName[2] = ( nHighscoreName &0x1F) + 65;
if (pszName[2] == '_') pszName[2] = ' ';
pszName[3] = 0;
}
/* Function: tetris_view_showResults
* Description: shows results after game
* Argument pV: pointer to the view which should show the reults
@ -441,20 +463,23 @@ void tetris_view_update(tetris_view_t *pV)
*/
void tetris_view_showResults(tetris_view_t *pV)
{
char pszResults[48];
char pszResults[54], pszHighscoreName[4];
uint16_t nScore = tetris_logic_getScore(pV->pLogic);
uint16_t nHighscore = tetris_logic_getHighscore(pV->pLogic);
uint16_t nLines = tetris_logic_getLines(pV->pLogic);
uint16_t nHighscoreName = tetris_logic_getHighscoreName(pV->pLogic);
tetris_view_formatHighscoreName(nHighscoreName, pszHighscoreName);
if (nScore <= nHighscore)
{
snprintf(pszResults, 48 * sizeof(char),
"</#Lines %u Score %u Highscore %u",
nLines, nScore, nHighscore);
snprintf(pszResults, sizeof(pszResults),
"</#Lines %u Score %u Highscore %u (%s)",
nLines, nScore, nHighscore, pszHighscoreName);
}
else
{
snprintf(pszResults, 48 * sizeof(char),
snprintf(pszResults, sizeof(pszResults),
"</#Lines %u New Highscore %u", nLines, nScore);
}
#ifdef SCROLLTEXT_SUPPORT