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.pswp.cn/news/717371.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/717371.shtml
英文地址,請注明出處:http://en.pswp.cn/news/717371.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

常見Vue原理面試題

1. Vue的響應式原理是什么&#xff1f;請詳細說明Object.defineProperty()和Proxy的區別和用法。 響應式原理&#xff1a;Vue中采用了數據劫持的方式&#xff0c;通過Object.defineProperty()函數來監聽數據變化&#xff0c;并在數據變化時觸發對應的更新函數。 Object.define…

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) # 水平…

工作日記:JavaScript fill() 方法

定義 fill() 方法用于將一個固定值替換數組的元素。 語法 array.fill(value, start, end) value&#xff1a;必填。要填充的值 start&#xff1a;可選。開始填充位置 end&#xff1a;可選。結束填充位置&#xff08;默認是數組的長度&#xff1a;array.length&#xff09;…

提取拼多多店鋪商家電話的爬蟲軟件

拼多多是中國知名的團購電商平臺&#xff0c;許多用戶在購物時都希望能夠直接聯系到店鋪商家&#xff0c;以便獲得更多的產品信息或解決問題。在這篇文章中&#xff0c;我們將介紹如何使用Python編寫一個爬蟲軟件&#xff0c;來提取拼多多店鋪商家電話。 首先&#xff0c;我們…

c++之通訊錄管理系統

1&#xff0c;系統需求 通訊錄是一個記錄親人&#xff0c;好友信息的工具 系統中需要實現的功能如下&#xff1a; 1&#xff0c;添加聯系人&#xff1a;向通訊錄中添加新人&#xff0c;信息包括&#xff08;姓名&#xff0c;性別&#xff0c;年齡&#xff0c;聯系電話&#…

構建高效的接口自動化測試框架思路

在選擇接口測試自動化框架時&#xff0c;需要根據團隊的技術棧和項目需求來綜合考慮。對于測試團隊來說&#xff0c;使用Python相關的測試框架更為便捷。無論選擇哪種框架&#xff0c;重要的是確保 框架功能完備&#xff0c;易于維護和擴展&#xff0c;提高測試效率和準確性。今…

IntelliJ IDEA 的常用快捷鍵

IntelliJ IDEA 的常用快捷鍵非常多&#xff0c;這些快捷鍵可以幫助你更高效地編寫代碼。以下是一些常用的快捷鍵總結&#xff1a; 基礎操作 CtrlN&#xff1a;查找類CtrlShiftN&#xff1a;查找文件CtrlAltL&#xff1a;格式化代碼AltInsert&#xff1a;生成代碼&#xff08;…

信息安全技術第1章——信息網絡安全基本概念

課程介紹 網絡信息安全是醫學信息工程專業的限選課。主要圍繞計算機網絡安全所涉及的主要問題進行講解&#xff0c;內容包括&#xff1a;對稱密碼與公鑰密碼的基本原理、相關算法及應用。電子郵件的安全&#xff0c;IP安全&#xff0c;Web安全&#xff0c;惡意軟件及防火墻等內…

UI自動化-(web端窗口截圖文件上傳-實操入門)

1、窗口截圖 1. UI自動化中&#xff0c;為什么需要進行窗口截圖&#xff1f; 調試和故障排除&#xff1a;截圖可以直觀地查看界面的狀態&#xff0c;快速識別和解決問題。當自動化過程中出現錯誤或異常時&#xff0c;通過查看截圖可以確定是否是界面元素的問題&#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知識庫,歡迎大家訪…

mysql之 case when

1 簡單 case 函數&#xff0c;IF函數 格式&#xff1a; CASE input_expression WHEN when_expression THENresult_expression [...n ] [ ELSEelse_result_expression ENDIF(條件,True結果,False結果)2 條件表達式 可嵌套多層&#xff0c;類似于 if … else if … else … end…

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…

反向迭代器

反向迭代器 以list為例,我們完全可以再添加一個__list_reverse_iterator結構體,只需要修改和–的邏輯 template <class T, class Ref, class Ptr> struct __list_reverse_iterator {...self& operator(){_node _node->_prev;return *this;}self operator(int){…

Android 14.0 Launcher3定制化之桌面分頁橫線改成圓點顯示功能實現

1.前言 在14.0的系統rom產品定制化開發中&#xff0c;在進行launcher3的定制化中&#xff0c;在雙層改為單層的開發中&#xff0c;在原生的分頁 是橫線&#xff0c;而為了美觀就采用了系統原來的另外一種分頁方式&#xff0c;就是圓點比較美觀&#xff0c;接下來就來分析下相關…

網絡爬蟲部分應掌握的重要知識點

目錄 一、預備知識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…