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 pyglet
 
window = 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,text

window = 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 randint
 
window = 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,48
        font_size = 128,60,30,24,21,16,12,11
        size = size[order-2]
        font_size = font_size[order-2]
        margin = 14 if order<5 else 12
        self.order = order
        self.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)+38
            index = 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 box
    order = symbol - 48 if symbol<100 else symbol - 65456
    if 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 randint
 
window = 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,rectangle
    width, height = 70, 80
    coord = (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 = 30
    label[2].rotation = 30
    label[2].x += 10
    label[2].y -= 25

class Game2048:
    def __init__(self, order=4):
        size = 255,165,120,96,77,65,55,48
        font_size = 128,60,30,24,21,16,12,11
        size = size[order-2]
        font_size = font_size[order-2]
        margin = 14 if order<5 else 12
        self.order = order
        self.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)+38
            index = randint(0, min(self.index, len(COLOR)-1))
            rect = x, y, size, size
            self.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, game
    if any_key:
        any_key = False
        title2048(20, 630)
        game = Game2048(5)
        return
    order = symbol - 48 if symbol<100 else symbol - 65456
    if 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.visible

if 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 randint

window = 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,rectangle
    width, height = 70, 80
    coord = (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 = 30
    label[2].rotation = 30
    label[2].x += 10
    label[2].y -= 25

class Game2048:
    def __init__(self, order=4):
        size = 255,165,120,96,77,65,55,48
        font_size = 128,60,30,24,21,16,12,11
        size = size[order-2]
        font_size = font_size[order-2]
        margin = 14 if order<5 else 12
        self.order = order
        self.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)+38
            index = randint(0, min(self.index, len(COLOR)-1))
            rect = x, y, size, size
            self.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 game
    game.text.text = direction.title()

@window.event
def on_key_press(symbol, modifiers):
    global any_key, game, direction
    if any_key:
        any_key = False
        title2048(20, 630)
        game = Game2048(5)
        return
    order = symbol - 48 if symbol<100 else symbol - 65456
    if 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 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

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

if any_key:
    pyglet.clock.schedule_interval(switch_visible, 0.5)

title2048()
pyglet.app.run()

待续......

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

详解算法的时间复杂度和空间复杂度!

目录 ​编辑 1. 算法效率 2. 时间复杂度 2.1 时间复杂度的概念 2.2 大O的表示渐进法 2.3 一个栗子 3. 空间复杂度 4. 常见复杂度对比 5. 完结散花 ​​​​​​​ 悟已往之不谏&#xff0c;知来者犹可追 创作不易&#xff0c;宝子们&#xff01;如果这篇文章对你们有…

C++之queue和deque

1、queue queue&#xff08;队列&#xff09;&#xff0c;一种数据结构&#xff0c;可以让某些数据结构的操作变得简单。队列&#xff08;queue&#xff09;最大的特点就是先进先出。就是说先放入queue容器的元素一定是要先出队列之后&#xff0c;比它后进入队列的元素才能够出…

二维码门楼牌管理系统技术服务详解:性能标准与反光膜要求

文章目录 前言一、二维码门楼牌管理系统技术服务的性能要求二、反光膜的性能标准三、制作完成的反光膜表层保护 前言 随着科技的快速发展&#xff0c;二维码门楼牌管理系统在现代化城市管理中扮演着越来越重要的角色。这一系统不仅提高了管理效率&#xff0c;还为市民提供了更…

Autosar Appl介绍

AUTOSAR架构中的应用层 AUTOSAR 应用层构成AUTOSAR 架构中的最顶层,被认为对所有车辆应用至关重要。AUTOSAR 标准使用“组件”概念指定应用层实现。 在谈论应用层实现时,应该考虑的三个最重要的部分是: AUTOSAR 应用软件组件这些组件的 AUTOSAR 端口AUTOSAR 端口接口 AUTOS…

steam++加速问题:出现显示443端口被 vmware-hostd(9860)占用的错误。

目录 前言&#xff1a; 正文&#xff1a; 前言&#xff1a; 使用Steam对GitHub进行加速处理时&#xff0c;建议使用2.8.6版本。 下载地址如下&#xff1a;Release 2.8.6 BeyondDimension/SteamTools GitHub 下载时注意自己的系统位数 正文&#xff1a; 使用GitHub时会使…

任务拆解的艺术

1.任务拆解背后的深层逻辑 任务拆解背后的深层逻辑主要涉及以下几个方面&#xff1a; 分解复杂性&#xff1a; 任务拆解的首要目的是分解复杂的大目标或任务&#xff0c;将其分解成更小、更具体的部分。这种分解有助于减少问题的复杂性&#xff0c;使其更易于理解和解决。通过将…

DC-2靶机详解

写写自己打DC-2的过程 使用工具 kali DC-2的靶机下载地址为&#xff1a;https://www.vulnhub.com/entry/dc-2,311/ 环境配置。 Kali和DC-2都设置为NAT模式&#xff0c;都为仅主机模式也可以。 信息收集 arp-scan -l nmap -sn 192.168.236.0/24 获取靶机ip&#xff1a;192.16…

K8S之Deployment的介绍和使用

Deployment的理论和实操 Deployment控制器&#xff1a;概念、原理解读概述工作原理 编写Deployment资源清单文件使用案例&#xff1a;创建一个web站点Deployment管理pod&#xff1a;扩容、缩容通过deployment管理应用&#xff0c;实现扩容&#xff0c;把副本数变成3通过deploym…

C++重新入门-vector容器

目录 1.动态数组&#xff1a; 2.头文件和命名空间&#xff1a; 3.创建和初始化&#xff1a; 使用默认构造函数创建空的std::vector&#xff1a; 使用初始化列表初始化std::vector&#xff1a; 使用拷贝构造函数&#xff1a; 使用范围构造函数&#xff1a; 使用重复值初…

Tkinter.Text控件中,文本存在某个关键字的将被高亮显示(标记颜色+字体加粗)

在Tkinter的Text控件中&#xff0c;要标记某个关键字并改变其颜色&#xff0c;你可以使用tag_add方法来给包含关键字的文本添加标签&#xff0c;然后使用tag_config方法来配置该标签的显示样式&#xff0c;包括前景色&#xff08;字体颜色&#xff09;和背景色等。以下是一个完…

使用腾讯云go sdk 查询对象存储中最新文件

背景&#xff1a; 腾讯云账号下&#xff0c;有很多对象存储COS桶&#xff1a; 我现在想确认某一个对象存储桶的活跃程度&#xff0c;简单的来说。我想知道这个桶里面最后上传的一个文件是什么&#xff0c;以及它的上传时间戳。 本文将介绍如何使用腾讯云对象存储&#xff08;…

MySQL:开始深入其数据(三)DQL的后续

上一章学习mysql语句里的where和join,这一章我们开始分析group by ,having,order by,limit语句。 three,too,one,go! 文章目录 重温select语法having:order by:limit 重温select语法 SELECT [ALL | DISTINCT] { * | table.* | [ table.field1 [ as alias1] [, table.field2 [a…

【C++干货基地】揭秘C++11常用特性:内联函数 | 范围for | auto自动识别 | nullptr指针空值

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引入 哈喽各位铁汁们好啊&#xff0c;我是博主鸽芷咕《C干货基地》是由我的襄阳家乡零食基地有感而发&#xff0c;不知道各位的…

Dockerfile构建过程详解

Dockerfile介绍 docker是用来构建docker镜像的文件&#xff01;命令参数脚本&#xff01; 构建步骤&#xff1a; 1、编写一个dockerfile文件 2、docker build构建成为一个镜像 3、docker run 运行镜像 …

如何在Window系统部署VisualSVN服务并结合cpolar实现无公网ip远程访问

文章目录 前言1. VisualSVN安装与配置2. VisualSVN Server管理界面配置3. 安装cpolar内网穿透3.1 注册账号3.2 下载cpolar客户端3.3 登录cpolar web ui管理界面3.4 创建公网地址 4. 固定公网地址访问 前言 SVN 是 subversion 的缩写&#xff0c;是一个开放源代码的版本控制系统…

mongoDB 优化(1)索引

1、创建复合索引&#xff08;多字段&#xff09; db.collection_test1.createIndex({deletedVersion: 1,param: 1,qrYearMonth: 1},{name: "deletedVersion_1_param_1_qrYearMonth_1",background: true} ); 2、新增索引前&#xff1a; 执行查询&#xff1a; mb.r…

[业务系统]人物坐骑系统介绍I

1.问题描述 旧版本的坐骑系统依赖于人物装备了【法宝】&#xff08;一种装备类型&#xff09;&#xff0c;装备了法宝的人物变拥有了【幻化】坐骑的能力&#xff0c;即在人物装备栏中的【外观】中会有已经幻化和未幻化&#xff08;解锁&#xff09;的坐骑。如果玩家至少幻化一…

【笔试强训错题选择题】Day5.习题(错题)解析

文章目录 前言 错题题目 错题解析 总结 前言 错题题目 1. ​ ​ 2. 3. ​ 4. ​ 5. ​ 错题解析 1. 移位运算符的使用 2. 3. 4. 5. 总结

股票技术指标(包含贪婪指数)

股票技术指标是用于分析股票价格和成交量数据&#xff0c;以便预测未来市场走势的工具。技术分析师使用这些指标来识别市场趋势、价格模式、交易信号和投资机会。技术指标通常基于数学公式&#xff0c;并通常在股票价格图表上以图形形式表示。 技术指标主要分为以下几类&#x…

过于老旧的pytorch_ssim包 请从github下载源码

有些冷门算法真的不要随便pip&#xff0c;有可能下载到史前版本…最好还是找源代码 汗 今天要用到SSIM损失函数&#xff0c;从网上简单看了一下原理就想测试一下&#xff0c;偷了一下懒就直接在命令行输入pip install pytorch_ssim了&#xff0c;结果报了一堆错误&#xff08;汗…