对pong这个游戏我们不必要真的接入一个ai,我们只需要对手球拍能追踪球y轴方位移动就行了
1. 创建 AI 球拍
复制player,并改名为ai_player
ai_player脚本(一定要先分离原来player脚本在创建一个新脚本):
python
extends CharacterBody2D
@export var ai_paddle_speed:float=280
var ball:CharacterBody2D = null
func _physics_process(delta:float):
if ball == null:
return
var dif_y=ball.position.y - position.y
if abs(dif_y)>10 :
velocity.y = sign(dif_y) * ai_paddle_speed
else:
velocity.y = 0
velocity.x = 0
move_and_slide()
position.y=clamp(position.y,40,440)
将ai_player添加到game场景里,调整位置 x : 560 y : 240

2.让ai看见球
给game场景添加脚本
python
extends Node2D
func _ready() -> void:
# $节点名
var ai = $ai_player
var ball = $Ball
#让ai这个节点识别到球
ai.ball = ball
3.创建得分检测区域
创建area2D和collisionshape2d,一个不可视的区域,当有物体进入该区域就会发出信号

更名为LeftScoreZone

将碰撞层尺寸和位置修改一下

重复上面步骤把右边的得分区也做了

4.创建 UI 显示分数
在game节点下创建canvaslayer

改名叫UI(不论背景怎么动,这个canvaslayer上的节点都不会动,很适合用于做UI)

再在UI节点下创建label用来做比分

改名score

设置水平居中,垂直居中

将字的大小调整到 48
size x : 200 y : 67
position x : 220 y : 30

再创建一个label,改名为message

和上面的操作差不多,就参数上再微调一下(这里是未来的我,size.x调成500,position.x调成70会更好,其他不变)

visible关掉,默认隐藏

5.给 Game 脚本添加计分逻辑
python
extends Node2D
# 分数变量
var player_score : int = 0
var ai_score : int= 0
var win_score : int= 11
# 这的enum和c语言中一样
# 游戏状态
enum GameState {PLAYING,PLAYER_WIN,AI_WIN}
var game_state : GameState = GameState.PLAYING
# @onready可以理解成我们ready执行前才执行
# 如果不加上的话,ai_player等节点还没有被创建
# 最后会被赋值null
@onready var ai : CharacterBody2D = $ai_player
@onready var ball : CharacterBody2D = $Ball
@onready var score_label : Label = $UI/score
@onready var message_label : Label = $UI/message
func _ready() -> void:
ai.ball = ball
# body_entered :检测是否有东西进入
# 若有则触发_on_left_score函数
$leftscorezone.body_entered.connect(_on_left_score)
$rightscorezone.body_entered.connect(_on_right_score)
update_score_display()
func _on_left_score(body):
# ai进球得分
if game_state != GameState.PLAYING :
return
if body == ball :
ai_score += 1
check_winner()
func _on_right_score(body):
# 玩家进球得分
if game_state != GameState.PLAYING :
return
if body == ball :
player_score += 1
check_winner()
func check_winner():
if player_score >= win_score:
game_state = GameState.PLAYER_WIN
message_label.text = "You win!\n press space to restart"
message_label.visible = true
elif ai_score >= win_score:
game_state = GameState.AI_WIN
message_label.text = "AI win!\n press space to restart"
message_label.visible = true
else :
ball.reset_ball()
update_score_display()
# 更新比分
func update_score_display():
score_label.text = str(player_score) + " - " + str(ai_score)
# _input(event)特殊函数,当有输入的时候自动调用
func _input(event: InputEvent) -> void:
if event.is_action_pressed("ui_accept"):
if game_state == GameState.PLAYER_WIN or game_state == GameState.AI_WIN :
restart_game()
# 重开游戏
func restart_game():
player_score = 0
ai_score = 0
message_label.visible = false
game_state = GameState.PLAYING
update_score_display()
ball.reset_ball()
这是程序流程图可以和代码配合来看
6.结果展示

7.个人错误改证
ball要改一下初始位置,因为我们原来的初始位置就在leftscorezone上,ai会在游戏刚开始时多得一分

