欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
基于單片機的俄羅斯方塊游戲課程設計
[打印本頁]
作者:
qq496640511
時間:
2017-10-27 20:38
標題:
基于單片機的俄羅斯方塊游戲課程設計
/*基于MSP430F5529俄羅斯方塊游戲程序*/
//作者: 詹磊
//功能: 基于MSP430F5529俄羅斯方塊游戲程序
//說明: 運行環(huán)境:TI官方MSP-EXP5529開發(fā)板(外接4個帶上拉電阻獨立按鍵)
// 非原創(chuàng),思路是從51單片機上移植過來的
// 底層液晶驅(qū)動是TI官方提供的LCD API
// 游戲算法部分的底層程序多處已經(jīng)修改,與原版會有較大的差別
//版本: 測試版 V1.0(基本能流暢運行,但需要進一步的美化和優(yōu)化)
#include "MSP430F5529.h"
#include "LCD_102x64.h"
#include "main.h"
#include "Key.h"
#define MAXHANG 20 //游戲顯示行數(shù)
#define MAXLIE 16 //游戲顯示列數(shù)
#define MapWide 48 //地圖寬
#define MapHigh 60 //地圖高
#define ON 0
#define OFF 1
#define BIT(n) (1<<(n))
volatile uint cubeMap[MAXHANG]; //地圖顯示存存
typedef struct{
uchar const * box; //方塊圖形字模數(shù)據(jù)指針
uchar cube : 4; //方塊形態(tài)(占用4個位域)
uchar state : 4; //方塊狀態(tài)(占用4個位域)
char row; //方塊所在行
char column; //方塊所在列
} block;
block this;
uchar liang=1;
uchar Speed=1,Score=0;
uint timeA=0;
uchar downflag=0;
uchar randomNumber=0;
const uchar cube[]=
{
/* ■
■■■
*/
0,4,0xe,0, 0,2,6,2, 0,7,2,0, 4,6,4,0,
/*■
■■■
*/
0,8,0xe,0, 0,4,4,0xc, 0,0,0xe,2, 0,6,4,4,
/*■■■
■
*/
0,0xe,8,0, 0,4,4,6, 0,1,7,0, 6,2,2,0,
/*■■
■■
*/
0,0xc,6,0, 0,2,6,4, 0,6,3,0, 2,6,4,0,
/* ■■
■■
*/
0,6,0xc,0, 0,4,6,2, 0,3,6,0, 4,6,2,0,
/*■■■■
*/
0,0xf,0,0, 4,4,4,4, 0,0,0xf,0, 2,2,2,2,
/*■■
■■
*/
0,6,6,0, 0,6,6,0, 0,6,6,0, 0,6,6,0
};
void delay_ms(uint z)//毫秒級延時函數(shù)
{
uint i,m;
for(i=z;i>0;i--)
for(m=4500;m>0;m--)
{
_NOP();
}
}
//-------------------------------------------//
//函數(shù)名:八位LED燈控制函數(shù)
//入口:Number:Number哪位為一則哪位LED點亮
//出口:Void
//功能:
//-------------------------------------------//
void DigitalLedControl(uchar Number)
{
if(Number&BIT7)
P1OUT|=BIT0;
else
P1OUT&=~BIT0;
if(Number&BIT6)
P8OUT|=BIT1;
else
P8OUT&=~BIT1;
if(Number&BIT5)
P8OUT|=BIT2;
else
P8OUT&=~BIT2;
if(Number&BIT4)
P1OUT|=BIT1;
else
P1OUT&=~BIT1;
if(Number&BIT3)
P1OUT|=BIT2;
else
P1OUT&=~BIT2;
if(Number&BIT2)
P1OUT|=BIT3;
else
P1OUT&=~BIT3;
if(Number&BIT1)
P1OUT|=BIT4;
else
P1OUT&=~BIT4;
if(Number&BIT0)
P1OUT|=BIT5;
else
P1OUT&=~BIT5;
}
//-------------------------------------------//
//函數(shù)名:顯存清空函數(shù)
//入口:Void
//出口:Void
//功能:清空顯存
//-------------------------------------------//
void DisplayRamClear()
{
uchar i;
for(i=0;i<20;i++)
{
cubeMap
=0x0;
}
}
//-------------------------------------------//
//函數(shù)名:兩位十進制數(shù)字顯示函數(shù)
//入口: Row:顯示的行數(shù)
// Column:顯示的列數(shù)
// Number:需要顯示的數(shù)字<100 && >=0
//出口:Void
//功能:
//-------------------------------------------//
void Number2BitDisplay(uchar Row,uchar Column,uchar Number)
{
uchar tempShi,tempGe;
tempShi=Number/10;
tempGe=Number%10;
Dogs102x6_charDraw(Row, Column,tempShi+'0',ON);
Dogs102x6_charDraw(Row, Column+6,tempGe+'0',ON);
}
//-------------------------------------------//
//函數(shù)名:游戲背景函數(shù)
//入口:Void
//出口:Void
//功能:繪制游戲背景地圖
//-------------------------------------------//
void GameBackground()
{
uchar i;
for(i=0;i<MapHigh+1;i++)
{
Dogs102x6_pixelDraw(0, i, ON);
Dogs102x6_pixelDraw(MapWide+1, i, ON);
}
for(i=0;i<MapWide+2;i++)
{
Dogs102x6_pixelDraw(i, 0, ON);
Dogs102x6_pixelDraw(i, MapHigh+1, ON);
}
DisplayRamClear();
Dogs102x6_stringDraw(3, 10, "START",ON);
Dogs102x6_stringDraw(1, 51, "NEXT:",ON);
Dogs102x6_stringDraw(3, 51, "SPEED:--",ON);
Dogs102x6_stringDraw(5, 51, "SCORE:--",ON);
Number2BitDisplay(3,87,Speed);
Number2BitDisplay(5,87,Score);
}
//-------------------------------------------//
//函數(shù)名:游戲Map清空
//入口:Void
//出口:Void
//功能:清空游戲背景地圖(不清空顯存)
//-------------------------------------------//
void GameMapClear()
{
uchar i,j;
for(i=0;i<MapHigh;i++)
{
for(j=0;j<MapWide;j++)
{
Dogs102x6_pixelDraw(j+1, i+1, OFF);
}
}
}
//-------------------------------------------//
//函數(shù)名:系統(tǒng)初始化
//入口:Void
//出口:Void
//功能:
//-------------------------------------------//
void SystemInit()
{
WDTCTL = WDTPW + WDTHOLD;
P8DIR|=BIT1+BIT2;
P8OUT|=BIT1+BIT2;
P1DIR|=BIT0+BIT1+BIT2+BIT3+BIT4+BIT5;
P1OUT|=BIT0+BIT1+BIT2+BIT3+BIT4+BIT5;
InitKey();
UCSCTL3 = SELREF_2; // Set DCO FLL reference = REFO
UCSCTL4 |= SELA_2; // Set ACLK = REFO
__bis_SR_register(SCG0); // Disable the FLL control loop
UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx
UCSCTL1 = DCORSEL_7; // Select DCO range 50MHz operation
UCSCTL2 = FLLD_1 + 609; // Set DCO Multiplier for 25MHz(這里設置為20MHz適應液晶的SPI通信)
// (N + 1) * FLLRef = Fdco
// (762 + 1) * 32768 = 25MHz
// Set FLL Div = fDCOCLK/2
__bic_SR_register(SCG0); // Enable the FLL control loop
TA1CCTL0 = CCIE; // CCR0 interrupt enabled
TA1CCR0 = 328-1;
TA1CTL = TASSEL_1 + MC_1 + TACLR; // ACLK, upmode, clear TAR
_BIS_SR(GIE);
Dogs102x6_init();
Dogs102x6_clearScreen();
Dogs102x6_backlightInit();
Dogs102x6_setContrast(11);
Dogs102x6_setBacklight(liang);
}
//-------------------------------------------//
//函數(shù)名:3x3點顯示函數(shù)
//入口: x:x軸坐標
// y:y軸坐標
// mode:ON 打點;OFF 消點
//出口:Void
//功能:
//-------------------------------------------//
void Display3x3Pixels(uchar x,uchar y,uchar mode)
{
x=3*x+1;
y=3*y+1;
Dogs102x6_pixelDraw(x, y, mode);
Dogs102x6_pixelDraw(x+1, y, mode);
Dogs102x6_pixelDraw(x+2, y, mode);
Dogs102x6_pixelDraw(x, y+1, mode);
Dogs102x6_pixelDraw(x+1, y+1, mode);
Dogs102x6_pixelDraw(x+2, y+1, mode);
Dogs102x6_pixelDraw(x, y+2, mode);
Dogs102x6_pixelDraw(x+1, y+2, mode);
Dogs102x6_pixelDraw(x+2, y+2, mode);
}
//-------------------------------------------//
//函數(shù)名:顯示像素點更改函數(shù)
//入口: Row:行數(shù)
// Column:列數(shù)
// mode:ON 打點;OFF 消點
//出口:Void
//功能:
//-------------------------------------------//
void ChangeRamBit(uchar Row,uchar Column,uchar mode)
{
uint tempData;
tempData=(0x8000>>(Column%16));
if(mode==ON)
cubeMap[Row]|=tempData;
else
cubeMap[Row]&=~tempData;
}
//-------------------------------------------//
//函數(shù)名:讀取某個顯示像素點位值函數(shù)
//入口: Row:行數(shù)
// Column:列數(shù)
//出口:uchar 1:所選點位1,0:所選的點位0
//功能:
//-------------------------------------------//
uchar ReadDisplayRamBit(uchar Row,uchar Column)
{
uint tempData;
tempData=(0x8000>>(Column%16));
if(cubeMap[Row]&tempData)
return 1;
else
return 0;
}
//-------------------------------------------//
//函數(shù)名:下一個方塊顯示函數(shù)
//入口: x:x軸坐標
// y:y軸坐標
// *p:圖形字模數(shù)據(jù)指針
//出口:Void
//功能:
//-------------------------------------------//
void showNextCube(uchar const * p,uchar x,uchar y)
#define NexPoinX 27 //下一個圖形顯示的X坐標
#define NexPoinY 2 //下一個圖形顯示的Y坐標
{
uchar i,j,temp;
for(i=0;i<4;i++)
{
temp=0x08;
for(j=0;j<4;j++)
{
if(p
& temp)
Display3x3Pixels(x+j,y+i,ON);
else
Display3x3Pixels(x+j,y+i,OFF);
temp>>=1;
}
}
}
//-------------------------------------------//
//函數(shù)名:顯示函數(shù)
//入口:Void
//出口:Void
//功能:將顯存的內(nèi)容寫入顯示器顯示
//-------------------------------------------//
void showCubeMap(void)
{
uchar hang,lie;
for(hang=0;hang<MAXHANG;hang++)
{
if(cubeMap[hang]!=0) //跳過某行全為零的地方
for(lie=0;lie<MAXLIE;lie++)
{
if(cubeMap[hang]&(0x8000>>(lie%16)))
Display3x3Pixels(lie,hang,ON);
}
}
}
//-------------------------------------------//
//函數(shù)名:產(chǎn)生新方塊函數(shù)
//入口:Void
//出口:Void
//功能:
//-------------------------------------------//
void createCube(void)
{
static uchar next=0;
this.cube=next;
next=randomNumber%7; //產(chǎn)生隨機數(shù)
this.row=0; //初始行為0
this.column=6; //初始列為6
this.state=0; //初始狀態(tài)為0
this.box=cube+16*this.cube; //設定方塊指針起始地址
showNextCube(cube+16*next,NexPoinX,NexPoinY); //提示區(qū)顯示下一個方塊
timeA=0;
downflag=0;
}
//-------------------------------------------//
//函數(shù)名:寫顯存函數(shù)
//入口:mode:ON 打點;OFF 消點
//出口:Void
//功能:將數(shù)據(jù)寫入顯存,同時寫入顯示器顯示
//-------------------------------------------//
void writeCubeToMap(uchar mode)
{
uchar tempData,tempRow,tempColumn,i,j,k=0;
for(i=0;i<4;i++)
{
tempData=this.box
;
if(tempData==0)
continue;
for(j=0;j<4;j++)
{
if(tempData&0x08)
{
tempRow=this.row+k;
tempColumn=this.column+j;
ChangeRamBit(tempRow,tempColumn,mode);
Display3x3Pixels(tempColumn,tempRow,mode);
}
tempData<<=1;
}
k++;
}
}
//-------------------------------------------//
//函數(shù)名:方塊邊沿檢測函數(shù)
//入口:Void
//出口:uchar 0:可以繼續(xù)移動 1:到底,停止移動
//功能:
//-------------------------------------------//
uchar checkClask(void)
{
uchar tempData,tempRow,tempColumn,i,j,k=0;
for(i=0;i<4;i++)
{
tempData=this.box
;
if(tempData==0) //跳過全為零的行
continue;
for(j=0;j<4;j++)
{
if(tempData&0x08)
{
tempRow=this.row+k;
tempColumn=this.column+j;
if (
ReadDisplayRamBit(tempRow,tempColumn) //與邊上的方塊接觸
||(tempRow>=MAXHANG) //到了最底部
||(tempColumn>=MAXLIE) //到了最右邊
||(tempColumn==255) //到了最左邊
)
return 1; //返回1,停止移動
}
tempData<<=1;
}
k++;
}
return 0; //返回0,可以繼續(xù)移動
}
//-------------------------------------------//
//函數(shù)名:地圖檢測函數(shù)
//入口:Void
//出口:Void
//功能:檢測地圖中是否有滿行,有的話就消行,加分,一定分后加速,同時刷一次屏
//-------------------------------------------//
void CheckMap()
{
uchar fullFlag=0;
static uchar tempScore=0,tempSpeed=0;
char i,j;
for(i=MAXHANG-1;i>0;i--)
{
if(cubeMap
==0xffff)
{
fullFlag++;
for(j=i;j>0;j--)
{
if(j>0)
cubeMap[j]=cubeMap[j-1];
else
cubeMap[j]=0;
}
i++;
}
}
tempScore=Score;
tempSpeed=Speed;
switch(fullFlag)
{
case 1:Score++;break;
case 2:Score+=2;break;
case 3:Score+=4;break;
case 4:Score+=6;break;
default:break;
}
if(Score>99)
{
Speed++;
if(Speed>9)
Speed=1;
Score=0;
}
if(tempScore!=Score)
Number2BitDisplay(5,87,Score);
if(tempSpeed!=Speed)
Number2BitDisplay(3,87,Speed);
if(fullFlag)
{
GameMapClear();
showCubeMap();
}
}
//-------------------------------------------//
//函數(shù)名:方塊左移函數(shù)
//入口:Void
//出口:Void
//功能:
//-------------------------------------------//
void moveLeft(void)
{
writeCubeToMap(OFF);
this.column--;
if(checkClask())
this.column++;
writeCubeToMap(ON);
}
//-------------------------------------------//
//函數(shù)名:方塊右移函數(shù)
//入口:Void
//出口:Void
//功能:
//-------------------------------------------//
void moveRigh(void)
{
writeCubeToMap(OFF);
this.column++;
if(checkClask())
this.column--;
writeCubeToMap(ON);
}
//-------------------------------------------//
//函數(shù)名:方塊下移函數(shù)
//入口:Void
//出口:uchar 到底返回1,否則返回0;
//功能:
//-------------------------------------------//
uchar moveDown(void)
{
writeCubeToMap(OFF);
this.row++;
if(checkClask()) //到底
{
this.row--;
writeCubeToMap(ON);
CheckMap(); //是否消行
return 1;
}
else
{
writeCubeToMap(ON);
return 0;
}
}
//-------------------------------------------//
//函數(shù)名:方塊翻轉(zhuǎn)函數(shù)
//入口:Void
//出口:Void
//功能:
//-------------------------------------------//
void cubeRotation(void)
{
uchar temp;
temp=this.state;
writeCubeToMap(OFF);
this.state=++this.state%4;
this.box=cube+16*this.cube+4*this.state;
if(checkClask())
{
this.state=temp;
this.box=cube+16*this.cube+4*this.state;
}
writeCubeToMap(ON);
}
//-------------------------------------------//
//函數(shù)名:俄羅斯方塊結(jié)束界面函數(shù)
//入口:Void
//出口:Void
//功能:
//-------------------------------------------//
void TetrisGameOver()
{
DisplayRamClear();
GameMapClear();
Score=0;
Speed=1;
Number2BitDisplay(5,87,Score);
Number2BitDisplay(3,87,Speed);
Dogs102x6_stringDraw(3, 13, "GAME",ON);
Dogs102x6_stringDraw(4, 13, "OVER",ON);
}
//-------------------------------------------//
//函數(shù)名:俄羅斯方塊游戲運行函數(shù)
//入口:Void
//出口:Void
//功能:不阻塞CPU
//-------------------------------------------//
void TetrisGame()
{
uchar temp=0;
static uchar Flag=0;
if(Flag==0)
{
createCube();
if(checkClask())
{
TetrisGameOver();
delay_ms(1000);
GameMapClear();
}
else
writeCubeToMap(ON);
Flag=1;
}
if(downflag&&Flag)
{
downflag=0;
if(moveDown())
{
Flag=0;
}
}
temp=GetKey();
switch(temp)
{
case KeyUP:cubeRotation();DigitalLedControl(0);
break;
case KeyDOWN:while(moveDown()==0);Flag=0;DigitalLedControl(1);
break;
case KeyLEFT:moveLeft();DigitalLedControl(2);
break;
case KeyRIGHT:moveRigh();DigitalLedControl(3);
break;
case KeyBACK:DigitalLedControl(4);liang=++liang%12;Dogs102x6_setBacklight(liang);
break;
case KeyMEU:DigitalLedControl(5);
break;
case 0:
break;
default:
break;
}
}
void main(void)
{
SystemInit();
GameBackground();
DisplayRamClear();
GameMapClear();
showCubeMap();
while(1)
{
TetrisGame();
}
}
#pragma vector=TIMER1_A0_VECTOR
__interrupt void TIMER1_A0_ISR(void)
{
randomNumber=++randomNumber%100;
if(downflag==0)
timeA++;
if(timeA==(10-Speed)*10)
{
timeA=0;
downflag=1;
}
}
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1