Don't know if you yet know it: When you click in your code on a keyword such as 'case' and then hit F1, the manual will pop up showing the help page for this command or keyword. Also pay attention to the footer. Whenever you edit the code, a short help for the command you're editing is displayed there, which I find very helpful.
That was very confusing for me too in the beginning. The reason that there is no main loop is javascript. SB code is transpiled into javascript and this runs asynchronously. That's why a linear programm execution is not possible, and because of that also no event loop. But the difference is not too big. With BindEvent() you assign a procedure to your window, which handles all the events. This is pretty much like a main loop.
By the way, I had a look in your website today and really like it. Was like a trip to the past with nice memories! As a kid I owned a VC 2600 by myself and truly loved it. Spent hours to play Pitfall and River Raid and some others all day... Even took my first approach to code with this machine.
I also added some code to the editor. The playfield is now cleared when select a new row mode, and there are new buttons for toggle and erase. Maybe you'd like have a look:
Code: Select all
;- META
EnableExplicit
#AppName = "Playfield Editor"
#Version = "0.0.3"
;- DECLARATIONS
; defining named constants for all objects
; important for much better code readability
Enumeration windows
#Window_Main
#Window_Color
#Window_Code
EndEnumeration
Enumeration gadgets
#Button_Clear
#Button_FrontColor
#Button_BackColor
#Button_Draw
#Button_Toggle
#Button_Erase
#Button_EditBG
#Button_EditFG
#Canvas_Playfield
#Combo_Rows
#Container_ColorTable
#Text_EditingMode
#Text_FrontColor
#Text_BackColor
#Text_Footer
#Text_Mode
#Text_Title
EndEnumeration
Enumeration fonts
#Font_UiBig
#Font_UiNormal
#Font_UiSmall
EndEnumeration
;- SETTINGS
; defines several settings for the appearance
; change as you wish
; ui
Global colorWindowBG = RGB(64,64,64) ; colors for the editor
Global colorText = RGB(255,255,255)
Global fontUiBig.s = "Arial" ; fonts for text in editor ui
Global fontUiBigSize = 30
Global fontUiNormal.s = "Arial"
Global fontUiNormalSize = 16
Global fontUiSmall.s = "Arial"
Global fontUiSmallSize = 10
Global spacer = 10 ; space between ui elements; change as you like
Global textFooter.s = #AppName + " v." + #Version + " by randomterrain.com"
; playyfield
Global mode = #Button_Draw ; default mode
Global colorFG = #Black ; default foreground color
Global colorBG = #White ; default background color
Global cols = 32 ; fixed value for number of columns
Global colScale = 15 ; currently set to 15, which results in 15*32 columns = 480 pixel width; change as you wish
Global rows = 176 ; same as for columns
Global rowScale = 2 ; same as for columns
Global rowHeight = 16 ; set to 16 by default because I put 11 rows as default in the initUI() procedure
Global x, y, GID, whichColor
Global Dim playfieldData(cols, rows)
Global Dim playfieldFG(rows)
Global Dim playfieldBG(rows)
Define i
For i = 0 To rows-1
playfieldFG(i) = colorFG
playfieldBG(i) = colorBG
Next
;- PROCEDURES
Procedure ClearPlayfield()
Dim playfieldData(cols, rows)
Dim playfieldFG(rows)
Dim playfieldBG(rows)
StartDrawing(CanvasOutput(#Canvas_Playfield))
Box(0, 0, cols*colScale, rows*rowHeight, #White)
StopDrawing()
EndProcedure
Procedure TimerEvents()
Select EventTimer()
Case 0
If WindowMouseX(#Window_Color) = -1
CloseWindow(#Window_Color)
EndIf
EndSelect
EndProcedure
Procedure WindowEvents()
Select EventWindow()
Case #Window_Color
CloseWindow(#Window_Color)
EndSelect
EndProcedure
Procedure ColorCellClicked(Title.s, Color.s)
Protected selectedColor = Val(ReplaceString(Color.s, "#", "$"))
selectedColor = Blue(selectedColor) + Green(selectedColor)*256 + Red(selectedColor)*65536
Select whichColor
Case #Button_FrontColor
colorFG = selectedColor
GID=GadgetID(#Button_FrontColor)
! $(v_gid.div).find(".dijitButtonContents").css("background-color", spider_helper_ColorToHtml(v_colorfg));
Case #Button_BackColor
colorBG = selectedColor
GID=GadgetID(#Button_BackColor)
! $(v_gid.div).find(".dijitButtonContents").css("background-color", spider_helper_ColorToHtml(v_colorbg));
EndSelect
CloseWindow(#Window_Color)
EndProcedure
Procedure.s Get_NTSC_ColorTable()
Protected Table.s
Protected Title.s, Color.s
Protected RowCounter, ColCounter
Restore NTSC
Table + "<table id='colorTable' style='width:100%;height:100%'>"
For RowCounter = 0 To 15
Table + "<tr>"
For ColCounter = 0 To 7
Read.s Title
Read.s Color
Table + "<td title='" + Title + "' color='" + Color + "' style='background-color:" + Color + "'></td>"
Next ; ColCounter
Table + "</tr>"
Next ; RowCounter
Table + "</table>"
ProcedureReturn Table
EndProcedure
Procedure GadgetEvents()
; handle all that happens during runtime
Protected gadget = EventGadget()
Protected type = EventType()
Protected i
Select gadget
Case #Canvas_Playfield
If EventType() = #PB_EventType_LeftButtonDown Or (EventType() = #PB_EventType_MouseMove And GetGadgetAttribute(#Canvas_Playfield, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton)
If StartDrawing(CanvasOutput(#Canvas_Playfield))
; find out which column and row was clicked
x = (GetGadgetAttribute(#Canvas_Playfield, #PB_Canvas_MouseX)/colScale)
y = (GetGadgetAttribute(#Canvas_Playfield, #PB_Canvas_MouseY)/(rowHeight*rowScale))
; perform drawing depending on current mode
If mode = #Button_Draw
playfieldData(x, y*rowHeight) = 1
Box(x*colScale, y*rowScale*rowHeight, colScale, rowHeight*rowScale, playfieldFG(y*rowheight))
ElseIf mode = #Button_Toggle
Select playfieldData(x, y*rowHeight)
Case 1
playfieldData(x, y*rowHeight) = 0
Box(x*colScale, y*rowScale*rowHeight, colScale, rowHeight*rowScale, playfieldBG(y*rowheight))
Case 0
playfieldData(x, y*rowHeight) = 1
Box(x*colScale, y*rowScale*rowHeight, colScale, rowHeight*rowScale, playfieldFG(y*rowheight))
EndSelect
ElseIf mode = #Button_Erase
playfieldData(x, y*rowHeight) = 0
Box(x*colScale, y*rowScale*rowHeight, colScale, rowHeight*rowScale, playfieldBG(y*rowheight))
ElseIf mode = #Button_EditBG
playfieldBG(y*rowHeight) = colorBG
Box(0, y*rowHeight*rowScale, cols*colScale, rowHeight*rowScale, colorBG)
For i = 0 To cols-1
If playfieldData(i,y*rowHeight) = 1
Box(i*colScale, y*rowScale*rowHeight, colScale, rowHeight*rowScale, playfieldFG(y*rowheight))
EndIf
Next
ElseIf mode = #Button_EditFG
playfieldFG(y*rowHeight) = colorFG
For i = 0 To cols-1
If playfieldData(i,y*rowHeight) = 1
Box(i*colScale, y*rowScale*rowHeight, colScale, rowHeight*rowScale, colorFG)
EndIf
Next
EndIf
StopDrawing()
EndIf
EndIf
Case #Combo_Rows
rowHeight = Pow(2, GetGadgetState(#Combo_Rows))
If type = #PB_EventType_Change
ClearPlayfield()
EndIf
Case #Button_Draw To #Button_EditFG
; set drawing mode
For i = #Button_Draw To #Button_EditFG
SetGadgetState(i, 0)
Next
SetGadgetState(gadget, 1)
mode = gadget
Case #Button_FrontColor, #Button_BackColor
whichColor = gadget
OpenWindow(#Window_Color, WindowMouseX(#Window_Main)-10, WindowMouseY(#Window_Main)-50,
200, 400, "Color NTSC");, #PB_Window_BorderLess)
ContainerGadget(#Container_ColorTable, 0, 0, WindowWidth(#Window_Color), WindowHeight(#Window_Color) )
GID = GadgetID(#Container_ColorTable)
! $(v_gid.div).empty();
! $(v_gid.div).append($(v_ntsc_colortable));
! $('#colorTable').on('click','td', function() {
! f_colorcellclicked($(this).attr("title"), $(this).attr("color"));
! });
AddWindowTimer(#Window_Color, 0, 100)
Case #Button_Clear
ClearPlayfield()
EndSelect
EndProcedure
Procedure initUI()
; create main window and user interface
LoadFont(#Font_UiBig, fontUiBig, fontUiBigSize)
LoadFont(#Font_UiNormal, fontUiNormal, fontUiNormalSize)
LoadFont(#Font_UiSmall, fontUiSmall, fontUiSmallSize)
If OpenWindow(#Window_Main, 0, 0, 0, 0, #AppName, #PB_Window_Background)
SetWindowColor(#Window_Main, colorWindowBG)
; title
TextGadget(#Text_Title, 5*spacer, 5*spacer, cols*colScale*3, fontUiBigSize, #AppName)
SetGadgetFont(#Text_Title, FontID(#Font_UiBig))
SetGadgetColor(#Text_Title, #PB_Gadget_FrontColor, colorText)
; playfield
CanvasGadget(#Canvas_Playfield, GadgetX(#Text_Title), GadgetY(#Text_Title)+GadgetHeight(#Text_Title)+4*spacer,
cols*colScale, rows*rowScale, #PB_Canvas_Border)
; clear button
ButtonGadget(#Button_Clear, GadgetX(#Text_Title), GadgetY(#Canvas_Playfield)+GadgetHeight(#Canvas_Playfield)+3*spacer,
80, 30, "Clear")
; row modes
TextGadget(#Text_Mode, GadgetX(#Canvas_Playfield)+GadgetWidth(#Canvas_Playfield)+3*spacer, GadgetY(#Canvas_Playfield),
200, fontUiNormalSize, "Row Mode")
SetGadgetFont(#Text_Mode, FontID(#Font_UiNormal))
SetGadgetColor(#Text_Mode, #PB_Gadget_FrontColor, colorText)
ComboBoxGadget(#Combo_Rows, GadgetX(#Text_Mode), GadgetY(#Text_Mode)+fontUiNormalSize+spacer, 240, 30)
AddGadgetItem(#Combo_Rows, -1, " 32 columns with 176 rows")
AddGadgetItem(#Combo_Rows, -1, " 32 columns with 88 rows")
AddGadgetItem(#Combo_Rows, -1, " 32 columns with 44 rows")
AddGadgetItem(#Combo_Rows, -1, " 32 columns with 22 rows")
AddGadgetItem(#Combo_Rows, -1, " 32 columns with 11 rows")
SetGadgetState(#Combo_Rows, 4)
; editing mode
TextGadget(#Text_EditingMode, GadgetX(#Text_Mode), GadgetY(#Combo_Rows)+30+3*spacer, 240, fontUiNormalSize, "Editing Mode")
SetGadgetFont(#Text_EditingMode, FontID(#Font_UiNormal))
SetGadgetColor(#Text_EditingMode, #PB_Gadget_FrontColor, colorText)
ButtonGadget(#Button_Draw, GadgetX(#Text_Mode), GadgetY(#Text_EditingMode)+fontUiNormalSize+spacer, 80, 30,
"Draw", #PB_Button_Toggle )
ButtonGadget(#Button_Toggle, GadgetX(#Text_Mode)+80, GadgetY(#Text_EditingMode)+fontUiNormalSize+spacer, 80, 30,
"Toggle", #PB_Button_Toggle )
ButtonGadget(#Button_Erase, GadgetX(#Text_Mode)+160, GadgetY(#Text_EditingMode)+fontUiNormalSize+spacer, 80, 30,
"Erase", #PB_Button_Toggle)
ButtonGadget(#Button_EditFG, GadgetX(#Text_Mode), GadgetY(#Text_EditingMode)+fontUiNormalSize+spacer+30, 80, 30,
"Color FG", #PB_Button_Toggle )
ButtonGadget(#Button_EditBG, GadgetX(#Text_Mode)+80, GadgetY(#Text_EditingMode)+fontUiNormalSize+spacer+30, 80, 30,
"Color BG", #PB_Button_Toggle)
SetGadgetState(mode, 1)
; color selection
TextGadget(#Text_FrontColor, GadgetX(#Text_Mode), GadgetY(#Button_EditFG)+35+3*spacer, 160, fontUiNormalSize, "Foreground Color")
SetGadgetFont(#Text_FrontColor, FontID(#Font_UiNormal))
SetGadgetColor(#Text_FrontColor, #PB_Gadget_FrontColor, colorText)
ButtonGadget(#Button_FrontColor, GadgetX(#Text_FrontColor)+GadgetWidth(#Text_FrontColor), GadgetY(#Text_FrontColor)-5, 60, 30, "")
GID=GadgetID(#Button_FrontColor)
! $(v_gid.div).find(".dijitButtonContents").css("background-color", spider_helper_ColorToHtml(v_colorfg));
TextGadget(#Text_BackColor, GadgetX(#Text_Mode), GadgetY(#Button_EditFG)+75+3*spacer, 160, fontUiNormalSize, "Background Color")
SetGadgetFont(#Text_BackColor, FontID(#Font_UiNormal))
SetGadgetColor(#Text_BackColor, #PB_Gadget_FrontColor, colorText)
ButtonGadget(#Button_BackColor, GadgetX(#Text_BackColor)+GadgetWidth(#Text_BackColor), GadgetY(#Text_BackColor)-5, 60, 30, "")
GID=GadgetID(#Button_BackColor)
! $(v_gid.div).find(".dijitButtonContents").css("background-color", spider_helper_ColorToHtml(v_colorbg));
; footer
TextGadget(#Text_Footer, GadgetX(#Text_Title), GadgetY(#Button_Clear)+GadgetHeight(#Button_Clear)+3*spacer,
cols*colScale*3, fontUiSmallSize, textFooter)
SetGadgetFont(#Text_Footer, FontID(#Font_UiSmall))
SetGadgetColor(#Text_Footer, #PB_Gadget_FrontColor, colorText)
EndIf
EndProcedure
;- POINT OF ENTRY
; programm starts here
Global NTSC_ColorTable.s = Get_NTSC_ColorTable()
initUI()
BindEvent(#PB_Event_Gadget, @GadgetEvents())
BindEvent(#PB_Event_CloseWindow, @WindowEvents())
BindEvent(#PB_Event_Timer, @TimerEvents())
;- DATA SECTION
DataSection
NTSC:
Data.s "$00", "#000000", "$02", "#1A1A1A", "$04", "#393939", "$06", "#5B5B5B", "$08", "#7E7E7E", "$0A", "#A2A2A2", "$0C", "#C7C7C7", "$0E", "#EDEDED"
Data.s "$10", "#190200", "$12", "#3A1F00", "$14", "#5D4100", "$16", "#826400", "$18", "#A78800", "$1A", "#CCAD00", "$1C", "#F2D219", "$1E", "#FEFA40"
Data.s "$20", "#370000", "$22", "#5E0800", "$24", "#832700", "$26", "#A94900", "$28", "#CF6C00", "$2A", "#F58F17", "$2C", "#FEB438", "$2E", "#FEDF6F"
Data.s "$30", "#470000", "$32", "#730000", "$34", "#981300", "$36", "#BE3216", "$38", "#E45335", "$3A", "#FE7657", "$3C", "#FE9C81", "$3E", "#FEC6BB"
Data.s "$40", "#440008", "$42", "#6F001F", "$44", "#960640", "$46", "#BB2462", "$48", "#E14585", "$4A", "#FE67AA", "$4C", "#FE8CD6", "$4E", "#FEB7F6"
Data.s "$50", "#2D004A", "$52", "#570067", "$54", "#7D058C", "$56", "#A122B1", "$58", "#C743D7", "$5A", "#ED65FE", "$5C", "#FE8AF6", "$5E", "#FEB5F7"
Data.s "$60", "#0D0082", "$62", "#3300A2", "$64", "#550FC9", "$66", "#782DF0", "$68", "#9C4EFE", "$6A", "#C372FE", "$6C", "#EB98FE", "$6E", "#FEC0F9"
Data.s "$70", "#000091", "$72", "#0A05BD", "$74", "#2822E4", "$76", "#4842FE", "$78", "#6B64FE", "$7A", "#908AFE", "$7C", "#B7B0FE", "$7E", "#DFD8FE"
Data.s "$80", "#000072", "$82", "#001CAB", "$84", "#033CD6", "$86", "#205EFD", "$88", "#4081FE", "$8A", "#64A6FE", "$8C", "#89CEFE", "$8E", "#B0F6FE"
Data.s "$90", "#00103A", "$92", "#00316E", "$94", "#0055A2", "$96", "#0579C8", "$98", "#239DEE", "$9A", "#44C2FE", "$9C", "#68E9FE", "$9E", "#8FFEFE"
Data.s "$A0", "#001F02", "$A2", "#004326", "$A4", "#006957", "$A6", "#008D7A", "$A8", "#1BB19E", "$AA", "#3BD7C3", "$AC", "#5DFEE9", "$AE", "#86FEFE"
Data.s "$B0", "#002403", "$B2", "#004A05", "$B4", "#00700C", "$B6", "#09952B", "$B8", "#28BA4C", "$BA", "#49E06E", "$BC", "#6CFE92", "$BE", "#97FEB5"
Data.s "$C0", "#002102", "$C2", "#004604", "$C4", "#086B00", "$C6", "#289000", "$C8", "#49B509", "$CA", "#6BDB28", "$CC", "#8FFE49", "$CE", "#BBFE69"
Data.s "$D0", "#001501", "$D2", "#103600", "$D4", "#305900", "$D6", "#537E00", "$D8", "#76A300", "$DA", "#9AC800", "$DC", "#BFEE1E", "$DE", "#E8FE3E"
Data.s "$E0", "#1A0200", "$E2", "#3B1F00", "$E4", "#5E4100", "$E6", "#836400", "$E8", "#A88800", "$EA", "#CEAD00", "$EC", "#F4D218", "$EE", "#FEFA40"
Data.s "$F0", "#380000", "$F2", "#5F0800", "$F4", "#842700", "$F6", "#AA4900", "$F8", "#D06B00", "$FA", "#F68F18", "$FC", "#FEB439", "$FE", "#FEDF70"
EndDataSection