#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製作俄羅斯方塊小遊戲(三)程序源碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.