生活随笔
收集整理的這篇文章主要介紹了
Python 植物大战僵尸代码实现(2):植物卡片选择和种植
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
python 植物大戰(zhàn)僵尸代碼實現(xiàn)(2):植物卡片選擇和種植
- 功能介紹
- 代碼實現(xiàn)
- 植物卡片類
- 卡片欄類
- 鼠標(biāo)圖片切換
- 提示種在哪個方格中
- 編譯環(huán)境
功能介紹
最近一直在給這個植物大戰(zhàn)僵尸游戲添加新的植物和僵尸, 因為網(wǎng)上的圖片資源有限,能加的植物和僵尸比較少, 目前進(jìn)展如下:
功能實現(xiàn)如下:
- 支持的植物類型:太陽花,豌豆射手,寒冰射手,堅果,櫻桃炸彈。新增加植物:雙重豌豆射手,三重豌豆射手,食人花 ,小噴菇,土豆地雷,倭瓜。
- 支持的僵尸類型:普通僵尸,棋子僵尸,路障僵尸,鐵桶僵尸。新增加讀報僵尸。
- 使用json文件保存關(guān)卡信息,設(shè)置僵尸出現(xiàn)的時間和位置。
- 增加每關(guān)開始時選擇上場植物。
- 增加除草機(jī)。
Python 植物大戰(zhàn)僵尸代碼實現(xiàn)(1):圖片加載和顯示切換
下面是游戲的截圖:
圖1:新增的植物和僵尸
圖2:每關(guān)開始選擇上場植物卡片
圖3:選擇植物在哪里種植
植物卡片選擇和種植
如圖3所示,游戲中可以種植物的方格一共有45個(有5行,每行9列)。
這篇文章要介紹的是:
- 上方植物卡片欄的實現(xiàn)。
- 點擊植物卡片,鼠標(biāo)切換為植物圖片。
- 鼠標(biāo)移動時,判斷當(dāng)前在哪個方格中,并顯示半透明的植物作為提示。
完整代碼
游戲?qū)崿F(xiàn)代碼的github鏈接 植物大戰(zhàn)僵尸
這邊是csdn的下載鏈接 植物大戰(zhàn)僵尸
代碼實現(xiàn)
所有的植物卡片的名稱和屬性都保存在單獨的list中,每個list index都對應(yīng)一種植物。
比如list index 0 就是太陽花:
- card_name_list[0] 是太陽花卡片的名字,用來獲取太陽花卡片的圖片。
- plant_name_list[0] 是太陽花的名字,用來獲取太陽花卡片的圖片。
- plant_sun_list[0] 是種植太陽花需要花費的太陽點數(shù)。
- plant_frozen_time_list[0] 是太陽花的冷卻時間。
代碼在source\component\menubar.py中
card_name_list
= [c
.CARD_SUNFLOWER
, c
.CARD_PEASHOOTER
, c
.CARD_SNOWPEASHOOTER
, c
.CARD_WALLNUT
,c
.CARD_CHERRYBOMB
, c
.CARD_THREEPEASHOOTER
, c
.CARD_REPEATERPEA
, c
.CARD_CHOMPER
,c
.CARD_PUFFMUSHROOM
, c
.CARD_POTATOMINE
, c
.CARD_SQUASH
]
plant_name_list
= [c
.SUNFLOWER
, c
.PEASHOOTER
, c
.SNOWPEASHOOTER
, c
.WALLNUT
,c
.CHERRYBOMB
, c
.THREEPEASHOOTER
, c
.REPEATERPEA
, c
.CHOMPER
,c
.PUFFMUSHROOM
, c
.POTATOMINE
, c
.SQUASH
]
plant_sun_list
= [50, 100, 175, 50, 150, 325, 200, 150, 0, 25, 50]
plant_frozen_time_list
= [0, 5000, 5000, 10000, 5000, 5000, 5000, 5000, 8000, 8000, 8000]
all_card_list
= [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
植物卡片類
代碼在source\component\menubar.py中,每個植物卡片是一個單獨的Card類,用來顯示這個植物。
- checkMouseClick函數(shù):判斷鼠標(biāo)是否點擊到這個卡片
- canClick:判斷這個卡片是否能種植(有沒有足夠的點數(shù),是否還在冷卻時間內(nèi))
- update 函數(shù):通過設(shè)置圖片的透明度來表示這個卡片是否能選擇
class Card():def __init__(self
, x
, y
, name_index
, scale
=0.78):self
.loadFrame
(card_name_list
[name_index
], scale
)self
.rect
= self
.image
.get_rect
()self
.rect
.x
= xself
.rect
.y
= yself
.name_index
= name_indexself
.sun_cost
= plant_sun_list
[name_index
]self
.frozen_time
= plant_frozen_time_list
[name_index
]self
.frozen_timer
= -self
.frozen_timeself
.select
= Truedef loadFrame(self
, name
, scale
):frame
= tool
.GFX
[name
]rect
= frame
.get_rect
()width
, height
= rect
.w
, rect
.hself
.image
= tool
.get_image
(frame
, 0, 0, width
, height
, c
.BLACK
, scale
)def checkMouseClick(self
, mouse_pos
):x
, y
= mouse_pos
if(x
>= self
.rect
.x
and x
<= self
.rect
.right
andy
>= self
.rect
.y
and y
<= self
.rect
.bottom
):return Truereturn Falsedef canClick(self
, sun_value
, current_time
):if self
.sun_cost
<= sun_value
and (current_time
- self
.frozen_timer
) > self
.frozen_time
:return Truereturn Falsedef canSelect(self
):return self
.select
def setSelect(self
, can_select
):self
.select
= can_select
if can_select
:self
.image
.set_alpha
(255)else:self
.image
.set_alpha
(128)def setFrozenTime(self
, current_time
):self
.frozen_timer
= current_time
def update(self
, sun_value
, current_time
):if (self
.sun_cost
> sun_value
or(current_time
- self
.frozen_timer
) <= self
.frozen_time
):self
.image
.set_alpha
(128)else:self
.image
.set_alpha
(255)def draw(self
, surface
):surface
.blit
(self
.image
, self
.rect
)
卡片欄類
代碼在source\component\menubar.py中,MenuBar類顯示圖3中的植物卡片欄,
- self.sun_value:當(dāng)前采集的太陽點數(shù)
- self.card_list: 植物卡片的list
- setupCards函數(shù):遍歷初始化__init__函數(shù)中傳入這個關(guān)卡選好的植物卡片list,依次創(chuàng)建Card類,設(shè)置每個卡片的顯示位置。
- checkCardClick函數(shù):檢查鼠標(biāo)是否點擊了卡片欄上的某個植物卡片,如果選擇了一個可種植的卡片,返回結(jié)果。
class MenuBar():def __init__(self
, card_list
, sun_value
):self
.loadFrame
(c
.MENUBAR_BACKGROUND
)self
.rect
= self
.image
.get_rect
()self
.rect
.x
= 10self
.rect
.y
= 0self
.sun_value
= sun_valueself
.card_offset_x
= 32self
.setupCards
(card_list
)def loadFrame(self
, name
):frame
= tool
.GFX
[name
]rect
= frame
.get_rect
()frame_rect
= (rect
.x
, rect
.y
, rect
.w
, rect
.h
)self
.image
= tool
.get_image
(tool
.GFX
[name
], *frame_rect
, c
.WHITE
, 1)def update(self
, current_time
):self
.current_time
= current_time
for card
in self
.card_list
:card
.update
(self
.sun_value
, self
.current_time
)def createImage(self
, x
, y
, num
):if num
== 1:returnimg
= self
.imagerect
= self
.image
.get_rect
()width
= rect
.wheight
= rect
.hself
.image
= pg
.Surface
((width
* num
, height
)).convert
()self
.rect
= self
.image
.get_rect
()self
.rect
.x
= xself
.rect
.y
= y
for i
in range(num
):x
= i
* widthself
.image
.blit
(img
, (x
,0))self
.image
.set_colorkey
(c
.BLACK
)def setupCards(self
, card_list
):self
.card_list
= []x
= self
.card_offset_xy
= 8for index
in card_list
:x
+= 55self
.card_list
.append
(Card
(x
, y
, index
))def checkCardClick(self
, mouse_pos
):result
= Nonefor card
in self
.card_list
:if card
.checkMouseClick
(mouse_pos
):if card
.canClick
(self
.sun_value
, self
.current_time
):result
= (plant_name_list
[card
.name_index
], card
.sun_cost
)breakreturn result
def checkMenuBarClick(self
, mouse_pos
):x
, y
= mouse_pos
if(x
>= self
.rect
.x
and x
<= self
.rect
.right
andy
>= self
.rect
.y
and y
<= self
.rect
.bottom
):return Truereturn Falsedef decreaseSunValue(self
, value
):self
.sun_value
-= value
def increaseSunValue(self
, value
):self
.sun_value
+= value
def setCardFrozenTime(self
, plant_name
):for card
in self
.card_list
:if plant_name_list
[card
.name_index
] == plant_name
:card
.setFrozenTime
(self
.current_time
)breakdef drawSunValue(self
):self
.value_image
= getSunValueImage
(self
.sun_value
)self
.value_rect
= self
.value_image
.get_rect
()self
.value_rect
.x
= 21self
.value_rect
.y
= self
.rect
.bottom
- 21self
.image
.blit
(self
.value_image
, self
.value_rect
)def draw(self
, surface
):self
.drawSunValue
()surface
.blit
(self
.image
, self
.rect
)for card
in self
.card_list
:card
.draw
(surface
)
鼠標(biāo)圖片切換
代碼在source\state\level.py中,setupMouseImage 函數(shù)實現(xiàn)鼠標(biāo)圖片切換為選中的植物
- self.mouse_image :根據(jù) plant_name 獲取選中的植物圖片
- self.mouse_rect:選中植物圖片的位置,在drawMouseShow函數(shù)中,需要將植物圖片的位置設(shè)置成當(dāng)前鼠標(biāo)的位置
- pg.mouse.set_visible(False):隱藏默認(rèn)的鼠標(biāo)顯示,這樣效果就是鼠標(biāo)圖片切換為選中的植物了。
def setupMouseImage(self
, plant_name
, plant_cost
):frame_list
= tool
.GFX
[plant_name
]if plant_name
in tool
.PLANT_RECT
:data
= tool
.PLANT_RECT
[plant_name
]x
, y
, width
, height
= data
['x'], data
['y'], data
['width'], data
['height']else:x
, y
= 0, 0rect
= frame_list
[0].get_rect
()width
, height
= rect
.w
, rect
.h
if plant_name
== c
.POTATOMINE
or plant_name
== c
.SQUASH
:color
= c
.WHITE
else:color
= c
.BLACKself
.mouse_image
= tool
.get_image
(frame_list
[0], x
, y
, width
, height
, color
, 1)self
.mouse_rect
= self
.mouse_image
.get_rect
()pg
.mouse
.set_visible
(False)self
.drag_plant
= Trueself
.plant_name
= plant_nameself
.plant_cost
= plant_cost
def drawMouseShow(self
, surface
):if self
.hint_plant
:surface
.blit
(self
.hint_image
, self
.hint_rect
)x
, y
= pg
.mouse
.get_pos
()self
.mouse_rect
.centerx
= xself
.mouse_rect
.centery
= ysurface
.blit
(self
.mouse_image
, self
.mouse_rect
)
提示種在哪個方格中
先看下map類,代碼在source\component\map.py 中
- self.map:二維list,用來保存每個方格的狀態(tài)。每個entry初始化為 0, 表示可以種植物,值為1時表示這個方格已經(jīng)種了植物。
- getMapIndex 函數(shù):傳入?yún)?shù)是游戲中的坐標(biāo)位置(比如當(dāng)前鼠標(biāo)的位置),返回該位置在地圖的哪個方格中。
- getMapGridPos 函數(shù):傳入一個方格的index,返回在該方格中種植物的坐標(biāo)位置。
- showPlant 函數(shù):根據(jù)傳入的坐標(biāo)位置,判斷該位置所在的方格是否能種植物,如果能種,就返回返回在該方格中種植物的坐標(biāo)位置。
MAP_EMPTY
= 0
MAP_EXIST
= 1class Map():def __init__(self
, width
, height
):self
.width
= widthself
.height
= heightself
.map = [[0 for x
in range(self
.width
)] for y
in range(self
.height
)]def isValid(self
, map_x
, map_y
):if (map_x
< 0 or map_x
>= self
.width
ormap_y
< 0 or map_y
>= self
.height
):return Falsereturn Truedef isMovable(self
, map_x
, map_y
):return (self
.map[map_y
][map_x
] == c
.MAP_EMPTY
)def getMapIndex(self
, x
, y
):x
-= c
.MAP_OFFSET_Xy
-= c
.MAP_OFFSET_Y
return (x
// c
.GRID_X_SIZE
, y
// c
.GRID_Y_SIZE
)def getMapGridPos(self
, map_x
, map_y
):return (map_x
* c
.GRID_X_SIZE
+ c
.GRID_X_SIZE
//2 + c
.MAP_OFFSET_X
,map_y
* c
.GRID_Y_SIZE
+ c
.GRID_Y_SIZE
//5 * 3 + c
.MAP_OFFSET_Y
)def setMapGridType(self
, map_x
, map_y
, type):self
.map[map_y
][map_x
] = typedef getRandomMapIndex(self
):map_x
= random
.randint
(0, self
.width
-1)map_y
= random
.randint
(0, self
.height
-1)return (map_x
, map_y
)def showPlant(self
, x
, y
):pos
= Nonemap_x
, map_y
= self
.getMapIndex
(x
, y
)if self
.isValid
(map_x
, map_y
) and self
.isMovable
(map_x
, map_y
):pos
= self
.getMapGridPos
(map_x
, map_y
)return pos
代碼在source\state\level.py中,
- canSeedPlant 函數(shù):判斷當(dāng)前鼠標(biāo)位置能否種植物
- setupHintImage 函數(shù):如果當(dāng)前鼠標(biāo)位置能種植物,且有選擇了一個植物卡片,則設(shè)置self.hint_image 顯示當(dāng)前會在哪一個方格中種植物,self.hint_rect 是植物種的坐標(biāo)位置。
def canSeedPlant(self
):x
, y
= pg
.mouse
.get_pos
()return self
.map.showPlant
(x
, y
)def setupHintImage(self
):pos
= self
.canSeedPlant
()if pos
and self
.mouse_image
:if (self
.hint_image
and pos
[0] == self
.hint_rect
.x
andpos
[1] == self
.hint_rect
.y
):returnwidth
, height
= self
.mouse_rect
.w
, self
.mouse_rect
.himage
= pg
.Surface
([width
, height
])image
.blit
(self
.mouse_image
, (0, 0), (0, 0, width
, height
))image
.set_colorkey
(c
.BLACK
)image
.set_alpha
(128)self
.hint_image
= imageself
.hint_rect
= image
.get_rect
()self
.hint_rect
.centerx
= pos
[0]self
.hint_rect
.bottom
= pos
[1]self
.hint_plant
= Trueelse:self
.hint_plant
= False
編譯環(huán)境
python3.7 + pygame1.9
總結(jié)
以上是生活随笔為你收集整理的Python 植物大战僵尸代码实现(2):植物卡片选择和种植的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。