import * as BAGEL from "./index.js";
/**
* A Screen contains the code for each individual game screen,
* such as a title screen, menu screens, and screens corresponding to each room or level in the game.
* <br/>
* Each screen manages a collection of {@link Group|Groups},
* each of which stores a list of {@link Sprite|Sprites},
* that are rendered by the {@link Game} class,
* in the order in which they were added.
* <br/>
* Classes which extend Screen must implement the {@link Screen#initialize|initialize} and {@link Screen#update|update} methods.
*/
class Screen
{
/**
* Creates a collection to store {@link Group|Groups}, a default Group named "main",
* a variable to reference the {@link Game} containing this screen,
* and calls the {@link Screen#initialize|initialize} method.
* @param {Game} game - a reference to the Game containing this Screen
* @constructor
*/
constructor(game)
{
// collection of Groups to be rendered by Game
this.groupCollection = {};
this.groupCollection["main"] = new BAGEL.Group();
// a list to store the order in which groups are added;
// necessary because draw order is important
this.groupDrawOrder = [];
this.groupDrawOrder.push("main");
// store reference to Game containing this Screen
this.game = game;
// set up screen-specific objects
this.initialize();
}
/**
* Create a new group and add it to the collection.
* @param {string} groupName - the name that will be used to reference the group
*/
createGroup(groupName)
{
this.groupCollection[groupName] = new BAGEL.Group();
this.groupDrawOrder.push(groupName);
}
/**
* Get a group from the collection.
* @param {string} groupName - the name of the group
* @return {Group} the group stored with the given name
*/
getGroup(groupName)
{
return this.groupCollection[groupName];
}
/**
* Add a sprite to a group in the collection.
* @param {Sprite} sprite - the sprite to be added
* @param {string} groupName - the name of the group
*/
addSpriteToGroup(sprite, groupName="main")
{
this.getGroup(groupName).addSprite(sprite);
}
/**
* Remove a sprite from a group in the collection.
* <br/>
* (Note: simpler to use the {@link Sprite} class {@link Sprite#destroy|destroy} method.)
* @param {Sprite} sprite - the sprite to be removed
* @param {string} groupName - the name of the group
*/
removeSpriteFromGroup(sprite, groupName)
{
this.getGroup(groupName).removeSprite(sprite);
}
/**
* Remove all sprites from a group in the collection.
* @param {string} groupName - the name of the group
*/
removeAllSpritesFromGroup(groupName)
{
let spriteList = this.getGroupSpriteList(groupName);
// traverse list in reverse order
// because splicing from list changes indices
for (let i = spriteList.length - 1; i >= 0; i--)
{
let sprite = spriteList[i];
sprite.destroy();
}
}
/**
* Get the list of sprites stored in the group with the given name.
* <br/>
* Typically used in loops that involve all sprites in this group.
* @param {string} groupName - the name of the group
* @return {List} the list of sprites in the group
*/
getGroupSpriteList(groupName)
{
return this.getGroup(groupName).getSpriteList();
}
/**
* Get the number of sprites stored in the group with the given name.
* @param {string} groupName - the name of the group
* @return {number} the number of sprites in the group
*/
getGroupSpriteCount(groupName)
{
return this.getGroup(groupName).getSpriteCount();
}
/**
* Draw all sprites in all groups in the collection (in the order they were added).
* @param context - the graphics context object associated to the game canvas
*/
drawGroups(context)
{
for (let i = 0; i < this.groupDrawOrder.length; i++)
{
let groupName = this.groupDrawOrder[i];
this.getGroup(groupName).drawSprites(context);
}
}
/**
* Pauses the game: enables/disables automatic {@link Group#update|Group updates},
* which in turn calls the {@link Sprite#update|Sprite update} functions.
* <br>
* The {@link Screen#update|Screen update} function is still called,
* so {@link Input} functions can still be checked,
* to enable the user to un-pause the currently running game.
*/
setPaused(paused)
{
this.paused = paused;
}
/**
* Update all sprites in all groups in the collection.
* <br>
* Can be enabled/disabled with {@link Screen#setPaused|setPaused}.
* @param deltaTime - the change in time since the last clock update
*/
updateGroups(deltaTime)
{
if (this.paused)
return;
for (let i = 0; i < this.groupDrawOrder.length; i++)
{
let groupName = this.groupDrawOrder[i];
this.getGroup(groupName).updateSprites(deltaTime);
}
}
/**
* Create all objects and any other initialization code required by this screen.
* <br/>
* Must be implemented by extending class.
* <br/>
*/
initialize()
{
throw new Error("initialize() method not implemented");
}
/**
* Update all game logic for this screen, such as processing player input,
* interaction between sprites, and game event conditions (such as win/lose).
* <br/>
* Must be implemented by extending class.
*/
update()
{
throw new Error("update() method not implemented");
}
/**
* Resume function is called by Game {@link Game#setScreen|setScreen} function,
* which enables screen data to be updated, if needed.
* <br/>
* Optional to implement in extending class.
*/
resume()
{
}
}
export { Screen };