【代码】Godot官网入门2D游戏《Dodge the Creeps》(含注解)

本来在学习 Unity,看到有网友在推荐这款 godot 游戏引擎,听说是跨平台的框架,性能不错,也容易入门,找到官网上的例子试试。

以下是我按照官网上的操作进行编程后的代码:

玩家场景

创建玩家场景,绘制玩家、碰撞区域,设置移动动画及碰撞效果等

extends Area2D

signal hit

@export var speed = 400 # How fast the player will move (pixels/sec). 玩家移动速度
var screen_size # Size of the game window. 游戏窗口大小

# Called when the node enters the scene tree for the first time.
# 节点第一次进入场景树时,调用该函数
func _ready() -> void:
	# 获取窗口大小
	screen_size = get_viewport_rect().size
	# 初次加载时,隐藏玩家
	hide()

# Called every frame. 'delta' is the elapsed time since the previous frame.
# 每帧调用一次。'delta' 是自上一帧以来经过的时间。
func _process(delta: float) -> void:
	# 按键移动
	var velocity = Vector2.ZERO
	if Input.is_action_pressed("move_right"):
		velocity.x += 1
	if Input.is_action_pressed("move_left"):
		velocity.x -= 1
	if Input.is_action_pressed("move_down"):
		velocity.y += 1
	if Input.is_action_pressed("move_up"):
		velocity.y -= 1
	
	# 运动计算及动画播放
	if velocity.length() > 0:
		velocity = velocity.normalized() * speed
		$AnimatedSprite2D.play()
	else:
		$AnimatedSprite2D.stop()
		
	position += velocity * delta
	position = position.clamp(Vector2.ZERO, screen_size) # 限制玩家在屏幕内活动
	
	# 左右移动动画
	if velocity.x != 0:
		$AnimatedSprite2D.animation = "walk"
		$AnimatedSprite2D.flip_v = false
		# 左移水平翻转
		$AnimatedSprite2D.flip_h = velocity.x < 0
	
	# 上下移动动画
	if velocity.y != 0:
		$AnimatedSprite2D.animation = "up"
		# 下移竖直翻转
		$AnimatedSprite2D.flip_v = velocity.y > 0

# 开始
func start(pos):
	# 显示在坐标位置
	position = pos
	show()
	$CollisionShape2D.disabled = false

# 接触动作
func _on_body_entered(body: Node2D) -> void:
	# Player disappears after being hit.
	# 接触后玩家消失,发出被攻击信号
	hide()
	hit.emit()
	# Must be deferred as we can't change physics properties on a physics callback.
	# 当前物理处理完成后,禁用玩家的碰撞检测
	$CollisionShape2D.set_deferred("disabled", true)

敌人场景

绘制敌人动画,并在敌人离开屏幕后标记删除节点

extends RigidBody2D

# Called when the node enters the scene tree for the first time.
# 节点第一次进入场景树时,调用该函数
func _ready() -> void:
	var mob_types = Array($AnimatedSprite2D.sprite_frames.get_animation_names())
	$AnimatedSprite2D.animation = mob_types.pick_random()

# 敌人离开屏幕,标记删除该节点
func _on_visible_on_screen_notifier_2d_screen_exited() -> void:
	queue_free()

游戏主场景

开始游戏、生成敌人,以及结束游戏

extends Node

# 导出变量,用于在编辑器中指定 Mob Scene(敌人/移动物体 场景)
@export var mob_scene: PackedScene
var score

# Called when the node enters the scene tree for the first time.
# 节点第一次进入场景树时,调用该函数
func _ready() -> void:
	#new_game()
	pass # Replace with function body.

# 开始新游戏
func new_game():
	score = 0
	$Player.start($StartPosition.position)
	$StartTimer.start()
	$HUD.update_score(score)
	$HUD.show_message("Get Ready")
	get_tree().call_group("mobs", "queue_free")
	$BGMusic.play()	

# 游戏结束
func game_over():
	$ScoreTimer.stop()
	$MobTimer.stop()
	$HUD.show_game_over()
	$BGMusic.stop()
	$DeathSound.play()

# 玩家受到攻击
func _on_player_hit() -> void:
	game_over()
	
# 敌人/移动物体 计时器,用于生成敌人/移动物体
func _on_mob_timer_timeout() -> void:
	# 实例化 Mob Scene
	var mob = mob_scene.instantiate()
	
	# 根据 Path2D 随机选择生成位置
	var mob_spawn_location = $MobPath/MobSpawnLocation
	mob_spawn_location.progress_ratio = randf()
	
	# Set the mob's postion to the random location.
	mob.position = mob_spawn_location.position
	
	# 将敌人方向设置为与路线垂直
	var direction = mob_spawn_location.rotation + PI / 2
	
	# 设置随机方向
	direction += randf_range(-PI / 4, PI / 4)
	mob.rotation = direction
	
	# 设置随机速度 [150.0, 250.0]
	var velocity = Vector2(randf_range(150.0, 250.0), 0.0)
	mob.linear_velocity = velocity.rotated(direction)
	
	# 将实例添加到主场景中
	add_child(mob)

# 分数定时 +1
func _on_score_timer_timeout() -> void:
	score += 1
	$HUD.update_score(score)

# 点击开始按钮后,StartTimer开始计时,(2秒)后,启动敌人生成计时器及分数刷新计时器
func _on_start_timer_timeout() -> void:
	$MobTimer.start()
	$ScoreTimer.start()

游戏信息显示(结算信息等)

游戏的欢迎词及结算信息

extends CanvasLayer

# Notifies `Main` node that the button has been pressed
# 通知主节点:开始游戏
signal start_game
	
# 提示词
func show_message(text):
	$Message.text = text
	$Message.show()
	$MessageTimer.start()
	
# 提示游戏结束
func show_game_over():
	show_message("Game Over")
	# Wait until the MessageTimer has counted down
	# 等待消息计时器(用于显示“Game Over”的停顿)
	await $MessageTimer.timeout
	
	$Message.text = "Dodge the Creeps!"
	$Message.show()
	# Make a one-shot timer and wait for it to finish.
	# 创建一次性计时器并等待其完成(1秒钟后显示“开始”按钮)
	await get_tree().create_timer(1.0).timeout
	$StartButton.show()
	
# 展示分数
func update_score(score):
	$ScoreLabel.text = str(score)
	
# 按下开始按钮
func _on_start_button_pressed() -> void:
	$StartButton.hide()
	start_game.emit()
	
# 消息计时器超时即退出消息展示
func _on_message_timer_timeout() -> void:
	$Message.hide()

游戏效果

最终的游戏效果如下图:
在这里插入图片描述

遇到的问题

1. mob_scene、MobPath、MobSpawnLocation单词不要拼错(比如不要拼成“mod”),同一变量名或相关联的变量名注意在各处保持一致;
2. 如果按照官网的教程一步步进行开发,可能遇到找不到可绑定start_game信号的new_game函数问题(截至2025年3月7日):

a. 点击“Main”节点->左上角初始化子场景->选择HUD场景;
b. 创建完成HUD子场景后,文件系统选中主场景 -> 选中HUD节点 -> 右侧选择Node标签页 -> 点击start_game函数 -> 点击pick按钮选择接收函数 -> 选择new_game函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值