2015-01-21 03:42:47 +00:00
/*
* Copyright ( c ) 2015 Joel Bodenmann aka Tectu < joel @ unormal . org >
* Copyright ( c ) 2015 Andrew Hannam aka inmarket
*
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* * Neither the name of the < organization > nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS " AND
* ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL < COPYRIGHT HOLDER > BE LIABLE FOR ANY
* DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
* ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
* LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
/*
* This program was originally contributed by community member " Fleck " as
* the winning entry in the December 2014 demo competition .
*
* Some minor changes have been made by the uGFX maintainers .
*/
# include "gfx.h"
# include "stdlib.h"
# include "string.h"
# include "math.h"
# include "tetris.h"
# define SEVEN_SEG_HEIGHT SEVEN_SEG_SIZE*3
# define SEVEN_SEG_WIDTH SEVEN_SEG_HEIGHT*3
# define SEVEN_SEG_CHAR_WIDTH ((SEVEN_SEG_SIZE*4)+(SEVEN_SEG_HEIGHT*2)+SEVEN_SEG_WIDTH)
# define SEVEN_SEG_CHAR_HEIGHT ((SEVEN_SEG_SIZE*4)+(SEVEN_SEG_HEIGHT*3)+(SEVEN_SEG_WIDTH*2))
# define TETRIS_SEVEN_SEG_SCORE_X (TETRIS_FIELD_WIDTH*TETRIS_CELL_WIDTH)-(strlen(pps_str)*SEVEN_SEG_CHAR_WIDTH)+(SEVEN_SEG_CHAR_WIDTH*i)
// bit0 = A
// bit1 = B
// bit2 = C
// bit3 = D
// bit4 = E
// bit5 = F
// bit6 = G
// 7segment number array, starting from 0 (array index matches number)
// 7segment number:
/*
A
F B
G
E C
D
*/
const uint8_t sevenSegNumbers [ 10 ] = { 0x3F , 0x06 , 0x5B , 0x4F , 0x66 , 0x6D , 0x7D , 0x07 , 0x7F , 0x6F } ; // 0,1,2,3,4,5,6,7,8,9
2018-07-08 01:19:43 +00:00
const gColor tetrisShapeColors [ 9 ] = { GFX_BLACK , HTML2COLOR ( 0x009000 ) , GFX_RED , GFX_BLUE , GFX_MAGENTA , GFX_SKYBLUE , GFX_ORANGE , HTML2COLOR ( 0xBBBB00 ) , GFX_WHITE } ; // shape colors
2015-01-21 03:42:47 +00:00
// default tetris shapes
const int tetrisShapes [ TETRIS_SHAPE_COUNT ] [ 4 ] [ 2 ] = {
{ { 4 , 17 } , { 4 , 16 } , { 5 , 16 } , { 4 , 15 } } ,
{ { 4 , 16 } , { 5 , 16 } , { 4 , 15 } , { 5 , 15 } } ,
{ { 4 , 17 } , { 5 , 16 } , { 4 , 16 } , { 5 , 15 } } ,
{ { 5 , 17 } , { 5 , 16 } , { 4 , 16 } , { 4 , 15 } } ,
{ { 5 , 17 } , { 5 , 16 } , { 5 , 15 } , { 4 , 15 } } ,
{ { 4 , 17 } , { 4 , 16 } , { 4 , 15 } , { 5 , 15 } } ,
{ { 4 , 18 } , { 4 , 17 } , { 4 , 16 } , { 4 , 15 } }
} ;
int tetrisField [ TETRIS_FIELD_HEIGHT ] [ TETRIS_FIELD_WIDTH ] ; // main tetris field array
unsigned int tetrisGameSpeed = 500 ; // game auto-move speed in ms
unsigned int tetrisKeySpeed = 140 ; // game key repeat speed in ms
systemticks_t tetrisPreviousGameTime = 0 ;
systemticks_t tetrisPreviousKeyTime = 0 ;
int tetrisCurrentShape [ 4 ] [ 2 ] ;
int tetrisNextShape [ 4 ] [ 2 ] ;
int tetrisOldShape [ 4 ] [ 2 ] ;
int tetrisNextShapeNum , tetrisOldShapeNum ;
unsigned long tetrisLines = 0 ;
unsigned long tetrisScore = 0 ;
2018-06-23 03:02:07 +00:00
gBool tetrisKeysPressed [ 5 ] = { gFalse , gFalse , gFalse , gFalse , gFalse } ; // left/down/right/up/pause
gBool tetrisPaused = gFalse ;
gBool tetrisGameOver = gFalse ;
2015-01-21 03:42:47 +00:00
font_t font16 ;
font_t font12 ;
GEventMouse ev ;
// static void initRng(void) { //STM32 RNG hardware init
// rccEnableAHB2(RCC_AHB2ENR_RNGEN, 0);
// RNG->CR |= RNG_CR_RNGEN;
// }
static void initRng ( void ) {
srand ( gfxSystemTicks ( ) ) ;
}
static int uitoa ( unsigned int value , char * buf , int max ) {
int n = 0 ;
int i = 0 ;
int tmp = 0 ;
if ( ! buf ) return - 3 ;
if ( 2 > max ) return - 4 ;
i = 1 ;
tmp = value ;
if ( 0 > tmp ) {
tmp * = - 1 ;
i + + ;
}
for ( ; ; ) {
tmp / = 10 ;
if ( 0 > = tmp ) break ;
i + + ;
}
if ( i > = max ) {
buf [ 0 ] = ' ? ' ;
buf [ 1 ] = 0x0 ;
return 2 ;
}
n = i ;
tmp = value ;
if ( 0 > tmp ) {
tmp * = - 1 ;
}
buf [ i - - ] = 0x0 ;
for ( ; ; ) {
buf [ i - - ] = ( tmp % 10 ) + ' 0 ' ;
tmp / = 10 ;
if ( 0 > = tmp ) break ;
}
if ( - 1 ! = i ) {
buf [ i - - ] = ' - ' ;
}
return n ;
}
2018-07-08 01:19:43 +00:00
static void sevenSegDraw ( int x , int y , uint8_t number , gColor color ) {
2015-01-21 03:42:47 +00:00
if ( number & 0x01 ) gdispFillArea ( x + SEVEN_SEG_HEIGHT + SEVEN_SEG_SIZE , y , SEVEN_SEG_WIDTH , SEVEN_SEG_HEIGHT , color ) ; // A
if ( number & 0x02 ) gdispFillArea ( x + SEVEN_SEG_HEIGHT + ( SEVEN_SEG_SIZE * 2 ) + SEVEN_SEG_WIDTH , y + SEVEN_SEG_HEIGHT + SEVEN_SEG_SIZE , SEVEN_SEG_HEIGHT , SEVEN_SEG_WIDTH , color ) ; // B
if ( number & 0x04 ) gdispFillArea ( x + SEVEN_SEG_HEIGHT + ( SEVEN_SEG_SIZE * 2 ) + SEVEN_SEG_WIDTH , y + ( SEVEN_SEG_HEIGHT * 2 ) + SEVEN_SEG_WIDTH + ( SEVEN_SEG_SIZE * 3 ) , SEVEN_SEG_HEIGHT , SEVEN_SEG_WIDTH , color ) ; // C
if ( number & 0x08 ) gdispFillArea ( x + SEVEN_SEG_HEIGHT + SEVEN_SEG_SIZE , y + ( SEVEN_SEG_HEIGHT * 2 ) + ( SEVEN_SEG_WIDTH * 2 ) + ( SEVEN_SEG_SIZE * 4 ) , SEVEN_SEG_WIDTH , SEVEN_SEG_HEIGHT , color ) ; // D
if ( number & 0x10 ) gdispFillArea ( x , y + ( SEVEN_SEG_HEIGHT * 2 ) + SEVEN_SEG_WIDTH + ( SEVEN_SEG_SIZE * 3 ) , SEVEN_SEG_HEIGHT , SEVEN_SEG_WIDTH , color ) ; // E
if ( number & 0x20 ) gdispFillArea ( x , y + SEVEN_SEG_HEIGHT + SEVEN_SEG_SIZE , SEVEN_SEG_HEIGHT , SEVEN_SEG_WIDTH , color ) ; // F
if ( number & 0x40 ) gdispFillArea ( x + SEVEN_SEG_HEIGHT + SEVEN_SEG_SIZE , y + SEVEN_SEG_HEIGHT + SEVEN_SEG_WIDTH + ( SEVEN_SEG_SIZE * 2 ) , SEVEN_SEG_WIDTH , SEVEN_SEG_HEIGHT , color ) ; // G
}
static void drawShape ( uint8_t color ) {
int i ;
for ( i = 0 ; i < = 3 ; i + + ) {
if ( tetrisCurrentShape [ i ] [ 1 ] < = 16 | | tetrisCurrentShape [ i ] [ 1 ] > = 19 ) {
gdispFillArea ( ( tetrisCurrentShape [ i ] [ 0 ] * TETRIS_CELL_WIDTH ) + 2 , gdispGetHeight ( ) - TETRIS_CELL_HEIGHT - ( tetrisCurrentShape [ i ] [ 1 ] * TETRIS_CELL_HEIGHT ) - 3 , TETRIS_CELL_WIDTH - 2 , TETRIS_CELL_HEIGHT - 2 , tetrisShapeColors [ color ] ) ;
if ( color ! = 0 ) {
gdispDrawBox ( ( tetrisCurrentShape [ i ] [ 0 ] * TETRIS_CELL_WIDTH ) + 2 , gdispGetHeight ( ) - TETRIS_CELL_HEIGHT - ( tetrisCurrentShape [ i ] [ 1 ] * TETRIS_CELL_HEIGHT ) - 3 , TETRIS_CELL_WIDTH - 1 , TETRIS_CELL_HEIGHT - 1 , tetrisShapeColors [ 8 ] ) ;
} else {
gdispDrawBox ( ( tetrisCurrentShape [ i ] [ 0 ] * TETRIS_CELL_WIDTH ) + 2 , gdispGetHeight ( ) - TETRIS_CELL_HEIGHT - ( tetrisCurrentShape [ i ] [ 1 ] * TETRIS_CELL_HEIGHT ) - 3 , TETRIS_CELL_WIDTH - 1 , TETRIS_CELL_HEIGHT - 1 , tetrisShapeColors [ 0 ] ) ;
}
}
}
}
// static uint32_t randomInt(uint32_t max) { //getting random number from STM32 hardware RNG
// static uint32_t new_value=0;
// while ((RNG->SR & RNG_SR_DRDY) == 0) { }
// new_value=RNG->DR % max;
// return new_value;
// }
static uint32_t randomInt ( uint32_t max ) {
return rand ( ) % max ;
}
static void createShape ( void ) {
int i ;
memcpy ( tetrisNextShape , tetrisShapes [ tetrisNextShapeNum ] , sizeof ( tetrisNextShape ) ) ; // assign from tetrisShapes arr;
memcpy ( tetrisCurrentShape , tetrisNextShape , sizeof ( tetrisCurrentShape ) ) ; // tetrisCurrentShape = tetrisNextShape;
memcpy ( tetrisOldShape , tetrisNextShape , sizeof ( tetrisOldShape ) ) ; // tetrisOldShape = tetrisNextShape;
for ( i = 0 ; i < = 3 ; i + + ) {
tetrisCurrentShape [ i ] [ 0 ] + = 7 ;
tetrisCurrentShape [ i ] [ 1 ] - = 4 ;
}
drawShape ( 0 ) ;
tetrisOldShapeNum = tetrisNextShapeNum ;
tetrisNextShapeNum = randomInt ( TETRIS_SHAPE_COUNT ) ;
memcpy ( tetrisNextShape , tetrisShapes [ tetrisNextShapeNum ] , sizeof ( tetrisNextShape ) ) ; // assign from tetrisShapes arr;
memcpy ( tetrisCurrentShape , tetrisNextShape , sizeof ( tetrisCurrentShape ) ) ; // tetrisCurrentShape = tetrisNextShape;
for ( i = 0 ; i < = 3 ; i + + ) {
tetrisCurrentShape [ i ] [ 0 ] + = 7 ;
tetrisCurrentShape [ i ] [ 1 ] - = 4 ;
}
drawShape ( tetrisNextShapeNum + 1 ) ;
memcpy ( tetrisCurrentShape , tetrisOldShape , sizeof ( tetrisCurrentShape ) ) ; // tetrisCurrentShape = tetrisOldShape;
}
static void tellScore ( uint8_t color ) {
char pps_str [ 12 ] ;
uint8_t i ;
uitoa ( tetrisLines , pps_str , sizeof ( pps_str ) ) ;
gdispFillArea ( ( TETRIS_FIELD_WIDTH * TETRIS_CELL_WIDTH ) + 5 , gdispGetHeight ( ) - 50 , gdispGetStringWidth ( pps_str , font16 ) + 4 , gdispGetCharWidth ( ' A ' , font16 ) + 2 , tetrisShapeColors [ 0 ] ) ;
gdispDrawString ( ( TETRIS_FIELD_WIDTH * TETRIS_CELL_WIDTH ) + 5 , gdispGetHeight ( ) - 50 , pps_str , font16 , tetrisShapeColors [ color ] ) ;
uitoa ( tetrisScore , pps_str , sizeof ( pps_str ) ) ;
gdispFillArea ( 0 , 0 , gdispGetWidth ( ) , gdispGetHeight ( ) - ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) - 6 , tetrisShapeColors [ 0 ] ) ;
for ( i = 0 ; i < strlen ( pps_str ) ; i + + ) {
2018-03-10 10:36:12 +00:00
if ( pps_str [ i ] = = ' 0 ' ) sevenSegDraw ( TETRIS_SEVEN_SEG_SCORE_X , gdispGetHeight ( ) - ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) - SEVEN_SEG_CHAR_HEIGHT - 7 , sevenSegNumbers [ 0 ] , GFX_LIME ) ;
if ( pps_str [ i ] = = ' 1 ' ) sevenSegDraw ( TETRIS_SEVEN_SEG_SCORE_X , gdispGetHeight ( ) - ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) - SEVEN_SEG_CHAR_HEIGHT - 7 , sevenSegNumbers [ 1 ] , GFX_LIME ) ;
if ( pps_str [ i ] = = ' 2 ' ) sevenSegDraw ( TETRIS_SEVEN_SEG_SCORE_X , gdispGetHeight ( ) - ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) - SEVEN_SEG_CHAR_HEIGHT - 7 , sevenSegNumbers [ 2 ] , GFX_LIME ) ;
if ( pps_str [ i ] = = ' 3 ' ) sevenSegDraw ( TETRIS_SEVEN_SEG_SCORE_X , gdispGetHeight ( ) - ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) - SEVEN_SEG_CHAR_HEIGHT - 7 , sevenSegNumbers [ 3 ] , GFX_LIME ) ;
if ( pps_str [ i ] = = ' 4 ' ) sevenSegDraw ( TETRIS_SEVEN_SEG_SCORE_X , gdispGetHeight ( ) - ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) - SEVEN_SEG_CHAR_HEIGHT - 7 , sevenSegNumbers [ 4 ] , GFX_LIME ) ;
if ( pps_str [ i ] = = ' 5 ' ) sevenSegDraw ( TETRIS_SEVEN_SEG_SCORE_X , gdispGetHeight ( ) - ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) - SEVEN_SEG_CHAR_HEIGHT - 7 , sevenSegNumbers [ 5 ] , GFX_LIME ) ;
if ( pps_str [ i ] = = ' 6 ' ) sevenSegDraw ( TETRIS_SEVEN_SEG_SCORE_X , gdispGetHeight ( ) - ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) - SEVEN_SEG_CHAR_HEIGHT - 7 , sevenSegNumbers [ 6 ] , GFX_LIME ) ;
if ( pps_str [ i ] = = ' 7 ' ) sevenSegDraw ( TETRIS_SEVEN_SEG_SCORE_X , gdispGetHeight ( ) - ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) - SEVEN_SEG_CHAR_HEIGHT - 7 , sevenSegNumbers [ 7 ] , GFX_LIME ) ;
if ( pps_str [ i ] = = ' 8 ' ) sevenSegDraw ( TETRIS_SEVEN_SEG_SCORE_X , gdispGetHeight ( ) - ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) - SEVEN_SEG_CHAR_HEIGHT - 7 , sevenSegNumbers [ 8 ] , GFX_LIME ) ;
if ( pps_str [ i ] = = ' 9 ' ) sevenSegDraw ( TETRIS_SEVEN_SEG_SCORE_X , gdispGetHeight ( ) - ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) - SEVEN_SEG_CHAR_HEIGHT - 7 , sevenSegNumbers [ 9 ] , GFX_LIME ) ;
2015-01-21 03:42:47 +00:00
}
}
static void initField ( void ) {
int i , j ;
tellScore ( 0 ) ; // clear score
for ( i = 0 ; i < TETRIS_FIELD_HEIGHT ; i + + ) {
for ( j = 0 ; j < TETRIS_FIELD_WIDTH ; j + + ) {
tetrisField [ i ] [ j ] = 0 ;
}
}
createShape ( ) ;
drawShape ( tetrisOldShapeNum + 1 ) ;
tetrisLines = 0 ;
tetrisScore = 0 ;
tellScore ( 8 ) ;
}
static void drawCell ( int x , int y , uint8_t color ) {
gdispFillArea ( ( x * TETRIS_CELL_WIDTH ) + 2 , gdispGetHeight ( ) - TETRIS_CELL_HEIGHT - ( y * TETRIS_CELL_HEIGHT ) - 3 , TETRIS_CELL_WIDTH - 2 , TETRIS_CELL_HEIGHT - 2 , tetrisShapeColors [ color ] ) ;
if ( color ! = 0 ) {
gdispDrawBox ( ( x * TETRIS_CELL_WIDTH ) + 2 , gdispGetHeight ( ) - TETRIS_CELL_HEIGHT - ( y * TETRIS_CELL_HEIGHT ) - 3 , TETRIS_CELL_WIDTH - 1 , TETRIS_CELL_HEIGHT - 1 , tetrisShapeColors [ 8 ] ) ;
} else {
gdispDrawBox ( ( x * TETRIS_CELL_WIDTH ) + 2 , gdispGetHeight ( ) - TETRIS_CELL_HEIGHT - ( y * TETRIS_CELL_HEIGHT ) - 3 , TETRIS_CELL_WIDTH - 1 , TETRIS_CELL_HEIGHT - 1 , tetrisShapeColors [ 0 ] ) ;
}
}
static void printText ( uint8_t color ) {
gdispDrawString ( ( TETRIS_FIELD_WIDTH * TETRIS_CELL_WIDTH ) + TETRIS_CELL_WIDTH , gdispGetHeight ( ) - ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) , " Next " , font16 , tetrisShapeColors [ color ] ) ;
gdispDrawString ( ( TETRIS_FIELD_WIDTH * TETRIS_CELL_WIDTH ) + 5 , gdispGetHeight ( ) - 70 , " Lines " , font16 , tetrisShapeColors [ color ] ) ;
}
static void printPaused ( void ) {
if ( tetrisPaused ) gdispDrawString ( ( TETRIS_FIELD_WIDTH * TETRIS_CELL_WIDTH ) + TETRIS_CELL_WIDTH , gdispGetHeight ( ) - ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) / 2 , " Paused! " , font12 , tetrisShapeColors [ 2 ] ) ;
else gdispFillArea ( ( TETRIS_FIELD_WIDTH * TETRIS_CELL_WIDTH ) + TETRIS_CELL_WIDTH , gdispGetHeight ( ) - ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) / 2 , gdispGetStringWidth ( " Paused! " , font12 ) + 4 , gdispGetCharWidth ( ' A ' , font12 ) + 2 , tetrisShapeColors [ 0 ] ) ;
}
static void printGameOver ( void ) {
if ( tetrisGameOver ) gdispDrawString ( ( ( TETRIS_FIELD_WIDTH * TETRIS_CELL_WIDTH ) / 2 ) - ( gdispGetStringWidth ( " Game Over! " , font12 ) / 2 ) , gdispGetHeight ( ) - ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) / 2 , " Game Over! " , font12 , tetrisShapeColors [ 2 ] ) ;
else gdispFillArea ( ( ( TETRIS_FIELD_WIDTH * TETRIS_CELL_WIDTH ) / 2 ) - ( gdispGetStringWidth ( " Game Over! " , font12 ) / 2 ) , gdispGetHeight ( ) - ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) / 2 , gdispGetStringWidth ( " Game Over! " , font12 ) + 4 , gdispGetCharWidth ( ' A ' , font12 ) + 2 , tetrisShapeColors [ 0 ] ) ;
}
static void printTouchAreas ( void ) {
2018-07-08 02:50:05 +00:00
gdispDrawStringBox ( 0 , 0 , gdispGetWidth ( ) , gdispGetFontMetric ( font16 , gFontHeight ) , " Touch Area's " , font16 , GFX_WHITE , gJustifyCenter ) ;
2018-07-08 02:19:30 +00:00
gdispDrawStringBox ( 0 , 0 , gdispGetWidth ( ) , gdispGetHeight ( ) / 4 , " Pause " , font16 , GFX_GRAY , gJustifyCenter ) ;
gdispDrawStringBox ( 0 , gdispGetHeight ( ) / 4 , gdispGetWidth ( ) , gdispGetHeight ( ) / 2 , " Rotate " , font16 , GFX_GRAY , gJustifyCenter ) ;
gdispDrawStringBox ( 0 , gdispGetHeight ( ) - ( gdispGetHeight ( ) / 4 ) , gdispGetWidth ( ) / 4 , gdispGetHeight ( ) / 4 , " Left " , font16 , GFX_GRAY , gJustifyCenter ) ;
gdispDrawStringBox ( gdispGetWidth ( ) / 4 , gdispGetHeight ( ) - ( gdispGetHeight ( ) / 4 ) , gdispGetWidth ( ) / 2 , gdispGetHeight ( ) / 4 , " Down " , font16 , GFX_GRAY , gJustifyCenter ) ;
gdispDrawStringBox ( gdispGetWidth ( ) - ( gdispGetWidth ( ) / 4 ) , gdispGetHeight ( ) - ( gdispGetHeight ( ) / 4 ) , gdispGetWidth ( ) / 4 , gdispGetHeight ( ) / 4 , " Right " , font16 , GFX_GRAY , gJustifyCenter ) ;
2018-03-10 10:36:12 +00:00
gdispDrawLine ( 0 , gdispGetHeight ( ) / 4 , gdispGetWidth ( ) - 1 , gdispGetHeight ( ) / 4 , GFX_GRAY ) ;
gdispDrawLine ( 0 , gdispGetHeight ( ) - gdispGetHeight ( ) / 4 , gdispGetWidth ( ) - 1 , gdispGetHeight ( ) - gdispGetHeight ( ) / 4 , GFX_GRAY ) ;
gdispDrawLine ( gdispGetWidth ( ) / 4 , gdispGetHeight ( ) - gdispGetHeight ( ) / 4 , gdispGetWidth ( ) / 4 , gdispGetHeight ( ) - 1 , GFX_GRAY ) ;
gdispDrawLine ( gdispGetWidth ( ) - ( gdispGetWidth ( ) / 4 ) , gdispGetHeight ( ) - gdispGetHeight ( ) / 4 , gdispGetWidth ( ) - ( gdispGetWidth ( ) / 4 ) , gdispGetHeight ( ) - 1 , GFX_GRAY ) ;
2015-01-21 03:42:47 +00:00
}
2018-06-23 03:02:07 +00:00
static gBool stay ( gBool down ) {
2015-01-21 03:42:47 +00:00
int sk , k ;
2018-06-23 03:02:07 +00:00
gBool stay ;
if ( down ) sk = 1 ; else sk = 0 ;
stay = gFalse ;
2015-01-21 03:42:47 +00:00
for ( k = 0 ; k < = 3 ; k + + ) {
if ( tetrisCurrentShape [ k ] [ 1 ] = = 0 ) {
2018-06-23 03:02:07 +00:00
return gTrue ;
2015-01-21 03:42:47 +00:00
}
}
for ( k = 0 ; k < = 3 ; k + + ) {
2018-06-23 03:02:07 +00:00
if ( ( tetrisCurrentShape [ k ] [ 0 ] < 0 ) | | ( tetrisCurrentShape [ k ] [ 0 ] > 9 ) ) return gTrue ;
2015-01-21 03:42:47 +00:00
if ( tetrisCurrentShape [ k ] [ 1 ] < = 16 )
2018-06-23 03:02:07 +00:00
if ( tetrisField [ tetrisCurrentShape [ k ] [ 1 ] - sk ] [ tetrisCurrentShape [ k ] [ 0 ] ] ! = 0 ) return gTrue ;
2015-01-21 03:42:47 +00:00
}
return stay ;
}
static void clearCompleteLines ( void ) {
2018-06-23 03:02:07 +00:00
gBool t ;
2015-01-21 03:42:47 +00:00
uint8_t reiz = 0 ;
int l , k , j ;
l = 0 ;
while ( l < = 16 ) {
2018-06-23 03:02:07 +00:00
t = gTrue ;
2015-01-21 03:42:47 +00:00
for ( j = 0 ; j < = 9 ; j + + )
2018-06-23 03:02:07 +00:00
if ( tetrisField [ l ] [ j ] = = 0 ) t = gFalse ;
if ( t ) {
2015-01-21 03:42:47 +00:00
for ( j = 4 ; j > = 0 ; j - - ) { // cheap & dirty line removal animation :D
drawCell ( j , l , 0 ) ;
drawCell ( 9 - j , l , 0 ) ;
gfxSleepMilliseconds ( 40 ) ;
}
reiz + + ;
for ( k = 0 ; k < = 9 ; k + + ) {
for ( j = l ; j < 16 ; j + + ) {
tetrisField [ j ] [ k ] = tetrisField [ j + 1 ] [ k ] ;
drawCell ( k , j , tetrisField [ j ] [ k ] ) ;
}
}
for ( j = 0 ; j < = 9 ; j + + ) {
tetrisField [ 16 ] [ j ] = 0 ;
drawCell ( j , 16 , 0 ) ;
}
} else {
l + + ;
}
}
if ( reiz > 0 ) {
tetrisLines + = reiz ;
tetrisScore + = ( reiz * 10 ) * reiz ;
tellScore ( 8 ) ;
}
}
static void goDown ( void ) {
int i ;
2018-06-23 03:02:07 +00:00
if ( ! stay ( gTrue ) ) {
2015-01-21 03:42:47 +00:00
drawShape ( 0 ) ;
for ( i = 0 ; i < = 3 ; i + + ) {
tetrisCurrentShape [ i ] [ 1 ] - - ;
}
drawShape ( tetrisOldShapeNum + 1 ) ;
} else {
for ( i = 0 ; i < = 3 ; i + + ) {
if ( tetrisCurrentShape [ i ] [ 1 ] > = 17 ) {
2018-06-23 03:02:07 +00:00
tetrisGameOver = gTrue ;
2015-01-21 03:42:47 +00:00
return ;
} else {
tetrisField [ tetrisCurrentShape [ i ] [ 1 ] ] [ tetrisCurrentShape [ i ] [ 0 ] ] = tetrisOldShapeNum + 1 ;
}
}
clearCompleteLines ( ) ;
createShape ( ) ;
2018-06-23 03:02:07 +00:00
if ( stay ( gFalse ) ) {
tetrisGameOver = gTrue ;
2015-01-21 03:42:47 +00:00
return ;
}
drawShape ( tetrisOldShapeNum + 1 ) ;
}
}
static void clearField ( void ) {
int j , k ;
for ( k = 16 ; k > = 0 ; k - - ) {
for ( j = 0 ; j < = 9 ; j + + ) {
drawCell ( j , 16 - k , randomInt ( 8 ) + 1 ) ;
gfxSleepMilliseconds ( 10 ) ;
}
}
for ( k = 0 ; k < = 16 ; k + + ) {
for ( j = 0 ; j < = 9 ; j + + ) {
drawCell ( j , 16 - k , tetrisShapeColors [ 0 ] ) ;
gfxSleepMilliseconds ( 10 ) ;
}
}
}
static void rotateShape ( void ) {
int i , ox , oy , tx , ty ;
ox = tetrisCurrentShape [ 1 ] [ 0 ] ;
oy = tetrisCurrentShape [ 1 ] [ 1 ] ;
memcpy ( tetrisOldShape , tetrisCurrentShape , sizeof ( tetrisOldShape ) ) ; // tetrisOldShape = tetrisCurrentShape;
for ( i = 0 ; i < = 3 ; i + + ) {
tx = tetrisCurrentShape [ i ] [ 0 ] ;
ty = tetrisCurrentShape [ i ] [ 1 ] ;
tetrisCurrentShape [ i ] [ 0 ] = ox + ( round ( ( tx - ox ) * cos ( 90 * ( 3.14 / 180 ) ) - ( ty - oy ) * sin ( 90 * ( 3.14 / 180 ) ) ) ) ;
tetrisCurrentShape [ i ] [ 1 ] = oy + ( round ( ( tx - ox ) * sin ( 90 * ( 3.14 / 180 ) ) + ( ty - oy ) * cos ( 90 * ( 3.14 / 180 ) ) ) ) ;
}
2018-06-23 03:02:07 +00:00
if ( ! stay ( gFalse ) ) {
2015-01-21 03:42:47 +00:00
memcpy ( tetrisNextShape , tetrisCurrentShape , sizeof ( tetrisNextShape ) ) ; // tetrisNextShape = tetrisCurrentShape;
memcpy ( tetrisCurrentShape , tetrisOldShape , sizeof ( tetrisCurrentShape ) ) ; // tetrisCurrentShape = tetrisOldShape;
drawShape ( 0 ) ;
memcpy ( tetrisCurrentShape , tetrisNextShape , sizeof ( tetrisCurrentShape ) ) ; // tetrisCurrentShape = tetrisNextShape;
drawShape ( tetrisOldShapeNum + 1 ) ;
} else {
memcpy ( tetrisCurrentShape , tetrisOldShape , sizeof ( tetrisCurrentShape ) ) ; // tetrisCurrentShape = tetrisOldShape;
}
}
2018-06-23 03:02:07 +00:00
static gBool checkSides ( gBool left ) {
2015-01-21 03:42:47 +00:00
int sk , k ;
2018-06-23 03:02:07 +00:00
if ( left ) sk = 1 ; else sk = - 1 ;
2015-01-21 03:42:47 +00:00
for ( k = 0 ; k < = 3 ; k + + ) {
2018-06-23 03:02:07 +00:00
if ( ( tetrisCurrentShape [ k ] [ 0 ] + sk < 0 ) | | ( tetrisCurrentShape [ k ] [ 0 ] + sk > 9 ) ) return gTrue ;
2015-01-21 03:42:47 +00:00
if ( tetrisCurrentShape [ k ] [ 1 ] < = 16 )
2018-06-23 03:02:07 +00:00
if ( tetrisField [ tetrisCurrentShape [ k ] [ 1 ] ] [ tetrisCurrentShape [ k ] [ 0 ] + sk ] ! = 0 ) return gTrue ;
2015-01-21 03:42:47 +00:00
}
2018-06-23 03:02:07 +00:00
return gFalse ;
2015-01-21 03:42:47 +00:00
}
static void goRight ( void ) {
int i ;
2018-06-23 03:02:07 +00:00
if ( ! checkSides ( gTrue ) ) {
2015-01-21 03:42:47 +00:00
drawShape ( 0 ) ;
for ( i = 0 ; i < = 3 ; i + + ) {
tetrisCurrentShape [ i ] [ 0 ] + + ;
}
drawShape ( tetrisOldShapeNum + 1 ) ;
}
}
static void goLeft ( void ) {
int i ;
2018-06-23 03:02:07 +00:00
if ( ! checkSides ( gFalse ) ) {
2015-01-21 03:42:47 +00:00
drawShape ( 0 ) ;
for ( i = 0 ; i < = 3 ; i + + ) {
tetrisCurrentShape [ i ] [ 0 ] - - ;
}
drawShape ( tetrisOldShapeNum + 1 ) ;
}
}
static DECLARE_THREAD_FUNCTION ( thdTetris , arg ) {
( void ) arg ;
uint8_t i ;
while ( ! tetrisGameOver ) {
// key handling
if ( gfxSystemTicks ( ) - tetrisPreviousKeyTime > = gfxMillisecondsToTicks ( tetrisKeySpeed ) | | gfxSystemTicks ( ) < = gfxMillisecondsToTicks ( tetrisKeySpeed ) ) {
for ( i = 0 ; i < sizeof ( tetrisKeysPressed ) ; i + + ) {
2018-06-23 03:02:07 +00:00
if ( tetrisKeysPressed [ i ] ) {
tetrisKeysPressed [ i ] = gFalse ;
2015-01-21 03:42:47 +00:00
}
}
tetrisPreviousKeyTime = gfxSystemTicks ( ) ;
}
// auto-move part :D
ginputGetMouseStatus ( 0 , & ev ) ;
if ( gfxSystemTicks ( ) - tetrisPreviousGameTime > = gfxMillisecondsToTicks ( tetrisGameSpeed ) | | gfxSystemTicks ( ) < = gfxMillisecondsToTicks ( tetrisGameSpeed ) ) {
if ( ( ! ( ev . buttons & GINPUT_MOUSE_BTN_LEFT ) | | ( ( ev . buttons & GINPUT_MOUSE_BTN_LEFT ) & & ! ( ev . x > gdispGetWidth ( ) / 4 & & ev . x < = gdispGetWidth ( ) - ( gdispGetWidth ( ) / 4 ) & & ev . y > = gdispGetHeight ( ) - ( gdispGetHeight ( ) / 4 ) ) ) ) & & ! tetrisPaused ) goDown ( ) ; // gives smooth move_down when down button pressed! :D
tetrisPreviousGameTime = gfxSystemTicks ( ) ;
}
if ( ! ( ev . buttons & GINPUT_MOUSE_BTN_LEFT ) ) continue ;
2018-06-23 03:02:07 +00:00
if ( ev . x < = gdispGetWidth ( ) / 4 & & ev . y > = gdispGetHeight ( ) - ( gdispGetHeight ( ) / 4 ) & & ! tetrisKeysPressed [ 0 ] & & ! tetrisPaused ) {
2015-01-21 03:42:47 +00:00
goLeft ( ) ;
2018-06-23 03:02:07 +00:00
tetrisKeysPressed [ 0 ] = gTrue ;
2015-01-21 03:42:47 +00:00
tetrisPreviousKeyTime = gfxSystemTicks ( ) ;
}
2018-06-23 03:02:07 +00:00
if ( ev . x > gdispGetWidth ( ) - ( gdispGetWidth ( ) / 4 ) & & ev . y > = gdispGetHeight ( ) - ( gdispGetHeight ( ) / 4 ) & & ! tetrisKeysPressed [ 2 ] & & ! tetrisPaused ) {
2015-01-21 03:42:47 +00:00
goRight ( ) ;
2018-06-23 03:02:07 +00:00
tetrisKeysPressed [ 2 ] = gTrue ;
2015-01-21 03:42:47 +00:00
tetrisPreviousKeyTime = gfxSystemTicks ( ) ;
}
2018-06-23 03:02:07 +00:00
if ( ev . y > gdispGetHeight ( ) / 4 & & ev . y < gdispGetHeight ( ) - ( gdispGetHeight ( ) / 4 ) & & ! tetrisKeysPressed [ 3 ] & & ! tetrisPaused ) {
2015-01-21 03:42:47 +00:00
rotateShape ( ) ;
2018-06-23 03:02:07 +00:00
tetrisKeysPressed [ 3 ] = gTrue ;
2015-01-21 03:42:47 +00:00
tetrisPreviousKeyTime = gfxSystemTicks ( ) ;
}
2018-06-23 03:02:07 +00:00
if ( ev . x > gdispGetWidth ( ) / 4 & & ev . x < = gdispGetWidth ( ) - ( gdispGetWidth ( ) / 4 ) & & ev . y > = gdispGetHeight ( ) - ( gdispGetHeight ( ) / 4 ) & & ! tetrisKeysPressed [ 1 ] & & ! tetrisPaused ) {
2015-01-21 03:42:47 +00:00
goDown ( ) ;
2018-06-23 03:02:07 +00:00
tetrisKeysPressed [ 1 ] = gTrue ;
2015-01-21 03:42:47 +00:00
tetrisPreviousKeyTime = gfxSystemTicks ( ) ;
}
2018-06-23 03:02:07 +00:00
if ( ev . y < = gdispGetHeight ( ) / 4 & & ! tetrisKeysPressed [ 4 ] ) {
tetrisKeysPressed [ 4 ] = gTrue ;
2015-01-21 03:42:47 +00:00
tetrisPaused = ! tetrisPaused ;
printPaused ( ) ;
tetrisPreviousKeyTime = gfxSystemTicks ( ) ;
}
}
return ( threadreturn_t ) 0 ;
}
static void tetrisDeinit ( void ) {
gdispCloseFont ( font16 ) ;
gdispCloseFont ( font12 ) ;
}
void tetrisStart ( void ) {
// Show the help first
2018-03-10 10:36:12 +00:00
gdispClear ( GFX_BLACK ) ;
2015-01-21 03:42:47 +00:00
printTouchAreas ( ) ;
gfxSleepMilliseconds ( 3000 ) ;
// Draw the board
2018-03-10 10:36:12 +00:00
gdispClear ( GFX_BLACK ) ;
gdispDrawBox ( 0 , gdispGetHeight ( ) - ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) - 5 , ( TETRIS_FIELD_WIDTH * TETRIS_CELL_WIDTH ) + 3 , ( TETRIS_FIELD_HEIGHT * TETRIS_CELL_HEIGHT ) + 3 , GFX_WHITE ) ;
2015-01-21 03:42:47 +00:00
printText ( 8 ) ;
// Away we go
initField ( ) ;
2018-06-23 03:02:07 +00:00
tetrisGameOver = gFalse ;
printGameOver ( ) ; // removes "Game Over!" if tetrisGameOver == gFalse
2015-01-21 03:42:47 +00:00
tetrisPreviousGameTime = gfxSystemTicks ( ) ;
gfxThreadCreate ( 0 , 1024 , NORMAL_PRIORITY , thdTetris , 0 ) ;
while ( ! tetrisGameOver ) {
gfxSleepMilliseconds ( 1000 ) ;
}
clearField ( ) ;
printGameOver ( ) ;
tetrisDeinit ( ) ;
}
void tetrisInit ( void ) {
initRng ( ) ;
tetrisNextShapeNum = randomInt ( TETRIS_SHAPE_COUNT ) ;
font16 = gdispOpenFont ( " DejaVuSans16 " ) ;
font12 = gdispOpenFont ( " DejaVuSans12 " ) ;
}