Downloading a file from a server

It is a very common property of today's games—even those that are strictly single player—to connect to a server at some point in time to retrieve data such as the latest headlines from the game's official website, leaderboards, patches or the latest bonus content package. By the end of this recipe you will be able to do so as well.

Hosting files on a web server is very simple to set up and reasonably priced these days. Additionally, this makes it easy to use Panda3D's built in networking features. The engine comes with a class called HTTPClient that hides the complexities of communicating with a web server.

In this sample you will learn how to connect to a server, download some data and display it on the screen.

Getting ready

This recipe will use the framework presented in Setting up the game structure found in Chapter 1, Setting Up Panda3D and Configuring Development Tools. Please set up your project prior to going on with the following tasks.

How to do it...

Complete these tasks to make Panda3D download files from a server:

  1. Open Application.py and fill in the following code:
    from direct.showbase.ShowBase import ShowBase
    from panda3d.core import *
    from direct.gui.OnscreenImage import OnscreenImage
    class Application(ShowBase):
    def __init__(self):
    ShowBase.__init__(self)
    self.http = HTTPClient.getGlobalPtr()
    self.channel = self.http.makeChannel(False)
    self.channel.beginGetDocument(DocumentSpec("http://www.panda3d.org/images/panda-logo-2.png"))
    self.channel.downloadToFile(Filename("panda.png"))
    taskMgr.add(self.downloadData, "downloadData")
    def downloadData(self, task):
    if self.channel.run():
    return task.cont
    if not self.channel.isDownloadComplete():
    print "Unable to download file."
    return task.done
    else:
    OnscreenImage("panda.png", scale = Vec3(0.2, 0, 0.2))
    return task.done
    
  2. Press F6 to launch the program. After a short moment you should be able to see the following result:
How to do it...

How it works...

Now that our little program is able to download an image file to disk and display it on the screen, let's take a look at the steps that are necessary to achieve this goal.

First, we retrieve a reference to the global singleton instance of HTTPClient that Panda3D creates for us automatically. We could also create a new instance here, which wouldn't alter anything about this program's behavior apart from a minimally increased memory footprint.

We then go on to create a new HTTPChannel object by calling the makeChannel() method on our HTTPClient. This channel object represents the communication line to the server over which we will retrieve the image file. We also pass False as an argument, which makes the channel non-persistent. This means that immediately after the requested file has finished downloading, the connection will be closed. This fits our use case pretty well as we want to retrieve only one single file from the server. If we wanted to download a series of files, we would use a persistent connection. This is more efficient as the connection is kept open and reused instead of opening a new one for each request.

The next two calls, beginGetDocument() and downloadToFile(), are used to set which file to request from the server and where to store it. We try to retrieve a file hosted on the website of Panda3D, but we could easily replace it with a URL that points to a different resource, hosted on another server. Note, however, how we need to hand the URL to a new DocumentSpec object, which is responsible for handling whether the file can be retrieved from the local cache or needs to be downloaded.

By using downloadToFile(), we configure our HTTPChannel to download the requested data into a local file. Alternatively, we could also use downloadToRam() to store the data in a Ramfile object that represents a virtual file that uses the system's RAM for storage instead of the hard disk.

The call to beginGetDocument() is non-blocking. This means that instead of waiting for the complete download to finish within the execution of this method, it places a request for the desired file. Then the call returns and the program continues execution from that point onward. To actually download data after requesting it, we need to periodically update our channel using the run() method that is called periodically inside the downloadData task. This task will keep on updating the channel as long as there is data incoming before checking if the download has finished. As soon as the file is retrieved to the local hard drive, a new OnscreenImage is created to display the downloaded image.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset