【三、打砖块】

【三、打砖块】

本节我们将沿用 上一节 所提到的函数式游戏框架来写一个弹球打砖块的游戏。

基本量、边框绘制

我们首先定义好可能需要的变量,比如小球坐标以及速度、游戏界面高度和宽度等等,然后再根据之前提到的弹跳小球重构代码,剩下的内容再分步添置即可。

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <cwindow.h>

// 全局变量
int width,high;		//游戏界面尺寸
int ball_x,ball_y;		//小球坐标
int ball_vx,ball_vy;		//小球速度

void gotoxy(int x, int y)	//移动光标便于清屏重画
{
    
    
	HANDLE handle = GetStdHandle(STD_UOTPUT_HANDLE);
	CROOD pos;
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(handle, pos);
}

void startup()		//数据初始化
{
    
    
	high = 15;
	width = 20;
	ball_x = 0;
	ball_y = width/2;
	ball_vx = 1;
	ball_vy = 1;
}

void show()		//显示界面
{
    
    
	gotoxy(0,0);	//光标移动到原点便于重画
	int i,j;
	for(i=0; i<high; i++)
	{
    
    
		for(j=0; j<width; j++)
		{
    
    
			if((i==ball_x)&&(j==ball_y))
				printf("O"); //输出小球
			else if(j == width)	//到达右边界
				printf("|"); //输出边界
			else if(i == high)  //到达下边界
				printf("-"); //输出边界
			else
				printf(" "); //非小球坐标输出空格
		}
		printf("\n");
	}
}

void updateWithoutInput()	//与输入无关更新
{
    
    
	ball_x = ball_x + ball_vx;
	ball_y = ball_y + ball_vy;
	// 判断是否到达边界
	if((ball_x == 0)||(ball_x == high - 1))
		ball_vx = - ball_vx;
	if((ball_y == 0)||(ball_y == width - 1))
		ball_vy = - ball_vy;
	//延时刷新
	sleep(50); 
}

void updateWithInput()	//与输入有关更新
{
    
    } 	//当前没有

int main()
{
    
    
	startup();	//最开始初始化一次
	while(1)	//游戏循环体
	{
    
    
		show(); //先展示画面
		//然后是数据更新
		updateWithoutInput();
		updateWithInput();
	}
	return 0;
}

在判断小球到达边界的部分,我们在第二条件中执行了减一操作,目的是为了避免出现小球和边界重合的情况。

移动挡板

接下来我们要在游戏中显示一个中心坐标为 ( position_x ,position_y ) 且半径为 ridus 的挡板。用 leftright 表示其左边和右边位置。

首先定义相关变量:

int position_x,position_y;
int ridus;
int left,right;

然后数据初始化:

position_x = high; //挡板在最底下
position_y = width/2;
ridus = 5;
left = position_y - ridus;
right = position_y + ridus;

最后在输出中添加输出挡板的部分:

if ...
else if ((i == high)&&(j >= left)&&(j <= right))
	printf("*");
else ...

既然已经画好了挡板,那么要能让它移动才行。
很明显,按照一般游戏思路来,我们不能在移动中改变 x 坐标,也就是说挡板只能左右移动,左移 y 坐标减一,右移则加一。

所以到此我们就要写 updateWithInput 函数部分了。

void updateWithInput()
{
    
    
	char input;
	if(kbhit())
	{
    
    
		input = getch();
		if(input == 'a')
		{
    
    
			position_y --;
			left = position_y - ridus;
			right = position_y + ridus;
		}
		if(input == 'd')
		{
    
    
			position_y ++;
			left = position_y - ridus;
			right = position_y + ridus;
		}
	}
}

反弹小球

反弹小球部分思路就比较清晰一些,简单来说就是判断当小球 x 坐标到达最底部时,其 y 坐标是不是在挡板所规定的范围内,如果是,则改变小球速度;如果不是,游戏结束。

我们还可以定义一个 ball_number 来记录小球反弹的次数。

int ball_number;
//初始化
ball_number = 0;

随后来写我们的 updateWithoutInput 部分:

void updateWithoutInput()
{
    
    
	if(ball_x == high - 1)
	{
    
    
		if((ball_y >= left)&&(ball_y <= right))	//被挡住
		{
    
    
			ball_number ++;
			printf("\a");	//响铃
		}else{
    
    
			printf("游戏结束,因为你没接住控制命运的小球\n");
			system("pause");
			exit(0);
		}
	}
	// 以后内容同前
}

消除砖块

我们使用字母O来表示小球了,那么用什么来表示砖块呢?

这个时候就是看你的英语有没有好好学,我们知道 Brick 是指砖块,所以我们使用字母B来表示砖块,毕竟B本身就像个砖块(并没有)。

需要定义的量:

  • 砖块位置
  • 得分(击中砖块加一)
int brick_x, brick_y;
int score;
//初始化
brick_x = 0;
brick_y = width/2 + 1;
score = 0;

至于输出和判定击中,我就不再多赘述了,基本思路还是和之前一样,输出部分加一句 else if 就可以了,而击中判定在 updateWithoutInput 里。

小结

啊啊啊啊啊啊终于写完了!!!

上代码!!!!!!

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <cwindow.h>

// 全局变量
int width,high;		//游戏界面尺寸
int ball_x,ball_y;		//小球坐标
int ball_vx,ball_vy;		//小球速度
int position_x,position_y;
int ridus;
int left,right;
int ball_number;
int brick_x, brick_y;
int score;

void gotoxy(int x, int y)	//移动光标便于清屏重画
{
    
    
	HANDLE handle = GetStdHandle(STD_UOTPUT_HANDLE);
	CROOD pos;
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(handle, pos);
}

void startup()		//数据初始化
{
    
    
	high = 15;
	width = 20;
	ball_x = 0;
	ball_y = width/2;
	ball_vx = 1;
	ball_vy = 1;
	position_x = high; //挡板在最底下
	position_y = width/2;
	ridus = 5;
	left = position_y - ridus;
	right = position_y + ridus;
	ball_number = 0;
	brick_x = 0;
	brick_y = width/2 + 1;
	score = 0;
}

void show()		//显示界面
{
    
    
	gotoxy(0,0);	//光标移动到原点便于重画
	int i,j;
	for(i=0; i<high; i++)
	{
    
    
		for(j=0; j<width; j++)
		{
    
    
			if((i == ball_x)&&(j == ball_y))
				printf("O"); //输出小球
			else if((i == brick_x)&&(j == brick_y))
				printf("B"); //输出砖块	
			else if(j == width)	//到达右边界
				printf("|"); //输出边界
			else if ((i == high)&&(j >= left)&&(j <= right))
				printf("*"); //输出挡板
			else if(i == high)  //到达下边界
				printf("-"); //输出边界
			else
				printf(" "); //非小球坐标输出空格
		}
		printf("\n");
	}
	printf("反弹小球:%d\n",ball_number);
	printf("得分:%d\n",score);
}

void updateWithoutInput()	//与输入无关更新
{
    
    
	if(ball_x == high - 1)
	{
    
    
		if((ball_y >= left)&&(ball_y <= right))	//被挡住
		{
    
    
			ball_number ++;
			printf("\a");	//响铃
		}else{
    
    	// 没挡住
			printf("游戏结束,因为你没接住控制命运的小球\n");
			system("pause");
			exit(0);
		}
	}
	ball_x = ball_x + ball_vx;
	ball_y = ball_y + ball_vy;
	// 判断是否到达边界
	if((ball_x == 0)||(ball_x == high - 1))
		ball_vx = - ball_vx;
	if((ball_y == 0)||(ball_y == width - 1))
		ball_vy = - ball_vy;
	// 判定击中
	if((ball_x == brick_x)&&(ball_y == brick_y))
	{
    
    
		score ++;
		brick_y = rand() % width; //砖块刷新
	}	
	//延时刷新
	sleep(50); 
}

void updateWithInput()	//与输入有关更新
{
    
    
	char input;
	if(kbhit())
	{
    
    
		input = getch();
		if(input == 'a') //挡板左移
		{
    
    
			position_y --;
			left = position_y - ridus;
			right = position_y + ridus;
		}
		if(input == 'd') //挡板右移
		{
    
    
			position_y ++;
			left = position_y - ridus;
			right = position_y + ridus;
		}
	}
} 

int main()
{
    
    
	startup();	//最开始初始化一次
	while(1)	//游戏循环体
	{
    
    
		show(); //先展示画面
		//然后是数据更新
		updateWithoutInput();
		updateWithInput();
	}
	return 0;
}

这里就是全部代码了,由于时间原因,这篇文章是3天抽出零碎时间更的,所以更新比较慢,到此,

感谢阅读,喜欢就点个赞吧~

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_54597744/article/details/113983606