The Windows only game is based on LodeRunner.....Collect diamonds whilst traversing ladders and avoiding three meanies. The only advantage you have is you can fall off ladders, they can't.
Embedded graphics,
Seeded levels (-99999999 to 999999999),
Sound work around,
Smooth and well balanced game play. Nice and fair collisions.
Only 3 Pages!
OK, copy this to a text file and rename it to "game.HTA". Place this in a new folder (it unpacks graphics wherever it is ran from). Double click and play! (Cursor keys)
Code: Select all
<HTML><HEAD><TITLE>Ladders'n'Things By Alan Bond</TITLE>
<HTA:application id="frmMain" singleinstance="yes" showintaskbar="yes" maximizeButton="no"
minimizeButton="no" border="thin" navigable="yes" windowState="normal" contextmenu="no"/>
<SCRIPT language="VBScript"> Option Explicit
Dim gfx,MainLoopRunner,tts,Fav,DmdCount,PH,PV,P1,P2,KDX,KDY,FSO,StrPath
Dim map(17,16),DMD(17,16),Mov(3),DX(3),DY(3),MT(3),Pulse(3),PU(3)
gfx = Array ("202020FF040404FF","80AAD4AAD4AAD4FF","8888F888888F8888","0202FF2020FF0202","007E425A5A427E00", _
"9942249999244299","DD007700DD007700","FF55AA000055AAFF","44FF1111FF444444","83070E1C3870E0C1", _
"3C04043C3C04043C", "7E007E7E7E007E7E","E781E7E7E781E7E7","BDBD81BDBDBD81BD","E7E4E5E127A787E7", _
"812400423C000081","81001200211E0081","81002400423C0081","8100480084780081","8100002400423C81","812424003C420081", _
"810066000024247E","9900426600813C7E","C3811824241881C3","BD185ABDC3811881","995A3CE7E73C5A99", _
"81240081E7E7C381","99004224810066BD","8124005A7E5A0081","DB99810024003C81","6642812400994266", _
"FFF7EBC580C1E3F7","FFE3C5828280C1E3","FFF7EBC9B6C9EBF7","FFFFFFE3C58280C1","FFF7DDE3A2E3DDF7")
Fav = Array (0,82,83,102,223,229,1433,2331,3233,5394,5422,6578,6784,10343,13331,15901,32388,52421)
Set tts = Nothing:Set tts = CreateObject("Sapi.SpVoice"):Set tts.Voice = tts.GetVoices.Item(0)
Sub Window_OnLoad
dim L,G,S,fs,ts,opt:Self.Resizeto 522,548:Self.Moveto (screen.width/2)-261,(screen.height/2)-266
Set FSO = CreateObject("Scripting.FileSystemObject")
strPath=FSO.GetFolder("."):if right(StrPath,1)<>"\" then strPath=StrPath & "\"
For G = 0 to ubound(Gfx)
S="#define XBM_width 8" & vbcrlf & "#define XBM_height 8" & vbcrlf & "static char XBM_bits[]={"
For L = 1 to len(gfx(G)) Step 2:S=S & "0x" & Mid(gfx(G),L,2) & ",":Next
S=S & "};":Set ts = FSO.OpenTextFile(StrPath & "G" & G & ".XBM", 2, True):ts.Write(S):ts.Close
Next
For L = 0 to ubound(Fav):Set opt=Document.createElement("OPTION")
opt.Text=Fav(L):opt.value=Fav(L):cmbBox.Add(opt):next:PlayGame()
End Sub
Sub MakeLevel()
Dim X,Y,H1,H2,L1,L2,E:Rnd(-1):Randomize htmLVL.value:DmdCount=0
For Y=0 to 16:For X=0 to 17
if y<>0 and y<>16 and x<>0 and x<>17 then map(x,y)=0 else map (x,y)=1 end if
next:next
For Y=2 to 14 step 2
For X=1 to 16:map(x,y)=1:next
H1=rand(4,7):map(H1,Y)=0:H2=rand(9,13):map(H2,Y)=0:select case rand(0,2)
case 0:For X=1 to H1:map(x,y)=0:next:L1=rand(H1,H2):L2=rand(H2,16)
case 1:For X=H1 to H2:map(x,y)=0:next:L1=rand(1,3):L2=rand(H2,16)
case 2:For X=H2 to 16:map(x,y)=0:next:L1=rand(1,3):L2=rand(H1,H2)
end select:Map(L1,Y)=2:Map(L2,Y)=2
next
For Y=1 to 15:For X=1 to 16
If map(X,Y)=2 and map(X,Y+1)=0 then map(X,Y+1)=2
If map(X,Y)=1 and map(X,Y-1)=0 and Rand(0,1)=0 and y>2 then map(X,Y-1)=3:DmdCount=DmdCount+1
Next:Next
Do While E<3:X=rand(1,16):if map (X,2)<>0 and map(X,1)=0 then map(X,1)=4:E=E+1
loop
Do While E<4:X=rand(1,16):if map (X,15)=0 then map(X,15)=5:E=E+1
loop
End Sub
Sub DrawLevel()
Dim X,Y,S,Gr,Col,WCol,LCol,DCol,ECol,YCol,I,M,WGr,LGr,DGr,EGr
WCol=RandC(40,180):LCol=RandC(40,200):DCol=RandC(160,255):ECol=RandC(90,200):YCol=RandC(80,200)
WGr=Rand (0,9):LGr=Rand(10,14):EGr=Rand(21,30):DGr=Rand(31,35)
For Y=1 to 15:For X=1 to 16:Select case map(X,Y)
Case 0:Gr=-1
Case 1:Gr=WGr:Col=WCol
Case 2:Gr=LGr:Col=LCol
Case 3:Gr=DGr:Col=DCol:DMD(X,Y)=I
Case 4:Gr=EGr:Col=ECol:Mov(M)=I:M=M+1:Map(X,Y)=0
Case 5:Gr=5:Col=YCol:Mov(M)=I:M=M+1:Map(X,Y)=0
End Select
if Gr<>-1 then s=s & "<img src='G" & Gr & ".XBM' width=32 height=32 style='position:absolute; left:" & _
(X-1)*32 & ";top:" & (Y-1)*32 & ";background-color:#" & Col & "'>":I=I+1
Next:Next:htmViewport.innerhtml=S
PH=rand(0,1):PV=rand(0,1):P1=rand(15,25):P2=rand(26,35):if PV=0 and PH=0 then PV=1
For X = 0 to 3:document.images(Mov(X)).style.zIndex=1000-X:MT(X)=0:DX(X)=0:DY(X)=0:Pulse(X)=P1+1:PU(X)=RandD():next
End Sub
Sub MainLoop()
Dim L,MX,MY,X,Y,YX,YY
YX=document.images(Mov(3)).style.pixelleft
YY=document.images(Mov(3)).style.pixeltop
For L =0 to 3:X=document.images(Mov(L)).style.pixelleft:Y=document.images(Mov(L)).style.pixeltop
MT(L)=MT(L)-1:if MT(L)<=0 then
MT(L)=32:MX=cint(X/32)+1:MY=cint(Y/32)+1
If L=3 then
DX(L)=KDX:Select case map(MX,MY+1)
Case 0,3:DY(L)=1:DX(L)=0
Case 2:DY(L)=KDY:if map(MX,MY)=0 and DY(L)=-1 then DY(L)=0
Case Else:If DY(L)<>0 then tts.speak"xxe",1:DY(L)=0
end select:If map(MX+DX(L),MY)=1 then DX(L)=0
Select Case map(MX,MY)
Case 2:DY(L)=KDY:if KDY=1 and map(MX,MY+1)<>2 then DY(L)=0
Case 3: tts.Speak "umm",1:Map(MX,MY)=0:DmdCount=DmdCount-1
document.images(DMD(MX,MY)).style.pixeltop=-800
If DmdCount=<0 then
tts.speak "iqqqqqqqqqqqqqqq":htmLVL.value = htmLVL.value + 1
window.clearInterval(MainLoopRunner):PlayGame():Exit sub
End If
End Select
document.images(Mov(L)).src= "G" & ((DY(L)*2) + DX(L)+2)+15 & ".XBM"
else
IF DX(L)<>0 then
If map(MX,MY+1)=2 and YY>Y then DY(L)=sgn(YY-Y):DX(L)=0
If map(MX,MY)=2 then DY(L)=sgn(YY-Y):DX(L)=0
If map(MX,MY+DY(L))=1 then DX(L)=RandD():DY(L)=0
If map(MX,MY)=0 and DY(L)=-1 then DX(L)=RandD():DY(L)=0
If map(MX+DX(L),MY)=1 then DX(L)=-DX(L):DY(L)=0
else
If map(MX,MY)=0 or map(MX,MY+DY(L))=1 then DX(L)=RandD():DY(L)=0
If DY(L)=0 and DX(L)=0 then DX(L)=RandD():DY(L)=0
If map(MX+DX(L),MY)=1 then DX(L)=-DX(L):DY(L)=0
End if
If map(MX,MY+1)=0 or map(MX,MY+1)=3 then DX(L)=0:DY(L)=1
end if
end if
If L<>3 then
If (ABS(YY-Y)<26 and ABS(YX-X)<26) then
document.images(Mov(3)).src= "G20.XBM":tts.Speak "uxxxxxxx",1
window.clearInterval(MainLoopRunner):document.images(Mov(3)).style.backgroundcolor="red"
End If
If PH=1 then document.images(Mov(l)).style.width=Pulse(L)
If PV=1 then document.images(Mov(l)).style.height=Pulse(L)
Pulse(L)=Pulse(L)+PU(L):If Pulse(L)=<P1 or Pulse(L)=>P2 then PU(L)=-PU(L)
End If
document.images(Mov(L)).style.pixelleft = X + DX(L):document.images(Mov(L)).style.pixeltop = Y + DY(L)
Next
End Sub
sub document_onkeydown()
select case window.event.Keycode
case 38:KDY=-1:KDX=0
case 40:KDY=1:KDX=0
case 37:KDX=-1:KDY=0
case 39:KDX=1:KDY=0
end select
end sub
sub document_onkeyup()
select case window.event.Keycode
case 38:if KDY<>1 then KDY=0
case 40:if KDY<>-1 then KDY=0
case 37:if KDX<>1 then KDX=0
case 39:if KDX<>-1 then KDX=0
end select
end sub
Function Rand(Lo,Hi):Rand=Int((hi-lo+1)*Rnd+lo):end function
Function RandC(Lo,Hi)
Dim L,S,V:For L = 0 to 2:V=Hex(rand(Lo,Hi)):if len(V)=1 then V="0" & V
RandC=RandC & V:next
end function
Function RandD():RandD=Int(rnd(1)*2)-1:if RandD=0 then RandD=1
end function
Sub PlayGame()
tts.Speak "ihhhhhhhhhhhhh",1:window.clearInterval(MainLoopRunner):MakeLevel:DrawLevel
MainLoopRunner = window.setInterval ("MainLoop", 1)
End Sub
Sub CLevel(LAdd):htmLVL.value=htmLVL.value+LAdd:PlayGame():End Sub
Sub cmbSel():htmLVL.value=cmbBox.value:PlayGame():end sub
</SCRIPT>
<BODY scroll="no" BGColor=buttonface style="margin:0px;font-family:Arial;font-size:12PX">
<INPUT type="button" value="Play" onClick="PlayGame()" style="Width:100;Height:40"/>
<DIV STYLE="position:absolute;left:190;top:0">Level<BR>
<INPUT type="button" value="<" onClick="CLevel(-1)" style="Width:25;">
<INPUT type="text" ID="htmLVL" value="1" MAXLENGTH="9" style="Width:75;">
<INPUT type="button" value=">" onClick="CLevel(1)" style="Width:25;"></DIV>
<DIV STYLE="position:absolute;left:450;top:0">Favorites<BR><select size="1" ID="cmbBox" onchange="cmbSel()"></select></DIV>
<DIV ID="htmViewport" STYLE="position:absolute;left:0;top:40;width:512;height:480;background-color:#000000;">
</BODY></HTML>
Graphics
I use XBM. A very old format that I have to admit I have never used! It is handy for scripts however. They remind me of the Sinclair Spectrum's UDGs (User defined graphics). They look like this in a text editor:-
Code: Select all
#define XBM_width 8
#define XBM_height 8
static char XBM_bits[]={0x20,0x20,0x20,0xFF,0x04,0x04,0x04,0xFF,};
The big drawback is they are only one colour..They have no background either (and so where used for cursors). Even worse you can't set the colour anywhere, it has to be black. But I defined all the graphics reversed and used the background of each one as the colour.

Oh, and to save room I made all the graphics 8x8, but since they're HTML IMG's I can scale them up. They look very pixilated though (who cares?). Also to save more room I animated the meanies by stretching them, it looks pretty good sometimes!
Levels
I am really happy with the level algorithm. It was my 1st attempt at a level like this and it worked 1st go! It never makes islands and you can get to every platform. Here's what I did:-
1. Draw 7 lines of bricks across the map horizontally....always in the same place.
2. Randomly wipe two bricks on the left side and right, this leaves us with 3 platforms per line.
3. Randomly wipe one platform, put "ladder-tops" randomly on the remaining two platforms.
4. Now scan through the map, project any ladder-top down (if room).
And it seems to work 100%

Sounds
I abused Microsoft SAM

I first thought I could make sounds by making him say odd words like:- "mmmmmm" but instead he actually says the letters like this:- "em,em,em,em,em,em", which is silly. But I found you can "crash" SAM by placing odd letters at the start or end like this:- "uxxxxxxx" This is the closest to an explosion sound as I could get!

Have fun!