概述
一直在学习C++,深感学习一门语言必须得下手实践,因此在网上找了很多小项目,但好多有都不感兴趣坚持不下来。近期突然发现河海大学童晶老师的书,是专门讲编写C++小游戏的例子,很感兴趣。我根据该书的例子然后也根据自己对C++的理解,尽量以新的方式重新实现。能力有限写的不好,大家可以自己优化。
另外需要说明的是,这些例子用到了EasyX图形库,自认为这个图形库是亮点童晶老师的书最大的亮点,它是针对 C/C++ 的图形库,最大的好处是效果可视化,大大降低了直接用C++实现图形的难度,也增加了趣味性和成就感。网址在这里:https://easyx.cn/。直接下载安装就可以。
开始前说几个用的多的快捷键:
选中需要注释的代码段,按Ctrl + K + C 即可快速注释;
选中需要取消注释的代码段,按Ctrl + K + U 即可取消注释。
实现效果和涉及的知识
本例子我们将模拟物理小球的运动的场景。
例子中我们会学习EasyX图形库函数、类、头文件和源文件、全局变量等。
文件结构
比较好的文件结构是:
为每一个模块都编写一个.c文件,一个.h文件。
.c文件:函数的定义,全局变量的定义,全局结构体变量的定义。
.h文件:函数的声明,全局变量的声明(extern),全局结构体的定义,全局结构体变量的声明。
然后main.c文件直接包含.h头文件即可。
具体代码
代码中有注释,可供参考。
FQF_CPP.cpp
// FQF_CPP.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
#include <iostream> // C++ STL 输入输出库
#include <graphics.h> // C++图形库(EasyX)
#include <conio.h> // console input/output:非cpp STL,定义了通过控制台进行输入输出的函数,如getch()
#include <stdio.h> // standard input&output:标准输入输出头文件,如scanf, printf
#include "ballXY.h" // 计算小球圆心坐标的头文件
#include "ifcollision.h" // 判断小球与边界碰撞的头文件
#include "data.h" // 全局变量
using namespace std;
int main()
{
ballXY ballxy;
ballxy.set_ballenvi(A, B, R, G, a, Tstep);
initgraph(A, B);
Sleep(1000);
ballxy.cal_ballxy(X, Y, VX, VY);
fillcircle(X, Y, R);
Sleep(1000);
while (1)
{
cleardevice();
float x = ballxy.get_ball_x();
float y = ballxy.get_ball_y();
float vx = ballxy.get_ball_vx();
float vy = ballxy.get_ball_vy();
fillcircle(x, y, R);
Sleep(20); // 延迟20ms,非标准库函数
ballxy.cal_ballxy(x, y, vx, vy);
}
//_getch(); // Get a character from the console
closegraph();
return 0;
}
ballXY.h
#pragma once
#ifndef BALLXY_H_
#define BALLXY_H_
class ballXY
{
private:
float A, B, R, G, a;
float x, y, vx, vy;
float Tstep;
public:
ballXY();
~ballXY();
void set_ballenvi(float W, float H, float r, float g, float f, float Tstep);
void cal_ballxy(float X, float Y, float Vx, float Vy);
float get_ball_x();
float get_ball_y();
float get_ball_vx();
float get_ball_vy();
};
#endif // !BALLXY_H_
ballXY.c
#include "ballXY.h"
#include "ifcollision.h"
#include <math.h>
#include "data.h"
ballXY::ballXY()
{
x = 0, y = 0, vx = 0, vy = 0; // 不要float是赋值,加了就是定义
}
ballXY::~ballXY()
{
}
void ballXY::set_ballenvi(float W, float H, float r, float g, float f, float tstep)
{
A = W;
B = H;
R = r;
G = g;
a = f;
Tstep = tstep;
}
void ballXY::cal_ballxy(float X, float Y, float Vx, float Vy)
{
int ifcoll = ifcollision(X, Y, R, A, B);
switch (ifcoll)
{
case 0:
vx = Vx * a;
vy = (Vy + G * Tstep) * a;
x = X + vx * Tstep;
y = Y + vy * Tstep;
break;
case 1:
vx = Vx * a;
vy = -1 * vy * a;
x = X + vx * Tstep;
y = Y + vy * Tstep;
if (y< R)
{
y = R;
}
break;
case 2:
vx = Vx * a*0.97;
vy = -1 * vy * a * 0.85;
x = X + vx * Tstep;
y = Y + vy * Tstep;
if (y > B - R)
{
y = B - R;
}
if (y > B - R - 2 && fabs(vy) < 1.04)
{
vy = 0;
y = y = B - R;
}
if (y > B - R - 2 && fabs(vy) < 1.04 && vx < 0.001)
{
//vx = 0;
}
break;
case 3:
vx = -vx * a;
vy = (Vy + G * Tstep) * a;
x = X + vx * Tstep;
y = Y + vy * Tstep;
if (x < 0)
{
x = 0;
}
break;
case 4:
vx = -vx * a;
vy = (Vy + G * Tstep) * a;
x = X + vx * Tstep;
y = Y + vy * Tstep;
if (x > A - R)
{
x = A - R;
}
break;
default:
break;
}
/*
if (fabs(Vx) <= 0.1)
{
vx = 0;
}
if (y > B - R - 0.5 && fabs(Vy) <= 0.05)
{
vy = 0;
}*/
}
float ballXY::get_ball_x()
{
return x;
}
float ballXY::get_ball_y()
{
return y;
}
float ballXY::get_ball_vx()
{
return vx;
}
float ballXY::get_ball_vy()
{
return vy;
}
ifcollsion.h
#pragma once
#ifndef IFCOLLISION_H_
#define IFCOLLISION_H_
extern int ifcollision(float X, float Y, float r, float A, float B);
#endif // !1
ifcollsion.cpp
#include "ifcollision.h"
int ifcollision(float X, float Y, float r, float A, float B)
{
int ifcoll = 0;
if (Y - r <= 0)
{
ifcoll = 1;
};
if (Y + r >= B)
{
ifcoll = 2;
};
if (X - r <= 0)
{
ifcoll = 3;
};
if (X + r >= A)
{
ifcoll = 4;
}
return ifcoll;
}
data.h
#pragma once
#ifndef DATA_H_
#define DATA_H_
extern float A, B, R, G, a, Tstep;
extern float X, Y, VX, VY;
#endif // !DATA_H_
data.cpp
// 全局变量
float A = 400, B = 600, R = 10, G = 9.8, a = 0.99, Tstep = 0.4;
float X = 150, Y = 450, VX = 100, VY = -200;