《打蜜蜂》是早期 DOS 年代經典的入門遊戲:玩家控制坦克左右移動、發射子彈擊落蜂群。本文以 Turbo C / Borland Graphics Interface (BGI) 為繪圖庫,展示如何用 C 語言實現遊戲主迴圈、碰撞檢測、物件管理等核心機制。雖然 BGI 已過時,但其中的遊戲程式架構思維(初始化→主迴圈→輸入處理→邏輯更新→渲染→清理)放在現代引擎(Unity、Godot、SDL、Raylib)依然通用。
#define TANK_SIZE 30
#define STAR_SIZE 30
int tank_x, tank_y; // 坦克座標
int tank_left=20, tank_right=620, tank_top=20, tank_bottom=450; // 邊界
int bullet_x=-1, bullet_y=-1, bullet_color=4; // 子彈狀態
int bee_x[6][18], bee_y[6][18]; // 蜂群陣列 (6行 x 18列)
int bee_count = 0; // 存活蜜蜂數
void DrawBee(int x, int y, int color)
{
int Ax=x+15, Ay=y;
int Bx=x+2, By=y+10;
int Cx=x+7, Cy=y+30;
int Dx=x+22, Dy=y+30;
int Ex=x+28, Ey=y+10;
int old = getcolor();
setcolor(color == -1 ? (x%8==0?x+1:x%8) : color);
line(Ax,Ay,Cx,Cy); line(Ax,Ay,Dx,Dy);
line(Bx,By,Dx,Dy); line(Bx,By,Ex,Ey);
line(Cx,Cy,Ex,Ey);
setcolor(old);
}
void DrawTank(int x, int y)
{
int old = getcolor();
setcolor(getcolor()!=getbkcolor() ? 2 : getbkcolor()); // 綠色或背景色(消除)
rectangle(x, y+10, x+TANK_SIZE, y+TANK_SIZE);
circle(x+TANK_SIZE/2, y+10+TANK_SIZE/2-5, TANK_SIZE/2-7);
rectangle(x+TANK_SIZE/2-2, y, x+TANK_SIZE/2+2, y+10+TANK_SIZE/2-5-(TANK_SIZE/2-7)-2+10);
setcolor(old);
}
技巧:用「畫背景色」覆蓋舊位置實現動畫,避免全螢幕重繪閃爍。
void AutoFire()
{
if (bullet_y == tank_top) { // 到達頂部
DrawBullet(bullet_x, bullet_y, getbkcolor());
bullet_x = -1; // 標記無效
}
if (bullet_x == -1) { // 發射新子彈
DrawBullet(tank_x, tank_y-TANK_SIZE, bullet_color);
bullet_x = tank_x;
bullet_y = tank_y - TANK_SIZE;
delay(50);
} else { // 子彈向上移動
DrawBullet(bullet_x, bullet_y, getbkcolor());
bullet_y -= TANK_SIZE;
DrawBullet(bullet_x, bullet_y, bullet_color);
delay(50);
}
CheckHit(); // 碰撞檢測
}
void GameLoop()
{
char key = 0;
while (1) {
while (!kbhit()) AutoFire(); // 無輸入時自動推進
key = getch();
switch (key) {
case 'a': MoveLeft(); break;
case 'd': MoveRight(); break;
case 'p': exit(0); break;
}
}
}
| BGI 函數 | SDL2 / Raylib 對應 | 備註 |
|---|---|---|
initgraph | InitWindow / SDL_CreateWindow | 建立視窗與繪圖上下文 |
line/circle/rectangle | DrawLine/DrawCircle/DrawRectangle | 基本圖元 |
setcolor | SetDrawColor / SDL_SetRenderDrawColor | 色彩設定 |
kbhit/getch | IsKeyDown / SDL_PollEvent | 事件驅動取代輪詢 |
delay | WaitTime / SDL_Delay | 幀率控制 |
#include <graphics.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
// 全域變數、結構體定義...
// DrawBee, DrawTank, DrawBullet, MoveLeft, MoveRight, CheckHit, AutoFire, GameLoop...
int main()
{
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI"); // 路徑視編譯器而定
rectangle(tank_left-1, tank_top-1, tank_right+1, tank_bottom);
tank_x = 290; tank_y = 410;
DrawTank(tank_x, tank_y);
InitBees(); // 雙層迴圈產生蜂群座標
GameLoop();
closegraph();
return 0;
}
Enemy {int x,y; int type; int hp;},支援不同分數、血量、移動模式。fwrite/fread 儲存二進位紀錄,或 SQLite 輕量資料庫。《打蜜蜂》雖小,五臟俱全:遊戲迴圈、輸入處理、狀態機、碰撞檢測、資源管理。用 C 語言從零寫出可玩的遊戲,是理解電腦圖形學與即時互動系統的最佳捷徑。建議讀者嘗試移植到 Raylib 或 SDL2,體驗現代框架如何簡化底層細節,同時保留核心邏輯不變。