【Python】那些年我們一起玩過的遊戲(四)-貪吃蛇(上)

更新於 2022/06/18閱讀時間約 33 分鐘
Blockade(封鎖線)這款你可能不知道的貪吃蛇類史祖,問世於1976年街機平台上,其可兩人同時對戰的設計與簡約卻又不簡單的遊戲模式,在當時還真讓不少人為之瘋狂,這也是我們本次教學所要致敬的對象Blockade(封鎖線),希望在完成遊戲後也能讓您感受到70年代人們對此遊戲的瘋狂,廢話不多說以下開始本次教學。
依照慣例我們還是先來看看完成後的遊戲影片:
以下會以”A、提案企劃 > B、執行企劃 > C、製作日誌”的順序寫作,各部份代表的分工如下:
A、提案企劃:主要用來紀錄點子,平常想到就可以陸續不斷的寫,等有專案要執行時就從中挑選出一份合適的企劃來執行。
B、執行企劃:在確定要執行的提案企劃後,接下來會在針對需要執行的內容作更完整的細節規格與製作規畫,以方便讓製作人員了解到要如何執行此專案。
C、製作日誌執行專案時,每位製作人員會將製作時的心得、經驗與規劃方式紀錄下來,以方便往後維護時可以給自己或接手的人參考。

A、提案企劃

一句話形容這個遊戲

  • 闔家娛樂的對戰遊戲

遊戲類型

  • 休閒類

遊戲特色

  • 對戰
  • 闔家娛樂

發想概念

  • 藉由重製Blockade(封鎖線)遊戲學習Python語言

遊戲玩法

  • 需兩人同時一起遊玩
  • 控制不斷前進與的長條並阻擋對手繼續前進

目標族群

  • 用Python學遊戲

發行平台

  • Windows
  • MAC
  • Linux

預計製作期

  • 7天

美術風格

  • 復古字元風格

遊戲周邊

  • 復古遊戲機

製作人員需求

  • 企劃 x 1
  • 美術 x 1
  • 程式 x 1

收費方式

  • 佛家弟子不談錢談緣,什麼是緣。。。50元(好冷)

製作預算

  • 繼續燒熱血當預算

參考資料

B、執行企劃

前言

本企劃的重點依然還是以重製Blockade(封鎖線)遊戲來學習使用Python語言,希望讓您能在學習程式語言同時也能了解到遊戲的運作原理。

使用解析度

  • 800 x 600

遊戲玩法

遊戲流程
遊戲畫面示意圖
細節說明
  • 畫面上箭頭會持續朝前方移動
  • 箭頭每移動一格線段就會增加一格
  • 在箭頭移動中玩家可操控左右上下轉向
  • 箭頭碰到我方或對方線段就算失敗,失敗後對方分數加1
  • 雙方任一方先達到分數6遊戲結束

遊戲操作

鍵盤
Esc:結束遊戲
Enter:開始遊戲
P:開啟/關閉遊戲除錯模式
W:1P上移動
A:1P左移動
S:1P下移動
D:1P右移動
上:2P上移動
左:2P左移動
下:2P下移動
右:2P右移動

美術元件列表

  • 字元”▨”,編碼1
  • 字元”▦”,編碼2
  • 字元”⠀”,編碼3
  • 字元”6”,編碼6
  • 字元”▴”,編碼10
  • 字元”▾”,編碼11
  • 字元”◂”,編碼12
  • 字元”▸”,編碼13
  • 字元”▵”,編碼20
  • 字元”▿”,編碼21
  • 字元”◃”,編碼22
  • 字元”▹”,編碼23

C、開發日誌

開發工具

使用語言與版本
Python 3.7.0
安裝套件
在安裝套件前建議先檢查一下pip管理工具並更新,請在命令列輸入以下指令:
python -m pip install --upgrade pip
以下為所需安裝套件:
  • PyGame - 遊戲開發套件
請在命令列輸入以下指令以進行安裝:
pip install pygame
第2~3天
系統分析與設計

關於文字模式

經歷過DOS時代的前輩們都非常熟習這個模式,在這模式下只能使用系統提供的ASCII碼來作畫面顯示,其實在Windows上也可以體驗文字模式,只要開啟 ”命令提示字元”程式。
言歸正傳提到文字模式主要是想說明本次的教學我們會以摸擬文字模式的風格來繪製遊戲畫面,也就是說我們遊戲的畫面繪製會把”字元”當作圖形來顯示,這樣會讓畫面的感覺更趨近街機版的Blockade(封鎖線),接下來我們需要先選一套裡面有本次遊戲所需用到的圖案字型庫,在這邊我選用了微軟免費等寬字型(Cascadia Code)來當主要的字型庫,以下是字型庫下載網址,進入後請下載Cascadia.ttf檔案:
下載完畢後在Cascadia.ttf上快速點擊兩下,會出現以下視窗:
點擊”安裝”將此字形檔安裝進您的Windows系統,並且打開字元對應表程式:
將字形選到”Cascadia Code”,這些字元裡面的某些部分稍後會被我們選作遊戲的基本圖形使用,這在稍後的遊戲程式說明裡會在進一步解說。

關於陣列元素對應畫面技巧

何謂陣列元素對應畫面技巧?我們實際舉個例子來說明,會比較容易理解, 首先我們設定8x8二維陣列如下:
接下來在二維陣列內填入數字1如下:
然後判斷二維陣列只要填入1的地方就在畫面相對位置上顯示字元■,完成後就可以看到如下圖案:
這就是陣列元素對應畫面技巧,只要依照在二維陣列內填入代表各種圖形的數字,然後繪圖的時候在判斷二維陣列內的數字將相對應到的字元顯示在畫面上就可以了,這也是本次遊戲教學在顯示畫面時所使用到的技巧。
其實這技巧也常被用在PRG遊戲的地圖顯示上,這等以後有機會分享RPG類遊戲教學時在詳細說明。
第4~7天
程式碼說明

主程式

所有Blockade(封鎖線)的邏輯運作與繪圖方法都在這邊執行,已將程式碼放置GitHub Gist上,點選以下連結查看:

【play.py程式碼】

程式碼內已寫上詳細說明,後面再針對細節作個別解說:
19 ~ 21:宣告字元遊戲區大小變數
# 遊戲區大小. 
game_area_width = 64
game_area_height = 48
27 ~ 28:設定字元遊戲區二維陣列
# 遊戲區陣列. 
gameAreaArray =[[0]*game_area_height for i in range(game_area_width)]
設定後就可以使用如gameAreaArray[0][0] = 1 來設定字元編號
75 ~ 81:秀字函數
# — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — 
# 函數:秀字. 
# — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
def showFont( text, x, y, color): 
global canvas
text = font_24.render(text, True, color)
canvas.blit( text, (x,y))
此函數是本次遊戲畫面顯示的重點,前面解說過會以字元來顯示畫面,所以都是通過此函數來將要顯示的字元或文字顯示在畫面上。
83 ~ 114:判斷邊界-1P
# — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — 
# 函數:判斷邊界-1P. 
# — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
def ifBoundary1P(direction): 
global gameAreaArray, game1P_x, game1P_y, playFial, score2P
  # 判斷邊界. 
if(game1P_x > game_area_width-2):
game1P_x = game_area_width-1
elif(game1P_x < 1):
game1P_x = 0
if(game1P_y > game_area_height-2):
game1P_y = game_area_height-1
elif(game1P_y < 1):
game1P_y = 0

# 設定失敗.
if(gameAreaArray[game1P_x][game1P_y] != 0):
playFial = 1
gameAreaArray[game1P_x][game1P_y] = 2
# 加對方分數.
score2P += 1
else:
# 箭頭.
if(direction==0):
gameAreaArray[game1P_x][game1P_y] = 10
elif(direction==1):
gameAreaArray[game1P_x][game1P_y] = 11
elif(direction==2):
gameAreaArray[game1P_x][game1P_y] = 12
elif(direction==3):
gameAreaArray[game1P_x][game1P_y] = 13
以上是此函數的所有程式碼,以下在針對程式細節一一解說。
# 判斷邊界. 
if(game1P_x > game_area_width-2):
game1P_x = game_area_width-1
elif(game1P_x < 1):
game1P_x = 0
if(game1P_y > game_area_height-2):
game1P_y = game_area_height-1
elif(game1P_y < 1):
game1P_y = 0
這邊在判斷1P玩家的箭頭是否移動到超出邊界,是的話會將變數修正再邊界上。
# 設定失敗. 
if(gameAreaArray[game1P_x][game1P_y] != 0):
playFial = 1
gameAreaArray[game1P_x][game1P_y] = 2
# 加對方分數.
score2P += 1
else:
# 箭頭.
if(direction==0):
gameAreaArray[game1P_x][game1P_y] = 10
elif(direction==1):
gameAreaArray[game1P_x][game1P_y] = 11
elif(direction==2):
gameAreaArray[game1P_x][game1P_y] = 12
elif(direction==3):
gameAreaArray[game1P_x][game1P_y] = 13
以上程式碼上半是在判斷1P是否碰上障礙物,只要判斷要前進的陣列位置內容是否不為0就表示發生碰撞了,如果要前進的陣列位置內容為0表示尚未發生碰撞,這時會進入程式碼下半段,這邊是將要前進的位置改成箭頭編號。
116 ~ 147:判斷邊界-2P
判斷邊界2P的運作原理與判斷邊界1P相同,只是將1P的相關變數改成2P的相關變數。
149 ~ 174:重新開始遊戲,初始遊戲變數
176 ~ 453:主程式區段
180 ~200:初始pygame與遊戲變數
# 初始. 
pygame.init()
# 顯示Title.
pygame.display.set_caption(u”封鎖線遊戲”)
# 建立畫佈大小.
canvas = pygame.display.set_mode((canvas_width, canvas_height))
# 時脈.
clock = pygame.time.Clock() # 設定字型.
font_24 = pygame.font.Font("Fonts/Cascadia.ttf", 24) # 重新開始遊戲.
restart()
# 1P位置.
gameAreaArray[game1P_x][game1P_y] = 11
# 2P位置.
gameAreaArray[game2P_x][game2P_y] = 20# 設定字型.
font_24 = pygame.font.Font(“Fonts/Cascadia.ttf”, 24)
# 重新開始遊戲.
restart()
# 1P位置.
gameAreaArray[game1P_x][game1P_y] = 11
# 2P位置.
gameAreaArray[game2P_x][game2P_y] = 20
主要是初始pygame基本設定,如設定Title、設定畫佈大小、時脈、設定字型,還有重新設定遊戲變數跟1P與2P的初始位置。
202 ~449:主迴圈
210 ~273:判斷輸入
# — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — 
# 判斷輸入. 
# — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
for event in pygame.event.get(): 
# 離開遊戲.
if event.type == pygame.QUIT:
running = False
# 判斷按下按鈕
if event.type == pygame.KEYDOWN:
# 判斷按下ESC按鈕
if event.key == pygame.K_ESCAPE:
running = False
# 除錯訊息開關.
elif event.key == pygame.K_p:
debug_message = not debug_message
# 0:遊戲結束.
if gameMode == 0:
# 開始遊戲.
if event.key == pygame.K_RETURN:
# 初始分數.
score1P = 0
score2P = 0
# 重新開始遊戲.
restartTime = 0
restart()
# 設定開始遊戲.
gameMode = 1
以上程式碼主要是在判斷玩家按下Esc按鈕後處理結束遊戲、按下P按鈕後顯示除錯訊息與按下Enter按鈕開始遊戲。
# 1:遊戲中. 
elif gameMode == 1:
# — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
# 1P-上.
if event.key == pygame.K_w:
game1P_direction = 0
# — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
# 1P-下.
elif event.key == pygame.K_s:
game1P_direction = 1
# — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
# 1P-左.
elif event.key == pygame.K_a:
game1P_direction = 2
# — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
# 1P-右.
elif event.key == pygame.K_d:
game1P_direction = 3
# — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
# 2P-上.
if event.key == pygame.K_UP:
game2P_direction = 0
# — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
# 2P-下.
elif event.key == pygame.K_DOWN:
game2P_direction = 1
# — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
# 2P-左.
elif event.key == pygame.K_LEFT:
game2P_direction = 2
# — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
# 2P-右.
elif event.key == pygame.K_RIGHT:
game2P_direction = 3
這段程式碼主要處理遊戲中判斷1P與2P的控制箭頭方向判斷(控制按鍵請參考上方遊戲操作說明)。
281 ~293:遊戲結束畫面顯示
# — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — 
# 遊戲模式.
# 0:遊戲結束.
if gameMode == 0:
# 清除顯示區.
for y in range(18,24):
for x in range(25,40):
gameAreaArray[x][y] = 3
# 顯示GameOver與雙方分數.
showFont( “GAME”, 380, 240, green)
showFont( “OVER”, 380, 262, green)
showFont( str(score1P), 340, 262, green)
showFont( str(score2P), 460, 262, green)
gameMode=0表示遊戲結束狀態,接下來是先用迴圈把中間區域清空,然後顯示遊戲結束訊息與雙方分數。
301 ~340:1P、2P箭頭移動
# 還沒分出勝負. 
if (playFial == 0):
if(move):
# 1P位置.
gameAreaArray[game1P_x][game1P_y] = 1
# 1P前進方向.
# 0:上.
if (game1P_direction == 0):
game1P_y -= 1
# 1:下.
elif (game1P_direction == 1):
game1P_y += 1
# 2:左.
elif (game1P_direction == 2):
game1P_x -= 1
# 3:右.
elif (game1P_direction == 3):
game1P_x += 1
# 1P判斷邊界.
ifBoundary1P(game1P_direction)
else:
# 2P位置.
gameAreaArray[game2P_x][game2P_y] = 1
# 2P前進方向.
# 0:上.
if (game2P_direction == 0):
game2P_y -= 1
# 1:下.
elif (game2P_direction == 1):
game2P_y += 1
# 2:左.
elif (game2P_direction == 2):
game2P_x -= 1
# 3:右.
elif (game2P_direction == 3):
game2P_x += 1
# 1P判斷邊界.
ifBoundary2P(game2P_direction)
move = not move
在變數playFial=0時表示遊戲尚未分出勝負,程式會繼續讓1P或2P往箭頭前方前進,其中1P的前進方向會判斷game1P_direction變數內容( 0:上 1:下 2:左 3:右.),處理加減陣列元素位置變數game1P_x、game1P_y,2P前進方向會判斷game2P_direction變數內容( 0:上 1:下 2:左 3:右.),處理加減陣列元素位置變數game2P_x、game2P_y,然後再看到move變數,主要是讓1P與2P同時間只能有一個移動,也就以1P移動一步 →2P移動一步→1P移動一步 →2P移動一步如此重複移動直到玩家箭頭發生碰撞。
342 ~366:分出勝負後處理
# 分出勝負. 
else:
# 1P失敗,閃爍失敗處.
if(playFial==1):
if(gameAreaArray[game1P_x][game1P_y]==2):
gameAreaArray[game1P_x][game1P_y] = 3
else:
gameAreaArray[game1P_x][game1P_y] = 2
# 2P失敗,閃爍失敗處.
elif(playFial==2):
if(gameAreaArray[game2P_x][game2P_y]==2):
gameAreaArray[game2P_x][game2P_y] = 3
else:
gameAreaArray[game2P_x][game2P_y] = 2
# 重新開始遊戲時間.
restartTime += 1
if((restartTime / fps) == 3):
# 判斷遊戲結束.
if(score1P >=6 or score2P >= 6):
# 設定遊戲結束.
gameMode = 0
else:
restartTime = 0
restart() # 重新開始遊戲.
變數playFial等於1代表1P失敗,然後在碰撞陣列位置輪流設定圖形編號3與2,這樣等繪製畫面時會在畫面上呈現閃爍的失敗點,變數playFial等於 2代表2P失敗,程式同樣會輪流顯示圖形編號3與2,然後等待restartTime變數累加到24(算法為fps變數預設是8,24/8=3)的時候就進入判斷遊戲結束狀態,進入後如果1P分數(score1P)與2P分數(score2P)其中一個分數大於6表示分出勝負了,所以將變數gameMode狀態設定為0讓程式去顯示遊戲結束畫面,反之就初始變數重新開始遊戲。
368 ~378:在畫面上繪製閃爍的失敗點與分數
# 在畫面上繪製閃爍的失敗點與分數
if (playFial > 0):
# 1P失敗,2P閃爍分數.
if(playFial==1):
if(gameAreaArray[game1P_x][game1P_y]==2):
showFont( str(score2P), ((CONST_STARTING_2P_POS_X)*12)+15, ((CONST_STARTING_2P_POS_Y + 2)*12), green)
showFont( str(score1P), ((CONST_STARTING_1P_POS_X)*12)+15, ((CONST_STARTING_1P_POS_Y — 2)*12), green)
# 2P失敗,1P閃爍分數.
elif(playFial==2):
if(gameAreaArray[game2P_x][game2P_y]==2):
showFont( str(score1P), ((CONST_STARTING_1P_POS_X)*12)+15, ((CONST_STARTING_1P_POS_Y — 2)*12), green)
showFont( str(score2P), ((CONST_STARTING_2P_POS_X)*12)+15, ((CONST_STARTING_2P_POS_Y + 2)*12), green)
這區塊的程式碼在處理將失敗點與分數繪製在畫面上,並進行閃爍。
380~392:設定外框編號
# — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — 
# 設定外框.
gameAreaArray[32][0]=6
for x in range(game_area_width):
if(gameAreaArray[x][0]==0):
gameAreaArray[x][0] = 1
if(gameAreaArray[x][game_area_height-1]==0):
gameAreaArray[x][game_area_height-1] = 1
for y in range(game_area_height):
if(gameAreaArray[0][y]==0):
gameAreaArray[0][y] = 1
if(gameAreaArray[game_area_width-1][y]==0):
gameAreaArray[game_area_width-1][y] = 1
以上程式碼主要在陣列內設定外框編號。
394~446:繪製遊戲畫面
# — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — 
# 繪製遊戲區.
ix = 15
iy = 2
for y in range(game_area_height):
for x in range(game_area_width):
# 方塊.
if(gameAreaArray[x][y]==1):
showFont( u”▨”, ix, iy, green)
# 死亡.
elif(gameAreaArray[x][y]==2):
showFont( u”▦”, ix, iy, green)
# 空白.
elif(gameAreaArray[x][y]==3):
showFont( u”⠀”, ix, iy, green)
# 6
elif(gameAreaArray[x][y]==6):
showFont( u”6", ix, iy, green)
# 1p-上箭頭.
elif(gameAreaArray[x][y]==10):
showFont( u”▴”, ix, iy, green)
# 1p-下箭頭.
elif(gameAreaArray[x][y]==11):
showFont( u”▾”, ix, iy, green)
# 1p-左箭頭.
elif(gameAreaArray[x][y]==12):
showFont( u”◂”, ix, iy, green)
# 1p-右箭頭.
elif(gameAreaArray[x][y]==13):
showFont( u”▸”, ix, iy, green)
# 2p-上箭頭.
elif(gameAreaArray[x][y]==20):
showFont( u”▵”, ix, iy, green)
# 2p-下箭頭.
elif(gameAreaArray[x][y]==21):
showFont( u”▿”, ix, iy, green)
# 2p-左箭頭.
elif(gameAreaArray[x][y]==22):
showFont( u”◃”, ix, iy, green)
# 2p-右箭頭.
elif(gameAreaArray[x][y]==23):
showFont( u”▹”, ix, iy, green)
# 除錯.
if(debug_message):
if(gameAreaArray[x][y]!=0):
# 顯示陣列編碼.
showFont( str(gameAreaArray[x][y]), ix, iy, (255, 0, 0))
# 顯示FPS.
showFont( u”FPS:” + str(int(clock.get_fps())), 8, 2, (255, 255, 255))
ix+=12
ix = 15
iy+=12
這邊使用兩個迴圈來判斷gameAreaArray二維陣列內的編號,然後在依照編號所代表的字元圖形繪製到畫面上,各字元編號所代表的圖形請參考上面美術元件列表。
436~442:除錯訊息
# 除錯. 
if(debug_message):
if(gameAreaArray[x][y]!=0):
# 顯示陣列編碼.
showFont( str(gameAreaArray[x][y]), ix, iy, (255, 0, 0))
# 顯示FPS.
showFont( u”FPS:” + str(int(clock.get_fps())), 8, 2, (255, 255, 255))
在按下P按鍵後可以顯示除錯訊息,這邊會將gameAreaArray二維陣列內的數字編號顯示在畫面上的相對位置,以方便我們查看gameAreaArray二維陣列內的編號與對應的字元圖形是否正確。

執行遊戲

  • 請在命令列下輸入python play.py 以執行遊戲

GitHub下載原始碼

後記

這次貪吃蛇系列很罕見的分成上下兩期來寫,主要是因為在找貪吃蛇相關資料的時候,發現原來貪吃蛇的玩法是從Blockade(封鎖線)這款遊戲變形而來,並且在看了Blockade(封鎖線)遊玩影片後發現其封閉式的雙打體驗還滿吸引我的,所以就決定上篇先以致敬Blockade(封鎖線)為開頭,下篇再將大家帶入主題貪吃蛇,順便也讓大家了解到原來貪吃蛇是從Blockade(封鎖線)變形而來的這個冷知識,希望大家會喜歡,本次教學也到這邊結束囉,接下來敬請期待下篇的貪吃蛇教學。
為什麼會看到廣告
avatar-img
5會員
16內容數
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
無限升級的沙龍 的其他內容
這幾天腦海裡一直浮現小時候很愛玩的一款紅白機光線槍遊戲打鴨子(Duck Hunt), 在倉庫翻找了好幾天就是找不到光線槍,不過倒是翻出了塵封已久的Wii,上網查了一下發現可以透過Wii Remote控制器連電腦玩槍卡遊戲,二話不說先來試試Wii Remote可否連接電腦當搖桿用。。。
有些風景需要親自經歷後才能了解箇中滋味,這初衷,也可能讓您在20幾年後的今天,被現實打擊到身心疲憊時為了鼓舞自己大聲吶喊莫忘初衷後可以立即回憶起的經歷。 以上故事純屬虛構,如有雷同實屬巧合,以下開始本次教學。 依照慣例我們一樣先來看看完成後的的遊玩影片: A、提案企劃 一句話形容這個遊戲 遊戲類型
Tetris,沒錯這次要聊的主題就是俄羅斯方塊(Tetris)也是小老弟我從小玩到大的最愛遊戲之一,每次只要學習新程式語言就會在祭出來在給他狠狠地致敬一下,俄羅斯方塊以其簡單易懂的遊戲規則,往往讓人一玩就無法自拔。。。剛說到哪裡了,什麼教程,先別吵,等我玩完這局俄羅斯方塊再說。。。
可能是初老症發作的的原因,最近玩到這類懷舊遊戲就很容易陷入某種懷舊時光的情緒中,一不小心就會玩到忘了時間,所以就興起了何不自己動手把童年那些有印象的街機遊戲全部實作一遍的念頭呢?不囉嗦以下就是這系列的第一款。。。
Blockade(封鎖線)是一款在1976年街機上發行的對戰遊戲,其簡單易懂的玩法,在當時可讓不少人為之瘋狂,這也是我們本次教學的主角,借由重製這款經典遊戲來學習如何使用Family BASIC開發遊戲,讓經典再現。
緣起 場景回到1986年鄉下的一家遊戲專賣店,一群小朋友圍著老闆正聽他口沫橫飛的說著,我跟你們說阿這卡夾還有這個鍵盤組合叫Family BASIC(註1)是用來開發紅白機遊戲用的,是我託廠商從日本弄回來的。。。
這幾天腦海裡一直浮現小時候很愛玩的一款紅白機光線槍遊戲打鴨子(Duck Hunt), 在倉庫翻找了好幾天就是找不到光線槍,不過倒是翻出了塵封已久的Wii,上網查了一下發現可以透過Wii Remote控制器連電腦玩槍卡遊戲,二話不說先來試試Wii Remote可否連接電腦當搖桿用。。。
有些風景需要親自經歷後才能了解箇中滋味,這初衷,也可能讓您在20幾年後的今天,被現實打擊到身心疲憊時為了鼓舞自己大聲吶喊莫忘初衷後可以立即回憶起的經歷。 以上故事純屬虛構,如有雷同實屬巧合,以下開始本次教學。 依照慣例我們一樣先來看看完成後的的遊玩影片: A、提案企劃 一句話形容這個遊戲 遊戲類型
Tetris,沒錯這次要聊的主題就是俄羅斯方塊(Tetris)也是小老弟我從小玩到大的最愛遊戲之一,每次只要學習新程式語言就會在祭出來在給他狠狠地致敬一下,俄羅斯方塊以其簡單易懂的遊戲規則,往往讓人一玩就無法自拔。。。剛說到哪裡了,什麼教程,先別吵,等我玩完這局俄羅斯方塊再說。。。
可能是初老症發作的的原因,最近玩到這類懷舊遊戲就很容易陷入某種懷舊時光的情緒中,一不小心就會玩到忘了時間,所以就興起了何不自己動手把童年那些有印象的街機遊戲全部實作一遍的念頭呢?不囉嗦以下就是這系列的第一款。。。
Blockade(封鎖線)是一款在1976年街機上發行的對戰遊戲,其簡單易懂的玩法,在當時可讓不少人為之瘋狂,這也是我們本次教學的主角,借由重製這款經典遊戲來學習如何使用Family BASIC開發遊戲,讓經典再現。
緣起 場景回到1986年鄉下的一家遊戲專賣店,一群小朋友圍著老闆正聽他口沫橫飛的說著,我跟你們說阿這卡夾還有這個鍵盤組合叫Family BASIC(註1)是用來開發紅白機遊戲用的,是我託廠商從日本弄回來的。。。
你可能也想看
Google News 追蹤
Thumbnail
我很鼓勵投資人不要只投資台股,對股市有一點熟悉度後,建議範圍擴況大到美股,甚至是投資全球。因為台股僅是單一國家/市場,如果能將資產投資到其他國家,風險會更分散,機會也更多,特別是美國股市。 美股會很難懂嗎?我相信你認識的美國企業可能會比台灣企業多,我從標普500成分股前15大企業裡隨便抓十
Thumbnail
投資新手大多從身邊市場開始著手,選擇台股市場入門,單筆投資或台股定期定額投資,隨著經驗累積,進入美股市場也是好選擇,這篇文章帶你前進美股投資,證券開戶選擇國內券商複委託,使用美股定期定額投資,並以國泰 CUBE App為例說明。 內容目錄: 1.一站式開戶:以國泰世華 CUBE App 為例
Thumbnail
這是張老師的第三本書,我想前二本應該也有很多朋友們都有讀過,我想絕對是受益良多,而這次在書名上就直接點出,著重在從投資的角度來切入
Thumbnail
在讀取檔案時,最怕路徑的問題,常常會有路徑錯誤造成的異常報錯。 為了避免諸如此類的問題發生,明白程式的當前目錄與檔案的路徑是很重要的。 可以利用os 模組是 Python 中的一個標準庫,提供了許多與操作系統的功能。 以下是一些常用的 os 模組基本操作及其範例: 1. os.getcwd
解讀JSON 字串 首先,你需要使用 Python 的 json 模組來解讀JSON 字串。 JSON的基本結構: 由花括號 {} 包圍,內部是鍵值對的集合,每個鍵值對之間用逗號分隔。 鍵是字串類型,值可以是任何JSON支持的資料類型(字串、數字、布林值、陣列、物件或 null)。 {
Thumbnail
在我們正式開始Python串接LINE Bot的教程之前,有必要先為大家準備好所需的工具。實際上,製作LINE Bot的工具有很多選擇,我將會介紹我在製作過程中所使用的具體工具有哪些,以及如何進行事前的準備工作。讓我們一起走進這個有趣的製作過程吧!
Thumbnail
每當要研究投資標的時,你是否也會覺得A網站的財報資料完整,又覺得B網站的選股條件完善,又覺得C網站的新聞比較重要,有時身邊又沒有隨身攜帶筆電怎麼好查詢呢?這時可能就在想怎麼沒有人開發一個程式能完成符合我想要的功能啊~~與其求助於人,不如自己動手做最好,有相同煩惱的人,LINE Bot超適合你!!
Thumbnail
在看官網文件時,看到一份文件:PEP 8 -- Style Guide for Python Code。這份文件是關於Python程式碼風格的指引和建議。
Thumbnail
Selenium WebDriver Page Object Model (POM) 設計模式,若是有開發過 UI 自動化測試或是寫網路爬蟲的多少都有聽過或是看過吧!  最近剛好有幸接觸到某外商的 SDET 面試考試,題目要求使用 POM 設計 UI 自動化測試,又再度幫自己複習一遍。 Why?
Thumbnail
畢竟~我是一個懶人嘛... 估狗之後,大部分的做法就是手動的去下載當前瀏覽器對應版本的 Driver,放到一個特定位置,將 Driver Binary 位置指向它。 在 Google Chrome About Page 你可以看到版本 接著去下載對應的 Chrome Driver ↓ 解決方案:
Thumbnail
我很鼓勵投資人不要只投資台股,對股市有一點熟悉度後,建議範圍擴況大到美股,甚至是投資全球。因為台股僅是單一國家/市場,如果能將資產投資到其他國家,風險會更分散,機會也更多,特別是美國股市。 美股會很難懂嗎?我相信你認識的美國企業可能會比台灣企業多,我從標普500成分股前15大企業裡隨便抓十
Thumbnail
投資新手大多從身邊市場開始著手,選擇台股市場入門,單筆投資或台股定期定額投資,隨著經驗累積,進入美股市場也是好選擇,這篇文章帶你前進美股投資,證券開戶選擇國內券商複委託,使用美股定期定額投資,並以國泰 CUBE App為例說明。 內容目錄: 1.一站式開戶:以國泰世華 CUBE App 為例
Thumbnail
這是張老師的第三本書,我想前二本應該也有很多朋友們都有讀過,我想絕對是受益良多,而這次在書名上就直接點出,著重在從投資的角度來切入
Thumbnail
在讀取檔案時,最怕路徑的問題,常常會有路徑錯誤造成的異常報錯。 為了避免諸如此類的問題發生,明白程式的當前目錄與檔案的路徑是很重要的。 可以利用os 模組是 Python 中的一個標準庫,提供了許多與操作系統的功能。 以下是一些常用的 os 模組基本操作及其範例: 1. os.getcwd
解讀JSON 字串 首先,你需要使用 Python 的 json 模組來解讀JSON 字串。 JSON的基本結構: 由花括號 {} 包圍,內部是鍵值對的集合,每個鍵值對之間用逗號分隔。 鍵是字串類型,值可以是任何JSON支持的資料類型(字串、數字、布林值、陣列、物件或 null)。 {
Thumbnail
在我們正式開始Python串接LINE Bot的教程之前,有必要先為大家準備好所需的工具。實際上,製作LINE Bot的工具有很多選擇,我將會介紹我在製作過程中所使用的具體工具有哪些,以及如何進行事前的準備工作。讓我們一起走進這個有趣的製作過程吧!
Thumbnail
每當要研究投資標的時,你是否也會覺得A網站的財報資料完整,又覺得B網站的選股條件完善,又覺得C網站的新聞比較重要,有時身邊又沒有隨身攜帶筆電怎麼好查詢呢?這時可能就在想怎麼沒有人開發一個程式能完成符合我想要的功能啊~~與其求助於人,不如自己動手做最好,有相同煩惱的人,LINE Bot超適合你!!
Thumbnail
在看官網文件時,看到一份文件:PEP 8 -- Style Guide for Python Code。這份文件是關於Python程式碼風格的指引和建議。
Thumbnail
Selenium WebDriver Page Object Model (POM) 設計模式,若是有開發過 UI 自動化測試或是寫網路爬蟲的多少都有聽過或是看過吧!  最近剛好有幸接觸到某外商的 SDET 面試考試,題目要求使用 POM 設計 UI 自動化測試,又再度幫自己複習一遍。 Why?
Thumbnail
畢竟~我是一個懶人嘛... 估狗之後,大部分的做法就是手動的去下載當前瀏覽器對應版本的 Driver,放到一個特定位置,將 Driver Binary 位置指向它。 在 Google Chrome About Page 你可以看到版本 接著去下載對應的 Chrome Driver ↓ 解決方案: