⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ring.cpp

📁 c语言源玛,扫描的游戏代码,攻大家看.多体意见
💻 CPP
字号:

#include "defines.h"
#include "Ring.h"

/*
 铃声代码表:
 255: 音乐结束,重新演奏
 254: 循环开始
 253: 循环结束
 252: 调用子串,后接子串地址
 251: 子串返回
 250: 音乐跳转,后接跳转地址
 >128:设置音长,音长=(该数-128)/16 (拍)
 128: 音乐结束,不重新演奏
 <128:设置音符,高4位选择哪组音,低4位0-C分别代表0,1,1#,2,2#,3,4,4#,5,5#,6,6#,7
                                                 1 2  3 4  5 6 7  8 9  a b  c
      例:21h代表主音1
*/

const UCHAR *CRing::m_cur_addr; //当前乐谱在内存的位置
UCHAR CRing::m_cur_length;      //当前音长
UCHAR CRing::m_note_length;     //乐谱最后一次设置的音长
UCHAR CRing::m_stack_deep;      //栈的位置
UCHAR CRing::m_done_deep;       //辅助栈的位置
UCHAR CRing::m_loop_stack[10];  //循环栈
UCHAR CRing::m_loop_done[10];   //循环辅助栈
UCHAR CRing::m_cur_index;       //乐谱当前位置
USHORT CRing::m_time;           //已经播放的节拍数

//嘀嘀嘀嘀----嘀嘀嘀嘀----
const UCHAR music0[] = {128+1, 254, 0x31, 0, 0x31, 0, 253, 128+8 , 0, 255};
//1, 2, 3, 4, 5, 6, 7
const UCHAR music1[] = {128+16, 254,
                        0x21, 0x23, 0x25, 0x26, 0x28, 0x2a, 0x2c,
                        253, 255};
const UCHAR *MUSIC[] = {music0, music1};

#define SetTimer1freq(freq)\
{\
    OCR1A = 1000000 / (2 * freq);\
    TCNT1 = 0xffff - (1000000 / (2 * freq)) +1;\
}
#define isTimer1Busy (TCCR1B & 0x07)
#define OpenTimer1() {TCCR1A = 0x40; TCCR1B = 9;}
#define CloseTimer1() {TCCR1A = 0x00; TCCR1B = 0; PORTB &= ~2;}

// 1/16节拍
void CRing::OnTick()
{
    if(!(m_time || m_cur_addr)) return;
    if(!m_cur_addr){//现在是在Beep
        if(!--m_time)
            CloseTimer1();
        return;
    }
    if(++m_time == 16 * 60){
        //播放了一分钟后自动停止
        StopRing();
        return;
    }
    if(--m_cur_length) return;
    for(;;){
      UCHAR note = m_cur_addr[m_cur_index++];
        if(note == 254){//循环开始
            m_loop_done[m_done_deep++] = 0;//第一遍播放
            m_loop_stack[m_stack_deep++] = m_cur_index;
        }else if(note == 253){//循环结束
            if(m_loop_done[m_done_deep-1]){
                //第二遍播放完毕
                m_done_deep--;
            }else{
                m_loop_done[m_done_deep-1] = 1; //第二遍播放
                m_cur_index = m_loop_stack[--m_stack_deep];
            }
        }else if(note == 252){//调用子串
            m_loop_stack[m_stack_deep++] = m_cur_index + 1;
            m_cur_index = m_cur_addr[m_cur_index];
        }else if(note == 251){//子串返回
            m_cur_index = m_loop_stack[--m_stack_deep];
        }else if(note == 250){//音乐跳转
            m_cur_index = m_cur_addr[m_cur_index];
        }else if(note == 255){
            m_cur_index   = 0;
            m_stack_deep  = 0;
            m_done_deep   = 0;
        }else if(note == 128){//停止
            StopRing();
            break;
        }else if(note < 128){//真正的音符
            SetNote(note);
            m_cur_length = m_note_length;
            break;
        }else if(note >  128){//音长
            m_note_length = note & 0x7f;
        }
    }
}

//播放铃声
void CRing::Play(UCHAR index, UCHAR repeat)
{
    m_cur_addr = MUSIC[index];//当前乐谱在内存的位置
    m_cur_length  = 1;        //当前音长
    m_note_length = 0;        //乐谱最后一次设置的音长
    m_stack_deep  = 0;        //栈的位置
    m_done_deep   = 0;        //辅助栈的位置
    m_cur_index   = 0;        //乐谱当前位置
    OpenTimer1();
    OnTick();
    m_time = 0;               //已经播放的节拍数
}

void CRing::Beep(USHORT freq, UCHAR note16)
{
    if(!isTimer1Busy){
        SetTimer1freq(freq);
        OpenTimer1();
        m_time = note16;
        m_cur_addr = 0;
    }
}

void CRing::SetNote(UCHAR note)
{
    static USHORT delay[]={0,
                           3817, 3610, 3401, 3215,
                           3030, 2865, 2703, 2551,
                           2410, 2273, 2146, 2024};
    if(note & 0x0f){
        if(!isTimer1Busy) OpenTimer1();
        USHORT data = delay[note & 0x0f];
        data >>= (note >> 4);
        OCR1A = data;
        TCNT1 = 1 + ~data;
    }else{
        //不要忘记,乐谱里还有休止符
        TCCR1B = 0;
        PORTB &= ~2; //Timer停止的时候,PB1的电平时随机的,为了省电,把它置低
    }
}

UCHAR CRing::GetCount()
{
    return sizeof(MUSIC) / sizeof(UCHAR*);
}

void CRing::StopRing()
{
    CloseTimer1();
    m_cur_addr = NULL;
    m_time = 0;
}

UCHAR CRing::IsPlayingRing()
{
    return m_cur_addr != NULL;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -