⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 t-tris.c

📁 This Tetris-Clone was assembled from one ATmega8, 240 red LEDs, a few BJTs, a few IC s and some push
💻 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 + -