raylib U3 - 反弹球 - 用数组和结构体管理小球

说明

从这一部分开始,是一些常用的功能或者小例子,涉及到的功能和代码复杂度会比较高,代码中也会加入越来越多的算法。

让小球做反弹运动

上一篇文章,我们让小球动力起来。接下来咱们让小球做个反弹运动。

在讲反弹运动之前,先来了解一下屏幕上绘制元素的坐标系:

image

窗口的布局,都是从左上角开始的。

  • 左上角是0,0点;
  • 往左是横轴,往下是纵轴(并且往下是正的);
  • 任何一个元素都是以矩形的方式来定位的;
  • 元素的左上角表示坐标。

那我们怎么判断小球到了边界呢?以碰到右边界为例,看下面的图
image

先理解下关键代码来:
image

点击可以复制完整的代码:
#include <raylib.h>
#include<bits/stdc++.h>
using namespace std;
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600

int main() {
	
	InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT,"Test");
	SetTargetFPS(60);
	
	Image img=GenImageColor(40,40,BLANK);
	ImageDrawCircle(&img,20,20,19,RED);
	Texture ball = LoadTextureFromImage(img);
	UnloadImage(img);
	
	int x=0,y=0;//x和y坐标 
	int speedx=8,speedy=3;//坐标的改变速度 

	while (!WindowShouldClose()) {
		
		//判断本次运动,是否会碰到边界 
		if(x+speedx>=WINDOW_WIDTH-40 || x+speedx<=0){
			speedx*=-1;
		}
		if(y+speedy>=WINDOW_HEIGHT-40 || y+speedy<=0){
			speedy*=-1;
		} 
		x+=speedx;
		y+=speedy;
		
		BeginDrawing();
		ClearBackground(WHITE);
		DrawTexture(ball,x,y,WHITE);
		EndDrawing();
	}
	
	//释放texture对象
	UnloadTexture(ball); 
	
	
	//关闭窗口
	CloseWindow();
	return 0;
}

把小球封装一下

上面我们一个小球的反弹就用了5个变量,那如果5个小球呢?用数组的话,5个数组也麻烦呀。所以咱们得封装~~~

image

结构体大家都认识吧。
Texture也是一个结构体,所以咱们可以直接在结构体里使用。raylib都是用C实现的,很牛逼啊!

封装之后我们就可以用数组来管理多个小球了。

image

判断的时候也是直接用数组,套个循环
image

循环绘制
image

结束后循环释放空间
image

点击复制完整代码
#include <raylib.h>
#include<bits/stdc++.h>
using namespace std;
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600

struct Ball{
	Texture t;
	int x,y;
	int speedx,speedy;
};

int main() {
	
	InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT,"Test");
	SetTargetFPS(60);
	
	Ball ballarray[5];
	for(int i=0;i<5;++i){
		Image img=GenImageColor(40,40,BLANK);
		ImageDrawCircle(&img,20,20,19,RED);
		ballarray[i].t = LoadTextureFromImage(img);
		UnloadImage(img);
		
		ballarray[i].x=0;
		ballarray[i].y=0;
		
		//这里用个简单的方式让小球有不同的速度。
		//大家也可以研究下随机数
		ballarray[i].speedx=(6-i);
		ballarray[i].speedy=(6+i);
	}

	while (!WindowShouldClose()) {
		
		for(int i=0;i<5;++i){
			//判断本次运动后,是否碰到了边界 
			if(ballarray[i].x+ballarray[i].speedx>=WINDOW_WIDTH-40 || ballarray[i].x+ballarray[i].speedx<=0){
				ballarray[i].speedx*=-1;
			}
			if(ballarray[i].y+ballarray[i].speedy>=WINDOW_HEIGHT-40 || ballarray[i].y+ballarray[i].speedy<=0){
				ballarray[i].speedy*=-1;
			} 
			ballarray[i].x+=ballarray[i].speedx;
			ballarray[i].y+=ballarray[i].speedy;
		}
		
		
		//绘制帧,这一Part都是放在循环的最后的
		BeginDrawing();//开始绘制
		ClearBackground(WHITE);//重新绘制一些背景。
		
		for(int i=0;i<5;++i){
			DrawTexture(ballarray[i].t,ballarray[i].x,ballarray[i].y,WHITE);
		}
		
		EndDrawing();//结束绘制
	}
	
	//释放texture对象
	for(int i=0;i<5;++i){
		UnloadTexture(ballarray[i].t); 
	}
	
	
	//关闭窗口
	CloseWindow();
	return 0;
}

posted @ 2024-12-28 15:06  一亩食堂  阅读(209)  评论(0)    收藏  举报