python实现的生态模拟系统

用python实现的一个简单的生态模拟系统

  • 红色:顶层捕食者(攻击性越强颜色越红)

  • 绿色:中层消费者

  • 蓝色:底层生产者

  • 动态行为

  • 底层生物主动寻找黄色食物

  • 中层生物追捕底层生物

  • 顶层生物猎杀中层生物

  • 统计面板

  • 实时显示各层级生物数量

  • 食物数量和帧率显示

    import pygame
    import math
    import random
    from enum import Enum
    from collections import defaultdict
    from dataclasses import dataclass

    初始化Pygame

    pygame.init()

    常量定义

    SCREEN_WIDTH = 1280
    SCREEN_HEIGHT = 720
    FPS = 45
    GRID_SIZE = 60
    MAX_FOOD = 150
    FOOD_SPAWN_RATE = 0.02

    基因参数结构体

    @dataclass
    class Genes:
    size: float
    speed: float
    sense_range: float
    metabolism: float
    aggression: float

    生态位类型枚举

    class TrophicLevel(Enum):
    TOP = 0 # 顶层捕食者(红色)
    MIDDLE = 1 # 中层消费者(绿色)
    BOTTOM = 2 # 底层生产者(蓝色)

    食物类

    class Food:
    def init(self):
    self.x = random.uniform(0, SCREEN_WIDTH)
    self.y = random.uniform(0, SCREEN_HEIGHT)
    self.energy = random.uniform(8, 15)
    self.size = 3

    复制代码
      def draw(self, surface):
          pygame.draw.circle(surface, (255, 255, 100), (int(self.x), int(self.y)), self.size)

    生物类

    class Organism:
    def init(self, x, y, level, genes=None):
    self.x = x
    self.y = y
    self.level = level
    self.age = 0
    self.sick = False
    self.energy = 150.0

    复制代码
          # 基因系统
          if genes:
              self.genes = genes
          else:
              self.genes = self._generate_genes(level)
    
          # 动态属性
          self.color = self._get_color()
          self.direction = random.uniform(0, 2 * math.pi)
          self.target = None
    
      def _generate_genes(self, level):
          """根据生态位生成初始基因"""
          base_genes = {
              TrophicLevel.TOP: (8, 2.8, 120, 0.06, 0.8),
              TrophicLevel.MIDDLE: (6, 2.0, 90, 0.04, 0.5),
              TrophicLevel.BOTTOM: (4, 1.2, 60, 0.02, 0.2)
          }
          size, speed, sense, meta, agg = base_genes[level]
          return Genes(
              size * random.uniform(0.9, 1.1),
              speed * random.uniform(0.9, 1.1),
              sense * random.uniform(0.8, 1.2),
              meta * random.uniform(0.9, 1.1),
              agg * random.uniform(0.8, 1.2)
          )
    
      def _get_color(self):
          """根据生态位和攻击性生成颜色"""
          base_colors = {
              TrophicLevel.TOP: (200, 50, 50),
              TrophicLevel.MIDDLE: (50, 200, 50),
              TrophicLevel.BOTTOM: (50, 50, 200)
          }
          r, g, b = base_colors[self.level]
          return (
              min(255, int(r * (1 + self.genes.aggression / 3))),
              min(255, int(g * (1 - self.genes.aggression / 3))),
              b
          )
    
      def move_towards(self, target_x, target_y):
          """向目标方向移动"""
          dx = target_x - self.x
          dy = target_y - self.y
          target_angle = math.atan2(dy, dx)
          angle_diff = (target_angle - self.direction) % (2 * math.pi)
    
          # 平滑转向
          if angle_diff > math.pi:
              angle_diff -= 2 * math.pi
          self.direction += angle_diff * 0.1
    
          # 前进
          self.x += self.genes.speed * math.cos(self.direction)
          self.y += self.genes.speed * math.sin(self.direction)
    
      def avoid(self, target_x, target_y):
          """躲避目标"""
          dx = target_x - self.x
          dy = target_y - self.y
          target_angle = math.atan2(dy, dx)
          self.direction = target_angle + math.pi  # 反向
    
      def update_target(self, foods, organisms):
          """根据感知选择目标"""
          closest_food = None
          closest_predator = None
          closest_prey = None
    
          min_food_dist = float('inf')
          min_pred_dist = float('inf')
          min_prey_dist = float('inf')
    
          # 感知范围内检测
          for obj in foods + organisms:
              if obj is self:
                  continue
    
              dx = obj.x - self.x
              dy = obj.y - self.y
              dist_sq = dx ** 2 + dy ** 2
    
              # 食物检测(仅底层)
              if (self.level == TrophicLevel.BOTTOM and
                      isinstance(obj, Food) and
                      dist_sq < self.genes.sense_range ** 2 and
                      dist_sq < min_food_dist):
                  closest_food = obj
                  min_food_dist = dist_sq
    
              # 天敌检测
              if (isinstance(obj, Organism) and
                      obj.level.value == self.level.value - 1 and
                      dist_sq < self.genes.sense_range ** 2 and
                      dist_sq < min_pred_dist):
                  closest_predator = obj
                  min_pred_dist = dist_sq
    
              # 猎物检测
              if (isinstance(obj, Organism) and
                      obj.level.value == self.level.value + 1 and
                      dist_sq < self.genes.sense_range ** 2 and
                      dist_sq < min_prey_dist):
                  closest_prey = obj
                  min_prey_dist = dist_sq
    
          # 行为优先级:躲避天敌 > 寻找食物/猎物 > 随机游走
          if closest_predator:
              self.target = closest_predator
              self.avoid(self.target.x, self.target.y)
          elif closest_prey and self.level != TrophicLevel.BOTTOM:
              self.target = closest_prey
              self.move_towards(self.target.x, self.target.y)
          elif closest_food and self.level == TrophicLevel.BOTTOM:
              self.target = closest_food
              self.move_towards(self.target.x, self.target.y)
          else:
              # 随机方向微调
              self.direction += random.uniform(-0.3, 0.3)
    
      def check_collision(self, other):
          """通用碰撞检测方法"""
          if isinstance(other, Organism):
              dx = self.x - other.x
              dy = self.y - other.y
              return dx ** 2 + dy ** 2 < (self.genes.size + other.genes.size) ** 2
          elif isinstance(other, Food):
              dx = self.x - other.x
              dy = self.y - other.y
              return dx ** 2 + dy ** 2 < (self.genes.size + other.size) ** 2
          return False
    
      def draw(self, surface):
          """绘制生物体"""
          pygame.draw.circle(
              surface,
              self.color,
              (int(self.x), int(self.y)),
              int(self.genes.size)
          )
    
      def update(self, foods):
          self.age += 1
          self.energy -= self.genes.metabolism
    
          if self.sick and random.random() < 0.03:
              self.sick = False
    
          if self.level == TrophicLevel.BOTTOM:
              self.energy += 0.05
    
          self.energy = min(self.energy, 200)
    
      def reproduce(self):
          child_genes = Genes(
              size=max(2, self.genes.size * random.uniform(0.95, 1.05)),
              speed=max(0.5, self.genes.speed * random.uniform(0.9, 1.1)),
              sense_range=max(30, self.genes.sense_range * random.uniform(0.8, 1.2)),
              metabolism=max(0.01, self.genes.metabolism * random.uniform(0.95, 1.05)),
              aggression=min(1.0, self.genes.aggression * random.uniform(0.9, 1.1))
          )
          child = Organism(
              self.x + random.uniform(-20, 20),
              self.y + random.uniform(-20, 20),
              self.level,
              child_genes
          )
          self.energy -= 35
          return child

    模拟管理器

    class EcosystemSimulation:
    def init(self):
    self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    self.clock = pygame.time.Clock()
    self.font = pygame.font.Font(None, 28)

    复制代码
          self.organisms = []
          self.foods = []
          self.init_ecosystem()
    
      def init_ecosystem(self):
          # 初始种群分布
          for _ in range(80):
              x = random.uniform(0, SCREEN_WIDTH)
              y = random.uniform(0, SCREEN_HEIGHT)
              level = random.choices(
                  list(TrophicLevel),
                  weights=[0.12, 0.25, 0.63]
              )[0]
              self.organisms.append(Organism(x, y, level))
    
          # 初始食物
          for _ in range(80):
              self.foods.append(Food())
    
      def spawn_food(self):
          if random.random() < FOOD_SPAWN_RATE and len(self.foods) < MAX_FOOD:
              self.foods.append(Food())
    
      def handle_collisions(self):
          to_add = []
          to_remove = []
          grid = defaultdict(list)
    
          # 建立空间索引
          for org in self.organisms:
              grid_key = (int(org.x // GRID_SIZE), int(org.y // GRID_SIZE))
              grid[grid_key].append(org)
    
          # 处理生物行为
          for org in self.organisms:
              org.update_target(self.foods, self.organisms)
    
              # 边界反弹
              if org.x < 0 or org.x > SCREEN_WIDTH:
                  org.direction = math.pi - org.direction
              if org.y < 0 or org.y > SCREEN_HEIGHT:
                  org.direction = -org.direction
              org.x = max(0, min(SCREEN_WIDTH, org.x))
              org.y = max(0, min(SCREEN_HEIGHT, org.y))
    
              # 进食检测(底层吃食物)
              if org.level == TrophicLevel.BOTTOM:
                  for food in self.foods[:]:
                      if org.check_collision(food):
                          org.energy += food.energy
                          self.foods.remove(food)
    
              # 捕食检测
              current_key = (int(org.x // GRID_SIZE), int(org.y // GRID_SIZE))
              for dx in (-1, 0, 1):
                  for dy in (-1, 0, 1):
                      neighbor_key = (current_key[0] + dx, current_key[1] + dy)
                      for other in grid.get(neighbor_key, []):
                          if org != other and org.check_collision(other):
                              if org.level.value == other.level.value + 1:
                                  org.energy += other.energy * 0.6
                                  to_remove.append(other)
    
          # 繁殖与死亡
          for org in self.organisms[:]:
              org.update(self.foods)
              if org.energy > 130 and org.age > 18:
                  to_add.append(org.reproduce())
              if org.energy <= 0 or org.age > 250:
                  to_remove.append(org)
    
          # 更新列表
          self.organisms = [o for o in self.organisms if o not in to_remove]
          self.organisms.extend(to_add)
    
      def draw_stats(self):
          stats = [
              f"Time: {pygame.time.get_ticks() // 1000}s",
              f"Organisms: {len(self.organisms)}",
              f"  TOP: {sum(1 for o in self.organisms if o.level == TrophicLevel.TOP)}",
              f"  MID: {sum(1 for o in self.organisms if o.level == TrophicLevel.MIDDLE)}",
              f"  BOT: {sum(1 for o in self.organisms if o.level == TrophicLevel.BOTTOM)}",
              f"Food: {len(self.foods)}",
              f"FPS: {self.clock.get_fps():.1f}"
          ]
          for i, text in enumerate(stats):
              surface = self.font.render(text, True, (240, 240, 240))
              self.screen.blit(surface, (10, 10 + i * 28))
    
      def run(self):
          running = True
          while running:
              for event in pygame.event.get():
                  if event.type == pygame.QUIT:
                      running = False
    
              # 更新状态
              self.spawn_food()
              self.handle_collisions()
    
              # 渲染
              self.screen.fill((18, 18, 18))
              for food in self.foods:
                  food.draw(self.screen)
              for org in self.organisms:
                  org.draw(self.screen)
              self.draw_stats()
    
              pygame.display.flip()
              self.clock.tick(FPS)
    
          pygame.quit()

    if name == "main":
    sim = EcosystemSimulation()
    sim.run()

相关推荐
JavaEdge在掘金4 分钟前
告别“作坊式”开发,CodeBuddy能否成为企业级AI编程的“银弹”?
python
lightqjx12 分钟前
【数据结构】复杂度分析
c语言·开发语言·数据结构·算法
sohoAPI18 分钟前
Flask快速入门
后端·python·flask
程序员小白条2 小时前
我的第二份实习,学校附近,但是干前端!
java·开发语言·前端·数据结构·算法·职场和发展
钟琛......2 小时前
java中父类和子类的成员变量可以重名吗
java·开发语言
沐知全栈开发2 小时前
PHP 超级全局变量
开发语言
Deng9452013145 小时前
基于Python的职位画像系统设计与实现
开发语言·python·文本分析·自然语言处理nlp·scrapy框架·gensim应用
一只小青团8 小时前
Python之面向对象和类
java·开发语言
qq_529835358 小时前
ThreadLocal内存泄漏 强引用vs弱引用
java·开发语言·jvm
景彡先生8 小时前
C++并行计算:OpenMP与MPI全解析
开发语言·c++