Browse Source

synced with my personal Bastet tree

feature/2015
Christian Kroll 15 years ago
parent
commit
903072815b
  1. 12
      animations/Makefile
  2. 4
      defaults.mk
  3. 25
      display_loop.c
  4. 1
      games/config.in
  5. 6
      games/tetris/Makefile
  6. 151
      games/tetris/bast.c
  7. 26
      games/tetris/bast.h
  8. 172
      games/tetris/logic.c
  9. 14
      games/tetris/logic.h
  10. 29
      games/tetris/playfield.c
  11. 6
      games/tetris/playfield.h
  12. 111
      games/tetris/view.c

12
animations/Makefile

@ -13,13 +13,13 @@ ifeq ($(ANIMATION_MATRIX),y)
SRC += matrix.c
endif
ifeq ($(ANIMATION_STONEFLY),y)
SRC += stonefly.c
endif
ifeq ($(ANIMATION_STONEFLY),y)
SRC += stonefly.c
endif
ifeq ($(ANIMATION_FLYINGDOTS),y)
SRC += flyingdots.c
endif
ifeq ($(ANIMATION_FLYINGDOTS),y)
SRC += flyingdots.c
endif
ifeq ($(ANIMATION_GAMEOFLIFE),y)
SRC += gameoflife.c

4
defaults.mk

@ -19,7 +19,7 @@ export HOSTCC
# flags for the compiler
CFLAGS ?= -Wall -W -Wno-unused-parameter -Wno-sign-compare
CFLAGS += -g -Os -std=gnu99 -fgnu89-inline
CFLAGS += -g -Os -std=gnu99 -fgnu89-inline -DNDEBUG
# flags for the linker
LDFLAGS += -T ./avr5.x -mmcu=$(MCU)
@ -33,7 +33,7 @@ MACHINE = $(shell uname -m)
#$(info $(OSTYPE))
ifeq ($(OSTYPE),cygwin)
CFLAGS_SIM = -g -Wall -pedantic -std=c99 -O2 -D_WIN32 -mno-cygwin
CFLAGS_SIM = -g -Wall -pedantic -std=c99 -O0 -D_WIN32 -mno-cygwin
LDFLAGS_SIM = -Wl -mno-cygwin -T simulator/i386pe.x
LIBS_SIM = -lglut32 -lglu32 -lopengl32
else

25
display_loop.c

@ -7,7 +7,7 @@
#include "animations/programm.h"
#include "animations/matrix.h"
#include "animations/gameoflife.h"
#include "animations/stonefly.h"
#include "animations/stonefly.h"
#include "animations/flyingdots.h"
#include "borg_hw/borg_hw.h"
#include "can/borg_can.h"
@ -92,12 +92,12 @@ void display_loop(){
break;
#endif
#ifdef ANIMATION_STONEFLY
case 9:
stonefly();
break;
#endif
#ifdef ANIMATION_STONEFLY
case 9:
stonefly();
break;
#endif
#ifdef ANIMATION_GAMEOFLIFE
case 10:
gameoflife();
@ -109,10 +109,10 @@ void display_loop(){
flyingdots();
break;
#endif
#ifdef ANIMATION_MHERWEG
case 11:
case 11:
flydots();
lines1();
dots1();
movinglines();
@ -141,10 +141,9 @@ void display_loop(){
break;
#endif
case 42:
mode = 1;
break;
case 42:
mode = 1;
break;
#ifdef MENU_SUPPORT
case 43:

1
games/config.in

@ -2,6 +2,7 @@ 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

6
games/tetris/Makefile

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

151
games/tetris/bast.c

@ -1,6 +1,7 @@
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include "../../random/prng.h"
#include "piece.h"
#include "playfield.h"
#include "bast.h"
@ -13,18 +14,46 @@
/* Function: tetris_bastet_clearColHeights;
* Description: resets the array for the column heights
* Argument pBastet: bastet instance whose array should be reset
* Argument nStart: start index
* Argument nStop: stop index
* Return value: void
*/
void tetris_bastet_clearColHeights(tetris_bastet_t *pBastet)
void tetris_bastet_clearColHeights(tetris_bastet_t *pBastet,
int8_t nStart,
int8_t nStop)
{
int8_t nWidth = tetris_playfield_getWidth(pBastet->pPlayfield);
for (int i = 0; i < nWidth; ++i)
for (int i = nStart; i <= nStop; ++i)
{
pBastet->pColHeights[i] = 0;
}
}
/* Function: tetris_bastet_qsortCompare
* Description: compare function for quick sorting the pieces by score
* Argument pa: the first value to compare
* Argument pb: the second value to compare
* Return value: void
*/
int tetris_bastet_qsortCompare(const void *pa, const void *pb)
{
tetris_bastet_scorepair_t *pScoreA = (tetris_bastet_scorepair_t *)pa;
tetris_bastet_scorepair_t *pScoreB = (tetris_bastet_scorepair_t *)pb;
if (pScoreA->nScore == pScoreB->nScore)
{
return 0;
}
else if (pScoreA->nScore < pScoreB->nScore)
{
return -1;
}
else
{
return 1;
}
}
/****************************
* construction/destruction *
****************************/
@ -43,7 +72,7 @@ tetris_bastet_t* tetris_bastet_construct(tetris_playfield_t *pPl)
int8_t nWidth = tetris_playfield_getWidth(pBastet->pPlayfield);
pBastet->pColHeights = (int8_t*) calloc(nWidth, sizeof(int8_t));
tetris_bastet_clearColHeights(pBastet);
tetris_bastet_clearColHeights(pBastet, 0, nWidth - 1);
return pBastet;
}
@ -87,20 +116,46 @@ int16_t tetris_bastet_evalPos(tetris_bastet_t *pBastet,
pPiece, nColumn);
nScore += 5000 * nLines;
// determine sane start and stop columns whose heights we want to calculate
int8_t nWidth = tetris_playfield_getWidth(pBastet->pPlayfield);
int8_t nStartCol = ((nColumn - 1) < 0) ? 0 : nColumn - 1;
int8_t nStopCol;
// do we start at the left most position?
if (nColumn <= -3)
{
// in case we start at the left most position we calculate all heights
nStopCol = nWidth - 1;
// reset all column heights to zero
tetris_bastet_clearColHeights(pBastet, 0 , nWidth);
}
// if not, only calculate columns which are affected by the piece
else
{
nStopCol = (nColumn + 3) < nWidth ? nColumn + 3 : nWidth - 1;
// clear affected column heights to prevent miscalculations
tetris_bastet_clearColHeights(pBastet, nStartCol, nStopCol);
}
// go through every row and calculate column heights
tetris_playfield_iterator_t iterator;
int8_t nWidth = tetris_playfield_getWidth(pBastet->pPlayfield);
int8_t nHeight = 1;
uint16_t *pDump = tetris_playfield_predictBottomRow(&iterator,
pBastet->pPlayfield, pPiece, nColumn);
if (pDump == NULL)
{
// an immediately returned NULL is caused by a full dump -> low score
return -32766;
}
while (pDump != NULL)
{
for (int x = 0; x < nWidth; ++x)
uint16_t nColMask = 0x0001 << nStartCol;
for (int x = nStartCol; x <= nStopCol; ++x)
{
if ((*pDump & (0x0001 << x)) != 0)
if ((*pDump & nColMask) != 0)
{
pBastet->pColHeights[x] = nHeight;
}
nColMask <<= 1;
}
pDump = tetris_playfield_predictNextRow(&iterator);
++nHeight;
@ -111,8 +166,84 @@ int16_t tetris_bastet_evalPos(tetris_bastet_t *pBastet,
nScore -= 5 * pBastet->pColHeights[x];
}
// reset column height array for later use
tetris_bastet_clearColHeights(pBastet);
return nScore;
}
/* Function: tetris_bastet_minimax
* Description: calculates the best possible score for every piece
* Argument pBastet: the bastet instance of interest
* Return value: void
*/
void tetris_bastet_minimax(tetris_bastet_t *pBastet)
{
int8_t nWidth = tetris_playfield_getWidth(pBastet->pPlayfield);
tetris_piece_t *pPiece = tetris_piece_construct(TETRIS_PC_LINE,
TETRIS_PC_ANGLE_0);
for (int8_t nBlock = TETRIS_PC_LINE; nBlock <= TETRIS_PC_Z; ++nBlock)
{
int16_t nMaxScore = -32768;
tetris_piece_changeShape(pPiece, nBlock);
int8_t nAngleCount = tetris_piece_angleCount(pPiece);
for (int8_t nAngle = TETRIS_PC_ANGLE_0; nAngle < nAngleCount; ++nAngle)
{
tetris_piece_changeAngle(pPiece, nAngle);
for (int8_t nCol = -3; nCol < nWidth; ++nCol)
{
int16_t nScore = tetris_bastet_evalPos(pBastet, pPiece, nCol);
nMaxScore = nMaxScore > nScore ? nMaxScore : nScore;
}
}
pBastet->nPieceScores[nBlock].shape = nBlock;
pBastet->nPieceScores[nBlock].nScore = nMaxScore;
}
tetris_piece_destruct(pPiece);
}
/* Function: tetris_bastet_choosePiece
* Description: calculates the worst possible piece
* Argument pBastet: the bastet instance of interest
* Return value: the worst possible piece
*/
tetris_piece_t* tetris_bastet_choosePiece(tetris_bastet_t *pBastet)
{
const uint8_t nPercent[7] = {75, 92, 98, 100, 100, 100, 100};
tetris_bastet_minimax(pBastet);
// perturb score (-2 to +2) to avoid stupid tie handling
for (uint8_t i = 0; i < 7; ++i)
{
pBastet->nPieceScores[i].nScore += random8() % 5 - 2;
}
qsort(pBastet->nPieceScores, 7, sizeof(tetris_bastet_scorepair_t),
&tetris_bastet_qsortCompare);
uint8_t rnd = rand() % 100;
for (uint8_t i = 0; i < 7; i++)
{
if (rnd < nPercent[i])
{
return tetris_piece_construct(pBastet->nPieceScores[i].shape,
TETRIS_PC_ANGLE_0);
}
}
//should not arrive here
return tetris_piece_construct(pBastet->nPieceScores[0].shape,
TETRIS_PC_ANGLE_0);
}
/* Function: tetris_bastet_choosePreviewPiece
* Description: returns the best possible piece
* (run tetris_bastet_choosePiece first!)
* Argument pBastet: the bastet instance of interest
* Return value: the worst possible piece
*/
tetris_piece_t* tetris_bastet_choosePreviewPiece(tetris_bastet_t *pBastet)
{
return tetris_piece_construct(pBastet->nPieceScores[6].shape,
TETRIS_PC_ANGLE_0);
}

26
games/tetris/bast.h

@ -9,10 +9,19 @@
* types *
*********/
typedef struct tetris_bastet_scorepair_t
{
tetris_piece_shape_t shape;
int16_t nScore;
}
tetris_bastet_scorepair_t;
typedef struct tetris_bastet_t
{
tetris_playfield_t *pPlayfield; // the playfield to be examined
int8_t *pColHeights; // array of calculated column heights
tetris_playfield_t *pPlayfield; // the playfield to be examined
int8_t *pColHeights; // array of calculated heights
tetris_bastet_scorepair_t nPieceScores[7]; // score for every piece
}
tetris_bastet_t;
@ -52,4 +61,17 @@ int16_t tetris_bastet_evalPos(tetris_bastet_t *pBastet,
tetris_piece_t *pPiece,
int8_t nColumn);
/* Function: tetris_bastet_minimax
* Description: calculates the best possible score for every piece
* Argument pBastet: the bastet instance of interest
* Return value: void
*/
void tetris_bastet_minimax();
tetris_piece_t* tetris_bastet_choosePiece(tetris_bastet_t *pBastet);
tetris_piece_t* tetris_bastet_choosePreviewPiece(tetris_bastet_t *pBastet);
#endif /* BAST_H_ */

172
games/tetris/logic.c

@ -8,36 +8,53 @@
#include <assert.h>
#include <inttypes.h>
#include "../../autoconf.h"
#include "../../compat/eeprom.h"
#include "../../compat/pgmspace.h"
#include "../../menu/menu.h"
#include "../../random/prng.h"
#include "logic.h"
#include "piece.h"
#include "playfield.h"
#include "view.h"
#include "input.h"
#include "../../random/prng.h"
#ifdef GAME_BASTET
#include "bast.h"
#endif
#ifdef EEMEM
/***********************
* Highscore in EEPROM *
***********************/
/***********************
* Highscore in EEPROM *
***********************/
uint16_t tetris_logic_nHighscore EEMEM;
uint16_t tetris_logic_nHighscore EEMEM;
#endif
// MSB is leftmost pixel
static uint8_t icon[8] PROGMEM =
{0x0f, 0x0f, 0xc3, 0xdb, 0xdb, 0xc3, 0xf0, 0xf0}; // Tetris icon
// Tetris icon, MSB is leftmost pixel
void tetris();
static uint8_t tetris_icon[8] PROGMEM =
{ 0x0f, 0x0f, 0xc3, 0xdb, 0xdb, 0xc3, 0xf0, 0xf0 };
game_descriptor_t tetris_game_descriptor
__attribute__((section(".game_descriptors"))) =
{
&tetris,
tetris_icon,
};
game_descriptor_t tetris_game_descriptor __attribute__((section(".game_descriptors"))) ={
&tetris,
icon,
#ifdef GAME_BASTET
// Bastet icon, MSB is leftmost pixel
static uint8_t bastet_icon[8] PROGMEM =
{ 0x81, 0xc3, 0xff, 0x99, 0xff, 0xff, 0x66, 0x3c };
game_descriptor_t bastet_game_descriptor
__attribute__((section(".game_descriptors"))) =
{
&tetris_bastet,
bastet_icon,
};
#endif
/***************************
@ -104,7 +121,7 @@ void tetris_logic_saveHighscore(uint16_t nHighscore)
*/
tetris_logic_t *tetris_logic_construct()
{
tetris_logic_t *pLogic = (tetris_logic_t *)malloc(sizeof(tetris_logic_t));
tetris_logic_t *pLogic = (tetris_logic_t *) malloc(sizeof(tetris_logic_t));
assert(pLogic != NULL);
memset(pLogic, 0, sizeof(tetris_logic_t));
return pLogic;
@ -130,7 +147,28 @@ void tetris_logic_destruct(tetris_logic_t *pLogic)
* Description: runs the tetris game
* Return value: void
*/
void tetris ()
void tetris()
{
tetris_main(0);
}
/* Function: tetris_bastet
* Description: runs the bastet game
* Return value: void
*/
void tetris_bastet()
{
tetris_main(1);
}
/* Function: tetris_main
* Description: runs the tetris game
* Argument nBastet: 0 for normal Tetris, 1 for Bastet
* Return value: void
*/
void tetris_main(int8_t nBastet)
{
// get view dependent dimensions of the playfield
int8_t nWidth;
@ -145,6 +183,9 @@ void tetris ()
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);
#ifdef GAME_BASTET
tetris_bastet_t *pBastet;
#endif
// runtime variable
int8_t nPieceRow;
@ -157,15 +198,28 @@ void tetris ()
}
// initialize current and next piece
tetris_piece_t *pPiece = NULL;
tetris_piece_t *pNextPiece = pPiece =
tetris_piece_construct(random8() % 7, TETRIS_PC_ANGLE_0);
tetris_piece_t *pPiece;
tetris_piece_t *pNextPiece;
#ifdef GAME_BASTET
if (nBastet)
{
pBastet = tetris_bastet_construct(pPl);
pNextPiece = pPiece = NULL;
}
else
{
#endif
pNextPiece = pPiece =
tetris_piece_construct(random8() % 7, TETRIS_PC_ANGLE_0);
tetris_logic_setPreviewPiece(pLogic, pNextPiece);
#ifdef GAME_BASTET
}
#endif
// the view only monitors the logic and the playfield object for the game
// 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_setPreviewPiece(pLogic, pNextPiece);
// pace flag
tetris_input_pace_t inPace;
@ -178,22 +232,45 @@ void tetris ()
{
// the playfield awaits a new piece
case TETRIS_PFS_READY:
// make preview piece the current piece and create new preview piece
pPiece = pNextPiece;
pNextPiece =
tetris_piece_construct(random8() % 7, TETRIS_PC_ANGLE_0);
tetris_logic_setPreviewPiece(pLogic, pNextPiece);
// insert new piece into playfield
tetris_piece_t *pOldPiece;
tetris_playfield_insertPiece(pPl, pPiece, &pOldPiece);
// destruct old piece (if it exists) since we don't need it anymore
if (pOldPiece != NULL)
#ifdef GAME_BASTET
if (nBastet)
{
tetris_piece_destruct(pOldPiece);
pOldPiece = NULL;
if (pPiece != NULL)
{
tetris_piece_destruct(pPiece);
}
if (pNextPiece != NULL)
{
tetris_piece_destruct(pNextPiece);
}
pPiece = tetris_bastet_choosePiece(pBastet);
pNextPiece = tetris_bastet_choosePreviewPiece(pBastet);
tetris_piece_t *pOldPiece;
tetris_playfield_insertPiece(pPl, pPiece, &pOldPiece);
tetris_logic_setPreviewPiece(pLogic, pNextPiece);
}
else
{
#endif
// make preview piece the current piece and create new preview piece
pPiece = pNextPiece;
pNextPiece = tetris_piece_construct(random8() % 7,
TETRIS_PC_ANGLE_0);
tetris_logic_setPreviewPiece(pLogic, pNextPiece);
// insert new piece into playfield
tetris_piece_t *pOldPiece;
tetris_playfield_insertPiece(pPl, pPiece, &pOldPiece);
// destruct old piece (if it exists) since we don't need it anymore
if (pOldPiece != NULL)
{
tetris_piece_destruct(pOldPiece);
pOldPiece = NULL;
}
#ifdef GAME_BASTET
}
#endif
break;
// a piece is hovering and can be controlled by the player
@ -296,7 +373,6 @@ void tetris ()
// and whether the level gets changed
tetris_logic_removedLines(pLogic, tetris_playfield_getRowMask(pPl));
tetris_input_setLevel(pIn, tetris_logic_getLevel(pLogic));
break;
// avoid compiler warnings
@ -320,6 +396,12 @@ void tetris ()
}
// clean up
#ifdef GAME_BASTET
if (nBastet)
{
tetris_bastet_destruct(pBastet);
}
#endif
tetris_view_destruct(pView);
tetris_input_destruct(pIn);
tetris_playfield_destruct(pPl);
@ -374,18 +456,18 @@ void tetris_logic_removedLines(tetris_logic_t *pLogic,
switch (nLines)
{
case 1:
pLogic->nScore += 50;
break;
case 2:
pLogic->nScore += 150;
break;
case 3:
pLogic->nScore += 250;
break;
case 4:
pLogic->nScore += 400;
break;
case 1:
pLogic->nScore += 50;
break;
case 2:
pLogic->nScore += 150;
break;
case 3:
pLogic->nScore += 250;
break;
case 4:
pLogic->nScore += 400;
break;
}
}

14
games/tetris/logic.h

@ -46,6 +46,20 @@ void tetris_logic_destruct(tetris_logic_t *pLogic);
void tetris();
/* Function: tetris_bastet
* Description: runs the bastet game
* Return value: void
*/
void tetris_bastet();
/* Function: tetris_main
* Description: runs the tetris game
* Argument nBastet: 0 for normal Tetris, 1 for Bastet
* Return value: void
*/
void tetris_main(int8_t nBastet);
/* Function: tetris_logic_singleDrop
* Description: add points which result from single step dropping
* Argument pLogic: the logic object we want to modify

29
games/tetris/playfield.c

@ -2,9 +2,9 @@
#include <string.h>
#include <assert.h>
#include <inttypes.h>
#include "../../autoconf.h"
#include "playfield.h"
#include "piece.h"
#include "bast.h"
/***************************
@ -58,6 +58,7 @@ tetris_playfield_t *tetris_playfield_construct(int8_t nWidth,
if (pPlayfield->dump != NULL)
{
// setting desired attributes
pPlayfield->nFirstMatterRow = nHeight - 1;
pPlayfield->nWidth = nWidth;
pPlayfield->nHeight = nHeight;
tetris_playfield_reset(pPlayfield);
@ -336,6 +337,20 @@ void tetris_playfield_advancePiece(tetris_playfield_t *pPl)
pPl->dump[i] |= nPieceMap;
}
// update value for the highest row with matter
int8_t nPieceRow = pPl->nRow;
uint16_t nMask = 0x000F;
for (int i = 0; i < 4; ++i, nMask <<= 4)
{
if ((nMask & nPiece) != 0)
{
nPieceRow += i;
break;
}
}
pPl->nFirstMatterRow = (pPl->nFirstMatterRow > nPieceRow) ?
nPieceRow : pPl->nFirstMatterRow;
// the piece has finally been docked
pPl->status = TETRIS_PFS_DOCKED;
}
@ -456,6 +471,9 @@ void tetris_playfield_removeCompleteLines(tetris_playfield_t *pPl)
// is current row a full row?
if ((nFullRow & pPl->dump[i]) == nFullRow)
{
// adjust value for the highest row with matter
pPl->nFirstMatterRow++;
// set corresponding bit for the row mask
// nRowMask |= 0x08 >> (nStartRow - i);
nRowMask |= 0x01 << (i - pPl->nRow);
@ -602,6 +620,9 @@ uint16_t tetris_playfield_getDumpRow(tetris_playfield_t *pPl,
return pPl->dump[nRow];
}
#ifdef GAME_BASTET
/* Function: tetris_playfield_predictDeepestRow
* Description: returns the deepest possible row of a given piece
* Argument pPl: the playfield on which we want to test a piece
@ -621,10 +642,14 @@ int8_t tetris_playfield_predictDeepestRow(tetris_playfield_t *pPl,
if (tetris_playfield_collision(pPl, (pPl->nWidth - 2) / 2, nRow) ||
(tetris_playfield_collision(pPl, nColumn, nRow)))
{
// restore real piece
pPl->pPiece = pActualPiece;
return -4;
}
// determine deepest row
nRow = (nRow < pPl->nFirstMatterRow - 4) ? pPl->nFirstMatterRow - 4 : nRow;
while ((nRow < pPl->nHeight) &&
(!tetris_playfield_collision(pPl, nColumn, nRow + 1)))
{
@ -777,3 +802,5 @@ uint16_t* tetris_playfield_predictNextRow(tetris_playfield_iterator_t *pIt)
return NULL;
}
}
#endif /* GAME_BASTET */

6
games/tetris/playfield.h

@ -2,6 +2,7 @@
#define TETRIS_PLAYFIELD_H_
#include <inttypes.h>
#include "../../autoconf.h"
#include "piece.h"
@ -40,6 +41,7 @@ typedef struct tetris_playfield_t
int8_t nRow; // vert. piece pos. (0 is top)
uint8_t nRowMask; // removed lines relative to nRow (bitmap)
tetris_playfield_status_t status; // status
int8_t nFirstMatterRow; // first row (from top) which contains matter
uint16_t *dump; // playfield itself
}
tetris_playfield_t;
@ -223,6 +225,8 @@ uint16_t tetris_playfield_getDumpRow(tetris_playfield_t *pPl,
int8_t nRow);
#ifdef GAME_BASTET
/* Function: tetris_playfield_predictDeepestRow
* Description: returns the deepest possible row of a given piece
* Argument pPl: the playfield on which we want to test a piece
@ -287,6 +291,6 @@ uint16_t* tetris_playfield_predictBottomRow(tetris_playfield_iterator_t *pIt,
*/
uint16_t* tetris_playfield_predictNextRow(tetris_playfield_iterator_t *pIt);
#endif /* GAME_BASTET */
#endif /*TETRIS_PLAYFIELD_H_*/

111
games/tetris/view.c

@ -30,10 +30,12 @@
#define TETRIS_VIEW_LINE_BLINK_DELAY 75
// colors of game elements
#define TETRIS_VIEW_COLORSPACE 0
#define TETRIS_VIEW_COLORBORDER 1
#define TETRIS_VIEW_COLORFADE 2
#define TETRIS_VIEW_COLORPIECE 3
#define TETRIS_VIEW_COLORSPACE 0
#define TETRIS_VIEW_COLORBORDER 1
#define TETRIS_VIEW_COLORFADE 2
#define TETRIS_VIEW_COLORPIECE 3
#define TETRIS_VIEW_COLORPAUSE 1
#define TETRIS_VIEW_COLORCOUNTER 2
/***************************
@ -53,7 +55,7 @@ uint8_t tetris_view_getPieceColor (tetris_view_t *pV)
}
else
{
return TETRIS_VIEW_COLORBORDER;
return TETRIS_VIEW_COLORPAUSE;
}
}
@ -207,17 +209,18 @@ void tetris_view_drawBorders(uint8_t nColor)
setpixel((pixel){4, y}, nColor);
setpixel((pixel){15, y}, nColor);
}
for (y = 0; y < 5; ++y)
{
for (x = 0; x <= 3; ++x){
if ((y<1 || y>3) || (x<1 || y>3)){
setpixel((pixel){x, y}, nColor);
setpixel((pixel){x, y + 11}, nColor);
}
for (x = 0; x <= 3; ++x)
{
if ((y < 1 || y > 3) || (x < 1 || y > 3))
{
setpixel((pixel){x, y}, nColor);
setpixel((pixel){x, y + 11}, nColor);
}
}
}
}
@ -287,69 +290,39 @@ void tetris_view_blinkLines(tetris_playfield_t *pPl)
/* Function: tetris_view_showLineNumbers
* Description: displays completed Lines (0-99)
* Argmument pV: pointer to the view
* Argument nColor: color
* Return value: void
*/
void tetris_view_showLineNumbers (tetris_view_t *pV, uint8_t nColor)
void tetris_view_showLineNumbers(tetris_view_t *pV)
{
//Get number of completed lines
uint8_t Lines = tetris_logic_getLines(pV->pLogic);
uint8_t nPen;
int x=0, y=0, i;
int ones, tens;
ones= Lines%10;
tens=(Lines/10)%10;
//pick drawing color, dark if ones=0, faded otherwise (bright counter gets confused with piece preview)
if ((ones%10)!=0)
nPen=TETRIS_VIEW_COLORFADE;
else nPen=TETRIS_VIEW_COLORSPACE;
//Draws ones in the upper part of the border as a 3x3 square with 0-9 pixels
//Start at column 1
y=1;
for (i=1;i<=9;i++)
{
//Start at line 1, increase every loop cycle
x++;
//the square is just three pixels wide, start over in next column once the row is full
if (x%4==0)
{
y++;
x=1;
}
setpixel((pixel){x,y}, nPen);
//only draw as many ones as there are, make the rest of the square dark.
if (i==ones) nPen=TETRIS_VIEW_COLORSPACE;
}
//back to normal color, but only if tens is not divisible by 10
if ((tens%10)!=0)
nPen=TETRIS_VIEW_COLORFADE;
else nPen=TETRIS_VIEW_COLORSPACE;
//Draws ones in the lower part of the border as a 3x3 square with 0-9 pixels
x=0;
y=12; //offset for lower part of the border
for (i=1;i<=9;i++)
{
x++; //Start at line 1, increase every loop cycle
//the square is just three pixels wide, start over in next column once the row is full
if (x%4==0)
// get number of completed lines
uint8_t nLines = tetris_logic_getLines(pV->pLogic);
// get decimal places
int8_t nOnes = nLines % 10;
int8_t nTens = (nLines / 10) % 10;
// draws the decimal places as 3x3 squares with 9 pixels
for (int i = 0, x = 1, y = 1; i < 9; ++i)
{
y++;
x=1;
// pick drawing color
uint8_t nOnesPen = nOnes > i ?
TETRIS_VIEW_COLORCOUNTER : TETRIS_VIEW_COLORSPACE;
uint8_t nTensPen = nTens > i ?
TETRIS_VIEW_COLORCOUNTER : TETRIS_VIEW_COLORSPACE;
// wrap lines if required
if ((x % 4) == 0)
{
y++;
x = 1;
}
// ones
setpixel((pixel){x, y}, nOnesPen);
// tens (increment x, add vertical offset for lower part of the border)
setpixel((pixel){x++, y + 11}, nTensPen);
}
setpixel((pixel){x,y}, nPen);
//only draw as many ones as there are, make the rest of the square dark.
if (i==tens) nPen=TETRIS_VIEW_COLORSPACE;
}
}
/****************************
* construction/destruction *
****************************/
@ -441,7 +414,7 @@ void tetris_view_update(tetris_view_t *pV)
if (tetris_playfield_getRowMask(pV->pPl) != 0)
{
tetris_view_blinkLines(pV->pPl);
tetris_view_showLineNumbers(pV, TETRIS_VIEW_COLORPIECE);
tetris_view_showLineNumbers(pV);
}
// draw preview piece

Loading…
Cancel
Save