c语言通过easyx窗口实现小球打砖块的游戏

 (创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹)

在学完easyx之后,我们可以结合c语言,实现更高层次的游戏开发,今天我们就以小球打砖块为例

首先就是常规引入相关的头文件

#include<stdio.h>
#include<graphics.h>  //便于引入easyx窗口及其函数
#include<conio.h>     //按键控制 

接下来就是对这个游戏的各个变量进行定义

包括Brick:砖块, Broad:木板, Ball_x:球的方向向量, circle_x:球心坐标

这里我们用define对各个变量进行定义

#define WINDOW_Width 700 //窗口宽度
#define WINDOW_Height 600//窗口高度
#define BrickWidth 50 //固定一个砖块的宽50  和高30 描述每一个砖块
#define BrickHeight 30//
#define Brick_ROWS 4  //砖块行
#define ZK_COLS 14    //砖块列
#define Broad_Width BrickWidth * 4//木板宽度
#define Broad_Height BrickHeight//木板高度
#define Radius 20     //球的半径

接下来就是对球和木板的坐标进行定义

int Broad_x = (WINDOW_Width - Broad_Width) / 2; //木板初始化
int  Broad_y = WINDOW_Height - Broad_Height;    
int circle_x = WINDOW_Width / 2;                             //球初始化
int  circle_y = WINDOW_Height - Radius - Broad_Height;
int Ball_x = 6;                                                            //球x方向向量   为+右,为-左
int Ball_y = -6;                                                            //球y方向向量  为+下,为-上 

 因为在后续的编写中,要考虑到砖块被消除的问题,所以我们这里定义砖块是否存在

int Brick[Brick_ROWS][ZK_COLS] = {0};//木板是否存在:1为不存在,0为存在 

接下来我们尝试画一个砖块

void DrawOneBrick(int x, int y)                  //xy下标                                            
{
    if (0 == Brick[y][x])
    {
        setlinecolor(BLACK);//线框颜色
        setfillcolor(RGB(250, 84, 101));//方块颜色
        fillrectangle(x * BrickWidth, y * BrickHeight, x *
            BrickWidth + BrickWidth, y * BrickHeight + BrickHeight);//(x1,y1),(x2,y2)方块大小
    }

如果你觉得颜色过于单调,可以改为

setfillcolor(RGB(rand()%255, rand() % 255, rand() % 255)) 

会有意想不到的色彩效果,哈哈哈哈哈 

然后就是全部砖块的绘制

void DrawAllBrick()
{
    for (int i = 0; i < Brick_ROWS; i++)
    {
        for (int j = 0; j < 14; j++)
            DrawOneBrick(j, i);
    }

 至于这里为什么先画一个砖块在绘制全部呢?是为了便于以后小球消砖块时可以一个一个消除而不会影响整体。

接下来就是绘制弹跳木板

void DrawDownBrick()
{
    setlinecolor(BLACK);//线框颜色
    setfillcolor(RGB(235, 107, 126));//木板颜色

    fillrectangle(Broad_x, Broad_y, Broad_x + Broad_Width, Broad_y + Broad_Height);//木板坐标

}

 接下来就是小球的绘制

void DrawCircle()
{
    setlinecolor(BLACK);
    setfillcolor(RGB(252, 190, 163));//红色
    fillcircle(circle_x, circle_y, Radius);//小球坐标和半径

}

 接着就是全部游戏的显示了,别忘了清屏和防止屏幕一闪一闪

 void GameDraw()
{
    BeginBatchDraw();//绘图前    防闪
    cleardevice();//清屏
    DrawAllBrick();//画全部方块
    DrawDownBrick();//画木板块
    DrawCircle();//画球
    EndBatchDraw(); //绘图后    防闪
}

 完成绘制之后,就要解决移动问题了,我们先来解决球的移动问题

void CircleMove()
{
    circle_x += Ball_x;
    circle_y += Ball_y;
}

以及球在运动中消砖块的情况 

int DisappearBrick()
{
    int ZK_COL = circle_x / BrickWidth;
    int ZK_ROW = circle_y / BrickHeight;

    if (ZK_ROW < 4 && ZK_COL < 14 && Brick[ZK_ROW][ZK_COL] == 0)
    {
        Brick[ZK_ROW][ZK_COL] = 1;
        return 1;
    }
    return 0;
}

 接下来就是球碰撞到边缘或者木板或者砖块时的运动情况

void CollisionDetection()
{
    HWND hwnd = GetHWnd();//获得一个窗口句柄,便于接下来弹出小窗口
    //球如果往右边移动,检测球是否撞上右边沿
    if (Ball_x > 0 && circle_x >= WINDOW_Width - Radius)
    {
        Ball_x = -6;
    }
    //球如果往上边移动,检测球是否撞上上边沿
    if (Ball_y < 0 && circle_y <= Radius || DisappearBrick())
    {
        Ball_y = 6;
    }
    //球如果往左边移动,检测球是否撞上左边沿
    if (Ball_x < 0 && circle_x <= Radius)
    {
        Ball_x = 6;
    }
    //球如果往下边移动,检测球是否撞上下边沿
    if (Ball_y > 0 && circle_y >= WINDOW_Height - Radius)
    {
        Ball_y = 0;
        Ball_x = 0;
        MessageBox(hwnd, "游戏结束", "出界", MB_OK);//弹出小窗口
    }
    //检测球是否撞上板子,只能从上往下撞,只有两种极限情况
    if ((Ball_y > 0) && (circle_y >= (Broad_y - Radius)) && //球y坐标
        (circle_x >= Broad_x) && (circle_x <= (Broad_x + Broad_Width)))
    {
        Ball_y = -6;
    }

}

接下来就是用键盘去操控木板的移动,如果大家对键盘操作不太明白,可以查阅(http://t.csdn.cn/QAMbU

void KeyControl()
{
    CollisionDetection();    //不管有没有按键都要碰撞检测
    int ch;
    if (_kbhit())//检测是否有按键
    {                       
        ch = _getch();//获取按键的值
        switch (ch)
        {
        case 'a':
        case 'A':
        case 75:
            Broad_x -= 20;
            if (Broad_x <= 0)
            {
                Broad_x = 0;
            }
            break;
        case 'd':
        case 'D':
        case 77:
            Broad_x += 20;
            if (Broad_x >= 500)
            {
                Broad_x = 500;
            }
            break;
        }
    }

最后就是将一切汇总到主函数

int main()
{
    initgraph(WINDOW_Width, WINDOW_Height); //width宽 height高
    while (1)
    {
        GameDraw();
        CircleMove();
        KeyControl();
        DisappearBrick();
        Sleep(50);
    }
    return 0;

总体代码就是这样,如果大家发现bug或者有更好的方法 ,欢迎大家一起来讨论

#include<stdio.h>
#include<graphics.h>  //便于引入easyx窗口及其函数
#include<conio.h>     //按键控制 
//Brick:砖块 Broad:木板 Ball_x:球的方向向量 circle_x:球心坐标
#define WINDOW_Width 700 //窗口宽度
#define WINDOW_Height 600//窗口高度
#define BrickWidth 50 //固定一个砖块的宽50  和高30 描述每一个砖块
#define BrickHeight 30//
#define Brick_ROWS 4  //砖块行
#define ZK_COLS 14    //砖块列
#define Broad_Width BrickWidth * 4//木板宽度
#define Broad_Height BrickHeight//木板高度
#define Radius 20     //球的半径
int Broad_x = (WINDOW_Width - Broad_Width) / 2; //木板初始化
int  Broad_y = WINDOW_Height - Broad_Height;    
int circle_x = WINDOW_Width / 2;                //球初始化
int  circle_y = WINDOW_Height - Radius - Broad_Height;
int Ball_x = 6;//球x方向向量   为+右,为-左
int Ball_y = -6;//球y方向向量  为+下,为-上

int Brick[Brick_ROWS][ZK_COLS] = {0};//木板是否存在:1为不存在,0为存在

//画一个方块
void DrawOneBrick(int x, int y)                  //xy下标   										 
{
	if (0 == Brick[y][x])
	{
		setlinecolor(BLACK);//线框颜色
		setfillcolor(RGB(250, 84, 101));//方块颜色
		fillrectangle(x * BrickWidth, y * BrickHeight, x *
			BrickWidth + BrickWidth, y * BrickHeight + BrickHeight);//(x1,y1),(x2,y2)方块大小
	}
}
//画全部方块
void DrawAllBrick()
{
	for (int i = 0; i < Brick_ROWS; i++)
	{
		for (int j = 0; j < 14; j++)
			DrawOneBrick(j, i);
	}
}
//画木板块
void DrawDownBrick()
{
	setlinecolor(BLACK);//线框颜色
	setfillcolor(RGB(235, 107, 126));//木板颜色

	fillrectangle(Broad_x, Broad_y, Broad_x + Broad_Width, Broad_y + Broad_Height);//木板坐标

}
//画球
void DrawCircle()
{
	setlinecolor(BLACK);
	setfillcolor(RGB(252, 190, 163));
	fillcircle(circle_x, circle_y, Radius);

}
//所有游戏显示
void GameDraw()
{
	BeginBatchDraw();//绘图前    防闪
	cleardevice();//清屏
	DrawAllBrick();//画全部方块
	DrawDownBrick();//画木板块
	DrawCircle();//画球
	EndBatchDraw(); //绘图后    防闪
}
//球的移动
void CircleMove()
{
	circle_x += Ball_x;
	circle_y += Ball_y;
}
//消除砖块
int DisappearBrick()
{
	int ZK_COL = circle_x / BrickWidth;
	int ZK_ROW = circle_y / BrickHeight;

	if (ZK_ROW < 4 && ZK_COL < 14 && Brick[ZK_ROW][ZK_COL] == 0)
	{
		Brick[ZK_ROW][ZK_COL] = 1;
		return 1;
	}
	return 0;
}
//碰撞检测int circle_x, int circle_y
void CollisionDetection()
{
	HWND hwnd = GetHWnd();
	//球如果往右边移动,检测球是否撞上右边沿
	if (Ball_x > 0 && circle_x >= WINDOW_Width - Radius)
	{
		Ball_x = -6;
	}
	//球如果往上边移动,检测球是否撞上上边沿
	if (Ball_y < 0 && circle_y <= Radius || DisappearBrick())
	{
		Ball_y = 6;
	}
	//球如果往左边移动,检测球是否撞上左边沿
	if (Ball_x < 0 && circle_x <= Radius)
	{
		Ball_x = 6;
	}
	//球如果往下边移动,检测球是否撞上下边沿
	if (Ball_y > 0 && circle_y >= WINDOW_Height - Radius)
	{
		Ball_y = 0;
		Ball_x = 0;
		MessageBox(hwnd, "游戏结束", "出界", MB_OK);
	}
	//检测球是否撞上板子,只能从上往下撞,只有两种极限情况
	if ((Ball_y > 0) && (circle_y >= (Broad_y - Radius)) && //球y坐标
		(circle_x >= Broad_x) && (circle_x <= (Broad_x + Broad_Width)))
	{
		Ball_y = -6;
	}

}
//键盘控制
void KeyControl()
{
	CollisionDetection();	//不管有没有按键都要碰撞检测
	int ch;
	if (_kbhit())//检测是否有按键
	{                       
		ch = _getch();//获取按键的值
		switch (ch)
		{
		case 'a':
		case 'A':
		case 75:
			Broad_x -= 20;
			if (Broad_x <= 0)
			{
				Broad_x = 0;
			}
			break;
		case 'd':
		case 'D':
		case 77:
			Broad_x += 20;
			if (Broad_x >= 500)
			{
				Broad_x = 500;
			}
			break;
		}
	}
}
int main()
{
    initgraph(WINDOW_Width, WINDOW_Height); //width宽 height高
	while (1)
	{
		GameDraw();
		CircleMove();
		KeyControl();
		DisappearBrick();
		Sleep(50);
	}
	return 0;
}

加油

TC编写 main() { int mode=VGAHI,driver=VGA; char ch; unsigned int l; int i,gi,gj,j,flag=1;/*i,j是循环变量,flag是标记变量,-1:向x负半轴移动,+1:向x正半轴移动*/ double qx,qy,k,b=0.0,speech=0.4,x,y; double r=2.0,bx=60.0,byy=270.0; double pianx=100.0,piany=100.0,tx=20.0,ty=10.0,jx=2.0,jy=2.0; int mx=0,my=0,mb,sum;/*sum纪录砖块的数目*/ FILE * p; if((p = fopen("record.dat", "r")) == NULL) { p=fopen("record.dat","w"); fprintf(p,"0 0 0 0 0\n"); rewind(p); } fclose(p); initgraph(&driver,&mode,"C:\\tc"); setbkcolor(BLUE); Msinit(); Setmouse((int)(pianx+1+bx/2),(int)((tx+jx)*8+pianx-1-bx/2),(int)byy+piany,(int)byy+piany); star: cleardevice();/*程序重载的介入点*/ setcolor(RED); outtextxy(30,20,"^_^ Welcome to Play Hitting Brick Game! ^_^"); sum=0; qx=100.0+pianx-10;qy=180.0+pianx-10;k=0.33; setcolor(7); rectangle((int)(pianx-2),(int)(piany-2),(int)((tx+jx)*8+2+pianx),302+piany); setcolor(1); rectangle((int)(pianx-1),(int)(piany-1),(int)((tx+jx)*8+1+pianx),301+piany); /*读取盘面情况*/ p=fopen("record.dat", "r"); for(i=0;i<5;i++) fscanf(p,"%x ",&zhuan[i]); fclose(p); /*画砖块*/ for(i=0;i<5;i++) { l=1; for(j=0;j<16;j++) { if((zhuan[i]&l)==0) { Draw((int)((jx+tx)*((16*i+j)%8)+pianx+jx),(int)((jy+ty)*((int)((16*i+j)/8))+piany+jy),(int)tx,(int)ty); sum+=1; } l=l*2; } } gotoxy(5,4); printf("Press any key to start game...Q key to quit..."); ch=getch(); if(ch=='q'||ch=='Q') quitgame(); else { gotoxy(5,4); printf(" "); } for(;;) { setfillstyle(1, 0); bar(mx-bx/2,my,mx+bx/2,my+5); Msread(&mx, &my, &mb); Draw(mx-bx/2,my,bx,5); setcolor(0); mycircle(qx,qy,r,0); /*判断求是否反弹*/ if(qx-r<=pianx+1 || qx+r>=(tx+jx)*8+pianx-1) { flag=-flag; k=-k; } if(qy-r<=piany+1) k=-k; for(gi=0;gi<5;gi++) { l=1; for(gj=0;gj<16;gj++) { if((zhuan[gi]&l)==0) { j=(16*gi+gj)/8; i=(16*gi+gj)%8; x=(jx+tx)*i+jx+tx/2+pianx; y=(jy+ty)*j+jy+ty/2+piany; /*边判断1*/ if(qy>=y-ty/2 && qy<=y+ty/2 &&(pow(qx+r-x+tx/2,2)<1 || pow(qx-r-x-tx/2,2)<1)) { flag=-flag; k=-k; zhuan[gi]=zhuan[gi]|l; sum-=1; if(sum==0) wingame(); setfillstyle(1, 0); bar((jx+tx)*i+pianx+jx,(jy+ty)*j+piany+jy,(jx+tx)*i+pianx+jx+tx,(jy+ty)*j+piany+jy+ty); } else /*边判断2*/ if(qx>=x-tx/2 && qx<=x+tx/2 &&(pow(qy+r-y+ty/2,2)<1 || pow(qy-r-y-ty/2,2)<1)) { k=-k; zhuan[gi]=zhuan[gi]|l; sum-=1; if(sum==0) wingame(); setfillstyle(1, 0); bar((jx+tx)*i+pianx+jx,(jy+ty)*j+piany+jy,(jx+tx)*i+pianx+jx+tx,(jy+ty)*j+piany+jy+ty); } else /*角判断*/ if(pow(qx-x+tx/2,2)+pow(qy-y+ty/2,2)<=r*r || pow(qx-x-tx/2,2)+pow(qy-y+ty/2,2)<=r*r || pow(qx-x+tx/2,2)+pow(qy-y-ty/2,2)<=r*r || pow(qx-x-tx/2,2)+pow(qy-y-ty/2,2)<=r*r) { flag=-flag; zhuan[gi]=zhuan[gi]|l; sum-=1; if(sum==0) wingame(); setfillstyle(1, 0); bar((jx+tx)*i+pianx+jx,(jy+ty)*j+piany+jy,(jx+tx)*i+pianx+jx+tx,(jy+ty)*j+piany+jy+ty); } } l=l*2; } } /*棍棒的反弹*/ if(qx<=mx+bx/2 && qx>=mx-bx/2 && pow(qy+r-my,2)<1) { k=-(k/pow(k*k,0.5))*(0.3*bx/(pow(pow(qx-mx,2),0.5)+0.000001)); } if((int)(qy+r)>my+0.5) { gotoxy(5,5); printf("You have lost the game!Press any key to restart..."); getch(); goto star; } b=qy-qx*k; if(flag==1) qx=qx+speech/pow(1.0+k*k,0.5); if(flag==-1) qx=qx-speech/pow(1.0+k*k,0.5); qy=qx*k+b;/*计算球心坐标*/ setcolor(14); mycircle((int)qx,(int)qy,r,14); delay(1); if(mb==1) { gotoxy(5,5); printf("You have lost the game!Press any key to restart..."); getch(); goto star; } } }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小周不想卷

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

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

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

打赏作者

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

抵扣说明:

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

余额充值