新建一个场景(snake),创建头部(Sprite2D)。
声明方向(direction),声明速度(speed),在物理帧 `_physics_process()` 中移动,每帧累加,直至累加至一格才会执行移动,并保留余数。
func _physics_process(delta: float):
elapse += delta * speed
var step = floor(elapse / UNIT)
if step == 0:
return
elapse = (elapse as int) % UNIT
if direciton == Vector2.UP:
position.y -= UNIT
elif direction == Vector2.DOWN:
position.y += UNIT
elif direction == Vector2.LEFT:
position.x -= UNIT
elif direction == Vector2.RIGHT:
position.x += UNIT
声明一个数组(Array)来保存可以动态增长的身体,每次吃食物时,向数组中增加一个新部分(Sprite2D),位置和头部相同。
func grow() -> void:
var tail := Sprite2D.new()
tail.texture = snake_head.texture
tail.position = snake_head.position
tail.scale = Vector2(0.9, 0.9)
body_parts.append(tail)
snake_body.add_child(tail)
每次移动,先保存头部当前的位置,然后头部向对应方向移动一格,再取数组最后一节,位置改成头部原来的位置,并把这个节点放到数组的最前面,视觉上看起来就是整条蛇跟随头部一起移动了。
if not body_parts.is_empty():
var last = body_parts.pop_back()
last.position = current_head_position
body_parts.insert(0, last)
遍历对应身体的数组,如果有一个身体部分与头部位置相同,就认为碰撞。
func is_collided(new_position: Vector2):
for body_part in body_parts:
if body_part.position.x == new_position.x and body_part.position.y == new_position.y:
return true
return false
游戏启动后,随机更新食物的坐标。
蛇每次移动后,判断是否和食物碰撞,如果碰撞,身体长度增加,随机更新食物的位置,如果食物移动到蛇身体上,要再次更新,保证食物更新到空地。
func _process(_delta: float) -> void:
if is_zero_approx(snake.snake_head.position.x - snake_food.position.x) and is_zero_approx(snake.snake_head.position.y - snake_food.position.y):
snake.grow()
move_random()
while snake.is_collided(snake_food.position):
move_random()
回来看蛇本体和食物之外的配套组件,创建一个Label作为计分板,暂停界面是包含两行文字的一个组件(Control)。
每次蛇头部与食物碰撞,会触发一个信号(snake_grow),携带蛇身体数组作为参数,接收到这个信号后,根据蛇身体数组的长度更新计分板分数。
暂停界面是包含两行文字的一个组件(Control)。
游戏启动时,暂停界面默认显示,蛇本体状态为暂停(active=false),按任何健启动游戏。启动时,清空蛇身体数组,随机生成蛇头部位置,蛇身体长度增加一节,速度设为默认,启动游戏(active=true)。
func restart_game():
snake.restart()
$StartScreen.set_visible(false)
func restart():
for body_part in body_parts:
body_part.queue_free()
body_parts = []
var x = (floor(randf_range(0, WIDTH)) * UNIT + OFFSET) as int
var y = (floor(randf_range(0, HEIGHT)) * UNIT + OFFSET) as int
snake_head.position = Vector2(x, y)
grow()
speed = DEFAULT_SPEED
active = true
蛇头部与身体碰撞后,触发一个事件(snake_terminate)。设置蛇本体停止,显示暂停界面。
func terminate_game():
snake.active = false
$StartScreen.set_visible(true)
实体