413 lines
16 KiB
JavaScript
413 lines
16 KiB
JavaScript
Mapeate.Mapas = function(mapeate, entradas){
|
|
|
|
const self = this,
|
|
tipos = {},
|
|
mapas = {},
|
|
cache = {},
|
|
claves = ["x", "y", "ancho", "alto"],
|
|
tamano_cache = {x : 0, y : 0};
|
|
let iniciado = false,
|
|
sobreescribir_por_defecto,
|
|
sobreescribir_tipos_por_defecto,
|
|
mapas_hilo_de_proceso,
|
|
fecha_inicio_juego,
|
|
tiempo_partida, tiempo_crudo_partida,
|
|
puntos_tiempo_respuesta, puntos_aciertos, puntos_fallos,
|
|
aciertos, fallos, puntos_total, finalizada_partida;
|
|
|
|
let selector = this.selector;
|
|
let global = this.global;
|
|
let espana = this.espana;
|
|
|
|
const constructor = () => {
|
|
|
|
mapeate.print("info", "mapeate_mapas_construyendose");
|
|
|
|
selector = self.selector = new Mapeate.Mapas.Selector(mapeate, entradas);
|
|
global = self.global = new Mapeate.Mapas.Global(mapeate, entradas);
|
|
espana = self.espana = new Mapeate.Mapas.Espana(mapeate, entradas);
|
|
|
|
mapeate.print("ok", "mapeate_mapas_construido");
|
|
|
|
};
|
|
|
|
this.iniciar = callback => {
|
|
|
|
const terminar = estado => typeof callback == "function" && callback(estado);
|
|
|
|
mapeate.print("info", "mapeate_mapas_iniciando");
|
|
|
|
if(iniciado){
|
|
mapeate.print("warn", "mapeate_mapas_ya_iniciado");
|
|
terminar(false);
|
|
return false;
|
|
};
|
|
iniciado = true;
|
|
|
|
sobreescribir_por_defecto = mapeate.configuracion(["mapas_sobreescribir", "sobreescribir"]);
|
|
sobreescribir_tipos_por_defecto = mapeate.configuracion(["mapas_tipos_sobreescribir", "mapas_sobreescribir", "sobreescribir"]);
|
|
puntos_tiempo_respuesta = mapeate.configuracion("puntos_tiempo_respuesta");
|
|
puntos_aciertos = mapeate.configuracion("puntos_aciertos");
|
|
puntos_fallos = mapeate.configuracion("puntos_fallos");
|
|
|
|
mapeate.ejecutar_array_asincrono([
|
|
"archivos_de_mapas_tipos_por_defecto",
|
|
"archivos_de_mapas_tipos",
|
|
"mapas_tipos_por_defecto",
|
|
"mapas_tipos"
|
|
], (clave, callback) => self.cargar_tipos(mapeate.configuracion(clave), true, callback), () => {
|
|
mapeate.ejecutar_array_asincrono([
|
|
"archivos_de_mapas_por_defecto",
|
|
"archivos_de_mapas",
|
|
"mapas_por_defecto",
|
|
"mapas"
|
|
], (clave, callback) => self.cargar(mapeate.configuracion(clave), true, callback), () => {
|
|
mapeate.ejecutar_array_asincrono([
|
|
selector, global, espana
|
|
], (elemento, callback) => elemento.iniciar(callback), () => {
|
|
mapeate.print("ok", "mapeate_mapas_iniciado");
|
|
mapas_hilo_de_proceso = mapeate.anadir_hilo_de_proceso(hilo_de_proceso_metodo);
|
|
terminar(true);
|
|
});
|
|
});
|
|
});
|
|
|
|
return true;
|
|
};
|
|
|
|
const hilo_de_proceso_metodo = () => {
|
|
if(!mapeate.si_mismo)
|
|
return;
|
|
|
|
const mapa = mapeate.si_mismo.querySelector(".juego>.mapa"),
|
|
svg = mapa.querySelector("svg");
|
|
|
|
if(svg){
|
|
|
|
const limites = {},
|
|
final = {};
|
|
|
|
[limites.x, limites.y, limites.ancho, limites.alto] = svg.getAttribute("data-caja").split(" ").map(valor => Number(valor));
|
|
[final.x, final.y, final.ancho, final.alto] = mapeate.porcentuar(
|
|
limites.ancho, limites.alto, mapa.offsetWidth, mapa.offsetHeight
|
|
);
|
|
|
|
|
|
if(tamano_cache.x != final.ancho || tamano_cache.y != final.alto){
|
|
|
|
const proporcion = final.ancho / limites.ancho;
|
|
|
|
// console.log([proporcion, Object.values(limites).map(valor => valor * proporcion >> 0).join(" ")]);
|
|
|
|
// svg.currentScale = proporcion;
|
|
svg.setAttribute("viewBox", Object.values(limites).join(" "));
|
|
svg.setAttribute("width", final.ancho);
|
|
svg.setAttribute("height", final.alto);
|
|
// svg.style.width = ancho + "px";
|
|
// svg.style.height = alto + "px";
|
|
svg.style.marginLeft = -(final.ancho / 2) + "px";
|
|
svg.style.marginTop = -(final.alto / 2) + "px";
|
|
|
|
tamano_cache.x = final.ancho;
|
|
tamano_cache.y = final.alto;
|
|
|
|
};
|
|
|
|
if(!finalizada_partida){
|
|
tiempo_crudo_partida = Date.now() - fecha_inicio_juego;
|
|
mapeate.si_mismo.querySelector(".juego .temporizador>section").innerText = tiempo_partida = (
|
|
("00" + (tiempo_crudo_partida / 3600000 >> 0)).slice(-2) + ":" +
|
|
("00" + (tiempo_crudo_partida / 60000 % 60 >> 0)).slice(-2) + ":" +
|
|
("00" + (tiempo_crudo_partida / 1000 % 60 >> 0)).slice(-2) + "." +
|
|
("00" + (tiempo_crudo_partida % 1000 >> 0)).slice(-3)
|
|
);
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
const cargar_tipos = (clave, callback) => mapeate.leer_archivo(tipos[clave].url, datos => {
|
|
if(datos){
|
|
tipos[clave].datos = datos;
|
|
tipos[clave].ok = true;
|
|
};
|
|
mapeate.ejecutar(callback);
|
|
});
|
|
|
|
this.cargar_tipos = (entradas, sobreescribir, callback) => {
|
|
typeof sobreescribir == "boolean" || (sobreescribir = sobreescribir_tipos_por_defecto);
|
|
mapeate.cargar_diccionarios(mapeate.coger_array(entradas), (nuevos_tipos, callback) => {
|
|
|
|
let i = 0;
|
|
const l = Object.keys(nuevos_tipos).length,
|
|
terminar = () => ++ i == l && mapeate.ejecutar(callback);
|
|
|
|
for(const clave in nuevos_tipos){
|
|
if(sobreescribir || !tipos[clave]){
|
|
tipos[clave] = {
|
|
url : nuevos_tipos[clave].url,
|
|
clase : nuevos_tipos[clave].clase,
|
|
niveles_ocultables : nuevos_tipos[clave].niveles_ocultables,
|
|
datos : null,
|
|
ok : false
|
|
};
|
|
cargar_tipos(clave, terminar);
|
|
}else
|
|
terminar();
|
|
};
|
|
|
|
}, callback, 0);
|
|
|
|
};
|
|
|
|
this.cargar = (entradas, sobreescribir, callback) => {
|
|
typeof sobreescribir == "boolean" || (sobreescribir = sobreescribir_por_defecto);
|
|
mapeate.cargar_diccionarios(mapeate.coger_array(entradas), (nuevos_mapas, callback) => {
|
|
for(const clave in nuevos_mapas)
|
|
(sobreescribir || !mapas[clave]) &&
|
|
nuevos_mapas[clave] &&
|
|
typeof nuevos_mapas[clave] == "object" &&
|
|
(mapas[clave] = {
|
|
...nuevos_mapas[clave],
|
|
...(nuevos_mapas[clave].tipo && tipos[nuevos_mapas[clave].tipo] ? tipos[nuevos_mapas[clave].tipo] : {})
|
|
});
|
|
mapeate.ejecutar(callback);
|
|
}, callback, 0);
|
|
};
|
|
|
|
this.coger = claves => {
|
|
|
|
const l = (claves = mapeate.coger_array_de_strings(claves)).length;
|
|
|
|
for(let i = 0; i < l; i ++)
|
|
if(mapas[claves[i]] !== undefined)
|
|
return mapas[claves[i]];
|
|
return claves[0] || null;
|
|
};
|
|
|
|
this.coger_todos = () => ({...mapas});
|
|
|
|
this.cache = (clave, datos) => datos === undefined ? cache[clave] : (cache[clave] = datos);
|
|
|
|
this.construir = (clave, niveles) => {
|
|
|
|
let error = (
|
|
clave === undefined ? 1 << 0 :
|
|
clave === null ? 1 << 1 :
|
|
typeof clave != "string" ? 1 << 2 :
|
|
!clave ? 1 << 3 :
|
|
!(clave = clave.trim()) ? 1 << 4 :
|
|
mapas[clave] === undefined ? 1 << 5 :
|
|
mapas[clave] === null ? 1 << 6 :
|
|
0) << 1;
|
|
|
|
if(error)
|
|
return;
|
|
|
|
const mapa = {
|
|
nombre : clave,
|
|
...mapas[clave],
|
|
datos : cache[mapas[clave].url]
|
|
};
|
|
let objetivos = "", seleccion;
|
|
|
|
(seleccion = [].concat(...mapa.elementos.filter((bloque, i) => niveles.includes(i)))).sort(() => .5 - Math.random()).forEach((elemento, i) => {
|
|
|
|
const datos_comunes = {
|
|
elemento : elemento,
|
|
formato : mapa.formato,
|
|
seleccionado : !i
|
|
};
|
|
|
|
objetivos += mapeate.string_variables(mapeate.string_variables(mapeate.vistas.coger("elemento_juego_seleccion", datos_comunes), datos_comunes));
|
|
|
|
});
|
|
|
|
mapeate.si_mismo.querySelector(".juego .objetivos ul").innerHTML = objetivos;
|
|
mapeate.si_mismo.querySelector(".juego .puntos section").innerText = 0;
|
|
|
|
if(!mapa.datos)
|
|
mapeate.leer_archivo(mapas[clave].url, datos => {
|
|
|
|
mapas[clave].clase &&
|
|
self[mapas[clave].clase] &&
|
|
self[mapas[clave].clase].preparar &&
|
|
(datos = self[mapas[clave].clase].preparar(datos));
|
|
|
|
cache[mapas[clave].url] = datos;
|
|
mapa.datos = datos;
|
|
|
|
construir(mapa, niveles, seleccion);
|
|
|
|
});
|
|
else
|
|
construir(mapa, niveles, seleccion);
|
|
|
|
};
|
|
|
|
const construir = (datos, niveles, seleccion) => {
|
|
|
|
const juego = mapeate.si_mismo.querySelector(".juego"),
|
|
mapa = juego.querySelector(".mapa section"),
|
|
menu = mapeate.si_mismo.querySelector(".juego .objetivos ul");
|
|
|
|
mapa.innerHTML = (`
|
|
<div class="` + datos.nombre + `" data-clase="` + datos.clase + `"` + [0, 1, 2, 3].map(i => (
|
|
` data-nivel-` + i + `-ocultable="` + datos.niveles_ocultables.includes(i) + `"` +
|
|
` data-nivel-` + i + `="` + niveles.includes(i) + `"`
|
|
)).join("") + `>` + datos.datos + `</div>
|
|
`);
|
|
|
|
mapeate.si_mismo.querySelector(".menu-mapas").setAttribute("data-visible", false);
|
|
mapeate.si_mismo.querySelector(".juego").setAttribute("data-visible", true);
|
|
|
|
mapeate.precargar("." + datos.nombre + ">svg", svg => {
|
|
|
|
const limites = svg.getBBox();
|
|
|
|
svg.setAttribute("data-ancho", limites.width);
|
|
svg.setAttribute("data-alto", limites.height);
|
|
svg.setAttribute("data-caja", datos.posicion.join(" "));
|
|
|
|
tamano_cache.x = 0;
|
|
tamano_cache.y = 0;
|
|
|
|
svg.querySelectorAll("[data-habilitado]").forEach(elemento => {
|
|
|
|
let clon = elemento;
|
|
const clave = elemento.getAttribute("data-objetivo");
|
|
|
|
while(clon && clon.hasAttribute){
|
|
if(clon.tagName.toLowerCase() == "svg")
|
|
break;
|
|
|
|
const objetivo = clon.getAttribute("data-objetivo");
|
|
|
|
if(objetivo != clave && seleccion.includes(objetivo)){
|
|
|
|
const opcion = menu.querySelector("[data-clave=" + clave + "]");
|
|
|
|
opcion && opcion.remove();
|
|
|
|
return;
|
|
};
|
|
clon = clon.parentNode;
|
|
};
|
|
|
|
elemento.setAttribute("data-habilitado", seleccion.includes(elemento.getAttribute("data-objetivo")))
|
|
|
|
});
|
|
mapeate.si_mismo.querySelectorAll(".juego fieldset:not(.mapa)").forEach(campo => campo.innerHTML += mapeate.vistas.coger("posicionador"));
|
|
|
|
fecha_inicio_juego = Date.now();
|
|
aciertos = 0;
|
|
fallos = 0;
|
|
puntos_total = 0;
|
|
finalizada_partida = false;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
this.volver_al_menu = (elemento, evento) => {
|
|
|
|
mapeate.si_mismo.querySelector(".menu-mapas").setAttribute("data-visible", true);
|
|
mapeate.si_mismo.querySelector(".juego").setAttribute("data-visible", false);
|
|
|
|
};
|
|
|
|
this.mostrar_seleccion = (elemento, evento) => mapeate.si_mismo.querySelector(".juego .elemento section").innerText = (
|
|
elemento.getAttribute("data-habilitado") == "false" ? "" :
|
|
elemento.getAttribute("data-acertado") == "false" ? "??????" :
|
|
elemento.getAttribute("data-title")
|
|
);
|
|
|
|
this.ocultar_seleccion = (elemento, evento) => mapeate.si_mismo.querySelector(".juego .elemento section").innerText = "";
|
|
|
|
this.elegir = (elemento, evento) => {
|
|
if(elemento.getAttribute("data-habilitado") == "false")
|
|
return;
|
|
|
|
const clave = elemento.getAttribute("data-objetivo"),
|
|
seleccionado = mapeate.si_mismo.querySelector(".juego .objetivos [data-seleccionado=true][data-ok=false]");
|
|
|
|
if(!seleccionado)
|
|
mapeate.alerta("mapeate_mapas_seleccionar_objetivo");
|
|
else if(seleccionado.getAttribute("data-clave") == clave){
|
|
|
|
const opciones = [...seleccionado.parentNode.querySelectorAll("li")];
|
|
let siguiente = null,
|
|
preparado = false;
|
|
|
|
[0, 1].some(() => opciones.some(nuevo => {
|
|
if(preparado){
|
|
if(nuevo.getAttribute("data-seleccionado") == "false" && nuevo.getAttribute("data-ok") == "false"){
|
|
siguiente = nuevo;
|
|
return true;
|
|
};
|
|
}else if(nuevo.getAttribute("data-clave") == clave)
|
|
preparado = true;
|
|
}));
|
|
|
|
seleccionado.setAttribute("data-seleccionado", false);
|
|
seleccionado.setAttribute("data-ok", true);
|
|
elemento.setAttribute("data-acertado", true);
|
|
mapeate.si_mismo.querySelector(".juego .puntos section").innerText = puntos_total += puntos_aciertos;
|
|
aciertos ++;
|
|
|
|
if(siguiente){
|
|
siguiente.setAttribute("data-seleccionado", true);
|
|
seleccionado.parentNode.parentNode.scrollTop = siguiente.offsetTop - (siguiente.offsetHeight / 2) - (siguiente.parentNode.parentNode.offsetHeight / 2);
|
|
}else{
|
|
|
|
const total = aciertos + fallos,
|
|
porcentage_aciertos = aciertos / total,
|
|
marco_tiempo = tiempo_crudo_partida / aciertos,
|
|
puntos_tiempo = (
|
|
marco_tiempo < puntos_tiempo_respuesta[0] ? 1 :
|
|
marco_tiempo > puntos_tiempo_respuesta[1] ? 0 :
|
|
1 * (puntos_tiempo_respuesta[1] - marco_tiempo - puntos_tiempo_respuesta[0]) / (puntos_tiempo_respuesta[1] - puntos_tiempo_respuesta[0])
|
|
);
|
|
|
|
finalizada_partida = true;
|
|
|
|
mapeate.alerta("mapeate_mapas_ganaste", () => self.volver_al_menu(elemento, evento), {
|
|
final : mapeate.vistas.coger("resumen_fin_juego", {
|
|
tiempo : tiempo_partida,
|
|
aciertos : aciertos,
|
|
fallos : fallos,
|
|
porcentaje_aciertos : (100 * porcentage_aciertos).toFixed(2),
|
|
porcentaje_fallos : (100 * fallos / total).toFixed(2),
|
|
puntos : puntos_total,
|
|
puntos_tiempo : (aciertos * puntos_tiempo).toFixed(2),
|
|
puntos_totales : (10 * porcentage_aciertos * puntos_tiempo).toFixed(2)
|
|
})
|
|
});
|
|
|
|
};
|
|
|
|
}else{
|
|
mapeate.si_mismo.querySelector(".juego .puntos section").innerText = puntos_total -= puntos_fallos;
|
|
fallos ++;
|
|
if(puntos_total < 0){
|
|
finalizada_partida = true;
|
|
mapeate.alerta("mapeate_mapas_has_perdido", () => self.volver_al_menu(elemento, evento));
|
|
}else
|
|
mapeate.alerta("mapeate_mapas_mal_elegido");
|
|
};
|
|
|
|
};
|
|
|
|
this.seleccionar_objetivo = (elemento, evento) => {
|
|
if(elemento.getAttribute("data-seleccionado") == "true" || elemento.getAttribute("data-ok") == "true")
|
|
return;
|
|
|
|
mapeate.si_mismo.querySelectorAll(".juego .objetivos li[data-seleccionado=true]").forEach(elemento => elemento.setAttribute("data-seleccionado", false));
|
|
elemento.setAttribute("data-seleccionado", true);
|
|
|
|
};
|
|
|
|
constructor();
|
|
|
|
}; |