Socketless n-player游戏

时间:2017-10-07 21:25:41

标签: python google-app-engine

我的2人游戏,纯文字游戏,基于浏览器的游戏运行正常,但是一个玩家无法知道其他玩家的回合何时完成除了试图转过身来。能否在标准的低成本GAE应用程序中完成所需的结果 - 推送(推送)信息?

我已经在纯Python中消化了Joran Beasley's fine answer example,但假设套接字会增加GAE应用的成本。如果我的成本前提不正确,请纠正我,然后你能告诉我如何在GAE中添加套接字吗?但我希望有一种经济的方法来增强我的应用程序没有套接字。

的Python:

class BaseHandler(webapp2.RequestHandler):

    @webapp2.cached_property
    def jinja2(self):
        return jinja2.get_jinja2(app=self.app)

    def render_template(
        self,
        filename,
        template_values,
        **template_args
        ):
    template = JINJA_ENVIRONMENT.get_template(filename)
        self.response.out.write(template.render(template_values))

class MainPage(BaseHandler):

    def get(self):

        global player
        global players 
        global scores 
        global target 
        global guesses 

        player = 0
        players = ['me','you']
        scores = [False , False]
        target = random.randrange(10)
        initguesses = ['','']
        guesses = initguesses

    template_values = {'scores':scores}
    return webapp2.redirect("/game/%s" % players[0])

class Game(BaseHandler):

    def get(self,who_id):
    who = players.index(who_id)
    template_values = {'scores':scores,'guesses':guesses[who],'players':players,'who_id':who_id}
        template = JINJA_ENVIRONMENT.get_template('game.html')
        self.response.out.write(template.render(template_values))

    def post(self,who_id):

    global player
    who = players.index(who_id)
    if who == player:
        guess = self.request.get('guess', None)
        guesses[player]=guess+guesses[player]
        scores[player]=int(guess)==target
        logging.info("target: %s" % target)
        next_player = player
        player = (1+player)%2
        template_values = {'scores':scores}
    return webapp2.redirect("/game/%s" % who_id)

game.html

{% extends "base.html" %}
{% block content %}
<h1>{{who_id}}</h1>
<br/>
<form action="" method="post">
Guess an integer here <br />
0 ... 9: <input type="textbox" name="guess" value=></input>
  <input type="submit" value="submit" />

</form>
<p> Your previous guess(es): {{ guesses }}</p>
<p> Got target right (yet)?: 
{% for score in scores %} 
<br />
{% if score %}
<h2>
    {% endif %}
{{players[loop.index0] }} {{ score }}
{% if score %}
</h2>
    {% endif %}
{% endfor %}
</p>

{% if who_id == players[0] %}
<p> You can start over at the beginning (<a href="/"> here.</a>) but everyone restarts. </p>
{% endif %}
<p>If you see no change above, it's not your turn.</p>

{% endblock content %}

2 个答案:

答案 0 :(得分:2)

菲利普回答了一个问题。

作为替代方案,您可以考虑使用推送通知服务,例如OneSignal

当玩家移动时,您向OneSingla发出http(s)请求,他们会处理websockets(或客户端可用的任何内容)以发送通知。

<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://ws.mkyong.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="ServerInfoService" targetNamespace="http://ws.mkyong.com/">
    <wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns0="http://ws.mkyong.com/" targetNamespace="http://ws.mkyong.com/">
  <xsd:complexType name="getIpAddressResponse">
    <xsd:sequence>
      <xsd:element minOccurs="0" name="return" type="xsd:string"/>
    </xsd:sequence>
  </xsd:complexType>
  <xsd:complexType name="getIpAddress"/>
  <xsd:element name="getIpAddressResponse" type="ns0:getIpAddressResponse"/>
  <xsd:element name="getIpAddress" type="ns0:getIpAddress"/>
</xsd:schema>
    </wsdl:types>
    <wsdl:message name="getIpAddress">
        <wsdl:part element="tns:getIpAddress" name="parameters"/>
    </wsdl:message>
    <wsdl:message name="getIpAddressResponse">
        <wsdl:part element="tns:getIpAddressResponse" name="parameters"/>
    </wsdl:message>
    <wsdl:portType name="ServerInfo">
        <wsdl:operation name="getIpAddress">
            <wsdl:input message="tns:getIpAddress" name="getIpAddress"/>
            <wsdl:output message="tns:getIpAddressResponse" name="getIpAddressResponse"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="ServerInfoServiceSoapBinding" type="tns:ServerInfo">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="getIpAddress">
            <soap:operation soapAction="" style="document"/>
            <wsdl:input name="getIpAddress">
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output name="getIpAddressResponse">
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="ServerInfoService">
        <wsdl:port binding="tns:ServerInfoServiceSoapBinding" name="ARMServicePortTypeImplPort">
            <soap:address location="http://10.19.9.92:7001/poc-war/ServerInfoService"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

可以自由使用OneSignal,但很少有类似的服务。

答案 1 :(得分:1)

您可以添加套接字,这样可以让用户知道对手何时播放(推送),或者您每隔几秒就询问一次服务器(轮询)。

每个websocket和每个服务器轮询都要花钱。轮询越频繁,用户体验越好,因为对手完成移动和用户发现之间的延迟较低。更频繁的民意调查当然也会花费更多的钱,因为你提出了更多的请求。

Web套接字在GAE上并不便宜,但它可能就是你想要的。