com.kauridev.lunarbase.GameViewManager Maven / Gradle / Ivy
Show all versions of lunar-base Show documentation
/*
* This file is part of the lunar-base package.
*
* Copyright (c) 2014 Eric Fritz
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.kauridev.lunarbase;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* A manager that handles a stack of game views. The top-most view is "active". The active view is
* allowed to process user input. The active view can be changed by pushing or popping views on or
* off the stack.
*
* A collection of views act as a sort of state machine. Views can act as a state of game play, an
* interface, or a hierarchical menu system.
*
* @author Eric Fritz
*/
public class GameViewManager
{
/**
* Whether the manager has been initialized.
*/
private boolean isInitialized = false;
/**
* An ordered list of views.
*/
private List views = new ArrayList<>();
/**
* Returns an ordered list of registered views.
*
* @return An ordered list of registered views.
*/
public List getViews() {
return Collections.unmodifiableList(views);
}
/**
* Returns true if there is a view of the specified type.
*
* @param type The type of view.
*
* @return true if there is a view of the specified type.
*/
public boolean hasView(Class extends GameView> type) {
for (GameView view : views) {
if (type.isAssignableFrom(view.getClass())) {
return true;
}
}
return false;
}
/**
* Adds a view to the stack. If the manager has already been initialized, this view will be
* initialized immediately.
*
* @param view The view.
*/
public void addView(GameView view) {
if (isInitialized) {
view.init();
}
views.add(view);
}
/**
* Removes a view from the stack.
*
* @param view The view.
*/
public void removeView(GameView view) {
views.remove(view);
}
/**
* Initializes all the views.
*/
public void init() {
for (GameView view : views) {
view.init();
}
isInitialized = true;
}
/**
* Calls {@link GameView#exit()} on all the views.
*/
public void exit() {
for (GameView view : views) {
view.exit();
}
views.clear();
}
/**
* Called when it has been determined that game logic needs to be processed.
*
* All views in the stack will be updated from the top down. Each view receives true as
* the second parameter to their update method until a non-overlay view is updated. This acts as
* a flag to whether the current view is "blocked" by a higher view.
*
* @param elapsed The number of milliseconds elapsed since the last call to update.
*/
public void update(double elapsed) {
boolean hasFocus = true;
// Create a copy of the view list to iterate. This allows a view to be removed during
// a view's update method without concurrent modification issues.
List viewList = new ArrayList<>(views);
// Iterate the registered views in reverse order so that the top most (visible) view is
// updated first.
for (int i = viewList.size() - 1; i >= 0; i--) {
GameView view = viewList.get(i);
// Do not process this view if it has been removed by another view's update method
// during this tick.
if (!views.contains(view)) {
continue;
}
view.update(elapsed, hasFocus);
// If this view is not an overlay, or if we've already encountered a non-overlay view,
// set hasFocus to false for the next view.
hasFocus = hasFocus && view.isOverlay();
}
}
/**
* Called when it has been determines it is time to render a frame.
*
* All active views in the stack will be rendered from the bottom up. This allows lower views to
* display properly in the case that upper views only draw to a portion of the screen, or render
* with transparency.
*
* @param elapsed The number of milliseconds elapsed since the last call to render.
*/
public void render(double elapsed) {
// Render each view in forward order. We don't create a copy of the views during the render
// cycle, as views should not be removed during render.
for (GameView view : views) {
view.render(elapsed);
}
}
}