-
Vincent Nivoliers authored20c9ef9f
explorer.js 7.73 KiB
/*
* @licstart
* This program handles the navigation of a planet provided by an xml file
*
* Copyright (C) 2011 Vincent Nivoliers
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see http://www.gnu.org/licenses/gpl.html.
* @licend
*/
(function(factory) {
//namespacing
if(!window["Explosurf"]) {
window["Explosurf"] = {} ;
}
if(!window["Explosurf"]["explorer"]) {
window["Explosurf"]["explorer"] = {} ;
}
factory(window["Explosurf"]["explorer"]) ;
})(function(Xpl) { //namespace Explosurf.notes
/* data structures for a tile */
function Tile(XmlElement) {
this.name = XmlElement.getAttribute('id') ;
this.neighbours = new Array(null,null,null,null) ;
this.neighbour_edges = new Array(null,null,null,null) ;
this.orientations = new Array(null,null,null,null) ;
this.image = null ;
var children = XmlElement.childNodes ;
for(var i=0; i<children.length; i++) {
var child = children[i] ;
if(child.nodeName == 'image') {
this.image = child.getAttribute('name') ;
} else if (child.nodeName == 'edge') {
var index = parseInt(child.getAttribute('origin_index')) ;
var neighbour = child.getAttribute('neighbour') ;
if(neighbour != '') {
this.neighbours[index] = neighbour ;
var neighbour_edge = parseInt(child.getAttribute('opposite_index')) ;
this.neighbour_edges[index] = neighbour_edge ;
var orientation = child.getAttribute('orientation') ;
this.orientations[index] = (orientation != "switch") ;
}
}
}
}
function Map(planet,key) {
this.planet = planet ;
this.key = key ;
this.tile = planet[key] ;
this.rotation = 0 ;
this.orientation = true ;
this.tile_edge = function(edge) {
if(this.orientation) {
return (this.rotation+edge)%4 ;
} else {
return (this.rotation+4-edge)%4 ;
}
}
this.transformation = function() {
var trans = "r"+this.rotation ;
if(!this.orientation) {
trans += "_flip" ;
}
return trans ;
}
this.transformed_image = function() {
var img = this.tile.image ;
var image_base = img.substr(0, img.lastIndexOf('.')) || img ;
var url = window.location.href ;
var base_dir = url.substr(0,url.lastIndexOf('/')) ;
return base_dir+"/"+image_base+"_"+this.transformation()+".png" ;
}
this.neighbour_map = function(edge) {
var tedge = this.tile_edge(edge) ;
var neighbour = this.tile.neighbours[tedge] ;
if(neighbour) {
var neighbour_edge = this.tile.neighbour_edges[tedge] ;
var orientation = this.tile.orientations[tedge] ;
var neigh_map = new Map(this.planet,neighbour) ;
neigh_map.orientation = orientation ? this.orientation : !this.orientation ;
if(neigh_map.orientation) {
neigh_map.rotation = (neighbour_edge+6-edge)%4 ;
} else {
neigh_map.rotation = (neighbour_edge+2+edge)%4 ;
}
return neigh_map ;
} else {
return null ;
}
}
}
Map.prototype.toString = function() {
var buffer = "" ;
buffer += "Name: " + this.tile.name + "<br />" ;
buffer += "Rotation: " + this.rotation + "<br />" ;
buffer += "Orientation: " + this.orientation ;
return buffer ;
}
handle_request_error = function(evt) {
}
/* planet loading from xml */
function openXML(filename, handler) {
var xhttp ;
if (window.XMLHttpRequest) {
xhttp=new XMLHttpRequest() ;
} else {// IE 5/6
xhttp=new ActiveXObject("Microsoft.XMLHTTP") ;
}
xhttp.addEventListener("error", handle_request_error);
//xhttp.addEventListener("readystatechange", function() {handler(this);});
xhttp.open("GET",filename, false) ;
xhttp.overrideMimeType('text/xml');
xhttp.send(null) ;
handler(xhttp) ;
}
/* exploration */
var planet = {} ;
var center_map = null ;
var storage_prefix = 'Explosurf:'
+ document.getElementById('planet-name').innerText.toLowerCase()
+ ':explorer'
;
function save_position() {
var position = center_map.key ;
position += ":" + center_map.rotation ;
position += ":" + center_map.orientation ;
localStorage.setItem(storage_prefix + ":position" ,position) ;
}
window.addEventListener('beforeunload', save_position) ;
function load_position() {
var position = localStorage.getItem(storage_prefix + ":position" ) ;
if(position) {
/* load position from local storage */
var parsed = position.split(":") ;
center_map = new Map(planet,parsed[0]) ;
center_map.rotation = parseInt(parsed[1]) ;
center_map.orientation = (parsed[2] == "true") ;
} else {
/* generate random position */
var tile_size = 0 ;
var can_switch = false ;
for(var key in planet) {
tile_size++ ;
var tile = planet[key] ;
for(var i=0; i<4; i++) {
if(!tile.orientations[i]) {
can_switch = true ;
}
}
}
var rand_tile_index = Math.floor(Math.random()*tile_size) ;
var tile_index = 0 ;
for(var key in planet) {
if(tile_index == rand_tile_index) {
center_map = new Map(planet,key) ;
break ;
}
tile_index++ ;
}
if(can_switch) {
center_map.orientation = (Math.random() > 0.5) ;
}
save_position() ;
}
}
/* export */
Xpl.load = load_position ;
function load_planet(Xmldoc) {
var children = Xmldoc.childNodes ;
for(var i=0; i<children.length; i++) {
var child = children[i] ;
if(child.nodeName == 'planet') {
var tiles = child.childNodes
for(var j=0; j<tiles.length; j++) {
tileNode = tiles[j] ;
if(tileNode.nodeName == 'tile') {
var tile = new Tile(tileNode) ;
planet[tile.name] = tile ;
}
}
}
}
}
var center_elem = document.getElementById("tile_center") ;
var compass_elem = document.getElementById("boussole") ;
var neighbour_elem = ["bottom", "right", "top", "left"].map(function (dir) {
return document.getElementById("tile_"+dir) ;
}) ;
function redraw() {
center_elem.src = center_map.transformed_image() ;
compass_elem.setAttribute("transform", center_map.transformation()) ;
for(var i=0; i<4; i++) {
var map = center_map.neighbour_map(i) ;
var img = neighbour_elem[i] ;
if(map) {
img.src = map.transformed_image() ;
img.style.opacity = 1 ;
} else {
img.src = "" ;
img.style.opacity = 0 ;
}
}
Explosurf.notes.load() ;
}
function go(edge) {
var new_map = center_map.neighbour_map(edge) ;
if(new_map) {
Explosurf.notes.save() ;
center_map = new_map ;
redraw() ;
save_position() ;
}
}
function go_func(edge) {
return function() {go(edge) ;} ;
}
/* export */
Xpl.go = go ;
document.getElementById("go-down").addEventListener('click', go_func(0)) ;
document.getElementById("go-right").addEventListener('click', go_func(1)) ;
document.getElementById("go-up").addEventListener('click', go_func(2)) ;
document.getElementById("go-left").addEventListener('click', go_func(3)) ;
function check_boundary(edge) {
var neighbour = center_map.neighbour_map(edge) ;
return neighbour === null ;
}
/*export*/
Xpl.check_boundary = check_boundary ;
function init(filename) {
openXML(filename, function(response) {
if (response.readyState == 4 && response.status == 200) {
load_planet(response.responseXML) ;
load_position() ;
redraw() ;
}
}) ;
}
Xpl.init = init
}) //end of namespace