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

2024-03-03 22:36

本文主要是介绍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()

待续......

这篇关于Pyglet图形界面版2048游戏——详尽实现教程(上)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/771135

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者