2020年10月31日 星期六

【簡單玩python】~~如何將python程式打包成exe執行檔

 介紹了一些python及pygame的學習心得,但有個小問題~那就是:如何將寫好的小程式或遊戲分享給其他未安裝python環境的朋友使用呢?

首先要先認識一下,當你使用python或pygame編寫了一些程式或遊戲時,一般而言你的這些程式只能在具備python的環境下去執行,若是你的程式中使用了一些非標準安裝具備的模組那你還得確認執行的環境中必須具備這些(或是先安裝)模組,才能確保程式能夠順暢正確的執行。在這樣的條件下,你所編寫的程式或遊戲,通常就只能自己玩得開心了,而很難與他人分享成果!

所以囉~~若是想將成果便利的讓其他未安裝python環境的朋友能夠正常的執行、操作,就必須要先克服執行環境這一點,所以如何將程式中所需要的python執行環境及所需模組打包成一支可以獨立執行的執行檔,就成為想將程式或遊戲分享給他人之前必須要學會的一環。

這次就紀錄、分享一下,如何將python寫好的程式或遊戲打包成可以分享、獨立執行(無須安裝python環境)的執行檔(.exe)!

好囉~~廢話說完了,現在就開始談談如何將程式打包成執行檔(for Windows)這件事:

我們這次介紹使用的是:pyinstaller 這支lib

想完整認識pyinstaller這支好用的lib可以到這裡看看

一、首先你必須先安裝pyinstaller:pip install pyinstaller

 若是要升級(原先已安裝舊版):pip install --upgrade pyinstaller


安裝過程會自動檢查相依性,將相關需要的lib自動下載一併安裝,方便!
安裝完成,接著就可以進入「命令提示字元」模式,將目錄切換至python程式所在的目錄

二、開始進行打包程序:pyinstaller -F -w 要打包的程式.py

其中打包的設定參數中:(這是我個人習慣的設定)
-F:表示要將與程式有關的需求整個打包成單一的執行檔
-w:設定程式執行時不要有「命令提示字元」的背景視窗

想多認識一下各種設定參數,可以使用:pyinstaller --help 自行查詢閱讀

2020年10月29日 星期四

【雲端工具】好用的Gif動畫分解網站

Gif動畫,其實就是一組圖檔的輪播所產生的視覺效果 



最近在製作一些小遊戲或程式時,會需要用到一些動畫效果

但是因為像pygame這類gif動畫並無法在程式中顯示動畫效果,而需要自行設計動畫的機制時,就有將gif動畫分解成個別的分解圖檔,在進行後續的設計之用。

所以呢~~這次就來介紹個不錯的Gif動畫分解網站,你只要將要分解的Gif動畫檔上傳至該網站,就可以迅速獲取一組動畫分解後的圖檔,相當便利!現在就來看看吧~~~~

Gif動畫分解網站:https://zh.bloggif.com/gif-extract



操作上也很直覺便利~~~


就可以看到如下分解後的圖檔組,點選「下載..zip文件...」即可將所有分解後的圖檔打包成zip檔下載下來!


提供給有需求的朋友參考囉!

2020年10月23日 星期五

pygame玩遊戲系列(10)~在遊戲中偵測是否發生碰撞並進行計分、顯示分數

 前面已經介紹了如何在遊戲中如何隨機出現指定數量的物件,也介紹了遊戲中的碰撞偵測原理及作法,基本上有了這些法寶,已經可以開始玩一些比較像遊戲的設計了!

這次,我們就在上一篇:pygame玩遊戲系列(9)~在遊戲中隨機出現指定數量的物件的程式基礎上,來看看如何改進遊戲中的元素。

此次目標如下:

一、能夠偵測小車是否接到從天而降的禮物(碰撞偵測原理)

二、若小車接到禮物,則加一分並於遊戲視窗中顯示目前得分

為完成上述目標,我們除了應用之前介紹過的經驗外,會多認識一個pygame中顯示文字內容及區塊的操作及相關語法。

好囉~~不囉嗦了!

我們直接在上一篇:pygame玩遊戲系列(9)~在遊戲中隨機出現指定數量的物件的程式碼中加上並加註相關程式碼如下:

首先在原程式碼中的第20行位置,加上統計得分的變數:score = 0 並預設初始分數為0分




接著就是比較關鍵的檢查每個禮物是否與小車發生碰撞狀態(也就是小車是否接到禮物)?

這部分原理,在這裏就不再贅述了,想了解碰撞偵測(建議一定要了解啦)原理的請自行參照之前的文章!

了解碰撞原理後,重點是要檢查「每一個禮物」是否跟小車發生碰撞,所以我們可以考慮將碰撞的偵測行為放進原先檢查禮物狀態及位置的for迴圈中。

2020年10月22日 星期四

pygame玩遊戲系列(9)~在遊戲中隨機出現指定數量的物件

 之前已經介紹過如何在遊戲視窗中隨機出現物件(禮物)並自動落下的操作

但之前因為一些觀念尚未介紹,且考慮到初學者需按部就班了解各個遊戲中(程式)元素的操控及設計核心,所以只設計了產生一組禮物從天而降的設計。

這樣的操作,當然沒有辦法滿足設計遊戲元素的需求,通常遊戲中的元素會有數量及個別「屬性」設定的操作需求,而這也是遊戲設計中最重要、最精采也是最燒腦的核心。

而對於這樣一種既有共同特性(例如:從天而降的禮物),又需要有個別化的「屬性(參數)」或「行為」(例如:降落的速度,顯示的位置...等等),有經驗的設計者自然會想到使用所謂的「物件導向模式」(OOP)中的類別(Class)設計模式,來為每個遊戲中的物件元素進行「屬性」及「行為」的設定。

但是同樣的,我們現階段依然採用「土法煉鋼」方式進行遊戲中物件元素的設計方式進行操作及說明,為的依然是讓學習者及自己能夠更為精確的理解「物件」設計的核心思維及關鍵概念,為日後的「函式(Function)」及Class(類別)學習及操作建立良好的基礎知能。

好囉~~~現在正式進入主題!

本次的目標有二:

一、可以在遊戲中設定出現指定數量的物件(禮物),這次我們預設遊戲視窗中保持有五個從天而降的禮物物件。

二、上述各物件(禮物)會隨機出現在遊戲視窗中,並各自落下。

為了達成以上的目標,我們必須先從前面的各篇文章取思考以下的設計關鍵點:

1.遊戲中的物件(禮物、小車等)是如何藉由(rect)矩形座標物件將圖形繪製(顯示)在視窗中的!

   範例語法:  screen.blit(gift_img, gift_rect)    # 在視窗中的gift_rect座標繪製gift_img圖形

2.如何能夠隨機設定禮物(物件)的矩形座標(rect),讓物件隨機出現在視窗中。

    範例語法: gift_rect.centerx = random.randrange(0, screen_rect.width)

3.如何偵測視窗中的物件數量,並讓這些物件能夠保持在設定的數量並出現在視窗中並落下?

    (也就是保持有五個禮物物件並讓這些禮物自動落下)

    ---關鍵來了~~(個人習慣)若發現有「一批」物件要做同樣的事

    (例如:隨機產生五個禮物的出現位置、五個禮物都要自動落下...等),

    就可以考慮使用串列(list)+for(條件式迴圈)來進行思考及設計。

~~~串列(list)可以將一組物件加以組合,並透過for迴圈進行同樣的行為(動作)設計

好囉~~所以,我們在之前隨機出現單一物件並自動落下的設計基礎上,持續強化程式如下,達成上述的目標及設計理念。

2020年10月20日 星期二

【OnCode大叔簡單玩python】系列~認識一下 for + list + range 的操作

 這次再來練習、整理一下有關串列(list)的一些組合應用及操作

有別於之前單純介紹串列(list)的說明

這次更著重於在程式設計中的操作及應用

好了~~直接上操作、應用的程式碼及相關說明吧!

# for 是一個條件式迴圈的語法
# list 是python中的串列物件,可將一組或數組相關,不相關的物件加以組合成為一組集合物件
# list 是個人認為在python操作中相當重要、實用的工具,建議大家好好認識他、學習應用他
# range 是一組指定數值範圍的物件
# 將 for list range 這三者組合起來,可以在程式設計中發揮相當大的力量及應用面,建議大家好好熟悉、認識一下

# 先來看一個單純的 for + list的操作
list1 = ["python", "kotlin", "node.js", "Go", "C++"]    # 設定一組串列(list)物件
print(list1)

for i in list1:     # 將列表list1中的元素一個一個依序取出,儲存於 i 這個變數中,進行後續操作
    print("你學習的程式語言是:" + i)    # 將列表取出的元素,列印出來

print("="*30)   # 輸出(列印) =符號 30次

# 接著看一下 for range的組合應用
for i in range(5):  # 從0~5(不含5)
    print(i)

print("="*30)

for i in range(1, 5, 2):    # 從 1~5 間隔 2
    print(i)

print("="*30)   # 輸出(列印) =符號 30次

list1_num = len(list1)      # 計算list1列表長度(元素數量)
print("list1列表物件長度(元素數量):", list1_num)  # 觀察、比較一下這二種輸出方式有何差別?
print("list1列表物件長度(元素數量):" + str(list1_num))
# ↑因為list1_num是數字型態,若要使用 + 符號進行文字串接,必須先將數字變數使用str轉換為文字型態

print("="*30)

for i in range(len(list1)):
    print("list1[" + str(i) + "]元素內容:" + list1[i])

print("="*30)

# 在串列末端新增元素
list1.append("Java")
print(list1)

# 移除串列中指定的元素
list1.remove("C++")
print(list1)

串列(list)真的是程式設計中相當實用、好用又重要的物件

上列程式碼結果如下供參:

2020年10月18日 星期日

pygame玩遊戲系列(8)~談談pygame中二個物件是否發生「碰撞」的檢核機制

 前面已經談過一些pygame遊戲中的物件操控及設定的概念

但是遊戲中很基本的一個「碰撞」檢核,一直沒有介紹的~~所以遊戲只能很無聊的動動滑鼠、鍵盤,以及想辦法讓物件自動移動(飄落、上升...)等等,當然更不用談所謂的「計分」、「射擊」等等遊戲元素的設計!

所以囉~~這次就趕緊先來談一下pygame中所謂的是否發生「碰撞」這個概念!

當然,pygame本身就已經有所謂的「(群組)碰撞檢核」模組可供呼叫使用

但是對學習程式本身而言,「知其所以然」個人認為是相當重要的~不然很可能發生你自己寫了些甚麼東西,自己都不知道的窘境(我自己以前就是如此)!以至於想要做一些精進或改寫一些需求或設計時,根本不知從何下手!只有自己對其基本概念有所釐清,才能充分掌握內建模組的設計及設定理念,遇到問題時也才知道如何思考、或精進!

好了~~這次就單純以遊戲視窗中二個物件是否發生碰撞來做簡單的概念說明及操作示範!

所謂的二個物件發生「碰撞」,其實就是檢查二個物件的「區塊(矩形座標物件)」是否發生「重疊」在一起的狀態!

所以要檢核二個物件是否發生「重疊」就是遊戲中二個物件是否發生「碰撞」的核心!

好囉~~那剩下的問題就是:在程式中如何去檢核二個物件是否發生重疊呢?

(大家可以自己先思考看看~~~二個矩形物件是否重疊的條件是甚麼呢?如何寫出一個完整的判斷式呢?)

先參考以下的幾張圖表,在思考看看~不一定要受限圖表上的說明及參數,你也可以用自己的思考模式去創造自己的檢核機制!(但記得一定要從二個物件「前、後、左、右」不同的相對關係去進行多重檢核喔!)




以上~那些是發生重疊(碰撞)的狀態呢?條件是甚麼?

2020年10月11日 星期日

pygame玩遊戲系列(7)~遊戲中隨機出現物件並設定遊戲更新頻率

 這次我們同樣在上次的基礎上,繼續來看看如何將遊戲發展下去!

基本上,透過上一篇的說明及設定,我們應該要能夠認識所謂的pygame.rect這個重要的物件,後續我們的相關操作,都會應用到rect這個矩形座標物件的相關概念及操作!假如還不太清楚的話,建議一定要再回去好好了解一下,不然後續愈來愈複雜的設定及操作,會讓人眼花撩亂甚至錯亂的!

到上一篇為止,我們主要是完成了遊戲主體(小車)的設定及操控,但是遊戲中的其他元件,如:敵人、障礙物、禮物、射擊子彈...等等,都還沒有出現呢!

當然要讓以上各式各樣的遊戲元件出現,還要涉及到許多語法及程式概念(如:函式、物件導向等等)的認識,我們會一步一步來進化並認識這些程式及語法的操作,而在這之前,我們還是先用「土法煉鋼」的方式,一步一步來認識這些元件的基本概念,這樣不但壓力比較不大而且重要的是會對後續的函式、物件導向等的設定及操作建立比較完整的概念及基礎!

這次呢~~我們主要目標設定為:

一、如何在遊戲視窗中「隨機出現」物件並自動移動(本篇設定為禮物從天而降)

二、設定遊戲的更新頻率(讓遊戲依設定的頻率進行更新,避免因為電腦效能差異所產生的遊戲視覺差異)

好囉~~一樣先上程式碼的部分:

import pygame, sys, random
from pygame.locals import *
pygame.init()

car_img = pygame.image.load("./imgs/car6.png")
screen_width, screen_height = 500, 380  # 設定遊戲視窗寬、高參數
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('騎車春遊趣')
screen_rect = screen.get_rect()  # 獲取遊戲視窗矩形座標參數儲存於參數:screen_rect
car_rect = car_img.get_rect()    # 獲取小車矩形座標參數儲存於參數:car_rect
car_rect.midbottom = screen_rect.midbottom    # 將小車的中心底部座標設定與視窗的中心底部座標貼齊

# 產生gift物件並設定其隨機出現於遊戲視窗上方
gift = pygame.image.load("./imgs/gift320.png")
gift_rect = gift.get_rect()
gift_rect.centerx = random.randrange(0, screen_rect.width)

clock = pygame.time.Clock()  # 實體化Clock物件

while True:
    screen.fill((255, 255, 0))   # 將遊戲視窗背景塗成黃色

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

    key_p = pygame.key.get_pressed()
    if (key_p[pygame.K_l] or key_p[pygame.K_LEFT]) and car_rect.left >= screen_rect.left:
        car_rect.x -= 2
    if (key_p[pygame.K_r] or key_p[pygame.K_RIGHT]) and car_rect.right <= screen_rect.right:
        car_rect.x += 2

    # 透過小車矩形參數:car_rec於指定位置繪製小車(car_img)
    screen.blit(car_img, car_rect)

    # 設定禮物降落的速度,並設定若超出遊戲視窗下方,就隨機從上方再次出現並降落
    if gift_rect.top < screen_rect.bottom:
        screen.blit(gift, gift_rect)
        gift_rect.y += 1
    else:   # 重新將gift物件設定為隨機出現於遊戲視窗上方
        gift_rect.centerx = random.randrange(0, screen_rect.width)
        gift_rect.bottom = 0

    clock.tick(90)  # 設定更新頻率為90(就是每秒更新90次的意思,數字愈大~更新愈多次,車子、禮物等跑得愈快)
    pygame.display.update()    # 更新視窗

其中比較需要注意的是:

2020年10月5日 星期一

pygame玩遊戲系列(6)~認識一下pygame中的矩形座標物件Rect

 遊戲主要的設計及操作,大都在於安排遊戲中的角色定位、移動、行為、顯示/隱藏及偵測使用者行為及物件之間的相對關係及重要的「碰撞偵測」等等!

而這些有關物件的位置安排及相對位置、移動甚至是碰撞偵測等等,都跟pygame中一個物件:矩形座標物件:Rect 有關!

先簡單認識一下:pygame.Rect

基本上rect矩形物件是由一個矩形的四個參數:Rect(left, top, width, height) -> Rect 所構成的一個寬度=width, 高度=height, 矩形左上角座標:(left, top)的矩形參數物件。


在pygame中只要是引入的角色(物件)都能藉由設定獲取一組專屬的矩形物件,作為該物件定點、移動、物件相對位置及關係等等相關操作之應用。

例如~我們在前一篇設定小車在遊戲視窗中的起始位置的設定、遊戲視窗左右邊界偵測判斷等等,是先將計算後的數字設定成小車的座標點。這樣的操作,日後若是程式日益龐大或是我們要修改視窗大小等參數時,就得將相關數字一併重新計算修改,這樣不僅勞神耗時,而且非常容易因為漏改或計算錯誤而產生不易察覺的錯誤,造成維護及操作上的困擾!

在進入程式碼操作之前,我們先來認識一下rect的一些重要概念:

一、遊戲中物件獲取矩形座標參數方法:物件名稱.get_rect()

二、獲取矩形座標參數(rect)後,可藉由該物件其矩形座標相關虛擬參數:

進行相關設定及操作。

有關pygame.rect的詳細介紹可參考pygame官方文件

現在我們就將前一篇相關位置的設定及邊界偵測等相關參數改為使用rect參數進行操作,如下:

import pygame, sys
from pygame.locals import *
pygame.init()

car_img = pygame.image.load("./imgs/car6.png")
screen_width, screen_height = 500, 380  #設定遊戲視窗寬、高參數
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('騎車春遊趣')

screen_rect = screen.get_rect() #獲取遊戲視窗矩形座標參數儲存於參數:screen_rect
car_rec = car_img.get_rect()    #獲取小車矩形座標參數儲存於參數:car_rect

#設定小車座標方式:將(小車中心點x座標定位於視窗中心點x座標, 小車底部座標與視窗底部貼齊)
car_rec.centerx, car_rec.bottom = screen_rect.centerx, screen_rect.bottom
#另一種完全相同且更簡便的設定方法,就是將小車的中心底部座標設定與視窗的中心底部座標貼齊即可
car_rec.midbottom = screen_rect.midbottom

while True:
    screen.fill((255,255,0))   #將遊戲視窗背景塗成黃色
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

    key_p = pygame.key.get_pressed()
    if (key_p[pygame.K_l] or key_p[pygame.K_LEFT]) and car_rec.left >= screen_rect.left:
        car_rec.x -= 2
    if (key_p[pygame.K_r] or key_p[pygame.K_RIGHT]) and car_rec.right <= screen_rect.right:
        car_rec.x += 2

    # 透過小車矩形參數:car_rec於指定位置繪製小車(car_img)
    screen.blit(car_img, car_rec)

    pygame.display.update()    #更新視窗


這樣全部的設定中就只剩下了遊戲視窗的寬、高設定,其他都是透過rect參數座標進行相關設定及操作,日後維護起來就方便多了!

2020年10月4日 星期日

pygame玩遊戲系列(5)~偵測按鍵動作讓物件持續移動

 前面介紹了如何透過鍵盤按鍵的操作讓物件進行移動的操作!

透過上述操作的方式,透過偵測是否有按鍵被「按下去」來進行移動,這樣的方式讓物件移動時,移動模式是按一次指定的按鍵,車子移動一次(也就是設定的2單位),若要讓車子一直移動就需要不斷的重複按指定按鍵。

即使你一直按住指定按鍵時,系統只會偵測到一次「按鍵被按下去」的訊號,車子依舊只會移動一次,不會一直跑!(這就是上一篇我們留下要思考的點之一)

這次,我們就來看看如何設計讓使用者「按住」指定按鍵時,遊戲中的物件(小車)可以持續移動吧!

在實作貼出程式碼前,我們先來思考一下設計的注意事項:

有關如何讓遊戲中物件(小車)移動的概念,就請參考前一篇相關的介紹及說明,這裡就不重複敘述了!

一、首先先談一下:在pygame中,按鍵被「按下去(KEYDOWN)」和被「按住不放(PRESSED)」是不同的二種事件,要仔細分清楚~不能混為一談喔!

二、我們希望使用者「按住」鍵盤「L」或是「向左(←)」按鍵時,小車會持續向左移動,但當小車移動到遊戲視窗左邊界時,就停住不會再移動了(以免小車跑出遊戲視窗外)!

三、我們希望使用者「按住」鍵盤「R」或是「向右(→)」按鍵時,小車會持續向右移動,但當小車移動到遊戲視窗右邊界時,就停住不會再移動了(同樣是避免小車跑出遊戲視窗外)!

好囉~~那為了達成以上的設計目標,主要的核心就是如何偵測遊戲過程是否有按鍵被「按住」又是那些按鍵被「按住」了!是吧~~?!

一樣先貼出完整程式碼直接觀看囉~~~

import pygame, sys
from pygame.locals import *

pygame.init()
bg = pygame.image.load("./imgs/bg-02.jpg")     #設定背景圖來源
car_img = pygame.image.load("./imgs/car6.png")    #設定要被控制的小車圖檔來源
screen = pygame.display.set_mode((500, 380))    #設定視窗資訊
pygame.display.set_caption('騎車春遊趣')       #設定視窗標題

car_x = 240 #設定腳踏車圖檔起始x座標位置

while True:   #主視窗循環
    screen.blit(bg, (0, 0))  # 設定視窗的背景圖片及相對位置
    for event in pygame.event.get():   #偵測視窗中獲取的事件資訊
        if event.type == QUIT:      #如果出現[關閉]事件(按了關閉視窗的按鈕)時
            pygame.quit()      #離開pygame
            sys.exit()      #離開系統

    key_p = pygame.key.get_pressed()  #偵測是否有按鍵被按住的狀態
    # 若是L鍵或是向左(←)鍵被按住而且車子的x座標大於0(視窗左邊邊界位置,避免車子跑出視窗左邊界)
    if (key_p[pygame.K_l] or key_p[pygame.K_LEFT]) and car_x >= 0:
        car_x -= 2  #車子向左移動2單位
    if (key_p[pygame.K_r] or key_p[pygame.K_RIGHT]) and car_x <= 436:
    #若是R鍵或是向右(→)鍵被按住而且車子的x座標小於436(視窗寬度500-車子圖檔的寬度64,避免車子跑出視窗右邊)
        car_x += 2  #車子向右移動2單位

    screen.blit(car_img, (car_x, 270))  # 在指定的位置繪製出車子
    pygame.display.update()    #更新視窗

大家可以對照前一篇的按下按鍵的移動方式一起比較其中差異!

【OnCode大叔簡單玩python】~使用python進行md5與SHA雜湊加密

 這次來玩一下資料的加密!

MD5和SHA1、SHA2都是目前常用的資料加密方式,尤其是在一些帳號、密碼的認證、儲存操作中,也都會有此需求!

在python中可以很輕易地實現以上的雜湊加密操作喔!這次就紀錄、分享這部分的操作!

認識一下:MD5SHA2

在python3中主要是透過「hashlib」模組來完成MD5和SHA1、SHA2的加密操作!

現在就透過以下程式碼來直接看看如何進行相關的雜湊加密實作:

import hashlib

data = "wan"

md5 = hashlib.md5()
sha1 = hashlib.sha1()
sha256 = hashlib.sha256()
sha224 = hashlib.sha224()
sha512 = hashlib.sha512()

# 須先將資料編碼,再更新相關雜湊值
md5.update(data.encode("utf-8"))
sha1.update(data.encode("utf-8"))
sha256.update(data.encode("utf-8"))
sha224.update(data.encode("utf-8"))
sha512.update(data.encode("utf-8"))

#取得相關雜湊加密結果
h_md5 = md5.hexdigest()
h_sha1 = sha1.hexdigest()
h_sha256 = sha256.hexdigest()
h_sha224 = sha224.hexdigest()
h_sha512 = sha512.hexdigest()

print("原始資料:"+data)
print("md5雜湊加密:"+h_md5)
print("SHA1雜湊加密:"+h_sha1)
print("SHA256雜湊加密:"+h_sha256)
print("SHA224雜湊加密:"+h_sha224)
print("SHA512雜湊加密:"+h_sha512)

雜湊加密結果如下:


也是相當簡單的操作就可以實作完成的!

其實重點應該是如何將相關的操作實際應用到系統的設計及思維中,這也是程式設計中最重要、最有趣的地方!

好了~~這次的紀錄、分享就到這囉!