《咸鱼的救赎》代码总结

剧情一帧

看完了了童晶老师的《做游戏,学编程》网课,自己尝试着用C做了一个小游戏,主要实现了三个功能:galgame幻灯片剧情切换,打飞机小游戏,找不同游戏。利用了easyX的交互和图形界面功能。下面对代码实现进行总结,以免遗忘。
github:(https://github.com/iMaxmoe/game_saultyFish)

幻灯片切换

由于对easyX的函数并不熟悉,这里使用的是笨办法,通过加载新图片来实现剧情切换。这种方法适用于于小体量的galgame,但一旦文本量大了,就会造成不小的负担。更优解还是加载一张背景图片,变更文本框。

  • 加载IMAGE对象,使用loadimage(&pic,"path")函数。为了防止图片切换过快,自定义了load()函数,由putimage()Sleep()两部分组成。
  • 幻灯片切换主要依靠while()switch()语句,定义了clickjump两个变量,来控制切换图片和跳出循环。此处才深刻体会到了while()for()的本质区别。
  • easyX的鼠标交互函数
MOUSEMSG m;
while (MouseHit())
{
    m = GetMouseMsg();
    if (m.uMsg == WM_LBUTTONDOWN)
    click++;
}

打飞机游戏

设置了3种攻击对象,引入了时间函数,是三个主要功能中最复杂的部分。

对象绘制
  • 由于画面需要不断更新,为免卡顿,使用了BeginBatchDraw()FlushBatchDraw()以及EndBatchDraw()三个函数。
  • “退而求其次大法”:由于蠢,给炮弹只设置了长度为3的数组,因此在连续射击时出现了炮弹消失的Bug。这里炮弹并不是真正的消失,而是被重新定位到画面外的位置。这也是游戏处理图形对象的常用技巧。
  • easyX的putimage()函数非常好用,只需要定义两个关于x和y坐标的变量,就可以通过该函数实现图形位置切换。此处依旧是while()函数,在每个循环都需要更新画面,帧切换实现动画效果。
炮弹逻辑

主要是速度调节(依赖循环)和重新定位两个功能。

for (int j = 0; j < 3; j++)
    {
        if (speedBbl == 2)
        {
            bblY[j] -= 3;
            speedBbl = 0;
        }
        if (bblY[j] <= 0) //bubble is out of the canvas
        {
            bblY[j] = -3000;//redirect and wait for the new launch
        }
        speedBbl++;
    }
击中怪物

由于怪物数量多,也需要设置数组,此处用for()循环,同时涉及定位容错问题。我采用的方法:用photoshop处理怪物遮罩图,并且记录图片大小。

for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            if ((bblX[j] < mons1X[i] + 35) && (bblX[j] > mons1X[i] - 35) && (bblY[j] < mons1Y[i] + 35) && (bblY[j] > mons1Y[i] - 35))
            {
                mons1X[i] = (rand() % 750) + 20;
                mons1Y[i] = -200;
                score++;
                for (int j = 0; j<3; j++)
                    bblY[j] = -3000;
                //set the music
                mciSendString("close jpmusic", NULL, 0, NULL);
                mciSendString("open .\\gameImage\\mons1.mp3 alias jpmusic", NULL, 0, NULL);
                mciSendString("play jpmusic", NULL, 0, NULL);

            }
        }

同样,需要定义怪物坐标变量,并且在循环中更新怪物位置以实现降落效果。
怪物重生成则运用了随机数。

鼠标交互

easyX()鼠标定位函数以及click感知函数。

MOUSEMSG m;
    while (MouseHit())
    {
        m = GetMouseMsg();
        if (m.uMsg == WM_MOUSEMOVE)
        {
            fishX = m.x;
        }

        //for bubble 1
        if ((m.uMsg == WM_LBUTTONDOWN) && (bblY[0] == -3000))
        {
            bblX[0] = fishX + 25;
            bblY[0] = fishY - 50;
        }

        //for bubble after one
        for (int j = 1; j < 3; j++)
        {
            if ((m.uMsg == WM_LBUTTONDOWN)&&(bblY[j-1]!=-3000))
            {
                bblX[j] = fishX + 25;
                bblY[j] = fishY - 50;
            }
        }
    }
}
通关判定

while()框架下嵌入两个if()判断

void level1()
{
    startup1();
    while (1)
    {       /*end of shooting*/
        if (anger <= 0)
        {
            EndBatchDraw();
            break;
        }

        if (left <= 0)
            gameover1();
        show1();
        updateWithoutInput1();
        updateWithInput1();
    }
}

找不同游戏

主要利用的是鼠标交互功能。笨办法:photoshop标尺定位不同点的像素位置。图片处理时间远超代码时间XD。逻辑很简单。

void forPic1()
{
    //pic1
    while ((pic1[0] == 0) || (pic1[1] == 0) || (pic1[2] == 0) || (pic1[3] == 0) || (pic1[4] == 0))
    {
        MOUSEMSG m1;
        FlushMouseMsgBuffer();
        m1 = GetMouseMsg();
        setlinecolor(COLORREF RGB(256, 256, 256));
        setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 3);
        if (m1.uMsg == WM_LBUTTONDOWN)
        {
            m1 = GetMouseMsg();
            if ((m1.x < 636) && (m1.x > 592) && (m1.y < 225) && (m1.y > 200))
            {
                pic1[0] = 1;
                circle(614, 212.5, 15);
                right();
            }

            if ((m1.x < 473) && (m1.x > 447) && (m1.y < 131) && (m1.y > 114))
            {
                pic1[1] = 1;
                circle(460, 122.5, 15);
                right();
            }

            if ((m1.x < 748) && (m1.x > 676) && (m1.y < 174) && (m1.y > 94))
            {
                pic1[2] = 1;
                circle(712, 134, 30);
                right();
            }

            if ((m1.x < 514) && (m1.x > 414) && (m1.y < 497) && (m1.y > 419))
            {
                pic1[3] = 1;
                circle(464, 458, 40);
                right();
            }

            if ((m1.x < 620) && (m1.x > 580) && (m1.y < 190) && (m1.y > 164))
            {
                pic1[4] = 1;
                circle(600, 177, 20);
                right();
            }
        }
    }
    Sleep(500);
}

杂七杂八

  • 音乐设置包含背景音乐和音效两部分,注意切换音乐时需要关闭前一个。
mciSendString("close bkmusic", NULL, 0, NULL);
mciSendString("open .\\gameImage\\bgm1.mp3 alias bkmusic", NULL, 0, NULL);
mciSendString("play bkmusic", NULL, 0, NULL);
mciSendString("close jpmusic", NULL, 0, NULL);
mciSendString("open .\\gameImage\\mons3.mp3 alias jpmusic", NULL, 0, NULL);
mciSendString("play jpmusic", NULL, 0, NULL);
  • 使用了童晶老师教的游戏模块化框架:
int main()
{
startup();
while(1)
{
  show();
  updateWithoutInput();
  updateWithInput();
}
}
  • 使用了头文件的方法来分类编写不同关卡。
  • 自己绘制和处理立绘和素材,photoshop技术++。

总结

第一次独立完成的千行项目,有太多可以优化的地方,不过还是蛮有意思的。接下来想深入学java,开发一个安卓游戏~

你可能感兴趣的:(《咸鱼的救赎》代码总结)