All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.badlogic.gdx.ai.sched.PriorityScheduler Maven / Gradle / Ivy

There is a newer version: 1.8.2
Show newest version
/*******************************************************************************
 * Copyright 2014 See AUTHORS file.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/

package com.badlogic.gdx.ai.sched;

import com.badlogic.gdx.ai.sched.PriorityScheduler.PrioritySchedulableRecord;
import com.badlogic.gdx.utils.TimeUtils;

/** A {@code PriorityScheduler} works like a {@link LoadBalancingScheduler} but allows different tasks to get a different share of
 * the available time by assigning a priority to each task. The higher the priority the longer the amount of the available time
 * dedicated to the corresponding task.
 * 
 * @author davebaol */
public class PriorityScheduler extends SchedulerBase {

	/** The current frame number */
	protected int frame;

	/** Creates a {@code PriorityScheduler}.
	 * @param dryRunFrames number of frames simulated by the dry run to calculate the phase when adding a schedulable via
	 *           {@link #addWithAutomaticPhasing(Schedulable, int)} and {@link #addWithAutomaticPhasing(Schedulable, int, float)} */
	public PriorityScheduler (int dryRunFrames) {
		super(dryRunFrames);
		this.frame = 0;
	}

	/** Executes scheduled tasks based on their frequency and phase. This method must be called once per frame.
	 * @param timeToRun the maximum time in nanoseconds this scheduler should run on the current frame. */
	@Override
	public void run (long timeToRun) {
		// Increment the frame number
		frame++;

		// Clear the list of tasks to run and their total priority
		runList.size = 0;
		float totalPriority = 0;

		// Go through each task
		for (int i = 0; i < schedulableRecords.size; i++) {
			PrioritySchedulableRecord record = schedulableRecords.get(i);
			// If it is due, schedule it
			if ((frame + record.phase) % record.frequency == 0) {
				runList.add(record);
				totalPriority += record.priority;
			}
		}

		// Keep track of the current time
		long lastTime = TimeUtils.nanoTime();

		// Find the number of tasks we need to run
		int numToRun = runList.size;

		// Go through the tasks to run
		for (int i = 0; i < numToRun; i++) {
			// Find the available time
			long currentTime = TimeUtils.nanoTime();
			timeToRun -= currentTime - lastTime;
			PrioritySchedulableRecord record = runList.get(i);
			long availableTime = (long)(timeToRun * record.priority / totalPriority);

			// Run the schedulable object
			record.schedulable.run(availableTime);

			// Store the current time
			lastTime = currentTime;
		}
	}

	/** Adds the {@code schedulable} to the list using the given {@code frequency}, priority 1 and a phase calculated by a dry run
	 * of the scheduler.
	 * @param schedulable the task to schedule
	 * @param frequency the frequency */
	@Override
	public void addWithAutomaticPhasing (Schedulable schedulable, int frequency) {
		addWithAutomaticPhasing(schedulable, frequency, 1f);
	}

	/** Adds the {@code schedulable} to the list using the given {@code frequency} and {@code priority} while the phase is
	 * calculated by a dry run of the scheduler.
	 * @param schedulable the task to schedule
	 * @param frequency the frequency
	 * @param priority the priority */
	public void addWithAutomaticPhasing (Schedulable schedulable, int frequency, float priority) {
		// Calculate the phase and add the schedulable to the list
		add(schedulable, frequency, calculatePhase(frequency), priority);
	}

	/** Adds the {@code schedulable} to the list using the given {@code frequency} and {@code phase} with priority 1.
	 * @param schedulable the task to schedule
	 * @param frequency the frequency
	 * @param phase the phase */
	@Override
	public void add (Schedulable schedulable, int frequency, int phase) {
		add(schedulable, frequency, phase, 1f);
	}

	/** Adds the {@code schedulable} to the list using the given {@code frequency}, {@code phase} and priority.
	 * @param schedulable the task to schedule
	 * @param frequency the frequency
	 * @param phase the phase
	 * @param priority the priority */
	public void add (Schedulable schedulable, int frequency, int phase, float priority) {
		// Compile the record and add it to the list
		schedulableRecords.add(new PrioritySchedulableRecord(schedulable, frequency, phase, priority));
	}

	/** A scheduled task with priority.
	 * 
	 * @author davebaol */
	static class PrioritySchedulableRecord extends com.badlogic.gdx.ai.sched.SchedulerBase.SchedulableRecord {
		float priority;

		PrioritySchedulableRecord (Schedulable schedulable, int frequency, int phase, float priority) {
			super(schedulable, frequency, phase);
			this.priority = priority;
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy