博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
vue使用python_如何使用Python和Vue创建两人游戏
阅读量:2520 次
发布时间:2019-05-11

本文共 16735 字,大约阅读时间需要 55 分钟。

vue使用python

by Neo Ighodaro

由新Ighodaro

如何使用Python和Vue创建两人游戏 (How to create a two-player game with Python and Vue)

In this tutorial, we will create a realtime tic-tac-toe game using Python and Pusher channels. Here’s a demo of how the game will look and behave upon creation:

在本教程中,我们将使用Python和Pusher通道创建一个实时井字游戏。 以下是游戏制作后的外观和行为演示:

You will need Python 3+, virtualenv, and Flask installed on your machine.The advent of the PC and the internet has redefined the term “entertainment” and the means by which it can be obtained. While a console or some special hardware would have been required to play games in the past, games are only a click away in today’s world of technology.

您将需要在计算机上安装Python 3 +,virtualenv和Flask。PC和Internet的出现重新定义了“娱乐”一词及其获取方式。 尽管过去需要使用控制台或某些特殊的硬件才能玩游戏,但在当今的技术世界中,只需单击一下鼠标即可。

This multiplayer game will allow a player to connect using their preferred username (or generate a random username where a player doesn’t connect with a username) and choose to play with another player from a list of other online players.

这款多人游戏将允许玩家使用其首选用户名进行连接(或在不与用户名建立联系的情况下生成随机用户名),并从其他在线玩家列表中选择与另一位玩家一起玩。

The game itself follows the conventional principles of the popular game. The “online player(s)” feature is powered by and the realtime updates of a player’s move across multiple windows is powered by The source code for this tutorial is available here .

游戏本身遵循流行的游戏的传统原理。 “在线播放器”功能由 ,而播放器跨多个窗口的移动的实时更新由 该教程的源代码可在 。

Let’s get started.

让我们开始吧。

先决条件 (Prerequisites)

To follow along, a basic knowledge of Python, Flask, JavaScript (ES6 syntax) and Vue is required. You will also need the following installed on your machine:

接下来,需要具备Python,Flask,JavaScript(ES6语法)和Vue的基础知识。 您还将需要在计算机上安装以下软件:

Virtualenv is great for creating isolated Python environments, so we can install dependencies in an isolated environment without polluting our global packages directory.

Virtualenv非常适合创建隔离的Python环境,因此我们可以在隔离的环境中安装依赖项而不会污染我们的全局包目录。

搭建环境 (Setting up the environment)

We will create the project folder and activate a virtual environment within it:

我们将创建项目文件夹并在其中激活虚拟环境:

$ mkdir python-pusher-mutiplayer-game    $ cd python-pusher-mutiplayer-game    $ virtualenv .venv    $ source .venv/bin/activate # Linux based systems    $ \path\to\env\Scripts\activate # Windows users

We will install using this command:

我们将使用以下命令安装 :

$ pip install flask

设置推送器 (Setting up Pusher)

To integrate Pusher into the multiplayer game, we need to create a Pusher channels application from the Pusher dashboard. If you don’t already have a Pusher account, head over to the and create one.

要将Pusher集成到多人游戏中,我们需要从Pu​​sher仪表板创建Pusher频道应用程序。 如果您还没有Pusher帐户,请转到并创建一个。

After creating an account, create a new channels application and enable client events from the application dashboard. To enable client events, click on App settings and scroll to the bottom of the page then select the option that says Enable client events, and update the App settings.

创建帐户后,创建一个新的渠道应用程序并从应用程序仪表板启用客户端事件。 要启用客户端事件,请单击“ 应用程序设置”并滚动到页面底部,然后选择“ 启用客户端事件 ”选项然后更新应用程序设置。

构建后端服务器 (Building the backend server)

Back in the project directory, let’s install the with this command:

回到项目目录,让我们使用以下命令安装 :

$ pip install pusher

We will create a new file and call it app.py, this is where we will write all the code for the Flask backend server. We will also create a folder and call it templates, this folder will hold the markup files for this application.

我们将创建一个新文件并将其app.py ,这是我们将编写Flask后端服务器的所有代码的地方。 我们还将创建一个文件夹并将其称为templates ,该文件夹将保存此应用程序的标记文件。

Let’s write some code to register the endpoints for the game and serve the view, open the app.py file and paste the following code:

让我们编写一些代码来注册游戏的端点并提供视图,打开app.py文件并粘贴以下代码:

// File: ./app.py    from flask import Flask, render_template, request, jsonify, make_response, json    from pusher import pusher    app = Flask(__name__)    pusher = pusher_client = pusher.Pusher(      app_id='PUSHER_APP_ID',      key='PUSHER_APP_KEY',      secret='PUSHER_APP_SECRET',      cluster='PUSHER_APP_CLUSTER',      ssl=True    )    name = ''    @app.route('/')    def index():      return render_template('index.html')    @app.route('/play')    def play():      global name      name = request.args.get('username')      return render_template('play.html')    @app.route("/pusher/auth", methods=['POST'])    def pusher_authentication():      auth = pusher.authenticate(        channel=request.form['channel_name'],        socket_id=request.form['socket_id'],        custom_data={          u'user_id': name,          u'user_info': {            u'role': u'player'          }        }      )      return json.dumps(auth)    if __name__ == '__main__':        app.run(host='0.0.0.0', port=5000, debug=True)    name = ''

Replace the PUSHER_APP_* keys with the values on your Pusher dashboard.

PUSHER_APP_*键替换为Pusher仪表板上的值。

In the code above, we defined three endpoints, here’s what they do:

在上面的代码中,我们定义了三个端点,这是它们的作用:

  • / - renders the front page that asks a player to connect with a username.

    / -呈现要求玩家使用用户名进行连接的首页。

  • /play - renders the game view.

    /play play-渲染游戏视图。

  • /pusher/auth - authenticates Pusher’s presence and private channels for connected players.

    /pusher/auth为连接的播放/pusher/auth验证Pusher的状态和专用通道。

建立前端 (Building the frontend)

In the templates folder, we will create two files:

templates文件夹中,我们将创建两个文件:

  1. index.html

    index.html

  2. play.html

    play.html

The index.html file will render the connection page, so open the templates/index.html file and paste the following code:

index.html文件将呈现连接页面,因此请打开templates/index.html文件并粘贴以下代码:

TIC-TAC-TOE

When a player visits the connection page and puts in a username and email, the browser window will be redirected to the game view.

当玩家访问连接页面并输入用户名和电子邮件时,浏览器窗口将被重定向到游戏视图。

Let’s write the markup for the game view. Open the play.html file and paste the following code:

让我们为游戏视图编写标记。 打开play.html文件并粘贴以下代码:

TIC-TAC-TOE

{% raw %} {

{ username }} {% endraw %}

{% raw %} { { players }} {% endraw %} online player(s)


  • {% raw %} { { member }} {% endraw %}
  • {% raw %} {
    { status }} {% endraw %}

    The code above defines the layout of the game view but does not contain any interactivity or realtime features. In the scripts section, before the closing body tag, we included the Vue and Pusher libraries because they are required for the game to work.

    上面的代码定义了游戏视图的布局,但不包含任何交互性或实时功能。 在脚本部分的结束body标签之前,我们包含了Vue和Pusher库,因为它们是游戏正常运行所必需的。

    Let’s include the JavaScript code that will drive the entire game process and define its logic.

    让我们包括将驱动整个游戏过程并定义其逻辑JavaScript代码。

    In the same file, add the code below in between the script tag that is just before the closing body tag:

    在同一文件中,将以下代码添加在script标签之间,即结束body标签之前:

    var app = new Vue({      el: '#app',      data: {        username: '',        players: 0,        connectedPlayers: [],        status: '',        pusher: new Pusher('PUSHER_APP_KEY', {          authEndpoint: '/pusher/auth',          cluster: 'PUSHER_APP_CLUSTER',          encrypted: true        }),        otherPlayerName: '',        mychannel: {},        otherPlayerChannel: {},        firstPlayer: 0,        turn: 0,        boxes: [0, 0, 0, 0, 0, 0, 0, 0, 0]      },      created () {        let url = new URL(window.location.href);        let name = url.searchParams.get("username");        if (name) {          this.username = name          this.subscribe();          this.listeners();        } else {          this.username = this.generateRandomName();          location.assign("/play?username=" + this.username);        }      },      methods: {        // We will add methods here      }    });

    Replace the PUSHER_APP_* keys with the keys on your Pusher dashboard.

    PUSHER_APP_*键替换为Pusher仪表板上的键。

    Above, we create a new instance of Vue and we target the #app selector. We define all the defaults in the dataobject and then in the create() function which is called automatically when the Vue component is created, we check for a user and assign the user to the username if one was supplied.

    上面,我们创建了Vue的新实例,并以#app选择器为目标。 我们在data对象中定义所有默认值,然后在create() Vue组件时自动调用的create()函数中,检查用户并将用户分配给用户名(如果提供了用户名)。

    We also make calls to the subscribe and listeners methods. Let’s define those inside the methods object. Inside the methods object, paste the following functions:

    我们还调用subscribelisteners方法。 让我们在methods对象中定义它们。 在methods对象内,粘贴以下函数:

    // [...]    subscribe: function () {      let channel = this.pusher.subscribe('presence-channel');      this.myChannel = this.pusher.subscribe('private-' + this.username)      channel.bind('pusher:subscription_succeeded', (player) => {        this.players = player.count - 1        player.each((player) => {          if (player.id != this.username)            this.connectedPlayers.push(player.id)        });      });      channel.bind('pusher:member_added', (player) => {        this.players++;        this.connectedPlayers.push(player.id)      });      channel.bind('pusher:member_removed', (player) => {        this.players--;        var index = this.connectedPlayers.indexOf(player.id);        if (index > -1) {          this.connectedPlayers.splice(index, 1)        }      });    },    listeners: function () {      this.pusher.bind('client-' + this.username, (message) => {        if (confirm('Do you want to start a game of Tic Tac Toe with ' + message)) {          this.otherPlayerName = message          this.otherPlayerChannel = this.pusher.subscribe('private-' + this.otherPlayerName)          this.otherPlayerChannel.bind('pusher:subscription_succeeded', () => {            this.otherPlayerChannel.trigger('client-game-started', this.username)          })          this.startGame(message)        } else {          this.otherPlayerChannel = this.pusher.subscribe('private-' + message)          this.otherPlayerChannel.bind('pusher:subscription_succeeded', () => {            this.otherPlayerChannel.trigger('client-game-declined', "")          })          this.gameDeclined()        }      }),      this.myChannel.bind('client-game-started', (message) => {        this.status = "Game started with " + message        this.$refs.gameboard.classList.remove('invisible');        this.firstPlayer = 1;        this.turn = 1;      })      this.myChannel.bind('client-game-declined', () => {        this.status = "Game declined"      })      this.myChannel.bind('client-new-move', (position) => {        this.$refs[position].innerText = this.firstPlayer ? 'O' : 'X'      })      this.myChannel.bind('client-your-turn', () => {        this.turn = 1;      })      this.myChannel.bind('client-box-update', (update) => {        this.boxes = update;      })      this.myChannel.bind('client-you-lost', () => {        this.gameLost();      })    },    // [...]

    In the subscribe method, we subscribe to our Pusher presence channel, and then subscribe to the private channel for the current user. In the listeners method we register the listeners for all the events we are expecting to be triggered on the private channel we subscribed to.

    subscribe方法中,我们订阅Pusher在线状态频道,然后订阅当前用户的专用频道。 在listeners方法中,我们为希望在订阅的私有频道上触发的所有事件注册侦听器。

    Next, we will add other helper methods to our methods class. Inside the methods class, add the following functions to the bottom after the listeners method:

    接下来,我们将其他辅助方法添加到我们的方法类中。 在方法类内部,将以下函数添加到listeners方法的底部:

    // Generates a random string we use as a name for a guest user    generateRandomName: function () {      let text = '';      let possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';      for (var i = 0; i < 6; i++) {        text += possible.charAt(Math.floor(Math.random() * possible.length));      }      return text;    },    // Lets you choose a player to play as.    choosePlayer: function (e) {      this.otherPlayerName = e.target.innerText      this.otherPlayerChannel = this.pusher.subscribe('private-' + this.otherPlayerName)      this.otherPlayerChannel.bind('pusher:subscription_succeeded', () => {        this.otherPlayerChannel.trigger('client-' + this.otherPlayerName, this.username)      });    },    // Begins the game    startGame: function (name) {      this.status = "Game started with " + name      this.$refs.gameboard.classList.remove('invisible');    },    // User declined to play    gameDeclined: function () {      this.status = "Game declined"    },    // Game has ended with current user winning    gameWon: function () {      this.status = "You WON!"      this.$refs.gameboard.classList.add('invisible');      this.restartGame()    },    // Game has ended with current user losing    gameLost: function () {      this.turn = 1;      this.boxes = [0, 0, 0, 0, 0, 0, 0, 0, 0]      this.status = "You LOST!"      this.$refs.gameboard.classList.add('invisible');      this.restartGame()    },    // Restarts a game    restartGame: function () {      for (i = 1; i < 10; i++) {        this.$refs[i].innerText = ""      }      this.$refs.gameboard.classList.remove('invisible');    },    // Checks tiles to see if the tiles passed are a match    compare: function () {      for (var i = 1; i < arguments.length; i++) {        if (arguments[i] === 0 || arguments[i] !== arguments[i - 1]) {          return false        }      }      return true;    },    // Checks the tiles and returns true if theres a winning play    theresAMatch: function () {      return this.compare(this.boxes[0], this.boxes[1], this.boxes[2]) ||        this.compare(this.boxes[3], this.boxes[4], this.boxes[5]) ||        this.compare(this.boxes[6], this.boxes[7], this.boxes[8]) ||        this.compare(this.boxes[0], this.boxes[3], this.boxes[6]) ||        this.compare(this.boxes[1], this.boxes[4], this.boxes[7]) ||        this.compare(this.boxes[2], this.boxes[5], this.boxes[8]) ||        this.compare(this.boxes[2], this.boxes[4], this.boxes[6]) ||        this.compare(this.boxes[0], this.boxes[4], this.boxes[8])    },    // Checks to see if the play was a winning play    playerAction: function (e) {      let index = e.target.dataset.id - 1      let tile = this.firstPlayer ? 'X' : 'O'      if (this.turn && this.boxes[index] == 0) {        this.turn = 0        this.boxes[index] = tile        e.target.innerText = tile        this.otherPlayerChannel.trigger('client-your-turn', "")        this.otherPlayerChannel.trigger('client-box-update', this.boxes)        this.otherPlayerChannel.trigger('client-new-move', e.target.dataset.id)        if (this.theresAMatch()) {          this.gameWon()          this.boxes = [0, 0, 0, 0, 0, 0, 0, 0, 0]          this.otherPlayerChannel.trigger('client-you-lost', '')        }      }    },

    Above, we have added several helper methods that the game needs to function properly and before each method, we have added a comment to show what the method does.

    上面,我们添加了游戏需要正常运行的几种辅助方法,在每种方法之前,我们添加了注释以显示该方法的功能。

    Let’s test the game now.

    让我们现在测试游戏。

    测试游戏 (Testing the game)

    We can test the game by running this command:

    我们可以通过运行以下命令来测试游戏:

    $ flask run

    Now if we visit , we should see the connection page and test the game:

    现在,如果我们访问 ,我们应该看到连接页面并测试游戏:

    结论 (Conclusion)

    In this tutorial, we have learned how to leverage the Pusher SDK in creating an online multiplayer game powered by a Python backend server.

    在本教程中,我们学习了如何利用Pusher SDK创建由Python后端服务器提供支持的在线多人游戏。

    The source code for this tutorial is available on

    本教程的源代码可在上

    This post first appeared on the

    这篇文章首先出现在

    翻译自:

    vue使用python

    转载地址:http://augwd.baihongyu.com/

    你可能感兴趣的文章
    Vue基础安装(精华)
    查看>>
    Git 提交修改内容和查看被修改的内容
    查看>>
    PAT - 1008. 数组元素循环右移问题 (20)
    查看>>
    请求出现 Nginx 413 Request Entity Too Large错误的解决方法
    查看>>
    配置php_memcache访问网站的步骤
    查看>>
    hibernate的id生成策略
    查看>>
    树莓派3B+学习笔记:5、安装vim
    查看>>
    [Spfa][bfs] Jzoj P5781 秘密通道
    查看>>
    企业帐号进行IPA的打包、分发、下载安装的详细流程(转载)
    查看>>
    《项目架构那点儿事》——快速构建Junit用例
    查看>>
    {"errmsg":"invalid weapp pagepath hint: [IunP8a07243949]","errcode":40165}微信的坑
    查看>>
    DB2V9.5数据库使用pdf
    查看>>
    Java Bigdecimal使用
    查看>>
    SQL注入之绕过WAF和Filter
    查看>>
    jquery validate使用方法
    查看>>
    DataNode 工作机制
    查看>>
    windows系统下安装MySQL
    查看>>
    错误提示总结
    查看>>
    实验二+070+胡阳洋
    查看>>
    Linux IPC实践(3) --具名FIFO
    查看>>