python-游戏篇-初级-超级画板

文章目录

  • 开发环境要求
  • 运行方法
    • PyCharm
    • VScode
  • 代码
    • main.py
    • tools.py
  • 效果

开发环境要求

本系统的软件开发及运行环境具体如下。

  • 操作系统:Windows 7、Windows 10。
  • Python版本:Python 3.7.1。
  • 开发工具:PyCharm 2018。
  • Python内置模块:os、sys、time、math。
  • 第三方模块:pygame。
    注意:在使用第三方模块时,首先需要使用pip install命令安装该模块,例如,安装pygame模块,可以在Python命令窗口中执行以下命令:
pip install pygame

运行方法

PyCharm

打开PyCharm开发环境,然后打开源码文件夹,找到drawBoard文件夹,按下<Ctrl+C>进行复制,切换到PyCharm开发环境,在左侧列表中按下<Ctrl+V>进行粘贴,展开drawBoard文件夹,双击main.py打开该文件,然后在右侧窗口中单击右键,选择“Run’main”即可运行程序,如图1所示。
图1  选择“Run’main”即可运行程序

程序运行效果如图2所示(说明:单击左侧的铅笔或者橡皮,然后单击加减号可以增加或者缩小宽度,选择一个颜色,即可在右侧绘制图形,或者擦除绘制的图形)。
在这里插入图片描述

图2 项目主界面

VScode

在这里插入图片描述

代码

main.py

# -*- coding: utf-8 -*-
import os
import sys
import time# 导入Pygame
try:import pygame
except ModuleNotFoundError:print('正在安装pygame,请稍等...')os.system('pip install pygame') # 安装pygame模块
import tools # 导入tools模块# 检测Python版本号
__MAJOR, __MINOR, __MICRO = sys.version_info[0], sys.version_info[1], sys.version_info[2]
if __MAJOR < 3:print('Python版本号过低,当前版本为 %d.%d.%d, 请重装Python解释器' % (__MAJOR, __MINOR, __MICRO))time.sleep(2)exit()if __name__ == '__main__':# 创建Paint类的对象paint = tools.Paint()try:paint.run()  # 启动主窗口except Exception as e:print(e)

tools.py

# -*- coding: utf-8 -*-
import math
import pygame
from pygame.locals import QUIT, KEYDOWN, K_ESCAPE, MOUSEBUTTONDOWN, MOUSEMOTION, MOUSEBUTTONUP  # 导入事件class Brush:"""画笔类"""def __init__(self, screen):self.screen = screen  # 屏幕对象self.color = (0, 0, 0)  # 颜色self.size = 1  # 大小self.drawing = False  # 是否绘画self.last_pos = None  # 鼠标滑过最后的位置self.space = 1self.brush = pygame.image.load("img/pen.png").convert_alpha()  # 画笔图片self.brush_now = self.brush.subsurface((0, 0), (1, 1))  # 初始化画笔对象# 开始绘画def start_draw(self, pos):self.drawing = Trueself.last_pos = pos # 记录鼠标最后位置# 结束绘画def end_draw(self):self.drawing = False# 获取当前使用画笔def get_current_brush(self):return self.brush_now # 获取当前使用的画笔对象def set_size(self, size):  # 设置画笔大小if size < 0.5: # 判断画笔尺寸小于0.5size = 0.5 # 设置画笔最小尺寸为0.5elif size > 32: # 判断画笔尺寸大于32size = 32 # 设置画笔最大尺寸为32self.size = size # 设置画笔尺寸# 生成画笔对象self.brush_now = self.brush.subsurface((0, 0), (size * 2, size * 2))# 获取画笔大小def get_size(self):return self.size# 设置画笔颜色def set_color(self, color):self.color = color # 记录选择的颜色for i in range(self.brush.get_width()): # 获取画笔的宽度for j in range(self.brush.get_height()): #获取画笔的高度# 以指定颜色显示画笔self.brush.set_at((i, j), color + (self.brush.get_at((i, j)).a,))# 获取画笔颜色def get_color(self):return self.color# 绘制动作def draw(self, pos):if self.drawing: # 判断是否开始绘画for p in self._get_points(pos):# 在两点之间的每个点上都画上实心点pygame.draw.circle(self.screen, self.color, p, int(self.size))self.last_pos = pos # 记录画笔最后位置# 获取两点之间所有的点位,该函数通过对鼠标坐标前一次记录点与当前记录点之间进行线性插值# 从而获得一系列点的坐标,从而使得绘制出来的画笔痕迹更加平滑自然def _get_points(self, pos):points = [(self.last_pos[0], self.last_pos[1])]len_x = pos[0] - self.last_pos[0]len_y = pos[1] - self.last_pos[1]length = math.sqrt(len_x ** 2 + len_y ** 2)step_x = len_x / lengthstep_y = len_y / lengthfor i in range(int(length)):points.append((points[-1][0] + step_x, points[-1][1] + step_y))# 对 points 中的点坐标进行四舍五入取整points = map(lambda x: (int(0.5 + x[0]), int(0.5 + x[1])), points)return list(set(points)) # 去除坐标相同的点class Menu:"""菜单类"""def __init__(self, screen):self.screen = screen  # 初始化窗口self.brush = Noneself.colors = [  # 颜色表(0xff, 0x00, 0xff), (0x80, 0x00, 0x80),(0x00, 0x00, 0xff), (0x00, 0x00, 0x80),(0x00, 0xff, 0xff), (0x00, 0x80, 0x80),(0x00, 0xff, 0x00), (0x00, 0x80, 0x00),(0xff, 0xff, 0x00), (0x80, 0x80, 0x00),(0xff, 0x00, 0x00), (0x80, 0x00, 0x00),(0xc0, 0xc0, 0xc0), (0x00, 0x00, 0x00),(0x80, 0x80, 0x80), (0x00, 0xc0, 0x80),]self.eraser_color = (0xff, 0xff, 0xff) # 初始颜色# 计算每个色块在画板中的坐标值,便于绘制self.colors_rect = []for (i, rgb) in enumerate(self.colors):  # 方块颜色表rect = pygame.Rect(10 + i % 2 * 32, 254 + i / 2 * 32, 32, 32)self.colors_rect.append(rect)self.pens = [  # 画笔图片pygame.image.load("img/pen.png").convert_alpha(),]self.erasers = [  # 橡皮图片pygame.image.load("img/eraser.png").convert_alpha(),]self.erasers_rect = []for (i, img) in enumerate(self.erasers):  # 橡皮列表rect = pygame.Rect(10, 10 + (i + 1) * 64, 64, 64)self.erasers_rect.append(rect)self.pens_rect = []for (i, img) in enumerate(self.pens):  # 画笔列表rect = pygame.Rect(10, 10 + i * 64, 64, 64)self.pens_rect.append(rect)self.sizes = [  # 加减号图片pygame.image.load("img/plus.png").convert_alpha(),pygame.image.load("img/minus.png").convert_alpha()]# 计算坐标,便于绘制self.sizes_rect = []for (i, img) in enumerate(self.sizes):rect = pygame.Rect(10 + i * 32, 138, 32, 32)self.sizes_rect.append(rect)def set_brush(self, brush):  # 设置画笔对象self.brush = brushdef draw(self):  # 绘制菜单栏for (i, img) in enumerate(self.pens): # 绘制画笔样式按钮self.screen.blit(img, self.pens_rect[i].topleft)for (i, img) in enumerate(self.erasers): # 绘制橡皮按钮self.screen.blit(img, self.erasers_rect[i].topleft)for (i, img) in enumerate(self.sizes): # 绘制 + - 按钮self.screen.blit(img, self.sizes_rect[i].topleft)# 绘制用于实时展示画笔的小窗口self.screen.fill((255, 255, 255), (10, 180, 64, 64))pygame.draw.rect(self.screen, (0, 0, 0), (10, 180, 64, 64), 1)size = self.brush.get_size()x = 10 + 32y = 180 + 32# 在窗口中展示画笔pygame.draw.circle(self.screen, self.brush.get_color(), (x, y), int(size))for (i, rgb) in enumerate(self.colors): # 绘制色块pygame.draw.rect(self.screen, rgb, self.colors_rect[i])def click_button(self, pos):# 点击加减号事件for (i, rect) in enumerate(self.sizes_rect):if rect.collidepoint(pos):if i:  # i == 1, size downself.brush.set_size(self.brush.get_size() - 0.5)else:self.brush.set_size(self.brush.get_size() + 0.5)return True# 点击颜色按钮事件for (i, rect) in enumerate(self.colors_rect):if rect.collidepoint(pos):self.brush.set_color(self.colors[i])return True# 点击橡皮按钮事件for (i, rect) in enumerate(self.erasers_rect):if rect.collidepoint(pos):self.brush.set_color(self.eraser_color)return Truereturn Falseclass Paint:"""窗口绘制类"""def __init__(self):self.screen = pygame.display.set_mode((800, 600)) # 显示窗口pygame.display.set_caption("超级画板") # 设置窗口标题self.clock = pygame.time.Clock() # 控制速率self.brush = Brush(self.screen) # 创建画刷对象self.menu = Menu(self.screen) # 创建窗口菜单self.menu.set_brush(self.brush) # 设置默认画刷def clear_screen(self):self.screen.fill((255, 255, 255))  # 填充空白def run(self):self.clear_screen() # 清除屏幕while True:# 设置fps,表示每秒执行30次(注意:30不是毫秒数)self.clock.tick(30)for event in pygame.event.get(): # 遍历所有事件if event.type == QUIT:  # 退出事件returnelif event.type == KEYDOWN:  # 按键事件# 按ESC键清空画板if event.key == K_ESCAPE:  # ESC按键事件self.clear_screen()elif event.type == MOUSEBUTTONDOWN:  # ;鼠标左键按下事件if ((event.pos)[0] <= 74 and self.menu.click_button(event.pos)):  # 未点击画板按钮passelse:self.brush.start_draw(event.pos)  # 开始绘画elif event.type == MOUSEMOTION:  # 鼠标移动事件self.brush.draw(event.pos)  # 绘画动作elif event.type == MOUSEBUTTONUP:  # 鼠标左键松开事件self.brush.end_draw()  # 停止绘画self.menu.draw()pygame.display.update()  # 更新画板

效果

在这里插入图片描述

PS:全部文档放下载处
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/683675.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

秒懂百科,C++如此简单丨第十九天:动态规划

目录 动态规划的初步理解 求最短路径数 洛谷 P1002 过河卒 题目描述 输入样例 输出样例 思路 AC Code 动态规划的初步理解 什么是动态规划&#xff1f;最直白的理解就是动态的规划。 那高级一点的理解呢&#xff1f;就是每时每刻都拿着一个小本本&#xff0c;也就是…

「优选算法刷题」:和可被K整除的子数组

一、题目 给定一个整数数组 nums 和一个整数 k &#xff0c;返回其中元素之和可被 k 整除的&#xff08;连续、非空&#xff09; 子数组 的数目。 子数组 是数组的 连续 部分。 示例 1&#xff1a; 输入&#xff1a;nums [4,5,0,-2,-3,1], k 5 输出&#xff1a;7 解释&…

C语言-----函数功能实现---strcpystrlen

1.函数功能参数介绍 该函数的功能就是把一个字符串复制到另外的一个数组&#xff0c;包括\0&#xff1b; 2.首先我们要明确字符串的复制也是包括最后的\0的&#xff1b; void mystrcpy(char* dest, char* src) {while (*src!\0){*dest *src;dest;src;}*dest *src;} int mai…

HGAME 2024 WEEK2 WP

文章目录 WEBWhat the cow say?Select More Coursesmyflask CryptomidRSAmidRSA revengebackpackbackpack revengebabyRSA奇怪的图片plus MISC我要成为华容道高手ek1ng_want_girlfriendezWord龙之舞 回老家了&#xff0c;初七晚上才回去&#xff0c;估计week3前几天不怎么能做…

类加载过程介绍

一、类的生命周期 类被加载到jvm虚拟机内存开始&#xff0c;到卸载出内存为止&#xff0c;他的生命周期可以分为&#xff1a;加载->验证->准备->解析->初始化->使用->卸载。 其中验证、准备、解析统一称为链接阶段 1、加载 将类的字节码载入方法区中&#xf…

docker (一)-简介

1.什么是docker Docker 是一个开源的应用容器引擎&#xff0c;由于docker影响巨大&#xff0c;今天也用"Docker" 指代容器化技术。 2.docker的优势 一键部署&#xff0c;开箱即用 容器使用基于image镜像的部署模式&#xff0c;image中包含了运行应用程序所需的一…

Selenium实战教程系列(二)---元素定位

Selenium webdriver能够模拟人对浏览器进行操作的前提是界面元素的定位。元素的定位可以说是Selenium自动化脚本的基础。这一小节笔者将介绍如何在selenium中进行元素的定位。 定位元素的方法 Selenium中提供了以下定位元素的方法&#xff1a; 首先看一个HTML文件 test_page.…

(14)Hive调优——合并小文件

目录 一、小文件产生的原因 二、小文件的危害 三、小文件的解决方案 3.1 小文件的预防 3.1.1 减少Map数量 3.1.2 减少Reduce的数量 3.2 已存在的小文件合并 3.2.1 方式一&#xff1a;insert overwrite (推荐) 3.2.2 方式二&#xff1a;concatenate 3.2.3 方式三&#xff…

OpenMVG(特征匹配、照片组重建点云、GPS位置信息、GMS)

目录 1 图像的特征匹配 2 图像中提取GPS位置信息 2.1 写入GPS信息到图像中 2.2 读取带有GPS的图像 3 SIFT/AKAZE/AKAZE_MLDB特征提取对比 4 GMS Filter 5 将球形全景图转换为6个透视视图 6 照片组重建点云 1 图像的特征匹配 #include "openMVG/features/feature.…

Python面向对象学习小记——面向过程VS面向对象

【面向过程就好比你是一个工人&#xff0c;你得亲自去做一个个任务 面向对象就好比你一个包工头&#xff0c;你可以差遣你下面的工人去做】

【网站项目】228高校教师电子名片系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

PowerShell搭建vue起始项目

Windows PowerShell搭建vue起始项目 搜索PowerShell,以管理员身份运行。 复制文件夹路径 cd 到这个文件夹位置 命令行创建项目&#xff1a;vue create 项目名 这里写自己的项目名就行&#xff0c;我写的yeb vue create yeb 创建成功后是这样的 有颜色的就是选中的&#xff…

“恶意提起知识产权诉讼行为的法律规制”主题研讨活动成功举办

随着我国社会经济的迅速发展以及创新型国家、知识产权强国建设的不断深入,知识产权在社会生活中正发挥着越来越重要的作用。特别是对于广大市场主体而言,知识产权已经不仅是一种私权利,更成为商业竞争中非常重要的一种手段,由此引发了大量的知识产权诉讼纠纷。此类纠纷中,既有权…

C++ new 和 malloc 的区别?

相关系列文章 C new 和 malloc 的区别&#xff1f; C内存分配策略​​​​​​​ 目录 1.引言 2.区别 2.1.申请的内存分配区域 2.2.类型安全和自动大小计算 2.3.构造函数和析构函数的调用 2.4.异常处理 2.5.配对简便性 2.6.new 的重载 2.7.关键字和操作符 3.总结 1.引…

HACKTHEBOX通关笔记——mango(退役)

信息收集 端口扫描 ┌──(root㉿kali)-[~] └─# nmap -sC -sV -A -p- --min-rate10000 10.129.229.185 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-01-31 20:44 EST Warning: 10.129.229.185 giving up on port because retransmission cap hit (10). Nmap scan …

【微服务】skywalking自定义告警规则使用详解

目录 一、前言 二、SkyWalking告警功能介绍 2.1 SkyWalking告警是什么 2.2 为什么需要SkyWalking告警功能 2.2.1 及时发现系统异常 2.2.2 保障和提升系统稳定性 2.2.3 避免数据丢失 2.2.4 提高故障处理效率 三、 SkyWalking告警规则 3.1 SkyWalking告警规则配置 3.2 …

VMware虚拟机网络配置

VMware虚拟机网络配置 桥接模式NAT网络 桥接模式 桥接模式其实就是借助你宿主机上的网卡进行联网和通信&#xff0c;所以相当于虚拟机和宿主机平级&#xff0c;处于同一个网段中。 配置要点&#xff1a; 注意选择正确的宿主机网卡 查看宿主机的网络信息&#xff0c;这些信息指…

[嵌入式AI从0开始到入土]8_在线Gpu环境训练(基于启智ai协作平台)

[嵌入式AI从0开始到入土]嵌入式AI系列教程 注&#xff1a;等我摸完鱼再把链接补上 可以关注我的B站号工具人呵呵的个人空间&#xff0c;后期会考虑出视频教程&#xff0c;务必催更&#xff0c;以防我变身鸽王。 第1期 昇腾Altas 200 DK上手 第2期 下载昇腾案例并运行 第3期 官…

原子变量和原子操作

一、什么是原子操作 通常某一个变量的操作对应的CPU指令是大于一个的&#xff0c;在多线程环境下&#xff0c;为了确保对共享变量的操作在执行时不会被干扰&#xff0c;从而避免竞态条件和死锁等问题&#xff0c;使用原子变量。 原子变量可以看作是一种特殊的类型&#xff0c…

php基础学习之函数

基本概念 是一种语法结构&#xff0c;将实现某一个功能的代码块封装到一个结构中&#xff0c;从而实现代码的重复利用 php函数的定义语法 &#xff08;与C/Java很类似&#xff0c;区别在于没有数据类型&#xff0c;因为php是弱类型语言&#xff09; function 函数名(参数){ //…