Game source

This commit is contained in:
kg 2021-02-06 08:39:23 +01:00
parent a8107ec957
commit 1d3ef8c775
1 changed files with 297 additions and 0 deletions

297
tris.ino Normal file
View File

@ -0,0 +1,297 @@
#include <SPI.h>
#include <Encoder.h>
const uint8_t CS = 10;
const uint8_t SEGMENTS = 4;
const uint32_t SPICLOCK = 200000;
const uint8_t SPIBITORDER = MSBFIRST;
const uint8_t SPIDATAMODE = SPI_MODE0;
const static uint16_t ENABLE = 0x0C00;
const static uint16_t TEST = 0x0F00;
const static uint16_t INTENSITY = 0x0A00;
const static uint16_t SCAN_LIMIT = 0x0B00;
const static uint16_t DECODE_MODE = 0x0900;
const static uint8_t P1RA = 2;
const static uint8_t P1RB = 4;
const static uint8_t P1B = 6;
const static uint8_t P2RA = 3;
const static uint8_t P2RB = 5;
const static uint8_t P2B = 7;
const static uint8_t SPEAKER = 8;
const static uint8_t blocks=9;
// 0 row0 , 1, row1, height, width
const static uint8_t blockdata[4][9] = {{ 0b11 , 0b11 , 0b10 , 0b01 , 0b01, 0b11 , 0b11 , 0b10 , 0b01},
{ 0b10 , 0b01 , 0b11 , 0b11 , 0b01, 0b00 , 0b11 , 0b01 , 0b10},
{ 2 , 2 , 2 , 2 , 1 , 2 , 2 , 2 , 2 },
{ 2 , 2 , 2 , 2 , 2 , 1 , 2 , 2 , 2 }};
const static uint8_t logo[32]={ 15,31,24,31,15,1,31,31, 153,153,25,25,152,129,153,24, 152,152,152,248,248,152,249,249, 96,96,96,96,96,96,248,248 };
const static uint8_t winnerlogo[2][3][32]={
{
{146,36,73,146,146,73,36,146 ,70,150,38,70,71,39,150,70, 102,102,102,102,102,224,230,102, 99,119,127,107,99,99,99,99},
{36,73,146,36,36,146,73,36 ,150,38,70,150,151,71,38,150, 102,102,102,102,102,224,230,102, 99,119,127,107,99,99,99,99},
{73,146,36,73,73,36,146,73 ,38,70,150,38,39,151,70,38, 102,102,102,102,102,224,230,102, 99,119,127,107,99,99,99,99}
},
{
{204,204,204,204,236,252,220,204 ,204,206,207,205,204,12,204,204, 98,233,228,98,98,100,105,98, 73,36,146,73,73,146,36,73},
{204,204,204,204,236,252,220,204 ,204,206,207,205,204,12,204,204, 105,228,226,105,105,98,100,105, 36,146,73,36,36,73,146,36},
{204,204,204,204,236,252,220,204 ,204,206,207,205,204,12,204,204, 100,226,233,100,100,105,98,100, 146,73,36,146,146,36,73,146}
}
};
uint8_t playfield[2][16];
uint8_t shadowplayfield[2][16];
uint8_t framebuffer[32];
// game settings
uint8_t SOUND=1; // sound on 1 , sound off 0
uint16_t FALLDELAY=500; // delay in ms
uint16_t DROPDELAY=50; // delay in ms
uint8_t MAXROW=10; // max row of random pixel
Encoder P1(P1RA,P1RB);
Encoder P2(P2RA,P2RB);
void sendcommand(uint16_t command) {
SPI.beginTransaction(SPISettings(SPICLOCK,SPIBITORDER,SPIDATAMODE));
digitalWrite(CS, 0);
//send the same command to all segments
for (uint8_t i = 0; i < SEGMENTS; ++i) {
SPI.transfer16(command);
}
digitalWrite(CS, 1);
SPI.endTransaction();
}
void renderframebuffer(void) {
uint8_t buffer[64];
uint16_t cm;
for (uint8_t j = 0 ; j < 8 ; j++){
SPI.beginTransaction(SPISettings(SPICLOCK,SPIBITORDER,SPIDATAMODE));
digitalWrite(CS, 0);
for (uint8_t i = 0; i < SEGMENTS; ++i) {
cm=((j+1)<<8)|framebuffer[i*8+j];
SPI.transfer16( cm);
}
digitalWrite(CS, 1);
SPI.endTransaction();
}
}
void prepareframebuffer(void) {
for(uint8_t i=0; i<8;i++){
framebuffer[i]= (((shadowplayfield[0][0]&(1<<i))&&(1<<i))<<7) |
(((shadowplayfield[0][1]&(1<<i))&&(1<<i))<<6) |
(((shadowplayfield[0][2]&(1<<i))&&(1<<i))<<5) |
(((shadowplayfield[0][3]&(1<<i))&&(1<<i))<<4) |
(((shadowplayfield[0][4]&(1<<i))&&(1<<i))<<3) |
(((shadowplayfield[0][5]&(1<<i))&&(1<<i))<<2) |
(((shadowplayfield[0][6]&(1<<i))&&(1<<i))<<1) |
(((shadowplayfield[0][7]&(1<<i))&&(1<<i))<<0);
framebuffer[i+8]= (((shadowplayfield[0][8]&(1<<i))&&(1<<i))<<7) |
(((shadowplayfield[0][9]&(1<<i))&&(1<<i))<<6) |
(((shadowplayfield[0][10]&(1<<i))&&(1<<i))<<5) |
(((shadowplayfield[0][11]&(1<<i))&&(1<<i))<<4) |
(((shadowplayfield[0][12]&(1<<i))&&(1<<i))<<3) |
(((shadowplayfield[0][13]&(1<<i))&&(1<<i))<<2) |
(((shadowplayfield[0][14]&(1<<i))&&(1<<i))<<1) |
(((shadowplayfield[0][15]&(1<<i))&&(1<<i))<<0);
framebuffer[23-i]= (((shadowplayfield[1][15]&(1<<i))&&(1<<i))<<7) |
(((shadowplayfield[1][14]&(1<<i))&&(1<<i))<<6) |
(((shadowplayfield[1][13]&(1<<i))&&(1<<i))<<5) |
(((shadowplayfield[1][12]&(1<<i))&&(1<<i))<<4) |
(((shadowplayfield[1][11]&(1<<i))&&(1<<i))<<3) |
(((shadowplayfield[1][10]&(1<<i))&&(1<<i))<<2) |
(((shadowplayfield[1][9]&(1<<i))&&(1<<i))<<1) |
(((shadowplayfield[1][8]&(1<<i))&&(1<<i))<<0);
framebuffer[31-i]= (((shadowplayfield[1][7]&(1<<i))&&(1<<i))<<7) |
(((shadowplayfield[1][6]&(1<<i))&&(1<<i))<<6) |
(((shadowplayfield[1][5]&(1<<i))&&(1<<i))<<5) |
(((shadowplayfield[1][4]&(1<<i))&&(1<<i))<<4) |
(((shadowplayfield[1][3]&(1<<i))&&(1<<i))<<3) |
(((shadowplayfield[1][2]&(1<<i))&&(1<<i))<<2) |
(((shadowplayfield[1][1]&(1<<i))&&(1<<i))<<1) |
(((shadowplayfield[1][0]&(1<<i))&&(1<<i))<<0);
}
}
void intro(void) {
for(uint8_t i=0;i<32;i++){
framebuffer[i]=logo[i];
}
renderframebuffer();
while(digitalRead(P1B)==1 || digitalRead(P2B)==1 ){}
for(uint8_t i=0;i<40;i++){
tone(SPEAKER,440+i*10,30);
delay(30);
}
}
byte game(void) {
uint8_t winner=0;
uint8_t player=0;
uint8_t pxc[2]={3,3}; // Xpos current
uint8_t pxn[2]={3,3}; // Xpos new
int8_t py[2]={15,15}; // Ypos
uint16_t pdd[2]={FALLDELAY,FALLDELAY}; // Dropdelay
uint8_t pbt[2]={random(blocks),random(blocks)}; // Blocktype
uint32_t prevmillis[2] = {millis(),millis()};
uint8_t i,j,rx,ry;
// clean the playfields
for(i=0;i<16;i++){
shadowplayfield[0][i]=0;
playfield[0][i]=0;
shadowplayfield[1][i]=0;
playfield[1][i]=0;
}
while(winner==0){
// update shadowplayfield
for(i=0;i<16;i++){
shadowplayfield[0][i]=playfield[0][i];
shadowplayfield[1][i]=playfield[1][i];
}
// X movement
pxc[player]=pxn[player];
if(player==0) {
if(P1.read()>2){
if(pxn[player]<8-blockdata[2][pbt[player]]) pxn[player]++;
if (SOUND==1) tone(SPEAKER,880,10);
P1.write(0);
}
if(P1.read()<-2){
if(pxn[player]>0) pxn[player]--;
if (SOUND==1) tone(SPEAKER,880,10);
P1.write(0);
}
} else {
if(P2.read()>2){
if(pxn[player]<8-blockdata[2][pbt[player]]) pxn[player]++;
if (SOUND==1) tone(SPEAKER,987,10);
P2.write(0);
}
if(P2.read()<-2){
if(pxn[player]>0) pxn[player]--;
if (SOUND==1) tone(SPEAKER,987,10);
P2.write(0);
}
}
if( ( (playfield[player][py[player]] & (blockdata[0][pbt[player]]<<pxn[player])) !=0 ) ||
( (playfield[player][py[player]-1] & (blockdata[1][pbt[player]]<<pxn[player])) !=0 ) ) {
pxn[player]=pxc[player];
}
// button pressed
if(player==0){
if(digitalRead(P1B)==0){
pdd[player]=DROPDELAY;
if (SOUND==1) tone(SPEAKER,1046,15);
}
} else {
if(digitalRead(P2B)==0){
pdd[player]=DROPDELAY;
if (SOUND==1) tone(SPEAKER,1174,15);
}
}
// falling
if(millis()-prevmillis[player] > pdd[player]) {
if (SOUND==1 && pdd[player]==DROPDELAY) tone(SPEAKER,1318+py[player]*10,10);
if(py[player]>=blockdata[3][pbt[player]]-1) {
py[player]--;
}
// if it reaches the bottom or runs into a existing blocks.. fix the drop, and setup for a new block
if( (py[player] < blockdata[3][pbt[player]]-1) ||
( (playfield[player][py[player]] & (blockdata[0][pbt[player]]<<pxn[player])) !=0 ) ||
( (playfield[player][py[player]-1] & (blockdata[1][pbt[player]]<<pxn[player])) !=0 ) ) {
playfield[player][py[player]+1]=shadowplayfield[player][py[player]+1]|(blockdata[0][pbt[player]]<<pxn[player]);
playfield[player][py[player]] =shadowplayfield[player][py[player]]|(blockdata[1][pbt[player]]<<pxn[player]);
if(py[player]==14) winner=1;
py[player]=15;
pdd[player]=FALLDELAY;
pbt[player]=random(blocks);
pxn[player]=3;
// dropping lines
j=0;
for(i=0;i<14;i++){
if(playfield[player][i]==255){
if (SOUND==1) tone(SPEAKER,1760,15);
// other player annoyance
rx=random(8);
ry=random(MAXROW);
playfield[!player][ry]=playfield[!player][ry]^(1<<rx);
// move lines down
for(j=i;j<14;j++){
playfield[player][j]=playfield[player][j+1];
}
// reset to the previous line
i--;
}
}
}
prevmillis[player]=millis();
}
shadowplayfield[player][py[player]]=playfield[player][py[player]]|(blockdata[0][pbt[player]]<<pxn[player]);
if(blockdata[3][pbt[player]] == 2) shadowplayfield[player][py[player]-1]=playfield[player][py[player]-1]|(blockdata[1][pbt[player]]<<pxn[player]);
prepareframebuffer();
renderframebuffer();
player=!player;
}
return(player);
}
void showwinner(uint8_t winner) {
for(uint8_t k=0;k<10;k++){
for(uint8_t j=0;j<3;j++){
for(uint8_t i=0;i<32;i++){
framebuffer[i]=winnerlogo[winner][j][i];
}
renderframebuffer();
delay(200);
}
}
}
void setup() {
randomSeed(analogRead(3));
pinMode(P1B,INPUT_PULLUP);
pinMode(P2B,INPUT_PULLUP);
// init display
pinMode(CS, OUTPUT);
digitalWrite(CS, 1);
SPI.begin();
sendcommand(ENABLE|1);
sendcommand(INTENSITY|0);
sendcommand(SCAN_LIMIT|7);
sendcommand(TEST);
sendcommand(DECODE_MODE);
}
void loop() {
uint8_t winner;
intro();
winner=game();
showwinner(winner);
}