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()

相关推荐
红队it9 分钟前
【数据分析大屏】基于Django+Vue汽车销售数据分析可视化大屏(完整系统源码+数据库+开发笔记+详细部署教程+虚拟机分布式启动教程)✅
python·数据分析·spark·汽车·大屏端
蹦蹦跳跳真可爱58916 分钟前
Python----计算机视觉处理(opencv:图片灰度化)
人工智能·python·opencv·计算机视觉
不爱学习的小枫36 分钟前
scala的集合
开发语言·scala
梦醒沉醉37 分钟前
Scala的初步使用
开发语言·后端·scala
小白学大数据42 分钟前
Fuel 爬虫:Scala 中的图片数据采集与分析
开发语言·爬虫·scala
贩卖纯净水.1 小时前
《React 属性与状态江湖:从验证到表单受控的实战探险》
开发语言·前端·javascript·react.js
JouJz1 小时前
Java基础系列:深入解析反射机制与代理模式及避坑指南
java·开发语言·代理模式
HelloGitHub1 小时前
经过 10 亿级性能验证的隐私计算开源利器
python·开源·github
白羊不吃白菜1 小时前
PAT乙级(1101 B是A的多少倍)C语言解析
c语言·开发语言
一号言安1 小时前
牛客python蓝桥杯11-32(自用)
开发语言·python