📄 t-tris.c
字号:
#include <avr/io.h>
#include <avr/interrupt.h>
#define STARTPOSITION_X 6
#define STARTPOSITION_Y 26
#define PLACED 1
#define REMOVED -1
#define X 0
#define Y 1
// Names of the pushbuttons
#define MOVE_RIGHT 0
#define ROLL_CW 1
#define ROLL_CCW 2
#define MOVE_LEFT 3
#define SPEED_UP 4
// The "pressedKey"-Flags
volatile uint8_t pressedKey[5];
// Direction of the bricks
#define UP 0
#define RIGHT 1
#define DOWN 2
#define LEFT 3
volatile uint8_t amountKeyPressed;
uint8_t shaft[12][29];
uint8_t stonesPerRow[25];
uint8_t gameOver;
uint8_t movD_possible;
volatile uint8_t waiting_for_next_step;
volatile uint16_t speedCounter;
volatile uint16_t stepTime;
uint16_t stepTimeBackup;
struct brick{
uint8_t posi[2];
uint8_t shape;
uint8_t dir;
} currentBrick, nextBrick;
// In diesem Feld sind die Formen der Spielsteine abgelegt.
// shape [I|J|L|O|S|T|Z] [UP|RIGHT|DOWN|LEFT] [Stone] [X|Y]
int8_t shape[7][4][4][2] = {
{{{ 0,-1},{ 0, 1},{ 0, 2}},{{1, 0},{-1, 0},{-2, 0}},{{0, 1},{0,-1},{ 0,-2}},{{-1,0},{ 1,0},{ 2, 0}}},
{{{ 0, 1},{ 0,-1},{ 1,-1}},{{1, 1},{ 1, 0},{-1, 0}},{{0,-1},{0, 1},{-1, 1}},{{ 1,0},{-1,0},{-1,-1}}},
{{{ 0, 1},{ 0,-1},{-1,-1}},{{1,-1},{ 1, 0},{-1, 0}},{{1, 1},{0, 1},{ 0,-1}},{{ 1,0},{-1,0},{-1, 1}}},
{{{-1, 0},{-1,-1},{ 0,-1}},{{1, 0},{ 1,-1},{ 0,-1}},{{1, 1},{0, 1},{ 1, 0}},{{ 0,1},{-1,1},{-1, 0}}},
{{{-1, 0},{ 1,-1},{ 0,-1}},{{1, 1},{ 1, 0},{ 0,-1}},{{1, 0},{0, 1},{-1, 1}},{{ 0,1},{-1,0},{-1,-1}}},
{{{ 1, 0},{-1, 0},{ 0,-1}},{{0, 1},{ 1, 0},{ 0,-1}},{{0, 1},{1, 0},{-1, 0}},{{ 0,1},{-1,0},{ 0,-1}}},
{{{ 1, 0},{ 0,-1},{-1,-1}},{{0, 1},{ 1, 0},{ 1,-1}},{{1, 1},{0, 1},{-1, 0}},{{-1,1},{-1,0},{ 0,-1}}} };
// prototypes ***********************************************************
void led_on ( uint8_t index );
// ************************************************************prototypes
ISR (TIMER0_OVF_vect)
{
static uint8_t frame, row, row_cycle, key[5] = {0xFF,0xFF,0xFF,0xFF,0xFF};
static uint16_t keyTimer, speedCounter;
uint8_t i;
TCNT0 = 173;
//*************************************************** game speed control
if ( speedCounter < stepTime ) speedCounter++;
else {
speedCounter = 0;
waiting_for_next_step = 0;
}
//*************************************************** keyboard
if ( keyTimer < 476 ) keyTimer++;
else {
keyTimer = 0;
for ( i=0; i<=3; i++ ){
key[i] <<= 1;
if ( bit_is_set(PINB, i+2) ) key[i]++;
key[i] &= 0x0F; // clear high nibble
if ( key[i] == 0x0C ){
pressedKey[i] = 1;
amountKeyPressed++;
}
}
key[4] <<= 1;
if ( bit_is_set(PINC, 5) ) key[4]++;
key[4] &= 0x0F; // clear high nibble
if ( key[4] == 0x0C ){
pressedKey[4] = 1;
amountKeyPressed++;
}
}
if ( row_cycle == 0 ){
PORTD = 0x00;// deactivate all LEDs before activating next row
PORTB &= 0xFC;
PORTC = 0xE0 + row;
for ( i=0; i<=9; i++ )
if ( shaft[i+1][row+1] > 0 ) led_on(i);
}
// update display-clock for the next Timer0-Interrupt
if ( row_cycle < 9 ) row_cycle++;
else {
row_cycle = 0;
if ( row < 23 ) row++;
else {
row = 0;
if ( frame < 99 ) frame++;
else frame = 0;
}
}
}
void initGame( void )
{
uint8_t i, o, temp[10], splashscreen = 1;
for ( i=1; i<=5; i++ ){
shaft[i][6-i] = 1;
shaft[5+i][i] = 1;
}
for ( o=1; o<=9; o++ ){
shaft[5][o] = 1;
shaft[6][o] = 1;
}
do {
stepTime = 800; //|
waiting_for_next_step = 1; //|----wait for 500 * 42us = 21ms
for (;waiting_for_next_step;); //|
for ( i=1; i<=10; i++ )
temp[i-1] = shaft[i][1]; // abspeichern einer Zeile
for ( o=2; o<=24; o++ )
for ( i=1; i<=10; i++ )
shaft[i][o-1] = shaft[i][o];
for ( i=1; i<=10; i++ )
shaft[i][24] = temp[i-1];
if ( pressedKey[SPEED_UP] ){
pressedKey[SPEED_UP] = 0;
splashscreen = 0;
}
} while ( splashscreen );
// clear whole screen
for ( i=0; i<=11; i++ )
for ( o=0; o<=28; o++ )
shaft[i][o] = 0;
// Init. shaft-limits
for ( o=0; o<=28; o++ ) shaft[ 0][o] = 1; // set right limit
for ( o=0; o<=28; o++ ) shaft[11][o] = 1; // set left limit
for ( i=0; i<=11; i++ ) shaft[ i][0] = 1; // set bottom limit
for ( i=0; i<=24; i++ ) stonesPerRow[i] = 0;
speedCounter = 0;
stepTimeBackup = stepTime = 12000; // 42us * 23809 = ca. 1 second -> The brick falls down with 1 step per second.
gameOver = 0;
waiting_for_next_step = 1;
}
void led_on ( uint8_t index )
{
if ( index < 8 ) PORTD = PORTD | ( 1 << index );
else PORTB = PORTB | ( index - 7 );
}
void brickWillBe (int8_t action, struct brick Brick)
{
uint8_t i;
for ( i=0; i<=3; i++ ){
shaft[Brick.posi[X]+shape[Brick.shape][Brick.dir][i][X]][Brick.posi[Y]+shape[Brick.shape][Brick.dir][i][Y]] = 1 + action;
stonesPerRow[Brick.posi[Y]+shape[Brick.shape][Brick.dir][i][Y]-1] += action;
}
}
void put_in_new_stone ( void )
{
//stepTime = stepTimeBackup *= 0.97;
stepTime = stepTimeBackup *= 1;
currentBrick.shape = nextBrick.shape = (TCNT0 + amountKeyPressed ) % 7;
currentBrick.dir = nextBrick.dir = 0;
currentBrick.posi[X] = nextBrick.posi[X] = STARTPOSITION_X;
currentBrick.posi[Y] = nextBrick.posi[Y] = STARTPOSITION_Y;
movD_possible = 1;
brickWillBe ( PLACED, currentBrick );
}
uint8_t movImpossible ( struct brick Brick )
{
uint8_t blockedSpace = 0, i;
for ( i=0; i<=3; i++ )
if (shaft[Brick.posi[X]+shape[Brick.shape][Brick.dir][i][X]][Brick.posi[Y]+shape[Brick.shape][Brick.dir][i][Y]]){
blockedSpace++;
break;
}
return blockedSpace;
}
void moveNrollLR()
{
if ( pressedKey[MOVE_RIGHT] ){
pressedKey[MOVE_RIGHT] = 0;
nextBrick.posi[X]--;
brickWillBe( REMOVED, currentBrick );
if ( movImpossible(nextBrick) ){
brickWillBe( PLACED, currentBrick );
nextBrick = currentBrick;
}
else {
brickWillBe( PLACED, nextBrick );
currentBrick = nextBrick;
}
}
if ( pressedKey[ROLL_CW] ){
pressedKey[ROLL_CW] = 0;
if ( nextBrick.dir < LEFT ) nextBrick.dir++;
else nextBrick.dir = UP;
brickWillBe( REMOVED, currentBrick );
if ( movImpossible(nextBrick) ){
brickWillBe( PLACED, currentBrick );
nextBrick = currentBrick;
}
else {
brickWillBe( PLACED, nextBrick );
currentBrick = nextBrick;
}
}
if ( pressedKey[ROLL_CCW] ){
pressedKey[ROLL_CCW] = 0;
if ( nextBrick.dir > UP ) nextBrick.dir--;
else nextBrick.dir = LEFT;
brickWillBe( REMOVED, currentBrick );
if ( movImpossible(nextBrick) ){
brickWillBe( PLACED, currentBrick );
nextBrick = currentBrick;
}
else {
brickWillBe( PLACED, nextBrick );
currentBrick = nextBrick;
}
}
if ( pressedKey[MOVE_LEFT] ){
pressedKey[MOVE_LEFT] = 0;
nextBrick.posi[X]++;
brickWillBe( REMOVED, currentBrick );
if ( movImpossible(nextBrick) ){
brickWillBe( PLACED, currentBrick );
nextBrick = currentBrick;
}
else {
brickWillBe( PLACED, nextBrick );
currentBrick = nextBrick;
}
}
if ( pressedKey[SPEED_UP] ){
pressedKey[SPEED_UP] = 0;
stepTime = 0;
}
}
void move_one_step_down( void )
{
uint8_t i, x, y;
// nur zum test;
uint8_t rowsCleared;
nextBrick.posi[Y]--;
brickWillBe( REMOVED, currentBrick );
if ( movImpossible( nextBrick ) ){
brickWillBe( PLACED, currentBrick);
nextBrick = currentBrick;
for ( y=24; y>=1; y-- ){
if ( stonesPerRow[y-1] == 10 ){
rowsCleared++;
for ( i=y; i<=24; i++ ){
for ( x=1; x<=10; x++ )
shaft[x][i] = shaft[x][i+1];
stonesPerRow[i-1] = stonesPerRow[i];
}
}
}
movD_possible = 0;
if ( stonesPerRow[24] ) gameOver = 1;
}
else {
brickWillBe( PLACED, nextBrick );
currentBrick = nextBrick;
}
}
int main( void )
{
DDRB = 0x03;
DDRC = 0x1F;
DDRD = 0xFF;
PORTB = 0xFC;
PORTC = 0x20;
TCNT0 = 173; // interrupt every 42us
TCCR0 = 0x02; // prescaler: 8
TIMSK = 0x01;
SREG |= 0x80;
initGame();
do {
put_in_new_stone();
do {
do {
moveNrollLR();
} while ( waiting_for_next_step );
waiting_for_next_step = 1;
move_one_step_down();
} while ( movD_possible );
} while ( !gameOver );
for (;;) {
};
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -