📄 russia.c
字号:
/*========================================================================
*
* 版权所有 2003-2004 吴柏建. All Rights Reserved.
*
* 文件: russia.c
* 内容: 演示应用SSS库功能制作窗口游戏——俄罗斯方块。
* 作者: 吴柏建。
* 制作日期: 2003.3.8-2003.3.11
* 修改日期: 2003..
*
*========================================================================*/
#include <windows.h>
#include "resource.h"
#include "sss.h"
#pragma comment(lib,"sss.lib")
static HINSTANCE g_hInstance;
/*======================================================================
---消息宏---
======================================================================*/
#define RKEY_LEFT 0
#define RKEY_RIGHT 1
#define RKEY_DOWN 2
#define RKEY_CIRCLE 3
#define RKEY_START 4
#define RKEY_PAUSE 5
#define RMSG_TIME 6
#define RMSG_PAINT 7
#define RKEY_SPEEDUP 8
#define RKEY_SPEEDDOWN 9
/*======================================================================
---消息队列函数---
======================================================================*/
#define MSG_QUEUE_SIZE 16 /*定义队列中容纳的消息数量*/
int MsgQueue[MSG_QUEUE_SIZE];/*定义全局的消息队列*/
int MsgWrite = 0; /*消息队列的写入位置*/
int MsgRead = 0; /*消息队列的读出位置*/
void SendMsg( int msg )
{
int i = (1+MsgWrite)%MSG_QUEUE_SIZE;
MsgQueue[MsgWrite] = msg;
MsgWrite = i;
if( i == MsgRead )MsgRead = (++MsgRead)%MSG_QUEUE_SIZE;
}
BOOL GetMsg( int *msg )
{
if( MsgRead != MsgWrite )
{
*msg = MsgQueue[MsgRead];
MsgRead = ((++MsgRead)%MSG_QUEUE_SIZE);
return 1;
}
return 0;
}
void ClearMsg( void )
{
MsgRead = MsgWrite;
}
/*======================================================================
---常量数据---
======================================================================*/
// ■■ ■■ ■■ ■■
// ■■ ■■ ■■ ■■
const char gBlock0[4][2][2]=
{
{ {1,1,},{1,1,}, },
{ {1,1,},{1,1,}, },
{ {1,1,},{1,1,}, },
{ {1,1,},{1,1,}, },
};
// ○○○○ ○■○○ ○○○○ ○■○○
// ■■■■ ○■○○ ■■■■ ○■○○
// ○○○○ ○■○○ ○○○○ ○■○○
// ○○○○ ○■○○ ○○○○ ○■○○
const char gBlock1[4][4][4]=
{
{ {0,0,0,0,},{1,1,1,1,},{0,0,0,0,},{0,0,0,0,}, },
{ {0,1,0,0,},{0,1,0,0,},{0,1,0,0,},{0,1,0,0,}, },
{ {0,0,0,0,},{1,1,1,1,},{0,0,0,0,},{0,0,0,0,}, },
{ {0,1,0,0,},{0,1,0,0,},{0,1,0,0,},{0,1,0,0,}, },
};
// ○■○ ○■○ ○○○ ○■○
// ■■■ ○■■ ■■■ ■■○
// ○○○ ○■○ ○■○ ○■○
const char gBlock2[4][3][3]=
{
{ {0,1,0,},{1,1,1,},{0,0,0,}, },
{ {0,1,0,},{0,1,1,},{0,1,0,}, },
{ {0,0,0,},{1,1,1,},{0,1,0,}, },
{ {0,1,0,},{1,1,0,},{0,1,0,}, },
};
// ○■○ ○○○ ○■○ ○○○
// ■■○ ■■○ ■■○ ■■○
// ■○○ ○■■ ■○○ ○■■
const char gBlock3[4][3][3]=
{
{ {0,1,0,},{1,1,0,},{1,0,0,}, },
{ {0,0,0,},{1,1,0,},{0,1,1,}, },
{ {0,1,0,},{1,1,0,},{1,0,0,}, },
{ {0,0,0,},{1,1,0,},{0,1,1,}, },
};
// ■○○ ○○○ ■○○ ○○○
// ■■○ ○■■ ■■○ ○■■
// ○■○ ■■○ ○■○ ■■○
const char gBlock4[4][3][3]=
{
{ {1,0,0,},{1,1,0,},{0,1,0,}, },
{ {0,0,0,},{0,1,1,},{1,1,0,}, },
{ {1,0,0,},{1,1,0,},{0,1,0,}, },
{ {0,0,0,},{0,1,1,},{1,1,0,}, },
};
// ■○○ ○■■ ○○○ ○■○
// ■■■ ○■○ ■■■ ○■○
// ○○○ ○■○ ○○■ ■■○
const char gBlock5[4][3][3]=
{
{ {1,0,0,},{1,1,1,},{0,0,0,}, },
{ {0,1,1,},{0,1,0,},{0,1,0,}, },
{ {0,0,0,},{1,1,1,},{0,0,1,}, },
{ {0,1,0,},{0,1,0,},{1,1,0,}, },
};
// ○○○ ■■○ ○○■ ○■○
// ■■■ ○■○ ■■■ ○■○
// ■○○ ○■○ ○○○ ○■■
const char gBlock6[4][3][3]=
{
{ {0,0,0,},{1,1,1,},{1,0,0,}, },
{ {1,1,0,},{0,1,0,},{0,1,0,}, },
{ {0,0,1,},{1,1,1,},{0,0,0,}, },
{ {0,1,0,},{0,1,0,},{0,1,1,}, },
};
const int gBlockSize[7] = { 2,4,3,3,3,3,3, };
const void *gBlockAddr[7] = { gBlock0,gBlock1,gBlock2,gBlock3,gBlock4,gBlock5,gBlock6,};
typedef struct _RUSSIADATA
{
int Flag; //状态标志:0:初始化状态 1:运行状态 2:暂停状态 3:结束状态。
int XinWnd,YinWnd;//显示起点。
int Speed; //飞行速度。
int Score; //得分。
int FlyBlock; //飞行块的标志 0:NULL 1 ~ 7 : gBlock1 ~ gBlock7
int FlyX,FlyY; //飞行块的在map[24][10]中的位置。
int FlyF; //飞行块的方向。0~3
int NextFlyBlock; //下一个飞行块的标志。
int NextFlyX,NextFlyY;//下一个飞行块的在map[24][10]中的位置。
int NextFlyF; //下一个飞行块的方向。0~3
int w,h; //块的宽与高。
LPBMP pBmpBlock; //一个块的显示图象。
LPBMP pBmpNoBlock;//一个块的背景显示图象。
LPBMP pBmpNumber; //数字图象。
LPBMP pBmpBuffer; //显示缓冲,用于防止闪烁。宽度=10*w,高度=20*h。
LPBMP pBmpBoard; //预告区背景图象。
/*
//不可见部分。
00 ○○○○○○○○○○
01 ○○○○○○○○○○
02 ○○○○○○○○○○
03 ○○○○○○○○○○
//可见部分。
04 ○○○○○○○○○○
05 ○○○○○○○○○○
06 ○○○○○○○○○○
07 ○○○○○○○○○○
08 ○○○○○○○○○○
09 ○○○○○○○○○○
10 ○○○○○○○○○○
11 ○○○○○○○○○○
12 ○○○○○○○○○○
13 ○○○○○○○○○○
14 ○○○○○○○○○○
15 ○○○○○○○○○○
16 ○○○○○○○○○○
17 ○○○○○○○○○○
18 ○○○○○○○○○○
19 ○○○○○○○○○○
20 ○○○○○○○○○○
21 ○○○○○○○○○○
22 ○○○○○○○○○○
23 ○○○○○○○○○○
*/
char map[24][10]; //块的显示表。
char map2[24][10];
}RUSSIADATA;
/*======================================================================
---功能函数---
======================================================================*/
void IntTime( int ID )
{
SendMsg( RMSG_TIME );
SSS_Cpu_Interrupt( 0 );
}
BOOL InitRussia( RUSSIADATA * p )
{
RECT sRC, dRC;
LPBMP pBmp;
memset( p, 0, sizeof(RUSSIADATA) );
memset( p->map, 1, 24*10 );
memset( p->map2, -1, 24*10 );
p->XinWnd = 10;
p->YinWnd = 10;
p->Speed = 50;
p->Score = 0;
p->w = 10;
p->h = 10;
pBmp = SSS_Bmp_Load( MAKEINTRESOURCE(IDB_BLOCK) );
p->pBmpBlock = SSS_Bmp_Create( p->w, p->h );
p->pBmpNoBlock = SSS_Bmp_Create( p->w, p->h );
p->pBmpNumber = SSS_Bmp_Load( MAKEINTRESOURCE(IDB_NUMBER) );
p->pBmpBuffer = SSS_Bmp_Create( p->w*10, p->h*20 );
p->pBmpBoard = SSS_Bmp_Create( 47, 47 );
if( !( pBmp && p->pBmpBlock && p->pBmpNoBlock && p->pBmpBuffer ) )return 0;
SetRect( &dRC, 0, 0, p->w, p->h );
SetRect( &sRC, p->w, 0, p->w*2, p->h );
SSS_Bmp_ShowInBmp( &dRC, p->pBmpBlock, &dRC, pBmp, 0 );
SSS_Bmp_ShowInBmp( &dRC, p->pBmpNoBlock, &sRC, pBmp, 0 );
SetRect( &dRC, 0, 0, 47, 47 );
SSS_Bmp_ShowInBmp( &dRC, p->pBmpBoard, &sRC, pBmp, 0 );
SSS_Bmp_Release( pBmp );
return 1;
}
void DrawRussia( RUSSIADATA * p )
{
RECT sRC, dRC;
int i,j,x,y,k;
LPBMP pBmp;
char *s;
//显示游戏区。
SetRect( &sRC, 0, 0, p->w, p->h );
for( j=4; j<24; j++ )for( i=0; i<10; i++ )
{
if( p->map2[j][i] != p->map[j][i] )
{
p->map2[j][i] = p->map[j][i];
pBmp = p->map[j][i] ? p->pBmpBlock : p->pBmpNoBlock;
SetRect( &dRC, p->w*i, p->h*(j-4), p->w*(i+1), p->h*(j-3) );
SSS_Bmp_ShowInBmp( &dRC, p->pBmpBuffer, &sRC, pBmp, 0 );
}
}
SetRect( &sRC, 0, 0, p->w*10, p->h*20 );
dRC = sRC;
OffsetRect( &dRC, p->XinWnd, p->YinWnd );
SSS_Bmp_ShowInWnd( &dRC, &sRC, p->pBmpBuffer, 0 );
//预告区显示。
if( p->Flag != 1 && p->Flag != 2 )//显示速度。
{
j = (p->Speed/5)/10;
i = (p->Speed/5)%10;
SetRect( &sRC, j*13, 0, (j+1)*13, 23 );
SetRect( &dRC, 177, 61, 190, 84 );
SSS_Bmp_ShowInWnd( &dRC, &sRC, p->pBmpNumber, 0 );
SetRect( &sRC, i*13, 0, (i+1)*13, 23 );
SetRect( &dRC, 190, 61, 203, 84 );
SSS_Bmp_ShowInWnd( &dRC, &sRC, p->pBmpNumber, 0 );
}
else//显示下一个块。
{
//清除预告区域,注意直接缩放图形显示到窗口时DIRECTX导致窗口在屏幕边缘的剪切会有问题。
SetRect( &sRC, 0, 0, 47, 47 );
dRC = sRC;
OffsetRect( &dRC, 166, 49 );
SSS_Bmp_ShowInWnd( &dRC, &sRC, p->pBmpBoard, 0 );
//画预告区域。
SetRect( &sRC, 0, 0, p->w, p->h );
k = gBlockSize[p->NextFlyBlock];
s = (char *)gBlockAddr[p->NextFlyBlock];
s += p->NextFlyF*k*k;
x = 169+(4-k)*p->w/2;
y = 52+(4-k)*p->h/2;
for( j=0; j<k; j++ )for( i=0; i<k; i++ )
{
if( s[j*k+i] )
{
SetRect( &dRC, x+i*p->w, y+j*p->h, x+(i+1)*p->w, y+(j+1)*p->h );
SSS_Bmp_ShowInWnd( &dRC, &sRC, p->pBmpBlock, 0 );
}
}
}
}
void StepRussia( RUSSIADATA * p )
{
// 0 1 2 3 4 5 6
// ■■ ○○○○ ○■○ ○■○ ■○○ ■○○ ○○○
// ■■ ■■■■ ■■■ ■■○ ■■○ ■■■ ■■■
// ○○○○ ○○○ ■○○ ○■○ ○○○ ■○○
// 0 1 2 3 4 5 6
// 9 13 12 8 8 10 10
static int X[7] = { 9,22,34,42,50,60,70, };
int i = (rand()%70), j;
p->FlyBlock = p->NextFlyBlock;
p->FlyX = p->NextFlyX;
p->FlyY = p->NextFlyY;
p->FlyF = p->NextFlyF;
//p->NextFlyBlock = (rand()%7);
for( j=0;;j++ )if( i<X[j] )break;
p->NextFlyBlock = j;
p->NextFlyX = (10-gBlockSize[p->NextFlyBlock])/2;
p->NextFlyY = 0;
p->NextFlyF = (rand()%4);
}
void StartRussia( RUSSIADATA * p )
{
if( p->Flag == 1 )return;
if( p->Flag != 2 )
{
StepRussia( p );
StepRussia( p );
memset( p->map, 0, 24*10 );
DrawRussia( p );
}
p->Flag = 1;
SSS_Timer_Init( RMSG_TIME, (100-p->Speed)*2/3, IntTime );
}
void PauseRussia( RUSSIADATA * p )
{
if( p->Flag == 1 )
{
p->Flag = 2;
SSS_Timer_Out( RMSG_TIME );
}
}
BOOL BlockIn( RUSSIADATA * p )
{
int i,j,w,h,x,y;
char *s;
s = (char *)gBlockAddr[ p->FlyBlock ];
w = h = gBlockSize[ p->FlyBlock ];
for( j=0; j<h; j++ )for( i=0; i<w; i++ )
{
if( s[ p->FlyF*w*h+j*w+i ] !=0 )
{
x = p->FlyX+i;
y = p->FlyY+j;
if( y < 0 || y >= 24 || x < 0 || x >= 10 )return 0;
if( p->map[ y ][ x ] == 1 )return 0;
}
}
for( j=0; j<h; j++ )for( i=0; i<w; i++ )
{
if( s[ p->FlyF*w*h+j*w+i ] !=0 )
{
p->map[ p->FlyY+j ][ p->FlyX+i ] = 1;
}
}
return 1;
}
void BlockOut( RUSSIADATA * p )
{
int i,j,w,h;
char *s;
s = (char *)gBlockAddr[ p->FlyBlock ];
w = h = gBlockSize[ p->FlyBlock ];
for( j=0; j<h; j++ )for( i=0; i<w; i++ )
{
if( s[ p->FlyF*w*h+j*w+i ] !=0 )
{
p->map[ p->FlyY+j ][ p->FlyX+i ] = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -