(原) Godot下载数据

原创文章,请后转载,并注明出处。

在Godot中实现下载更建议使用HttpClient,它不是控件。主要是在其它线程中进行下载,在_process()中显示进度。保存时使用 file.store_buffer。

原始代码如下,可以进一步优化或变为公共功能调用。这样就实现了通过Web下载游戏包(进行升级)

UI很简单,一个控件显示文字,一个控件显示进度。

下载主体部份在官方有示例

extends Node2D

var thread: Thread
var currentSize :int
var totalSize :int
var updateInfo :String

func _process(_delta):
	$ProgressBar.value = currentSize
	$ProgressBar.max_value = totalSize
	$Text.text = updateInfo
	if currentSize == totalSize and totalSize!=0:
		OS.delay_msec(500)
		LoadPCK()

# 保存文件
func save(filename,content):
	var file = FileAccess.open(filename, FileAccess.WRITE)
	file.store_buffer(content)

# 下载pck
func downPCK():	
	print("下载Pck文件")
	var http = HTTPClient.new()
	var err = http.connect_to_host("127.0.0.1",7000)
	assert(err==OK)
	# 等待,直到解决并连接为止
	while http.get_status() == HTTPClient.STATUS_CONNECTING or http.get_status() == HTTPClient.STATUS_RESOLVING:
		http.poll()
		updateInfo = "连接服务器..."
		OS.delay_msec(100)
	assert(http.get_status() == HTTPClient.STATUS_CONNECTED) 					# 检查该连接是否已成功完成。

	var headers = [
		"User-Agent: Ease/1.0 (Godot)",
		"Accept: */*"
	]

	err = http.request(HTTPClient.METHOD_GET, "/down/first.pck", headers)
	assert(err == OK) 

	while http.get_status() == HTTPClient.STATUS_REQUESTING:
		# 只要正在处理请求,请一直保持轮询。
		http.poll()
		updateInfo = "请求数据包..."
		
	assert(http.get_status() == HTTPClient.STATUS_BODY or http.get_status() == HTTPClient.STATUS_CONNECTED) 

	#print("response? ", http.has_response()) # 网址是否有返回

	#if http.has_response():
		#headers = http.get_response_headers_as_dictionary() # 获取头信息
		#print("code: ", http.get_response_code()) # 显示响应代码
		#print("headers: ", headers) # 显示头信息
		
	# 获取HTTP内容	
	if http.is_response_chunked():
		print("响应被分块")
	else:
		# 或者只是简单的内容长度
		totalSize = http.get_response_body_length()
		print("返回长度: ", totalSize)
		
	# 这个方法对两者都适用
	var rb = PackedByteArray() # 将保存数据的数组

	while http.get_status() == HTTPClient.STATUS_BODY:
		http.poll()
		# 获取块
		var chunk = http.read_response_body_chunk()
		if chunk.size() == 0:
			pass
		else:
			rb = rb + chunk # 附加到读取缓冲区
		updateInfo = "下载中... %d / %d KB" % [currentSize/1024, totalSize/1024]
		printt(currentSize,totalSize)
		currentSize = rb.size()

	if currentSize == totalSize:
		save("./first.pck",rb)

# 载入pck资源文件
func LoadPCK():
	var HavePCK = false 
	var dir = DirAccess.open(".")
	
	if dir:
		var files = dir.get_files()
		for file in files:
			if file.get_extension() == "pck":
				HavePCK = true
				ProjectSettings.load_resource_pack(file)
		
		if HavePCK:
			if ResourceLoader.exists("res://framework/scenes/launch/launch.tscn"):
				get_tree().change_scene_to_file("res://framework/scenes/launch/launch.tscn")
	
	return HavePCK

func _ready():
	thread = Thread.new()
	if !LoadPCK():
		thread.start(CheckPCK)

func CheckPCK():
	downPCK()

func _exit_tree():
	thread.wait_to_finish()

要注意的是:因为下载时间可能比较久,服务端需要设置好超时时间。否则将导致不能完全下载就断开的情况。

相关文章