Last snake update: 877 chars. Not sure if I can go much lower with the same “architecture”. It’s getting hard ![]()
I managed to get the character count down to 160!
extends CharacterBody2D
func _process(d):velocity.y+=d*1e3;velocity.x=Input.get_axis('l','r')*600;move_and_slide()
func j():if is_on_floor():velocity.y=-700
I accomplished this by creating a Button with a shortcut mapped to the same action as jump. Then, I connected the button’s pressed signal to the j method. This saves having to type Input.is_action_just_pressed!
I tried also doing this with left and right, but you can’t hold down a button with a shortcut key ![]()
Nice, but if I was making the rules I’d forbid relying on any pre-existing node context except the existence of the node the script is attached to.
I squeezed the snake down to 855 chars:
extends Node2D;var s=[];var t={};var m=Vector2i.UP;var l;var a;var c="#ff8800";var n;var v=Vector2i.ONE
var q=4194319;var k={q+1:m,q+3:Vector2i.DOWN,q:Vector2i.LEFT,q+2:Vector2i(1,0)}
func _draw():for r in t:draw_rect(Rect2(r*32,v*31),t[r]);draw_string(ThemeDB.fallback_font,Vector2(520,18),l)
func _ready():Engine.max_fps=6;x(v*8);l="-1";for i in 16:o(0,i);o(15,i);o(i,0);o(i,15)
func o(x,y,c="#a0a0a0"):t[Vector2i(x,y)]=c
func x(p):n=t.get(p);s.push_front(p);o(p.x,p.y);return n==c
func _input(e):if e is InputEventKey&&e.pressed:n=k.get(e.keycode,m);m=n if n!=-m else m;if!is_processing():get_tree().reload_current_scene()
func _process(d):
if t.has(s[0]+m)&&s[0]+m!=a:set_process(0);l+="-GMOVR"
elif x(s[0]+m)||!a:
l=str(l.to_int()+1);while 1:a=Vector2i(randi()%15,randi()%15)+v;if!t.has(a):o(a.x,a.y,c);break
else:t.erase(s[-1]);s.pop_back()
queue_redraw()
The only possibility for further significant shrinkage would be in completely getting rid of Vector2i and pack every coordinate into a 16 bit integer, unpacking only for drawing.
I had the same thought. If this is Node Golf instead of Code Golf, that would be different.
We can squeeze it even more if we change the VECTOR2i,InputEventKey,pressed,return,set_process,_process,_input,randi,quene_redraw,pop_back,while,_draw,push_front and many more built in func/method to single or 2 char by changing the source code and recompiling Godot : >
You can change Vector2i.DOWN to -Vector2i.UP. That saves one character.
You could forbid that too and embed the code in the .tscn file. Then you have just one file that holds the whole game logic.
[gd_scene format=3 uid="uid://cvdgud21ohiqo"]
[sub_resource type="GDScript" id="i"]
script/source = "extends Node2D;var s=[];var t={};var m=Vector2i.UP;var l;var a;var c='#ff8800';var n;var v=Vector2i.ONE
var q=4194319;var k={q+1:m,q+3:Vector2i.DOWN,q:Vector2i.LEFT,q+2:Vector2i(1,0)}
func _draw():for r in t:draw_rect(Rect2(r*32,v*31),t[r]);draw_string(ThemeDB.fallback_font,Vector2(520,18),l)
func _ready():Engine.max_fps=6;x(v*8);l='-1';for i in 16:o(0,i);o(15,i);o(i,0);o(i,15)
func o(x,y,c='#a0a0a0'):t[Vector2i(x,y)]=c
func x(p):n=t.get(p);s.push_front(p);o(p.x,p.y);return n==c
func _input(e):if e is InputEventKey&&e.pressed:n=k.get(e.keycode,m);m=n if n!=-m else m;if!is_processing():get_tree().reload_current_scene()
func _process(d):
if t.has(s[0]+m)&&s[0]+m!=a:set_process(0);l+='-GMOVR'
elif x(s[0]+m)||!a:
l=str(l.to_int()+1);while 1:a=Vector2i(randi()%15,randi()%15)+v;if!t.has(a):o(a.x,a.y,c);break
else:t.erase(s[-1]);s.pop_back()
queue_redraw()"
[node name="n" type="Node2D" unique_id=64373920]
script = SubResource("i")
Although there isn’t that much you can chip off the .tscn code itself (at least I couldn’t find a way to get rid of it without breaking it), so it seems to be more interesting sticking to the pure .gd file and allow to attach it to a preexisting Node.
I just realized that the more threads there are with GDScript code golf, the more confusing and unreadable LLM AI answers will become. This made me laugh.
Can you imagine a Godot newbie asking LLM how to make a snake game in Godot and this is what it spits out? I love it, can’t wait to find their questions on the forum.
I think it’s interesting, that -Vector2i.UP is shorter code, but more token.
Fair enough. But wouldn’t “node golf” be trying to get the least amount of nodes possible? Which is always 1.
I don’t know the rules of node golf.
Well we can implement it entirely in source and just do snake() from GDScript ![]()
Good catch. I could have in fact just do -m as I assign UP to m the line before. However, I eliminated vectors completely. See further below.
Why else would I bother with this ![]()
Putting everything into a tscn may be a good format if nodes are to be included, as introducing a node would then have some character cost. It can be called “Code&Node Golf”.
The following is hopefully the final version. I ditched vectors and packed coordinates into ints, 4 bits + 1 sign bit per component, standard two’s complement encoding, packed into two lower bytes of the integer. I could have packed tight into total of 10 bits but there probably wouldn’t be much gain, maybe a couple chars less in total. It’s getting seriously obfuscated now. Exactly 777 chars in length:
extends Node2D;var s=[];var t={};var m=7936;var l;var a;var c="#ff8800";var n
var q=4194319;var k={q+1:m,q+3:256,q:31,q+2:1}
func _draw():draw_string(ThemeDB.fallback_font,Vector2(520,18),l);for r in t:draw_rect(Rect2((r&15)*32,(r>>8)*32,31,31),t[r])
func _ready():Engine.max_fps=6;x(2056);l="-1";for i in 16:o(i);o(3840+i);o(i<<8);o((i<<8)+15)
func o(p,c=Color()):t[p]=c
func x(p):n=t.get(p);s.push_front(p);o(p);return n==c
func _input(e):if e is InputEventKey&&e.pressed:n=k.get(e.keycode,m);m=n if m&n==0 else m;if!is_processing():get_tree().reload_current_scene()
func _process(d):
n=s[0]+m&3855
if t.has(n)&&n!=a:set_process(0);l+="-GAMEOVER"
elif x(n)||!a:
l=str(l.to_int()+1);while 1:a=randi()+257&3855;if!t.has(a):o(a,c);break
else:t.erase(s[-1]);s.pop_back()
queue_redraw()
This is probably nearing the limits of my abilities. If someone wishes to take it further - be my guest.
I’ve been trying to make codeless snake, but I’ve run into some difficulties.
So, I’m using a 3x3 grid to test things. I have 3 buttons with the left arrow key as a shortcut, and 3 buttons with the right arrow key as a shortcut. Each button is for a different column (I haven’t done rows yet). I also have a spinbox and an AnimationPlayer. And a ColorRect representing the snake.
Only one left button and one right button can be enabled at one time. I’ve connected the pressed signal of each button to a ton of other functions so that when each button is pressed, it disables itself, disables the corresponding button of the opposite direction, enables the next two buttons if possible, and sets the value of the SpinBox.
The SpinBox has its value_changed signal connected to the AnimationPlayer’s seek method. The AnimationPlayer has a single animation that auto plays (with speed scale set to 0) and that animation moves the snake along the x-axis. The value from the SpinBox is used directly in the seek function.
The issue I am running into is that I need a node for every row and every column, and it’s really tedious to connect all the signals manually. I wonder if there’s a better way to do this? (Don’t say “use code”
)
I won’t, but I’ll say this: If you pull this off, I’ll eat my hat ![]()
Codeless game of Snake:
Use an animation player and have it play a predetermined game of Snake
Snake in 695 691 chars. I’m done with it, for realz ![]()
extends Panel;var s=[];var t={};var m=7936;var l="";var a;var c="ff8800";var n
var q=4194319;var k={q+1:m,q+3:256,q:31,q+2:1}
func _draw():draw_string(get_theme_font(l),Vector2(520,20),l);for r in t:draw_rect(Rect2(r*32&511,r>>3,31,31),t[r])
func _ready():Engine.max_fps=6;x(2056);for i in 16:o(i);o(3840+i);n=i<<8;o(n);o(n+15)
func o(p,c=Color()):t[p]=c
func x(p):n=t.get(p);s.push_front(p);o(p);return n==c
func _input(e):n=k.get(e.get("keycode"),m);if!m&n:m=n
elif len(l)>2:get_tree().reload_current_scene()
func _process(d):queue_redraw();n=s[0]+m&3855;if n in t&&n-a:set_process(0);l+="-X"
elif x(n)||!a:
l=str(int(l)+1);a=1;while a in t:a=randi()+257&3855
o(a,c)
else:t.erase(s[-1]);s.pop_back()
Sure buddy : ) Just wait till a new discovery comes along that can shave off even more.
This is honestly impressive. Please don’t stop ![]()
Impressive.
We need to see a flappy bird next.
