|
<!----------------------------------------------------------------\
| |
| Fair License |
| |
| JS Games :: Jigsaw Puzzle |
| Copyright (C) 2002-2004 Arun Narayanan |
| |
| For latest release information and downloads visit: |
| http://jsgames.sourceforge.net/ |
| |
| Usage of the works is permitted provided that this |
| instrument is retained with the works, so that any entity |
| that uses the works is notified of this instrument. |
| |
| DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY. |
| |
| [2004, Fair License: rhid.com/fair] |
| |
\----------------------------------------------------------------->
<html>
<head>
<title>!!! JS Games :: Jigsaw Puzzle !!!</title>
<style>
body,h1,h2,h3,.msg,capt2,td {font-family: Verdana,Comic Sans MS,Arial;}
body {margin: 0px;}
h1 {font-size:28pt; font-weight:bold; margin-bottom:0px;}
h2,.h2 {font-size:22pt; margin:0px; font-weight:bold; padding:0px;}
h3 {font-size:8pt; margin:0px; font-weight:bold;}
.msg {font-size:8pt; font-weight:bold;}
.capt1,.base,.bar {font-size:10pt; font-weight:bold;}
.capt2 {font-size:9pt; font-weight:bold;}
.capt3 {font-size:8pt; font-weight:bold;}
.tip {font-size:9pt; font-weight:bold; color:#66ffcc;}
.fscapt {font-size:9pt; font-weight:bold;color:#ddffdd;}
.selcapt2 {font-size:9pt; font-weight:normal; margin:4px;background-color:#ddffee;color:#666655;}
.selcapt3 {font-size:9pt; font-weight:normal; margin:4px;background-color:#336666;color:#ffffff;}
.selcapt {font-size:9pt; font-weight:normal; margin:4px;background-color:#ffffff;color:#006600;}
.but {font-size:8pt; font-weight:bold; height:24px; background-color:#606060;color:#ffffff;background-image:url(images/butbase.gif);border:0px solid #cccccc; border-left:none; border-right:none;}
.base {background-color:#aaff66;border:1px solid #009900;color:#006600;}
.bar {background-image:url(jigsaw/bar.gif);background-color:#336633;color:#00330;text-align:center;}
.url,.urlp,.urla {font-size:8pt; font-weight:bold;color:#ffffaa}
.urlp {color:#aaffaa}
.urla {color:#66eeff}
.info {border:2px;border-style:solid;border-color:white;}
.bnote {font-size:8pt; font-weight:normal;color:white;}
a.notelnk,a.notelnk:visited,a.notelnk:active {font-size:8pt; font-weight:normal; color:#66ffcc;}
.bnotehead {font-size:10pt; font-weight:bold;color:#66ffcc;}
.email {font-size:8pt; font-weight:bold; color:white;}
.menubar {padding:0px; margin:0px; brder-top:1px solid white; brder-bottom:1px solid white; background-color:#606060;
background-image:url(images/menu.gif);}
.fra {border:2px solid #999999; background-color:#606060;}
.clsThisGame, .clsBar {font-size:8pt; font-weight:bold; color:#cccccc;}
.clsBar {margin:0px; font-size:8pt; font-weight:bold; color:#ffffff;}
.clsOtherGame {margin:0px; font-size:8pt; font-weight:bold; color:#ffffff; text-decoration:none;}
.help {font-size:8pt; margin:0px; font-weight:bold;}
</style>
<script language="javascript">
<!--
//global configuration (change these to alter the position of the playing board)
var gtop = 200; //168; //constant denotes top of board
var gleft = 10; //constant denotes left of board
//internal use variables
var gintervalid = -1; //keeps track of the game timer
var gtime = 0; //stores time in seconds
var gmoves = 0; //stores the total moves per game
var gpicid = -1; //keeps track of the picture loading timer
var gpictick = 0; //counter for the picture loading timer
var gpicture = ""; //current picture path
var gloaded = false; //becomes true when a proper picture has been loaded
var gdragging = false; //true while a block is being dragged
var gcurrobjid = ""; //id of the block being dragged
var gdx = 0; //width of a block of the picture
var gdy = 0; //height of a block of the picture
var gsrcx = 0; //x coordinate of the block before the drag started
var gsrcy = 0; //y coordinate of the block before the drag started
var gpicurl = ""; //last valid picture url used
var gprogress = 0; //stores the % of correctly positioned pieces
var gactive = false; //keeps track of whether the game timer is active
function toggleHelp()
{
if (butHelp.value == "Hide Help")
{
help.style.display = "none";
divTip.style.display = "block";
butHelp.value = "Show Help";
}
else
{
help.style.display = "block";
divTip.style.display = "none";
butHelp.value = "Hide Help";
}
}
function loadPicture(picture)
{
var i;
gloaded = false;
selPic.disabled = true;
butLoad.value = "Cancel Loading";
board.style.display = "none";
board.style.pixelLeft = gleft;
board.style.pixelTop = gtop;
divPic.style.pixelLeft = gleft;
divPic.style.pixelTop = gtop;
divPic.style.display = "block";
showStatus("Picture Loading... Please Wait!");
pic.src = picture;
gpictick = 0;
gpicture = picture;
stopPicTimer();
gpicid = setInterval("checkPictureLoadStatus()",300);
}
function checkPictureLoadStatus()
{
gpictick++;
if (pic.readyState != "complete")
{
if (gpictick >= 100) //after each 30 secs
{
gpictick = 0; //reset the timer
//ask user if he wants to continue loading the picture
//vbRetryCancel=5 vbRetry=4 vbCancel=2
if (2 == VBMsgBox("The url you provided may be invalid or too slow!\n\n" +
"Do you wish to continue loading the picture?",5,"Loading Picture"))
{
//do a final check to see if by this time the picture has already loaded!
if (pic.readyState == "complete")
{
checkPictureLoadStatus();
return;
}
gloaded = false;
divPic.style.display = "block";
showStatus('Unable to load Picture: ' + gpicture);
stopPicTimer();
return;
}
}
}
else //picture loaded!
{
stopPicTimer();
showStatus('Picture \"' + gpicture + '" Loaded!<p>'
+ "Press 'Start Game' to start the game.");
gloaded = true;
butLoad.disabled = true;
selPic.disabled = false;
butLoad.value="Load Picture";
butStart.disabled = false;
butStart.focus();
gpicurl = gpicture;
}
}
function drawBoard()
{
var i,j,s="",dx,dy,t=0,l=0,n=0,picWidth,picHeight;
if (!gloaded)
{
alert("No Picture selected!. Please use the picture drop down.");
selPic.focus();
return;
}
divisionsX = parseInt(selCols.value);
divisionsY = parseInt(selRows.value);
picWidth = pic.clientWidth;
picHeight = pic.clientHeight;
if (picWidth == 0) picWidth = 400;
if (picHeight == 0) picHeight = 400;
divPic.style.display = "none";
board.style.display = "block";
dx = parseInt(picWidth/divisionsX);
dy = parseInt(picHeight/divisionsY);
board.style.pixelWidth = divisionsX * dx + 1;
board.style.pixelHeight = divisionsY * dy + 1;
for (i=0;i<divisionsY;i++)
for (j=0;j<divisionsX;j++)
{
t = i*dy;
l = j*dx;
s += '<div id=a_' + j + '_' + i + ' style="position:absolute;clip:rect('
+ (t+1) + ',' + (l+dx) + ',' + (t+dy) + ',' + (l+1) + ');"'
+ ' ondragstart="startDrag(this)" ondrag="move();" ondragend="reposition()">'
+ '<img id=p_' + j + '_' + i + ' src="' + gpicture + '" width=' + picWidth
+ ' height=' + picHeight + "></div>\n";
}
s += '<table width="100%" style="position:absolute;top:-60;" cellpadding=0 cellspacing=0><tr>'
+ '<td width="33%"><input style="width:120px" type=button class=but onclick="quitGame();" value="Quit Game"> </td>'
+ '<td width="33%" align=center><input style="width:120px" type=button class=but onclick="restartGame();" value="Restart Game"> </td>'
+ '<td width="33%" align=right><input style="width:120px" type=button name=butPause class=but onclick="pauseGame();" value="Pause Game"></td>'
+ '</tr><tr><td height=6 colspan=4></td></tr>'
+ '<tr><td valign=center id=fldTime class=capt1 nowrap></td>'
+ '<td align=center valign=center id=fldMoves class=capt1 nowrap></td>'
+ '<td valign=center id=fldProgress class=base nowrap>'
+ '<span class=bar id=divProgressBar></span></td></tr></table>'
board.innerHTML = s
gdx = dx;
gdy = dy;
}
function startDrag(obj)
{
if (!gactive)
{
if (butPause.value == "Continue Game")
alert("Press the 'Continue Game' button above to resume the game");
else
alert("Press the 'Restart Game' button to start a new game");
return;
}
gsrcx = obj.style.pixelLeft;
gsrcy = obj.style.pixelTop;
gcurrobjid=obj.id;
obj.style.zIndex = 1; //make topmost layer
gdragging=true;
}
function move()
{
var obj,a;
if (!gactive) return;
if (!gdragging) return;
obj = eval(gcurrobjid);
a = getRowCol(obj)
obj.style.pixelLeft = event.clientX - (parseInt(a[0])+1)*gdx + gdx/2 + document.body.scrollLeft - gleft;
obj.style.pixelTop = event.clientY - (parseInt(a[1])+1)*gdy + gdy/2 + document.body.scrollTop - gtop;
}
function reposition()
{
var osrc,odest,x1,y1,x2,y2,cx1,cy1,cx2,cy2,s;
if (!gactive) return;
if (!gdragging) return;
gdragging = false;
osrc = eval(gcurrobjid);
osrc.style.zIndex = 0;
osrc.style.display = "none";
odest = document.elementFromPoint(event.clientX,event.clientY)
osrc.style.display = "block";
if (!osrc) return;
osrc.style.pixelLeft = gsrcx;
osrc.style.pixelTop = gsrcy;
a = odest.id.replace('p','a');
if (a.substr(0,2) != "a_") return;
odest = eval(a);
if (!odest) return;
swapPieces(osrc,odest);
gmoves++;
showProgress();
if (isWin())
{
gactive = false;
butPause.disabled = true;
stopTimer();
showProgress(); //needed because isWin() may update the status
getPiece(0,0).style.clip = "rect(auto)"; //show the full image
//vbYesNo=4 vbYes=6 vbNo=7
if (6 == VBMsgBox('!! C O N G R A T S !!\n\n' +
'You did it in ' + gmoves + ' moves and ' + gtime + ' secs!\n\n'
+ 'Do you wish to play it again?',4,"Game Over!") )
restartGame();
}
}
function getPiece(row,col)
{
return eval("a_" + col + "_" + row);
}
function getRow(obj)
{
var a = obj.id.split('_');
return parseInt(a[1]);
}
function getCol(obj)
{
var a = obj.id.split('_');
return parseInt(a[2]);
}
function getRowCol(obj)
{
var a = obj.id.split('_');
return new Array(a[1],a[2]);
}
function getClipRow(col)
{
return (col*gdx);
}
function getClipCol(row)
{
return (row*gdy);
}
function getX(obj)
{
return getClipRow(getRow(obj));
}
function getY(obj)
{
return getClipCol(getCol(obj));
}
function showStatus(msg)
{
fldStatus.innerHTML = msg;
}
//random number between 0 and hi
function r0(hi)
{
return Math.floor((hi)*Math.random());
}
function shuffle()
{
var i, j, divisionsX, divisionsY;
divisionsX = selCols.value;
divisionsY = selRows.value;
showStatus('Loading Game... Please Wait!');
for (i=0;i<divisionsY;i++)
for (j=0;j<divisionsX;j++)
{
swapPieces(getPiece(i,j),getPiece(r0(divisionsY),r0(divisionsX)));
}
if (isWin()) shuffle(); //ensure that it is not already a won puzzle!
showStatus('');
showProgress();
}
function swapPieces(osrc,odest)
{
var x1,y1,x2,y2,cx1,cy1,cx2,cy2;
if (osrc == odest) return; //nothing to swap!
x1 = osrc.style.pixelLeft;
y1 = osrc.style.pixelTop;
cx1 = getX(osrc);
cy1 = getY(osrc);
x2 = odest.style.pixelLeft;
y2 = odest.style.pixelTop;
cx2 = getX(odest);
cy2 = getY(odest);
//Calculate new co-ordinates
osrc.style.pixelLeft = x2 + (cx2 - cx1);
osrc.style.pixelTop = y2 + (cy2 - cy1);
odest.style.pixelLeft = x1 - (cx2 - cx1);
odest.style.pixelTop = y1 - (cy2 - cy1);
}
function changePicture(lasturl)
{
var picurl, locfile, re, defurl="http://",retval;
stopPicTimer();
if (selPic.value == "") return;
if (selPic.value == "myurl")
{
if (lasturl != null) defurl = lasturl;
picurl = prompt("Please enter a valid Picture URL (JPG,GIF,PNG,BMP)",defurl);
if (picurl == null || picurl == "")
{
selPic.value = "";
return;
}
re = /^http\:\/\/[\w/.-~?&\\%=]*\.(JPG|JPEG|GIF|PNG|BMP)$/i;
if (re.test(picurl))
{
loadPicture(picurl);
}
else
{
//yes=6 no=7 cancel=2
retval = VBMsgBox("HMMM. Looks like an invalid url !!\n\n" + picurl + "\n\nDo you really want to proceed with it?",3,"Invalid URL?");
if (retval == 6) //yes button
loadPicture(picurl);
else if (retval == 2) //cancel button
changePicture(picurl); //prompt again
else //no button
selPic.value = "";
return;
}
}
else if (selPic.value == "localfile")
{
//locfile
loadPicture(selPic.value);
}
else
{
loadPicture(selPic.value);
}
}
//stops the game timer if it is running
function stopTimer()
{
if (gintervalid != -1)
{
clearInterval(gintervalid);
gintervalid = -1;
}
}
function stopPicTimer()
{
if (gpicid != -1)
{
clearInterval(gpicid);
gpicid = -1;
}
}
function quitGame()
{
// stopGame();
stopTimer();
gtime = 0;
gmoves = 0;
gactive = false;
board.style.display = "none";
board.innerHTML = "";
divMain.style.display = "block";
divInfo.style.display = "block";
divPic.style.display = "block";
// butStart.disabled = true;
selPic.focus();
showStatus('');
}
function showProgress()
{
fldTime.innerHTML = "Time: " + gtime + " secs";
fldMoves.innerHTML = "Moves: " + gmoves + " ";
fldProgress.title = "Percentage Solved: " + gprogress + "%";
if (gprogress < 40)
{
divProgressBar.innerHTML = "";
fldProgress.innerHTML = divProgressBar.outerHTML + " " + gprogress + "%";
}
else
{
fldProgress.innerHTML = divProgressBar.outerHTML;
divProgressBar.innerHTML = gprogress + "%";
}
divProgressBar.style.width = gprogress + "%";
}
function startGame()
{
if (parseInt(selRows.value) * parseInt(selCols.value) < 4)
{
alert("Sorry. At least 4 pieces are needed for a proper jigsaw game!\n\n" +
' No. of Jigsaw Pieces = Rows X Cols\n\n' +
"Please try increasing the 'Rows' and/or 'Cols'.");
return;
}
stopTimer();
stopPicTimer();
gtime = 0;
gmoves = 0;
gactive = true;
drawBoard() ;
divMain.style.display = "none";
divInfo.style.display = "none";
shuffle();
tickTime();
gintervalid = setInterval("tickTime()",1000);
}
function tickTime()
{
showProgress();
gtime++;
}
function isWin()
{
var i, j, divisionsX, divisionsY, obj,s="", prog=0;
divisionsX = parseInt(selCols.value);
divisionsY = parseInt(selRows.value);
for (i=0;i<divisionsY;i++)
for (j=0;j<divisionsX;j++)
{
obj = getPiece(i,j);
if (obj.style.pixelLeft != 0 || obj.style.pixelTop != 0) prog++;
}
gprogress = 100 - Math.round((prog * 100.0) / (divisionsX * divisionsY));
if (prog == 0)
return true;
else
return false;
}
function restartGame()
{
stopTimer();
gtime = 0;
gmoves = 0;
getPiece(0,0).style.clip = "rect(1," + gdx + "," + gdy + ",1)" ;
shuffle();
tickTime();
gintervalid = setInterval("tickTime()",1000);
butPause.value = "Pause Game";
butPause.disabled = false;
gactive = true;
}
function pauseGame()
{
if (butPause.value == "Pause Game" && gactive)
{
butPause.value = "Continue Game";
gactive = false;
stopTimer();
}
else
{
butPause.value = "Pause Game";
gintervalid = setInterval("tickTime()",1000); //start the count again
gactive = true;
}
}
function checkSelection()
{
var obj;
switch (selPic.value)
{
case "":
divURL.style.display = "none";
divFile.style.display = "none";
divPic.style.display = "none";
butStart.disabled = true;
butLoad.disabled = true;
gloaded = false;
showStatus("<marquee width=300 loop=4>" +
"Select a Picture for the Jigsaw Puzzle from the drop down above." +
"</marquee>");
break;
case "myurl":
divURL.style.display = "block";
divFile.style.display = "none";
divPic.style.display = "none";
butStart.disabled = true;
obj = document.getElementById("fldURL");
butLoad.disabled = (obj.value == "") ? true : false;
gloaded = false;
obj.select();
obj.focus();
showStatus("Type in the URL of the Picture you wish to<br>" +
"play the Jigsaw Game with.<p>" +
"Press 'Load Picture' button when done.");
break;
case "localfile":
divURL.style.display = "none";
divFile.style.display = "block";
divPic.style.display = "none";
butStart.disabled = true;
obj = document.getElementById("fldFile");
butLoad.disabled = (obj.value == "") ? true : false;
gloaded = false;
obj.select();
obj.focus();
showStatus("Type in the Path to a Picture file (JPG,GIF,BMP,PNG)<br>" +
"OR use the 'Browse' button to locate a file in your<br>" +
"machine or on a shared network drive.<p>" +
"Press the 'Load Picture' button when done.");
break;
default:
divURL.style.display = "none";
divFile.style.display = "none";
divPic.style.display = "none";
butStart.disabled = true;
butLoad.disabled = false;
butLoad.focus();
gloaded = false;
selPic.disabled = true;
checkPicture();
}
}
function checkPicture()
{
var picsrc, picurl, retval, re, re2;
stopPicTimer();
butStart.disabled = true;
if (butLoad.value == "Cancel Loading")
{
selPic.disabled = false;
butLoad.value = "Load Picture";
divPic.style.display = "none";
showStatus("<marquee width=300 loop=4>" +
"Select a Picture for the Jigsaw Puzzle from the drop down above." +
"</marquee>");
return;
}
switch (
|