diff --git a/source/1.txt b/source/1.txt new file mode 100644 index 00000000..4f69b6a4 --- /dev/null +++ b/source/1.txt @@ -0,0 +1,980 @@ + + + + +我需要了解当前的关卡系统实现,以便添加黑夜关卡类型。让我搜索关卡相关的代码。 + + +toolName: search_codebase + +status: success + +query: level state game mode implementation + +我需要查看常量文件,了解当前的背景类型和游戏模式定义,以便添加黑夜关卡相关的常量。 + + +toolName: search_codebase + +status: success + +query: BACKGROUND_DAY BACKGROUND_TYPE game mode constants + +我需要查看植物类的实现,了解阳光蘑菇、喷气蘑菇和墓碑吞噬者的当前状态。 + + +toolName: search_codebase + +status: success + +query: SunShroom PuffShroom GraveBuster implementation + +我需要查看阳光蘑菇的完整实现代码,以了解其当前的行为和需要修改的地方。 + + +toolName: view_files + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\component\plant.py + +我需要查看地图组件的实现,以了解如何添加墓碑机制。 + + +toolName: view_files + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\component\map.py + +现在我已经了解了游戏的基本结构,让我开始实现黑夜关卡和新植物。首先,我需要修改level.py文件来添加黑夜环境的支持。 + + +toolName: edit_file_update + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\state\level.py + +changes: + +newStr: def setupBackground(self): + img_index = self.map_data[c.BACKGROUND_TYPE] + self.background_type = img_index + self.background = tool.GFX[c.BACKGROUND_NAME][img_index] + self.bg_rect = self.background.get_rect() + + self.level = pg.Surface((self.bg_rect.w, self.bg_rect.h)).convert() + self.viewport = tool.SCREEN.get_rect(bottom=self.bg_rect.bottom) + self.viewport.x += c.BACKGROUND_OFFSET_X + + # Add night blue filter for night levels + if self.background_type == c.BACKGROUND_NIGHT: + self.night_filter = pg.Surface((self.bg_rect.w, self.bg_rect.h)) + self.night_filter.fill((0, 0, 100)) # Dark blue color + self.night_filter.set_alpha(80) # Transparency level + +oldStr: def setupBackground(self): + img_index = self.map_data[c.BACKGROUND_TYPE] + self.background_type = img_index + self.background = tool.GFX[c.BACKGROUND_NAME][img_index] + self.bg_rect = self.background.get_rect() + + self.level = pg.Surface((self.bg_rect.w, self.bg_rect.h)).convert() + self.viewport = tool.SCREEN.get_rect(bottom=self.bg_rect.bottom) + self.viewport.x += c.BACKGROUND_OFFSET_X + + +现在我需要修改draw方法来应用黑夜滤镜。 + + +toolName: edit_file_update + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\state\level.py + +changes: + +newStr: def draw(self, surface): + self.level.blit(self.background, self.viewport, self.viewport) + + # Apply night filter for night levels + if self.background_type == c.BACKGROUND_NIGHT: + self.level.blit(self.night_filter, (0, 0)) + + surface.blit(self.level, (0,0), self.viewport) + +oldStr: def draw(self, surface): + self.level.blit(self.background, self.viewport, self.viewport) + surface.blit(self.level, (0,0), self.viewport) + + +现在我需要修改阳光蘑菇的实现,使其符合需求:小蘑菇每15秒产生15阳光,60秒后长大,之后每15秒产生25阳光。 + + +toolName: edit_file_update + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\component\plant.py + +changes: + +newStr: class SunShroom(Plant): + def __init__(self, x, y, sun_group): + Plant.__init__(self, x, y, c.SUNSHROOM, c.PLANT_HEALTH, None) + self.can_sleep = True + self.animate_interval = 200 + self.sun_timer = 0 + self.sun_group = sun_group + self.is_big = False + self.change_timer = 0 + + def loadImages(self, name, scale): + self.idle_frames = [] + self.big_frames = [] + self.sleep_frames = [] + + idle_name = name + big_name = name + 'Big' + sleep_name = name + 'Sleep' + + frame_list = [self.idle_frames, self.big_frames, self.sleep_frames] + name_list = [idle_name, big_name, sleep_name] + + for i, name in enumerate(name_list): + self.loadFrames(frame_list[i], name, 1, c.WHITE) + + self.frames = self.idle_frames + + def idling(self): + if not self.is_big: + if self.change_timer == 0: + self.change_timer = self.current_time + elif (self.current_time - self.change_timer) > 60000: # 60 seconds to grow + self.changeFrames(self.big_frames) + self.is_big = True + + # Produce sun every 15 seconds + if self.sun_timer == 0: + self.sun_timer = self.current_time + elif (self.current_time - self.sun_timer) > 15000: + # Small sunshroom produces 15 sun, big one produces 25 + sun_value = 25 if self.is_big else 15 + # Create sun with appropriate value + sun = Sun(self.rect.centerx, self.rect.bottom, self.rect.right, + self.rect.bottom + self.rect.h // 2, self.is_big) + sun.sun_value = sun_value + self.sun_group.add(sun) + self.sun_timer = self.current_time + +oldStr: class SunShroom(Plant): + def __init__(self, x, y, sun_group): + Plant.__init__(self, x, y, c.SUNSHROOM, c.PLANT_HEALTH, None) + self.can_sleep = True + self.animate_interval = 200 + self.sun_timer = 0 + self.sun_group = sun_group + self.is_big = False + self.change_timer = 0 + + def loadImages(self, name, scale): + self.idle_frames = [] + self.big_frames = [] + self.sleep_frames = [] + + idle_name = name + big_name = name + 'Big' + sleep_name = name + 'Sleep' + + frame_list = [self.idle_frames, self.big_frames, self.sleep_frames] + name_list = [idle_name, big_name, sleep_name] + + for i, name in enumerate(name_list): + self.loadFrames(frame_list[i], name, 1, c.WHITE) + + self.frames = self.idle_frames + + def idling(self): + if not self.is_big: + if self.change_timer == 0: + self.change_timer = self.current_time + elif (self.current_time - self.change_timer) > 25000: + self.changeFrames(self.big_frames) + self.is_big = True + + if self.sun_timer == 0: + self.sun_timer = self.current_time - (c.FLOWER_SUN_INTERVAL - 6000) + elif (self.current_time - self.sun_timer) > c.FLOWER_SUN_INTERVAL: + self.sun_group.add(Sun(self.rect.centerx, self.rect.bottom, self.rect.right, + self.rect.bottom + self.rect.h // 2, self.is_big)) + self.sun_timer = self.current_time + + +现在我需要修改喷气蘑菇的实现,使其符合需求:近距离(3格)喷射攻击,30秒后自动消失。 + + +toolName: edit_file_update + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\component\plant.py + +changes: + +newStr: class PuffShroom(Plant): + def __init__(self, x, y, bullet_group): + Plant.__init__(self, x, y, c.PUFFSHROOM, c.PLANT_HEALTH, bullet_group) + self.can_sleep = True + self.shoot_timer = 0 + self.life_timer = 0 # Timer for automatic disappearance + self.life_duration = 30000 # 30 seconds + + def loadImages(self, name, scale): + self.idle_frames = [] + self.sleep_frames = [] + + idle_name = name + sleep_name = name + 'Sleep' + + frame_list = [self.idle_frames, self.sleep_frames] + name_list = [idle_name, sleep_name] + + for i, name in enumerate(name_list): + self.loadFrames(frame_list[i], name, 1) + + self.frames = self.idle_frames + + def handleState(self): + # Check if PuffShroom should disappear + if self.life_timer == 0: + self.life_timer = self.current_time + elif (self.current_time - self.life_timer) > self.life_duration: + self.health = 0 # Set health to 0 to trigger removal + else: + super().handleState() + + def attacking(self): + if (self.current_time - self.shoot_timer) > 3000: + self.bullet_group.add(Bullet(self.rect.right, self.rect.y + 10, self.rect.y + 10, + c.BULLET_MUSHROOM, c.BULLET_DAMAGE_NORMAL, True)) + self.shoot_timer = self.current_time + + def canAttack(self, zombie): + # Close range attack (3 grids) + if (self.rect.x <= zombie.rect.right and + (self.rect.right + c.GRID_X_SIZE * 3 >= zombie.rect.x)): + return True + return False + +oldStr: class PuffShroom(Plant): + def __init__(self, x, y, bullet_group): + Plant.__init__(self, x, y, c.PUFFSHROOM, c.PLANT_HEALTH, bullet_group) + self.can_sleep = True + self.shoot_timer = 0 + + def loadImages(self, name, scale): + self.idle_frames = [] + self.sleep_frames = [] + + idle_name = name + sleep_name = name + 'Sleep' + + frame_list = [self.idle_frames, self.sleep_frames] + name_list = [idle_name, sleep_name] + + for i, name in enumerate(name_list): + self.loadFrames(frame_list[i], name, 1) + + self.frames = self.idle_frames + + def attacking(self): + if (self.current_time - self.shoot_timer) > 3000: + self.bullet_group.add(Bullet(self.rect.right, self.rect.y + 10, self.rect.y + 10, + c.BULLET_MUSHROOM, c.BULLET_DAMAGE_NORMAL, True)) + self.shoot_timer = self.current_time + + def canAttack(self, zombie): + if (self.rect.x <= zombie.rect.right and + (self.rect.right + c.GRID_X_SIZE * 4 >= zombie.rect.x)): + return True + return False + + +现在我需要实现墓碑和墓碑吞噬者。首先,我需要在constants.py中添加相关常量。 + + +toolName: view_files + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\constants.py + +我需要在constants.py中添加墓碑和墓碑吞噬者的相关常量。 + + +toolName: edit_file_update + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\constants.py + +changes: + +newStr: #BACKGROUND +BACKGROUND_DAY = 0 +BACKGROUND_NIGHT = 1 + +#GRAVE +GRAVE = 'Grave' +GRAVE_BUSTER = 'GraveBuster' +GRAVE_BUSTER_EAT_TIME = 5000 # 5 seconds to eat grave + +#PLANT CARD INFO +CARD_GRAVE_BUSTER = 'card_grave_buster' + +oldStr: #BACKGROUND +BACKGROUND_DAY = 0 +BACKGROUND_NIGHT = 1 + + +现在我需要在menubar.py中添加墓碑吞噬者的卡片信息。 + + +toolName: edit_file_update + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\component\menubar.py + +changes: + +newStr: 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_PUFFSHROOM, c.CARD_POTATOMINE, c.CARD_SQUASH, c.CARD_SPIKEWEED, + c.CARD_JALAPENO, c.CARD_SCAREDYSHROOM, c.CARD_SUNSHROOM, c.CARD_ICESHROOM, + c.CARD_HYPNOSHROOM, c.CARD_WALLNUT, c.CARD_REDWALLNUT, c.CARD_GRAVE_BUSTER] +plant_name_list = [c.SUNFLOWER, c.PEASHOOTER, c.SNOWPEASHOOTER, c.WALLNUT, + c.CHERRYBOMB, c.THREEPEASHOOTER, c.REPEATERPEA, c.CHOMPER, + c.PUFFSHROOM, c.POTATOMINE, c.SQUASH, c.SPIKEWEED, + c.JALAPENO, c.SCAREDYSHROOM, c.SUNSHROOM, c.ICESHROOM, + c.HYPNOSHROOM, c.WALLNUTBOWLING, c.REDWALLNUTBOWLING, c.GRAVE_BUSTER] +plant_sun_list = [50, 100, 175, 50, 150, 325, 200, 150, 0, 25, 50, 100, + 125, 25, 25, 75, 75, 0, 0, 75] +plant_frozen_time_list = [7500, 7500, 7500, 30000, 50000, 7500, 7500, 7500, 7500, 30000, + 30000, 7500, 50000, 7500, 7500, 50000, 30000, 0, 0, 7500] +all_card_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] + +oldStr: 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_PUFFSHROOM, c.CARD_POTATOMINE, c.CARD_SQUASH, c.CARD_SPIKEWEED, + c.CARD_JALAPENO, c.CARD_SCAREDYSHROOM, c.CARD_SUNSHROOM, c.CARD_ICESHROOM, + c.CARD_HYPNOSHROOM, c.CARD_WALLNUT, c.CARD_REDWALLNUT] +plant_name_list = [c.SUNFLOWER, c.PEASHOOTER, c.SNOWPEASHOOTER, c.WALLNUT, + c.CHERRYBOMB, c.THREEPEASHOOTER, c.REPEATERPEA, c.CHOMPER, + c.PUFFSHROOM, c.POTATOMINE, c.SQUASH, c.SPIKEWEED, + c.JALAPENO, c.SCAREDYSHROOM, c.SUNSHROOM, c.ICESHROOM, + c.HYPNOSHROOM, c.WALLNUTBOWLING, c.REDWALLNUTBOWLING] +plant_sun_list = [50, 100, 175, 50, 150, 325, 200, 150, 0, 25, 50, 100, + 125, 25, 25, 75, 75, 0, 0] +plant_frozen_time_list = [7500, 7500, 7500, 30000, 50000, 7500, 7500, 7500, 7500, 30000, + 30000, 7500, 50000, 7500, 7500, 50000, 30000, 0, 0] +all_card_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + + +现在我需要实现墓碑类。我将在map.py中添加墓碑相关的功能,或者创建一个新的组件类。 + + +toolName: write_to_file + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\component\grave.py + +content: __author__ = 'marble_xu' + +import pygame as pg +from .. import tool +from .. import constants as c + +class Grave(pg.sprite.Sprite): + def __init__(self, x, y): + pg.sprite.Sprite.__init__(self) + + self.name = c.GRAVE + self.frames = [] + self.frame_index = 0 + self.loadImages() + self.frame_num = len(self.frames) + + self.image = self.frames[self.frame_index] + self.rect = self.image.get_rect() + self.rect.centerx = x + self.rect.bottom = y + + self.health = 10 # Grave health + self.dead = False + + self.animate_timer = 0 + self.animate_interval = 150 + + def loadImages(self): + # Load grave images + grave_name = self.name + self.loadFrames(self.frames, grave_name, 1) + + def loadFrames(self, frame_list, name, scale): + # Load frames from sprite sheet + frame_rect = tool.GRAVE_RECT[name] + for i in range(frame_rect['frame_num']): + x = frame_rect['x'] + i * frame_rect['width'] + y = frame_rect['y'] + width = frame_rect['width'] + height = frame_rect['height'] + image = tool.get_image(tool.GFX[name], x, y, width, height, c.BLACK, scale) + frame_list.append(image) + + def update(self, game_info): + self.current_time = game_info[c.CURRENT_TIME] + self.animation() + + def animation(self): + if (self.current_time - self.animate_timer) > self.animate_interval: + self.frame_index += 1 + if self.frame_index >= self.frame_num: + self.frame_index = 0 + self.animate_timer = self.current_time + self.image = self.frames[self.frame_index] + + def setDamage(self, damage): + self.health -= damage + if self.health <= 0: + self.dead = True + self.kill() + +class GraveBuster(pg.sprite.Sprite): + def __init__(self, x, y, grave): + pg.sprite.Sprite.__init__(self) + + self.name = c.GRAVE_BUSTER + self.frames = [] + self.frame_index = 0 + self.loadImages() + self.frame_num = len(self.frames) + + self.image = self.frames[self.frame_index] + self.rect = self.image.get_rect() + self.rect.centerx = x + self.rect.bottom = y + + self.grave = grave + self.eat_timer = 0 + self.eat_duration = c.GRAVE_BUSTER_EAT_TIME + self.state = c.IDLE + + self.animate_timer = 0 + self.animate_interval = 150 + + def loadImages(self): + # Load grave buster images + buster_name = self.name + self.loadFrames(self.frames, buster_name, 1) + + def loadFrames(self, frame_list, name, scale): + # Load frames from sprite sheet + frame_rect = tool.PLANT_RECT[name] + for i in range(frame_rect['frame_num']): + x = frame_rect['x'] + i * frame_rect['width'] + y = frame_rect['y'] + width = frame_rect['width'] + height = frame_rect['height'] + image = tool.get_image(tool.GFX[name], x, y, width, height, c.BLACK, scale) + frame_list.append(image) + + def update(self, game_info): + self.current_time = game_info[c.CURRENT_TIME] + self.handleState() + self.animation() + + def handleState(self): + if self.state == c.IDLE: + self.idling() + elif self.state == c.ATTACK: + self.attacking() + + def idling(self): + # Start eating grave + self.state = c.ATTACK + self.eat_timer = self.current_time + + def attacking(self): + # Check if done eating + if (self.current_time - self.eat_timer) > self.eat_duration: + # Destroy both grave and grave buster + self.grave.setDamage(10) # Enough damage to destroy grave + self.kill() + + def animation(self): + if (self.current_time - self.animate_timer) > self.animate_interval: + self.frame_index += 1 + if self.frame_index >= self.frame_num: + self.frame_index = self.frame_num - 1 # Stay on last frame + self.animate_timer = self.current_time + self.image = self.frames[self.frame_index] + + def canAttack(self, zombie): + # Grave buster doesn't attack zombies + return False + +现在我需要在level.py中添加墓碑的生成和管理功能。 + + +toolName: edit_file_update + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\state\level.py + +changes: + +newStr: from .. import tool +from .. import constants as c +from ..component import map, plant, zombie, menubar, grave + +oldStr: from .. import tool +from .. import constants as c +from ..component import map, plant, zombie, menubar + + +现在我需要在setupGroups方法中添加墓碑组。 + + +toolName: edit_file_update + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\state\level.py + +changes: + +newStr: def setupGroups(self): + self.sun_group = pg.sprite.Group() + self.head_group = pg.sprite.Group() + self.grave_group = pg.sprite.Group() + + self.plant_groups = [] + self.zombie_groups = [] + self.hypno_zombie_groups = [] #zombies who are hypno after eating hypnoshroom + self.bullet_groups = [] + for i in range(self.map_y_len): + self.plant_groups.append(pg.sprite.Group()) + self.zombie_groups.append(pg.sprite.Group()) + self.hypno_zombie_groups.append(pg.sprite.Group()) + self.bullet_groups.append(pg.sprite.Group()) + +oldStr: def setupGroups(self): + self.sun_group = pg.sprite.Group() + self.head_group = pg.sprite.Group() + + self.plant_groups = [] + self.zombie_groups = [] + self.hypno_zombie_groups = [] #zombies who are hypno after eating hypnoshroom + self.bullet_groups = [] + for i in range(self.map_y_len): + self.plant_groups.append(pg.sprite.Group()) + self.zombie_groups.append(pg.sprite.Group()) + self.hypno_zombie_groups.append(pg.sprite.Group()) + self.bullet_groups.append(pg.sprite.Group()) + + +现在我需要在initPlay方法中添加墓碑的生成逻辑。 + + +toolName: edit_file_update + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\state\level.py + +changes: + +newStr: self.removeMouseImage() + self.setupGroups() + self.setupZombies() + self.setupCars() + + # Generate graves for night levels + if self.background_type == c.BACKGROUND_NIGHT: + self.generateGraves() + +oldStr: self.removeMouseImage() + self.setupGroups() + self.setupZombies() + self.setupCars() + + +现在我需要实现generateGraves方法,在黑夜关卡的2-5列随机生成5-8个墓碑。 + + +toolName: edit_file_update + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\state\level.py + +changes: + +newStr: def generateGraves(self): + import random + num_graves = random.randint(5, 8) + + for _ in range(num_graves): + # Random column between 2 and 5 (inclusive) + map_x = random.randint(2, 5) + # Random row between 0 and 4 (inclusive) + map_y = random.randint(0, self.map_y_len - 1) + + # Get the position for the grave + x, y = self.map.getMapGridPos(map_x, map_y) + + # Create and add the grave + new_grave = grave.Grave(x, y) + self.grave_group.add(new_grave) + + def createZombie(self, name, map_y): + x, y = self.map.getMapGridPos(0, map_y) + if name == c.NORMAL_ZOMBIE: + self.zombie_groups[map_y].add(zombie.NormalZombie(c.ZOMBIE_START_X, y, self.head_group)) + elif name == c.CONEHEAD_ZOMBIE: + self.zombie_groups[map_y].add(zombie.ConeHeadZombie(c.ZOMBIE_START_X, y, self.head_group)) + elif name == c.BUCKETHEAD_ZOMBIE: + self.zombie_groups[map_y].add(zombie.BucketHeadZombie(c.ZOMBIE_START_X, y, self.head_group)) + elif name == c.FLAG_ZOMBIE: + 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)) + +oldStr: def createZombie(self, name, map_y): + x, y = self.map.getMapGridPos(0, map_y) + if name == c.NORMAL_ZOMBIE: + self.zombie_groups[map_y].add(zombie.NormalZombie(c.ZOMBIE_START_X, y, self.head_group)) + elif name == c.CONEHEAD_ZOMBIE: + self.zombie_groups[map_y].add(zombie.ConeHeadZombie(c.ZOMBIE_START_X, y, self.head_group)) + elif name == c.BUCKETHEAD_ZOMBIE: + self.zombie_groups[map_y].add(zombie.BucketHeadZombie(c.ZOMBIE_START_X, y, self.head_group)) + elif name == c.FLAG_ZOMBIE: + 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)) + + +现在我需要在addPlant方法中添加墓碑吞噬者的支持。 + + +toolName: edit_file_update + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\state\level.py + +changes: + +newStr: elif self.plant_name == c.HYPNOSHROOM: + new_plant = plant.HypnoShroom(x, y) + elif self.plant_name == c.WALLNUTBOWLING: + new_plant = plant.WallNutBowling(x, y, map_y, self) + elif self.plant_name == c.REDWALLNUTBOWLING: + new_plant = plant.RedWallNutBowling(x, y) + elif self.plant_name == c.GRAVE_BUSTER: + # Check if there's a grave at this position + for g in self.grave_group: + if g.rect.collidepoint(x, y): + new_plant = grave.GraveBuster(x, y, g) + break + else: + # No grave found, can't plant + return + +oldStr: elif self.plant_name == c.HYPNOSHROOM: + new_plant = plant.HypnoShroom(x, y) + elif self.plant_name == c.WALLNUTBOWLING: + new_plant = plant.WallNutBowling(x, y, map_y, self) + elif self.plant_name == c.REDWALLNUTBOWLING: + new_plant = plant.RedWallNutBowling(x, y) + + +现在我需要在update方法中更新墓碑组,并在draw方法中绘制墓碑。 + + +toolName: edit_file_update + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\state\level.py + +changes: + +newStr: self.head_group.update(self.game_info) + self.sun_group.update(self.game_info) + self.grave_group.update(self.game_info) + +oldStr: self.head_group.update(self.game_info) + self.sun_group.update(self.game_info) + + +现在我需要在draw方法中绘制墓碑。 + + +toolName: edit_file_update + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\state\level.py + +changes: + +newStr: # Draw graves + self.grave_group.draw(surface) + + for i in range(self.map_y_len): + self.plant_groups[i].draw(surface) + self.zombie_groups[i].draw(surface) + self.hypno_zombie_groups[i].draw(surface) + self.bullet_groups[i].draw(surface) + self.drawZombieFreezeTrap(i, surface) + +oldStr: for i in range(self.map_y_len): + self.plant_groups[i].draw(surface) + self.zombie_groups[i].draw(surface) + self.hypno_zombie_groups[i].draw(surface) + self.bullet_groups[i].draw(surface) + self.drawZombieFreezeTrap(i, surface) + + +现在我需要创建一个测试关卡来验证这些功能是否正常工作。我将创建一个新的level_4.json文件作为黑夜关卡。 + + +toolName: write_to_file + +status: failed + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\data\map\level_4.json + + +文件已存在,我需要先查看其内容,然后再修改。 + + +toolName: view_files + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\data\map\level_4.json + +我需要创建一个新的黑夜关卡文件,让我使用level_5.json。 + + +toolName: write_to_file + +status: failed + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\data\map\level_5.json + + +让我查看现有的关卡文件,然后选择一个合适的编号创建新的黑夜关卡。 + + +toolName: view_folder + +status: success + +e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\data\map + +让我检查level_3.json是否已经是黑夜关卡。 + + +toolName: view_files + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\data\map\level_3.json + +让我检查是否有现有的测试文件结构。 + + +toolName: view_folder + +status: success + +e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1 + +让我查看main.py文件,了解如何启动游戏和特定关卡。 + + +toolName: view_files + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\main.py + +让我查看source/main.py文件,了解游戏的启动流程。 + + +toolName: view_files + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\main.py + +现在我需要运行游戏来测试黑夜关卡的功能。让我执行main.py来启动游戏。 + + +toolName: run_command + +status: running + +command: python main.py + +让我检查游戏的运行状态,看看是否有任何错误或异常信息。 + + +toolName: check_command_status + +status: success + + +现在我需要创建一个测试用例来验证所有功能是否正常工作。让我创建一个测试脚本。 + + +toolName: write_to_file + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\test_night_level.py + +content: import pygame as pg +import sys +import os + +# 添加source目录到路径 +sys.path.append(os.path.join(os.path.dirname(__file__), 'source')) + +from source import tool +from source import constants as c +from source.state import level + +def test_night_level(): + """测试黑夜关卡功能""" + print("=== 测试黑夜关卡功能 ===") + + # 初始化pygame + pg.init() + screen = pg.display.set_mode((c.SCREEN_WIDTH, c.SCREEN_HEIGHT)) + clock = pg.time.Clock() + + # 创建游戏控制 + game = tool.Control() + + # 创建黑夜关卡 + level_state = level.Level() + + # 模拟加载黑夜关卡 + level_state.setupLevel(3) # level_3.json是黑夜关卡 + + print("1. 测试背景类型是否为黑夜:") + print(f" background_type = {level_state.background_type}") + print(f" 预期: {c.BACKGROUND_NIGHT}") + print(f" 结果: {'通过' if level_state.background_type == c.BACKGROUND_NIGHT else '失败'}") + + print("\n2. 测试是否不生成阳光:") + print(f" produce_sun = {level_state.produce_sun}") + print(f" 预期: False") + print(f" 结果: {'通过' if not level_state.produce_sun else '失败'}") + + print("\n3. 测试墓碑生成:") + print(f" 墓碑数量: {len(level_state.grave_group)}") + print(f" 预期: 5-8个墓碑") + print(f" 结果: {'通过' if 5 <= len(level_state.grave_group) <= 8 else '失败'}") + + # 显示墓碑位置 + for i, grave in enumerate(level_state.grave_group): + print(f" 墓碑{i+1}: 位置 ({grave.map_x}, {grave.map_y})") + + print("\n4. 测试黑夜滤镜是否创建:") + print(f" night_filter存在: {hasattr(level_state, 'night_filter')}") + print(f" 结果: {'通过' if hasattr(level_state, 'night_filter') else '失败'}") + + if hasattr(level_state, 'night_filter'): + print(f" night_filter alpha: {level_state.night_filter.get_alpha()}") + print(f" 预期: 80") + print(f" 结果: {'通过' if level_state.night_filter.get_alpha() == 80 else '失败'}") + + print("\n=== 测试完成 ===") + + # 清理 + pg.quit() + +if __name__ == "__main__": + test_night_level() + +现在我需要运行测试脚本,看看是否有任何错误或异常信息。 + + +toolName: run_command + +status: success + +command: python test_night_level.py + +让我检查Level类的方法名。 + + +toolName: search_by_regex + +status: success + +query: def setup + +让我查看Level类的初始化方法,了解如何正确初始化关卡。 + + +toolName: view_files + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\state\level.py + +让我查看Level类的__init__方法,了解如何正确初始化关卡。 + + +toolName: view_files + +status: success + + +filePath: e:\my_code\git\shujvbiaozhu\PythonPlantsVsZombies-master1\source\state\level.pyModel thinking limit reached, please enter 'Continue' to get more. \ No newline at end of file diff --git a/source/__pycache__/__init__.cpython-39.pyc b/source/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 00000000..669a2f48 Binary files /dev/null and b/source/__pycache__/__init__.cpython-39.pyc differ diff --git a/source/__pycache__/constants.cpython-39.pyc b/source/__pycache__/constants.cpython-39.pyc new file mode 100644 index 00000000..96b75526 Binary files /dev/null and b/source/__pycache__/constants.cpython-39.pyc differ diff --git a/source/__pycache__/main.cpython-39.pyc b/source/__pycache__/main.cpython-39.pyc new file mode 100644 index 00000000..2199dceb Binary files /dev/null and b/source/__pycache__/main.cpython-39.pyc differ diff --git a/source/__pycache__/tool.cpython-39.pyc b/source/__pycache__/tool.cpython-39.pyc new file mode 100644 index 00000000..4f3ce0a6 Binary files /dev/null and b/source/__pycache__/tool.cpython-39.pyc differ diff --git a/source/component/__pycache__/__init__.cpython-39.pyc b/source/component/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 00000000..4c2349fd Binary files /dev/null and b/source/component/__pycache__/__init__.cpython-39.pyc differ diff --git a/source/component/__pycache__/grave.cpython-39.pyc b/source/component/__pycache__/grave.cpython-39.pyc new file mode 100644 index 00000000..1c93475a Binary files /dev/null and b/source/component/__pycache__/grave.cpython-39.pyc differ diff --git a/source/component/__pycache__/map.cpython-39.pyc b/source/component/__pycache__/map.cpython-39.pyc new file mode 100644 index 00000000..73be486f Binary files /dev/null and b/source/component/__pycache__/map.cpython-39.pyc differ diff --git a/source/component/__pycache__/menubar.cpython-39.pyc b/source/component/__pycache__/menubar.cpython-39.pyc new file mode 100644 index 00000000..a4bd846f Binary files /dev/null and b/source/component/__pycache__/menubar.cpython-39.pyc differ diff --git a/source/component/__pycache__/plant.cpython-39.pyc b/source/component/__pycache__/plant.cpython-39.pyc new file mode 100644 index 00000000..b9d1a1c4 Binary files /dev/null and b/source/component/__pycache__/plant.cpython-39.pyc differ diff --git a/source/component/__pycache__/zombie.cpython-39.pyc b/source/component/__pycache__/zombie.cpython-39.pyc new file mode 100644 index 00000000..1d941c1b Binary files /dev/null and b/source/component/__pycache__/zombie.cpython-39.pyc differ diff --git a/source/component/grave.py b/source/component/grave.py new file mode 100644 index 00000000..592ba560 --- /dev/null +++ b/source/component/grave.py @@ -0,0 +1,134 @@ +__author__ = 'marble_xu' + +import pygame as pg +from .. import tool +from .. import constants as c + +class Grave(pg.sprite.Sprite): + def __init__(self, x, y): + pg.sprite.Sprite.__init__(self) + + self.name = c.GRAVE + self.frames = [] + self.frame_index = 0 + self.loadImages() + self.frame_num = len(self.frames) + + self.image = self.frames[self.frame_index] + self.rect = self.image.get_rect() + self.rect.centerx = x + self.rect.bottom = y + + self.health = 10 # Grave health + self.dead = False + + self.animate_timer = 0 + self.animate_interval = 150 + + def loadImages(self): + # Load grave images + grave_name = self.name + self.loadFrames(self.frames, grave_name, 1) + + def loadFrames(self, frame_list, name, scale): + # Load frames from sprite sheet + frame_rect = tool.GRAVE_RECT[name] + for i in range(frame_rect['frame_num']): + x = frame_rect['x'] + i * frame_rect['width'] + y = frame_rect['y'] + width = frame_rect['width'] + height = frame_rect['height'] + image = tool.get_image(tool.GFX[name], x, y, width, height, c.BLACK, scale) + frame_list.append(image) + + def update(self, game_info): + self.current_time = game_info[c.CURRENT_TIME] + self.animation() + + def animation(self): + if (self.current_time - self.animate_timer) > self.animate_interval: + self.frame_index += 1 + if self.frame_index >= self.frame_num: + self.frame_index = 0 + self.animate_timer = self.current_time + self.image = self.frames[self.frame_index] + + def setDamage(self, damage): + self.health -= damage + if self.health <= 0: + self.dead = True + self.kill() + +class GraveBuster(pg.sprite.Sprite): + def __init__(self, x, y, grave): + pg.sprite.Sprite.__init__(self) + + self.name = c.GRAVE_BUSTER + self.frames = [] + self.frame_index = 0 + self.loadImages() + self.frame_num = len(self.frames) + + self.image = self.frames[self.frame_index] + self.rect = self.image.get_rect() + self.rect.centerx = x + self.rect.bottom = y + + self.grave = grave + self.eat_timer = 0 + self.eat_duration = c.GRAVE_BUSTER_EAT_TIME + self.state = c.IDLE + + self.animate_timer = 0 + self.animate_interval = 150 + + def loadImages(self): + # Load grave buster images + buster_name = self.name + self.loadFrames(self.frames, buster_name, 1) + + def loadFrames(self, frame_list, name, scale): + # Load frames from sprite sheet + frame_rect = tool.PLANT_RECT[name] + for i in range(frame_rect['frame_num']): + x = frame_rect['x'] + i * frame_rect['width'] + y = frame_rect['y'] + width = frame_rect['width'] + height = frame_rect['height'] + image = tool.get_image(tool.GFX[name], x, y, width, height, c.BLACK, scale) + frame_list.append(image) + + def update(self, game_info): + self.current_time = game_info[c.CURRENT_TIME] + self.handleState() + self.animation() + + def handleState(self): + if self.state == c.IDLE: + self.idling() + elif self.state == c.ATTACK: + self.attacking() + + def idling(self): + # Start eating grave + self.state = c.ATTACK + self.eat_timer = self.current_time + + def attacking(self): + # Check if done eating + if (self.current_time - self.eat_timer) > self.eat_duration: + # Destroy both grave and grave buster + self.grave.setDamage(10) # Enough damage to destroy grave + self.kill() + + def animation(self): + if (self.current_time - self.animate_timer) > self.animate_interval: + self.frame_index += 1 + if self.frame_index >= self.frame_num: + self.frame_index = self.frame_num - 1 # Stay on last frame + self.animate_timer = self.current_time + self.image = self.frames[self.frame_index] + + def canAttack(self, zombie): + # Grave buster doesn't attack zombies + return False \ No newline at end of file diff --git a/source/component/menubar.py b/source/component/menubar.py index 56054a52..a9dd245c 100644 --- a/source/component/menubar.py +++ b/source/component/menubar.py @@ -15,16 +15,17 @@ c.CARD_CHERRYBOMB, c.CARD_THREEPEASHOOTER, c.CARD_REPEATERPEA, c.CARD_CHOMPER, c.CARD_PUFFSHROOM, c.CARD_POTATOMINE, c.CARD_SQUASH, c.CARD_SPIKEWEED, c.CARD_JALAPENO, c.CARD_SCAREDYSHROOM, c.CARD_SUNSHROOM, c.CARD_ICESHROOM, - c.CARD_HYPNOSHROOM, c.CARD_WALLNUT, c.CARD_REDWALLNUT] + c.CARD_HYPNOSHROOM, c.CARD_WALLNUT, c.CARD_REDWALLNUT, c.CARD_GRAVE_BUSTER] plant_name_list = [c.SUNFLOWER, c.PEASHOOTER, c.SNOWPEASHOOTER, c.WALLNUT, c.CHERRYBOMB, c.THREEPEASHOOTER, c.REPEATERPEA, c.CHOMPER, c.PUFFSHROOM, c.POTATOMINE, c.SQUASH, c.SPIKEWEED, c.JALAPENO, c.SCAREDYSHROOM, c.SUNSHROOM, c.ICESHROOM, - c.HYPNOSHROOM, c.WALLNUTBOWLING, c.REDWALLNUTBOWLING] -plant_sun_list = [50, 100, 175, 50, 150, 325, 200, 150, 0, 25, 50, 100, 125, 25, 25, 75, 75, 0, 0] + c.HYPNOSHROOM, c.WALLNUTBOWLING, c.REDWALLNUTBOWLING, c.GRAVE_BUSTER] +plant_sun_list = [50, 100, 175, 50, 150, 325, 200, 150, 0, 25, 50, 100, + 125, 25, 25, 75, 75, 0, 0, 75] plant_frozen_time_list = [7500, 7500, 7500, 30000, 50000, 7500, 7500, 7500, 7500, 30000, - 30000, 7500, 50000, 7500, 7500, 50000, 30000, 0, 0] -all_card_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + 30000, 7500, 50000, 7500, 7500, 50000, 30000, 0, 0, 7500] +all_card_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] def getSunValueImage(sun_value): font = pg.font.SysFont(None, 22) diff --git a/source/component/plant.py b/source/component/plant.py index 684065b1..c9d9a7ac 100644 --- a/source/component/plant.py +++ b/source/component/plant.py @@ -453,6 +453,8 @@ def __init__(self, x, y, bullet_group): Plant.__init__(self, x, y, c.PUFFSHROOM, c.PLANT_HEALTH, bullet_group) self.can_sleep = True self.shoot_timer = 0 + self.life_timer = 0 # Timer for automatic disappearance + self.life_duration = 30000 # 30 seconds def loadImages(self, name, scale): self.idle_frames = [] @@ -469,6 +471,15 @@ def loadImages(self, name, scale): self.frames = self.idle_frames + def handleState(self): + # Check if PuffShroom should disappear + if self.life_timer == 0: + self.life_timer = self.current_time + elif (self.current_time - self.life_timer) > self.life_duration: + self.health = 0 # Set health to 0 to trigger removal + else: + super().handleState() + def attacking(self): if (self.current_time - self.shoot_timer) > 3000: self.bullet_group.add(Bullet(self.rect.right, self.rect.y + 10, self.rect.y + 10, @@ -476,8 +487,9 @@ def attacking(self): self.shoot_timer = self.current_time def canAttack(self, zombie): + # Close range attack (3 grids) if (self.rect.x <= zombie.rect.right and - (self.rect.right + c.GRID_X_SIZE * 4 >= zombie.rect.x)): + (self.rect.right + c.GRID_X_SIZE * 3 >= zombie.rect.x)): return True return False @@ -736,15 +748,21 @@ def idling(self): if not self.is_big: if self.change_timer == 0: self.change_timer = self.current_time - elif (self.current_time - self.change_timer) > 25000: + elif (self.current_time - self.change_timer) > 60000: # 60 seconds to grow self.changeFrames(self.big_frames) self.is_big = True + # Produce sun every 15 seconds if self.sun_timer == 0: - self.sun_timer = self.current_time - (c.FLOWER_SUN_INTERVAL - 6000) - elif (self.current_time - self.sun_timer) > c.FLOWER_SUN_INTERVAL: - self.sun_group.add(Sun(self.rect.centerx, self.rect.bottom, self.rect.right, - self.rect.bottom + self.rect.h // 2, self.is_big)) + self.sun_timer = self.current_time + elif (self.current_time - self.sun_timer) > 15000: + # Small sunshroom produces 15 sun, big one produces 25 + sun_value = 25 if self.is_big else 15 + # Create sun with appropriate value + sun = Sun(self.rect.centerx, self.rect.bottom, self.rect.right, + self.rect.bottom + self.rect.h // 2, self.is_big) + sun.sun_value = sun_value + self.sun_group.add(sun) self.sun_timer = self.current_time class IceShroom(Plant): diff --git a/source/constants.py b/source/constants.py index 0c4e2b6e..502df212 100644 --- a/source/constants.py +++ b/source/constants.py @@ -177,4 +177,12 @@ #BACKGROUND BACKGROUND_DAY = 0 -BACKGROUND_NIGHT = 1 \ No newline at end of file +BACKGROUND_NIGHT = 1 + +#GRAVE +GRAVE = 'Grave' +GRAVE_BUSTER = 'GraveBuster' +GRAVE_BUSTER_EAT_TIME = 5000 # 5 seconds to eat grave + +#PLANT CARD INFO +CARD_GRAVE_BUSTER = 'card_grave_buster' \ No newline at end of file diff --git a/source/state/__pycache__/__init__.cpython-39.pyc b/source/state/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 00000000..6191044b Binary files /dev/null and b/source/state/__pycache__/__init__.cpython-39.pyc differ diff --git a/source/state/__pycache__/level.cpython-39.pyc b/source/state/__pycache__/level.cpython-39.pyc new file mode 100644 index 00000000..68533000 Binary files /dev/null and b/source/state/__pycache__/level.cpython-39.pyc differ diff --git a/source/state/__pycache__/mainmenu.cpython-39.pyc b/source/state/__pycache__/mainmenu.cpython-39.pyc new file mode 100644 index 00000000..d67b25bb Binary files /dev/null and b/source/state/__pycache__/mainmenu.cpython-39.pyc differ diff --git a/source/state/__pycache__/screen.cpython-39.pyc b/source/state/__pycache__/screen.cpython-39.pyc new file mode 100644 index 00000000..07753079 Binary files /dev/null and b/source/state/__pycache__/screen.cpython-39.pyc differ diff --git a/source/state/level.py b/source/state/level.py index 133cc28a..f218e907 100644 --- a/source/state/level.py +++ b/source/state/level.py @@ -5,7 +5,7 @@ import pygame as pg from .. import tool from .. import constants as c -from ..component import map, plant, zombie, menubar +from ..component import map, plant, zombie, menubar, grave class Level(tool.State): def __init__(self): @@ -38,10 +38,17 @@ def setupBackground(self): self.level = pg.Surface((self.bg_rect.w, self.bg_rect.h)).convert() self.viewport = tool.SCREEN.get_rect(bottom=self.bg_rect.bottom) self.viewport.x += c.BACKGROUND_OFFSET_X + + # Add night blue filter for night levels + if self.background_type == c.BACKGROUND_NIGHT: + self.night_filter = pg.Surface((self.bg_rect.w, self.bg_rect.h)) + self.night_filter.fill((0, 0, 100)) # Dark blue color + self.night_filter.set_alpha(80) # Transparency level def setupGroups(self): self.sun_group = pg.sprite.Group() self.head_group = pg.sprite.Group() + self.grave_group = pg.sprite.Group() self.plant_groups = [] self.zombie_groups = [] @@ -127,6 +134,10 @@ def initPlay(self, card_list): self.setupGroups() self.setupZombies() self.setupCars() + + # Generate graves for night levels + if self.background_type == c.BACKGROUND_NIGHT: + self.generateGraves() def play(self, mouse_pos, mouse_click): if self.zombie_start_time == 0: @@ -148,6 +159,7 @@ def play(self, mouse_pos, mouse_click): self.head_group.update(self.game_info) self.sun_group.update(self.game_info) + self.grave_group.update(self.game_info) if not self.drag_plant and mouse_pos and mouse_click[0]: result = self.menubar.checkCardClick(mouse_pos) @@ -186,6 +198,23 @@ def play(self, mouse_pos, mouse_click): self.checkCarCollisions() self.checkGameState() + def generateGraves(self): + import random + num_graves = random.randint(5, 8) + + for _ in range(num_graves): + # Random column between 2 and 5 (inclusive) + map_x = random.randint(2, 5) + # Random row between 0 and 4 (inclusive) + map_y = random.randint(0, self.map_y_len - 1) + + # Get the position for the grave + x, y = self.map.getMapGridPos(map_x, map_y) + + # Create and add the grave + new_grave = grave.Grave(x, y) + self.grave_group.add(new_grave) + def createZombie(self, name, map_y): x, y = self.map.getMapGridPos(0, map_y) if name == c.NORMAL_ZOMBIE: @@ -250,6 +279,15 @@ def addPlant(self): new_plant = plant.WallNutBowling(x, y, map_y, self) elif self.plant_name == c.REDWALLNUTBOWLING: new_plant = plant.RedWallNutBowling(x, y) + elif self.plant_name == c.GRAVE_BUSTER: + # Check if there's a grave at this position + for g in self.grave_group: + if g.rect.collidepoint(x, y): + new_plant = grave.GraveBuster(x, y, g) + break + else: + # No grave found, can't plant + return if new_plant.can_sleep and self.background_type == c.BACKGROUND_DAY: new_plant.setSleep() @@ -529,11 +567,19 @@ def drawZombieFreezeTrap(self, i, surface): def draw(self, surface): self.level.blit(self.background, self.viewport, self.viewport) + + # Apply night filter for night levels + if self.background_type == c.BACKGROUND_NIGHT: + self.level.blit(self.night_filter, (0, 0)) + surface.blit(self.level, (0,0), self.viewport) if self.state == c.CHOOSE: self.panel.draw(surface) elif self.state == c.PLAY: self.menubar.draw(surface) + # Draw graves + self.grave_group.draw(surface) + for i in range(self.map_y_len): self.plant_groups[i].draw(surface) self.zombie_groups[i].draw(surface) diff --git a/test_night_level.py b/test_night_level.py new file mode 100644 index 00000000..4754f9f2 --- /dev/null +++ b/test_night_level.py @@ -0,0 +1,64 @@ +import pygame as pg +import sys +import os + +# 添加source目录到路径 +sys.path.append(os.path.join(os.path.dirname(__file__), 'source')) + +from source import tool +from source import constants as c +from source.state import level + +def test_night_level(): + """测试黑夜关卡功能""" + print("=== 测试黑夜关卡功能 ===") + + # 初始化pygame + pg.init() + screen = pg.display.set_mode((c.SCREEN_WIDTH, c.SCREEN_HEIGHT)) + clock = pg.time.Clock() + + # 创建游戏控制 + game = tool.Control() + + # 创建黑夜关卡 + level_state = level.Level() + + # 模拟加载黑夜关卡 + level_state.setupLevel(3) # level_3.json是黑夜关卡 + + print("1. 测试背景类型是否为黑夜:") + print(f" background_type = {level_state.background_type}") + print(f" 预期: {c.BACKGROUND_NIGHT}") + print(f" 结果: {'通过' if level_state.background_type == c.BACKGROUND_NIGHT else '失败'}") + + print("\n2. 测试是否不生成阳光:") + print(f" produce_sun = {level_state.produce_sun}") + print(f" 预期: False") + print(f" 结果: {'通过' if not level_state.produce_sun else '失败'}") + + print("\n3. 测试墓碑生成:") + print(f" 墓碑数量: {len(level_state.grave_group)}") + print(f" 预期: 5-8个墓碑") + print(f" 结果: {'通过' if 5 <= len(level_state.grave_group) <= 8 else '失败'}") + + # 显示墓碑位置 + for i, grave in enumerate(level_state.grave_group): + print(f" 墓碑{i+1}: 位置 ({grave.map_x}, {grave.map_y})") + + print("\n4. 测试黑夜滤镜是否创建:") + print(f" night_filter存在: {hasattr(level_state, 'night_filter')}") + print(f" 结果: {'通过' if hasattr(level_state, 'night_filter') else '失败'}") + + if hasattr(level_state, 'night_filter'): + print(f" night_filter alpha: {level_state.night_filter.get_alpha()}") + print(f" 预期: 80") + print(f" 结果: {'通过' if level_state.night_filter.get_alpha() == 80 else '失败'}") + + print("\n=== 测试完成 ===") + + # 清理 + pg.quit() + +if __name__ == "__main__": + test_night_level() \ No newline at end of file