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:
parent
521b73e6ae
commit
187765a1ef
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef TETRIS_HIGHSCORE_H_
|
||||
#define TETRIS_HIGHSCORE_H_
|
||||
|
||||
uint16_t tetris_highscore_inputName(void);
|
||||
|
||||
#endif /*TETRIS_HIGHSCORE_H_*/
|
|
@ -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,16 +105,41 @@ 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 *
|
||||
|
@ -117,13 +147,15 @@ void tetris_logic_saveHighscore(uint16_t nHighscore)
|
|||
|
||||
/* 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
|
||||
|
|
|
@ -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
|
||||
|
@ -24,9 +26,10 @@ tetris_logic_t;
|
|||
|
||||
/* 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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue