Pyglet图形界面版2048游戏——详尽实现教程(上)

目录

Pyglet图形界面版2048游戏

一、色块展示

二、绘制标题

三、方阵色块

四、界面布局

五、键鼠操作


Pyglet图形界面版2048游戏

一、色块展示

准备好游戏数字的背景颜色,如以下12种:

COLOR = ((206, 194, 180, 255), (237, 229, 218, 255), (237, 220, 190, 255),
                  (241, 176, 120, 255), (247, 146, 90, 255), (245, 118, 86, 255),
                  (247, 83, 44, 255), (237, 206, 115, 255), (229, 210, 82, 255),
                  (208, 164, 13, 255), (230, 180, 5, 255), (160, 134, 117, 255))

这些颜色用于pyglet.shapes.Rectangle()绘制方块,用法:

Rectangle(x, y, width, height, color=(255, 255, 255, 255), batch=None, group=None)

示例代码: 

import pygletwindow = pyglet.window.Window(800, 600, caption='色块展示')COLOR = ((206, 194, 180), (237, 229, 218), (237, 220, 190), (241, 176, 120),(247, 146, 90), (245, 118, 86), (247, 83, 44), (237, 206, 115),(229, 210, 82), (208, 164, 13), (230, 180, 5), (160, 134, 117))batch = pyglet.graphics.Batch()
shape = [pyglet.shapes.Rectangle(180+i%4*120, 120+i//4*120, 100, 100, color=COLOR[i], batch=batch) for i in range(len(COLOR))]@window.event
def on_draw():window.clear()batch.draw()pyglet.app.run()

运行效果:

二、绘制标题

使用pyglet.text.Label()+pyglet.shapes.Rectangle()绘制标题图片,为美化效果把数字0转过一定角度,属性.rotaion为旋转角度,属性.anchor_position为旋转中心坐标,属性.x和.y为控件坐标,可以对个别控件的位置作出调整。

示例代码:

import pyglet
from pyglet import shapes,textwindow = pyglet.window.Window(800, 600, caption='2048')
batch = pyglet.graphics.Batch()x, y = 280, 260
width, height = 70, 80
coord = (x, y), (x+120, y), (x+70, y+60), (x+200, y)
color = (230, 182, 71), (220, 112, 82), (245, 112, 88), (248, 160, 88)
label = [text.Label(s,font_name='Arial',font_size=42,bold=True,x=coord[i][0]+width//2, y=coord[i][1]+height//2,anchor_x='center', anchor_y='center',  batch=batch) for i,s in enumerate('2408')]
rectangle = [shapes.Rectangle(coord[i][0], coord[i][1], width, height,color=color[i], batch=batch) for i in range(4)]
rectangle[2].anchor_position = (15, 15)
rectangle[2].rotation = 30
label[2].rotation = 30
label[2].x += 10
label[2].y -= 25@window.event
def on_draw():window.clear()batch.draw()pyglet.app.run()

运行效果: 

三、方阵色块

方阵色块和数字设置成一个类class Game2048,从2阶到9阶,数字色块的背景随数字的变化而变化,色块和数字也使用 Rectangle 和 Label 绘制。

        self.shapes = []
        self.labels = []
        for i in range(order**2):
            x, y = i%order*(size+margin)+38, i//order*(size+margin)+38
            index = randint(0, min(self.index, len(COLOR)-1))

示例代码:

import pyglet
from pyglet import shapes,text
from random import randintwindow = pyglet.window.Window(600, 600, caption='2048')pyglet.gl.glClearColor(176/255, 196/255, 222/255, 0.6)COLOR = ((206, 194, 180), (237, 229, 218), (237, 220, 190), (241, 176, 120), (247, 146, 90),(245, 118, 86), (247, 83, 44), (237, 206, 115), (229, 210, 82), (208, 164, 13),(230, 180, 5), (160, 134, 117))batch = pyglet.graphics.Batch()class Game2048:def __init__(self, order=4):size = 255,165,120,96,77,65,55,48font_size = 128,60,30,24,21,16,12,11size = size[order-2]font_size = font_size[order-2]margin = 14 if order<5 else 12self.order = orderself.index = order+7 if order>3 else (4 if order==2 else 7)self.shape = shapes.Rectangle(20, 20, 560, 560, color=(190,176,160), batch=batch)self.shapes = []self.labels = []for i in range(order**2):x, y = i%order*(size+margin)+38, i//order*(size+margin)+38index = randint(0, min(self.index, len(COLOR)-1))self.shapes.append(shapes.Rectangle(x,y,size,size,color=COLOR[index],batch=batch))self.labels.append(text.Label(str(2**index) if index else '', font_size=font_size,x=x+size//2, y=y+size//2,anchor_x='center', anchor_y='center',bold=True,batch=batch))@window.event
def on_draw():window.clear()batch.draw()@window.event
def on_key_press(symbol, modifiers):global boxorder = symbol - 48 if symbol<100 else symbol - 65456if order in range(2,10):game = Game2048(order)box = Boxes(5)
pyglet.app.run()

运行效果:可以用键盘操作,数字2~9分别对应方阵的2~9阶。

四、界面布局

把以上内容结合到一起成为游戏的主界面,在屏幕中央显示标题图以及提示语,任意键后显示标题移到界面左上方,色块盘则显示在界面下方。另外,使用pyglet.clock.schedule_interval()切换提示语的可见性,产生动画效果:

def switch_visible(event):
    any_key_label.visible = not any_key_label.visible

pyglet.clock.schedule_interval(switch_visible, 0.5)

完整示例代码:

import pyglet
from pyglet import shapes,text
from random import randintwindow = pyglet.window.Window(600, 800, caption='2048')pyglet.gl.glClearColor(176/255, 196/255, 222/255, 0.6)COLOR = ((206, 194, 180), (237, 229, 218), (237, 220, 190), (241, 176, 120), (247, 146, 90),(245, 118, 86), (247, 83, 44), (237, 206, 115), (229, 210, 82), (208, 164, 13),(230, 180, 5), (160, 134, 117))batch = pyglet.graphics.Batch()
group = pyglet.graphics.Group()def title2048(x=170, y=450):global label,rectanglewidth, height = 70, 80coord = (x, y), (x+width*2-20, y), (x+width, y+height), (x+width*3-10, y)color = (230, 182, 71), (220, 112, 82), (245, 112, 88), (248, 160, 88)label = [text.Label(s, font_name='Arial', font_size=42, bold=True, batch=batch, group=group,x=coord[i][0]+width//2, y=coord[i][1]+height//2, anchor_x='center',anchor_y='center') for i,s in enumerate('2408')]rect = lambda i:(coord[i][0], coord[i][1], width, height)rectangle = [shapes.Rectangle(*rect(i), color=color[i], batch=batch, group=group) for i in range(4)]rectangle[2].anchor_position = (15, 15)rectangle[2].rotation = 30label[2].rotation = 30label[2].x += 10label[2].y -= 25class Game2048:def __init__(self, order=4):size = 255,165,120,96,77,65,55,48font_size = 128,60,30,24,21,16,12,11size = size[order-2]font_size = font_size[order-2]margin = 14 if order<5 else 12self.order = orderself.index = order+7 if order>3 else (4 if order==2 else 7)self.shape = shapes.Rectangle(20, 20, 560, 560, color=(190, 176, 160), batch=batch)self.shapes = []self.labels = []for i in range(order**2):x, y = i%order*(size+margin)+38, i//order*(size+margin)+38index = randint(0, min(self.index, len(COLOR)-1))rect = x, y, size, sizeself.shapes.append(shapes.Rectangle(*rect, color=COLOR[index], batch=batch))text = str(2**index) if index else ''self.labels.append(text.Label(text, font_size=font_size, x=x+size//2, y=y+size//2,anchor_x='center', anchor_y='center', bold=True, batch=batch))any_key = True
any_key_label = text.Label("any key to start ......", x=window.width//2, y=window.height//2,font_size=24, anchor_x='center', anchor_y='center')@window.event
def on_draw():window.clear()batch.draw()if any_key:any_key_label.draw()@window.event
def on_key_press(symbol, modifiers):global any_key, gameif any_key:any_key = Falsetitle2048(20, 630)game = Game2048(5)returnorder = symbol - 48 if symbol<100 else symbol - 65456if order in range(2,10):game = Game2048(order) @window.event
def on_mouse_press(x, y, button, modifier):if any_key:on_key_press(0, 0)def switch_visible(event):any_key_label.visible = not any_key_label.visibleif any_key:pyglet.clock.schedule_interval(switch_visible, 0.5)title2048()
pyglet.app.run()

运行效果:

五、键鼠操作

增加上下左右方向的键盘操作,左手操作也可以用ASDW四个字符键;鼠标操作则检测在色块盘的位置,如下图所示,对角线分割出的四个区域分别分表上下左右。四个区域由y=x,y=-x+600两条直线方程所分割,并且满足0<x,y<580即可。测试用控件放在class Game2048类里:

        '''以下控件测试用'''

        self.line1 = shapes.Line(20, 20, 580, 580, width=4, color=(255, 0, 0), batch=batch)
        self.line2 = shapes.Line(20, 580, 580, 20, width=4, color=(255, 0, 0), batch=batch)
        self.box = shapes.Box(18, 18, 564, 564, thickness=4, color=(255, 0, 0), batch=batch)
        self.text = text.Label("", x=450, y=650, font_size=24, color=(250, 0, 0, 255),
                    anchor_x='center', anchor_y='center', bold=True, batch=batch)

键盘操作:

@window.event
def on_key_press(symbol, modifiers):
    if symbol in (key.A, key.LEFT):
        move_test('left')
    elif symbol in (key.D, key.RIGHT):
        move_test('right')
    elif symbol in (key.W, key.UP):
        move_test('up')
    elif symbol in (key.S, key.DOWN):
        move_test('down')

鼠标操作:

@window.event
def on_mouse_press(x, y, button, modifier):
    if any_key:
        on_key_press(0, 0)
    if direction == 'left':
        move_test('left')
    elif direction == 'right':
        move_test('right')
    elif direction == 'up':
        move_test('up')
    elif direction == 'down':
        move_test('down')

@window.event
def on_mouse_motion(x, y, dx, dy):
    global direction
    if 20<x<y<580 and x+y<600:
        direction = 'left'
    elif 20<y<x<580 and x+y>600:
        direction = 'right'
    elif 20<x<y<580 and x+y>600:
        direction = 'up'
    elif 20<y<x<580 and x+y<600:
        direction = 'down'
    else:
        direction = None

完整代码:

import pyglet
from pyglet import shapes,text
from pyglet.window import key
from random import randintwindow = pyglet.window.Window(600, 800, caption='2048')pyglet.gl.glClearColor(176/255, 196/255, 222/255, 0.6)COLOR = ((206, 194, 180), (237, 229, 218), (237, 220, 190), (241, 176, 120), (247, 146, 90),(245, 118, 86), (247, 83, 44), (237, 206, 115), (229, 210, 82), (208, 164, 13),(230, 180, 5), (160, 134, 117))batch = pyglet.graphics.Batch()
group = pyglet.graphics.Group()def title2048(x=170, y=450):global label,rectanglewidth, height = 70, 80coord = (x, y), (x+width*2-20, y), (x+width, y+height), (x+width*3-10, y)color = (230, 182, 71), (220, 112, 82), (245, 112, 88), (248, 160, 88)label = [text.Label(s, font_name='Arial', font_size=42, bold=True, batch=batch, group=group,x=coord[i][0]+width//2, y=coord[i][1]+height//2, anchor_x='center',anchor_y='center') for i,s in enumerate('2408')]rect = lambda i:(coord[i][0], coord[i][1], width, height)rectangle = [shapes.Rectangle(*rect(i), color=color[i], batch=batch, group=group) for i in range(4)]rectangle[2].anchor_position = (15, 15)rectangle[2].rotation = 30label[2].rotation = 30label[2].x += 10label[2].y -= 25class Game2048:def __init__(self, order=4):size = 255,165,120,96,77,65,55,48font_size = 128,60,30,24,21,16,12,11size = size[order-2]font_size = font_size[order-2]margin = 14 if order<5 else 12self.order = orderself.index = order+7 if order>3 else (4 if order==2 else 7)self.shape = shapes.Rectangle(20, 20, 560, 560, color=(190, 176, 160), batch=batch)self.shapes = []self.labels = []for i in range(order**2):x, y = i%order*(size+margin)+38, i//order*(size+margin)+38index = randint(0, min(self.index, len(COLOR)-1))rect = x, y, size, sizeself.shapes.append(shapes.Rectangle(*rect, color=COLOR[index], batch=batch))txt = str(2**index) if index else ''self.labels.append(text.Label(txt, font_size=font_size, x=x+size//2, y=y+size//2,anchor_x='center', anchor_y='center', bold=True, batch=batch))'''以下控件测试用'''self.line1 = shapes.Line(20, 20, 580, 580, width=4, color=(255, 0, 0), batch=batch)self.line2 = shapes.Line(20, 580, 580, 20, width=4, color=(255, 0, 0), batch=batch)self.box = shapes.Box(18, 18, 564, 564, thickness=4, color=(255, 0, 0), batch=batch)self.text = text.Label("", x=450, y=650, font_size=24, color=(250, 0, 0, 255),anchor_x='center', anchor_y='center', bold=True, batch=batch)any_key = True
any_key_label = text.Label("any key to start ......", x=window.width//2, y=window.height//2,font_size=24, anchor_x='center', anchor_y='center')@window.event
def on_draw():window.clear()batch.draw()if any_key:any_key_label.draw()def move_test(direction):global gamegame.text.text = direction.title()@window.event
def on_key_press(symbol, modifiers):global any_key, game, directionif any_key:any_key = Falsetitle2048(20, 630)game = Game2048(5)returnorder = symbol - 48 if symbol<100 else symbol - 65456if order in range(2,10):game = Game2048(order)if symbol in (key.A, key.LEFT):move_test('left')elif symbol in (key.D, key.RIGHT):move_test('right')elif symbol in (key.W, key.UP):move_test('up')elif symbol in (key.S, key.DOWN):move_test('down')direction = None@window.event
def on_mouse_press(x, y, button, modifier):if any_key:on_key_press(0, 0)if direction == 'left':move_test('left')elif direction == 'right':move_test('right')elif direction == 'up':move_test('up')elif direction == 'down':move_test('down')@window.event
def on_mouse_motion(x, y, dx, dy):global directionif 20<x<y<580 and x+y<600:direction = 'left'elif 20<y<x<580 and x+y>600:direction = 'right'elif 20<x<y<580 and x+y>600:direction = 'up'elif 20<y<x<580 and x+y<600:direction = 'down'else:direction = Nonedef switch_visible(event):any_key_label.visible = not any_key_label.visibleif any_key:pyglet.clock.schedule_interval(switch_visible, 0.5)title2048()
pyglet.app.run()

待续......

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

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

相关文章

SpringCloud负载均衡源码解析 | 带你从表层一步步剖析Ribbon组件如何实现负载均衡功能

目录 1、负载均衡原理 2、源码分析 2.1、LoadBalanced 2.2、LoadBalancerClient 2.3、RibbonAutoConfiguration 2.4、LoadBalancerAutoConfiguration 2.5、LoadBalancerIntercepor⭐ 2.6、再回LoadBalancerClient 2.7、RibbonLoadBalancerClient 2.7.1、DynamicServe…

OpenCV 4基础篇| OpenCV图像的拼接

目录 1. Numpy (np.hstack&#xff0c;np.vstack)1.1 注意事项1.2 代码示例 2. matplotlib2.1 注意事项2.2 代码示例 3. 扩展示例&#xff1a;多张小图合并成一张大图4. 总结 1. Numpy (np.hstack&#xff0c;np.vstack) 语法结构&#xff1a; retval np.hstack(tup) # 水平…

c++之通讯录管理系统

1&#xff0c;系统需求 通讯录是一个记录亲人&#xff0c;好友信息的工具 系统中需要实现的功能如下&#xff1a; 1&#xff0c;添加联系人&#xff1a;向通讯录中添加新人&#xff0c;信息包括&#xff08;姓名&#xff0c;性别&#xff0c;年龄&#xff0c;联系电话&#…

构建高效的接口自动化测试框架思路

在选择接口测试自动化框架时&#xff0c;需要根据团队的技术栈和项目需求来综合考虑。对于测试团队来说&#xff0c;使用Python相关的测试框架更为便捷。无论选择哪种框架&#xff0c;重要的是确保 框架功能完备&#xff0c;易于维护和扩展&#xff0c;提高测试效率和准确性。今…

信息安全技术第1章——信息网络安全基本概念

课程介绍 网络信息安全是医学信息工程专业的限选课。主要围绕计算机网络安全所涉及的主要问题进行讲解&#xff0c;内容包括&#xff1a;对称密码与公钥密码的基本原理、相关算法及应用。电子邮件的安全&#xff0c;IP安全&#xff0c;Web安全&#xff0c;恶意软件及防火墙等内…

C++ opencv 学习

文章目录 1、创建窗口2、读取图片3、视频采集4、Mat的使用5、异或操作6、通道分离&#xff0c;通道合并7、色彩空间转换8、最大值、最小值9、绘制图像10、多边形绘制11、随机数12、鼠标实时绘制矩形13、归一化14、resize操作15、旋转翻转16、视频操作17、模糊操作18、高斯模糊操…

SpringBoot整合MyBatis实现增删改查

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: 循序渐进学SpringBoot ✨特色专栏: MySQL学习 🥭本文内容: SpringBoot整合MyBatis实现增删改查 📚个人知识库: Leo知识库,欢迎大家访…

Java进阶-IO(1)

进入java IO部分的学习&#xff0c;首先学习IO基础&#xff0c;内容如下。需要了解流的概念、分类还有其他一些如集合与文件的转换&#xff0c;字符编码问题等&#xff0c;这次先学到字节流的读写数据&#xff0c;剩余下次学完。 一、IO基础 1、背景 1.1 数据存储问题 变量…

代码随想录day11(1)字符串:反转字符串中的单词 (leetcode151)

题目要求&#xff1a;给定一个字符串&#xff0c;将其中单词顺序反转&#xff0c;且每个单词之间有且仅有一个空格。 思路&#xff1a;因为本题没有限制空间复杂度&#xff0c;所以首先想到的是用split直接分割单词&#xff0c;然后将单词倒叙相加。 但如果想让空间复杂度为O…

芯来科技发布最新NI系列内核,NI900矢量宽度可达512/1024位

参考&#xff1a;芯来科技发布最新NI系列内核&#xff0c;NI900矢量宽度可达512/1024位 (qq.com) 本土RISC-V CPU IP领军企业——芯来科技正式发布首款针对人工智能应用的专用处理器产品线Nuclei Intelligence(NI)系列&#xff0c;以及NI系列的第一款AI专用RISC-V处理器CPU IP…

网络爬虫部分应掌握的重要知识点

目录 一、预备知识1、Web基本工作原理2、网络爬虫的Robots协议 二、爬取网页1、请求服务器并获取网页2、查看服务器端响应的状态码3、输出网页内容 三、使用BeautifulSoup定位网页元素1、首先需要导入BeautifulSoup库2、使用find/find_all函数查找所需的标签元素 四、获取元素的…

基于springboot+vue的健身房管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

●139.单词拆分 ● 关于多重背包,你该了解这些! ●背包问题总结篇!

●139.单词拆分 物品&#xff1a;wordDict里面的单词&#xff1b;背包容量&#xff1a;s.size()。 1.dp[j]含义。dp[j]true表示字符串前j个可以拆分成字典中的单词。dp[s.size()] 就是最后的结果&#xff0c;整个字符串能&#xff08;true&#xff09;不能&#xff08;false…

Docker 创建容器并指定时区

目录 1. 通过环境变量设置时区&#xff08;推荐&#xff09;2. 挂载宿主机的时区文件到容器中3. 总结 要在 Docker 容器中指定时区&#xff0c;可以通过两种方式来实现&#xff1a; 1. 通过环境变量设置时区&#xff08;推荐&#xff09; 在 Docker 运行时&#xff0c;可以通…

CentOS安装Docker(黑马学习笔记)

Docker 分为 CE 和 EE 两大版本。CE 即社区版&#xff08;免费&#xff0c;支持周期 7 个月&#xff09;&#xff0c;EE 即企业版&#xff0c;强调安全&#xff0c;付费使用&#xff0c;支持周期 24 个月。 Docker CE 分为 stable test 和 nightly 三个更新频道。 官方网站上…

文件底层的理解之缓冲区

目录 一、缓冲区的初步认识 二、向文件中写数据的具体过程 三、缓冲区刷新的时机 一、缓冲区的初步认识 缓冲区其实就是一块内存区域&#xff0c;采用空间来换时间&#xff0c;可以提高使用者的效率。我们一直说的缓冲区其实是语言层面上的缓冲区&#xff0c;其实操作系统内部…

JVM 第一部分 JVM两种解释器 类加载过程和类加载器

JVM是跨平台跨语言的虚拟机&#xff0c;不直接接触硬件&#xff0c;位于操作系统的上一层 跟字节码文件直接关联&#xff0c;和语言没有关系 一次编译成字节码文件&#xff0c;多次执行 虚拟机可以分成三部分&#xff1a;类加载器&#xff0c;运行时数据区&#xff0c;执行引…

TDengine 在 DISTRIBUTECH 分享输配电数据管理实践

2 月 27-29 日&#xff0c;2024 美国国际输配电电网及公共事业展&#xff08;DISTRIBUTECH International 2024&#xff09;在美国-佛罗里达州-奥兰多国家会展中心举办。作为全球领先的年度输配电行业盛会&#xff0c;也是美洲地区首屈一指的专业展览会&#xff0c;该展会的举办…

【和鲸冬令营】通过数据打造爆款社交APP用户行为分析报告

【&#x1f40b;和鲸冬令营】通过数据打造爆款社交APP用户行为分析报告 文章目录 【&#x1f40b;和鲸冬令营】通过数据打造爆款社交APP用户行为分析报告1 业务背景2 数据说明3 数据探索性分析4 用户行为分析4.1 用户属性与行为关系分析4.2 转化行为在不同用户属性群体中的分布…

值类型和引用类型详解(C#)

可能你对值类型和引用类型还不太了解。 值类型和引用类型&#xff0c;是c#比较基础&#xff0c;也必须掌握的知识点&#xff0c;但是也不是那么轻易就能掌握&#xff0c;今天跟着我一起来看看吧。 典型类型 首先我们看看这两种不同的类型有哪些比较典型的代表。 典型值类型…