C语言游戏开发:Pygame、SDL、OpenGL深度解析

C语言游戏开发:Pygame、SDL、OpenGL深度解析

C语言游戏开发:Pygame、SDL、OpenGL深度解析

在这里插入图片描述

一、前言:为什么游戏开发是C语言开发的重要技能?

学习目标

  • 理解游戏开发的本质:编写程序实现游戏逻辑、图形渲染、用户交互
  • 明确游戏开发的重要性:支撑游戏产业的发展,成为游戏开发者的必备技能
  • 掌握本章学习重点:Pygame、SDL、OpenGL的开发方法、避坑指南、实战案例分析
  • 学会使用C语言开发游戏,实现游戏逻辑和用户交互

重点提示

💡 游戏开发是C语言开发的重要技能!随着游戏产业的发展,游戏开发的需求越来越大,C语言的高性能和可移植性使其在游戏开发中具有重要地位。


二、模块1:Pygame游戏开发基础

2.1 学习目标

  • 理解Pygame的本质:基于SDL的Python游戏库,简化游戏开发
  • 掌握Pygame的核心架构:窗口管理、事件处理、图形渲染、音频播放
  • 掌握Pygame的开发方法:使用Pygame库进行游戏开发
  • 掌握Pygame的避坑指南:避免窗口创建失败、避免图形渲染错误、避免事件处理错误
  • 避开Pygame使用的3大常见坑

2.2 Pygame的核心架构

窗口管理:创建和管理窗口
事件处理:处理键盘、鼠标、触摸等输入事件
图形渲染:使用Surface进行图形绘制
音频播放:播放音频文件

2.3 Pygame的开发方法

代码示例1:Pygame窗口创建

import pygame import sys # 初始化Pygame pygame.init()# 设置窗口大小和标题 screen_width =800 screen_height =600 screen = pygame.display.set_mode((screen_width, screen_height)) pygame.display.set_caption("Pygame窗口创建")# 设置背景颜色 background_color =(255,255,255)# 游戏循环 running =Truewhile running:# 事件处理for event in pygame.event.get():if event.type== pygame.QUIT: running =False# 填充背景颜色 screen.fill(background_color)# 更新显示 pygame.display.flip()# 退出Pygame pygame.quit() sys.exit()

代码示例2:Pygame绘制图形

import pygame import sys # 初始化Pygame pygame.init()# 设置窗口大小和标题 screen_width =800 screen_height =600 screen = pygame.display.set_mode((screen_width, screen_height)) pygame.display.set_caption("Pygame绘制图形")# 设置颜色 white =(255,255,255) red =(255,0,0) blue =(0,0,255) green =(0,255,0)# 游戏循环 running =Truewhile running:# 事件处理for event in pygame.event.get():if event.type== pygame.QUIT: running =False# 填充背景颜色 screen.fill(white)# 绘制矩形 rect = pygame.Rect(300,200,200,200) pygame.draw.rect(screen, red, rect)# 绘制圆形 pygame.draw.circle(screen, blue,(400,300),100)# 绘制线条 pygame.draw.line(screen, green,(100,100),(700,500),5)# 更新显示 pygame.display.flip()# 退出Pygame pygame.quit() sys.exit()

三、模块2:SDL游戏开发基础

3.1 学习目标

  • 理解SDL的本质:Simple DirectMedia Layer,跨平台图形、音频、输入库
  • 掌握SDL的核心架构:窗口管理、事件处理、图形渲染、音频播放
  • 掌握SDL的开发方法:使用SDL 2.0库进行游戏开发
  • 掌握SDL的避坑指南:避免窗口创建失败、避免图形渲染错误、避免事件处理错误
  • 避开SDL使用的3大常见坑

3.2 SDL的核心架构

窗口管理:创建和管理窗口
事件处理:处理键盘、鼠标、触摸等输入事件
图形渲染:使用渲染器绘制图形
音频播放:播放音频文件

3.3 SDL的开发方法

代码示例3:SDL窗口创建

#include<SDL.h>intmain(int argc,char*argv[]){ SDL_Window *window =NULL; SDL_Renderer *renderer =NULL;// 初始化SDLif(SDL_Init(SDL_INIT_VIDEO)<0){fprintf(stderr,"SDL初始化失败:%s\n",SDL_GetError());return0;}// 创建窗口 window =SDL_CreateWindow("SDL窗口", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,800,600, SDL_WINDOW_SHOWN );if(window ==NULL){fprintf(stderr,"窗口创建失败:%s\n",SDL_GetError());SDL_Quit();return0;}// 创建渲染器 renderer =SDL_CreateRenderer(window,-1, SDL_RENDERER_ACCELERATED);if(renderer ==NULL){fprintf(stderr,"渲染器创建失败:%s\n",SDL_GetError());SDL_DestroyWindow(window);SDL_Quit();return0;}// 设置渲染器颜色SDL_SetRenderDrawColor(renderer,255,255,255,255);SDL_RenderClear(renderer);SDL_RenderPresent(renderer);// 事件循环 SDL_Event event;int quit =0;while(!quit){while(SDL_PollEvent(&event)){if(event.type == SDL_QUIT){ quit =1;}}}// 清理资源SDL_DestroyRenderer(renderer);SDL_DestroyWindow(window);SDL_Quit();return0;}

代码示例4:SDL绘制图形

#include<SDL.h>intmain(int argc,char*argv[]){ SDL_Window *window =NULL; SDL_Renderer *renderer =NULL;// 初始化SDLif(SDL_Init(SDL_INIT_VIDEO)<0){fprintf(stderr,"SDL初始化失败:%s\n",SDL_GetError());return0;}// 创建窗口 window =SDL_CreateWindow("SDL绘制图形", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,800,600, SDL_WINDOW_SHOWN );if(window ==NULL){fprintf(stderr,"窗口创建失败:%s\n",SDL_GetError());SDL_Quit();return0;}// 创建渲染器 renderer =SDL_CreateRenderer(window,-1, SDL_RENDERER_ACCELERATED);if(renderer ==NULL){fprintf(stderr,"渲染器创建失败:%s\n",SDL_GetError());SDL_DestroyWindow(window);SDL_Quit();return0;}// 绘制图形SDL_SetRenderDrawColor(renderer,255,255,255,255);SDL_RenderClear(renderer);// 绘制矩形 SDL_Rect rect ={300,200,200,200};SDL_SetRenderDrawColor(renderer,255,0,0,255);SDL_RenderFillRect(renderer,&rect);// 绘制圆形int x =400, y =300, r =100;SDL_SetRenderDrawColor(renderer,0,0,255,255);for(int i = x - r; i <= x + r; i++){for(int j = y - r; j <= y + r; j++){int dx = i - x;int dy = j - y;if(dx * dx + dy * dy <= r * r){SDL_RenderDrawPoint(renderer, i, j);}}}// 绘制线条SDL_SetRenderDrawColor(renderer,0,255,0,255);SDL_RenderDrawLine(renderer,100,100,700,500);SDL_RenderPresent(renderer);// 事件循环 SDL_Event event;int quit =0;while(!quit){while(SDL_PollEvent(&event)){if(event.type == SDL_QUIT){ quit =1;}}}// 清理资源SDL_DestroyRenderer(renderer);SDL_DestroyWindow(window);SDL_Quit();return0;}

四、模块3:OpenGL游戏开发基础

4.1 学习目标

  • 理解OpenGL的本质:跨平台图形库,用于3D和2D图形渲染
  • 掌握OpenGL的核心架构:上下文管理、着色器、顶点缓冲、纹理
  • 掌握OpenGL的开发方法:使用OpenGL 3.3+核心模式进行游戏开发
  • 掌握OpenGL的避坑指南:避免上下文创建失败、避免着色器编译错误、避免渲染错误
  • 避开OpenGL使用的3大常见坑

4.2 OpenGL的核心架构

上下文管理:创建和管理OpenGL上下文
着色器:顶点着色器和片段着色器,负责图形渲染
顶点缓冲:存储顶点数据
纹理:存储图像数据

4.3 OpenGL的开发方法

代码示例5:OpenGL三角形绘制

#include<stdio.h>#include<stdlib.h>#include<GL/glew.h>#include<GLFW/glfw3.h>const GLchar *vertexSource ="#version 330 core\n""layout (location = 0) in vec3 position;\n""void main() {\n"" gl_Position = vec4(position, 1.0);\n""}\n";const GLchar *fragmentSource ="#version 330 core\n""out vec4 color;\n""void main() {\n"" color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n""}\n";intmain(){// 初始化GLFWif(!glfwInit()){fprintf(stderr,"GLFW初始化失败!\n");return0;}// 配置GLFWglfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);// 创建窗口 GLFWwindow* window =glfwCreateWindow(800,600,"OpenGL三角形绘制",NULL,NULL);if(window ==NULL){fprintf(stderr,"窗口创建失败!\n");glfwTerminate();return0;}glfwMakeContextCurrent(window);// 初始化GLEWif(glewInit()!= GLEW_OK){fprintf(stderr,"GLEW初始化失败!\n");glfwTerminate();return0;}// 设置视口int width, height;glfwGetFramebufferSize(window,&width,&height);glViewport(0,0, width, height);// 顶点数据 GLfloat vertices[]={-0.5f,-0.5f,0.0f,0.5f,-0.5f,0.0f,0.0f,0.5f,0.0f};// 创建顶点缓冲对象 GLuint VBO, VAO;glGenVertexArrays(1,&VAO);glGenBuffers(1,&VBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER,sizeof(vertices), vertices, GL_STATIC_DRAW);// 编译顶点着色器 GLuint vertexShader =glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader,1,&vertexSource,NULL);glCompileShader(vertexShader); GLint success; GLchar infoLog[512];glGetShaderiv(vertexShader, GL_COMPILE_STATUS,&success);if(!success){glGetShaderInfoLog(vertexShader,512,NULL, infoLog);fprintf(stderr,"顶点着色器编译失败:%s\n", infoLog);}// 编译片段着色器 GLuint fragmentShader =glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader,1,&fragmentSource,NULL);glCompileShader(fragmentShader);glGetShaderiv(fragmentShader, GL_COMPILE_STATUS,&success);if(!success){glGetShaderInfoLog(fragmentShader,512,NULL, infoLog);fprintf(stderr,"片段着色器编译失败:%s\n", infoLog);}// 链接着色器程序 GLuint shaderProgram =glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);glGetProgramiv(shaderProgram, GL_LINK_STATUS,&success);if(!success){glGetProgramInfoLog(shaderProgram,512,NULL, infoLog);fprintf(stderr,"着色器程序链接失败:%s\n", infoLog);}glDeleteShader(vertexShader);glDeleteShader(fragmentShader);// 配置顶点属性glVertexAttribPointer(0,3, GL_FLOAT, GL_FALSE,3*sizeof(GLfloat),(GLvoid*)0);glEnableVertexAttribArray(0);glBindBuffer(GL_ARRAY_BUFFER,0);glBindVertexArray(0);// 渲染循环while(!glfwWindowShouldClose(window)){glfwPollEvents();// 清除颜色缓冲glClearColor(0.2f,0.3f,0.3f,1.0f);glClear(GL_COLOR_BUFFER_BIT);// 使用着色器程序glUseProgram(shaderProgram);// 绑定顶点数组对象glBindVertexArray(VAO);// 绘制三角形glDrawArrays(GL_TRIANGLES,0,3);glBindVertexArray(0);// 交换缓冲glfwSwapBuffers(window);}// 清理资源glDeleteVertexArrays(1,&VAO);glDeleteBuffers(1,&VBO);glDeleteProgram(shaderProgram);// 终止GLFWglfwTerminate();return0;}

五、模块4:实战案例分析——使用SDL实现简单的游戏

5.1 学习目标

  • 掌握使用SDL实现简单的游戏:通过SDL库实现一个简单的贪吃蛇游戏
  • 学会使用SDL的窗口管理、渲染、事件处理功能
  • 避开实战案例使用的3大常见坑

5.2 使用SDL实现简单的游戏

代码示例6:贪吃蛇游戏

#include<SDL.h>#include<stdio.h>#include<stdlib.h>#include<time.h>#defineSCREEN_WIDTH800#defineSCREEN_HEIGHT600#defineGRID_SIZE20#defineGRID_WIDTH(SCREEN_WIDTH / GRID_SIZE)#defineGRID_HEIGHT(SCREEN_HEIGHT / GRID_SIZE)#defineINITIAL_SNAKE_LENGTH3#defineSNAKE_SPEED100typedefstruct{int x;int y;} Point;typedefstruct{ Point head; Point body[100];int length;int direction;// 0: up, 1: right, 2: down, 3: left} Snake;typedefstruct{ Point position;int active;} Food;voidinit_snake(Snake *snake){ snake->length = INITIAL_SNAKE_LENGTH; snake->direction =1;// right snake->head.x = GRID_WIDTH /2; snake->head.y = GRID_HEIGHT /2;for(int i =1; i < snake->length; i++){ snake->body[i -1].x = snake->head.x - i; snake->body[i -1].y = snake->head.y;}}voiddraw_snake(SDL_Renderer *renderer, Snake *snake){SDL_SetRenderDrawColor(renderer,0,255,0,255); SDL_Rect head_rect ={snake->head.x * GRID_SIZE, snake->head.y * GRID_SIZE, GRID_SIZE, GRID_SIZE};SDL_RenderFillRect(renderer,&head_rect);for(int i =0; i < snake->length -1; i++){ SDL_Rect body_rect ={snake->body[i].x * GRID_SIZE, snake->body[i].y * GRID_SIZE, GRID_SIZE, GRID_SIZE};SDL_RenderFillRect(renderer,&body_rect);}}voidupdate_snake(Snake *snake,int*game_over){for(int i = snake->length -2; i >=0; i--){ snake->body[i +1]= snake->body[i];} snake->body[0]= snake->head;switch(snake->direction){case0:// up snake->head.y--;break;case1:// right snake->head.x++;break;case2:// down snake->head.y++;break;case3:// left snake->head.x--;break;}if(snake->head.x <0|| snake->head.x >= GRID_WIDTH || snake->head.y <0|| snake->head.y >= GRID_HEIGHT){*game_over =1;}for(int i =0; i < snake->length -1; i++){if(snake->head.x == snake->body[i].x && snake->head.y == snake->body[i].y){*game_over =1;}}}voidgenerate_food(Food *food, Snake *snake){int valid_position =0;while(!valid_position){ food->position.x =rand()% GRID_WIDTH; food->position.y =rand()% GRID_HEIGHT; valid_position =1;if(food->position.x == snake->head.x && food->position.y == snake->head.y){ valid_position =0;}for(int i =0; i < snake->length -1; i++){if(food->position.x == snake->body[i].x && food->position.y == snake->body[i].y){ valid_position =0;}}} food->active =1;}voiddraw_food(SDL_Renderer *renderer, Food *food){if(food->active){SDL_SetRenderDrawColor(renderer,255,0,0,255); SDL_Rect rect ={food->position.x * GRID_SIZE, food->position.y * GRID_SIZE, GRID_SIZE, GRID_SIZE};SDL_RenderFillRect(renderer,&rect);}}voidcheck_collision(Snake *snake, Food *food){if(snake->head.x == food->position.x && snake->head.y == food->position.y){ snake->length++; food->active =0;generate_food(food, snake);}}intmain(int argc,char*argv[]){ SDL_Window *window =NULL; SDL_Renderer *renderer =NULL;if(SDL_Init(SDL_INIT_VIDEO)<0){fprintf(stderr,"SDL初始化失败:%s\n",SDL_GetError());return0;} window =SDL_CreateWindow("贪吃蛇游戏", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );if(window ==NULL){fprintf(stderr,"窗口创建失败:%s\n",SDL_GetError());SDL_Quit();return0;} renderer =SDL_CreateRenderer(window,-1, SDL_RENDERER_ACCELERATED);if(renderer ==NULL){fprintf(stderr,"渲染器创建失败:%s\n",SDL_GetError());SDL_DestroyWindow(window);SDL_Quit();return0;}srand(time(NULL)); Snake snake;init_snake(&snake); Food food; food.active =0;generate_food(&food,&snake);int game_over =0;int last_time =SDL_GetTicks();int frame_time =0; SDL_Event event;while(!game_over){int current_time =SDL_GetTicks();int delta_time = current_time - last_time; last_time = current_time; frame_time += delta_time;while(SDL_PollEvent(&event)){if(event.type == SDL_QUIT){ game_over =1;}elseif(event.type == SDL_KEYDOWN){switch(event.key.keysym.sym){case SDLK_UP:if(snake.direction !=2){ snake.direction =0;}break;case SDLK_RIGHT:if(snake.direction !=3){ snake.direction =1;}break;case SDLK_DOWN:if(snake.direction !=0){ snake.direction =2;}break;case SDLK_LEFT:if(snake.direction !=1){ snake.direction =3;}break;}}}if(frame_time >= SNAKE_SPEED){update_snake(&snake,&game_over);check_collision(&snake,&food); frame_time =0;}SDL_SetRenderDrawColor(renderer,0,0,0,255);SDL_RenderClear(renderer);draw_snake(renderer,&snake);draw_food(renderer,&food);SDL_RenderPresent(renderer);SDL_Delay(16);// 限制帧率在60FPS}SDL_DestroyRenderer(renderer);SDL_DestroyWindow(window);SDL_Quit();return0;}

六、本章总结与课后练习

6.1 总结

Pygame游戏开发:基于SDL的Python游戏库,简化游戏开发
SDL游戏开发:跨平台图形、音频、输入库,适合游戏开发
OpenGL游戏开发:跨平台图形库,用于3D和2D图形渲染
实战案例分析:使用SDL实现简单的贪吃蛇游戏

6.2 课后练习

  1. 编写程序:使用Pygame创建窗口并绘制图形
  2. 编写程序:使用Pygame处理键盘和鼠标事件
  3. 编写程序:使用Pygame播放音频
  4. 编写程序:使用SDL创建窗口并绘制图形
  5. 编写程序:使用SDL处理键盘和鼠标事件
  6. 编写程序:使用SDL播放音频
  7. 编写程序:使用OpenGL绘制三角形
  8. 编写程序:使用OpenGL绘制矩形
  9. 编写程序:使用OpenGL加载并显示纹理
  10. 编写程序:使用SDL和OpenGL结合开发3D游戏

Read more

2024最新版Node.js下载安装及环境配置教程(非常详细)

一、进入官网地址下载安装包 官网:Node.js — Run JavaScript Everywhere 其他版本下载:Node.js — Download Node.js? (nodejs.org) 选择对应你系统的Node.js版本 二、安装程序 (1)下载完成后,双击安装包,开始安装Node.js (2)直接点【Next】按钮,此处可根据个人需求修改安装路径,我这里路径改为了D:Program Files odejs,修改完毕后继续点击【Next】按钮 (3)可根据自身需求进行,此处我选择默认安装,继续点击【Next】按钮 (4)不选中,直接点击【Next】按钮 (5)点击【

By Ne0inhk
PostgreSQL:逻辑复制与物理复制

PostgreSQL:逻辑复制与物理复制

🧑 博主简介:ZEEKLOG博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c=1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编程,高并发设计,Springboot和微服务,熟悉Linux,ESXI虚拟化以及云原生Docker和K8s,热衷于探索科技的边界,并将理论知识转化为实际应用。保持对新技术的好奇心,乐于分享所学,希望通过我的实践经历和见解,启发他人的创新思维。在这里,我希望能与志同道合的朋友交流探讨,共同进步,一起在技术的世界里不断学习成长。 技术合作请加本人wx(注明来自ZEEKLOG):foreast_sea

By Ne0inhk
【MySQL】win 10 / win11:mysql 5.7 下载、安装与配置

【MySQL】win 10 / win11:mysql 5.7 下载、安装与配置

目录 一、MySQL 下载 (1)MySQL 官网下载地址 (2)下载保存安装包 二、MySQL 安装 (1)运行安装包 (2)选择安装类型 (3)选择安装版本号 (4)配置服务端口 (5)配置 root 的密码 (6)配置服务名称 (7)安装完成 三、配置系统环境变量 (1)打开系统环境变量配置面板 (2)编辑系统变量 Path 四、验证安装完成 五、Navicat 测试连接 (1)连接数据库 (2)填写连接信息 (3)测试连接 (4)保存连接 (5)高级配置(

By Ne0inhk
MySQL 9.1.0 安装教程(详细版)

MySQL 9.1.0 安装教程(详细版)

MySQL 9.1.0 安装教程(详细版) 1. 下载 MySQL 安装包 1. 访问 MySQL 官网下载页面:MySQL Downloads 2. 选择 MySQL Community Server,然后点击下载按钮。 3. 选择适合自己操作系统的版本。比如,如果你是 Windows 用户,选择 Windows (x86, 64-bit), ZIP Archive(压缩包版)。 4. 下载完成后,将 MySQL 压缩包解压到你想要安装的位置(比如:D:\mysql-9.1.0-winx64)。 2. 配置 MySQL 安装 2.

By Ne0inhk