HylZee : Game « Page Components « JavaScript DHTML

JavaScript DHTML
1. Ajax Layer
2. Data Type
3. Date Time
4. Development
5. Document
6. Event
7. Event onMethod
8. Form Control
9. GUI Components
10. HTML
11. Javascript Collections
12. Javascript Objects
13. Language Basics
14. Node Operation
15. Object Oriented
16. Page Components
17. Security
18. Style Layout
19. Table
20. Utilities
21. Window Browser
Microsoft Office Word 2007 Tutorial
Java
Java Tutorial
Java Source Code / Java Documentation
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
C# / C Sharp
C# / CSharp Tutorial
ASP.Net
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
PHP
Python
SQL Server / T-SQL
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
JavaScript DHTML » Page Components » Game 
HylZee

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="content-language" content="en">
<title>HylZee</title>
<!--META HTTP-EQUIV="Expires" CONTENT="Fri, Jan 01 1900 00:00:00 GMT"-->
<!-- commented out, seems to affect images META HTTP-EQUIV="Pragma" CONTENT="no-cache"-->
<!--META HTTP-EQUIV="Cache-Control" CONTENT="no-cache"-->
<meta name="author" content="peter.schaefer@gmail.com">
<META HTTP-EQUIV="Reply-to" CONTENT="peter.schaefer@gmail.com">
<meta name="generator" content="Code Monkey 1970.01.18(tm Peter Schaefer)">
<META NAME="description" CONTENT="HylZee - A DHTML puzzle game">
<meta name="keywords" content="HylZee DHTML javascript puzzle game huelsi tal pyr">
<META NAME="Creation_Date" CONTENT="09.10.2004">
<meta name="revisit-after" content="30 days">

<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" src="favicon.ico">

<!-- copyright 2004 peter schaefer -->
<!-- 
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 2
of the License, or (at your optionany 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-->

<style type="text/css">

{font-size:16px;}

.map {color:white;}
.controlembossed {
        background: #66CC33;
        border-top-style:solid;
        border-right-style:solid;
        border-bottom-style:solid;
        border-left-style:solid;
        border-top-width: 1px;
        border-right-width: 1px;
        border-bottom-width: 1px;
        border-left-width: 1px;
        border-right-color: #99FF66;
        border-top-color: #99FF66;
        border-left-color: #666666;
        border-bottom-color: #666666;
}
a:link color: #99FF66; }
a:hover color: #FFFF66; }
a:active color: #FF9966; }
a:visited color: #66FF33; }

table,tbody,th,td,img,span {
        margin-left: 0px;
        margin-top: 0px;
        margin-right: 0px;
        margin-bottom 0px;
        padding-left: 0px;
        padding-top: 0px;
        padding-right: 0px;
        padding-bottom: 0px;
}

</style>

<script language="JavaScript" type="text/JavaScript">
<!--

// placement of map window
var map_top= 18;
var map_left= 20;

// grid size of map tiles
var cell_height=32;
var cell_width= cell_height;

// size of bullet graphics
var bullet_width= 12;
var bullet_height= 12;
var status_font= 18;

//status bar minimum width
var minStatusbarWidth= 10*32;

var tileset="default"

// number of space units/tile
var step_unit= 100;

// number of ticks/1 tile movement
var ticks_unit= 420;

// ticks/processing of mainLoop
//FIXME: this doesn't work with 40/240;
var theTick= 42;

// frequency of mainloop
var mainDelay= 20;

// which level to load
var lastLevel= "maps/test/devel-001.html";

// show shrinking animations
var shrink= true;

//continue running
var mainProceed= true;

var debug= false;

//
// debugall switches on most annoying debug output
//
var debugall= true;

var hideDebug= true || debug;

//input constants
var key_fire= 70;
var key_right= 39;
var key_down= 40;
var key_up= 38;
var key_left= 37;

//map object
var map= null;

//log repeat functionality
var log_lastMsg="";
var log_count=0;
var log_threshold=2;
var log_limit=3000;

//which codes signal start and home
var code_start='A';
var code_home ='H';

//
// arguments.caller has been deprecated
// So the stacktrace will not work in new browsers
//
function funcname(f) {
 var s = f.toString().match(/function (\w*)/)[1];
 if ((s == null|| (s.length==0)) return "anonymous";
 return s;
}

function stacktrace() {
 if(!arguments.caller) {
        return "no stacktrace available";
 }

 var s = "";
 for (var a = arguments.caller; a !=null; a = a.caller) {
   s += "->"+funcname(a.callee"\n";
   if (a.caller == a) {s+="*"break;}
 }
 return s;
}


function debugMsg(message) {
         if(debug) {
           //window.status= message;
           if(log_lastMsg!=message) {
              log_lastMsg=message;
              log_count=0;
              log_threshold=2;
              message="<br>"+message;
           }else {
               log_count++;
               if(log_count>=log_threshold) {
                  message= "<br>last message repeated "+log_count+" more times.";
                  log_threshold<<=1;
                  log_count=0;
               }else {
                  message="";
               }
           }

           if(message) {
               var debugDiv= document.getElementById("debugoutput");
               if(debugDiv){
                 var startpos= (debugDiv.innerHTML.length>log_limit)?(debugDiv.innerHTML.length-log_limit):0;
                 debugDiv.innerHTML= debugDiv.innerHTML.substring(startpos, debugDiv.innerHTML.length)+message;
               }else if(debug && debugall) {
                 alert("debugMsg "+log_lastMsg+" (page isn't loaded yet/no debug window found)");
                 debugall= false;
               }

           }
         }
}

function debugEval(test) {
         debugMsg(test+"="+eval(test));
}


function showLayer(layer) {
        var div= document.getElementById(layer);
        if(div)
         div.style.visibility = 'visible';
}

function hideLayer(layer) {
        var div= document.getElementById(layer);
        if(div)
         div.style.visibility = 'hidden';
}

// the fudge factor is used to work around math rounding errors
var fudge= 0.000001;


function toGridX(x) {
        return  Math.floor(x/step_unit+fudge);
}

function toGridY(y) {
        return  Math.floor(y/step_unit+fudge);
}

function toScreenX(x) {
        return  map_left+Math.floor(x*cell_width+fudge);
}

function toScreenY(y) {
        return  map_top+Math.floor(y*cell_height+fudge);
}

var protagonist=null;
var gameState=null;

var Coordinate_toString= function() {
        return '('+this.x+','+this.y+')';
}

function Coordinate_copy() {
        return new Coordinate(this.x,this.y);
}

function Coordinate_clip() {
        var clipped= false;
        ifthis.x<-fudge ) {
          this.x=0;
          clipped= true;
        else ifthis.x-fudge>step_unit*(map.xmax-1) ) {
          this.x= step_unit*(map.xmax-1);
          clipped= true;
        }

        ifthis.y<-fudge ) {
          this.y=0;
          clipped= true;
        else ifthis.y-fudge>step_unit*(map.ymax-1) ) {
          this.y= step_unit*(map.ymax-1);
          clipped= true;
        }
        return clipped;
}

function Coordinate_add(coordinate) {
        this.x+= coordinate.x;
        this.y+= coordinate.y;
}

function Coordinate_gridLock() {
        this.x= step_unit*Math.floor((this.x+step_unit/2+fudge)/step_unit);
        this.y= step_unit*Math.floor((this.y+step_unit/2+fudge)/step_unit);
}

function Coordinate(x,y) {
        this.x= x;
        this.y= y;
        //methods
        this.clip= Coordinate_clip;
        this.toString= Coordinate_toString;
        this.add= Coordinate_add;
        this.copy= Coordinate_copy;
        this.gridLock= Coordinate_gridLock;
}

function toName() {
        return 'Avatar of:'+this.name;
}

function Avatar(name,modifier,facing) {
        this.name= name;
        this.modifier= modifier;
        this.facing= facing;

        //methods
        this.toString= toName;
}

//
// image preloading
//
var myImages= new Array();
function loadImages() {
  for (i=0;i<loadImages.arguments.length;i++) {
          var pos= myImages.length;
          myImages[pos]=new Image();
          myImages[pos].src= loadImages.arguments[i];
  }
}

function imagePath(imageName) {
 return 'images/'+tileset+'/'+imageName;
}

var browsercaps= new Object();

//get internal browser representation/ordering of html
function fixHTML(html) {
        if(browsercaps.fixHTML) {
          var div= document.getElementById("scratchpad");
          div.innerHTML= html;
          return div.innerHTML;
        }else{
          return html;
        }
}

//
// Some browser, like gecko, covert innerHTML to canonic representation.
// this causes flickering
//
function debugHTMLrep(text){
  var fixed= fixHTML(text);
  iffixed!= text) {
    debugMsg("txt:"+escape(text));
    debugMsg("fix:"+escape(fixed));
  }
}


function Direction_normalize(direction) {
        if(direction<0)
           direction= (direction- 360*Math.floor(direction/360+fudge))
        direction= (direction+360)%360;
        return direction;
}

//
// This function almost works for all agents
//
function Protagonist_mapToImage() {
        this.image="protagonist";
        if(this.mode) {
                this.image+= "_"+this.mode;
        }

        if(this.mode!="victorious") {
              if(this.facing>=&& this.facing<=45)
                      this.image+= "_right";
              else if(this.facing>=45 && this.facing<=135)
                      this.image+= "_up";
              else if(this.facing>=135 && this.facing<=225)
                      this.image+= "_left";
              else if(this.facing>=225 && this.facing<=315)
                      this.image+= "_down";
              else if(this.facing>=315 && this.facing<=360)
                      this.image+= "_right";
              else {
                      var msg='mapToImage: ('+this.facing+', bad facing)';
                      debugMsg(msg);
              }
        }

        this.image+="_64.gif";

        return this.image;
}

var bullet_right= new Avatar('bullet_small','right',0);
var bullet_up= new Avatar('bullet_small','up',90);
var bullet_left= new Avatar('bullet_small','left',180);
var bullet_down= new Avatar('bullet_small','down',270);

var bird_right= new Avatar('phoenix_moving','right',0);
var bird_up= new Avatar('phoenix_moving','up',90);
var bird_left= new Avatar('phoenix_moving','left',180);
var bird_down= new Avatar('phoenix_moving','down',270);

var siren_right= new Avatar('chess-rook_moving','right',0);
var siren_up= new Avatar('chess-rook_moving','up',90);
var siren_left= new Avatar('chess-rook_moving','left',180);
var siren_down= new Avatar('chess-rook_moving','down',270);


function getSirenForDirection(direction) {
        direction= Direction_normalize(direction);

        if(direction>=&& direction<=45)
                return siren_right;
        else if(direction>=45 && direction<=135)
                return siren_up;
        else if(direction>=135 && direction<=225)
                return siren_left;
        else if(direction>=225 && direction<=315)
                return siren_down;
        else if(direction>=315 && direction<=360)
                return siren_right;
        else {
                var avatar= 'getSiren: fuck up('+direction+', bad argument)';
                debugMsg(avatar);
                return null;
        }
}

function getBirdForDirection(direction) {
        direction= Direction_normalize(direction);

        if(direction>=&& direction<=45)
                return bird_right;
        else if(direction>=45 && direction<=135)
                return bird_up;
        else if(direction>=135 && direction<=225)
                return bird_left;
        else if(direction>=225 && direction<=315)
                return bird_down;
        else if(direction>=315 && direction<=360)
                return bird_right;
        else {
                var avatar= 'getBird: fuck up('+direction+', bad argument)';
                debugMsg(avatar);
                return null;
        }
}

//FIXME: replace all the verbatim stuff with imagePath(imageName)
function mapCodeToImage(code){
        var src='';
        switch(code) {

                 case 'H':src='images/'+tileset+'/'+'house_64.gif'; break;
                 case 'h':src='images/'+tileset+'/'+'house_open_64.gif'; break;


                 case 'K':src='images/'+tileset+'/'+'ball_red_64.gif'; break;
                 case 'I':src='images/'+tileset+'/'+'ball_blue_64.gif'; break;
                 case 'J':src='images/'+tileset+'/'+'ball_green_64.gif'; break;

                case 'L':src='images/'+tileset+'/'+'box_blue_64.gif'; break;

                 case 'C':src='images/'+tileset+'/'+'bricks_red_64.gif'; break;
                 case 'g':src='images/'+tileset+'/'+'bricks_green_64.gif'; break;
                 case 'N':src='images/'+tileset+'/'+'bricks_grey_64.gif'; break;

                 case 'M':src='images/'+tileset+'/'+'centerstone-blue_64.gif'; break;
                 case 'O':src='images/'+tileset+'/'+'centerstone-grey_64.gif'; break;

                case 'R':src='images/'+tileset+'/'+'phoenix_sleeping_left_64.gif'; break;
                case 'S':src='images/'+tileset+'/'+'phoenix_sleeping_up_64.gif'; break;
                case 'T':src='images/'+tileset+'/'+'phoenix_sleeping_right_64.gif'; break;
                case 'U':src='images/'+tileset+'/'+'phoenix_sleeping_down_64.gif'; break;

                case 'r':src='images/'+tileset+'/'+'phoenix_awake_left_64.gif'; break;
                case 's':src='images/'+tileset+'/'+'phoenix_awake_up_64.gif'; break;
                case 't':src='images/'+tileset+'/'+'phoenix_awake_right_64.gif'; break;
                case 'u':src='images/'+tileset+'/'+'phoenix_awake_down_64.gif'; break;

                case 'P':src='images/'+tileset+'/'+'chess-rook_sleeping_left_64.gif'; break;
                case 'p':src='images/'+tileset+'/'+'chess-rook_awake_left_64.gif'; break;

                case 'P.right':src='images/'+tileset+'/'+'chess-rook_sleeping_right_64.gif'; break;
                case 'p.right':src='images/'+tileset+'/'+'chess-rook_awake_right_64.gif'; break;

                case 'p.moving.left':src='images/'+tileset+'/'+'chess-rook_moving_left_64.gif'; break;
                case 'p.moving.up':src='images/'+tileset+'/'+'chess-rook_moving_up_64.gif'; break;
                case 'p.moving.right':src='images/'+tileset+'/'+'chess-rook_moving_right_64.gif'; break;
                case 'p.moving.down':src='images/'+tileset+'/'+'chess-rook_moving_down_64.gif'; break;

                //FIXME: this should be handled more elegantly by checking for code.mapToImage and writing adding mapToImage function to avatar
                case bullet_right:
                case bullet_left:
                case bullet_up:
                case bullet_down:

                case siren_right:
                case siren_left:
                case siren_up:
                case siren_down:

                case bird_right:
                case bird_left:
                case bird_up:
                case bird_down:
                        src='images/'+tileset+'/'+code.name+'_'+code.modifier+'_64.gif';
                        //debugMsg('setting image:'+src);
                        break;

                case 'Z':src='images/'+tileset+'/'+'cone_up_64.gif'; break;
                case '[':src='images/'+tileset+'/'+'cone_down_64.gif'; break;

                case 'bullet_big':src='images/'+tileset+'/'+'bullet_big_right_64.gif'; break;

                case 'background':src='images/'+tileset+'/'+'background.gif'; break;

                 default: src='';
        }
        return src;
}

function mapCodeToHtml(code,width,height) {
             var box="";
             var imgsrc= mapCodeToImage(code);
             if(imgsrc) {
                box+='<img src="'+imgsrc+'" alt="'+code+'" title="'+code+'" style="margin: 0px;" border="0" height="'+Math.floor(height)+'" width="'+Math.floor(width)+'">';
                if(debug && debugall) {
                        debugHTMLrep(box);
                }
             else {
                   switchcode ){
                          case '_':
                          case ' ':
                          case 'A':
                               box= "&nbsp;";
                               break;
                          default:
                            box= "&nbsp;"+code+"&nbsp;";
                   }
             }
             return box;
}

function Snapshot(what,pos,zoom,time) {
        this.what= what;
        this.pos= pos;
        this.zoom= zoom;
        this.time= time;
}

function Code_animate(t) {

        var completed= (t-this.a.time)/(this.b.time-this.a.time);
        var zoom = this.b.zoom*completed+this.a.zoom*(1.0-completed);
        var posx= this.b.pos.x*completed+this.a.pos.x*(1.0-completed);
        var posy= this.b.pos.y*completed+this.a.pos.y*(1.0-completed);

        var pos= new Coordinate(posx,posy);

        //note: clipping suffers badly from bad math which gives >xmax*step_
        ifpos.clip() ) {
                this.b.time=t;//FIXME:zayin ba debug!
        }

        if(this.updateObj && this.updateObj.update) {
                this.updateObj.update(pos);
        }

        var animDiv= document.getElementById(this.div);
        if(animDiv) {
         animDiv.style.left= toScreenX(pos.x/step_unit+(1.0-zoom)*0.5);
         animDiv.style.top=  toScreenY(pos.y/step_unit+(1.0-zoom)*0.5);

         var node= mapCodeToNode(this.a.what,cell_width*zoom,cell_height*zoom,animDiv.id);
         if(node!= animDiv.firstChild){
             clearChildren(animDiv);
             animDiv.appendChild(node);
         }
         //this redraw often isn't necessary => don't redraw
//          var text= mapCodeToHtml(this.a.what,cell_width*zoom,cell_height*zoom);
         //
         //text= fixHTML(text);
         // fixed already !?
//          if(text!=animDiv.innerHTML)
//               animDiv.innerHTML= text;
        else {
          debugMsg("Error: no layer left for animations");
        }
}

var animation_divs= new Array();

function Animation_begin() {
        this.finished= false;
        this.hasChanged= true;
        for(var i=0; i<1000; ++i