raylib U3 - 对开始按钮的封装

这一篇实现的效果还是开始按钮,但是在代码上做了大量的封装。
在实现复杂功能的时候,把重复的代码封装起来,是编程必须掌握的技能。
后面我们会再用class类来做一次封装。

主要的修改:

  1. 把按钮相关的功能都用结构体封装了,尽量让main函数里的代码更简洁。
  2. 使用raylib自带的碰撞检测。

上代码:

#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;
};

//创建一个枚举类型,表示按钮的状态。
enum startState{
	normal,
	hover,
	pressed
};

struct Button{
	Texture normal;
	Texture hover;
	Texture pressed;
	Rectangle frame;
	startState cstate;//当前状态
	
	void unload(){
		UnloadTexture(normal);
		UnloadTexture(hover);
		UnloadTexture(pressed);
	}
	void setframe(int x,int y,int width,int height){
		frame.x = x;
		frame.y = y;
		frame.width=width;
		frame.height=height;
	}
	
    //下面是三个按钮的图片
	void setNormalImage(const char *filename){
		Image startimg=LoadImage(filename);
		normal = LoadTextureFromImage(startimg);
		UnloadImage(startimg);
	}
	void setHoverImage(const char *filename){
		Image startimg=LoadImage(filename);
		hover = LoadTextureFromImage(startimg);
		UnloadImage(startimg);
	}
	void setPressedImage(const char *filename){
		Image startimg=LoadImage(filename);
		pressed = LoadTextureFromImage(startimg);
		UnloadImage(startimg);
	}
};

//创建一个变量,用来管理程序状态
int state=0;

int main() {
	
	InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT,"Test");
	SetTargetFPS(60);
	
    //用结构体实例实现开始按钮 ,main函数里的代码越少,我们实现复杂的功能就可以更清晰
	Button startbtn;
	startbtn.cstate = normal;
	startbtn.setframe((WINDOW_WIDTH-200)/2,(WINDOW_HEIGHT-200)/2,200,200);
	startbtn.setNormalImage("start_normal.png");
	startbtn.setHoverImage("start_hover.png");
	startbtn.setPressedImage("start_pressed.png");
	
	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()) {
		
		if(state==0){
			//开始菜单,如果点击了,把state改成1就行了
			Vector2 mp = GetMousePosition();
			
			if(IsMouseButtonUp(MOUSE_BUTTON_LEFT)){
				startbtn.cstate=normal;
					
				//判断鼠标是否在按钮的区域
				if(CheckCollisionPointRec(mp,startbtn.frame)){
					startbtn.cstate = hover;
				}
			}
			if(IsMouseButtonPressed(MOUSE_BUTTON_LEFT)){
				startbtn.cstate=normal;
				//判断鼠标是否在按钮的区域
				if(CheckCollisionPointRec(mp,startbtn.frame)){
					startbtn.cstate = pressed;
				}
			}
			if(IsMouseButtonReleased(MOUSE_BUTTON_LEFT)){
				if(CheckCollisionPointRec(mp,startbtn.frame)){
					state=1;
				}
			}
		}
		else if(state==1){
			//游戏进行
			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;
			}
		}
		else if(state==2){
			//游戏结束
		}
		
		BeginDrawing();
		ClearBackground(WHITE);
		if(state==0){
			//开始菜单
			if(startbtn.cstate == normal)
				DrawTexture(startbtn.normal,startbtn.frame.x,startbtn.frame.y,WHITE);
			else if(startbtn.cstate == hover)
				DrawTexture(startbtn.hover,startbtn.frame.x,startbtn.frame.y,WHITE);
			else if(startbtn.cstate == pressed)
				DrawTexture(startbtn.pressed,startbtn.frame.x,startbtn.frame.y,WHITE);
		}
		else if(state==1){
			//游戏进行
			for(int i=0;i<5;++i){
				DrawTexture(ballarray[i].t,ballarray[i].x,ballarray[i].y,WHITE);
			}
		}
		else if(state==2){
			//游戏结束
		}
		
		EndDrawing();//结束绘制
	}
	
	//释放texture对象
	for(int i=0;i<5;++i){
		UnloadTexture(ballarray[i].t); 
	}

    //调用结构体的释放函数
	startbtn.unload();
	//关闭窗口
	CloseWindow();
	return 0;
}


posted @ 2025-02-12 11:16  一亩食堂  阅读(103)  评论(0)    收藏  举报