C语言实现弹跳小球
1. 实现思路
本例中的弹跳小球,实质上就是一个在窗口中移动的小球,它有自己的坐标和移动方向,同时也有一定的大小和颜色。而在运动期间它还需要遇到窗口边界时进行反弹的操作,也就是改变移动方向。
基于此,我们可以考虑使用C语言结构体来存储小球的位置、大小、颜色和移动方向等信息,同时利用窗口显示库如SDL
或Qt
来实现小球在窗口中的运动和反弹效果。
2. 实现步骤
2.1 定义结构体
typedef struct _Ball {
int x; // 小球圆心x坐标
int y; // 小球圆心y坐标
int r; // 小球半径
int dx; // 小球x方向移动距离
int dy; // 小球y方向移动距离
int color; // 小球颜色
} Ball;
以上是小球结构体的定义,包含圆心坐标、半径、移动距离、颜色等属性,方便操作和维护。
2.2 处理窗口事件
while (!quit) {
// 处理窗口事件
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
} else {
// 其他事件
}
}
// 渲染小球
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, ball.color >> 16 & 0xFF, ball.color >> 8 & 0xFF, ball.color & 0xFF, 255);
SDL_RenderFillCircle(renderer, ball.x, ball.y, ball.r);
SDL_RenderPresent(renderer);
}
以上是主循环中处理窗口事件的代码,主要判断是否接收到了窗口关闭事件等操作。在此期间,我们将小球的绘制渲染放在了主循环外部,但是循环内部仍需更新小球坐标等信息。
2.3 实现小球移动和反弹
// 更新小球位置
ball.x += ball.dx;
ball.y += ball.dy;
// 检测是否越界
if (ball.x + ball.r > WIDTH) {
ball.x = WIDTH - ball.r;
ball.dx = -ball.dx;
} else if (ball.x - ball.r < 0) {
ball.x = ball.r;
ball.dx = -ball.dx;
}
if (ball.y + ball.r > HEIGHT) {
ball.y = HEIGHT - ball.r;
ball.dy = -ball.dy;
} else if (ball.y - ball.r < 0) {
ball.y = ball.r;
ball.dy = -ball.dy;
}
以上是小球运动及反弹的实现代码,在主循环每次迭代中会更新小球的位置坐标,并判断小球是否接触到了窗口边界,如果是,则将对应的移动方向改变即可。
2.4 渲染小球
// 渲染小球
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, ball.color >> 16 & 0xFF, ball.color >> 8 & 0xFF, ball.color & 0xFF, 255);
SDL_RenderFillCircle(renderer, ball.x, ball.y, ball.r);
SDL_RenderPresent(renderer);
以上是小球渲染的实现代码,在每次迭代更新小球位置后即进行渲染,利用窗口显示库提供的API即可实现圆形绘制,依靠每次重绘即可让小球在窗口中运动和反弹。
3. 示例如下
3.1 SDL版本
// 初始化SDL
SDL_Init(SDL_INIT_VIDEO);
// 创建窗口
SDL_Window* window = SDL_CreateWindow("Bouncing Ball", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, 0);
// 创建渲染器
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
// 圆形绘制API
bool SDL_RenderFillCircle(SDL_Renderer* renderer, int x, int y, int r)
// 参考实现:https://www.libsdl.org/cgi/docwiki.cgi/SDL_RenderDrawCircle
bool SDL_RenderFillCircle(SDL_Renderer* renderer, int x, int y, int r) {
int offsetx, offsety, d;
int status;
offsetx = 0;
offsety = r;
d = r - 1;
status = 0;
while (offsety >= offsetx) {
status += SDL_RenderDrawLine(renderer, x - offsety, y + offsetx, x + offsety, y + offsetx);
status += SDL_RenderDrawLine(renderer, x - offsetx, y + offsety, x + offsetx, y + offsety);
status += SDL_RenderDrawLine(renderer, x - offsetx, y - offsety, x + offsetx, y - offsety);
status += SDL_RenderDrawLine(renderer, x - offsety, y - offsetx, x + offsety, y - offsetx);
if (status < 0) {
return false;
}
if (d >= 2 * offsetx) {
d -= 2 * offsetx + 1;
offsetx += 1;
} else if (d < 2 * (r - offsety)) {
d += 2 * offsety - 1;
offsety -= 1;
} else {
d += 2 * (offsety - offsetx - 1);
offsety -= 1;
offsetx += 1;
}
}
return true;
}
// 其他部分请见代码
以上是基于SDL
实现的代码,其中圆形绘制的API是参考了libsdl
官方文档并稍做修改后编写。
3.2 Qt版本
// 实现渲染器
class BallRenderer : public QWidget {
Q_OBJECT
public:
BallRenderer(QWidget* parent = nullptr)
: QWidget(parent)
{
}
void setBall(const Ball& ball)
{
m_ball = ball;
update();
}
protected:
void paintEvent(QPaintEvent* event) override
{
QPainter painter(this);
painter.setBrush(QBrush(QColor(m_ball.color)));
painter.drawEllipse(QPointF(m_ball.x, m_ball.y), m_ball.r, m_ball.r);
}
private:
Ball m_ball;
};
// 操纵窗口和主循环
void MainWindow::play()
{
Ball ball;
ball.r = 30;
ball.x = ball.r + 10;
ball.y = HEIGHT / 2;
ball.dx = 5;
ball.dy = 5;
ball.color = QColor(Qt::green).rgb();
BallRenderer renderer(this);
renderer.setGeometry(rect().marginsRemoved(QMargins(10, 10, 10, 10)));
renderer.show();
while (true) {
// 更新小球位置
ball.x += ball.dx;
ball.y += ball.dy;
// 检测是否越界
if (ball.x + ball.r > WIDTH) {
ball.x = WIDTH - ball.r;
ball.dx = -ball.dx;
} else if (ball.x - ball.r < 0) {
ball.x = ball.r;
ball.dx = -ball.dx;
}
if (ball.y + ball.r > HEIGHT) {
ball.y = HEIGHT - ball.r;
ball.dy = -ball.dy;
} else if (ball.y - ball.r < 0) {
ball.y = ball.r;
ball.dy = -ball.dy;
}
// 绘制小球
renderer.setBall(ball);
qApp->processEvents();
}
}
以上是基于Qt
实现的代码,首先创建了一个自定义的渲染器BallRenderer
用于绘制小球,并在主窗口中包含了该渲染器。随后在主循环中不断更新小球的位置信息,然后利用构建好的渲染器中的绘制方法重绘即可实现小球的运动和反弹。
4. 总结
本文详细讲解了如何使用C语言实现弹跳小球的过程,先大致阐述了实现思路,随后表述了具体实现步骤,并以SDL和Qt两个窗口显示库为例分别给出了实现代码,供大家参考。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言实现弹跳小球 - Python技术站