Block Coding - high-level, block-based visual programming

Hi! Here at Endless OS Foundation we have recently started engaging young learners in the world of Godot; our learning programs aim to develop a broad range of 21st century skills in underserved communities, and game creation provides a fantastic environment for that to happen.

We are looking at different ways to ease first-time game developers into Godot. As part of this we have just published our initial learner-oriented block programming plugin prototype for Godot. It is available via the AssetLib. Here is a demo of how it can be used to build a simple game:

More background and getting started info in the README.

Our aim is to reduce the learning curve faced by learners who are on the early part of their journey towards becoming game developers and are starting to use Godot for the first time. These learners face the challenge of learning to code, while simultaneously having to learn their way around the Godot Editor. In this project, we take a step to smoothen that out for the learners: we allow games to be built with high-level visual programming blocks, instead of GDScript. Tools like Scratch and Makecode have demonstrated that block coding can be much more accessible and intuitive to beginners than textual programming. We envision that learners will use block coding as a stepping stone to learn programming concepts while building their first games, simultaneously getting familiar with the rest of the Godot editor, before later progressing onto learning GDScript.

We are making this initial version available seeking feedback from community members, learners and educators. We will then continue development, incorporating such feedback and improving the technical architecture. Please share your feedback!

The Endless team will be at GodotCon 2024 in Berlin - hope to see you there!

15 Likes

Thx, amazing project,

I did try it a little and it is very well done and easy to use.

Do you think it would be possible to provide the ping-pong project (without block code) to follow along with the tutorial ?

Do you plan to add node as Velocity to be able to make platform game ? I think that would be a nice goal so kids would be able to make their own platform game.

1 Like

Thanks for the feedback!

The plugin includes the Pong game at addons/block_code/examples/pong_game/pong_game.tscn. You could delete the BlockCode nodes and then you would be at the state shown at the start of the video.

We’ll also produce a video showing how to build that scene from scratch - I think it’s interesting now that the coding is aspect is simplified through blocks, we have to think about how we get learners through the rest of the learning curve needed to build games like this, like navigating Godot UI, learning what is a RigidBody2D, what is a collision shape, etc.

Yes we should add nodes to make common types of games! We haven’t tried a platformer yet, do you have specific suggestions for which blocks would be useful, or some common GDScript code operations that we would need to expose?

hello i encountered a issue where the code blocks dont appear on the left panel, using godot 4.2.1 and code blocks 0.2.0

1 Like

this project looks really promising!

This is so great! I’ve been using the Blender game engine branch to teach game development. The bricks and nodes are fairly easy to understand. I’m definitely interested in using this in my classes when it is ready.

Thanks for your feedback! I’m curious if you have any feedback on what is needed to make it “ready”. Or if you have any students available for testing this in the next few weeks? Our usual “testbed” student group is not available to us currently due to summer break so we are looking for alternatives!

1 Like

I’m also out for summer. In the inputs, I didn’t see any way to choose specific buttons or a way to program joystick controls.

what are the limitations so far? I’m in the process of learning godot so that I can eventually teach godot to people at the library I work for. I think the block code could be a gentle introduction to the scripting parts.

Technically I could test it out as a “student” since I’m new to godot and coding.

Does the block code make gdscript as the output? I think someone mentioned that was maybe a possibility in the future. If you are taking suggestions I would recommend that you do that. Block code that can then be read as gdscript would be great to transition from using blocks to writing code.

I had this at first. I’m not sure if you had the same issue but for me I needed to put a “block code” child node into the scene that needed a script. once that child node is there then the blocks show up.

The readme mentions it but it’s easy to overlook at first.

That’s the idea - smoothen out the learning progress. This way you can focus on teaching the Godot editor without additionally burdening the learners of simultaneously learning how to code and how to write GDScript.

This is an early prototype produced with some initial guesses, without much input from the education/learner side, so we don’t know how useful our tool is for its stated purpose. We’re going through the process now of getting expert feedback and student playtesting. Would love your input on this.

In terms of limitations - there are many already, because we’re intentionally designing this as a less powerful (but more approachable) scripting approach than GDScript. I think the more relevant questions are: can learners build a suitable range of basic games with this? Is it a smooth and intuitive process for early stage learners?

It does currently generate and execute GDScript, and there’s a button that lets you view the GDScript generated from a bunch of blocks. However, this is largely because it was the fastest way we found to prototype this idea. It is not a design decision that we are glued to, we are considering it’s pros/cons and may move away from this.

The idea of being able to generate code from blocks for the benefit of learners seems nice but carries some tricky realities, because when working with learners who have never written code before, you want their first experience of coding to be suitably leveled:

  • Converting a block-built game to code is likely to give you a larger, more complex code project than would be ideal for a learner at this stage.
  • It assumes that the code generated is near perfect quality too, which in our prototype it currently is not. Another example, Makecode Arcade has a blocks-to-code function, but for any game beyond the most trivial one, the code it generates is not something that I believe should be presented to a learner who has no experience of coding.
  • To make this approachable for early stage learners, we’re building a high level abstraction into these blocks (e.g. the “Move character with player 1 buttons” block). There’s a tension there with teaching learner-friendly GDScript. Depending on how our abstraction layer grows and evolves, the code generated is perhaps going to be rooted in our abstraction rather than the more standard and universal GDScript approaches that you might want as the focus of your teaching objectives for when you move towards “learning textual programming”.

That makes total sense when explained like that. I originally thought after some time with the code blocks a student can start reading the code and trying to figure out what the code does based on the blocks the added in. But if it’s not good code output then, like you said, it wouldn’t be worth it. It’ll probably be more of a harm than a good.

I’m going to try to run through a few online tutorials and try to use the codeblocks to replace the scripting. I’ll definitely post feedback as I go. Is this the best place to post or is there somewhere else that you would prefer the feedback?

That would be great! It would be great to have your feedback here on this thread.

Very clever. I’m going to have to try this more on Android Tablet and Phone. One of the problems with “mobile” Godot is small screen coding can be very difficult. And Block assembly is a bit easier than losing space to keyboard.

I do agree with one of the YouTube comments about looking at how GDevelop has organized their Blocks that are really just pre-designed method snippets. By general genres and mechanics. Another example that rarely comes up is the Kodu “Tile” based visual scripting, and the 10 years departed Kode variant created for Project Spark.

Hmm, Android tablet comments… Only vertical scrolling in the Blocks container. Defiantly needs horizontal. I’ll have to look over your codebase of the Main Screen plugin before making suggestions on the how. Also the Block Code tab hid the Asset Library tab once, had to disable/re-enable the plugin to get it back, probably more of Godot bug than this specific plugin.

Longer term, there will likely be need for a touch screen gamepad Control. I know there are several existing ones, but ones that are “just there and just work” with the Blocks will be important. I got held up because there’s no Input.get_vector and no Call method block that pass on a return.

I had to set some VAR_DICT entries from the called method. Which was on, technically a child, Node. Because the BlockCode node replaces the Script of its Parent (good detail to know). I’ll see about cleaning this up and getting it off the Android tablet and into a GitHub repository.

A Call Method with a return would let an instructor fill a lot of holes, by creating helper methods in GDScript, on Singletons. Node paths are easy to Singletons, “/root/globals”. “get_joypad_dir”.

From an English grade school humor stand. Perhaps VAR_LIST instead of VAR_DICT. I know it’s the common abbreviation for dictionary, but… What say you, any current middle school teachers. DICTs or LISTs?

Let’s design a high level block for touchscreen input then - what would the equivalent GDScript look like?

I like this idea. Another option is to make it clearer/easier how to add custom blocks via GDScript. Take a look at the script attached to our SimpleCharacter scene for an example. This is how we would do the touchscreen input block too, I think.

This is so amazing it reminds me of scratch and stencyl, I’m looking forward for this plugin for more updates

Hi, I’m new to this forum.

can you suggest me a simple line of code on creating my own block such as this


Because I need for creating custom block based on existing lines of code on gdscript.

See docs/OVERVIEW.md for some info on this, or look at simple_character.gd inside the plugin for the GDScript that implements the block you have pictured there.

1 Like

Thank you so much dsd.
By the way, how this code in simple_character.gd works

@tool
class_name SimpleCharacter
extends CharacterBody2D

@export var texture: Texture2D:
	set = _set_texture

@export var speed: Vector2 = Vector2(300, 300):
	set = _set_speed

const PLAYER_KEYS = {
	"player_1":
	{
		"up": KEY_W,
		"down": KEY_S,
		"left": KEY_A,
		"right": KEY_D,
	},
	"player_2":
	{
		"up": KEY_UP,
		"down": KEY_DOWN,
		"left": KEY_LEFT,
		"right": KEY_RIGHT,
	}
}

# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")

var _jumping = false


func _set_texture(new_texture):
	texture = new_texture

	if not is_node_ready():
		return

	$Sprite2D.texture = texture
	var shape = RectangleShape2D.new()
	shape.size = Vector2(100, 100) if texture == null else texture.get_size()
	$CollisionShape2D.shape = shape


func _set_speed(new_speed):
	speed = new_speed


## Nodes in the "affected_by_gravity" group will receive gravity changes:
func on_gravity_changed(new_gravity):
	gravity = new_gravity


func _ready():
	add_to_group("affected_by_gravity")
	simple_setup()


func simple_setup():
	_set_texture(texture)
	_set_speed(speed)


func get_custom_class():
	return "SimpleCharacter"


func _player_input_to_direction(player: String):
	var direction = Vector2()
	direction.x += float(Input.is_physical_key_pressed(PLAYER_KEYS[player]["right"]))
	direction.x -= float(Input.is_physical_key_pressed(PLAYER_KEYS[player]["left"]))
	direction.y += float(Input.is_physical_key_pressed(PLAYER_KEYS[player]["down"]))
	direction.y -= float(Input.is_physical_key_pressed(PLAYER_KEYS[player]["up"]))
	return direction


func move_with_player_buttons(player: String, kind: String, delta: float):
	var direction = _player_input_to_direction(player)

	if kind == "top-down":
		velocity = direction * speed

	elif kind == "platformer":
		velocity.x = direction.x * speed.x
		if not is_on_floor():
			velocity.y += gravity * delta
		else:
			if not _jumping and Input.is_physical_key_pressed(PLAYER_KEYS[player]["up"]):
				_jumping = true
				velocity.y -= speed.y
			else:
				_jumping = false

	elif kind == "spaceship":
		rotation_degrees += direction.x * speed.x / 100.0
		velocity = Vector2.DOWN.rotated(rotation) * speed.y * direction.y
	move_and_slide()


static func get_custom_blocks() -> Array[Block]:
	var b: Block
	var block_list: Array[Block] = []

	# Movement
	b = CategoryFactory.BLOCKS["statement_block"].instantiate()
	b.block_type = Types.BlockType.EXECUTE
	b.block_format = "Move with {player: OPTION} buttons as {kind: OPTION}"
	# TODO: delta here is assumed to be the parameter name of
	# the _process or _physics_process method:
	b.statement = 'move_with_player_buttons("{player}", "{kind}", delta)'
	b.defaults = {
		"player": OptionData.new(["player_1", "player_2"]),
		"kind": OptionData.new(["top-down", "platformer", "spaceship"]),
	}
	b.category = "Input"
	block_list.append(b)

	var property_blocks = (
		CategoryFactory
		. property_to_blocklist(
			{
				"name": "speed",
				"type": TYPE_VECTOR2,
				"category": "Physics | Velocity",
			}
		)
	)
	block_list.append_array(property_blocks)

	return block_list

And how to customize this code?