美文网首页
《咸鱼的救赎》代码总结

《咸鱼的救赎》代码总结

作者: Maxmoe | 来源:发表于2018-01-31 10:41 被阅读0次
    剧情一帧

    看完了了童晶老师的《做游戏,学编程》网课,自己尝试着用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,开发一个安卓游戏~

    相关文章

      网友评论

          本文标题:《咸鱼的救赎》代码总结

          本文链接:https://www.haomeiwen.com/subject/adckzxtx.html