Wooden Railway started, for Game Jam in need of some 'improvement'

Godot Version

v4.7.beta2.official [777579205]

Question

I've started a Project for a Game Jam, for end of this month. The idea is to place Wooden Train tracks on a board, like a jigsaw puzzle. Once a circuit is created, a loco would appear and run around the circuit. That's the idea, but I'm quite some way away from there..!
It's 3D, but for moving the track elements, the view is 'Top Down'. For the moment, only two straight tracks and one curve are on the board. These can be moved, by selecting with the mouse, Left click to place it. If the tongue is over a hole, this locks the piece (turns Red...). To free a piece, Right click. Whilst not locked, Right click rotates the piece 90°. A Right click on a locked piece frees it (turns Green...).
All fine for now, so where's the problem..? Hmm... It's a bit 'clunky'; if the mouse pointer moves too fast, the piece gets lost.
The main issue is the way that the pieces need, for now, individual scripts, and there should be a lot more pieces to come..! Soooooo...

Before going too far, could I have some advice as to how better structure it all. I can do what it takes, as long as it’s within the grasp of a slow-witted old duffer (yes, that’s me…), and does not imply use of elaborate plugins, artificial intelligence or uncouth language..! I’ve attached a link to a ā€˜zip’ file on my Google Drive, containing all of the Project (without the ā€˜.godot’ folder, naturally). It’s quite small, and, I hope, fairly easy to follow, but needs suggestions for improvement. The ā€˜biggy’ is the addressing of the piece, and its label, in the code, for each piece. That’s not good, for extending to lots of pieces; how to do better, please..?
Thanks in advance for any advice and/or suggestions; meanwhile…

Have a great day.

Google Drive : Wood_Trai.zip…

You probably don’t need individual scripts for each piece. Just write a single script that all pieces will share, with exported variables.

Make each different track piece a standalone scene, so you can modify the exported variables in the Inspector.

Yes, thanks for that; I’ve been trying to get that to work, but there’s a snag, it seems. The code which reacts to the signal has to address the specific Object, which I can’t seem to decouple, or address from outside the Object. Here’s the code in question…


func _process(_delta):
	if lv_dragging == true:
		if get_mouse_world_position() != null:
			lv_offset = get_mouse_world_position()
			var lv_x = lv_offset.x
			var lv_z = lv_offset.z
			$stra_01_54.global_position = Vector3(lv_x,0.0,lv_z)

func _on_static_body_3d_input_event(_camera, event, _event_position, _normal, _shape_idx):
	if event is InputEventMouseButton:
		if event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed():
			print("Dragging")
			if lv_dragging == false:
				if lv_lock == false:
					lv_dragging = true
			else:
				print("Over")
				lv_dragging = false
				if lv_conn_flag == true:
					lv_lock = true
					print("Locked")
					$stra_01_54/Label3D.modulate = Color(1.0,0.0,0.0,1)
		if event.button_index == MOUSE_BUTTON_RIGHT and event.is_pressed():
			if lv_lock == true:
				lv_lock = false
				lv_conn_flag = false
				print("Unlocked")
				$stra_01_54/Label3D.modulate = Color(0.0,1.0,0.0,1)
			else:
				print("Rotate") 
				lv_dragging = false
				if lv_conn_flag == true:
					lv_lock = true
				$stra_01_54.rotate_y(deg_to_rad(int(90)))
, 

...and here's the Layout tree and overall Editor view...

It’s the MeshInstance3d that’s being addressed, for Mouse position detection, Rotation, and changing the Label3D colour. If I could address this outside of the script, I think that a common script would work, but how to address this MeshInstance3D..?

If I’m understanding correctly what you’re trying to do, you can store the MeshInstance3D in the script:

  1. Declare a variable to store the MeshInstance3D in the script, e.g. ā€˜var mesh_node: MeshInstance3D’.

  2. In _ready(), assign the MeshInstance3D to mesh_node.

It looks like your MeshInstance3D nodes have a different name for each piece, but they’re the only direct child of the root node. So this should work:

for child in self.get_children():
mesh_node = child

If you add more direct children to any piece’s root node later, the above won’t work anymore. In that case, you may want to add a condition to check that the child is a MeshInstance3D:

for child in self.get_children():
if child is MeshInstance3D:
mesh_node = child

Of course, that won’t work either if the additional children are also MeshInstance3D.

Another option is to make mesh_node an exported variable, and assign the MeshInstance3D manually in the Inspector:

@export var mesh_node: MeshInstance3D

You should be able to drag the MeshInstance3D from the node tree to the mesh_node field in the Inspector. If each track piece variant is a standalone scene, that’s doable. It’s just more manual work.

Hope that helps!

Edit: forgot to add - after that, any external code just needs address mesh_node on the track piece. For example:

$ā€Layout/track_pieceā€.mesh_node → That finds the MeshInstance3D.

Yes, these are the suggestions I was hoping for. I’ll have to break open another tube of aspirin and try to incorporate these (foreign, to me…) notions, but it’s on the right track. The actual structure of the track pieces shouldn’t change much, now (it took me long enough to get this structure to work..!), but there will be other, identical and different, pieces to add to the board. It would make sense to have most of the code common, and not specific to each piece. That would work, but would be a real ā€˜pig’s ear’ of code. Dinner first, then I’ll try out these methods. Thanks again. :slight_smile:

You’re welcome! The wooden railway brought back some nice childhood memories :slight_smile:

I also wrote code for train tracks a year ago, so I’ve been there!

Thanks to the help offered above ^^, I was able to render the code ā€˜anonymous’, common to all of the pieces. Using the same principles, I could also have colour-coding on the pieces, to indicate their state, or condition (waiting, moving or locked…). I have enough pieces on the virtual ā€˜board’ to complete a closed circuit for the first time..! I added some background music, just because, and need to tidy up a little, before deciding how to turn it into something a bit less ā€˜clunky’. Progress has been made, then, but there is more progress to come before signing it off.
I’m very pleased with the advice given; many thanks. :slight_smile:

You’re welcome, I’m glad I could be of help! Train systems have a reputation for being hard to do, but I also learned a lot from making one.

I’d love to see the final result if you post it somewhere later when it’s finished!

I finished the Project (but are they ever really finished..?) with a lot less going on than originally imagined, but the short delay for the Game Jam meant that I consider it a miracle that anything at all got done..! I sent it off to the Jam; there’s a copy of the Windows ā€˜exe’ file on my Google drive, for anyone to download, if interested. Be aware that it’s extremely modest, of course; unlikely to overtake Tetris in the game charts..! At the very last minute, I even added a screen overlay with the mouse and keyboard controls. Here’s the link to it …

Wood_Rail.exe on my Google Drive …

It’s not much, but at least I got ā€˜not much’ done..! Miracle, I tell’ee; miracle..!

Peace.

Edit : I see that there’s now an Itch.io link to download it..! Here…

# Wooden Railway for Game Jam…