#include <avr/pgmspace.h>
#include <Wire.h>
#define u8 unsigned char
// 1. LCD显示屏的接口定义
#define PIN_LCD_SDI 6
#define PIN_LCD_SCK 8
#define PIN_LCD_DCX 18
#define PIN_LCD_RST 13
#define PIN_LCD_CS 1
#define LCD_X_MAX 160-1
#define LCD_Y_MAX 80-1
u8 AllTetris[15][30] = { 0 };
char Position_x[7][4][4] =
{
{ {-1, 0, 1, 2}, {0, 0, 0, 0}, {-1, 0, 1, 2}, {0, 0, 0, 0} },
{ {0, 0, 0, 1}, {0, 1, 2, 0}, {-1, 0, 0, 0}, {-1, 0, 1, 1} },
{ {0, 0, 0, -1}, {-1, -1, 0, 1}, {0, 1, 0, 0}, {-1, 0, 1, 1} },
{ {0, 0, 1, 0}, {0, -1, 0, 1}, {0, -1, 0, 0}, {-1, 0, 1, 0} },
{ {-1, 0, 0, 1}, {1, 0, 1, 0}, {-1, 0, 0, 1}, {1, 0, 1, 0} },
{ {0, 1, -1, 0}, {0, 0, 1, 1}, {0, 1, -1, 0}, {0, 0, 1, 1} },
{ {0, 1, 0, 1}, {0, 1, 0, 1}, {0, 1, 0, 1}, {0, 1, 0, 1} }
};
char Position_y[7][4][4] =
{
{ {0, 0, 0, 0}, {1, 0, -1, -2}, {0, 0, 0, 0}, {1, 0, -1, -2} },
{ {1, 0, -1, -1}, {0, 0, 0, -1}, {1, 1, 0, -1}, {0, 0, 0, 1} },
{ {1, 0, -1, -1}, {1, 0, 0, 0}, {1, 1, 0, -1}, {0, 0, 0, -1} },
{ {1, 0, 0, -1}, {1, 0, 0, 0}, {1, 0, 0, -1}, {0, 0, 0, -1} },
{ {1, 1, 0, 0}, {1, 0, 0, -1}, {1, 1, 0, 0}, {1, 0, 0, -1} },
{ {1, 1, 0, 0}, {1, 0, 0, -1}, {1, 1, 0, 0}, {1, 0, 0, -1} },
{ {1, 1, 0, 0}, {1, 1, 0, 0}, {1, 1, 0, 0}, {1, 1, 0, 0} }
};
u8 Now_Form, Now_Shape;
u8 Now_x, Now_y;
u8 Next_Form, Next_Shape;
u8 LOSE = 0;
u8 rate = 1;
int Score = 0;
char lcd_buf[20];
/*以下均为LCD示例里的函数*/
/*****************************************/
PROGMEM prog_uchar font8x12[][12] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //
{0x00,0x30,0x78,0x78,0x78,0x30,0x30,0x00,0x30,0x30,0x00,0x00}, // !
{0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // "
{0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00}, // #
{0x30,0x30,0x7C,0xC0,0xC0,0x78,0x0C,0x0C,0xF8,0x30,0x30,0x00}, // $
{0x00,0x00,0x00,0xC4,0xCC,0x18,0x30,0x60,0xCC,0x8C,0x00,0x00}, // %
{0x00,0x70,0xD8,0xD8,0x70,0xFA,0xDE,0xCC,0xDC,0x76,0x00,0x00}, // &
{0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // '
{0x00,0x0C,0x18,0x30,0x60,0x60,0x60,0x30,0x18,0x0C,0x00,0x00}, // (
{0x00,0x60,0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x60,0x00,0x00}, // )
{0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00}, // *
{0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00}, // +
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x60,0x00}, // ,
{0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00}, // -
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x00,0x00}, // .
{0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00}, // /
{0x00,0x7C,0xC6,0xD6,0xD6,0xD6,0xD6,0xD6,0xC6,0x7C,0x00,0x00}, // 0
{0x00,0x10,0x30,0xF0,0x30,0x30,0x30,0x30,0x30,0xFC,0x00,0x00}, // 1
{0x00,0x78,0xCC,0xCC,0x0C,0x18,0x30,0x60,0xCC,0xFC,0x00,0x00}, // 2
{0x00,0x78,0xCC,0x0C,0x0C,0x38,0x0C,0x0C,0xCC,0x78,0x00,0x00}, // 3
{0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x1E,0x00,0x00}, // 4
{0x00,0xFC,0xC0,0xC0,0xC0,0xF8,0x0C,0x0C,0xCC,0x78,0x00,0x00}, // 5
{0x00,0x38,0x60,0xC0,0xC0,0xF8,0xCC,0xCC,0xCC,0x78,0x00,0x00}, // 6
{0x00,0xFE,0xC6,0xC6,0x06,0x0C,0x18,0x30,0x30,0x30,0x00,0x00}, // 7
{0x00,0x78,0xCC,0xCC,0xEC,0x78,0xDC,0xCC,0xCC,0x78,0x00,0x00}, // 8
{0x00,0x78,0xCC,0xCC,0xCC,0x7C,0x18,0x18,0x30,0x70,0x00,0x00}, // 9
{0x00,0x00,0x00,0x38,0x38,0x00,0x00,0x38,0x38,0x00,0x00,0x00}, // :
{0x00,0x00,0x00,0x38,0x38,0x00,0x00,0x38,0x38,0x18,0x30,0x00}, // ;
{0x00,0x0C,0x18,0x30,0x60,0xC0,0x60,0x30,0x18,0x0C,0x00,0x00}, // <
{0x00,0x00,0x00,0x00,0x7E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00}, // =
{0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00}, // >
{0x00,0x78,0xCC,0x0C,0x18,0x30,0x30,0x00,0x30,0x30,0x00,0x00}, // ?
{0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xC0,0xC0,0x7C,0x00,0x00}, // @
{0x00,0x30,0x78,0xCC,0xCC,0xCC,0xFC,0xCC,0xCC,0xCC,0x00,0x00}, // A
{0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0xFC,0x00,0x00}, // B
{0x00,0x3C,0x66,0xC6,0xC0,0xC0,0xC0,0xC6,0x66,0x3C,0x00,0x00}, // C
{0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00}, // D
{0x00,0xFE,0x62,0x60,0x64,0x7C,0x64,0x60,0x62,0xFE,0x00,0x00}, // E
{0x00,0xFE,0x66,0x62,0x64,0x7C,0x64,0x60,0x60,0xF0,0x00,0x00}, // F
{0x00,0x3C,0x66,0xC6,0xC0,0xC0,0xCE,0xC6,0x66,0x3E,0x00,0x00}, // G
{0x00,0xCC,0xCC,0xCC,0xCC,0xFC,0xCC,0xCC,0xCC,0xCC,0x00,0x00}, // H
{0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00}, // I
{0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00}, // J
{0x00,0xE6,0x66,0x6C,0x6C,0x78,0x6C,0x6C,0x66,0xE6,0x00,0x00}, // K
{0x00,0xF0,0x60,0x60,0x60,0x60,0x62,0x66,0x66,0xFE,0x00,0x00}, // L
{0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0x00,0x00}, // M
{0x00,0xC6,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0x00,0x00}, // N
{0x00,0x38,0x6C,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00}, // O
{0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0xF0,0x00,0x00}, // P
{0x00,0x38,0x6C,0xC6,0xC6,0xC6,0xCE,0xDE,0x7C,0x0C,0x1E,0x00}, // Q
{0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0xE6,0x00,0x00}, // R
{0x00,0x78,0xCC,0xCC,0xC0,0x70,0x18,0xCC,0xCC,0x78,0x00,0x00}, // S
{0x00,0xFC,0xB4,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00}, // T
{0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00}, // U
{0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x30,0x00,0x00}, // V
{0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0x6C,0x6C,0x6C,0x00,0x00}, // W
{0x00,0xCC,0xCC,0xCC,0x78,0x30,0x78,0xCC,0xCC,0xCC,0x00,0x00}, // X
{0x00,0xCC,0xCC,0xCC,0xCC,0x78,0x30,0x30,0x30,0x78,0x00,0x00}, // Y
{0x00,0xFE,0xCE,0x98,0x18,0x30,0x60,0x62,0xC6,0xFE,0x00,0x00}, // Z
{0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00}, // [
{0x00,0x00,0x80,0xC0,0x60,0x30,0x18,0x0C,0x06,0x02,0x00,0x00}, /* \*/
{0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00}, // ]
{0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ^
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00}, // _
{0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // `
{0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0x76,0x00,0x00}, // a
{0x00,0xE0,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0xDC,0x00,0x00}, // b
{0x00,0x00,0x00,0x00,0x78,0xCC,0xC0,0xC0,0xCC,0x78,0x00,0x00}, // c
{0x00,0x1C,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00}, // d
{0x00,0x00,0x00,0x00,0x78,0xCC,0xFC,0xC0,0xCC,0x78,0x00,0x00}, // e
{0x00,0x38,0x6C,0x60,0x60,0xF8,0x60,0x60,0x60,0xF0,0x00,0x00}, // f
{0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0x7C,0x0C,0xCC,0x78}, // g
{0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0xE6,0x00,0x00}, // h
{0x00,0x18,0x18,0x00,0x78,0x18,0x18,0x18,0x18,0x7E,0x00,0x00}, // i
{0x00,0x0C,0x0C,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0x78}, // j
{0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x6C,0x66,0xE6,0x00,0x00}, // k
{0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00}, // l
{0x00,0x00,0x00,0x00,0xFC,0xD6,0xD6,0xD6,0xD6,0xC6,0x00,0x00}, // m
{0x00,0x00,0x00,0x00,0xF8,0xCC,0xCC,0xCC,0xCC,0xCC,0x00,0x00}, // n
{0x00,0x00,0x00,0x00,0x78,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00}, // o
{0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x7C,0x60,0xF0}, // p
{0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x1E}, // q
{0x00,0x00,0x00,0x00,0xEC,0x6E,0x76,0x60,0x60,0xF0,0x00,0x00}, // r
{0x00,0x00,0x00,0x00,0x78,0xCC,0x60,0x18,0xCC,0x78,0x00,0x00}, // s
{0x00,0x00,0x20,0x60,0xFC,0x60,0x60,0x60,0x6C,0x38,0x00,0x00}, // t
{0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00}, // u
{0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0x78,0x30,0x00,0x00}, // v
{0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0x6C,0x6C,0x00,0x00}, // w
{0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x6C,0xC6,0x00,0x00}, // x
{0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x0C,0x18,0xF0}, // y
{0x00,0x00,0x00,0x00,0xFC,0x8C,0x18,0x60,0xC4,0xFC,0x00,0x00}, // z
{0x00,0x1C,0x30,0x30,0x60,0xC0,0x60,0x30,0x30,0x1C,0x00,0x00}, // {
{0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x00,0x00}, // |
{0x00,0xE0,0x30,0x30,0x18,0x0C,0x18,0x30,0x30,0xE0,0x00,0x00}, // }
{0x00,0x73,0xDA,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ~
{0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0x00,0x00,0x00}, //
};
struct T_color
{
unsigned char red;
unsigned char grn;
unsigned char blu;
} lcd_front_color, lcd_back_color;
struct T_cursor
{
unsigned char x;
unsigned char y;
} lcd_cursor;
void lcd_spi_subop_wr(unsigned char fv_data)
{
if (SPI2STATbits.SPITBE)
{
SPI2BUF = fv_data;
}
while (SPI2STATbits.SPIBUSY);
fv_data = SPI2BUF;
}
void lcd_subop_chipSelect(void)
{
digitalWrite(PIN_LCD_CS, LOW);
}
void lcd_subop_chipUnselect(void)
{
digitalWrite(PIN_LCD_CS, HIGH);
}
void lcd_write_cmd(unsigned char fv_cmd)
{
digitalWrite(PIN_LCD_DCX, LOW);
lcd_spi_subop_wr(fv_cmd);
}
void lcd_write_data(unsigned char fv_data)
{
digitalWrite(PIN_LCD_DCX, HIGH);
lcd_spi_subop_wr(fv_data);
}
void lcd_init(void)
{
// 端口初始化
pinMode(PIN_LCD_SDI, OUTPUT);
digitalWrite(PIN_LCD_SDI, LOW);
pinMode(PIN_LCD_SCK, OUTPUT);
digitalWrite(PIN_LCD_SCK, LOW);
pinMode(PIN_LCD_DCX, OUTPUT);
digitalWrite(PIN_LCD_DCX, LOW);
pinMode(PIN_LCD_RST, OUTPUT);
digitalWrite(PIN_LCD_RST, HIGH);
pinMode(PIN_LCD_CS, OUTPUT);
digitalWrite(PIN_LCD_CS, HIGH);
// SPI2初始化
SPI2CON = 0;
SPI2CONbits.SMP = 1;
SPI2CONbits.CKE = 1;
SPI2CONbits.MSTEN = 1;
SPI2CONbits.DISSDI = 1;
SPI2BRG = 10 - 1;
SPI2CONbits.ON = 1;
// 端口映射(pps)
mapPps(PIN_LCD_SDI, PPS_OUT_SDO2);
digitalWrite(PIN_LCD_RST, LOW);
delay(100);
digitalWrite(PIN_LCD_RST, HIGH);
delay(50);
lcd_subop_chipSelect();
lcd_write_cmd(0x11);
lcd_subop_chipUnselect();
delay(120);
lcd_subop_chipSelect();
lcd_write_cmd(0x21); // Display Inversion ON
//lcd_write_cmd(0x20); // Display Inversion OFF
lcd_subop_chipUnselect();
lcd_subop_chipSelect();
lcd_write_cmd(0xB1); //lcd_write_cmd(0xB1);
lcd_write_data(0x05); //lcd_write_data(0x05);
lcd_write_data(0x3A); //lcd_write_data(0x3A);
lcd_write_data(0x3A); //lcd_write_data(0x3A);
lcd_subop_chipUnselect();
lcd_subop_chipSelect();
lcd_write_cmd(0xB2); //lcd_write_cmd(0xB2);
lcd_write_data(0x05); //lcd_write_data(0x05);
lcd_write_data(0x3A); //lcd_write_data(0x3A);
lcd_write_data(0x3A); //lcd_write_data(0x3A);
lcd_subop_chipUnselect();
lcd_subop_chipSelect();
lcd_write_cmd(0xB3); //lcd_write_cmd(0xB3);
lcd_write_data(0x05); //lcd_write_data(0x05);
lcd_write_data(0x3A); //lcd_write_data(0x3A);
lcd_write_data(0x3A); //lcd_write_data(0x3A);
lcd_write_data(0x05); //lcd_write_data(0x05);
lcd_write_data(0x3A); //lcd_write_data(0x3A);
lcd_write_data(0x3A);
lcd_subop_chipUnselect();
lcd_subop_chipSelect();
lcd_write_cmd(0xB4);
lcd_write_data(0x03);
lcd_subop_chipUnselect();
lcd_subop_chipSelect();
lcd_write_cmd(0xC0);
lcd_write_data(0x62);
lcd_write_data(0x02);
lcd_write_data(0x04);
lcd_subop_chipUnselect();
lcd_subop_chipSelect();
lcd_write_cmd(0xC1);
lcd_write_data(0xC0);
lcd_subop_chipUnselect();
lcd_subop_chipSelect();
lcd_write_cmd(0xC2);
lcd_write_data(0x0D);
lcd_write_data(0x00);
lcd_subop_chipUnselect();
lcd_subop_chipSelect();
lcd_write_cmd(0xC3);
lcd_write_data(0x8D);
lcd_write_data(0x6A);
lcd_subop_chipUnselect();
lcd_subop_chipSelect();
lcd_write_cmd(0xC4);
lcd_write_data(0x8D);
lcd_write_data(0xEE);
lcd_subop_chipUnselect();
lcd_subop_chipSelect();
lcd_write_cmd(0xC5); /*VCOM*/
lcd_write_data(0x0E);
lcd_subop_chipUnselect();
lcd_subop_chipSelect();
lcd_write_cmd(0xE0);
lcd_write_data(0x10);
lcd_write_data(0x0E);
lcd_write_data(0x02);
lcd_write_data(0x03);
lcd_write_data(0x0E);
lcd_write_data(0x07);
lcd_write_data(0x02);
lcd_write_data(0x07);
lcd_write_data(0x0A);
lcd_write_data(0x12);
lcd_write_data(0x27);
lcd_write_data(0x37);
lcd_write_data(0x00);
lcd_write_data(0x0D);
lcd_write_data(0x0E);
lcd_write_data(0x10);
lcd_subop_chipUnselect();
lcd_subop_chipSelect();
lcd_write_cmd(0xE1);
lcd_write_data(0x10);
lcd_write_data(0x0E);
lcd_write_data(0x03);
lcd_write_data(0x03);
lcd_write_data(0x0F);
lcd_write_data(0x06);
lcd_write_data(0x02);
lcd_write_data(0x08);
lcd_write_data(0x0A);
lcd_write_data(0x13);
lcd_write_data(0x26);
lcd_write_data(0x36);
lcd_write_data(0x00);
lcd_write_data(0x0D);
lcd_write_data(0x0E);
lcd_write_data(0x10);
lcd_subop_chipUnselect();
lcd_subop_chipSelect();
lcd_write_cmd(0x3A);
lcd_write_data(0x06);
//lcd_write_data(0xc0); // 18bit mode
lcd_subop_chipUnselect();
lcd_subop_chipSelect();
lcd_write_cmd(0x36);
//lcd_write_data(0xA8);//
lcd_write_data(0b01101010);
lcd_subop_chipUnselect();
lcd_subop_chipSelect();
lcd_write_cmd(0x29);
lcd_subop_chipUnselect();
lcd_cursor.x = 0;
lcd_cursor.y = 0;
}
void lcd_subop_set_region(unsigned char fv_x_start, unsigned char fv_y_start, unsigned char fv_x_end, unsigned char fv_y_end)
{
lcd_write_cmd(0x2a);
lcd_write_data(0x00);
lcd_write_data(fv_x_start + 1);
lcd_write_data(0x00);
lcd_write_data(fv_x_end + 1);
lcd_write_cmd(0x2b);
lcd_write_data(0x00);
lcd_write_data(fv_y_start + 0x1A);
lcd_write_data(0x00);
lcd_write_data(fv_y_end + 0x1A);
}
void gui_setCursor(unsigned char fv_x, unsigned char fv_y)
{
if ((fv_x <= LCD_X_MAX) && (fv_y <= LCD_Y_MAX))
{
lcd_cursor.x = fv_x;
lcd_cursor.y = fv_y;
}
}
void gui_set_frontColor(unsigned char fv_red, unsigned char fv_grn, unsigned char fv_blu)
{
lcd_front_color.red = fv_red;
lcd_front_color.grn = fv_grn;
lcd_front_color.blu = fv_blu;
}
void gui_set_backColor(unsigned char fv_red, unsigned char fv_grn, unsigned char fv_blu)
{
lcd_back_color.red = fv_red;
lcd_back_color.grn = fv_grn;
lcd_back_color.blu = fv_blu;
}
void gui_drawRec(struct T_color fv_color, unsigned char fv_x_start, unsigned char fv_y_start, unsigned char fv_x_end, unsigned char fv_y_end)
{
if ((fv_x_start <= LCD_X_MAX) && (fv_x_end <= LCD_X_MAX) && (fv_y_start <= LCD_Y_MAX) && (fv_y_end <= LCD_Y_MAX))
{
lcd_subop_chipSelect();
lcd_subop_set_region(fv_x_start, fv_y_start, fv_x_end, fv_y_end);
lcd_write_cmd(0x2c);
unsigned char fv_op_x, fv_op_y;
for (fv_op_y = fv_y_start; fv_op_y <= fv_y_end; fv_op_y++)
for (fv_op_x = fv_x_start; fv_op_x <= fv_x_end; fv_op_x++)
{
lcd_write_data(fv_color.red);
lcd_write_data(fv_color.grn);
lcd_write_data(fv_color.blu);
}
lcd_subop_chipUnselect();
}
}
void lcd_putChar(unsigned char fv_char)
{
unsigned char fv_x, fv_y;
unsigned char fv_op_data;
lcd_subop_chipSelect();
lcd_subop_set_region(lcd_cursor.x, lcd_cursor.y - 11, lcd_cursor.x + 7, lcd_cursor.y);
lcd_write_cmd(0x2c);
for (fv_y = 0; fv_y < 12; fv_y++)
{
fv_op_data = pgm_read_byte_near(font8x12 + (fv_char - 0x20) * 12 + fv_y);
for (fv_x = 0; fv_x < 8; fv_x++)
{
if (fv_op_data & 0x80)
{
// 数据是1,该点使用前景色绘制
lcd_write_data(lcd_front_color.red);
lcd_write_data(lcd_front_color.grn);
lcd_write_data(lcd_front_color.blu);
}
else
{
// 数据是0,该点使用背景色绘制
lcd_write_data(lcd_back_color.red);
lcd_write_data(lcd_back_color.grn);
lcd_write_data(lcd_back_color.blu);
}
fv_op_data <<= 1;
}
}
lcd_subop_chipUnselect();
lcd_cursor.x += 8;
if (lcd_cursor.x > LCD_X_MAX)
lcd_cursor.x = 0;
}
void gui_put_str(char *str_ptr, unsigned char str_len)
{
if ((lcd_cursor.x <= (LCD_X_MAX - str_len * 8)) && (lcd_cursor.y >= 11))
{
unsigned char fv_op_num;
for (fv_op_num = 0; fv_op_num < str_len; fv_op_num++)
{
lcd_putChar(str_ptr[fv_op_num]);
}
}
}
/***********************************************************************/
/*这两个函数用于横屏时显示字符,光标位置为字符的左上角,字符大小高12宽8*/
void lcd_putChar2(unsigned char fv_char)
{
unsigned char fv_x, fv_y;
unsigned char fv_op_data, fv_op_data2;
lcd_subop_chipSelect();
lcd_subop_set_region(lcd_cursor.x - 11, lcd_cursor.y, lcd_cursor.x, lcd_cursor.y + 7);
lcd_write_cmd(0x2c);
for (fv_y = 0; fv_y < 8; fv_y++)
{
for (fv_x = 0; fv_x <= 11; fv_x++)
{
fv_op_data = pgm_read_byte_near(font8x12 + (fv_char - 0x20) * 12 + 11 - fv_x);
fv_op_data = fv_op_data << fv_y;
if (fv_op_data & 0x80)
{
// 数据是1,该点使用前景色绘制
lcd_write_data(lcd_front_color.red);
lcd_write_data(lcd_front_color.grn);
lcd_write_data(lcd_front_color.blu);
}
else
{
// 数据是0,该点使用背景色绘制
lcd_write_data(lcd_back_color.red);
lcd_write_data(lcd_back_color.grn);
lcd_write_data(lcd_back_color.blu);
}
}
}
lcd_subop_chipUnselect();
lcd_cursor.y += 8;
if (lcd_cursor.y > LCD_Y_MAX)
lcd_cursor.y = 0;
}
void gui_put_str2(char *str_ptr, unsigned char str_len)
{
if ((lcd_cursor.y <= (LCD_Y_MAX - str_len * 8)) && (lcd_cursor.x >= 11))
{
unsigned char fv_op_num;
for (fv_op_num = 0; fv_op_num < str_len; fv_op_num++)
{
lcd_putChar2(str_ptr[fv_op_num]);
}
}
}
//绘制矩形,颜色为前景色
void lcd_drawRect(u8 fv_x_start, u8 fv_y_start, u8 fv_x_end, u8 fv_y_end)
{
if ((fv_x_start <= LCD_X_MAX) && (fv_x_end <= LCD_X_MAX) && (fv_y_start <= LCD_Y_MAX) && (fv_y_end <= LCD_Y_MAX))
{
lcd_subop_chipSelect();
lcd_subop_set_region(fv_x_start, fv_y_start, fv_x_end, fv_y_end);
lcd_write_cmd(0x2c);
unsigned char fv_op_x, fv_op_y;
for (fv_op_y = fv_y_start; fv_op_y <= fv_y_end; fv_op_y++)
for (fv_op_x = fv_x_start; fv_op_x <= fv_x_end; fv_op_x++)
{
lcd_write_data(lcd_front_color.red);
lcd_write_data(lcd_front_color.grn);
lcd_write_data(lcd_front_color.blu);
}
lcd_subop_chipUnselect();
}
}
//绘制矩形,颜色为给定颜色
void lcd_drawRect2(u8 fv_x_start, u8 fv_y_start, u8 fv_x_end, u8 fv_y_end, u8 fv_red = lcd_front_color.red, u8 fv_grn = lcd_front_color.grn, u8 fv_blu = lcd_front_color.blu)
{
if ((fv_x_start <= LCD_X_MAX) && (fv_x_end <= LCD_X_MAX) && (fv_y_start <= LCD_Y_MAX) && (fv_y_end <= LCD_Y_MAX))
{
lcd_subop_chipSelect();
lcd_subop_set_region(fv_x_start, fv_y_start, fv_x_end, fv_y_end);
lcd_write_cmd(0x2c);
unsigned char fv_op_x, fv_op_y;
for (fv_op_y = fv_y_start; fv_op_y <= fv_y_end; fv_op_y++)
for (fv_op_x = fv_x_start; fv_op_x <= fv_x_end; fv_op_x++)
{
lcd_write_data(fv_red);
lcd_write_data(fv_grn);
lcd_write_data(fv_blu);
}
lcd_subop_chipUnselect();
}
}
//清除矩形区域(颜色与背景色相同)
void lcd_clearRect(u8 fv_x_start, u8 fv_y_start, u8 fv_x_end, u8 fv_y_end)
{
if ((fv_x_start <= LCD_X_MAX) && (fv_x_end <= LCD_X_MAX) && (fv_y_start <= LCD_Y_MAX) && (fv_y_end <= LCD_Y_MAX))
{
lcd_subop_chipSelect();
lcd_subop_set_region(fv_x_start, fv_y_start, fv_x_end, fv_y_end);
lcd_write_cmd(0x2c);
unsigned char fv_op_x, fv_op_y;
for (fv_op_y = fv_y_start; fv_op_y <= fv_y_end; fv_op_y++)
for (fv_op_x = fv_x_start; fv_op_x <= fv_x_end; fv_op_x++)
{
lcd_write_data(lcd_back_color.red);
lcd_write_data(lcd_back_color.grn);
lcd_write_data(lcd_back_color.blu);
}
lcd_subop_chipUnselect();
}
}
//绘制游戏的框架
void DrawFrame()
{
lcd_drawRect(0, 0, 0 + 5 - 1, 79);
lcd_drawRect(159 - 5 + 1, 0, 159, 79);
lcd_drawRect(0, 0, 159, 0 + 4 - 1);
lcd_drawRect(0, 79 - 4 + 1, 159, 79);
lcd_clearRect(159 - 9 - 36, 2, 159 - 5 + 1, 78);
lcd_drawRect(159 - 9 - 36, 0, 159 - 5 - 36, 79);
}
//用于点亮(x,y)处,此处坐标为游戏内坐标,非LCD的坐标
//x,y的范围如下:
//x:1 -> 12 y : 1 -> 25
void DrawBlock(u8 x, u8 y)
{
if (x >= 1 && x <= 12 && y >= 1 && y <= 25)
lcd_drawRect(6 * y - 1, 6 * x - 2, 6 * y + 3, 6 * x + 2);
//这里是在6*6的范围内绘制了5*5的矩形,也就是上侧和右侧各留有一个像素的空隙,视觉效果会好一点
}
//用于熄灭(x,y)处
void ClearBlock(u8 x, u8 y)
{
if (x >= 1 && x <= 12 && y >= 1 && y <= 25)
lcd_clearRect(6 * y - 1, 6 * x - 2, 6 * y + 4, 6 * x + 3);
}
//绘制类型为form,形状为shape,基点坐标为(x,y)的俄罗斯方块
void DrawTetris(u8 x, u8 y, u8 form, u8 shape)
{
u8 i;
for (i = 0; i <= 3; i++)
{
DrawBlock(x + Position_x[form][shape][i], y + Position_y[form][shape][i]);
}
}
//清除类型为form,形状为shape,基点坐标为(x,y)的俄罗斯方块
void ClearTetris(u8 x, u8 y, u8 form, u8 shape)
{
u8 i;
for (i = 0; i <= 3; i++)
{
ClearBlock(x + Position_x[form][shape][i], y + Position_y[form][shape][i]);
}
}
//判断是否可以放下类型为form,形状为shape,基点坐标为(x,y)的俄罗斯方块,可以返回1,不可以返回0
u8 Judge(u8 x, u8 y, u8 form, u8 shape)
{
u8 i;
u8 x1, y1;
for (i = 0; i <= 3; i++)
{
x1 = x + Position_x[form][shape][i];
y1 = y + Position_y[form][shape][i];
if (y1 > 18)
LOSE = 1;
if (x1 < 1 || y1 < 1 || x1 > 12 || y1 > 18)
return 0;
if (AllTetris[x1][y1] == 1)
return 0;
}
return 1;
}
//检测是否可以消去一层,如果可以,消去
void Remove(u8 temp[15][30])
{
char x, y = 1;
char i, j;
char sign;
u8 AllSign = 0;
u8 sum;
u8 Line[30] = { 0 };
//从第1层向上检测每层是否可以消去
while (y <= (Now_y + 2))
{
sign = 1;
for (x = 1; x <= 12; x++)
{
if (AllTetris[x][y] == 0)
{
sign = 0;
break;
}
}
if (sign == 1) //如果可以消去
{
Line[y] = 1; //标记可消去的这一层
AllSign++; //可消去层的计数标记+1
Score = Score + y * y; //分数增加,消去的层数越高,分数越多
/*可消去的那一层会有炫酷的闪烁(没啥用,可以去掉)*/
/***********************************/
gui_set_frontColor(65, 105, 255);
for (x = 1; x <= 12; x++)
DrawBlock(x, y);
delay(60);
gui_set_frontColor(255, 0, 255);
for (x = 1; x <= 12; x++)
DrawBlock(x, y);
delay(60);
gui_set_frontColor(220, 20, 60);
for (x = 1; x <= 12; x++)
DrawBlock(x, y);
delay(60);
/********************************/
}
y++;
}
//如果计数为0,不用消去,直接返回,这是普遍情况,所以先判断,提高效率
if (AllSign == 0)
return;
//AllTetris数组更新,去掉所有应消去层
for (y = 1, i = 1; y <= 18; y++, i++)
{
if (Line[i] == 1)
{
y--;
continue;
}
else
{
for (x = 1; x <= 12; x++)
AllTetris[x][y] = temp[x][i];
}
}
//LCD屏幕的显示更新
gui_set_frontColor(255, 255, 0);
for (y = 1; y <= 18; y++)
{
for (x = 1; x <= 12; x++)
{
ClearBlock(x, y);
if (AllTetris[x][y] == 1)
DrawBlock(x, y);
}
}
return;
}
//用于失败后的炫酷显示,不再赘述(失败后所有中断关闭)
void LoseResult()
{
u8 i, j, k = 5;
while (k > 0)
{
k--;
gui_set_frontColor(255, 0, 0);
for (i = 1; i <= 18; i++)
{
for (j = 1; j <= 12; j++)
{
DrawBlock(j, i);
}
}
delay(20);
gui_set_frontColor(0, 255, 0);
for (i = 1; i <= 18; i++)
{
for (j = 1; j <= 12; j++)
{
DrawBlock(j, i);
}
}
delay(20);
gui_set_frontColor(0, 0, 255);
for (i = 1; i <= 18; i++)
{
for (j = 1; j <= 12; j++)
{
DrawBlock(j, i);
}
}
delay(20);
}
for (i = 1; i <= 18; i++)
{
for (j = 1; j <= 12; j++)
{
ClearBlock(j, i);
}
}
gui_set_frontColor(100, 0, 200);
gui_setCursor(100, 30);
gui_put_str2("You", 3);
delay(400);
gui_setCursor(80, 30);
gui_put_str2("Are", 3);
delay(400);
gui_setCursor(60, 33);
gui_put_str2("So", 2);
delay(400);
gui_setCursor(40, 30);
gui_put_str2("Cai", 3);
delay(400);
uint32_t status = disableInterrupts();
}
//游戏主体部分
void Game()
{
u8 i, j;
int delay_time;
//初始化新的俄罗斯方块的参数
Now_Form = Next_Form;
Now_Shape = Next_Shape;
Next_Form = random(7);
Next_Shape = random(4);
Now_x = 6;
Now_y = 17;
//游戏速度随分数增加而加快
if (Score <= 20)
delay_time = 260;
else if (Score <= 50)
delay_time = 230;
else if (Score <= 100)
delay_time = 210;
else if (Score <= 200)
delay_time = 170;
else if (Score <= 500)
delay_time = 150;
//顶部分数显示和下一个俄罗斯方块的形状显示
gui_set_frontColor(255, 0, 0);
gui_setCursor(152, 6);
sprintf(lcd_buf, "Score:%03d", Score * rate);
gui_put_str2(lcd_buf, strlen(lcd_buf));
gui_setCursor(135, 6);
gui_put_str2("Next:", 5);
DrawTetris(10, 22, Next_Form, Next_Shape);
//俄罗斯方块下落部分
gui_set_frontColor(0, 255, 255);
while (Judge(Now_x, Now_y, Now_Form, Now_Shape) == 1) //若可以继续下落
{
//如果按下 下 键, 以极快的速度下落至底部
if (digitalRead(12) == 1)
{
while (digitalRead(12) == 1)
;
delay_time = 1;
}
DrawTetris(Now_x, Now_y, Now_Form, Now_Shape); //绘制当前参数对应的俄罗斯方块
//如果按下暂停键,游戏暂停,中断关闭,直到再次按下暂停键
if (digitalRead(17) == 1)
{
while (digitalRead(17) == 1)
;
delay(200);
uint32_t status = disableInterrupts();
//作弊码hhh
while (digitalRead(17) == 0)
{
if ((digitalRead(10) + digitalRead(11) + digitalRead(12) + digitalRead(14)) == 4)
rate = 10;
}
restoreInterrupts(status);
delay(500);
}
delay(delay_time);
ClearTetris(Now_x, Now_y, Now_Form, Now_Shape); //清除俄罗斯方块
Now_y--;
}
if (Now_y >= 17) //如果俄罗斯方块已经堆到顶部,游戏结束
{
LOSE = 1;
delay(1000);
LoseResult();
return;
}
Now_y++; //while多减了一次,这里加回来
gui_set_frontColor(255, 255, 0);
DrawTetris(Now_x, Now_y, Now_Form, Now_Shape);
// AllTetris数组更新
for (i = 0; i <= 3; i++)
{
AllTetris[Now_x + Position_x[Now_Form][Now_Shape][i]][Now_y + Position_y[Now_Form][Now_Shape][i]] = 1;
}
//底部俄罗斯方块重新绘制,用于消除一个无伤大雅的BUG导致的错误显示
for (i = 1; i <= 18; i++)
{
for (j = 1; j <= 12; j++)
{
if (AllTetris[j][i] == 1)
DrawBlock(j, i);
else
ClearBlock(j, i);
}
}
Remove(AllTetris);
ClearTetris(10, 22, Next_Form, Next_Shape);
}
//若按下 上 键, 俄罗斯方块的Shape变化,并重新绘制
void __USER_ISR myISR_UP()
{
u8 temp = Now_Shape;
ClearTetris(Now_x, Now_y, Now_Form, Now_Shape);
Now_Shape++;
if (Now_Shape >= 4)
Now_Shape = 0;
if (Judge(Now_x, Now_y, Now_Form, Now_Shape) == 0)
{
Now_Shape = temp;
}
DrawTetris(Now_x, Now_y, Now_Form, Now_Shape);
clearIntFlag(_EXTERNAL_4_IRQ);
delay(10);
}
//若按下 左 键,判断是否可移动, 如果可以,俄罗斯方块左移,并重新绘制
void __USER_ISR myISR_LEFT()
{
if (Judge(Now_x - 1, Now_y, Now_Form, Now_Shape) == 1)
{
ClearTetris(Now_x, Now_y, Now_Form, Now_Shape);
Now_x--;
DrawTetris(Now_x, Now_y, Now_Form, Now_Shape);
}
clearIntFlag(_EXTERNAL_1_IRQ);
delay(10);
}
//若按下 右 键,判断是否可移动, 如果可以,俄罗斯方块右移,并重新绘制
void __USER_ISR myISR_RIGHT()
{
if (Judge(Now_x + 1, Now_y, Now_Form, Now_Shape) == 1)
{
ClearTetris(Now_x, Now_y, Now_Form, Now_Shape);
Now_x++;
DrawTetris(Now_x, Now_y, Now_Form, Now_Shape);
}
clearIntFlag(_EXTERNAL_3_IRQ);
delay(10);
}
void setup()
{
/*IO口初始化,四个按键在不输入时,下拉为低电平*/
pinMode(9, INPUT);
pinMode(10, INPUT);
pinMode(11, INPUT);
pinMode(12, INPUT);
pinMode(14, INPUT);
pinMode(17, INPUT);
CNPDAbits.CNPDA1 = 1;
CNPDBbits.CNPDB0 = 1;
CNPDBbits.CNPDB1 = 1;
CNPDBbits.CNPDB3 = 1;
//外部中断的映射
mapPps(10, PPS_IN_INT3);
mapPps(11, PPS_IN_INT1);
mapPps(14, PPS_IN_INT4);
//外部中断1,3,4设置为上升沿产生中断
INTCONCLR = 0x0000001A;//1 1010
//三个外部中断的初始化
setIntVector(_EXTERNAL_3_VECTOR, myISR_RIGHT);
setIntPriority(_EXTERNAL_3_VECTOR, 4, 1);
clearIntFlag(_EXTERNAL_3_IRQ);
setIntEnable(_EXTERNAL_3_IRQ);
setIntVector(_EXTERNAL_1_VECTOR, myISR_LEFT);
setIntPriority(_EXTERNAL_1_VECTOR, 4, 2);
clearIntFlag(_EXTERNAL_1_IRQ);
setIntEnable(_EXTERNAL_1_IRQ);
setIntVector(_EXTERNAL_4_VECTOR, myISR_UP);
setIntPriority(_EXTERNAL_4_VECTOR, 4, 3);
clearIntFlag(_EXTERNAL_4_IRQ);
setIntEnable(_EXTERNAL_4_IRQ);
//lcd初始化
lcd_init();
//游戏参数初始化
gui_set_backColor(0, 0, 0);
lcd_clearRect(0, 0, 160 - 1, 80 - 1);
gui_set_frontColor(0, 0, 255);
DrawFrame();
randomSeed(analogRead(9)); //读取Pin9的模拟电压值作为随机数种子
Next_Form = random(7);
Next_Shape = random(4);
}
void loop()
{
if (LOSE == 0)
Game();
}
Arduino制作俄罗斯方块小游戏(三)程序源码
最新推荐文章于 2022-10-28 10:56:39 发布