Source: level.mjs

/**
 * @module Level
 * @version 0.1
 * @author Luca Leon Happel
 * @file Speichert die Entitäten und den Hinter/Vordergrund der
 * gemalt werden soll, sowie das Kollisionsbild
 * @see {@link Entity}
 */

/**
 * Klasse, welche ein Level darstellt
 */
export class Level {
	/*
	 * Erstelle ein Level
	 * @param {string} URL - die basis-URL welche zu den Bildern des Levels gehört
	 * @example
	 * // läd die Dateien: [level/Landschaft-v, level/Landschaft-h.png, level/Landschaft-k.png]
	 * l = new Level('level/Landschaft');
	 */
	constructor(URL) {
		this.vordergrundIMG       = new Image();
		this.vordergrundIMG.src   = URL.concat('-v.png');
		this.hintergrundIMG       = new Image();
		this.hintergrundIMG.src   = URL.concat('-h.png');
		this.kollisionIMG         = new Image();
		this.kollisionIMG.src     = URL.concat('-k.png');
		this.kollisionCANVAS      = undefined; // Canvas, welches nur das kollisionIMG beinhaltet
		this.kollisionNeedsUpdate = true; // gibt an, ob kollisionCANVAS neu generiert werden muss
		this.entities             = [] // Entitäten im Level (wie Spieler etc)
		this.kollitionsgrenze     = 0.8; // alpha-Wert des Pixels, damit er als kollidierbar gilt
		this.gravity              = {x: 0, y: +0.2}
	}
	/**
	 * Gibt das Vordergrundbild zurück, wenn geladen
	 * @return {image|undefined} das Vordergrundbild, wenn geladen
	 */
	get vordergrund() {
		if(this.loaded)
			return this.vordergrundIMG;
		else
			console.warn('Vordergrundbild wurde noch nicht geladen!');
	}
	/**
	 * Gibt das Hintergrundbild zurück, wenn geladen
	 * @return {image|undefined} das Hintergrundbild, wenn geladen
	 */
	get hintergrund() {
		if(this.loaded)
			return this.hintergrundIMG;
		else
			console.warn('Hintergrundbild wurde noch nicht geladen!');
	}
	/**
	 * Gibt das Kollisionsbild zurück, wenn geladen
	 * @return {image|undefined} das Kollisionsbild, wenn geladen
	 */
	get kollision() {
		if(this.loaded)
			return this.kollisionIMG;
		else
			console.warn('Kollisionsbild wurde noch nicht geladen!');
	}
	/**
	 * Gibt an, ob alle Dateien welche vom Level benötigt werden geladen sind
	 * @return {boolean}
	 */
	get loaded(){
		return this.vordergrundIMG.complete
			&& this.hintergrundIMG.complete
			&& this.kollisionIMG.complete
			&& this.entities.every(e => e.loaded )
	}
	/**
	 * Updated das Level
	 * @fires Entity#update
	 * @fires Level#computeCollisions
	 */
	update() {
		this.entities.forEach(e => e.update(this))
		if( this.kollisionNeedsUpdate )
			this.computeCollisions();
	}
	/**
	 * füllt das kollisionCANVAS mit dem kollisionIMG
	 * damit die Pixel des kollisionIMG mit checkCollision
	 * überprüft werden können
	 * @return {boolean} true, wenn Kollisionen nun checkbar sind, sonst false
	 */
	computeCollisions() {
		if( !this.loaded ){
			console.warn(
				"kollisionCANVAS konnte noch nicht erzeugt werden, \
				da level noch nicht geladen wurde");
			return false
		}
		// Füllt das kollisionCANVAS mit dem Kollisionsbild
		let c = document.createElement("canvas");
			c.width  = this.kollisionIMG.width;
			c.height  = this.kollisionIMG.height;
		let ctx = c.getContext("2d");
			ctx.drawImage(this.kollision, 0, 0);
		this.kollisionCANVAS = c;
		this.kollisionNeedsUpdate = false;
		return true
	}
	/**
	 * Checkt ob ein Pixel kollidierbar ist
	 * @param {number} x - X-Position des Pixels
	 * @param {number} y - Y-Position des Pixels
	 * @param {number} [r] - Rotwert den der Pixel erfüllen muss zum kollidieren
	 * @param {number} [g] - Grünwert den der Pixel erfüllen muss zum kollidieren
	 * @param {number} [b] - Blauwert den der Pixel erfüllen muss zum kollidieren
	 * @param {number} [a=Level#kollisionsgrenze] - Alphawert den der Pixel erfüllen muss zum kollidieren
	 */
	checkCollision(x,y, r=0, b=0, g=0, a=this.kollitionsgrenze) {
		// Gibt an, ob ein Pixel kollidierbar ist
		if( !this.loaded )
			return
		if( this.kollisionCANVAS==undefined ){
			return
		}
		let data = this.kollisionCANVAS
			.getContext("2d")
			.getImageData(x,y,1,1)
			.data;
		return data[0] >= r
			&& data[1] >= g
			&& data[2] >= b
			&& data[3] >= a;
	}
}