def input_callback(loop_id, field, new_robot, controls, first): """Process input keyboard events to move and rotate the robot.""" # Use the same global events variables for all callbacks for a given loop. global loop_events #assert events is not None or first, "First callback must get events""" if loop_id not in loop_events: # Only the first callback on the loop has to get the events events = pygame.event.get() loop_events[loop_id] = events else: events = loop_events[loop_id] if not process_default_events(events): raise battlefield.AbortBattle new_bullet = None changed = False for event in events: if event.type == pygame.KEYDOWN: if event.key == controls.fire: new_bullet = battlefield.fire_bullet(new_robot, field) changed = True def sign(x): return cmp(x, 0.0) or 1.0 pressed = pygame.key.get_pressed() new_speed = new_rotation = new_turret_rotation = 0.0 if pressed[controls.forward]: new_speed += 150 if pressed[controls.backward]: new_speed += -100 if pressed[controls.rotate_right]: new_rotation += -100*sign(new_speed) if pressed[controls.rotate_left]: new_rotation += 100*sign(new_speed) if pressed[controls.turret_rotate_left]: new_turret_rotation += 100 if pressed[controls.turret_rotate_right]: new_turret_rotation += -100 for attr, value in [("speed", new_speed), ("rotation", new_rotation), ("turret_rotation", new_turret_rotation)]: if getattr(new_robot, attr) != value: setattr(new_robot, attr, value) changed = True if changed: return [battlefield.StateChange(update_robots=[new_robot], new_bullets=lib.compact([new_bullet]))]
def run(field, input_callbacks, draw_callbacks, delta_time=None): """ Run main battlefield loop: input + update + draw callbacks. Return the robot which won the battle (may be None). """ battle_start = time.time() itime = battle_start map_size = field.config["map"]["size"] field.battle_time = 0.0 while len(field.robots) > 1: # Draw for draw_callback in draw_callbacks: draw_callback(field) ### Input for robot_name, input_callback in input_callbacks.iteritems(): if robot_name in field.robots: robot = field.robots[robot_name] state_changes = input_callback(itime, field, robot) for state_change in (state_changes or []): apply_state_change(field, state_change) ### Update if delta_time: dt = delta_time field.battle_time += dt else: new_time = time.time() dt, itime = (new_time - itime), new_time field.battle_time = new_time - battle_start # Update turrets for robot in field.robots.itervalues(): state_changes = process_turret(field, robot, dt) apply_state_change(field, state_changes) # Update bullets field.bullets = lib.compact(process_bullet(bullet, dt, map_size) for bullet in field.bullets) # Update position of robots with control of collisions state_change = move_robots_and_process_collisions(field.robots, dt, map_size) apply_state_change(field, state_change) # Check collision between bullets and robots def _get_collisions(): for bullet in field.bullets: robot = check_bullet_collision(field.robots.values(), bullet) if robot: yield (bullet, robot) collisions = dict(_get_collisions()) for bullet, robot in collisions.iteritems(): robot.shield -= 1 if robot.shield <= 0: # Robot is dead del field.robots[robot.name] field.bullets = lib.remove_from_list(field.bullets, collisions.keys()) return field.robots and field.robots.values()[0]