背景
最近入手新遊戲:《Threes》,2048的前身,難度比2048大,這個遊戲的命運比較悲哀,App上架沒幾天,便被人仿製出與之類似、入手更快的《2048》,2048獲得了巨大的成功,無論App store 還是Android 市場,下載量都遠遠超過千萬,但是《Threes》卻不爲人所知。
就這幾天的遊戲體驗來說,threes的體驗更好一些,恰好java課設臨近DDL ,便準備編碼《Threes》,因此先嚐試2048,在2048的基礎上編碼threes.
環境
Ubuntu 16.04.2
工具
Python 3.5.2
Pygame
Gcolor2
Firefox
邏輯
邏輯實現
遊戲狀態=未結束
棋盤上隨機兩格置2
while 遊戲狀態=未結束:
接收到滑動
if(該方向可以滑動):
for 序列 in 棋盤作平行於該方向的切分:
for 元素 in 反序序列:
if 元素不爲空:
if 左邊存在相隔n個零的相同元素(n>=0):
自身數值翻倍
總分=總分+合併後該元素的值
被合併的格子置空
while 右邊元素爲空:
自身右移一格
if 當前棋盤有剩餘空位:
在空位中隨機出現數字2或4
if 棋盤上存在格子的值爲2048:
遊戲狀態=勝利
elif 棋盤上存在剩餘空格 或者 棋盤上依然存在可以合併的元素:
遊戲狀態=未結束
else:
遊戲狀態=失敗
效果圖
Code
步驟
1.瞭解Pygame。第一次使用GUI,用了一個下午看了一下pygame,強烈安利一個博客,翻譯的很詳細,基本上看完以後就大致瞭解了pygame的圖形化過程,screen完全是由不同的Surface堆上去的,Surface就相當於是貼紙,直接在screen上貼就可以,不管是字體、圖片、圖形,都是Surface,想要用什麼界面自己不斷把Surface往上貼就可以。
2.瞭解pygame時間的事件過程,對於鍵盤按鍵,鼠標移動,亦或是鼠標點擊,都稱之爲事件,在每個有效事件發生後,對事件進行處理,處理的過程無非就是改變一些數據的數值,然後在繼續給screen貼上新的Surface,然後在display一下
3.2048的邏輯見上圖,下面主要說一下圖形形成的邏輯,雖然我們在玩遊戲的時候畫面一部分是靜態的,但是實際上所有畫面
都是動態的,每時每刻都在形成畫面,稱爲screen display,實際上計算機每做一些事,都要顯示一下畫面,由於計算機運行速
度比較快,所以我們肉眼觀察不到畫面變化
while True:
for event in pygame.event.get():
# 對於每個事件進行處理
map_init()
map_init() //screen display
這樣一個很簡陋額的2048就出現了:
4.考慮優化它,首先是至少有個標題吧,上面可以加一些東西,比如說什麼最高分、悔棋(其實實現這個功能不難,多開個數
組就可以,但個人感覺最好不能悔棋,便沒有去實現),以及各數字的顏色應該不同,這個去網上查一下各顏色的RGB的值,
字體的Surface設置一下就好以及各數字的顏色應該不同,這個去網上查一下各顏色的RGB的值,字體的Surface設置一下就好
5.上面空白處放幾個按鈕,無奈pygame並沒有button這個類,在網上查了些資料,發現可以自己編寫button的class,監聽按鈕的類可以有兩個條件判斷,第一個鼠標點擊事件,第二個是此刻監聽鼠標的位置,判斷點擊的點是否在框內即可,有不足(可以
ps圖片)
class Button(object):
def __init__(self, name, col,position, size):
self.name = name
self.col = col
self.size = size
self.position = position
def isOver(self):
point_x,point_y = pygame.mouse.get_pos()
x, y = self. position
w, h = self.size
in_x = x - w < point_x < x
in_y = y - h < point_y < y
return in_x and in_y
def render(self):
w, h = self.size
x, y = self.position
pygame.draw.rect(screen, self.col, ((x - w, y - h), (w, h)), 0)
num_font = pygame.font.Font(None, h - 1)
font_test=num_font.render(self.name, True, (255, 255, 255))
fsetting = font_test.get_rect()
fsetting.center = (x - w / 2, y - h / 2)
screen.blit(font_test,fsetting)
6.上網看了一下2048遊戲各個數字的顏色,本來肉眼找每個顏色的RGB,但是效果特別差勁,對,大概就
是這個樣子,無奈。。。。。。
8.恰巧讓舍友看到了,便安利我一個軟件:
是一個屏幕取色器,通過這個軟件,點擊屏幕的顏色,可以直接分析出來RGB(神器),不過相同的RGB,在網頁上與在pygame還是有色差的,我最後會說解決方法,嘻嘻,然後自己的2048就變樣了
9.這樣就剩下最上面按鈕的處理上了,無奈自己一直找不到好看的樣式,便直接在網上找了張圖片,
把這個圖片當做Surface貼到screen中就可以,注意原來的按鈕NEW、Menu位置對應到圖片上來,嘻
嘻,然後我滴2048就變成這個樣子了
10.我們把這兩個按鈕的顏色調成圖片原按鈕的顏色,然後把兩個數字Surface貼上去就可以
嘻嘻,這個是成品:
技巧
1.想要自己做的畫面好看,千萬不要想着通過自己通過GUI畫圖形,很難得,直接從網上找圖片,然後PPP,直接把圖片當做surface貼到screen上來就可以,賊爽,比如按鈕的圖案,比如遊戲的背景等等
2.關於色差問題,既然是因爲同樣的RGB在不同畫面上有微小差距,那我們把網頁截圖,然後convert,
把png轉成surface顯示到pygame,這是再次使用Gcolor就可以了
3.遊戲邏輯,在編碼之前要想好,我本來感覺邏輯很清晰,結果編碼過程中產生了好多疑惑,甚至在最後時發現遊戲的一個大bug,
代碼鏈接
分析
優點:
1.界面優美(後面的背景圖是截圖p過來的,(逃 )
2.支持記錄最高分與重新開始
3.不支持悔棋,沒錯,我感覺這就是優點
4.python支持面向對象,便寫了button的一個類,嘻嘻,下面的編程過程輕鬆了不少
不足:
1.對按鈕處理不夠仔細,其實完全可以p出來兩個不同背景色的相同按鈕,這樣鼠標移動到按鈕上顯示一個顏色,否則背景是另一種顏色
2.編碼不夠條理,其實字體,圖形等都可以設置成一個類,直接繼承就好,代碼長度會減少,犯錯機率變得更小
3.對pygame的座標系不熟悉,把行當做x軸,列當做y軸,然後就GG了,出現了下面這些反人類的代碼
if event.key == K_LEFT:
push_up()
elif event.key == K_RIGHT:
push_down()
elif event.key == K_UP:
push_left()
elif event.key == K_DOWN:
push_right()
總結
1.第一次用pygame編遊戲,感覺還不錯,這次主要寫的是圖形化畫面的東西,2048邏輯編碼沒怎麼寫,玩着自己編的遊戲感覺美滋滋,嘻嘻, 自己玩遊戲不是娛樂,是在測試。。。。是的,沒錯
2.DDL就是第一生產力,從產生編2048的想法,到最終實現,完全是DDL在給我施壓,同樣,這兩天感覺過得很充實
3.PS要學好,PS要學好,PS要學好,重要的事情說三遍,自己以後的遊戲畫面全靠它了
4.明後天抽空把這個遊戲改成《Threes》,恩,立個Flag, 宛如戲臺上的老將軍,背後插滿了flag
5.正經臉。。。自己這次用python時,因爲語法錯誤耽誤了好長時間,果然手生。。以後沒事要常用python搞搞事情