c语言实现七巧板,能够旋转和拖拽
时间: 2023-06-24 10:08:40 浏览: 206
实现七巧板需要用到图形库,例如使用OpenGL或者SDL来实现。下面是一个基本的实现思路:
1. 定义七个不同形状的木块,可以使用一个结构体来表示,结构体中包含坐标信息、颜色信息和顶点信息等。
2. 使用图形库绘制出七个木块,并将它们组合成七巧板的形状。
3. 实现旋转功能,可以使用鼠标点击木块并拖动来实现旋转。在鼠标按下时记录当前坐标,然后根据鼠标移动的距离计算出旋转角度,最后更新坐标信息并重绘图形。
4. 实现拖拽功能,可以使用鼠标点击并拖动来移动木块。在鼠标按下时记录当前坐标,然后根据鼠标移动的距离更新坐标信息并重绘图形。
5. 实现碰撞检测,保证七个木块不会重叠或者越界。
这里提供一个基于SDL2的简单实现示例(仅供参考):
```c
#include <stdio.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
typedef struct {
int x, y; // 坐标
int w, h; // 宽度和高度
SDL_Color color; // 颜色
SDL_Point vertices[4]; // 四个顶点
float angle; // 旋转角度
} Block;
// 定义七个不同形状的木块
Block blocks[7] = {
{100, 100, 80, 80, {255, 0, 0, 255}, {{0, 0}, {80, 0}, {80, 80}, {0, 80}}, 0},
{200, 200, 80, 40, {0, 255, 0, 255}, {{0, 0}, {80, 0}, {80, 40}, {0, 40}}, 0},
{300, 300, 60, 60, {0, 0, 255, 255}, {{0, 0}, {60, 0}, {60, 60}, {0, 60}}, 0},
{400, 400, 40, 80, {255, 255, 0, 255}, {{0, 0}, {40, 0}, {40, 80}, {0, 80}}, 0},
{500, 100, 80, 80, {255, 0, 255, 255}, {{0, 0}, {80, 0}, {80, 80}, {0, 80}}, 0},
{400, 200, 60, 60, {0, 255, 255, 255}, {{0, 0}, {60, 0}, {60, 60}, {0, 60}}, 0},
{300, 400, 40, 80, {255, 255, 255, 255}, {{0, 0}, {40, 0}, {40, 80}, {0, 80}}, 0}
};
// 记录当前选中的木块索引
int selected_block = -1;
// 判断是否在矩形内部
bool inside_rect(SDL_Point point, SDL_Rect rect) {
return point.x >= rect.x && point.x <= rect.x + rect.w
&& point.y >= rect.y && point.y <= rect.y + rect.h;
}
// 绘制一个矩形
void draw_rect(SDL_Renderer* renderer, SDL_Rect rect, SDL_Color color) {
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
SDL_RenderDrawRect(renderer, &rect);
}
// 绘制一个填充矩形
void fill_rect(SDL_Renderer* renderer, SDL_Rect rect, SDL_Color color) {
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
SDL_RenderFillRect(renderer, &rect);
}
// 绘制一个多边形
void draw_polygon(SDL_Renderer* renderer, SDL_Point* vertices, int count, SDL_Color color) {
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
SDL_RenderDrawLines(renderer, vertices, count + 1);
}
// 绘制一个填充多边形
void fill_polygon(SDL_Renderer* renderer, SDL_Point* vertices, int count, SDL_Color color) {
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
SDL_RenderFillPolygon(renderer, vertices, count);
}
// 旋转一个点
SDL_Point rotate_point(SDL_Point point, SDL_Point center, float angle) {
SDL_Point new_point;
float s = sin(angle);
float c = cos(angle);
new_point.x = center.x + (point.x - center.x) * c - (point.y - center.y) * s;
new_point.y = center.y + (point.x - center.x) * s + (point.y - center.y) * c;
return new_point;
}
// 旋转一个矩形
SDL_Rect rotate_rect(SDL_Rect rect, SDL_Point center, float angle) {
SDL_Rect new_rect;
SDL_Point vertices[4] = {
{rect.x, rect.y},
{rect.x + rect.w, rect.y},
{rect.x + rect.w, rect.y + rect.h},
{rect.x, rect.y + rect.h}
};
for (int i = 0; i < 4; i++) {
vertices[i] = rotate_point(vertices[i], center, angle);
}
int min_x = vertices[0].x, max_x = vertices[0].x, min_y = vertices[0].y, max_y = vertices[0].y;
for (int i = 1; i < 4; i++) {
if (vertices[i].x < min_x) min_x = vertices[i].x;
if (vertices[i].x > max_x) max_x = vertices[i].x;
if (vertices[i].y < min_y) min_y = vertices[i].y;
if (vertices[i].y > max_y) max_y = vertices[i].y;
}
new_rect.x = min_x;
new_rect.y = min_y;
new_rect.w = max_x - min_x;
new_rect.h = max_y - min_y;
return new_rect;
}
int main(int argc, char* argv[]) {
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
SDL_Event event;
bool quit = false;
SDL_Rect screen_rect = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
SDL_Point mouse_down_pos = {0, 0};
SDL_Point mouse_up_pos = {0, 0};
SDL_Point mouse_pos = {0, 0};
float mouse_down_angle = 0;
float mouse_up_angle = 0;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL_Init failed: %s\n", SDL_GetError());
return -1;
}
window = SDL_CreateWindow("七巧板", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (window == NULL) {
printf("SDL_CreateWindow failed: %s\n", SDL_GetError());
return -1;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL) {
printf("SDL_CreateRenderer failed: %s\n", SDL_GetError());
return -1;
}
while (!quit) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
} else if (event.type == SDL_MOUSEBUTTONDOWN) {
mouse_down_pos.x = event.button.x;
mouse_down_pos.y = event.button.y;
// 判断是否点击到了木块
for (int i = 0; i < 7; i++) {
if (inside_rect(mouse_down_pos, blocks[i])) {
selected_block = i;
mouse_down_angle = blocks[i].angle;
break;
}
}
} else if (event.type == SDL_MOUSEBUTTONUP) {
mouse_up_pos.x = event.button.x;
mouse_up_pos.y = event.button.y;
// 计算旋转角度
if (selected_block != -1) {
float dx = mouse_up_pos.x - mouse_down_pos.x;
float dy = mouse_up_pos.y - mouse_down_pos.y;
mouse_up_angle = atan2(dy, dx);
float angle = mouse_up_angle - mouse_down_angle;
blocks[selected_block].angle += angle;
selected_block = -1;
}
} else if (event.type == SDL_MOUSEMOTION) {
mouse_pos.x = event.motion.x;
mouse_pos.y = event.motion.y;
// 移动木块
if (selected_block != -1) {
blocks[selected_block].x += mouse_pos.x - mouse_down_pos.x;
blocks[selected_block].y += mouse_pos.y - mouse_down_pos.y;
mouse_down_pos = mouse_pos;
}
}
}
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer);
// 绘制七巧板
for (int i = 0; i < 7; i++) {
Block block = blocks[i];
SDL_Rect rect = {block.x, block.y, block.w, block.h};
SDL_Point center = {block.x + block.w / 2, block.y + block.h / 2};
SDL_Point vertices[4] = {
{block.x, block.y},
{block.x + block.w, block.y},
{block.x + block.w, block.y + block.h},
{block.x, block.y + block.h}
};
for (int j = 0; j < 4; j++) {
vertices[j] = rotate_point(vertices[j], center, block.angle);
}
fill_polygon(renderer, vertices, 4, block.color);
draw_polygon(renderer, vertices, 4, {0, 0, 0, 255});
}
SDL_RenderPresent(renderer);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
```
这是一个简单的示例代码,实现了七巧板的旋转和拖拽功能,但是没有实现碰撞检测等高级功能,读者可以自行进行扩展和优化。
阅读全文