2016年4月5日 星期二

微處理器實作: AT89S52 迷你俄羅斯輪盤(電子骰子)遊戲

        既然我們會控制四個七段顯示器、按鍵,也會播放音樂,而且知道timer和中斷如何運作,那麼來製作一個小遊戲應該部會太困難吧?! 是的,集合之前練習所獲的相關知識,確實已經可以來做個遊戲試試看。

         這個遊戲很簡單,利用三個七節顯示器的六個小方格當俄羅斯輪盤,讓玩家先選擇一個方格(編號1~6),然後再用亂數讓目標方格跑動,如果目標方格和玩家選擇的方格重合,則玩家贏得此局比賽,當然選擇的時候要有按鍵音,目標方格跑動的時候要有跳格音效,中獎後也要有慶祝動畫和音樂(超級馬力歐)囉! 雖然這個遊戲很簡單,但是已經具備娛樂軟體的雛型,製作過程還蠻有樂趣的 !!! 你也可以試試看。


執行結果:



完整程式:

#include <regx52.h>
#include "music.h"

#define LED_NUM_0 0xC0
#define LED_NUM_1 0xF9
#define LED_NUM_2 0xA4
#define LED_NUM_3 0xB0
#define LED_NUM_4 0x99
#define LED_NUM_5 0x92
#define LED_NUM_6 0x82
#define LED_NUM_7 0xF8
#define LED_NUM_8 0x80
#define LED_NUM_9 0x98

#define LED_OUT P1

#define MUSIC_MAX_NUM 6

unsigned char count_10ms;
unsigned int  Tone;
unsigned char Beat;
unsigned char playNum=0;


unsigned short count2 = 10;
unsigned short count3 = 0;

unsigned int mynum2 = 0;

unsigned char myarray[4]={0xff, 0xff, 0xff, 0xff};

unsigned char music_mode=0;
unsigned char num_sel = 1;
unsigned char num_now = 1;

unsigned char SelButtonState=0;
unsigned char ButtonPressTime=0;
unsigned char LED_IN_USE=0;
unsigned char GAME_MODE=0;

unsigned char code led_show[56][5] = {
{ 255, 255, 255, 255, 10 },
{ 156, 255, 255, 255, 10 },
{ 156, 156, 255, 255, 10 },
{ 156, 156, 156, 255, 10 },
{ 156, 156, 156, 156, 10 },
{ 156, 156, 156, 128, 10 },
{ 156, 156, 128, 128, 10 },
{ 156, 128, 128, 128, 10 },
{ 128, 128, 128, 128, 10 },
{ 128, 128, 128, 128, 10 },
{ 192, 128, 128, 128, 10 },
{ 192, 192, 128, 128, 10 },
{ 192, 192, 192, 128, 10 },
{ 192, 192, 192, 192, 10 },
{ 208, 192, 192, 192, 10 },
{ 240, 192, 192, 192, 10 },
{ 244, 192, 192, 192, 10 },
{ 246, 192, 192, 192, 10 },
{ 246, 208, 192, 192, 10 },
{ 246, 240, 192, 192, 10 },
{ 246, 244, 192, 192, 10 },
{ 246, 246, 192, 192, 10 },
{ 246, 246, 208, 192, 10 },
{ 246, 246, 240, 192, 10 },
{ 246, 246, 244, 192, 10 },
{ 246, 246, 246, 192, 10 },
{ 246, 246, 246, 208, 10 },
{ 246, 246, 246, 240, 10 },
{ 246, 246, 246, 244, 10 },
{ 246, 246, 246, 246, 10 },
{ 246, 246, 246, 254, 10 },
{ 246, 246, 254, 254, 10 },
{ 246, 254, 254, 254, 10 },
{ 254, 254, 254, 254, 10 },
{ 255, 254, 254, 254, 10 },
{ 255, 255, 254, 254, 10 },
{ 255, 255, 255, 254, 10 },
{ 255, 255, 255, 255, 10 },
{ 255, 255, 255, 255, 10 },
{ 0, 255, 255, 255, 10 },
{ 0, 0, 255, 255, 10 },
{ 0, 0, 0, 255, 10 },
{ 0, 0, 0, 0, 10 },
{255,255,255,255,10},
{ 0, 0, 0, 0, 10 },
{255,255,255,255,10},
{ 0, 0, 0, 0, 10 },
{255,255,255,255,10},
{ 0, 0, 0, 0, 10 },
{255,255,255,255,10},
{ 0, 0, 0, 0, 10 },
{255,255,255,255,10},
{ 0, 0, 0, 0, 10 },
{255,255,255,255,10},
{ 0, 0, 0, 0, 10 },
{255,255,255,255,10},
};

unsigned char led_num[10] =
{
LED_NUM_0, LED_NUM_1, LED_NUM_2, LED_NUM_3, LED_NUM_4, 
LED_NUM_5, LED_NUM_6, LED_NUM_7, LED_NUM_8, LED_NUM_9
};

void my_delay_ms(unsigned int n)
{
unsigned int i, j;

for(j=0; j<n; j++)
for(i=0; i<120; i++) ; 

}

void led_write_1s(unsigned char r, unsigned char x)
{
 P3_4=1;
 switch(r)
{
case 0: P3_3 = 0; break;
case 1: P3_2 = 0; break;
case 2: P3_1 = 0; break;
case 3: P3_0 = 0; break;
default: break;
}
 LED_OUT = x;
 my_delay_ms(3);
 LED_OUT = 0xFF;
switch(r)
{
case 0: P3_3 = 1; break;
case 1: P3_2 = 1; break;
case 2: P3_1 = 1; break;
case 3: P3_0 = 1; break;
default: break;
}
P3_4=0;

}

void T0_int(void) interrupt 1
{
TL0 = (65536-10000)%256;
TH0 = (65536-10000)/256;
    count_10ms++;

if(count2 ==0 )
{
count2=10;                
    myarray[3]= ~(1<<mynum2); 
    mynum2++;

if(mynum2==6) mynum2=0;
}
else 
count2--;

count3++; // for update 7-seg-display
    
  if(SelButtonState==1)
{
if(ButtonPressTime<40)  
ButtonPressTime++;
else
{
ButtonPressTime=0;
SelButtonState=0;
num_sel++;
if(num_sel==(MUSIC_MAX_NUM+1)) 
num_sel=1;
}
}
}

void T1_int(void) interrupt 3
{
TH1=Tone/256;
  TL1=Tone%256;
 
if(Tone!=0xff && Tone!=0x00 ) //0xff is no_sound, 0x00 is the end
P2_0=~P2_0;
}


void EX0_int(void) interrupt 0
{
if(P3_4 == 0)
GAME_MODE=1;
}

void EX1_int(void) interrupt 2
{
if(P3_4 == 0 && GAME_MODE ==0)
SelButtonState=1;  //marking for the button is pressed
}

void timer0_init(void)
{
TMOD = (TMOD&0xf0) | 0x01; 
TL0 = (65536-10000) % 256;  
TH0 = (65536-10000) / 256;
ET0 = 1; 
TR0 = 1;
}

void timer1_init(void)
{
TMOD = (TMOD&0x0f) | 0x10;  
TL1 = (65536-10000) % 256; 
TH1 = (65536-10000) / 256; 
ET1 = 1; 
TR1 = 1;
}

void sys_init(void)
{

P2_0=1;
myarray[3] = 0xff;
playNum=0;
count_10ms = 0;

EX0=1;
IT0=1;
EX1=1;
IT1=1;
P3_4 = 0;
EA = 1;
timer0_init(); 
timer1_init();

}

void set_dice_num(unsigned char x, unsigned char user_num)
{
myarray[0] = 0xff;
myarray[1] = 0xff;
myarray[2] = 0xff;

switch(x)
{
case 1: myarray[2]=0x9c; break;
case 2: myarray[1]=0x9c; break;
case 3: myarray[0]=0x9c; break;
case 4: myarray[0]=0xa3; break;
case 5: myarray[1]=0xa3; break;
case 6: myarray[2]=0xa3; break;
default: break;
}
switch(user_num)
{
case 1: myarray[2]&=0x9c; break;
case 2: myarray[1]&=0x9c; break;
case 3: myarray[0]&=0x9c; break;
case 4: myarray[0]&=0xa3; break;
case 5: myarray[1]&=0xa3; break;
case 6: myarray[2]&=0xa3; break;
default: break;
}
}

void update_dice_display(unsigned char *a)
{

P3_4=1;
led_write_1s(0, a[0]);
led_write_1s(1, a[1]);
led_write_1s(2, a[2]);
P3_4=0;

}

void play_tone(unsigned int *tone_table, unsigned char *beat_table, 
unsigned short t, unsigned char mode)
{
playNum=0;
count_10ms=0;
Tone = tone_table[playNum];
Beat = beat_table[playNum];
TR1=1;
while(playNum < t)
{
if(count_10ms>Beat)
{
TR1=0;
playNum++;
count_10ms=0;
Tone=tone_table[playNum];
Beat=beat_table[playNum];
TH1=Tone/256;
TL1=Tone%256;
          TR1=1;
}
if(mode==1)
{

P3_4=1;
led_write_1s(3, led_show[playNum][0]);
led_write_1s(2, led_show[playNum][1]);
led_write_1s(1, led_show[playNum][2]);
led_write_1s(0, led_show[playNum][3]);
P3_4=0;
}
//else // 如果你不喜歡閃爍的跑格畫面,請把這行打開
   //{                                                         // 如果你不喜歡閃爍的跑格畫面,請把這行打開
   //   led_write_1s(3,led_num[num_sel]);  // 如果你不喜歡閃爍的跑格畫面,請把這行打開
   //   update_dice_display(myarray);        // 如果你不喜歡閃爍的跑格畫面,請把這行打開   
   //}                                                        // 如果你不喜歡閃爍的跑格畫面,請把這行打開


}
TR1=0;
}

main()
{
unsigned char num_result=1;
unsigned int game_speed_count=0;
unsigned int dice_run_num; 

sys_init();
set_dice_num(num_now, num_sel);
dice_run_num= TH0%7+TL0%13+(TH0+TL0)%23+19;
while(1)
{

if(GAME_MODE==1)
{  
if(game_speed_count==3)
{
set_dice_num(num_result, num_sel);
play_tone(ToneTable_3, BeatTable_3, 1, 0);
dice_run_num--;
if(dice_run_num == 0) 
{
if(num_result==num_sel) //Bingo!!!
{
play_tone(ToneTable_1, BeatTable_1, 56, 1);
}

GAME_MODE = 0;
game_speed_count=0;
dice_run_num=TH0%7+TL0%13+(TH0+TL0)%23+19;
}
else
{
num_result++; 
if(num_result==7) num_result=1;
}
game_speed_count=0;
}
game_speed_count++;
}
 else //GAME_MODE == 0
{
if(num_now != num_sel)
{
num_now = num_sel;
play_tone(ToneTable_2, BeatTable_2, 1, 0);
set_dice_num(num_sel, num_result);
}
}
led_write_1s(3,led_num[num_sel]);
 update_dice_display(myarray);
}
}

music.h 的內容:

/* --------------------- 超級馬利歐-----------------------------*/
unsigned int code ToneTable_1[]=
{
65347, 65347,   255, 65347,   255, 65298, 65347,   255, 65377,   255, 
  255,   255, 65218,   255,   255,   255, 65298,   255,   255, 65218, 
  255,   255, 65157,   255,   255, 65252,   255, 65283,   255, 65268, 
65252,   255, 65218, 65347, 65377, 65394,   255, 65358, 65377,   255, 
65347,   255, 65298, 65324, 65283,   255,   255, 65298,   255,   255, 
65218,   255,   255, 65157,   255,   255, 65252,   255, 65283,   255, 
65268, 65252,   255, 65218, 65347, 65377, 65394,   255, 65358, 65377, 
  255, 65347,   255, 65298, 65324, 65283,   255,   255, 0
};

unsigned char code BeatTable_1[]=
{
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
16, 16, 22, 22, 22, 16, 16, 16, 16, 16, 
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
16, 16, 16, 22, 22, 22, 16, 16, 16, 16, 
16, 16, 16, 16, 16, 16, 16, 16, 
};

unsigned int code ToneTable_2[]=
{
63628
};

unsigned char code BeatTable_2[]=
{
16, 
};

unsigned int code ToneTable_3[]=
{64778};

unsigned char code BeatTable_3[]=
{7};

沒有留言:

張貼留言