Blockly Games : Maze

274 views
Skip to first unread message

Clyde Eisenbeis

unread,
Nov 29, 2023, 8:53:08 AM11/29/23
to Blockly
Github --- https://github.com/google/blockly-games/tree/master/appengine/maze/src --- has main.js, html.js, and block.js.  

The html.js file contains:

goog.provide('Maze.html');
goog.require('BlocklyGames');
goog.require('BlocklyGames.html');
goog.require('BlocklyInterface');

Where do I find these files? Thanks!

Neil Fraser

unread,
Nov 29, 2023, 10:21:11 AM11/29/23
to blo...@googlegroups.com
Am Mi., 29. Nov. 2023 um 14:53 Uhr schrieb Clyde Eisenbeis <cte...@gmail.com>:
Github --- https://github.com/google/blockly-games/tree/master/appengine/maze/src --- has main.js, html.js, and block.js.  

The html.js file contains:


The 'appengine/src' directory contains all the files shared across multiple games.

--
Neil Fraser, Switzerland
https://neil.fraser.name

Clyde Eisenbeis

unread,
Nov 29, 2023, 10:40:08 AM11/29/23
to Blockly
Where do I find:
'Maze.html'
'BlocklyGames'
'BlocklyGames.html'
'BlocklyInterface'

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Christopher Allen

unread,
Nov 29, 2023, 1:19:02 PM11/29/23
to blo...@googlegroups.com
Hi Clyde,

Where do I find:
'Maze.html'
'BlocklyGames'
'BlocklyGames.html'
'BlocklyInterface'


My colleague Neil already answered you: 
 

The 'appengine/src' directory contains all the files shared across multiple games.

Perhaps some background information may help you to understand what's going on here better.

The goog.provide() and goog.require() calls are part of the old Closure module system, a module system provided (and used) by the Closure Library and understood by the Closure Compiler that we use to bundle and minify both the Blockly library and the individual Blockly Games games.  When I say "old" module system, I mean that it was supplanted by the "new" goog.module system starting around 2014, which was in turn supplanted by ECMAscript modules ("ESM"), and their equivalent TypeScript modules, in the years since then.

(If you are not already familiar with module systems in JavaScript and TypeScript, I can highly recommend this cartoon introduction to the ES module system.)

Now, when I say "supplanted", what I mean is that new code has generally been written in the new system, while existing code tended to be left using the old system at least until a major porting/migration effort could be undertaken; in the mean time Google developed a bunch of clever hacks sophisticated build tools that would let us combine code written in all three systems (goog.provide, goog.module and ES modules).

In fact, the Blockly library itself has literally just yesterday finished an approximately 2.5 year migration from being written in JavaScript using goog.provides to JavaScript using goog.module, and then to TypeScript + TS modules (in some cases via JS + ES modules in the interim), though a lot of our test code is still in JavaScript.

Blockly Games has not yet been migrated, and so is still using goog.provide()s.

Now, I was trying to find documentation about how the old Closure module system (goog.provide) works, but I can't find much on the web any more.  I did find this bit of documentation for the Closure Library in the Internet Archive, but to be honest it's not the best explanation so I'll try to summarize the important things to understand here, using some of the files mentioned above as examples.

Background: Scripts vs. Modern Modules

These days almost all code written in JavaScript is written in what I would describe as "modern module systems".  The first well-known one for JavaScript was probably the CommonJS module system; other well known ones are the aforementioned "new" Closure module system using goog.module, and ES modules.

A "modern" module system has the feature that if I create some top-level variable or functions in one file (e.g., let name = 'Alice'; or function send(from, to, message) { /*...*/ })  those name bindings (in this case name and send) are visible throughout that file but (by default) not in any other file in my project, so if I want to use them in another file I have to do something (like import them) before I can use them.  That also means I'm safe to use those names in other files without risking any clash.

But in the early days of JavaScript, there were no modules, only scripts, and if I write var name = 'Alice' in one script I create a global variable that can be seen in every other script in my project.  That's bad, especially for programmers writing libraries intended to be used by other developers: every variable or function name I use potentially clashes with every other JS program that my library is used in, and with every other library that those programs also use.

The usual workaround was to create some "namespace" objects, so all the code in a particular library would could be accessed by just one name, like:

var myLibrary = {};
myLibrary.name = 'Alice';
myLibrary.send = function send(from, to, message);

Then so long as no one else used the name myLibrary there would be no clashes.

What goog.provide() Does

The original closure module system wasn't a module system in the modern sense; it was just some helper functions to make it easier to use namespace objects.  The file appengine/src/html.js contains the line:

goog.provide('BlocklyGames.html');

it does two things:
  1. It makes sure namespace objects exist.  In this case, it is equivalent to writing:

    BlocklyGames = BlocklyGames || {};
    BlocklyGames.html = BlocklyGames.html || {};

    The first line makes sure that there is a global variable named BlocklyGames, and if it didn't already have a value it creates a new, initially-empty namespace object.  The second line makes sure that that namespace object has a property named html, and sets it to a second empty namespace object if it isn't already set.

    If you look at the rest of the file you will see that all of the code is then attached to the BlocklyGames.html namespace object, e.g.:

    BlocklyGames.html.headerBar = function(/*...*/) { /*...*/ };

  2. It tells the closure tools that if another file asks for "BlocklyGames.html" then appengine/src/html.js is the file to find it in.

What goog.require() Does

The file appengine/maze/src/html.js contains the line:

goog.require('BlocklyGames.html');

This tells the module system "if you haven't already, please go and execute the script that contained 'provide('BlocklyGames.html')' and then finish executing the rest of this file."

After that you will see that maze/src/html.js can then go and call BlocklyGames.html.headerBar() as usual, safe in the knowledge that src/html.js will have been run and so the functions defined in it are available.

(Of course there's some magic that goes on behind the scenes to make all that file loading work, but none of that is important for understanding what's going on here.)


I hope this will help you understand the code and my colleague's answer.

Christopher

Clyde Eisenbeis

unread,
Nov 29, 2023, 5:26:18 PM11/29/23
to Blockly
Hi Christopher,

Thanks for the detailed response.  Lots of information to absorb. 

I've written lots of code in the world of electronics - computers and microprocessors - Assembler thru C#.  Also, HTML / CSS for 30 years.   WordPress the past five years.  JavaScript the past six months. 

I discovered Blockly in Sep.  Very intriguing.  A good way to help students learn code writing.

I like to learn by looking at code.  My favorite potential is Blockly Games : Maze 1.
... Maze 1 is basic and simple.  
... ... A minimum toolbox with renamed tools.  
... ... Three images on the screen simultaneously.  
... ... The commands from the toolbox items are transmitted to the car.

Unfortunately, the github Maze code is complex - https://github.com/google/blockly-games/tree/master/appengine/maze/src.  I had assumed that the Maze HTML code would help me understand.  It appears that is not an option.

All of the YouTube video clips, I've seen, describe using Blockly ... not the HTML / JavaScript to create Blockly menus, etc.

As I'm retired, I have the time to learn and write the Maze 1 code (where the HTML / JavaScript code creates Maze 1).  I'd create a video clip for YouTube.  This would be very useful for beginners.

I have looked at some codelab examples - getting-started-codelab, custom-toolbox-codelab, context-menu-codela, etc.  

I've learned bits an pieces, but have not seen enough to write some simple code that uses HTML / JavaScript that includes:
... ... A minimum toolbox with renamed tools.  
... ... Three images on the screen simultaneously.  
... ... The commands from the toolbox items are transmitted to the car.

It appears that the best place for me to start is the custom-toolbox-codelab code.  What parts of that code could I delete to have a solid foundation?    I think I could eliminate the registry, but am not sure. 

I'm open to your ideas.  Thanks!

Clyde

-----------------------------
Clyde Eisenbeis
retired Electronic Design Engineer
NDAcademy.FoxPing.com/
641-691-0110
-----------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Maribeth Moffatt

unread,
Nov 30, 2023, 4:07:08 PM11/30/23
to Blockly
Hello Clyde,

You're not going to find sample code that demonstrates how to move a car with blocks. Rendering and controlling the car is not part of the Blockly library, so we can't help with that. As a concrete example, you might have a block that generates the code `moveForward()`. The `moveForward` function would have to be designed by you and is unrelated to using Blockly. Additionally, actually executing that code in JavaScript is also outside the scope of what this library does.

In a previous email, Mark gave you a simple "Hello World" with Blockly and some ideas on where to go from there. That is the sample code I would suggest you start with, and refer to the links he provided for the next topics you might want to learn, such as creating custom blocks.

Our team is happy to answer specific questions about any of the existing sample code we have written, but we're not going to be able to write you new sample code here in the forum like you're asking.

Best,
Maribeth

Clyde Eisenbeis

unread,
Nov 30, 2023, 4:50:31 PM11/30/23
to Blockly
What about this statement? --- "It appears that the best place for me to start is the custom-toolbox-codelab code.  What parts of that code could I delete to have a solid foundation?    I think I could eliminate the registry, but am not sure." ---

Would it be ok to delete the registry if the menu is never changed once it is released?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

Maribeth Moffatt

unread,
Nov 30, 2023, 4:59:06 PM11/30/23
to Blockly
In the custom toolbox codelab, part of the code is about creating a custom toolbox category. If you delete the code that uses the registry to register the custom category, then the custom category code will not work. If you don't want that, then go for it.

Clyde Eisenbeis

unread,
Nov 30, 2023, 5:32:24 PM11/30/23
to Blockly
Does "custom category" mean the student who uses the end result menu blocks, cannot modify the menu blocks?  The student can only drag the existing block to the center section?

For example, I noticed the getting-started-codelab\complete-code, which plays music sounds, does not use registry.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Maribeth Moffatt

unread,
Nov 30, 2023, 6:06:22 PM11/30/23
to Blockly
Have you read the toolbox codelab that accompanies the code? That codelab explains what I mean by custom category.

Maribeth

Clyde Eisenbeis

unread,
Nov 30, 2023, 6:24:12 PM11/30/23
to Blockly
Yes, I've read those pages.  It is purpose is not clear to me.  The word "override" does not answer my question.  Override the library?  Override the initial menu I created?

Does "custom category" mean the student who uses the end result menu blocks, cannot modify the menu blocks?  The student can only drag the existing block to the center section?

For example, I noticed the getting-started-codelab\complete-code, which plays music sounds, does not use registry.  Please answer the question.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Maribeth Moffatt

unread,
Nov 30, 2023, 7:17:19 PM11/30/23
to Blockly
Override refers to the JavaScript concept of inheritance. The codelab is about customizing the appearance of the Blockly toolbox. The codelab introduction shows a picture of a toolbox that looks different than the standard built-in toolbox. The codelab is teaching you how to create that custom toolbox, which includes subclassing some Blockly classes and overriding methods in them to change their behavior.

Blocks have fields that a student can edit, such as typing into a text input or selecting a value from a dropdown. Selecting which fields make up a block is a concept related to creating custom blocks. It is not affected by the appearance of the toolbox category. I would recommend you use the Block Factory (and docs for block factory, including a video) if you want to learn about creating custom blocks.

I have answered the question about using the registry previously in another email chain. The registry is used to register the custom toolbox category with Blockly. The getting started codelab doesn't create custom subclasses that need to be registered, so it doesn't use the registry.

Maribeth

Clyde Eisenbeis

unread,
Dec 1, 2023, 9:23:00 AM12/1/23
to Blockly
Thanks for the clarification!

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Reply all
Reply to author
Forward
0 new messages