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

news2024/9/28 9:28:07

目录

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()

待续......

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

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

相关文章

首例以“冠状病毒”为主题的勒索病毒,篡改系统MBR

前言概述 2020年勒索病毒攻击仍然是网络安全的最大威胁&#xff0c;在短短三个月的时间里&#xff0c;已经出现了多款新型的勒索病毒&#xff0c;关于2020年勒索病毒攻击新趋势&#xff0c;可以阅读笔者写的上一篇文章&#xff0c;里面有详细的分析&#xff0c;从目前观察到的…

深入解剖指针(4)

个人主页&#xff08;找往期文章包括但不限于本期文章中不懂的知识点&#xff09;&#xff1a; 我要学编程(ಥ_ಥ)-CSDN博客 目录 回调函数 qsort使用举例 使用qsort函数排序整型数据 使用qsort排序结构数据 qsort函数的模拟实现 回调函数 回调函数就是一个通过函数指…

java-幂等性

幂等性 1.1幂等性定义&#xff1a; 在计算机领域中&#xff0c;幂等&#xff08;Idempotence&#xff09;是指任意一个操作的多次执行总是能获得相同的结果&#xff0c;不会对系统状态产生额外影响。在Java后端开发中&#xff0c;幂等性的实现通常通过确保方法或服务调用的结…

68-解构赋值,迭代器,生成器函数,Symbol

1.解构赋值(针对数组array&#xff0c;字符串String及对象object以) 结构赋值是一种特殊的语法&#xff0c;通过将各种结构中的元素复制到变量中达到"解构"的目的&#xff0c;但是数组本身没有改变 1.1解构单层数组 <script>let arr [1,2,3,4,5];//获取数组…

C++之queue和deque

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

【python】遵守 robots.txt 规则的数据爬虫程序

程序1 编写一个遵守 robots.txt 规则的数据爬虫程序涉及到多个步骤&#xff0c;包括请求网页、解析 robots.txt 文件、扫描网页内容、存储数据以及处理异常。由于编程语言众多&#xff0c;且每种语言编写爬虫程序的方式可能有所不同&#xff0c;以下将使用 Python 语言举例&am…

Material UI 5 学习01-按钮组件

Material UI 5 学习01-按钮组件 一、安装Material UI二、 组件1、Button组件1、基础按钮2、variant属性3、禁用按钮4、可跳转的按钮5、disableElevation属性6、按钮的点击事件onClick 2、Button按钮的颜色和尺寸1、Button按钮的颜色2、按钮自定义颜色3、Button按钮的尺寸 3、图…

Topaz Gigapixel AI:让每一张照片都焕发新生mac/win版

Topaz Gigapixel AI 是一款革命性的图像增强软件&#xff0c;它利用先进的人工智能技术&#xff0c;能够显著提升图像的分辨率和质量。无论是摄影爱好者还是专业摄影师&#xff0c;这款软件都能帮助他们将模糊的、低分辨率的照片转化为清晰、细腻的高分辨率图像。 Topaz Gigap…

每日五道java面试题之mysql数据库篇(三)

目录&#xff1a; 第一题. 百万级别或以上的数据如何删除&#xff1f;第二题. 前缀索引第三题. 什么是最左前缀原则&#xff1f;什么是最左匹配原则?第四题. B树和B树的区别第五题. 使用B树和B树好处 第一题. 百万级别或以上的数据如何删除&#xff1f; 关于索引&#xff1a;…

【微服务】微服务中常用认证加密方案总结

目录 一、前言 二、登录认证安全问题 3.1 认证方式选择 三、常用的加密方案 3.1 MD5加密算法 3.1.1 md5特点 3.1.2 md5原理 3.1.3 md5使用场景 3.2 AES加密算法 3.2.1 AES简介 3.2.2 AES加解原理 3.2.3 AES算法优缺点 3.2.4 AES算法使用场景 3.3 RSA加密算法 3.3…

【IDEA+通义灵码插件】实现属于你的大模型编程助手

目录 1.前言 2.下载安装 3.解释代码 4.生成单元测试 5.生成注释 6.智能补全 1.前言 大模型到底该以一种什么方式落地&#xff0c;从而嵌入我们的工作当中&#xff0c;助力我们工作效率的提升&#xff0c;其实最好的方式也许就是虚拟助手的方式&#xff0c;就像钢铁侠的&…

无极低码:无极低码部署版操作指南

无极低码 &#xff1a;https://wheart.cn 无极低码是一个面向开发者的工具&#xff0c;旨在为开发者、创业者或研发企业&#xff0c;提供快速&#xff0c;高效&#xff0c;标准化&#xff0c;可定制&#xff0c;私有化部署的平台&#xff0c;在兼顾开发速度的同时&#xff0c;兼…

ChemDraw Pro 2022:呈现专业化学绘图的极 致之作 mac/win版

PerkinElmer ChemDraw Pro 2022是一款功能强大的化学绘图软件&#xff0c;专为化学家、科研工作者和教育者设计。这款软件凭借其卓越的性能和丰富的功能&#xff0c;已经成为化学绘图领域的领导者。 PerkinElmer ChemDraw Pro 2022软件获取 ChemDraw Pro 2022提供了广泛的化学…

可重入锁-隐式锁与显式锁

可重入锁 隐式锁&#xff08;即synchronized关键字使用的锁&#xff09;&#xff0c;默认是可重入锁 在一个synchronized修饰的方法或者代码块的内部调用本类的其他synchronized修饰的方法或者代码块时&#xff0c;是永远可以得到锁。 显式锁&#xff08;即Lock&#xff09;也…

【yolov8部署实战】VS2019环境下使用Onnxruntime环境部署yolov8目标检测|含源码

一、前言 部署yolo项目&#xff0c;是我这几个月以来做的事情&#xff0c;最近打算把这几个月试过的方法&#xff0c;踩过的坑&#xff0c;以博客的形式&#xff0c;分享一下。关于下面动态中讲到的如何用opencv部署&#xff0c;我在上一篇博客中已经详细讲到了&#xff1a;【…

【C++】const成员

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1. 前言2. const成员3. 取地址及const取地址操作符重载 1. 前言 在之前已经已经分享过了关于 【C】类和对象之常引用与运算符重载&#xff0c;这次分享的有关const的内容&#xff0c;话不多说&#xff0c;正文开始。…

Mybatis 框架 基础语法

Mybtais 中文网站 Maven 仓库 考点&#xff1a; SQL 注入 #{}最终生成预编译sql&#xff0c;预编译Sql语句中?替换#{}内容 一个#{} 替换一个? 在模糊查询时要使用 &#xff0c; ′ {}&#xff0c;% &#xff0c;′{}%’ &#xff0c;因为&#xff1f;不能出现在‘’中&…

2024最新算法:鹦鹉优化算法(Parrot optimizer,PO)求解23个基准函数

一、鹦鹉优化算法 鹦鹉优化算法&#xff08;Parrot optimizer&#xff0c;PO&#xff09;由Junbo Lian等人于2024年提出的一种高效的元启发式算法&#xff0c;该算法从驯养的鹦鹉中观察到的觅食、停留、交流和对陌生人行为的恐惧中汲取灵感。这些行为被封装在四个不同的公式中…

2024年自动化测试五大趋势

目录 2024年QA自动化趋势&#xff1a;塑造软件开发的未来 1.自动化测试中的AI和ML集成 2.DevOps中的持续测试 3.无代码自动化工具的使用 4.更加重视安全测试 5.定制化测试解决方案 有效实施2024年QA自动化趋势 1.集成AI和ML实现更智能的测试 2.在敏捷和DevOps文化中嵌入…

5.STL源码解析-算法、仿函数、适配器

算法 STL算法总览 仿函数与适配器 C标准模板库&#xff08;STL&#xff09;是C程序员的得力工具&#xff0c;提供了许多强大而高效的数据结构和算法。在STL中&#xff0c;仿函数&#xff08;Functor&#xff09;和适配器&#xff08;Adapter&#xff09;是两个重要的概念…