基于Python实现经典植物大战僵尸游戏

作者:梦执.py 时间:2021-01-28 11:17:20 

游戏截图

基于Python实现经典植物大战僵尸游戏

基于Python实现经典植物大战僵尸游戏

基于Python实现经典植物大战僵尸游戏

动态演示

基于Python实现经典植物大战僵尸游戏

源码分享

state/tool.py

import os
import json
from abc import abstractmethod
import pygame as pg
from . import constants as c

class State():
   def __init__(self):
       self.start_time = 0.0
       self.current_time = 0.0
       self.done = False
       self.next = None
       self.persist = {}

@abstractmethod
   def startup(self, current_time, persist):
       '''abstract method'''

def cleanup(self):
       self.done = False
       return self.persist

@abstractmethod
   def update(self, surface, keys, current_time):
       '''abstract method'''

class Control():
   def __init__(self):
       self.screen = pg.display.get_surface()
       self.done = False
       self.clock = pg.time.Clock()
       self.fps = 60
       self.keys = pg.key.get_pressed()
       self.mouse_pos = None
       self.mouse_click = [False, False]  # value:[left mouse click, right mouse click]
       self.current_time = 0.0
       self.state_dict = {}
       self.state_name = None
       self.state = None
       self.game_info = {c.CURRENT_TIME:0.0,
                         c.LEVEL_NUM:c.START_LEVEL_NUM}

def setup_states(self, state_dict, start_state):
       self.state_dict = state_dict
       self.state_name = start_state
       self.state = self.state_dict[self.state_name]
       self.state.startup(self.current_time, self.game_info)

def update(self):
       self.current_time = pg.time.get_ticks()
       if self.state.done:
           self.flip_state()
       self.state.update(self.screen, self.current_time, self.mouse_pos, self.mouse_click)
       self.mouse_pos = None
       self.mouse_click[0] = False
       self.mouse_click[1] = False

def flip_state(self):
       previous, self.state_name = self.state_name, self.state.next
       persist = self.state.cleanup()
       self.state = self.state_dict[self.state_name]
       self.state.startup(self.current_time, persist)

def event_loop(self):
       for event in pg.event.get():
           if event.type == pg.QUIT:
               self.done = True
           elif event.type == pg.KEYDOWN:
               self.keys = pg.key.get_pressed()
           elif event.type == pg.KEYUP:
               self.keys = pg.key.get_pressed()
           elif event.type == pg.MOUSEBUTTONDOWN:
               self.mouse_pos = pg.mouse.get_pos()
               self.mouse_click[0], _, self.mouse_click[1] = pg.mouse.get_pressed()
               print('pos:', self.mouse_pos, ' mouse:', self.mouse_click)

def main(self):
       while not self.done:
           self.event_loop()
           self.update()
           pg.display.update()
           self.clock.tick(self.fps)
       print('game over')

def get_image(sheet, x, y, width, height, colorkey=c.BLACK, scale=1):
       image = pg.Surface([width, height])
       rect = image.get_rect()

image.blit(sheet, (0, 0), (x, y, width, height))
       image.set_colorkey(colorkey)
       image = pg.transform.scale(image,
                                  (int(rect.width*scale),
                                   int(rect.height*scale)))
       return image

def load_image_frames(directory, image_name, colorkey, accept):
   frame_list = []
   tmp = {}
   # image_name is "Peashooter", pic name is 'Peashooter_1', get the index 1
   index_start = len(image_name) + 1
   frame_num = 0;
   for pic in os.listdir(directory):
       name, ext = os.path.splitext(pic)
       if ext.lower() in accept:
           index = int(name[index_start:])
           img = pg.image.load(os.path.join(directory, pic))
           if img.get_alpha():
               img = img.convert_alpha()
           else:
               img = img.convert()
               img.set_colorkey(colorkey)
           tmp[index]= img
           frame_num += 1

for i in range(frame_num):
       frame_list.append(tmp[i])
   return frame_list

def load_all_gfx(directory, colorkey=c.WHITE, accept=('.png', '.jpg', '.bmp', '.gif')):
   graphics = {}
   for name1 in os.listdir(directory):
       # subfolders under the folder resources\graphics
       dir1 = os.path.join(directory, name1)
       if os.path.isdir(dir1):
           for name2 in os.listdir(dir1):
               dir2 = os.path.join(dir1, name2)
               if os.path.isdir(dir2):
               # e.g. subfolders under the folder resources\graphics\Zombies
                   for name3 in os.listdir(dir2):
                       dir3 = os.path.join(dir2, name3)
                       # e.g. subfolders or pics under the folder resources\graphics\Zombies\ConeheadZombie
                       if os.path.isdir(dir3):
                           # e.g. it's the folder resources\graphics\Zombies\ConeheadZombie\ConeheadZombieAttack
                           image_name, _ = os.path.splitext(name3)
                           graphics[image_name] = load_image_frames(dir3, image_name, colorkey, accept)
                       else:
                           # e.g. pics under the folder resources\graphics\Plants\Peashooter
                           image_name, _ = os.path.splitext(name2)
                           graphics[image_name] = load_image_frames(dir2, image_name, colorkey, accept)
                           break
               else:
               # e.g. pics under the folder resources\graphics\Screen
                   name, ext = os.path.splitext(name2)
                   if ext.lower() in accept:
                       img = pg.image.load(dir2)
                       if img.get_alpha():
                           img = img.convert_alpha()
                       else:
                           img = img.convert()
                           img.set_colorkey(colorkey)
                       graphics[name] = img
   return graphics

def loadZombieImageRect():
   file_path = os.path.join('source', 'data', 'entity', 'zombie.json')
   f = open(file_path)
   data = json.load(f)
   f.close()
   return data[c.ZOMBIE_IMAGE_RECT]

def loadPlantImageRect():
   file_path = os.path.join('source', 'data', 'entity', 'plant.json')
   f = open(file_path)
   data = json.load(f)
   f.close()
   return data[c.PLANT_IMAGE_RECT]

pg.init()
pg.display.set_caption(c.ORIGINAL_CAPTION)
SCREEN = pg.display.set_mode(c.SCREEN_SIZE)

GFX = load_all_gfx(os.path.join("resources","graphics"))
ZOMBIE_RECT = loadZombieImageRect()
PLANT_RECT = loadPlantImageRect()

state/constants.py



START_LEVEL_NUM = 1

ORIGINAL_CAPTION = 'Plant VS Zombies Game'

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
SCREEN_SIZE = (SCREEN_WIDTH, SCREEN_HEIGHT)

GRID_X_LEN = 9
GRID_Y_LEN = 5
GRID_X_SIZE = 80
GRID_Y_SIZE = 100

WHITE        = (255, 255, 255)
NAVYBLUE     = ( 60,  60, 100)
SKY_BLUE     = ( 39, 145, 251)
BLACK        = (  0,   0,   0)
LIGHTYELLOW  = (234, 233, 171)
RED          = (255,   0,   0)
PURPLE       = (255,   0, 255)
GOLD         = (255, 215,   0)
GREEN        = (  0, 255,   0)

SIZE_MULTIPLIER = 1.3

#GAME INFO DICTIONARY KEYS
CURRENT_TIME = 'current time'
LEVEL_NUM = 'level num'

#STATES FOR ENTIRE GAME
MAIN_MENU = 'main menu'
LOAD_SCREEN = 'load screen'
GAME_LOSE = 'game los'
GAME_VICTORY = 'game victory'
LEVEL = 'level'

MAIN_MENU_IMAGE = 'MainMenu'
OPTION_ADVENTURE = 'Adventure'
GAME_LOOSE_IMAGE = 'GameLoose'
GAME_VICTORY_IMAGE = 'GameVictory'

#MAP COMPONENTS
BACKGROUND_NAME = 'Background'
BACKGROUND_TYPE = 'background_type'
INIT_SUN_NAME = 'init_sun_value'
ZOMBIE_LIST = 'zombie_list'

MAP_EMPTY = 0
MAP_EXIST = 1

BACKGROUND_OFFSET_X = 220
MAP_OFFSET_X = 35
MAP_OFFSET_Y = 100

#MENUBAR
CHOOSEBAR_TYPE = 'choosebar_type'
CHOOSEBAR_STATIC = 0
CHOOSEBAR_MOVE = 1
CHOSSEBAR_BOWLING = 2
MENUBAR_BACKGROUND = 'ChooserBackground'
MOVEBAR_BACKGROUND = 'MoveBackground'
PANEL_BACKGROUND = 'PanelBackground'
START_BUTTON = 'StartButton'
CARD_POOL = 'card_pool'

MOVEBAR_CARD_FRESH_TIME = 6000
CARD_MOVE_TIME = 60

#PLANT INFO
PLANT_IMAGE_RECT = 'plant_image_rect'
CAR = 'car'
SUN = 'Sun'
SUNFLOWER = 'SunFlower'
PEASHOOTER = 'Peashooter'
SNOWPEASHOOTER = 'SnowPea'
WALLNUT = 'WallNut'
CHERRYBOMB = 'CherryBomb'
THREEPEASHOOTER = 'Threepeater'
REPEATERPEA = 'RepeaterPea'
CHOMPER = 'Chomper'
CHERRY_BOOM_IMAGE = 'Boom'
PUFFSHROOM = 'PuffShroom'
POT * INE = 'PotatoMine'
SQUASH = 'Squash'
SPIKEWEED = 'Spikeweed'
JALAPENO = 'Jalapeno'
SCAREDYSHROOM = 'ScaredyShroom'
SUNSHROOM = 'SunShroom'
ICESHROOM = 'IceShroom'
HYPNOSHROOM = 'HypnoShroom'
WALLNUTBOWLING = 'WallNutBowling'
REDWALLNUTBOWLING = 'RedWallNutBowling'

PLANT_HEALTH = 5
WALLNUT_HEALTH = 30
WALLNUT_CRACKED1_HEALTH = 20
WALLNUT_CRACKED2_HEALTH = 10
WALLNUT_BOWLING_DAMAGE = 10

PRODUCE_SUN_INTERVAL = 7000
FLOWER_SUN_INTERVAL = 22000
SUN_LIVE_TIME = 7000
SUN_VALUE = 25

ICE_SLOW_TIME = 2000

FREEZE_TIME = 7500
ICETRAP = 'IceTrap'

#PLANT CARD INFO
CARD_SUNFLOWER = 'card_sunflower'
CARD_PEASHOOTER = 'card_peashooter'
CARD_SNOWPEASHOOTER = 'card_snowpea'
CARD_WALLNUT = 'card_wallnut'
CARD_CHERRYBOMB = 'card_cherrybomb'
CARD_THREEPEASHOOTER = 'card_threepeashooter'
CARD_REPEATERPEA = 'card_repeaterpea'
CARD_CHOMPER = 'card_chomper'
CARD_PUFFSHROOM = 'card_puffshroom'
CARD_POT * INE = 'card_potatomine'
CARD_SQUASH = 'card_squash'
CARD_SPIKEWEED = 'card_spikeweed'
CARD_JALAPENO = 'card_jalapeno'
CARD_SCAREDYSHROOM = 'card_scaredyshroom'
CARD_SUNSHROOM = 'card_sunshroom'
CARD_ICESHROOM = 'card_iceshroom'
CARD_HYPNOSHROOM = 'card_hypnoshroom'
CARD_REDWALLNUT = 'card_redwallnut'

#BULLET INFO
BULLET_PEA = 'PeaNormal'
BULLET_PEA_ICE = 'PeaIce'
BULLET_MUSHROOM = 'BulletMushRoom'
BULLET_DAMAGE_NORMAL = 1

#ZOMBIE INFO
ZOMBIE_IMAGE_RECT = 'zombie_image_rect'
ZOMBIE_HEAD = 'ZombieHead'
NORMAL_ZOMBIE = 'Zombie'
CONEHEAD_ZOMBIE = 'ConeheadZombie'
BUCKETHEAD_ZOMBIE = 'BucketheadZombie'
FLAG_ZOMBIE = 'FlagZombie'
NEWSPAPER_ZOMBIE = 'NewspaperZombie'
BOOMDIE = 'BoomDie'

LOSTHEAD_HEALTH = 5
NORMAL_HEALTH = 10
FLAG_HEALTH = 15
CONEHEAD_HEALTH = 20
BUCKETHEAD_HEALTH = 30
NEWSPAPER_HEALTH = 15

ATTACK_INTERVAL = 1000
ZOMBIE_WALK_INTERVAL = 70

ZOMBIE_START_X = SCREEN_WIDTH + 50

#STATE
IDLE = 'idle'
FLY = 'fly'
EXPLODE = 'explode'
ATTACK = 'attack'
ATTACKED = 'attacked'
DIGEST = 'digest'
WALK = 'walk'
DIE = 'die'
CRY = 'cry'
FREEZE = 'freeze'
SLEEP = 'sleep'

#LEVEL STATE
CHOOSE = 'choose'
PLAY = 'play'

#BACKGROUND
BACKGROUND_DAY = 0
BACKGROUND_NIGHT = 1

state/main.py

from . import tool
from . import constants as c
from .state import mainmenu, screen, level

def main():
   game = tool.Control()
   state_dict = {c.MAIN_MENU: mainmenu.Menu(),
                 c.GAME_VICTORY: screen.GameVictoryScreen(),
                 c.GAME_LOSE: screen.GameLoseScreen(),
                 c.LEVEL: level.Level()}
   game.setup_states(state_dict, c.MAIN_MENU)
   game.main()

主执行文件main.py

import pygame as pg
from source.main import main

if __name__=='__main__':
   main()
   pg.quit()

来源:https://blog.csdn.net/m0_70127749/article/details/124697185

标签:Python,植物大战僵尸,游戏
0
投稿

猜你喜欢

  • 一篇文章让你搞清楚JavaScript事件循环

    2024-04-19 09:53:02
  • 如何使用Goland IDE go mod 方式构建项目

    2024-02-23 00:36:40
  • mysql变量用法实例分析【系统变量、用户变量】

    2024-01-20 08:47:20
  • 在django中查询获取数据,get, filter,all(),values()操作

    2023-09-04 16:10:27
  • MySQL过滤重复数据的两种方法示例

    2024-01-16 12:54:27
  • 用python制作游戏外 挂

    2023-08-03 15:55:43
  • ASP实例:幻灯片新闻代码

    2008-11-21 17:40:00
  • python turtle 绘制太极图的实例

    2022-12-31 13:15:12
  • Python中的十大图像处理工具(小结)

    2021-02-04 09:17:51
  • 通过缓存+SQL修改优雅地优化慢查询

    2024-01-21 12:01:16
  • Python实现的ini文件操作类分享

    2022-01-01 12:46:24
  • 合并网页中的多个script引用实现思路及代码

    2023-06-29 09:02:19
  • 基于Python实现通过微信搜索功能查看谁把你删除了

    2022-07-10 00:19:37
  • python怎么判断素数

    2021-09-30 11:10:33
  • 微软Silverlight技术魅力初体验

    2008-11-05 11:16:00
  • js中创建对象的几种方式

    2024-04-10 10:44:41
  • Python 爬虫学习笔记之多线程爬虫

    2022-10-03 15:10:37
  • Python要如何实现列表排序的几种方法

    2022-02-01 16:23:07
  • 详解Laravel模型事件和模型事件在Trait中的使用

    2023-06-17 17:19:28
  • js multiple全选与取消全选实现代码

    2024-04-28 10:19:36
  • asp之家 网络编程 m.aspxhome.com