diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000..26d33521
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/PythonPlantsVsZombies.iml b/.idea/PythonPlantsVsZombies.iml
new file mode 100644
index 00000000..d0876a78
--- /dev/null
+++ b/.idea/PythonPlantsVsZombies.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 00000000..105ce2da
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 00000000..2a2c1b9b
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 00000000..35c0ec56
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..35eb1ddf
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/__pycache__/__init__.cpython-312.pyc b/source/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 00000000..73ec3c53
Binary files /dev/null and b/source/__pycache__/__init__.cpython-312.pyc differ
diff --git a/source/__pycache__/constants.cpython-312.pyc b/source/__pycache__/constants.cpython-312.pyc
new file mode 100644
index 00000000..929394fe
Binary files /dev/null and b/source/__pycache__/constants.cpython-312.pyc differ
diff --git a/source/__pycache__/main.cpython-312.pyc b/source/__pycache__/main.cpython-312.pyc
new file mode 100644
index 00000000..b84b6c22
Binary files /dev/null and b/source/__pycache__/main.cpython-312.pyc differ
diff --git a/source/__pycache__/tool.cpython-312.pyc b/source/__pycache__/tool.cpython-312.pyc
new file mode 100644
index 00000000..69e5afe0
Binary files /dev/null and b/source/__pycache__/tool.cpython-312.pyc differ
diff --git a/source/component/__pycache__/__init__.cpython-312.pyc b/source/component/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 00000000..1f9988a3
Binary files /dev/null and b/source/component/__pycache__/__init__.cpython-312.pyc differ
diff --git a/source/component/__pycache__/map.cpython-312.pyc b/source/component/__pycache__/map.cpython-312.pyc
new file mode 100644
index 00000000..92b1ac8f
Binary files /dev/null and b/source/component/__pycache__/map.cpython-312.pyc differ
diff --git a/source/component/__pycache__/menubar.cpython-312.pyc b/source/component/__pycache__/menubar.cpython-312.pyc
new file mode 100644
index 00000000..51a487c5
Binary files /dev/null and b/source/component/__pycache__/menubar.cpython-312.pyc differ
diff --git a/source/component/__pycache__/plant.cpython-312.pyc b/source/component/__pycache__/plant.cpython-312.pyc
new file mode 100644
index 00000000..2fae0b33
Binary files /dev/null and b/source/component/__pycache__/plant.cpython-312.pyc differ
diff --git a/source/component/__pycache__/zombie.cpython-312.pyc b/source/component/__pycache__/zombie.cpython-312.pyc
new file mode 100644
index 00000000..7eaed3fa
Binary files /dev/null and b/source/component/__pycache__/zombie.cpython-312.pyc differ
diff --git a/source/component/plant.py b/source/component/plant.py
index 684065b1..bf261e24 100644
--- a/source/component/plant.py
+++ b/source/component/plant.py
@@ -54,6 +54,7 @@ def __init__(self, x, start_y, dest_y, name, damage, ice):
self.ice = ice
self.state = c.FLY
self.current_time = 0
+ self.knockback = 0 # 击退效果,默认为0表示没有击退
def loadFrames(self, frames, name):
frame_list = tool.GFX[name]
@@ -825,6 +826,64 @@ def loadImages(self, name, scale):
self.frames = self.idle_frames
+# Chinese Red Theme Plants
+class RedPeony(Plant):
+ """红牡丹 - 中国红主题植物,能够释放花粉攻击多个僵尸"""
+ def __init__(self, x, y, zombie_groups, map_y):
+ Plant.__init__(self, x, y, c.RED_PEONY, c.RED_PEONY_HEALTH, None)
+ self.shoot_timer = 0
+ self.map_y = map_y
+ self.zombie_groups = zombie_groups
+ self.attack_range = 3 # 攻击范围为3行
+
+ def attacking(self):
+ if (self.current_time - self.shoot_timer) > 3000:
+ # 释放花粉攻击范围内的所有僵尸
+ for i in range(-self.attack_range, self.attack_range + 1):
+ tmp_y = self.map_y + i
+ if tmp_y < 0 or tmp_y >= c.GRID_Y_LEN:
+ continue
+ for zombie in self.zombie_groups[tmp_y]:
+ if self.canAttack(zombie):
+ zombie.setDamage(c.RED_PEONY_POLLEN_DAMAGE)
+ self.shoot_timer = self.current_time
+
+ def canAttack(self, zombie):
+ if (self.state != c.SLEEP and zombie.state != c.DIE and
+ self.rect.x <= zombie.rect.right and
+ self.rect.right + c.GRID_X_SIZE * 2 >= zombie.rect.x):
+ return True
+ return False
+
+class FirecrackerPlant(Plant):
+ """鞭炮花 - 中国红主题植物,能够发射鞭炮攻击僵尸"""
+ def __init__(self, x, y, bullet_group):
+ Plant.__init__(self, x, y, c.FIRECRACKER_PLANT, c.FIRECRACKER_PLANT_HEALTH, bullet_group)
+ self.shoot_timer = 0
+ self.bullet_speed = 6
+
+ def attacking(self):
+ if (self.current_time - self.shoot_timer) > 2500:
+ # 发射鞭炮子弹
+ self.bullet_group.add(Bullet(self.rect.right, self.rect.y, self.rect.y,
+ c.BULLET_PEA, c.FIRECRACKER_DAMAGE, False))
+ self.shoot_timer = self.current_time
+
+class LionDancePea(Plant):
+ """舞狮豌豆 - 中国红主题植物,能够发射具有击退效果的豌豆"""
+ def __init__(self, x, y, bullet_group):
+ Plant.__init__(self, x, y, c.LION_DANCE_PEA, c.LION_DANCE_PEA_HEALTH, bullet_group)
+ self.shoot_timer = 0
+
+ def attacking(self):
+ if (self.current_time - self.shoot_timer) > 3000:
+ # 发射具有击退效果的豌豆
+ bullet = Bullet(self.rect.right, self.rect.y, self.rect.y,
+ c.BULLET_PEA, c.LION_DANCE_PEA_DAMAGE, False)
+ bullet.knockback = c.LION_DANCE_PEA_KNOCKBACK
+ self.bullet_group.add(bullet)
+ self.shoot_timer = self.current_time
+
class WallNutBowling(Plant):
def __init__(self, x, y, map_y, level):
Plant.__init__(self, x, y, c.WALLNUTBOWLING, 1, None)
diff --git a/source/component/zombie.py b/source/component/zombie.py
index 73780f13..133c004f 100644
--- a/source/component/zombie.py
+++ b/source/component/zombie.py
@@ -411,4 +411,148 @@ def loadImages(self):
color = c.WHITE
self.loadFrames(frame_list[i], name, tool.ZOMBIE_RECT[name]['x'], color)
- self.frames = self.helmet_walk_frames
\ No newline at end of file
+ self.frames = self.helmet_walk_frames
+
+# Chinese Red Theme Zombies
+class LanternZombie(Zombie):
+ """灯笼僵尸 - 中国红主题僵尸,手持灯笼照亮周围区域"""
+ def __init__(self, x, y, head_group):
+ Zombie.__init__(self, x, y, c.LANTERN_ZOMBIE, c.LANTERN_ZOMBIE_HEALTH, head_group)
+ self.speed = c.LANTERN_ZOMBIE_SPEED
+ self.lantern_light_range = c.LANTERN_LIGHT_RANGE
+ self.lantern_on = True
+
+ def loadImages(self):
+ self.walk_frames = []
+ self.attack_frames = []
+ self.losthead_walk_frames = []
+ self.losthead_attack_frames = []
+ self.die_frames = []
+ self.boomdie_frames = []
+
+ walk_name = self.name
+ attack_name = self.name + 'Attack'
+ losthead_walk_name = self.name + 'LostHead'
+ losthead_attack_name = self.name + 'LostHeadAttack'
+ die_name = c.NORMAL_ZOMBIE + 'Die'
+ boomdie_name = c.BOOMDIE
+
+ frame_list = [self.walk_frames, self.attack_frames, self.losthead_walk_frames,
+ self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
+ name_list = [walk_name, attack_name, losthead_walk_name,
+ losthead_attack_name, die_name, boomdie_name]
+
+ for i, name in enumerate(name_list):
+ self.loadFrames(frame_list[i], name, tool.ZOMBIE_RECT[name]['x'])
+
+ self.frames = self.walk_frames
+
+class LionDanceZombie(Zombie):
+ """舞狮僵尸 - 中国红主题僵尸,穿着舞狮服装,具有较高的生命值和攻击力"""
+ def __init__(self, x, y, head_group):
+ Zombie.__init__(self, x, y, c.LION_DANCE_ZOMBIE, c.LION_DANCE_ZOMBIE_HEALTH, head_group)
+ self.speed = c.LION_DANCE_ZOMBIE_SPEED
+ self.damage = c.LION_DANCE_ATTACK_DAMAGE
+ self.helmet = True
+
+ def loadImages(self):
+ self.helmet_walk_frames = []
+ self.helmet_attack_frames = []
+ self.walk_frames = []
+ self.attack_frames = []
+ self.losthead_walk_frames = []
+ self.losthead_attack_frames = []
+ self.die_frames = []
+ self.boomdie_frames = []
+
+ helmet_walk_name = self.name
+ helmet_attack_name = self.name + 'Attack'
+ walk_name = self.name + 'NoCostume'
+ attack_name = self.name + 'NoCostumeAttack'
+ losthead_walk_name = self.name + 'LostHead'
+ losthead_attack_name = self.name + 'LostHeadAttack'
+ die_name = self.name + 'Die'
+ boomdie_name = c.BOOMDIE
+
+ frame_list = [self.helmet_walk_frames, self.helmet_attack_frames,
+ self.walk_frames, self.attack_frames, self.losthead_walk_frames,
+ self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
+ name_list = [helmet_walk_name, helmet_attack_name,
+ walk_name, attack_name, losthead_walk_name,
+ losthead_attack_name, die_name, boomdie_name]
+
+ for i, name in enumerate(name_list):
+ self.loadFrames(frame_list[i], name, tool.ZOMBIE_RECT[name]['x'])
+
+ self.frames = self.helmet_walk_frames
+
+class ChineseNewYearZombie(Zombie):
+ """春节僵尸 - 中国红主题僵尸,穿着春节服装,死亡时掉落金币"""
+ def __init__(self, x, y, head_group, gold_group):
+ Zombie.__init__(self, x, y, c.CHINESE_NEW_YEAR_ZOMBIE, c.CHINESE_NEW_YEAR_ZOMBIE_HEALTH, head_group)
+ self.speed = c.CHINESE_NEW_YEAR_ZOMBIE_SPEED
+ self.gold_group = gold_group
+ self.gold_drop = c.CHINESE_NEW_YEAR_GOLD_DROP
+
+ def loadImages(self):
+ self.walk_frames = []
+ self.attack_frames = []
+ self.losthead_walk_frames = []
+ self.losthead_attack_frames = []
+ self.die_frames = []
+ self.boomdie_frames = []
+
+ walk_name = self.name
+ attack_name = self.name + 'Attack'
+ losthead_walk_name = self.name + 'LostHead'
+ losthead_attack_name = self.name + 'LostHeadAttack'
+ die_name = self.name + 'Die'
+ boomdie_name = c.BOOMDIE
+
+ frame_list = [self.walk_frames, self.attack_frames, self.losthead_walk_frames,
+ self.losthead_attack_frames, self.die_frames, self.boomdie_frames]
+ name_list = [walk_name, attack_name, losthead_walk_name,
+ losthead_attack_name, die_name, boomdie_name]
+
+ for i, name in enumerate(name_list):
+ self.loadFrames(frame_list[i], name, tool.ZOMBIE_RECT[name]['x'])
+
+ self.frames = self.walk_frames
+
+ def dying(self):
+ # 死亡时掉落金币
+ if not self.dead:
+ for i in range(self.gold_drop):
+ gold = Gold(self.rect.centerx, self.rect.y)
+ self.gold_group.add(gold)
+ self.dead = True
+ super().dying()
+
+class Gold(pg.sprite.Sprite):
+ """金币类 - 春节僵尸死亡时掉落"""
+ def __init__(self, x, y):
+ pg.sprite.Sprite.__init__(self)
+ self.image = tool.get_image(tool.GFX['Gold'], 0, 0, 30, 30, c.BLACK, 1)
+ self.rect = self.image.get_rect()
+ self.rect.centerx = x
+ self.rect.y = y
+ self.y_vel = -2 # 金币向上飘
+ self.gravity = 0.1 # 重力效果
+ self.live_time = 5000 # 金币存在时间
+ self.created_time = pg.time.get_ticks()
+
+ def update(self, game_info):
+ # 金币向上飘然后下落
+ self.y_vel += self.gravity
+ self.rect.y += self.y_vel
+
+ # 金币存在时间结束后消失
+ if pg.time.get_ticks() - self.created_time > self.live_time:
+ self.kill()
+
+ def checkCollision(self, x, y):
+ if(x >= self.rect.x and x <= self.rect.right and
+ y >= self.rect.y and y <= self.rect.bottom):
+ self.kill()
+ return True
+ return False
\ No newline at end of file
diff --git a/source/constants.py b/source/constants.py
index 0c4e2b6e..b4950f25 100644
--- a/source/constants.py
+++ b/source/constants.py
@@ -93,6 +93,10 @@
HYPNOSHROOM = 'HypnoShroom'
WALLNUTBOWLING = 'WallNutBowling'
REDWALLNUTBOWLING = 'RedWallNutBowling'
+# Chinese Red Theme Plants
+RED_PEONY = 'RedPeony' # 红牡丹
+FIRECRACKER_PLANT = 'FirecrackerPlant' # 鞭炮花
+LION_DANCE_PEA = 'LionDancePea' # 舞狮豌豆
PLANT_HEALTH = 5
WALLNUT_HEALTH = 30
@@ -100,6 +104,15 @@
WALLNUT_CRACKED2_HEALTH = 10
WALLNUT_BOWLING_DAMAGE = 10
+# Chinese Red Theme Plant Properties
+RED_PEONY_HEALTH = 15 # 红牡丹生命值
+RED_PEONY_POLLEN_DAMAGE = 3 # 红牡丹花粉伤害
+FIRECRACKER_PLANT_HEALTH = 10 # 鞭炮花生命值
+FIRECRACKER_DAMAGE = 2 # 鞭炮伤害
+LION_DANCE_PEA_HEALTH = 5 # 舞狮豌豆生命值
+LION_DANCE_PEA_DAMAGE = 4 # 舞狮豌豆伤害
+LION_DANCE_PEA_KNOCKBACK = 50 # 舞狮豌豆击退效果
+
PRODUCE_SUN_INTERVAL = 7000
FLOWER_SUN_INTERVAL = 22000
SUN_LIVE_TIME = 7000
@@ -129,6 +142,10 @@
CARD_ICESHROOM = 'card_iceshroom'
CARD_HYPNOSHROOM = 'card_hypnoshroom'
CARD_REDWALLNUT = 'card_redwallnut'
+# Chinese Red Theme Plant Cards
+CARD_RED_PEONY = 'card_redpeony'
+CARD_FIRECRACKER_PLANT = 'card_firecrackerplant'
+CARD_LION_DANCE_PEA = 'card_liondancepea'
#BULLET INFO
BULLET_PEA = 'PeaNormal'
@@ -145,6 +162,10 @@
FLAG_ZOMBIE = 'FlagZombie'
NEWSPAPER_ZOMBIE = 'NewspaperZombie'
BOOMDIE = 'BoomDie'
+# Chinese Red Theme Zombies
+LANTERN_ZOMBIE = 'LanternZombie' # 灯笼僵尸
+LION_DANCE_ZOMBIE = 'LionDanceZombie' # 舞狮僵尸
+CHINESE_NEW_YEAR_ZOMBIE = 'ChineseNewYearZombie' # 春节僵尸
LOSTHEAD_HEALTH = 5
NORMAL_HEALTH = 10
@@ -153,6 +174,17 @@
BUCKETHEAD_HEALTH = 30
NEWSPAPER_HEALTH = 15
+# Chinese Red Theme Zombie Properties
+LANTERN_ZOMBIE_HEALTH = 15 # 灯笼僵尸生命值
+LANTERN_ZOMBIE_SPEED = 1.2 # 灯笼僵尸移动速度
+LANTERN_LIGHT_RANGE = 3 # 灯笼照亮范围
+LION_DANCE_ZOMBIE_HEALTH = 30 # 舞狮僵尸生命值
+LION_DANCE_ZOMBIE_SPEED = 0.8 # 舞狮僵尸移动速度
+LION_DANCE_ATTACK_DAMAGE = 2 # 舞狮僵尸攻击伤害
+CHINESE_NEW_YEAR_ZOMBIE_HEALTH = 25 # 春节僵尸生命值
+CHINESE_NEW_YEAR_ZOMBIE_SPEED = 1.0 # 春节僵尸移动速度
+CHINESE_NEW_YEAR_GOLD_DROP = 5 # 春节僵尸掉落金币数量
+
ATTACK_INTERVAL = 1000
ZOMBIE_WALK_INTERVAL = 70
diff --git a/source/state/__pycache__/__init__.cpython-312.pyc b/source/state/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 00000000..58f7eae1
Binary files /dev/null and b/source/state/__pycache__/__init__.cpython-312.pyc differ
diff --git a/source/state/__pycache__/level.cpython-312.pyc b/source/state/__pycache__/level.cpython-312.pyc
new file mode 100644
index 00000000..a25d4b94
Binary files /dev/null and b/source/state/__pycache__/level.cpython-312.pyc differ
diff --git a/source/state/__pycache__/mainmenu.cpython-312.pyc b/source/state/__pycache__/mainmenu.cpython-312.pyc
new file mode 100644
index 00000000..a64d3d7a
Binary files /dev/null and b/source/state/__pycache__/mainmenu.cpython-312.pyc differ
diff --git a/source/state/__pycache__/screen.cpython-312.pyc b/source/state/__pycache__/screen.cpython-312.pyc
new file mode 100644
index 00000000..ce3bd80d
Binary files /dev/null and b/source/state/__pycache__/screen.cpython-312.pyc differ
diff --git a/source/state/level.py b/source/state/level.py
index 133cc28a..d7dc76f8 100644
--- a/source/state/level.py
+++ b/source/state/level.py
@@ -42,6 +42,7 @@ def setupBackground(self):
def setupGroups(self):
self.sun_group = pg.sprite.Group()
self.head_group = pg.sprite.Group()
+ self.gold_group = pg.sprite.Group() # 金币组
self.plant_groups = []
self.zombie_groups = []
@@ -148,6 +149,7 @@ def play(self, mouse_pos, mouse_click):
self.head_group.update(self.game_info)
self.sun_group.update(self.game_info)
+ self.gold_group.update(self.game_info)
if not self.drag_plant and mouse_pos and mouse_click[0]:
result = self.menubar.checkCardClick(mouse_pos)
@@ -174,6 +176,11 @@ def play(self, mouse_pos, mouse_click):
for sun in self.sun_group:
if sun.checkCollision(mouse_pos[0], mouse_pos[1]):
self.menubar.increaseSunValue(sun.sun_value)
+ # 收集金币
+ for gold in self.gold_group:
+ if gold.checkCollision(mouse_pos[0], mouse_pos[1]):
+ self.menubar.increaseGoldValue(gold.gold_value)
+ gold.kill()
for car in self.cars:
car.update(self.game_info)
@@ -198,6 +205,13 @@ def createZombie(self, name, map_y):
self.zombie_groups[map_y].add(zombie.FlagZombie(c.ZOMBIE_START_X, y, self.head_group))
elif name == c.NEWSPAPER_ZOMBIE:
self.zombie_groups[map_y].add(zombie.NewspaperZombie(c.ZOMBIE_START_X, y, self.head_group))
+ # Chinese Red Theme Zombies
+ elif name == c.LANTERN_ZOMBIE:
+ self.zombie_groups[map_y].add(zombie.LanternZombie(c.ZOMBIE_START_X, y, self.head_group))
+ elif name == c.LION_DANCE_ZOMBIE:
+ self.zombie_groups[map_y].add(zombie.LionDanceZombie(c.ZOMBIE_START_X, y, self.head_group))
+ elif name == c.CHINESE_NEW_YEAR_ZOMBIE:
+ self.zombie_groups[map_y].add(zombie.ChineseNewYearZombie(c.ZOMBIE_START_X, y, self.head_group, self.gold_group))
def canSeedPlant(self):
x, y = pg.mouse.get_pos()
@@ -250,6 +264,13 @@ def addPlant(self):
new_plant = plant.WallNutBowling(x, y, map_y, self)
elif self.plant_name == c.REDWALLNUTBOWLING:
new_plant = plant.RedWallNutBowling(x, y)
+ # Chinese Red Theme Plants
+ elif self.plant_name == c.RED_PEONY:
+ new_plant = plant.RedPeony(x, y, self.zombie_groups, map_y)
+ elif self.plant_name == c.FIRECRACKER_PLANT:
+ new_plant = plant.FirecrackerPlant(x, y, self.bullet_groups[map_y])
+ elif self.plant_name == c.LION_DANCE_PEA:
+ new_plant = plant.LionDancePea(x, y, self.bullet_groups[map_y])
if new_plant.can_sleep and self.background_type == c.BACKGROUND_DAY:
new_plant.setSleep()
@@ -544,6 +565,7 @@ def draw(self, surface):
car.draw(surface)
self.head_group.draw(surface)
self.sun_group.draw(surface)
+ self.gold_group.draw(surface)
if self.drag_plant:
self.drawMouseShow(surface)
\ No newline at end of file