嘿, 一碰到这godot游戏引擎啊,就觉得这开发思维真他x的不一样. 跟着官方教程走一遍, 走着走着, 也就入乡随俗了.反正走一步看一步,说不定最后还真能搞出点啥名堂来. 你说有官方教程了,还做一遍是不是有毛病? 话不能这么说, 官方教程你可能还看不懂呢! 细节解释部分看官网,咱们只负责能够实现游戏项目.
游戏引擎 ⬇️
游戏素材⬇️
创建项目⬇️
输入素材⬇️
解压后的内容拖到左下角(资管管理区)
项目设置⬇️
修改窗口宽高, 以及模式
玩家场景⬇️
创建玩家⬇️
点击+ ➡️ 搜索ar ➡️ 选择Area2D ➡️ 创建节点
节点重命名⬇️
添加动画⬇️
创建动画控制界面⬇️
制作序列动画⬇️
添加碰撞区域⬇️
创建碰撞区域⬇️
调整碰撞区域⬇️
鼠标滚轮按下: (不要松开), 此时可以拖动精灵
鼠标滚轮滑动: 缩放精灵
玩家代码⬇️
创建脚本文件⬇️
创建控制按键⬇️
以此类推,创建上下左右⬇️
绑定键盘按钮⬇️
以此类推,绑定上下左右⬇️
也可以同时绑定wasd
代码知识⬇️
用键盘移动palyer⬇️
extends Area2D
var 速度 := 300
var 方向 := Vector2(0,0)
func _ready() -> void:
pass
func _process(delta: float) -> void:
方向 = Vector2(0,0)
if Input.is_action_pressed("move_right") :
方向.x = 方向.x + 1
if Input.is_action_pressed("move_left") :
方向.x = 方向.x - 1
if Input.is_action_pressed("move_down") :
方向.y = 方向.y + 1
if Input.is_action_pressed("move_up") :
方向.y = 方向.y - 1
if 方向.length() > 0 :
方向 = 方向.normalized() * 速度
position += 方向 * delta
pass
运行游戏测试⬇️
设置玩家不能跑出屏幕⬇️
extends Area2D
var 速度 := 300
var 方向 := Vector2(0,0)
func _ready() -> void:
pass
func _process(delta: float) -> void:
方向 = Vector2(0,0)
if Input.is_action_pressed("move_right") :
方向.x = 方向.x + 1
if Input.is_action_pressed("move_left") :
方向.x = 方向.x - 1
if Input.is_action_pressed("move_down") :
方向.y = 方向.y + 1
if Input.is_action_pressed("move_up") :
方向.y = 方向.y - 1
if 方向.length() > 0 :
方向 = 方向.normalized() * 速度
position += 方向 * delta
position = position.clamp(Vector2(0,0), 屏幕宽高)
pass
方向有变化时,播放动画⬇️
extends Area2D
var 速度 := 300
var 方向 := Vector2(0,0)
func _ready() -> void:
pass
func _process(delta: float) -> void:
方向 = Vector2(0,0)
if Input.is_action_pressed("move_right") :
方向.x = 方向.x + 1
if Input.is_action_pressed("move_left") :
方向.x = 方向.x - 1
if Input.is_action_pressed("move_down") :
方向.y = 方向.y + 1
if Input.is_action_pressed("move_up") :
方向.y = 方向.y - 1
if 方向.length() > 0 :
方向 = 方向.normalized() * 速度
$AnimatedSprite2D.play()
else:
$AnimatedSprite2D.stop()
position += 方向 * delta
position = position.clamp(Vector2(0,0), 屏幕宽高)
pass
播放指定动画⬇️
extends Area2D
var 速度 := 300
var 方向 := Vector2(0,0)
var 屏幕宽高 := Vector2(0,0)
func _ready() -> void:
屏幕宽高 = get_viewport_rect().size
pass
func _process(delta: float) -> void:
方向 = Vector2(0,0)
if Input.is_action_pressed("move_right") :
方向.x = 方向.x + 1
if Input.is_action_pressed("move_left") :
方向.x = 方向.x - 1
if Input.is_action_pressed("move_down") :
方向.y = 方向.y + 1
if Input.is_action_pressed("move_up") :
方向.y = 方向.y - 1
if 方向.length() > 0 :
方向 = 方向.normalized() * 速度
$AnimatedSprite2D.play()
else:
$AnimatedSprite2D.stop()
position += 方向 * delta
position = position.clamp(Vector2(0,0), 屏幕宽高)
if 方向.x != 0 :
$AnimatedSprite2D.animation = "walk"
$AnimatedSprite2D.flip_h = (方向.x < 0)
$AnimatedSprite2D.flip_v = false
if 方向.y != 0 :
$AnimatedSprite2D.animation = "up"
$AnimatedSprite2D.flip_v = (方向.y > 0)
pass
实现隐藏玩家 ⬇️
extends Area2D
var 速度 := 300
var 方向 := Vector2(0,0)
var 屏幕宽高 := Vector2(0,0)
func _ready() -> void:
屏幕宽高 = get_viewport_rect().size
hide()
pass
func _process(delta: float) -> void:
....内容保持不变
准备碰撞敌人功能⬇️
创建自定义信号方法
extends Area2D
signal 受伤
var 速度 := 300
var 方向 := Vector2(0,0)
var 屏幕宽高 := Vector2(0,0)
func _ready() -> void:
屏幕宽高 = get_viewport_rect().size
hide()
pass
func _process(delta: float) -> void:
....内容保持不变
制作碰撞信号 ⬇️
碰撞时发生事件 ⬇️
extends Area2D
signal 受伤
var 速度 := 300
var 方向 := Vector2(0,0)
var 屏幕宽高 := Vector2(0,0)
func _ready() -> void:
屏幕宽高 = get_viewport_rect().size
hide()
pass
func _process(delta: float) -> void:
方向 = Vector2(0,0)
if Input.is_action_pressed("move_right") :
方向.x = 方向.x + 1
if Input.is_action_pressed("move_left") :
方向.x = 方向.x - 1
if Input.is_action_pressed("move_down") :
方向.y = 方向.y + 1
if Input.is_action_pressed("move_up") :
方向.y = 方向.y - 1
if 方向.length() > 0 :
方向 = 方向.normalized() * 速度
$AnimatedSprite2D.play()
else:
$AnimatedSprite2D.stop()
position += 方向 * delta
position = position.clamp(Vector2(0,0), 屏幕宽高)
if 方向.x != 0 :
$AnimatedSprite2D.animation = "walk"
$AnimatedSprite2D.flip_h = (方向.x < 0)
$AnimatedSprite2D.flip_v = false
if 方向.y != 0 :
$AnimatedSprite2D.animation = "up"
$AnimatedSprite2D.flip_v = (方向.y > 0)
pass
func _on_body_entered(body: Node2D) -> void:
hide()
$CollisionShape2D.set_deferred("disabled", true)
受伤.emit()
pass
玩家初始化 ⬇️
extends Area2D
signal 受伤
var 速度 := 300
var 方向 := Vector2(0,0)
var 屏幕宽高 := Vector2(0,0)
func _ready() -> void:
屏幕宽高 = get_viewport_rect().size
hide()
pass
func _process(delta: float) -> void:
方向 = Vector2(0,0)
if Input.is_action_pressed("move_right") :
方向.x = 方向.x + 1
if Input.is_action_pressed("move_left") :
方向.x = 方向.x - 1
if Input.is_action_pressed("move_down") :
方向.y = 方向.y + 1
if Input.is_action_pressed("move_up") :
方向.y = 方向.y - 1
if 方向.length() > 0 :
方向 = 方向.normalized() * 速度
$AnimatedSprite2D.play()
else:
$AnimatedSprite2D.stop()
position += 方向 * delta
position = position.clamp(Vector2(0,0), 屏幕宽高)
if 方向.x != 0 :
$AnimatedSprite2D.animation = "walk"
$AnimatedSprite2D.flip_h = (方向.x < 0)
$AnimatedSprite2D.flip_v = false
if 方向.y != 0 :
$AnimatedSprite2D.animation = "up"
$AnimatedSprite2D.flip_v = (方向.y > 0)
pass
func _on_body_entered(body: Node2D) -> void:
hide()
$CollisionShape2D.disabled = true
受伤.emit()
pass
func start(pos) :
position = pos
show()
$CollisionShape2D.disabled = false
敌人篇⬇️
敌人场景⬇️
添加刚体⬇️
创建节点⬇️
设置刚体⬇️
设置动画⬇️
设置碰撞⬇️
npc代码⬇️
创建脚本⬇️
随机播放动画⬇️
extends RigidBody2D
func _ready() -> void:
var npcnames = $AnimatedSprite2D.sprite_frames.get_animation_names()
var npc = randi() % npcnames.size()
$AnimatedSprite2D.play( npcnames[npc] )
pass
func _process(delta: float) -> void:
pass
销毁屏幕外npc⬇️
extends RigidBody2D
func _ready() -> void:
var npcnames = $AnimatedSprite2D.sprite_frames.get_animation_names()
var npc = randi() % npcnames.size()
$AnimatedSprite2D.play( npcnames[npc] )
pass
func _process(delta: float) -> void:
pass
func _on_visible_on_screen_notifier_2d_screen_exited() -> void:
queue_free()
pass
主场景篇⬇️
主场景⬇️
创建node节点⬇️
实例化玩家场景⬇️
创建4个节点⬇️
设置时间细节⬇️
设置玩家初始位置
生成npc范围⬇️
主场景脚本⬇️
extends Node
@export var npc : PackedScene
var score
func _ready() -> void:
pass
func _process(delta: float) -> void:
pass
加载npc场景⬇️
玩家受伤信号 ⬇️
extends Node
@export var npc : PackedScene
var score
func _ready() -> void:
pass
func _process(delta: float) -> void:
pass
func game_over() -> void:
$Timer_npc.stop()
$Timer_score.stop()
pass
重新开始⬇️
extends Node
@export var npc : PackedScene
var score
func _ready() -> void:
pass
func _process(delta: float) -> void:
pass
func game_over() -> void:
$Timer_npc.stop()
$Timer_score.stop()
pass
func newgame() :
score = 0
$player.start( $Marker2D_startpos.position )
$Timer_start.start()
分数计时⬇️
extends Node
@export var npc : PackedScene
var score
func _ready() -> void:
pass
func _process(delta: float) -> void:
pass
func game_over() -> void:
$Timer_npc.stop()
$Timer_score.stop()
pass
func newgame() :
score = 0
$player.start( $Marker2D_startpos.position )
$Timer_start.start()
func _on_timer_score_timeout() -> void:
score += 1
pass
开始计时⬇️
extends Node
@export var npc : PackedScene
var score
func _ready() -> void:
pass
func _process(delta: float) -> void:
pass
func game_over() -> void:
$Timer_npc.stop()
$Timer_score.stop()
pass
func newgame() :
score = 0
$player.start( $Marker2D_startpos.position )
$Timer_start.start()
func _on_timer_score_timeout() -> void:
score += 1
pass
func _on_timer_start_timeout() -> void:
$Timer_npc.start()
$Timer_score.start()
pass
npc计时⬇️
extends Node
@export var npc : PackedScene
var score
func _ready() -> void:
pass
func _process(delta: float) -> void:
pass
func game_over() -> void:
$Timer_npc.stop()
$Timer_score.stop()
pass
func newgame() :
score = 0
$player.start( $Marker2D_startpos.position )
$Timer_start.start()
func _on_timer_score_timeout() -> void:
score += 1
pass
func _on_timer_start_timeout() -> void:
$Timer_npc.start()
$Timer_score.start()
pass
func _on_timer_npc_timeout() -> void:
# 获取NPC路径上的PathFollow2D节点
var npc_follow = $Path2D_npc/PathFollow2D
# 随机设置PathFollow2D在路径上的位置
npc_follow.progress_ratio = randf()
# 计算NPC的方向
var direction = npc_follow.rotation + PI/2
# 添加一些随机偏移到方向上
direction += randf_range(-PI/4 , PI/4)
# 设置随机速度
var velocity = Vector2(randf_range(155.0,250.0), 0.0)
# 实例化新的NPC
var new_npc = npc.instantiate()
# 设置NPC的位置、旋转和线性速度
new_npc.position = npc_follow.position
new_npc.rotation = direction
new_npc.linear_velocity = velocity.rotated(direction)
# 将新的NPC添加到场景中
add_child(new_npc)
ui篇⬇️
ui场景搭建⬇️
canvas节点⬇️
创建子节点⬇️
分数ui⬇️
信息ui⬇️
按钮ui⬇️
手动调整按钮位置和大小
计时器⬇️
ui代码
gui节点添加脚本⬇️
新增信号节点⬇️
extends CanvasLayer
signal start_game
func _ready() -> void:
pass
func _process(delta: float) -> void:
pass
显示文字 ⬇️
extends CanvasLayer
signal start_game
func _ready() -> void:
pass
func _process(delta: float) -> void:
pass
func show_message(text) :
$Label_message.text = text
$Label_message.show()
$Timer_message.start()
func show_gameover() :
show_message("游戏结束!")
await $Timer_message.timeout
$Label_message.text = "行不行啊?"
$Label_message.show()
await get_tree().create_timer(1.0).timeout
$Button_start.show()
更新分数⬇️
extends CanvasLayer
signal start_game
func _ready() -> void:
pass
func _process(delta: float) -> void:
pass
func show_message(text) :
$Label_message.text = text
$Label_message.show()
$Timer_message.start()
func show_gameover() :
show_message("游戏结束!")
await $Timer_message.timeout
$Label_message.text = "行不行啊?"
$Label_message.show()
await get_tree().create_timer(1.0).timeout
$Button_start.show()
func up_score(score) :
$Label_score.text = str( score )
按钮按下⬇️
extends CanvasLayer
signal start_game
func _ready() -> void:
pass
func _process(delta: float) -> void:
pass
func show_message(text) :
$Label_message.text = text
$Label_message.show()
$Timer_message.start()
func show_gameover() :
show_message("游戏结束!")
await $Timer_message.timeout
$Label_message.text = "行不行啊?"
$Label_message.show()
await get_tree().create_timer(1.0).timeout
$Button_start.show()
func up_score(score) :
$Label_score.text = str( score )
func _on_button_start_pressed() -> void:
$Button_start.hide()
start_game.emit()
pass
隐藏文字⬇️
extends CanvasLayer
signal start_game
func _ready() -> void:
pass
func _process(delta: float) -> void:
pass
func show_message(text) :
$Label_message.text = text
$Label_message.show()
$Timer_message.start()
func show_gameover() :
show_message("游戏结束!")
await $Timer_message.timeout
$Label_message.text = "行不行啊?"
$Label_message.show()
await get_tree().create_timer(1.0).timeout
$Button_start.show()
func up_score(score) :
$Label_score.text = str( score )
func _on_button_start_pressed() -> void:
$Button_start.hide()
start_game.emit()
pass
func _on_timer_message_timeout() -> void:
$Label_message.hide()
pass
返回主场景⬇️
添加gui的新游戏信号⬇️
extends Node
@export var npc : PackedScene
var score
func _ready() -> void:
pass
func _process(_delta: float) -> void:
pass
func game_over() -> void:
$Timer_npc.stop()
$Timer_score.stop()
$gui.show_gameover()
pass
func newgame() :
score = 0
$player.start( $Marker2D_startpos.position )
$Timer_start.start()
$gui.up_score( score )
$gui.show_message("准备开始!")
func _on_timer_score_timeout() -> void:
score += 1
$gui.up_score(score)
pass
func _on_timer_start_timeout() -> void:
$Timer_npc.start()
$Timer_score.start()
pass
func _on_timer_npc_timeout() -> void:
var npc_follow = $Path2D_npc/PathFollow2D
npc_follow.progress_ratio = randf()
var direction = npc_follow.rotation + PI/2
direction += randf_range(-PI/4 , PI/4)
var velocity = Vector2(randf_range(155.0,250.0), 0.0)
var new_npc = npc.instantiate()
new_npc.position = npc_follow.position
new_npc.rotation = direction
new_npc.linear_velocity = velocity.rotated( direction )
add_child( new_npc )
pass
游戏结束内容显示 ⬇️
extends Node
@export var npc : PackedScene
var score
func _ready() -> void:
pass
func _process(_delta: float) -> void:
pass
func game_over() -> void:
$Timer_npc.stop()
$Timer_score.stop()
$gui.show_gameover()
pass
func newgame() :
score = 0
$player.start( $Marker2D_startpos.position )
$Timer_start.start()
func _on_timer_score_timeout() -> void:
score += 1
pass
func _on_timer_start_timeout() -> void:
$Timer_npc.start()
$Timer_score.start()
pass
func _on_timer_npc_timeout() -> void:
var npc_follow = $Path2D_npc/PathFollow2D
npc_follow.progress_ratio = randf()
var direction = npc_follow.rotation + PI/2
direction += randf_range(-PI/4 , PI/4)
var velocity = Vector2(randf_range(155.0,250.0), 0.0)
var new_npc = npc.instantiate()
new_npc.position = npc_follow.position
new_npc.rotation = direction
new_npc.linear_velocity = velocity.rotated( direction )
add_child( new_npc )
pass
func new_game() -> void:
$gui.up_score( score )
$gui.show_message("准备开始!")
pass
gui分数更新⬇️
extends Node
@export var npc : PackedScene
var score
func _ready() -> void:
pass
func _process(_delta: float) -> void:
pass
func game_over() -> void:
$Timer_npc.stop()
$Timer_score.stop()
$gui.show_gameover()
pass
func newgame() :
score = 0
$player.start( $Marker2D_startpos.position )
$Timer_start.start()
func _on_timer_score_timeout() -> void:
score += 1
$gui.up_score(score)
pass
func _on_timer_start_timeout() -> void:
$Timer_npc.start()
$Timer_score.start()
pass
func _on_timer_npc_timeout() -> void:
var npc_follow = $Path2D_npc/PathFollow2D
npc_follow.progress_ratio = randf()
var direction = npc_follow.rotation + PI/2
direction += randf_range(-PI/4 , PI/4)
var velocity = Vector2(randf_range(155.0,250.0), 0.0)
var new_npc = npc.instantiate()
new_npc.position = npc_follow.position
new_npc.rotation = direction
new_npc.linear_velocity = velocity.rotated( direction )
add_child( new_npc )
pass
func new_game() -> void:
$gui.up_score( score )
$gui.show_message("准备开始!")
优化篇⬇️
npc场景⬇️
为npc添加组
主场景代码⬇️
销毁上一局中的npc
extends Node
@export var npc : PackedScene
var score
func _ready() -> void:
pass
func _process(_delta: float) -> void:
pass
func game_over() -> void:
$Timer_npc.stop()
$Timer_score.stop()
$gui.show_gameover()
pass
func newgame() :
score = 0
$player.start( $Marker2D_startpos.position )
$Timer_start.start()
$gui.up_score( score )
$gui.show_message("准备开始!")
get_tree().call_group("npcs", "queue_free")
func _on_timer_score_timeout() -> void:
score += 1
$gui.up_score(score)
pass
func _on_timer_start_timeout() -> void:
$Timer_npc.start()
$Timer_score.start()
pass
func _on_timer_npc_timeout() -> void:
var npc_follow = $Path2D_npc/PathFollow2D
npc_follow.progress_ratio = randf()
var direction = npc_follow.rotation + PI/2
direction += randf_range(-PI/4 , PI/4)
var velocity = Vector2(randf_range(155.0,250.0), 0.0)
var new_npc = npc.instantiate()
new_npc.position = npc_follow.position
new_npc.rotation = direction
new_npc.linear_velocity = velocity.rotated( direction )
add_child( new_npc )
pass
修改背景颜色⬇️
添加音频⬇️
代码播放音乐⬇️
extends Node
@export var npc : PackedScene
var score
func _ready() -> void:
pass
func _process(_delta: float) -> void:
pass
func game_over() -> void:
$Timer_npc.stop()
$Timer_score.stop()
$gui.show_gameover()
$AudioStreamPlayer2D_1.stop()
$AudioStreamPlayer2D_2.play()
pass
func newgame() :
score = 0
$player.start( $Marker2D_startpos.position )
$Timer_start.start()
$gui.up_score( score )
$gui.show_message("准备开始!")
get_tree().call_group("npcs", "queue_free")
$AudioStreamPlayer2D_1.play()
func _on_timer_score_timeout() -> void:
score += 1
$gui.up_score(score)
pass
func _on_timer_start_timeout() -> void:
$Timer_npc.start()
$Timer_score.start()
pass
func _on_timer_npc_timeout() -> void:
var npc_follow = $Path2D_npc/PathFollow2D
npc_follow.progress_ratio = randf()
var direction = npc_follow.rotation + PI/2
direction += randf_range(-PI/4 , PI/4)
var velocity = Vector2(randf_range(155.0,250.0), 0.0)
var new_npc = npc.instantiate()
new_npc.position = npc_follow.position
new_npc.rotation = direction
new_npc.linear_velocity = velocity.rotated( direction )
add_child( new_npc )
pass
通过按空格开始游戏⬇️
切换到gui场景
点击shortchut文件
完结⬇️
运行游戏后, 可以点击按钮开始,也可以用空格开始, 音乐播放没问题, 游戏可以玩了
可以继续打磨完善该游戏
祝大家游戏开发找到快乐!!!