消除射击(C++)

1. 游戏机制

        玩家通过小键盘上的"←"、"→"键来控制角色的移动,玩家需要按"z"键进行射击,发射的子弹会消灭迎面而来的敌人。同时敌人也有可以发射子弹,若敌人或敌人的子弹接触到玩家,则游戏结束。另外,玩家发射的子弹可以抵消敌人发射的子弹。

2. 游戏代码

#include "../Engine/BrickEngine.h"

const int BW(25), BH(30); // BW表示场景的宽度, BH表示场景的高度
// PlayerX表示玩家的横坐标, EnemyBX、EnemyBY分别表示敌方子弹的横横坐标、纵坐标
int PlayerX, EnemyBX, EnemyBY;
// Wall表示该处是否有墙, Bullet表示该处是否有子弹
bool Wall[25 * 30], Bullet[25 * 30];

void Run();
// 显示玩家
void ShowPlayer()
{
    FillStr(PlayerX, BH - 2, "■");
    FillStr(PlayerX - 1, BH - 1, "■■■");
}
// 玩家死亡
void GameOver()
{
    // 先在中间留一块空白区域, 然后居中显示Game Over!
    FillRec(BW - 6 >> 1, (BH >> 1) - 2, 7, 3, "  ");
    FillStr(BW - 5 >> 1, (BH >> 1) - 1, "Game Over!");
    // 改变玩家显示样式
    FillStr(PlayerX, BH - 2, "×");
    FillStr(PlayerX - 1, BH - 1, "×××");
    // 清除子弹
    FillStr(EnemyBX, EnemyBY, "  ");
    Pause();
    Run();
}
// 显示墙体
void ShowWall()
{
    for (int idx = 0; idx < BW * BH; ++idx)
        if (Wall[idx])
            FillStr(idx % BW, idx / BW, "■");
}
// 添加墙体
void AddWall()
{
    // 先判断玩家是否死亡
    int n = BW * (BH - 3) + BW - 1; // 倒数第3行最后一个坐标
    for (int idx = n - BW + 1; idx < n; ++idx)
        if (Wall[idx]) // 如果倒数第3行存在墙体, 则玩家死亡
            GameOver();
    // 下移所有墙体
    for (int idx = BW * (BH - 1) - 1; idx >= 0; --idx)
        if (Wall[idx])
        {
            Wall[idx] = false;
            FillStr(idx % BW, idx / BW, "  ");
            Wall[idx + BW] = true;
        }
    // 所有墙体向下移动一行, 此时最上方那行空出来了, 为空出来的那行添加墙体
    for (int x = 1; x < BW - 1; ++x)
        if (rand() & 1) // 有一半的概率生成墙体
            Wall[x] = true;
    // 显示移动后的墙体
    ShowWall();
}
// 显示子弹
void ShowBullet()
{
    for (int idx = 0; idx < BW * BH; ++idx)
        if (Bullet[idx])
            FillStr(idx % BW, idx / BW, "■");
}
// 玩家子弹移动
void PlayerBulletMove()
{
    for (int idx = 0; idx < BW * BH; ++idx)
        if (Bullet[idx])
        {
            Bullet[idx] = false;
            FillStr(idx % BW, idx / BW, "  ");
            if (idx > BW) // 子弹未抵达边界
            {
                if (Wall[idx - BW]) // 子弹下一位置是墙,子弹和墙一同消除
                {
                    Wall[idx - BW] = false;
                    FillStr(idx % BW, idx / BW - 1, "  ");
                }
                else
                    Bullet[idx - BW] = true;
            }
        }
    // 显示移动后的子弹
    ShowBullet();
}
// 敌人子弹移动
void EnemyBulletMove()
{
    if (!EnemyBX) // 敌人子弹是否存在
        return;
    if ((EnemyBY == BH - 2 && (EnemyBX == PlayerX - 1 || EnemyBX == PlayerX + 1)) ||
        EnemyBY == BH - 3 && EnemyBX == PlayerX) // 子弹击中玩家
        GameOver();
    if (!EnemyBY)
    {
        int MaxY = 0; // 敌方子弹所处列中Wall的最大纵坐标
        for (int y = BH - 2; y >= 0; --y)
            if (Wall[y * BW + EnemyBX])
            {
                MaxY = y;
                break;
            }
        EnemyBY = MaxY + 1;
        FillStr(EnemyBX, EnemyBY, "■");
    }
    if (EnemyBY < BH - 1) // 子弹未抵达边界
    {
        // 敌方子弹和玩家子弹距离小于2格, 分别移动1格后两个子弹将会发生碰撞
        for (int i = 1; i < 3; ++i)
            if (Bullet[(EnemyBY + i) * BW + EnemyBX])
            {
                Bullet[(EnemyBY + i) * BW + EnemyBX] = false;
                FillStr(EnemyBX, EnemyBY, "  ");
                FillStr(EnemyBX, EnemyBY + i, "  ");
                EnemyBX = 0;
                return;
            }
        ++EnemyBY;
        FillStr(EnemyBX, EnemyBY - 1, "  ");
        FillStr(EnemyBX, EnemyBY, "■");
    }
    else // 子弹抵达边界
    {
        FillStr(EnemyBX, EnemyBY, "  ");
        EnemyBX = 0;
    }
}
// 运行游戏
void Run()
{
    // 初始化游戏
    system("cls");
    for (bool &w : Wall)
        w = false;
    for (bool &b : Bullet)
        b = false;
    PlayerX = (BW - 1 >> 1);
    EnemyBX = EnemyBY = 0;
    ShowPlayer();
    AddWall();

    int t = 0;
    while (true)
    {
        Sleep(1);
        ++t &= 511; // t的取值范围0~511, t每次加1, 等于511时值变为0
        if (kbhit())
        {
            int ch = getch();
            if (ch == 224) // 玩家移动
            {
                // 清除角色
                FillStr(PlayerX, BH - 2, "  ");
                FillRec(PlayerX - 1, BH - 1, 3, 1, "  ");

                switch (getch())
                {
                case 75: // 左移
                    PlayerX -= PlayerX != 1;
                    break;
                case 77: // 右移
                    PlayerX += PlayerX != BW - 2;
                    break;
                }
                ShowPlayer();
            }
            else if (ch == 122) // 玩家射击
            {
                Bullet[BW * (BH - 3) + PlayerX] = true;
                ShowBullet();
            }
            else if (ch == 32) // 暂停游戏
                Pause();
        }
        if (!(t & 1)) // 子弹移动
        {
            PlayerBulletMove();
            EnemyBulletMove();
        }
        if (!(t & 127)) // 添加新的一行
            AddWall();
        if (!(t & 511)) // 敌人射击
        {
            EnemyBX = rand() % (BW - 3) + 1; // 1到23
            EnemyBY = 0;
        }
    }
}

int main()
{
    SetConsole("消除射击", 50, 30, "80");
    srand((int)time(0));
    Run();
}

3. 游戏截图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

来抓月亮啦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值