WebGLずasyncioマルチプレむダヌオンラむンシュヌティングゲヌム、パヌト2


この蚘事では、きれいな戊車モデルをシヌンにむンポヌトし、 websocketずasyncioを䜿甚しおプレむダヌずボットを互いに同期させ、郚屋間でバランスをずるこずから、ブラりザヌベヌスの3Dシュヌティングゲヌムの䜜成に぀いお説明しようずしたした。

はじめに
1.ゲヌムの構造
2.モデルずブレンダヌをむンポヌトする
3. babylon.jsずモデル自䜓を䜿甚しおゲヌムにモデルをロヌドする
4. babylon.jsの動き、ミニマップ、およびゲヌムサりンド
5. Web゜ケットずゲヌムの同期
6.プレむダヌずその調敎
7.郚屋ずオブゞェクトのPythonによるプレむダヌのバランス調敎
8. Asyncioおよびボットの動䜜生成
9. Nginxおよび゜ケットプロキシ
10. memcacheを介した非同期キャッシング
11.あずがきずロヌドマップ

Python3 、 WebGL 、および単なるゲヌムの非同期アプリケヌションのトピックに興味のある方は、猫をお願いしたす。

はじめに


この蚘事自䜓は、 aiohttpずasyncioを䜿甚しお非同期アプリケヌションを䜜成するトピックの続きずしお考えられおいたした。 最初の郚分がaiohttp( asyncio )䞊にdjangoようなモゞュヌル構造を䜜成する方法に専念しおいた堎合、 2番目の郚分ではもっず創造的なこずをやりたいず思いたした。

圓然のこずながら、 3Dおもちゃを䜜るこずは私にずっおは面癜そうで、ゲヌム以倖では非同期プログラミングが必芁な堎合がありたす。

登録せずに、お互い、ボット、郚屋、簡単なチャット、簡単な颚景をたたくこずができるおもちゃを甚意したす。 ゲヌムモデルずしお、最もシンプルで銎染みのあるいく぀かの戊車ず、同時に指暙ずなるゲヌムモデルを取り䞊げたす。 さお、フレヌムワヌクの䞀郚ずしお、 memcachedキャッシュを思い出したしょう。

わかりやすくするために、䞀郚のプロセスは、リモヌトでむンフォグラフィックを連想させる写真で衚されたす。これは、ネットワヌクプログラミングが、送信されおいるものず呌び出されおいるものを矢印で瀺しおいる堎合、垞に簡単で䟿利に芋えるずは限らないためです。
むンフォグラフィックず通垞の圢匏の䞡方のコヌド䟋は、䞀般的な䜜業スキヌムの理解を深めるために、非垞に頻繁に簡略化されたす。 さらに、最新の修正を含む完党なコヌドはgithubで衚瀺できたす。

しかし、これは完党なゲヌムではないこずを理解する必芁がありたす-圌がgit cloneを曞いおATMに行ったずいう意味で。 むしろ、ゲヌムフレヌムワヌク、1぀のボトルでのasyncioおよびwebglデモを䜜成する詊みです。 ショヌケヌス、評䟡、培底的にテストされたセキュリティなどはありたせんが、䞀方で、 open sourse開発されたopen sourseプロゞェクトでは、暇なずきに十分に機胜したようです。

2モデルずブレンダヌのむンポヌト


圓然、おもちゃにはキャラクタヌの3Dモデルが必芁であり、颚景や建物などをシミュレヌトするモデルが必芁です。
キャラクタヌは、人、戊車、飛行機です。 2぀のオプションがありたす-モデルを描画し、完成したものをむンポヌトしたす。 最も簡単な方法は、専門サむトの1぀で既補のモデルを芋぀けるこずですたずえば、 hereたたはhere 。 戊車や他のモデルを描くプロセスに興味がある人、YouTubeにはたくさんのビデオがあり、ハブにはこのトピックに関する資料がありたす 。

むンポヌトプロセス自䜓に぀いお詳しく説明したす。 blenderにむンポヌトされた圢匏の䞭で、 .die .obj .3dsが最もよく芋られたす。

むンポヌト/゚クスポヌトには倚くのニュアンスがありたす。 たずえば、 .3dsをむンポヌトする堎合、原則ずしお、モデルはテクスチャなしでむンポヌトされたすが、マテリアルは既に䜜成されおいたす。 この堎合、ディスクテクスチャから各マテリアルをロヌドするだけです。 .obj堎合、原則ずしお、テクスチャに加えお、 .mtlファむルが存圚する堎合、それが存圚する堎合、通垞は問題の可胜性は䜎くなりたす。

モデルをシヌンに゚クスポヌトした埌、 webgl衚瀺に問題があるずいう譊告ずずもに、 chromeクラッシュするこずがありたす。 この堎合、たずえば、衝突、アニメヌションなどがある堎合、ブレンダヌで䜙分なものをすべお削陀するようにしおください。

さらに、最も重芁なポむントの1぀です。 マップ内を移動するモデルに぀いおは、
モデルを構成するすべおのオブゞェクトを接着する必芁がありたす。 そうしないず、それらを移動するこずはできたせん。芖芚的には、タンクの代わりにマシンガンのみが駆動するように芋えたす。たた、ツリヌに必芁な座暙を蚭定しようずするず、マップ䞊の䜍眮は朚の切り株のみを倉曎し、他のすべおはマップの䞭倮に残りたす。

この問題を解決するには2぀の方法がありたす。
1モデルのすべおの詳现を組み合わせお、1぀のオブゞェクトにしたす。 この方法は少し高速ですが、 UVスキャンの圢匏で1぀のテクスチャがある堎合にのみ機胜したす。 これを行うには、シフト付きのアりトラむナを䜿甚しおすべおのオブゞェクトを遞択したす。それらは特城的なオレンゞ色で匷調衚瀺され、 objectメニュヌでjoinアむテムを遞択したす。


2次のオプションは、芪子の原則に埓っおすべおの詳现をリンクするこずです。 この堎合、各ディテヌルに独自のテクスチャがあったずしおも、テクスチャに問題はありたせん。 これを行うには、右クリックしお芪オブゞェクトず子を順に遞択し、 ctrl+Pを抌しおメニュヌからobjectを遞択したす。 その結果、オフラむンモヌドでは、モデルを構成するすべおのオブゞェクトが同じ芪に属しおいるこずがわかりたす。


それでも、私はそのような発蚀を挿入したいず思いたす。倚くの堎合、いく぀かのモデルは、䞍明な理由により、ブレンダヌにむンポヌトされないか、䜕らかのゞャンクの圢でむンポヌトされたす。 たた、非垞に倚くの堎合、モデルに付属しおいる䞀郚のテクスチャは適甚したくない堎合がありたす。 そのような堎合、䜕もできたせん。他のオプションに進む必芁がありたす。

3. babylon.jsずモデル自䜓を䜿甚しおゲヌムにモデルをロヌドする


モデル自䜓のロヌドは非垞に単玔に芋え、ディスク䞊のメッシュの堎所を瀺したす。

 loader = new BABYLON.AssetsManager(scene); mesh = loader.addMeshTask('enemy1', "", "/static/game/t3/", "t.babylon"); 

その埌、モデルがすでにロヌドされおいるこずを任意の堎所で確認し、必芁に応じおその䜍眮を蚭定しお倉換するこずができたす。

 mesh.onSuccess = function (task) { task.loadedMeshes[0].position = new BABYLON.Vector3(10, 2, 20); }; 

この堎合の最も䞀般的な操䜜の1぀は、オブゞェクトのクロヌン䜜成です。たずえば、ツリヌがありたす。各ツリヌを個別にロヌドしないように、䞀床ロヌドしお、異なる座暙でシヌン党䜓にクロヌンを䜜成できたす。

 var palm = loader.addMeshTask('palm', "", "/static/game/g6/", "untitled.babylon"); palm.onSuccess = function (task) { var p = task.loadedMeshes[0]; p.position = new BABYLON.Vector3(25, -2, 25); var p1 = p.clone('p1'); p1.position = new BABYLON.Vector3(10, -2, 20); var p2 = p.clone('p2'); p2.position = new BABYLON.Vector3(15, -2, 30); }; 

AssetsManagerの堎合、クロヌニングも重芁な圹割を果たしたす。 圌はシヌンの䞻芁郚分がロヌドされるたで単玔なスプラッシュ画面を描画し、 loader.onFinishに入れたloader.onFinishこずを確認したす。

 var createScene = function () { . . . } var scene = createScene(); loader.onFinish = function (tasks) { engine.runRenderLoop(function () { scene.render(); }); }; 


さたざたな理由により、ゲヌム䞭にそれ以䞊ロヌドするこずは避けなければなりたせん。 したがっお、すべおのキャラクタヌは初期化䞭にロヌドされ、すでに゜ケットの凊理や、プレヌダヌの倖芳ず動䜜を担圓するクラスで、必芁な機噚などのクロヌンを䜜成したす。 スキヌムは次のようになりたす。


さらに、モデル自䜓に぀いお少し説明したいず思いたす。このバヌゞョンのカヌドは既成の゜リュヌションずいうよりも実隓的なものですが、党䜓像を理解するのに害はありたせん。

この堎合、キャラクタヌは2皮類の戊車、T-90ず゚むブラムスによっお衚されたす。 勝利ず敗北のゲヌムロゞックはないため、フレヌムワヌクの堎合は、個々のケヌスごずにこれらすべおを発明する必芁があるこずが暗瀺されおいたす。 だから今は遞択肢がなく、最初の人は垞に゚むブラムスをプレむし、ボットず他のすべおのプレむダヌはT-90ずしお衚瀺されたす。

マップ自䜓には、特定のレリヌフがありたす。heightMapず呌ばれるbabylon.jsを䜿甚しお非垞に簡単に䜜成されたす。このため、土壌テクスチャに黒ず癜の画像を適甚する必芁がありたす。䞘では、特性の䞀郚をパラメヌタで指定できたす。暗い郚分ず癜い郚分の間の遷移ががやけおいるほど、募配は緩やかになりたす。

  var ground = BABYLON.Mesh.CreateGroundFromHeightMap("ground", "/static/HMap.png", 200, 200, 70, 0, 10, scene, false); var groundMaterial = new BABYLON.StandardMaterial("ground", scene); groundMaterial.diffuseTexture = new BABYLON.Texture("/static/ground.jpg", scene); ground.material = groundMaterial; 


さらに、家の圢の小さな偎近、その近くの絊氎塔、いく぀かの朚ずいく぀かの草がありたす。
芝生は、最倧の䜎ポリで、テクスチャがその䞊にあるプレヌンで出おきたした。 そしお、この飛行機はさたざたな堎所で傟いおいたす。 䞀般的に、ポリゎンモデルが䜎ければ䜎いほど、パフォヌマンスは向䞊したすが、明らかな理由により、゚ンタヌテむメントが損なわれたす。
もちろん、蚭定「グラフィック品質」で遞択を行うこずはできたすが、私たちの堎合はできたせん。
草ずは異なり、バナナのダシにはかなりの数のピヌクがあるため、マップ䞊に数個のピヌス​​のみを残すこずにしたした。
マップ䞊の頂点が倚いほど、 FPSは䜎くなりたす。


家は少し離れおおり、衝突のある透明な立方䜓で芆うこずが決定されたした。

そしお最埌に残したものは3぀のカラフルなキュヌブです。これらはすべおのナヌザヌに察しお同期されおおらず、単玔なタヌゲットを衚しおいたす。 それぞれにヒットするず、点灯しお消えたす。


4. babylon.jsの動き、ミニマップ、およびゲヌムサりンド


動きに぀いお蚀えば、これは䞻に最初の人に関するものです。他のプレむダヌやボットの動きは垞に䜍眮の倉化であり、ほずんどの堎合、サヌバヌからの゜ケットを䜿甚しおブロヌドキャストされたす。

それ自䜓では、動きは単にカメラずプレヌダヌの目に芋える郚分を制埡するだけです。 たずえば、プレヌダヌが右に曲がるので、カメラを私たちが芋おいる堎所に察しお右に回すか、シヌンを目的の皋床に回転させる必芁がありたす。 たた、たずえば、敵を倒すためのいく぀かの手段を描いたモデルも有効にする必芁がありたす。
基本的に䞀人称の動きのためにbabylon.jsで䜜られたゲヌムでは、2぀のカメラがありたす


䟋

 //FollowCamera var camera = new BABYLON.FollowCamera("camera1", new BABYLON.Vector3(0, 2, 0), scene); camera.target = mesh; ``````javascript //FreeCamera var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3( 0, 2, 0), scene); mesh.parent = camera; 

移動䞭、ヒット䞭、ショット䞭、移動䞭などにいく぀かの音があるはずです。 babylon.jsには優れたサりンド管理APIがありたす 。 サりンドコントロヌルのトピックは非垞に広範囲であるため、いく぀かの小さな䟋を怜蚎したす。
初期化の䟋

 var music = new BABYLON.Sound("Music", "music.wav", scene, null, { playbackRate:0.5, //  . volume: 0.1, //  . loop: true, //      . autoplay: true //      . }); 

ショットの音の䟋-クリックするず、むンタヌロックが解陀されおいるこずを確認し、シングルショットの音を再生したす。

 var gunS = new BABYLON.Sound("gunshot", "static/gun.wav", scene); window.addEventListener("mousedown", function (e) { if (!lock && e.button === 0) gunS.play(); }); 

矢印を前埌に抌しお、それに応じお再生を開始した堎合に、機噚の動きの音を停止したす。 キヌリリヌスむベントで、再生を停止したす。

  var ms = new BABYLON.Sound("mss", "static/move.mp3", scene, null, { loop: true, autoplay: false }); document.addEventListener("keydown", function(e){ switch (e.keyCode) { case 38: case 40: case 83: case 87: if (!ms.isPlaying) ms.play(); break; } }); document.addEventListener("keyup", function(e){ switch (e.keyCode) { case 38: case 40: case 83: case 87: if (ms.isPlaying) ms.pause(); break; } }); 

ミニマップ


シュヌティングゲヌムには、プレむダヌだけを芋るこずができるミニマップ、たたは䞀床にすべおを芋るこずができるミニマップが必芁です。この堎合、よく芋るず、シェルを芋るこずができたす。 babylon.jsこれを実装する方法はいく぀かありたす。 おそらく最も簡単な方法は、別のカメラを䜜成し、マップの䞊に配眮し、このカメラからのビュヌを必芁なコヌナヌに配眮するこずです。


私たちの堎合、 freeCameraを䜿甚しお、 freeCameraを䞀番䞊に配眮するように䌝えたす。

 camera2 = new BABYLON.FreeCamera("minimap", new BABYLON.Vector3(0,170,0), scene); 

Y座暙が倧きいほど、ビュヌは完党になりたすが、マップの詳现は现かくなりたす。
次に、カメラに画像をスクリヌンに配眮する方法をカメラに䌝えたす。

 camera2.viewport = new BABYLON.Viewport(x, y, width, height); 

最埌に、䞡方のカメラをシヌンに远加する必芁がありたすカメラが1台の堎合、これを行う必芁はありたせん。

 scene.activeCameras.push(camera); scene.activeCameras.push(camera2); 

5. Web゜ケットずゲヌムの同期


ゲヌムの基本構造党䜓がwebsoket構築され、プレむダヌは䜕らかのアクション、マりスの回転、たたはキヌストロヌクを実行し、プレむダヌの䜍眮座暙がサヌバヌに送信されるむベントがこの動きでハングアップしたす。郚屋。

最初は、 FreeCameraを䜿甚するため、芪オブゞェクトであるため、その座暙を䜿甚したす。 䟋


次の図では、サヌバヌぞの接続を開いお新しいプレヌダヌを䜜成しおから、ナヌザヌのアクションに応答するずきにメッセヌゞを亀換するたでのプロセス䟋を瀺しおいたす。



6.サヌバヌ偎のデバむス


䞊蚘では、非垞に簡朔な簡単な図を芋たしたが、今床はサヌバヌ偎の動䜜に぀いお詳しく説明したす。 ゜ケットハンドラヌの関数では、次のメッセヌゞを受信した埌、そのactionを確認し、次にプレヌダヌが実行したactionを確認し、これに埓っお目的の関数、むベントハンドラヌを呌び出したす。

 async def game_handler(request): . . . async for msg in ws: if msg.tp == MsgType.text: if msg.data == 'close': await ws.close() else: e = json.loads( msg.data ) action = e['e'] if action in handlers: handler = handlers[action] handler(ws, e) . . . 

たずえば、 moveが来た堎合、それはプレむダヌがいく぀かの座暙に移動したこずを意味したす。 このアクションの関数ハンドラヌでは、これらの座暙をPlayerクラスに割り圓おるだけで、それらの座暙が凊理されお戻され、さらに珟圚の郚屋の他のすべおのプレヌダヌに送信されたす。

 def h_move(me, e): me.player.set_pos(e['x'], e['y'], e['z']) mess = dict(e="move", id=me.player.id, **me.player.pos_as_dict) me.player.room.send_all(mess, except_=(me.player,)) 

もちろん、珟圚Playerクラスが座暙で行うこずはすべお、単玔にそれらをボットに枡しお、焊点を合わせたす。 そしお理想的には、座暙でマップ党䜓をチェックする必芁がありたす。プレヌダヌが障害に遭遇した堎合、たずえば䞍正行為を避けるために、クラむアントでスクリプトが倉曎された堎合、壁から挏れないようにする必芁がありたす。

 class Player(list): . . . def __init__(self, client, room, x=0, y=0, z=0, a=0, b=0): list.__init__(self, (x, y, z, a, b)) self._client = client self._room = room Player.last_id += 1 self._id = Player.last_id room.add_player(self) . . . def set_rot(self, a, b): self[3:5] = a, b def getX(self): return self[0] . . . def setX(self, newX): self[0] = newX . . . x = property(getX, setX) . . . @property def pos_as_dict(self): return dict(zip(('x', 'y', 'z'), self.pos)) 

Playerクラスでは、 propertyを䜿甚しお、座暙をより䟿利に凊理したす。 興味深いのは、ハブラでこのテヌマに関する良い資料があったこずです。

7.郚屋ごずのプレむダヌのバランス


ゲヌムのかなり重芁な郚分は、異なる氏族、郚屋、惑星、囜などでプレむダヌを育おるこずです。 それ以倖の堎合、すべおが1枚のカヌドに収たらないからです。 私たちの堎合、システムはただ非垞にシンプルです-1぀の郚屋に蚭定で蚭定されおいるよりも倚くのプレむダヌがいる堎合デフォルトではボットで4、新しい郚屋を䜜成し、残りのプレむダヌをそこに円で送信したす。

珟時点では、ショヌケヌスずレヌティングがないため、䜕らかのベヌスを䜿甚する意味がないため、どの郚屋のどのプレヌダヌなどに関するすべおの情報がメモリに保存されたす。

ルヌム番号は、プレむダヌがルヌト/pregameあるスタヌトペヌゞからゲヌムに入るずきに割り圓おられたす。 ボタンが抌されるず、 ajaxトリガヌされたす。結果が成功した堎合は、プレヌダヌが目的の郚屋にリダむレクトされたす。

 if (data.result == 'ok') { window.location = '/game#'+data.room; 

サヌバヌ偎では、すべおの郚屋ずその䞭のプレむダヌのリストを含むroomsディクショナリidたす。プレむダヌの数が指定された倀を超えおいない堎合は、郚屋idクラむアントに返したす。 プレむダヌの数が倚い堎合は、新しい郚屋を䜜成したす。

 def check_room(request): found = None for _id, room in rooms.items(): if len(room.players) < 3: found = _id break else: while not found: _id = uuid4().hex[:3] if _id not in rooms: found = _id 

Roomに぀いおは、 Roomクラスを担圓したす。 圌の䞀般的な䜜業スキヌムは次のようになりたす。


Playerクラスず盞互䜜甚するこずがわかりたす。おそらく、スキヌム党䜓は完党に線圢に芋えたせんが、最終的には、このようなチェヌンを非垞に䟿利に曞くこずができたす。

 #        me.player.room.send_all( {"e" : "move", . . . }) #     me.player.room.players #     me.player.room.add_player(self) #     me.player.room.remove_player( me.player ) 

私は、私の同僚に぀いお、この提起された質問に぀いお少し話をしたいず思いたす。 meは、むベントを提䟛する関数のパラメヌタヌずしお枡される゜ケットです。

 def h_new(me, e): me.player = Player(me, Room.get( room_id ), x, z) 

ここで、実際には、翻蚳者が蚀うように、しゃれ。 Pythonのすべおがオブゞェクトであるこずを知っおいるので。
これはより明確に起こるこずです

 player = Player( Room.get(room_id), x, z) player.me = me me.player = player 

playerモゞュヌルずmeオブゞェクトの.playerずいう2぀のリンクを取埗したす。䞡方ずも等しく、少なくずも1぀のリンクが存圚する限り存圚するメモリ内の同じオブゞェクトを参照したす。

これはさらに簡単な䟋で芋るこずができたす

 >>> a = {1} >>> b = a >>> b.add(2) >>> b {1, 2} >>> a {1, 2} 

この䟋では、 bずaは1぀の共通倀ぞの単なる参照です。

 >>> a.add(3) >>> a {1, 2, 3} >>> b {1, 2, 3} 

さらに調査したす。

 >>> class A(object): ... pass ... >>> a = A() >>> a.player = b >>> a.player {1, 2, 3} >>> b {1, 2, 3} >>> a.__dict__ {'player': {1, 2, 3}} 

オブゞェクトのプロパティは単なる構文糖です。 この堎合、それらは単に__dict__蟞曞に栌玍されたす

その結果、リンクa 1぀を匷制終了したしa 、その代わりに、新しく䜜成したオブゞェクトに属する別のリンクを䜜成し、実際にこのオブゞェクトの蟞曞__dict__たす。

 >>> a <__main__.A object at 0x7f3040db91d0> 

8. Asyncioおよびボットの動䜜生成


通垞のゲヌムでは、少なくずも1぀のボットが必芁です。このゲヌムも䟋倖ではありたせん。 もちろん、ボットができるのは同心円を描くこずだけで、プレむダヌがいる座暙に埐々に近づいおいきたす。 新しいプレヌダヌが入るず、ボットはそれに泚意を向けたす。
ボットが移動する座暙に関する郚屋内のすべおのプレむダヌにメッセヌゞを送信する行。

 mess = dict(e="move", bot=1, id=self.id, **self.pos_as_dict) self.room.send_all(mess, except_=(self,)) 

次のようにクラむアント郚分ずボットずの盞互䜜甚の䞀般的なスキヌムは次のずおりです。


クラスではRoom、私たちは、__init__クラスのむンスタンスを䜜成したすBot。そしお、すでにdef __init__クラスでBot、私たちはasyncio.async(self.update())各パス䞊で実行されなければならないタスクをperedaom。
を含む関数を呌び出しおもawait、関数自䜓は開始されたせんが、ゞェネレヌタヌオブゞェクトが䜜成されたす。classこの関数は開始しないため、宣蚀された関数を呌び出すだけでなく、このクラスが提䟛するオブゞェクトを䜜成したす。awaitゞェネレヌタヌでメ゜ッドが呌び出されるず、含む関数の呌び出しが発生したす.__next__()。この堎合- nextデコレヌタにありasync-コルヌチンを初期化したす。
簡単に蚀えば、100ミリ秒ごずにボットの新しい座暙を䜿甚しおクラむアントにメッセヌゞを送信し、0.5秒ごずにボットの座暙を曎新したす。

無限ルヌプでタスクを操䜜する簡単な䟋

 import asyncio async def test( name ): ctr = 0 while True: await asyncio.sleep(2) ctr += 1 print("Task {}: test({})".format( ctr, name )) asyncio.ensure_future( test("A") ) asyncio.ensure_future( test("B") ) asyncio.ensure_future( test("C") ) loop = asyncio.get_event_loop() loop.run_forever( ) 

入れたすべおの関数は、2秒でasyncio.ensure_future指定さasyncio.sleep(2)れた遅延で円で実行されたす。これの実甚的な甚途は非垞に広範囲であり、ゲヌム甚のボットに加えお、たずえばトレヌディングシステム甚のボットだけを曞くこずができたす。私の䞻芳的な意芋では、これは堎所での開発を簡玠化し、非垞に䟡倀があり、動物園を回避したす。

9. Nginxおよび゜ケットプロキシ


そしおゲヌムに関しお蚀及する最埌のこずは、Nginx私たちのプロゞェクトが確実に動䜜するwebsocketず確信しおいる堎合の正しい蚭定ですhttp。最初に思い浮かぶのは、この構成のようなものです

 server { server_name aio.dev; location / { proxy_pass http://127.0.0.1:8080; } } 

たた、ロヌカルで正垞に動䜜したすが、1぀の根本的な欠点がありたす。゜ケットは、この蚭定では倖郚サヌバヌで動䜜し5.5.5.10なくなりloalhostたす。
したがっお、次のアむデアは曞くこずです。

 server { server_name aio.dev; location / { proxy_pass http://5.5.0.10:8080; } } 

しかし、圌女はPythonのパフォヌマンス性胜の䜎いので、あたりにも、欠陥があるnginx桁違いによるず、いずれの堎合にproxy_passしなければならないhttp://127.0.0.1:8080
ので、機䌚を取るNginx゜ケットをプロキシ、数幎前に登堎し-aを、

 server { server_name aio.dev; location / { proxy_pass http://127.0.0.1:8080; } location /ws { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } 

゜ケットを初期化するずきのアドレスには、ポヌト80を指定したす。これは、明瀺的に指定しない限り、デフォルトでポヌト80でリッスンするように構成されおいるvar uri = "ws://aio.dev:80/ws"ためNginxですlisten。
この構成では、それがために働くだろうNginx番目、そしお䟿利にアクセス可胜ずなりwebsoket、S、およびhttp。

10.非同期キャッシュ。


このゲヌムはフレヌムワヌクのプラグむンコンポヌネントの1぀ずしお蚘述されおいるため、小さなむノベヌションに぀いお少し説明したいず思いたす。

そのmemcachedため、で関数を䜿甚するペヌゞキャッシングの䟋を考えおみたしょうasync def。倚かれ少なかれ蚪問したクラシックサむトでは、メむンペヌゞ、ニュヌスペヌゞなどの蚪問したペヌゞをキャッシュできるほか、ペヌゞが倉曎されたずきにキャッシュ時間が切れる前にキャッシュをリセットできるようにする必芁がありたす。幞いなこずに、memcached の非同期ドラむバヌは既にsvetlovによっお䜜成されおおり、デコレヌタヌを䜜成し、いく぀かの小さな問題を解決するために残っおいたす。

それ自䜓では、たずえば、次のように、任意の関数に察しおデコレヌタの圢でかなり銎染みのある方法でキャッシングを行うこずが決定されたした。ビヌカヌ。デコレヌタでは、キャッシュ時間を蚭定し、特にmemcachedのキヌずなる名前を蚭定する必芁がありたす。

デヌタmemcachedはシリアル化されお䜿甚されpickleたす。そしおもう1぀のニュアンス-フレヌムワヌクは最䞊郚aiohttpに蚘述さCIMultiDictれおいるため、シリアル化されおいたせん。同じキヌを持぀機胜を備えた蟞曞の実装であり、䜜成Cython者により高速に蚘述されおいたすaiohttp。

  dct = CIMultiDict() print( dct ) <CIMultiDict {}> dct = MultiDict({'1':['www', 333]}) print( dct ) <MultiDict {'1': ['www', 333]}> dct = MultiDict([('a', 'b'), ('a', 'c')]) print( dct ) <MultiDict {'a': 'b', 'a': 'c'}> dct = dict([('a', 'b'), ('a', 'c')]) print( dct ) {'a': 'c'} 

したがっお、そこに栌玍された倀はでシリアル化できたせんでしたpickle。したがっお、それらを取埗しお再梱包する必芁がありたしたが、時間が経぀に぀れおCIMultiDictシリアル化可胜になるこずを願っおいpickleたす。

 d = MultiDict([('a', 'b'), ('a', 'c')]) prepared = [(k, v) for k, v in d.items()] saved = pickle.dumps(prepared) restored = pickle.loads(saved) refined = MultiDict( restored ) 

完党なキャッシングコヌド
 def cache(name, expire=0): def decorator(func): async def wrapper(request=None, **kwargs): args = [r for r in [request] if isinstance(r, aiohttp.web_reqrep.Request)] key = cache_key(name, kwargs) mc = request.app.mc value = await mc.get(key) if value is None: value = await func(*args, **kwargs) v_h = {} if isinstance(value, web.Response): v_h = value._headers value._headers = [(k, v) for k, v in value._headers.items()] await mc.set(key, pickle.dumps(value, protocol=pickle.HIGHEST_PROTOCOL), exptime=expire) if isinstance(value, web.Response): value._headers = v_h else: value = pickle.loads(value) if isinstance(value, web.Response): value._headers = CIMultiDict(value._headers) return value return wrapper return decorator 


キャッシングは、デコレヌタを䞀番䞊に蚘述し、キャッシュの有効期限ず名前を指定するだけで適甚できたす。

 from core.union import cache @cache('list_cached', expire=10 ) async def list_tags(request): return templ('list_tags', request, {}) 

あずがき


この段階では、それはむしろ、可胜性を実蚌するために、可胜性の高いゲヌムの初期の実斜段階であるずWebGLし、asyncio補品版より。しかし、フレヌムワヌクの将来のバヌゞョンでは、すべおが理想にはるかに近づくこずを願っおいたす。空䞭、地䞊、そしお単に個々のプレむダヌずしお、プレむダヌが戊闘のキャラクタヌを遞択したり動的に倉曎したりできるスペヌスサガの圢でゲヌムを䜜りたいず思いたす。

私は垞にスタヌりォヌズのキャラクタヌが奜きだったので、歎史的なものよりも未来的な方法ですべおをやりたいです。
蚭定でゲヌムの任意のレベルをロヌカラむズし、それをメむンのレベルにし、可胜な限りゲヌムのカヌドずキャラクタヌを動的に倉曎する機胜を備えおいたす。

以䞋は、䞻に、ある皋床蚀える皋床に珟圚存圚し、最も可胜性の高い、さらなる䜜業が行われる䞻な欠点です。

ping

サヌバヌは各プレヌダヌからのpingを監芖し、ヒット、移動などの速床を同期しようずする必芁がありたす。少なくずもおよそ。新しいプレむダヌが参加するずき、圌は察戊盞手がほが同じpingを持っおいる郚屋に入る必芁がありたす。商業甚ですが、さたざたなオプションが思い浮かびたす。

䞍正行為

圓然、クラむアントを決しお信頌するべきではありたせん。通垞のサヌバヌでは、マップ党䜓を完党に理解し、プレヌダヌのすべおの動き、匟䞞の軌道をチェックする必芁がありたす。そうでなければ、ゲヌムの最小の人気で、倚様な䞍正行為の繁栄は避けられないでしょう。

ロヌドマップ-ゲヌム


クラむアント



サヌバヌ



ロヌドマップ-フレヌムワヌク党䜓



䜕かを曞くのを忘れお、どこかで圌は甚語ず間違えられるかもしれたせん。したがっお、すべおの文法的およびその他の゚ラヌをPMに曞き蟌むようお願いしたす。

前線
babylon.jsに関する蚘事を確認し、 githubのthree.js
ラむブラリず比范する
ドキュメントを読む
無料の倧芏暡な遞択を䞻芁なサむトの䞀぀ずは、3Dモデルを支払った
ブレンダヌのための無料の3Dモデルずりェブサむトを
回転
babylon.jsの䞭の音ず䜜業
音の可芖化䟋
asynioにネロの䞖界
スリヌプ
タスクず䜜業
ステッチ通話
PEP-0492
のブログ Svetlovの aiohttp著者
memcachedの非同期ドラむバ
babylon.jsのための曎新されたドキュメント
githubの䞊の文曞aiohttp
aiohttpドキュメントreadthedocsのための
歩留たり文からドキュメント
ラむブラリのリスト- AIO-LIBS
の別のより包括的なリスト

発電機の詳现
http://www.dabeaz.com/generators/Generators。 pdf
http://www.dabeaz.com/coroutines/Coroutines.pdf
http://www.dabeaz.com/finalgenerator/FinalGenerator.pdf

Source: https://habr.com/ru/post/J252575/


All Articles