My take on Snake

Post gaming related scripts
User avatar
maestrith
Posts: 825
Joined: 16 Oct 2013, 13:52

My take on Snake

24 Aug 2017, 17:34

I got bored and decided to write a version of Snake.
Hope someone finds it fun or interesting.
I am sorry but this code requires Windows 7+ and IE 11+ to run properly.

Code: Select all

#SingleInstance,Force
global wb,Main,IE,Snake
SetBatchLines,-1
Gui,+hwndMain
Gui,Margin,0,0
new Settings()
Snake:=new SnakeClass(),Snake.Stop:=0
Settings.Show()
Gui,Show,,Snake
Sleep,100
return
Start(){
	Snake:=new SnakeClass(),Snake.Stop:=0
	Snake.Sleep:=100
	Guicontrol,+Redraw,%IE%
	Snake.BodyLength:=Settings.SSN("//Snake/@Length").text-1,Snake.AddBody(),Snake.ShowScore()
	Snake.Move(1)
}
return
+Escape::
Settings.Save()
ExitApp
return
Settings(){
	Input:=Snake.Doc.GetElementById("Input")
	if(!Input)
		Input.Value:=4
	Vis:=Snake.Settings.Style.Visibility
	if(Vis="Visible"){
		Snake.Settings.Style.Visibility:="Hidden"
		SetTimer,Start,-1
		New Settings()
	}else{
		Settings.Show(),Snake.Move()
	}
}
GuiClose:
Settings.Save()
ExitApp
return
Movement(){
	static Problem:={S:"N",N:"S",E:"W",W:"E"},Direction:={Up:"N",Down:"S",Left:"W",Right:"E"}
	Left:
	Right:
	Up:
	Down:
	D:=Direction[A_ThisLabel]
	if(Snake.MoveQueue.1){
		Queue:=Snake.MoveQueue[Snake.MoveQueue.MaxIndex()]
		if(Problem[Queue]!=D)
			Snake.MoveQueue.Push(D)
	}else if(Problem[D]!=Snake.Direction&&D!=Snake.Direction){
		Snake.MoveQueue.Push(D),LastDirection:=Direction
		total:=""
		for a,b in Snake.MoveQueue
			total.=b "`n"
	}
	return
}
m(x*){
	for a,b in x
		msg.=b "`n"
	MsgBox,,Snake,%msg%
}
t(x*){
	for a,b in x
		msg.=b "`n"
	ToolTip,%msg%
}
FixIE(Version=0){
	static Key:="Software\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION",Versions:={7:7000,8:8888,9:9999,10:10001,11:11001}
	Version:=Versions[Version]?Versions[Version]:Version
	if(A_IsCompiled)
		ExeName:=A_ScriptName
	else
		SplitPath,A_AhkPath,ExeName
	RegRead,PreviousValue,HKCU,%Key%,%ExeName%
	if(!Version)
		RegDelete,HKCU,%Key%,%ExeName%
	else
		RegWrite,REG_DWORD,HKCU,%Key%,%ExeName%,%Version%
	return PreviousValue
}
Class SnakeClass{
	__New(){
		static init
		if(!init){
			Default:=FixIE(12)
			Gui,Add,ActiveX,% "vwb w" Settings.BoardWidth " h" Settings.BoardHeight " hwndIE",mshtml
			init:=1,FixIE(Default)
		}wb.Navigate("about:<html><script>onerror=function(event){return true;};onmessage=function(event){return false;};onclick=function(event){ahk_event('OnClick',event);};onchange=function(event){ahk_event('OnChange',event);};oninput=function(event){ahk_event('OnInput',event);};onprogresschange=function(event){ahk_event('OnProgressChange',event);};</script><body style='background-color:Black;margin:0px;'><div id='Settings' Style='Visibility:Hidden'></div><svg></svg></body></html>")
		while(wb.ReadyState!=4)
			Sleep,10
		this.IE:=wb,this.IE.Document.ParentWindow.ahk_event:=Settings._Event.Bind(Settings),this.Doc:=this.IE.Document
		this.Body:=[],this.Taken:=[],this.AppleVis:=this.Score:=this.Length:=0,this.MoveQueue:=[]
		this.Settings:=this.Doc.GetElementById("Settings"),this.Difficulty:=10,this.Init:=1,this.Direction:="W"
		this.svg:=wb.Document.GetElementsByTagName("svg").item[0],this.Shape:="Rectangle",defs:=this.Doc.CreateElementNS("http://www.w3.org/2000/svg","defs")
		Rad:=this.Doc.CreateElementNS("http://www.w3.org/2000/svg","radialGradient")
		for a,b in {id:"grad2"}
			Rad.SetAttribute(a,b)
		for a,b in [{offset:"0%","stop-color":RGB(Settings.Body1)},{offset:"95%","stop-color":RGB(Settings.Body2)}]{
			Stop:=this.Doc.CreateElementNS("http://www.w3.org/2000/svg","stop")
			for c,d in b
				Stop.SetAttribute(c,d)
			Rad.AppendChild(Stop)
		}defs.AppendChild(Rad),this.SVG.AppendChild(Defs),this.AppleObj:=wb.Document.CreateElementNS("http://www.w3.org/2000/svg","circle")
		for a,b in {r:Settings.Size/2,fill:"Red",cx:0,cy:0,visibility:"hidden",stroke:"black"}
			this.AppleObj.SetAttribute(a,b)
		this.svg.AppendChild(this.AppleObj)
		return this
	}
	AddBody(){
		Shape:=this.Shape="Rectangle"?"rect":"circle",rect:=wb.Document.CreateElementNS("http://www.w3.org/2000/svg",Shape),this.svg.AppendChild(rect)
		if(!this.Body.1){
			x:=Floor((Width:=(Settings.BoardWidth-Settings.Size)/2)+Mod(Width,Settings.Size)),y:=Floor((Height:=(Settings.BoardHeight-Settings.Size)/2)+Mod(Height,Settings.Size)),rect.ID:="Head"
			New.SetAttribute("id","head")
		}else
			obj:=this.Body[this.Body.MaxIndex()],x:=obj.x,y:=obj.y
		this.Body.Push({rect:rect,x:x,y:y,xml:New})
		if(!this.Gradient){
			Colors:=[]
			for a,Fill in [Settings.Body1,Settings.Body2]{
				for a,b in {R:Fill&0xFF,G:(Fill&0x00FF00)>>8,B:Fill>>16}{
					if(!IsObject(Obj:=Colors[a]))
						Obj:=Colors[a]:=[]
					Obj[b]:=1
				}
			}Fill:=0
			for a,b in Colors{
				Random,Color,% b.MinIndex(),% b.MaxIndex()
				if(a="R")
					Fill|=Color
				if(a="G")
					Fill|=Color<<8
				if(a="B")
					Fill|=Color<<16
			}Fill:=RGB(this.Init?Settings.SSN("//Snake/@Head").text:Fill),this.Init:=0
		}else
			Fill:=this.Init?RGB(Settings.SSN("//Snake/@Head").text):"url(#grad2)",this.Init:=0
		obj:=this.Shape="Rectangle"?{x:0,y:0,width:Settings.Size,height:Settings.Size,stroke:"black",fill:Fill,transform:"translate(" x "," y ")"}:{cx:0,cy:0,r:Settings.Size/2,stroke:"black",fill:Fill,transform:"translate(" x "," y ")"}
		for a,b in obj
			Rect.SetAttribute(a,b)
		Head:=Snake.Doc.GetElementById("Head"),Head.ParentNode.AppendChild(Head)
		/*
			create a color cycling option to go with this one
			Red, Blue, Red, Blue and so on.
		*/
	}
	Apple(){
		pos:=this.Random(),x:=pos.x,y:=pos.y,SnakePos:=Snake.Body.1,StartX:=x,StartY:=y
		while(this.Taken[x,y]||(SnakePos.x=x&&SnakePos.y=y)){
			x:=x>=Settings.BoardWidth-Settings.Size?0:x+Settings.Size
			if(x=StartX)
				y:=y>=Settings.BoardHeight-Settings.Size?0:y+Settings.Size
			if(x=StartX&&y=StartY){
				m("All spaces taken",A_Index)
				this.Stop:=1
				SetTimer,Start,-100
				return
		}}this.AppleX:=x,this.AppleY:=y,Style:=this.AppleObj.Style
		if(Style.Visibility!="Visible")
			Style.visibility:="Visible"
		this.AppleObj.SetAttribute("transform","translate(" this.AppleX+Settings.Size/2 " " this.AppleY+Settings.Size/2 ")"),this.AppleVis:=1
	}
	Move(Start:=0){
		if(Start){
			SetTimer,Move,1
			return
			Index:=0
			Move:
			if(Snake.AppleObj.Style.Visibility!="Visible")
				Snake.Apple()
			if(Snake.BodyLength)
				Snake.AddBody(),Snake.BodyLength--,Snake.ShowScore()
			if(Direction:=Snake.MoveQueue.RemoveAt(1))
				Snake.Direction:=Direction
			if(Snake.Direction~="(E|W)")
				AddX:=Snake.Direction="E"?Settings.Size:-Settings.Size,AddY:=0
			else
				AddY:=Snake.Direction="N"?-Settings.Size:Settings.Size,AddX:=0
			Total:=all.Length,Tick:=A_TickCount,total:="",max:=Snake.Body.MaxIndex()
			Loop,%Max%{
				Current:=Max-(A_Index-1),b:=Snake.Body[Current],a:=Snake.Body[Current-1]
				if(Current=1)
					b.x+=AddX,b.y+=AddY,b.x:=b.x<0?Settings.BoardWidth-Settings.Size:b.x>=Settings.BoardWidth?0:b.x,b.y:=b.y<0?Settings.BoardHeight-Settings.Size:b.y>=Settings.BoardHeight?0:b.y,b.x:=Floor(b.x),b.y:=Floor(b.y)
				else
					Snake.Taken[b.x:=a.x,b.y:=a.y]:=1
				b.rect.SetAttribute("transform","translate(" (Snake.Shape="Rectangle"?b.x:b.x+(Settings.Size/2)) " " (Snake.Shape="Rectangle"?b.y:b.y+(Settings.Size/2)) ")")
			}Elapsed:=A_TickCount-Tick
			if((Sleep:=Snake.Sleep-Elapsed)>0&&!GetKeyState(Settings.Zoom,"P"))
				Sleep,%Sleep%
			if(Snake.AppleX=b.x&&Snake.AppleY=b.y){
				Snake.Score++,Snake.Apple(),Snake.AddBody(),Snake.ShowScore()
			}if(Snake.Taken[b.x,b.y]&&!Settings.Zen){
				MsgBox,20,Snake,% "Game Over`n`nScore: " Snake.Score "`n`nPlay Again?"
				IfMsgBox,Yes
				{
					this.Stop:=1
					Start()
					return
				}else
					ExitApp
			}Snake.Taken:=[]
			if(Snake.Stop)
				SetTimer,Move,Off
			return
		}else
			SetTimer,Move,Off
	}
	Random(){
		x:=Floor((Settings.BoardWidth-Settings.Size)/Settings.Size),y:=Floor((Settings.BoardHeight-Settings.Size)/Settings.Size)
		Random,x,0,%x%
		Random,y,0,%y%
		return {x:x*Settings.Size,y:y*Settings.Size}
	}
	ShowScore(){
		WinSetTitle,ahk_id%Main%,,% "Snake: Score " this.Score " Length: " this.Body.MaxIndex() " Mode: " (Settings.Zen?"Zen":"Normal")
	}
}
Class Settings{
	_Event(Name,Event){
		static
		Node:=Event.srcElement,Node:=Node.NodeName="Div"?Node:Node.ParentNode
		if(Name="OnChange"){
			if(Select:=Node.GetElementsByTagName("select").Item[0]){
				if(InStr(Select.ID,"Board")){
					Settings.SSN("//Board/@" Select.ID).text:=Select.Value
					ea:=Settings.EA("//Board")
					Gui,Show,% "w" ea.BoardWidth " h" ea.BoardHeight " Center"
					GuiControl,Move,%IE%,% "w" ea.BoardWidth " h" ea.BoardHeight
					Settings.Update(),Settings.Show()
				}else{
					Settings.SSN("//Snake/@Size").text:=Select.Value,Settings.Update()
				}
			}
		}
		else if(Name="OnClick"){
			if(ID:=Node.ID){
				if(ID="ZenObj")
					Settings.Zen:=1,Node.Style.Color:="Blue",Settings.Normal.Style.Color:="Grey",Settings.SSN("//Snake").SetAttribute("Zen",1)
				else if(ID="Normal")
					Settings.Zen:=0,Node.Style.Color:="Blue",Settings.ZenObj.Style.Color:="Grey",Settings.SSN("//Snake").SetAttribute("Zen",0)
				else if(ID~="(Head|Body1|Body2)"){
					Color:=Dlg_Color(Settings[ID],Main)
					Node.Style.Color:=RGB(Color)
					Settings.SSN("//Snake/@" ID).text:=Color
				}else if(ID~="(Up|Down|Left|Right|Zoom|Settings)"){
					static Hotkey
					Text:=Node.OuterHtml
					Gui,2:Destroy
					Gui,2:Default
					Gui,Color,0,0
					Gui,Add,Hotkey,w200 vHotkey c0xAAAAAA,% Settings[ID]
					Gui,Add,Edit,gUpdateHotkey vHK w200 c0xAAAAAA
					Gui,Add,Button,gSetHotkey Default,Set Hotkey
					Gui,Show
					return
					UpdateHotkey:
					Gui,2:Submit,Nohide
					GuiControl,2:,msctls_hotkey321,%HK%
					return
					SetHotkey:
					Gui,2:Submit,Nohide
					Gui,2:Destroy
					if(!Hotkey)
						return
					StringUpper,Hotkey,Hotkey,T
					Settings.SSN("//Controls/@" ID).text:=Hotkey
					Node.OuterHtml:=SubStr(Text,1,InStr(Text,">",0,0,3)) Hotkey SubStr(Text,InStr(Text,"<",0,0,2))
					Settings.Update()
					return
				}else if(ID="Size")
					Settings.SSN("//Snake/@Size").text:=Node.Value,Settings.Update()
				else
					MsgBox,% "Coming Soon..." ID
				Settings.Update()
			}
		}else if(Name="OnInput"){
			Input:=Snake.Doc.GetElementById("Input"),Selection:=Input.SelectionStart
			Input.Value:=RegExReplace(Input.Value,"\D",,Count)
			if(Count)
				Input.SelectionStart:=Selection-1,Input.SelectionEnd:=Selection-1
			if(Input.Value>500)
				Input.Value:=500
			if(Input.Value)
				Settings.SSN("//Snake/@Length").text:=Input.Value
			Settings.Update()
		}else if(Name="OnSelect"){
			m("YAY")
		}
		Snake.Doc.GetSelection().RemoveAllRanges()
	}__New(){
		if(!IsObject(Settings.XML)){
			XML:=Settings.XML:=ComObjCreate("MSXML2.DOMDocument"),XML.SetProperty("SelectionLanguage","XPath")
			(FileExist("Settings.xml"))?XML.Load("Settings.xml"):XML.AppendChild(Settings.CreateElement("Settings"))
		}this.Update()
	}Add(XPath,Att:="",Text:="",Dup:=0){
		Obj:=StrSplit(XPath,"/")
		if(!Node:=Settings.SSN("//" XPath)){
			for a,b in Obj
				(!Exist:=Settings.SSN("//" Trim(Build.=b "/","/")))?(Node:=(A_Index=1?Settings.SSN("//*"):Node).AppendChild(Settings.CreateElement(b))):(Node:=Exist)
		}else if(Dup)
			Node:=Node.ParentNode.AppendChild(Settings.CreateElement(Obj.Pop()))
		for a,b in Att
			Node.SetAttribute(a,b)
		if(Text)
			Node.Text:=Text
		return Node
	}CreateElement(Node){
		return Settings.XML.CreateElement(Node)
	}Div(Parent,Width,Height,MarginLeft,MarginTop,Border:="1px Solid Blue",Radius:=4){
		Div:=Snake.Doc.CreateElement("div"),Style:=Div.Style
		for a,b in {Width:Width,Height:Height,BorderRadius:Radius "px",Border:Border,Display:"Block",VerticalAlign:"Middle",TextAlign:"Center",MarginLeft:MarginLeft,MarginTop:MarginTop,Float:"Left",LineHeight:"10px"}
			Style[a]:=b
		Parent.AppendChild(Div)
		return Div
	}EA(Node){
		Obj:=[],all:=Node.NodeName?Node.SelectNodes("@*"):Settings.SN(Node "/@*")
		while(aa:=all.item[A_Index-1])
			Obj[aa.NodeName]:=aa.Text
		return Obj
	}Hotkey(){
		Hotkey:
		Action:=Settings.SSN("//Controls/@*[.='" A_ThisHotkey "']").NodeName
		if(IsLabel(Action))
			SetTimer,%Action%,-1
		else if(IsFunc(Action))
			%Action%()
		return
	}Hotkeys(Enable:=1){
		static
		for a,b in LastHotkeys
			Hotkey,%b%,Hotkey,Off
		LastHotkeys:=[]
		Hotkey,IfWinActive,ahk_id%main%
		all:=Settings.SN("//Controls/@*")
		while(aa:=all.item[A_Index-1]){
			Hotkey,% aa.text,Hotkey,% Enable?"On":"Off"
			LastHotkeys[aa.NodeName]:=aa.text
		}
	}P(Parent,InnerHtml,StyleObj){
		Item:=Snake.Doc.CreateElement("p"),Item.InnerHtml:=InnerHtml,Parent.AppendChild(Item),Style:=Item.Style
		for a,b in StyleObj
			Style[a]:=b
		return Item
	}Save(){
		static
		if(!IsObject(xsl))
			xsl:=ComObjCreate("MSXML2.DOMDocument"),xsl.loadXML("<xsl:stylesheet version=""1.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform""><xsl:output method=""xml"" indent=""yes"" encoding=""UTF-8""/><xsl:template match=""@*|node()""><xsl:copy>`n<xsl:apply-templates select=""@*|node()""/><xsl:for-each select=""@*""><xsl:text></xsl:text></xsl:for-each></xsl:copy>`n</xsl:template>`n</xsl:stylesheet>")
		Settings.XML.TransformNodeToObject(xsl,Settings.xml),Settings.XML.Save(A_ScriptDir "\Settings.xml")
	}Show(){
		static Obj:=[]
		Win:=Snake.Settings,Win.Style.Visibility:="Visible"
		Try
			if(Things:=Snake.Doc.GetElementById("Things"))
				Things.ParentNode.RemoveChild(Things)
		Things:=Snake.Doc.CreateElement("div"),Things.ID:="Things",Win.AppendChild(Things)
		Width:=Floor(Settings.BoardWidth/5)
		TotalHeight:=40+200+100+40
		Spacing:=Floor((Settings.BoardHeight-TotalHeight)/7)
		for a,b in [["Head Color","Head"],["Body Color 1","Body1"],["Body Color 2","Body2"]]
			p:=this.P(this.Div(Things,Width,40,((Width/2)),Spacing,,15),"<u>" b.1 "</u>",{Color:RGB(Settings.SSN("//Snake/@" b.2).text),Cursor:"Hand"}),p.ID:=b.2
		Space:=Width:=Floor(Settings.BoardWidth/7)
		if(Space<125)
			Space:=Floor((Settings.BoardWidth-375)/4)
		this.P((Div:=this.Div(Things,(Width<125?125:Width),200,Space,Spacing,,20)),"Controls:",{Color:"Red"})
		for a,b in Settings.EA("//Controls")
			this.P(Div,a " - <u style='Cursor:Hand'>" b "</u>",{Color:"White"}).ID:=a
		this.P((Div:=this.Div(Things,(Width<125?125:Width),200,Space,Spacing,,20)),"Board Width:",{Color:"Red"})
		Select:=Snake.Doc.CreateElement("select"),Select.ID:="BoardWidth"
		ww:=400,hh:=400
		Div.AppendChild(Select),Select.Size:=9,Select.Style.BackgroundColor:="Black",Select.Style.Color:="White"
		while((ww+=100)<A_ScreenWidth){
			Option:=Snake.Doc.CreateElement("option"),Select.AppendChild(Option),Option.InnerHtml:=ww
			Option.SetAttribute("onchange","onchange()")
			if(ww=Settings.BoardWidth)
				Option.Selected:=1
		}
		this.P((Div:=this.Div(Things,(Width<125?125:Width),200,Space,Spacing,,20)),"Board Height:",{Color:"Red"})
		Select:=Snake.Doc.CreateElement("select"),Select.ID:="BoardHeight"
		Div.AppendChild(Select),Select.Size:=9,Select.Style.BackgroundColor:="Black",Select.Style.Color:="White" ;,Select.Style.Height:=80
		while((hh+=100)<A_ScreenHeight){
			Option:=Snake.Doc.CreateElement("option"),Select.AppendChild(Option),Option.InnerHtml:=hh
			Option.SetAttribute("onchange","onchange()")
			if(hh=Settings.BoardHeight)
				Option.Selected:=1
		}Width:=Floor(Settings.BoardWidth/5),this.P((Div:=this.Div(Things,Width*2,120,Width/3,Spacing,,20)),"Game Type:",{Color:"Red"})
		for a,b in {Normal:"Normal",ZenObj:"Zen - Can Not Lose"}
			(Settings[a]:=this.P(Div,"<u>" b "</u>",{Color:((Settings.Zen&&a="ZenObj")||(!Settings.Zen&&a="Normal")?"Blue":"Grey"),Cursor:"Hand"})).ID:=a
		this.P((Div:=This.Div(Things,Width*2,120,Width/3,Spacing,,20)),"Snake:",{Color:"Red"})
		(Settings.Length:=this.P(Div,"Snake Length: <input id='Input' type='text' style='width:50;color:grey;background-color:black;' value='" Settings.SSN("//Snake/@Length").text "' autofocus/>",{Color:"White"}))
		Size:=this.P(Div,"Snake Size: ",{Color:"White"}),Select:=Snake.Doc.CreateElement("select"),Select.ID:="Size",Size.AppendChild(Select),Sizes:={(Settings.BoardWidth):1,(Settings.BoardHeight):1}
		while((Index:=A_Index+9)<=Sizes.MinIndex()-1){
			if(!Mod(Sizes.MinIndex(),Index)&&!Mod(Sizes.MaxIndex(),Index)){
				Option:=Snake.Doc.CreateElement("option"),Option.InnerHtml:=Index,Select.AppendChild(Option)
				if(Index=Settings.Size)
					Option.Selected:=1
			}
		}Width:=Floor(Settings.BoardWidth/3),this.P(this.Div(Things,Width<200?200:Width,40,Width<200?(Settings.BoardWidth-200)/2:Width,Spacing,,10),"Press the Settings Key to Start",{Color:"White"}),Snake.Doc.GetElementById("Input").Select()
		return
	}SN(XPath){
		return Settings.XML.SelectNodes(XPath)
	}SSN(XPath,Other:=""){
		return (Other?XPath:Settings.XML).SelectSingleNode((Other?Other:XPath))
	}Update(){
		Node:=Settings.Add("Board")
		for a,b in {BoardWidth:500,BoardHeight:500}{
			if((Value:=Settings.SSN(Node,"@" a).text)<b)
				Node.SetAttribute(a,b),Value:=b
			Settings[a]:=Value
		}
		Node:=Settings.Add("Controls")
		for a,b in {Left:"Left",Right:"Right",Up:"Up",Down:"Down",Settings:"Escape",Zoom:"A"}{
			if(!Value:=Settings.SSN(Node,"@" a).text)
				Node.SetAttribute(a,b),Value:=b
			Settings[a]:=Value
		}this.Hotkeys(),Node:=Settings.Add("Snake")
		for a,b in {Length:4,Head:255,Body1:0x00FF00,Body2:0x009900,Zen:0,Size:10}{
			if(!Value:=Settings.SSN(Node,"@" a).text)
				Node.SetAttribute(a,b),Value:=b
			Settings[a]:=Value
		}
	}
}
Dlg_Color(Color,hwnd){
	static
	if !cc{
		VarSetCapacity(CUSTOM,16*A_PtrSize,0),cc:=1,size:=VarSetCapacity(CHOOSECOLOR,9*A_PtrSize,0)
		Loop,16{
			IniRead,col,Settings.ini,CustomColors,%A_Index%,0
			NumPut(col,CUSTOM,(A_Index-1)*4,"UInt")
	}}NumPut(size,CHOOSECOLOR,0,"UInt"),NumPut(hwnd,CHOOSECOLOR,A_PtrSize,"UPtr"),NumPut(Color,CHOOSECOLOR,3*A_PtrSize,"UInt"),NumPut(3,CHOOSECOLOR,5*A_PtrSize,"UInt"),NumPut(&CUSTOM,CHOOSECOLOR,4*A_PtrSize,"UPtr"),ret:=DllCall("comdlg32\ChooseColor","UPtr",&CHOOSECOLOR,"UInt")
	if(!ret)
		Exit
	Loop,16
		IniWrite,% NumGet(CUSTOM,(A_Index-1)*4,"UInt"),Settings.ini,CustomColors,%A_Index%
	Color:=NumGet(CHOOSECOLOR,3*A_PtrSize,"UInt")
	return Color
}
RGB(c){
	SetFormat,integer,H
	for a,b in [c&0xFF,(c&0x00FF00)>>8,c>>16]
		total.=Format("{:02}",SubStr(b,3))
	SetFormat,integer,D
	return "#" total
}
Last edited by maestrith on 28 Aug 2017, 21:53, edited 14 times in total.
John H Wilson III 05/29/51 - 03/01/2020. You will be missed.AHK Studio OSDGUI Creator
Donations
Discord
All code is done on a 64 bit Windows 10 PC Running AutoHotkey x32
User avatar
Masonjar13
Posts: 1555
Joined: 20 Jul 2014, 10:16
Location: Не Россия
Contact:

Re: My take on Snake

24 Aug 2017, 18:06

Nice maestrith! Because I'm the sadistic type (ever played Velocibox at 3x speed?), I added a speed modifier option. Feel free to clean it up, but seems to work well enough.

Regular (2 start length): 69 (got bored)
Speed@50 (2 start length): 45
Edit 2: Speed@10 (100): 16

Code: Select all

#SingleInstance,Force
Gui,Margin,0,0
global wb,Main,IE
Gui,+hwndMain
Hotkey,IfWinActive,ahk_id%main%
for a,b in {Left:"Left",Right:"Right",Up:"Up",Down:"Down"}
	Hotkey,%a%,%b%,On
Default:=FixIE(11)
Gui,Add,ActiveX,vwb w500 h500 hwndIE,mshtml
FixIE(Default)
Start:
wb.Navigate("about:<body style='margin:0px;background-color:#000000'>")
while(wb.ReadyState!=4)
	Sleep,200
Snake:=new SnakeClass()
Snake.Stop:=0
InputBox,Count,Snake Length,Starting Length 1-100 (Digits Only),,,,,,,,% Count?Count:4
InputBox,speedm,Snake Speed,Starting Speed 1-10 (Digits Only),,,,,,,,% speedm?speedm:0
if((Count~="\D"||ErrorLevel)||(Count<1||Count>100))
	goto,Start
if((speedm~="\D"||ErrorLevel)||(speedm<1||speedm>10))
    goto,Start
Guicontrol,+Redraw,%IE%
Loop,%Count%
	Snake.AddBody()
Snake.Speed-=speedm*10
Gui,Show
Snake.ShowScore()
Loop{
	Snake.MoveHead()
	if(Snake.Stop)
		Break
}
return
GuiClose:
ExitApp
return
Left:
Right:
Up:
Down:
Direction:={Up:"N",Down:"S",Left:"W",Right:"E"}
Snake.Direction(Direction[A_ThisLabel])
return
FixIE(Version=0){ ;Thanks GeekDude
	static Key:="Software\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION",Versions:={7:7000,8:8888,9:9999,10:10001,11:11001}
	Version:=Versions[Version]?Versions[Version]:Version
	if(A_IsCompiled)
		ExeName:=A_ScriptName
	else
		SplitPath,A_AhkPath,ExeName
	RegRead,PreviousValue,HKCU,%Key%,%ExeName%
	if(!Version)
		RegDelete,HKCU,%Key%,%ExeName%
	else
		RegWrite,REG_DWORD,HKCU,%Key%,%ExeName%,%Version%
	return PreviousValue
}
Class SnakeClass{
	__New(){
		this.SnakeBody:=[],this.Score:=0,this.Length:=0,this.MoveQueue:=[],this.Speed:=100,this.AppleOnScreen:=0
		this.AppleObj:=wb.Document.CreateElement("div"),this.Difficulty:=10
		Style:=this.AppleObj.Style
		for a,b in {width:10,height:10,Background:"Red",top:10,left:10,visibility:"hidden",position:"absolute",border:"1px solid Black"}
			Style[a]:=b
		wb.Document.Body.AppendChild(this.AppleObj)
		return this
	}
	AddBody(){
		WW := 10,HH := 10
		if(!obj:=this.SnakeBody[this.SnakeBody.MaxIndex()])
			XX := 270,YY := 230
		else
			XX:=obj.X,yy:=obj.Y
		Doc:=wb.Document
		div:=doc.CreateElement("div"),Style:=div.Style
		for a,b in {Width:"10px",Height:"10px",Background:this.length?"Green":"Purple",Position:"absolute",Left:XX,Top:YY,Border:"1px solid Black"}
			Style[a]:=b
		Doc.Body.AppendChild(div)
		this.SnakeBody[++this.Length]:={obj:div,x:XX,y:YY}
	}
	Apple(){
		Taken:=[]
		for a,b in this.SnakeBody
			Taken[b.x,b.y]:=1
		pos:=this.Random(),x:=pos.x,y:=pos.y
		while(Taken[x,y]){
			pos:=this.Random(),x:=pos.x,y:=pos.y
			ToolTip,Randomizing Apple Placement
		}ToolTip
		this.AppleX:=x,this.AppleY:=y
		Style:=this.AppleObj.Style
		Style.visibility:="Visible",Style.Top:=this.AppleY,Style.Left:=this.AppleX
		this.AppleOnScreen := True
	}
	Direction(Direction){
		static LastDirection,Problem:={S:"N",N:"S",E:"W",W:"E"}
		if(Problem[Direction]!=LastDirection)
			this.MoveQueue.Push(Direction),LastDirection:=Direction
	}
	MoveHead(){
		static moveTo
		if(this.MoveQueue.1)
			moveTo:=this.MoveQueue.RemoveAt(1)
		this.snakeHead(moveTo)
		if(!this.appleOnScreen)
			this.Apple()
		for a,b in this.SnakeBody{
			if(this.Stop)
				return
			if(b.x=this.SnakeBody.1.X&&b.y=this.SnakeBody.1.Y&&A_Index>1){
				MsgBox,20,Snake,% "Game Over`n`nScore: " this.Score "`n`nPlay Again?"
				appleOnScreen:=0
				IfMsgBox,Yes
				{
					this.Stop:=1
					SetTimer,Start,-1
					this.next:=1
					return
				}
				else
					ExitApp
				return
		}}
		if(this.AppleX=this.SnakeBody.1.X&&this.AppleY=this.SnakeBody.1.Y)
		{
			this.AddBody(),this.Score++,this.ShowScore()
			if(!Mod(this.Score,this.Difficulty)&&this.Speed>10)
				this.Speed-=10
			this.AppleOnScreen := False
		}
		Sleep, % this.Speed
	}
	Random(){
		Random, AppleX, 0, 490
		Random, AppleY, 0, 490
		return {x:Round(AppleX, -1),y:Round(AppleY, -1)}
	}
	ShowScore(){
		WinSetTitle,ahk_id%Main%,,% "Snake: Score " this.Score
	}
	SnakeHead(movementDirection){
		if(movementDirection~="(E|W)")
			AddX:=movementDirection="E"?10:-10,AddY:=0
		else
			AddY:=movementDirection="N"?-10:10,AddX:=0
		Max:=this.SnakeBody.MaxIndex(),SnakeObj:=this.SnakeBody
		Loop,% Max-1
			New:=SnakeObj[Max-(A_Index)],Old:=SnakeObj[Max-(A_Index-1)],Old.X:=New.X,Old.Y:=New.Y
		obj:=this.SnakeBody.1,NewX:=obj.X+AddX,NewY:=obj.Y+AddY,NewX:=NewX>=0&&NewX<500?NewX:NewX>=500?0:490,NewY:=NewY>=0&&NewY<500?NewY:NewY>=500?0:490,obj.x:=NewX,obj.y:=NewY
		for Index,Obj in this.SnakeBody{
			if(this.Stop){
				return
			}
			Obj.Obj.Style.Left:=Obj.x,Obj.Obj.Style.Top:=Obj.y
		}
	}
}
Edit: changed the modifier to 1-10 (multiplied by 10).
OS: Windows 10 Pro | Editor: Notepad++
My Personal Function Library | Old Build - New Build
User avatar
maestrith
Posts: 825
Joined: 16 Oct 2013, 13:52

Re: My take on Snake

25 Aug 2017, 07:44

I'll possibly get to actually making some more options, but I am working on improving performance :) It starts to slow down around 200 or so body segments.
John H Wilson III 05/29/51 - 03/01/2020. You will be missed.AHK Studio OSDGUI Creator
Donations
Discord
All code is done on a 64 bit Windows 10 PC Running AutoHotkey x32
User avatar
Delta Pythagorean
Posts: 626
Joined: 13 Feb 2017, 13:44
Location: Somewhere in the US
Contact:

Re: My take on Snake

25 Aug 2017, 08:30

*Cracks knuckles* Alright, let's see how many times I have to press space this time...

[AHK]......: v2.0.6 | 64-bit
[OS].......: Windows 11 | 22H2 (OS Build: 22621.1555)
[GITHUB]...: github.com/DelPyth
[PAYPAL]...: paypal.me/DelPyth
[DISCORD]..: tophatcat


You should consider migrating to v2. Practice with small features first such as learning how to do Guis!
Remember to use [code] ... [/code] for your multi-line scripts for the forums.
User avatar
maestrith
Posts: 825
Joined: 16 Oct 2013, 13:52

Re: My take on Snake

25 Aug 2017, 09:58

Added:
-Random Colors
-Zen Mode (no way to lose)
-Bumped up the start from 1-100 to 1-500 (it starts to slow a bit at about 400 or so)
-Score, Snake Length, and Mode displayed in the Title

I'll add more options later. I have a doctors appointment to go to.
John H Wilson III 05/29/51 - 03/01/2020. You will be missed.AHK Studio OSDGUI Creator
Donations
Discord
All code is done on a 64 bit Windows 10 PC Running AutoHotkey x32
User avatar
Masonjar13
Posts: 1555
Joined: 20 Jul 2014, 10:16
Location: Не Россия
Contact:

Re: My take on Snake

25 Aug 2017, 18:52

Oh jeez.. The random colors makes it nearly impossible to tell where the head is. Can the head be a more distinct color, or have the random colors as a switch? The title update was a great idea!

Edit: testing the limits, about 1011 length starts stuttering for me (at 9 speed, which should be 10ms delay, if you didn't change it). Around 1600-2000 it's about as slow as starting speed, and uses a whopping 50mb of memory and 15% CPU. At 4300, each body segment takes around 500ms to add. 5000, working set peaked at 103MB, CPU peak of about 16.8%. I realize this isn't technically useful information, I just like breaking things. ;)
OS: Windows 10 Pro | Editor: Notepad++
My Personal Function Library | Old Build - New Build
User avatar
maestrith
Posts: 825
Joined: 16 Oct 2013, 13:52

Re: My take on Snake

25 Aug 2017, 22:32

LOL! yea, I have some settings in the works I just had an appointment and then I fell asleep when I got home. I just woke up and I will work on some things.

I know it is a bit of a resource hog but it works a lot better than the original version. At around 80-100 it would start to flicker a lot and just look terrible.
John H Wilson III 05/29/51 - 03/01/2020. You will be missed.AHK Studio OSDGUI Creator
Donations
Discord
All code is done on a 64 bit Windows 10 PC Running AutoHotkey x32
User avatar
maestrith
Posts: 825
Joined: 16 Oct 2013, 13:52

Re: My take on Snake

26 Aug 2017, 06:26

Update:
-Settings Page: Press Escape to Start the game and show Settings
-Colors: Edit the colors of the head of the snake and the body
-Zoom: Not what you think
To Do:
-Setup custom keys for directions and Settings
John H Wilson III 05/29/51 - 03/01/2020. You will be missed.AHK Studio OSDGUI Creator
Donations
Discord
All code is done on a 64 bit Windows 10 PC Running AutoHotkey x32
User avatar
Masonjar13
Posts: 1555
Joined: 20 Jul 2014, 10:16
Location: Не Россия
Contact:

Re: My take on Snake

26 Aug 2017, 17:58

Hm, feels like there's a problem with the colors.. My assumption was that, by setting the two colors for the body, they would alternate only those colors. It seems to often disrespect the colors and add random ones in anyway. They're also not alternating, but seemingly randomized. I didn't look too terribly hard, but I didn't see anything in the code explicitly that would do that. Or is it meant to be within the range of the two colors? Because that seems accurate then.
OS: Windows 10 Pro | Editor: Notepad++
My Personal Function Library | Old Build - New Build
User avatar
maestrith
Posts: 825
Joined: 16 Oct 2013, 13:52

Re: My take on Snake

26 Aug 2017, 18:02

It is a range between the two colors
John H Wilson III 05/29/51 - 03/01/2020. You will be missed.AHK Studio OSDGUI Creator
Donations
Discord
All code is done on a 64 bit Windows 10 PC Running AutoHotkey x32
User avatar
Masonjar13
Posts: 1555
Joined: 20 Jul 2014, 10:16
Location: Не Россия
Contact:

Re: My take on Snake

26 Aug 2017, 18:13

Ah, yeah that makes a lot more sense. Also noticed that the head, being the first created, has the lowest z-index. Only applies to Zen mode: when you go back over your own body, your head appears underneath the other segments, making it non-visible. Not sure how you could alter that, but it would help tremendously to have the head always on top.
OS: Windows 10 Pro | Editor: Notepad++
My Personal Function Library | Old Build - New Build
User avatar
maestrith
Posts: 825
Joined: 16 Oct 2013, 13:52

Re: My take on Snake

26 Aug 2017, 18:17

I'll see if I can fix it.
John H Wilson III 05/29/51 - 03/01/2020. You will be missed.AHK Studio OSDGUI Creator
Donations
Discord
All code is done on a 64 bit Windows 10 PC Running AutoHotkey x32
User avatar
maestrith
Posts: 825
Joined: 16 Oct 2013, 13:52

Re: My take on Snake

26 Aug 2017, 18:25

Changed: Suggested by Masonjar13
-Changed the Z order of the head to be on top.
John H Wilson III 05/29/51 - 03/01/2020. You will be missed.AHK Studio OSDGUI Creator
Donations
Discord
All code is done on a 64 bit Windows 10 PC Running AutoHotkey x32
User avatar
maestrith
Posts: 825
Joined: 16 Oct 2013, 13:52

Re: My take on Snake

27 Aug 2017, 14:52

Changed:
-Added: Change the hotkeys
-Re-Wrote a good portion of the code
-Changed the Snake Length to an HTML control
John H Wilson III 05/29/51 - 03/01/2020. You will be missed.AHK Studio OSDGUI Creator
Donations
Discord
All code is done on a 64 bit Windows 10 PC Running AutoHotkey x32
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: My take on Snake

27 Aug 2017, 15:17

Hello!
I tried it earlier, very nice, a classic! Thanks for sharing. :clap: :thumbup:

The latest version gives me an error though.

Code: Select all

Error:  Call to nonexistent function.

Specifically: m(total,Snake.Direction)

	Line#
	052: if (Problem[D]!=Snake.Direction&&D!=Snake.Direction)  
	052: {
	053: Snake.MoveQueue.Push(D),LastDirection:=Direction  
	054: total := ""
	055: For a,b in Snake.MoveQueue
	056: total.=b "
"  
	057: if (snake.MoveQueue.2)  
--->	058: m(total,Snake.Direction)  
	059: }
	060: Return
	061: }
	062: {
	063: Static,Key,"Software\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION"
	063: Static,Versions,{7:7000,8:8888,9:9999,10:10001,11:11001}
	064: Version := Versions[Version]?Versions[Version]:Version

The program will exit.
Cheers.

Edit:
maestrith wrote: oops. Fixed.
:thumbup:
The read head is a nice improvement. I'm not very good though :lol:
Last edited by Helgef on 27 Aug 2017, 15:34, edited 1 time in total.
User avatar
maestrith
Posts: 825
Joined: 16 Oct 2013, 13:52

Re: My take on Snake

27 Aug 2017, 15:26

oops. Fixed.
John H Wilson III 05/29/51 - 03/01/2020. You will be missed.AHK Studio OSDGUI Creator
Donations
Discord
All code is done on a 64 bit Windows 10 PC Running AutoHotkey x32
User avatar
maestrith
Posts: 825
Joined: 16 Oct 2013, 13:52

Re: My take on Snake

27 Aug 2017, 15:29

Helgef wrote:Hello!
I tried it earlier, very nice, a classic! Thanks for sharing. :clap: :thumbup:
Cheers.
Thanks :)
John H Wilson III 05/29/51 - 03/01/2020. You will be missed.AHK Studio OSDGUI Creator
Donations
Discord
All code is done on a 64 bit Windows 10 PC Running AutoHotkey x32
User avatar
maestrith
Posts: 825
Joined: 16 Oct 2013, 13:52

Re: My take on Snake

28 Aug 2017, 09:07

Added:
-Board Size: Select and it will Reload (Will make this not reload in a future release)
-Snake Size
-Shift+Escape also exits the game
John H Wilson III 05/29/51 - 03/01/2020. You will be missed.AHK Studio OSDGUI Creator
Donations
Discord
All code is done on a 64 bit Windows 10 PC Running AutoHotkey x32
User avatar
SpeedMaster
Posts: 494
Joined: 12 Nov 2016, 16:09

Re: My take on Snake

28 Aug 2017, 12:54

Hello,
Very nice ! :thumbup:
but... Only the modified by Masonjar13 old version is working for me :cry:

Error: 0x80020006 - Nom inconnu.
Specifically: CreateElementNS
---> 103: defs := this.Doc.CreateElementNS("http://www.w3.org/2000/svg","defs")
User avatar
maestrith
Posts: 825
Joined: 16 Oct 2013, 13:52

Re: My take on Snake

28 Aug 2017, 14:32

SpeedMaster wrote:Hello,
Very nice ! :thumbup:
but... Only the modified by Masonjar13 old version is working for me :cry:

Error: 0x80020006 - Nom inconnu.
Specifically: CreateElementNS
---> 103: defs := this.Doc.CreateElementNS("http://www.w3.org/2000/svg","defs")
I am using SVG which requires IE 11+. Divs start to flicker badly, at least on my system, at around 100 or so and the SVG do not flicker even when my PC starts to slow down at 500 or so. https://support.microsoft.com/en-us/hel ... -downloads but Windows 7 is the minimum OS that will run it.

I tried the older version using IE 10 and below and the body segments were rectangular not square :( It just won't work properly below 11.
John H Wilson III 05/29/51 - 03/01/2020. You will be missed.AHK Studio OSDGUI Creator
Donations
Discord
All code is done on a 64 bit Windows 10 PC Running AutoHotkey x32

Return to “Gaming Scripts (v1)”

Who is online

Users browsing this forum: No registered users and 50 guests