📄 games_tetris.c
字号:
#ifdef __cplusplus
extern "C" {
#endif
/*==================================================================================================
MODULE NAME : module-filename.c
GENERAL DESCRIPTION
General description of this grouping of functions.
TECHFAITH Telecom Confidential Proprietary
(c) Copyright 2002 by TECHFAITH Telecom Corp. All Rights Reserved.
====================================================================================================
Revision History
Modification Tracking
Date Author Number Description of changes
---------- -------------- --------- -----------------------------------------------------------------------------------
MM/DD/YYYY name of author crxxxxx Brief description of changes made
03/01/2003 Steven Lai PC00010 Add a new game: tetris
03/14/2003 Steven Lai PP00158 Fixed the bug of memory leak
03/13/2003 Steven Lai PP00159 Removed some useless code
04/25/2003 Steven Lai P000166 If the game is paused by user, and then the focus is changed to
another app, when focus is set back, this game will begin to run, but
not keep paused. On receiving CUST_PAINT event, we need to check
the original state of this game.
03-06-3 Chenyu P00502 Fix game tetris
07/02/2003 Steven Lai C000662 Add a sound-switch for Games App
replace all the App_change_state() with Games_change_state()
fixed some bugs
07/11/2003 Steven Lai P000887 Add an introduction page at the Tetris beginning
07/25/2003 Steven Lai P001018 Show the introduction interface when come back to Game Tetris
08/08/2003 Steven Lai P001115 Add sound effects, remove some useless code
08/14/2003 Steven Lai P001239 Remove the audio effect for KEY_OK
06/12/2004 Lixingbo p006127 Modify display bugs for lotus.
06/18/2004 Lixingbo p006238 Modify a display bug for tetris.
07/20/2004 Lixingbo p007092 Modify a bug about timer can't be stopped correctly.
08/02/2004 Lixingbo p007438 Modify the timer mode from to periodic.
Self-documenting Code
Describe/explain low-level design of this module and/or group of funtions and/or specific
funtion that are hard to understand by reading code and thus requires detail description.
Free format !
====================================================================================================
INCLUDE FILES
==================================================================================================*/
#include "APP_include.h"
#include "MENU_main.h"
#include "GAMES_main.h"
#ifdef GAMES_TETRIS
#include <stdlib.h>
#include "uhapi.h"
#include "FORMAT_utility.h"
#include "GAMES_tetris.h"
#include "GAMES_highscore.h"
/*==================================================================================================
LOCAL FUNCTION PROTOTYPES
==================================================================================================*/
void APP_Tetris_entry(void);
void App_Tetris_exit(void);
void App_Tetris_handler ( OPUS_EVENT_ENUM_TYPE event,
void *pMess,
OP_BOOLEAN *handle );
static void APP_Tetris_Init(void);
static void ClearRect(OP_UINT8 col,OP_UINT8 row);
static void TetrisPutSTRnLINE(void);
static OP_BOOLEAN InitSquare(LPTSquare lpsq,OP_UINT8 col,OP_UINT8 row,DS_COLOR color,OP_BOOLEAN Data);
static void DrawPiece(TSquare sq[]);
static void ClearPiece(TSquare sq[]);
static OP_BOOLEAN InBounds(LPTSquare lpsq);
static OP_BOOLEAN FieldIsNull(OP_UINT8 row,OP_UINT8 col);
static OP_BOOLEAN IsLastLine(TSquare sq[]);
static OP_BOOLEAN ChangeSqValue(LPTSquare lps,LPTSquare lpd);
static void DrawDigit(OP_INT16 wInteger,LCD_POINT pt);
static void Repaint(void);
static OP_BOOLEAN canMoveTo(TSquare to[],OP_UINT8 num);
static OP_BOOLEAN MovePiece(TSquare from[],TSquare to[],OP_UINT8 num);
static void CopyPiece(TSquare from[],TSquare to[],OP_UINT8 num);
static void InitIndicator(void);
static OP_BOOLEAN RemoveLines(void);
static void NewPiece(TSquare sq[]);
static OP_BOOLEAN MoveCurPiece(OP_INT8 byx,OP_INT8 byy,OP_BOOLEAN rotate);
static OP_BOOLEAN MoveCurPieceBottom(void);
static void ShowIntroScreen(void);
static void ShowGameOver(OP_INT16 wScore);
static void TetrisShowInfo(void);
static void TetrisRun(void );
/*==================================================================================================
LOCAL CONSTANTS
==================================================================================================*/
#define TEXT_COLOR COLOR_BLUE_VIOLET
#define TETRIS_BG_COLOR COLOR_BLACK //COLOR_LIGHT_GRAY
#define TETRIS_TIME_DELAYER 500
#define MAX_STRING_LENGTH 100
static DS_COLOR square_colors[]=
{
_RGB(0, 255,255),
_RGB(255, 255, 0),
_RGB(255, 102, 51),
_RGB(0, 255, 0),
_RGB(255, 0, 0),
_RGB(0, 0, 255),
_RGB(255, 0, 255),
};
/*==================================================================================================
LOCAL TYPEDEFS - Structure, Union, Enumerations...etc
==================================================================================================*/
/*
* description of this structure, if needed. - Remember self documenting code
*/
/*==================================================================================================
LOCAL MACROS
==================================================================================================*/
/*
* description of this macro, if needed. - Remember self documenting code
*/
/*==================================================================================================
LOCAL VARIABLES
==================================================================================================*/
static TTetris Tetris;
static TSquare indicator[curPieceNum];
static OP_BOOLEAN theFirst = OP_TRUE;
static OP_BOOLEAN showOver = OP_TRUE;
static OP_BOOLEAN key_event_enabled = OP_FALSE; /* enable key event or not */
static RM_SOUND_ID_T sound_list[]=
{
RES_SOUND_0010, /* Tetris opening song */
RES_SOUND_0013, /* line is removed */
RES_SOUND_0014, /* piece is rotated */
RES_SOUND_0010, /* game over */
};
/*==================================================================================================
GLOBAL VARIABLES
==================================================================================================*/
extern APP_GAMES_STRUCTURE_NAME_T gamesApp_data;
extern APP_SUBSTATE_STRUCTURE_NAME_T games_substate;
/*==================================================================================================
LOCAL FUNCTIONS
==================================================================================================*/
/*==================================================================================================
FUNCTION: APP_Tetris_entry
DESCRIPTION:
ARGUMENTS PASSED:
RETURN VALUE:
IMPORTANT NOTES:
==================================================================================================*/
void APP_Tetris_entry(void)
{
ds_set_screen_mode( SCREEN_FULL_IMAGE);
srand( op_get_cur_tod()); /* set the seed for rand() */
APP_Tetris_Init();
}
/*==================================================================================================
FUNCTION: App_Tetris_exit
DESCRIPTION:
ARGUMENTS PASSED:
RETURN VALUE:
IMPORTANT NOTES:
==================================================================================================*/
void App_Tetris_exit(void)
{
SP_Audio_stop();
OPUS_Stop_Timer(OPUS_TIMER_GAME_TIMING);
}
/*==================================================================================================
FUNCTION: app_Tetris_handler
DESCRIPTION:
ARGUMENTS PASSED:
RETURN VALUE:
IMPORTANT NOTES:
==================================================================================================*/
void App_Tetris_handler
(
OPUS_EVENT_ENUM_TYPE event,
void *pMess,
OP_BOOLEAN *handle
)
{
KEYEVENT_STRUCT *pKey;
*handle = OP_TRUE;
switch (event)
{
case OPUS_FOCUS_CUST_PAINT :
if ( (pMess != OP_NULL) && (*((OP_BOOLEAN *)pMess) == OP_TRUE))
{
ds_set_screen_mode( SCREEN_FULL_IMAGE);
clear_full_screen(TETRIS_BG_COLOR);
Repaint();
if (Tetris.gameInPlay || !showOver)
{
if (!Tetris.gamePause)
{
TetrisRun();
}
else
{
/*
* To redraw the current piece. All other parts of screen
* have been redrawn in Repaint().
*/
DrawPiece(Tetris.curPiece);
}
}
else
{
ShowIntroScreen();
}
}
ds_refresh();
break;
case OPUS_TIMER_GAME_TIMING:
OPUS_Start_Timer(OPUS_TIMER_GAME_TIMING, Tetris.delayTimer, 0, ONE_SHOT);
TetrisRun();
break;
case OPUS_FOCUS_KEYPAD :
pKey = (KEYEVENT_STRUCT *)pMess;
if(pKey->state == UHKEY_RELEASE)
break;
SP_Audio_stop();
switch(pKey->code)
{
case KEY_8:
case KEY_DOWN:
if (key_event_enabled)
{
OPUS_Stop_Timer(OPUS_TIMER_GAME_TIMING);
if (!Tetris.needNewPiece)
{
Tetris.needNewPiece = MoveCurPieceBottom();
}
if(Tetris.needNewPiece)
{
TetrisShowInfo();
TetrisRun();
}
else
{
OPUS_Start_Timer(OPUS_TIMER_GAME_TIMING, Tetris.delayTimer, 0, ONE_SHOT);
}
}
break;
case KEY_5:
case KEY_UP:
case KEY_OK:
if (!Tetris.needNewPiece && key_event_enabled)
{
OPUS_Stop_Timer(OPUS_TIMER_GAME_TIMING);
MoveCurPiece(0,0,OP_TRUE); /* rotate the piece */
OPUS_Start_Timer(OPUS_TIMER_GAME_TIMING, 50, 0, ONE_SHOT);
}
break;
case KEY_LEFT:
case KEY_4:
if (!Tetris.needNewPiece && key_event_enabled)
{
OPUS_Stop_Timer(OPUS_TIMER_GAME_TIMING);
MoveCurPiece(-1,0,OP_FALSE);
OPUS_Start_Timer(OPUS_TIMER_GAME_TIMING, 50, 0, ONE_SHOT);
}
break;
case KEY_RIGHT:
case KEY_6:
if (!Tetris.needNewPiece && key_event_enabled)
{
OPUS_Stop_Timer(OPUS_TIMER_GAME_TIMING);
MoveCurPiece(1,0,OP_FALSE);
OPUS_Start_Timer(OPUS_TIMER_GAME_TIMING, 50, 0, ONE_SHOT);
}
break;
case KEY_SOFT_LEFT:
if (Tetris.gameInPlay==OP_FALSE)
{
if (gamesApp_data.popupwin == OP_NULL) /* if there is a popup, don't start game */
{
Tetris.gameInPlay=OP_TRUE;
ds_fill_rect(10, 40, 168, 120, TETRIS_BG_COLOR);
showOver = OP_FALSE;
if (gamesApp_data.audio_on == OP_TRUE)
{
SP_Audio_play_request(sound_list[0], gamesApp_data.volume, OP_FALSE);
}
TetrisRun();
}
}
else
{
if (Tetris.gamePause==OP_FALSE)
{
Tetris.gamePause=OP_TRUE;
OPUS_Stop_Timer(OPUS_TIMER_GAME_TIMING);
/*disable key event */
key_event_enabled=OP_FALSE;
}
else
{
Tetris.gamePause=OP_FALSE;
key_event_enabled=OP_TRUE; /* enable key event */
OPUS_Start_Timer(OPUS_TIMER_GAME_TIMING, Tetris.delayTimer, 0, ONE_SHOT);
}
}
break;
case KEY_SOFT_RIGHT:
case KEY_CLEAR:
if(gamesApp_data.popupwin != OP_NULL)
{
close_old_popup();
APP_Tetris_Init();
break;
}
OPUS_Stop_Timer(OPUS_TIMER_GAME_TIMING);
if (Tetris.gameInPlay==OP_TRUE)
{
ShowGameOver(Tetris.theScore);
}
else
{
Games_change_state((OP_UINT8) APP_GAMES_STATE_MENU);
}
break;
case KEY_END:
OPUS_Stop_Timer(OPUS_TIMER_GAME_TIMING);
break;
default:
break;
}
break;
case OPUS_TIMER_POPUP_MSG:
if (gamesApp_data.popupwin != OP_NULL)
{
close_old_popup();
}
APP_Tetris_Init();
break;
case OPUS_FOCUS_CUST_APP_PAUSE:
OPUS_Stop_Timer(OPUS_TIMER_GAME_TIMING);
SP_Audio_stop();
if (gamesApp_data.popupwin != OP_NULL)
{
close_old_popup();
APP_Tetris_Init();
}
break;
default :
*handle = OP_FALSE;
break;
}
}
/*==================================================================================================
FUNCTION: APP_Tetris_Init
DESCRIPTION:
ARGUMENTS PASSED:
RETURN VALUE:
IMPORTANT NOTES:
==================================================================================================*/
static void APP_Tetris_Init(void)
{
OP_INT8 i,j;
Tetris.theScore =0;
Tetris.playLevel =1;
Tetris.totalPieces=0;
Tetris.destroyLines=0;
Tetris.pieceValue=0;
Tetris.delayTimer=TETRIS_TIME_DELAYER/Tetris.playLevel;
Tetris.needNewPiece= OP_TRUE;
Tetris.gameInPlay=OP_FALSE;
Tetris.gamePause =OP_TRUE;
theFirst=OP_TRUE;
key_event_enabled=OP_FALSE;
gamesApp_data.popupwin=OP_NULL;
for(i=0;i<rowNum;i++)
for(j=0;j<colNum;j++)
Tetris.field[i][j].isOccupied=OP_FALSE;
//clear_full_screen(TETRIS_BG_COLOR);
ds_fill_rect(0,0, LCD_MAX_X-1, LCD_MAX_Y-1, TETRIS_BG_COLOR);
NewPiece(Tetris.nextPiece);
InitIndicator();
//DrawPiece(indicator);
Repaint();
ShowIntroScreen();
ds_refresh();
}
/*==================================================================================================
FUNCTION: ClearRect
DESCRIPTION:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -