C语言控制台制作Flappy bird&C语言小游戏合集

娱乐向

前两天在b站上看到有许多人用纯C语言和控制台去做一些简单的坦克大战以及用字符去做新型肺炎的图形化传播分析
然后我就也跟着做了个C语言的Flappy Bird

游戏规则:
打开游戏 按下任意键控制小鸟是否往上飞
前三个柱子是无敌时间 后面的撞到就GG

想要修改游戏参数的话就修改宏定义部分和char calculation()就好
原本我是想直接按照标准抛物线计算 但是发现这样累积速度太难控制 然后我就在累积速度处加了个类似于空阻的累积速度衰弱。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#include <Windows.h>
#include <stdio.h>
#include <time.h>
#define CAVE 3 //孔洞大小
#define VARIATION 5 //相邻两个柱子孔洞距离的最大变化量
#define ACCELERATION 10.0 //鸟下降的加速度 游戏中单帧时长已被固定为0.3秒 想要修改飞行参数的话 修改这个值就好
#define SPEED 5 //单击一次鸟的速度变化量
#define ORIGINAL_HEIGHT 24 //最初鸟的纵坐标
#define DELAYTIME 333 //游戏刷新周期&速度控制

const char bird[] = "√";
const char blank[] = " "; //16个字符一组
const char column[] = "██ "; //8个格 2+6
char height,GG;
int score = -2;

void modeset(int w,int h) {
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD size = {w, h};
SetConsoleScreenBufferSize(hOut,size);
SMALL_RECT rc = {1,1, w, h};
SetConsoleWindowInfo(hOut ,1 ,&rc);
}

void generate(char *high)
{
char temp[3];
char t1;
for(t1=0;t1<3;t1++)
temp[t1] = high[t1+1];
for(t1=0;t1<3;t1++)
high[t1] = temp[t1];
srand ((unsigned int)time(NULL));
high[3] = rand()%24 + 1;
if((high[3] - high[2]) > VARIATION)
high[3] = high[2] + VARIATION;
if((high[2] - high[3]) > VARIATION)
high[3] = high[2] - VARIATION;
}

char calculation(char TF)
{
static double h = ORIGINAL_HEIGHT,v = 0; //h为高度 v为速度
switch(TF)
{
case 'T':
v -= SPEED; //在输出时 为了方便起见 我将Y轴设为向上为负 所以这里要反过来减
h = h - ACCELERATION*0.045 + v*0.3; //游戏中的单步时长为0.3s
v = v*0.3;
break;
case 'F':
h = h - ACCELERATION*0.045 + v*0.3;
v += ACCELERATION*0.3;
v = v*0.7; //我也挺想按照抛物线算的 但是按照标准抛物线算的话 太难控制了
break;
default:
break;
}
if (h < 0){
h = 1;
v = 0;
return 0;
}
if (h > 29){
h = 30;
v = 0;
return 29;
}
return (char)h;
}

void GoodGame()
{
static char t1,t2;
Sleep(300);
for(t1 = 0;t1 <= 30;t1++)
{
for(t2 = 0;t2<=24;t2++)
{
printf("█");
Sleep(2);
}
printf("\n");
}
if(GG != 'N')
GG = 'T';
printf("Your Score:%d",score);
Sleep(10000);
}

void display(char *high)
{
static char t1,t2,t3,times = 0;
for(t1 = 0;t1 < 30;t1++){ //30行循环刷新

/*动画由第一组负责,需要单独输出第一组*/
for(t3 = times;t3 <= 15;t3+=2)
{
if((high[0] > t1-CAVE) && (high[0] <= t1))
{
putchar(blank[t3]);
putchar(blank[t3+1]);
} else {
putchar(column[t3]);
putchar(column[t3+1]);
}
}

/*因为小鸟在第二组 所以要独立输出第二组*/
if(t1 == height)
{
/*因为第一组长度不固定,所以第二组长度也不固定 但是小鸟横坐标是固定的 所以第二组需要拆成三部分输出*/
/*输出小鸟前的部分*/
for(t3 = 0;t3 < times;t3+=2){
if((high[1] > t1-CAVE) && (high[1] <= t1))
{
putchar(blank[t3]);
putchar(blank[t3+1]);
} else {
putchar(column[t3]);
putchar(column[t3+1]);
}
}

/*输出小鸟*/
putchar(bird[0]);
putchar(bird[1]);

/*输出小鸟后面的部分*/
if((high[1] > t1-CAVE) && (high[1] <= t1))
{
for(t3 = times + 2;t3<16;t3 = t3+2)
{
putchar(blank[t3]);
putchar(blank[t3+1]);
}
}else{
for(t3 = times + 2;t3<16;t3 = t3+2)
{
putchar(column[t3]);
putchar(column[t3+1]);
}
}
}else{
if((high[1] > t1-CAVE) && (high[1] <= t1))
printf("%s",blank);
else
printf("%s",column);
}

/*输出第3-4组,虽然只显示前三组*/
for(t2 = 2;t2 < 4;t2++)
{

if((high[t2] > t1-CAVE) && (high[t2] <= t1))
printf("%s",blank);
else
printf("%s",column);
}
printf("\n");
}

times += 2;
if(times > 14)
{
times = times%16;
generate(high);
score++;
}

/*小鸟撞杆判断*/
if(times <= 4)
{
if(((high[1] <= height-CAVE) || (high[1] > height)) && GG != 'N')
GoodGame();
}
}

void main()
{
modeset(48,32);//能塞下16个方块,一个方块占两个空格宽度
static char t1,t2;
char high[4];
while(1){
GG = 'N';
system("cls");
score = -2;

/*用于生成第一次的地图*/
for(t1 = 0;t1 < 4;t1++)
{
high[t1] = ORIGINAL_HEIGHT;
}

t1 = 0;
while(GG != 'T')
{
if(t1 < 18)
{
t1++;
GG = 'N';
} else {
GG = 0;
}

if(kbhit()){
height = calculation('T');
system("cls");
display(high);
getch();
}else{
height = calculation('F');
system("cls");
display(high);
}
printf("%d",score);

Sleep(DELAYTIME);
}
}
}

感觉游戏玩起来挺简单的。可能是参数调节的太简单了?
娱乐一下就好
用C写这个的主要原因是可以很方便的移植到单片机上
根本原因是我只会C(除了易语言)

不过要是用单片机的话 画面渲染输出方式就有更多选择了 刷新率也能抬得很高 游戏反馈也不用担心了。

后续(或许)也会再添加一些其他的C的小游戏 方便移植到单片机等等…