本文最后更新于 862 天前,其中的信息可能已经有所发展或是发生改变。
menu
:菜单页面
playground
:游戏界面
settings
:设置界面
对于复杂的界面设计,我们在每个界面下递归细分功能模块,直到实现最基本的功能模块。模块化设计便于项目创建、更新和维护。
| project/ #项目系统设计 |
| |-- menu #菜单界面 |
| |-- playground #游戏界面 |
| | |-- maps #地图 |
| | |-- players #人物 |
| | | |-- atcions #人物动作 |
| | | |-- movements #人物移动 |
| | | `-- talents #人物属性 |
| | `-- time #时间 |
| `-- settings #设置界面 |
对于一个 Django
项目,有如下框架:
| django_project/ |
| |-- django_project #整个Django项目的配置 |
| | |-- __init__.py #初始化文件 |
| | |-- __pycache__ |
| | | |-- __init__.cpython-38.pyc |
| | | `-- settings.cpython-38.pyc |
| | |-- asgi.py #异步通信服务启动文件 |
| | |-- settings.py #项目的全局配置文件 |
| | |-- urls.py #项目的全局路由设置 |
| | `-- wsgi.py #web网关服务启动文件 |
| |-- manage.py #命令行工具 |
| `-- project #子应用 |
| |-- __init__.py |
| |-- admin.py |
| |-- apps.py |
| |-- consumers #管理 websocket 函数 |
| |-- migrations |
| | `-- __init__.py |
| |-- models #管理数据库数据 |
| |-- static #管理静态文件 |
| | |-- audio #声音 |
| | |-- css #对象格式 |
| | |-- image #图片 |
| | `-- js #对象逻辑(脚本) |
| |-- templates #管理html |
| |-- tests.py |
| |-- urls #管理路由 |
| `-- views #管理http函数 |
我们在 python
中调用 import urls.xxx
时,需要索引文件 __init__.py
。为了便于维护 urls.py
、views.py
、models.py
,我们将其转为文件夹的方式存储,并在这三个文件夹目录下都添加 __init__.py
文件。
对于 templates
,urls
,views
等的文件夹,最好都建立文件夹menu
,playground
,settings
文件夹,用于细分模块设计。
对于 css
一般不需要细分。
对于 js
需要分为 dist
和 src
两个文件,dist
是最终打包好的 .js
文件,src
用于存储开发时的各种模块化的 .js
文件供。
我们可以在 acappp/
下创建一个文件夹 scripts
,用来存储各种脚本,将 src
打包为 dist
,创建打包 src
的脚本 compress_game_js.sh
如下
| #!/bin/bash |
| |
| JS_PATH=~/workspace/ac_app/ACApp/game/static/js/ |
| JS_PATH_DIST=${JS_PATH}/dist/ |
| JS_PATH_SRC=${JS_PATH}/src/ |
| |
| find ${JS_PATH_SRC} -type f -name "*.js" | sort | xargs cat > ${JS_PATH_DIST}game.js |
记得加上可执行权限:
| chmod +x compress_game_js.sh |
添加子应用:
打开/game/apps.py
,找到 class GameConfig
,然后在全局的 settings.py
里找到INSTALLED_APPS
,在里面加入 :
以便将创建的 game
加入进去。
静态文件地址设置:
打开 settings.py
,找到 STATIC_URL = '/static/'
,在该条目上方加入:
| STATIC_ROOT = os.path.join(BASE_DIR, 'static') |
| STATIC_URL = '/static/' |
此外按照上述方式再加入:
| MEDIA_ROOT = os.path.join(BASE_DIR, 'media') |
| MEDIA_URL = '/media/' |
- 一般来说,
static
存开发的文件,media
存用户的文件。
同时要记得import os
,os.path()
是将路径合并在一起。通过该操作可以使我们的静态文件会放到这个目录下。
| import os |
| from pathlib import Path |
首先进入 /game/templates/
,创建三个文件夹 menu
,playground
,settings
文件夹,便于模块化设计。为了支持多种终端上运行,再创建一个文件夹 multiends
存储 html
文件。
先实现网页端,创建 web.html
:
| {% load static %} |
| |
| <head> |
| |
| |
| <link rel="stylesheet" href="https://cdn.acwing.com/static/jquery-ui-dist/jquery-ui.min.css"> |
| |
| <script src="https://cdn.acwing.com/static/jquery/js/jquery-3.3.1.min.js"></script> |
| |
| <link rel="stylesheet" href="{% static 'css/game.css' %}"> |
| |
| <script src="{% static 'js/dist/game.js' %}"></script> |
| </head> |
| |
| <body style="margin: 0"> |
| |
| |
| <div id="ac_game_12345678"></div> |
| |
| <script> |
| $(document).ready(function(){ |
| let ac_game = new AcGame("ac_game_12345678"); |
| }); |
| </script> |
| </body> |
js
在客户端渲染,而 views
和 urls
在后端处理,由此实现前后端分离,能够减轻服务器的压力,并能适应多终端的开发需求。
在 html
文件的 <body>
内的 <script>
将页面渲染交给客户,调用 let ac_game = AcGame();
创建一个 js
对象,接下来实现这个创建 js
对象的文件。
进入 /game/static/js/
,同样创建三个文件夹 menu
,playground
,settings
,再创建一个总文件 zbase.js
。由于打包时按照文件名字典序排列的,可以保证在打包的时 zbase.js
在最后打包。
| class AcGame { |
| constructor(id) { |
| } |
| } |
在 web.html
中的 let ac_game = AcGame()
括号里面添加 id
,即 AcGame("ac_game_12345678")
,表示渲染<div id="ac_game_12345678">
。
进入 /game/views
,同样创建三个文件夹 menu
,playground
,settings
,在这三个文件夹里存放需要被调用的 .py
文件,故都要添加索引 __init__.py
。
在 /game/views/
里面写总的 index.py
:
| from django.shortcuts import render |
| |
| def index(request): |
| return render(request, "multiends/web.html") |
这个 index.py
只会在 html
即 Web
中被调用,未来其他东西都不会调用他它,主要用来访问刚刚写的 html
。
其中 from django.shortcuts import render
是 Django
的渲染工具,render
用来渲染 html
文件,通过 Python
来把 html
的内容写到网页上去。此处的路径是从 /game/templates/
开始的。
进入 /game/urls
,同样创建三个文件夹 menu
,playground
,settings
,在这三个文件夹里存放需要被调用的 .py
文件,故都要添加索引 __init__.py
。
每个文件夹下添加对应的路由 index.py
,格式如下:
| from django.urls import path |
| |
| urlpatterns = [ |
| ---- |
| ] |
最后在 /game/urls/
里面写总的 index.py
:
| from django.urls import path, include |
| from game.views.index import index |
| |
| urlpatterns = [ |
| path('', index, name='index'), |
| path('menu/', include('game.urls.menu.index')), |
| path('playground/', include('game.urls.playground.index')), |
| path('settings/', include('game.urls.settings.index')), |
| ] |
进入 game/static/js/src/zbase.js
,增添内容为:
| class AcGame { |
| constructor(id) { |
| this.id = id; |
| this.$ac_game = $(`#` + id); |
| this.menu = new AcGameMenu(this); |
| this.playground = new AcGamePlayground(this); |
| } |
| } |
以上实现的是整个 js
对象文件的定义部分,接下来在各个模块里实现相应的 js
对象文件。
进入 game/static/js/src/menu
,创建 zbase.js
:
| class AcGameMenu { |
| constructor(root) { |
| this.root = root; |
| this.$menu = $(` |
| <div class="ac_game_menu"> |
| <div class="ac_game_menu_field"> |
| <div class="ac_game_menu_field_item ac_game_menu_field_item_single_mod"> |
| 单人模式 |
| </div> |
| <br> |
| <div class="ac_game_menu_field_item ac_game_menu_field_item_multi_mod"> |
| 多人模式 |
| </div> |
| <br> |
| <div class="ac_game_menu_field_item ac_game_menu_field_item_settings"> |
| 设置 |
| </div> |
| </div> |
| </div> |
| `); |
| this.root.$ac_game.append(this.$menu); |
| this.$single_mod = this.$menu.find('.ac_game_menu_field_item_single_mod'); |
| this.$multi_mod = this.$menu.find('.ac_game_menu_field_item_multi_mod'); |
| this.$settings = this.$menu.find('.ac_game_menu_field_item_settings'); |
| |
| this.start(); |
| |
| } |
| start() { |
| this.add_listening_events(); |
| } |
| |
| add_listening_events() { |
| let outer = this; |
| this.$single_mod.click(function(){ |
| outer.hide(); |
| outer.root.playground.show(); |
| }); |
| this.$multi_mod.click(function(){ |
| console.log("click mulit_mod"); |
| }); |
| this.$settings.click(function(){ |
| console.log("click settings"); |
| }); |
| } |
| |
| |
| show() { |
| this.$menu.show(); |
| } |
| |
| hide() { |
| this.$menu.hide(); |
| } |
| |
| } |
jquery
库提供了 api
接口 append(this.$menu)
,目的是将 this.$menu
加入到 $ac_game
存储的 <div>
块内。
<div class="ac_game_menu">
在 $menu
内定义一个 ac_game_menu
,该样式从 /game/static/css/game.css
中调用,其他同理。
同理进入 /game/static/js/src/playground
,创建 zbase.js
:
| class AcGamePlayground { |
| constructor(root) { |
| this.root = root; |
| this.$playground = $(`<div>游戏界面</div>`); |
| |
| this.hide(); |
| this.root.$ac_game.append(this.$playground); |
| |
| this.start(); |
| } |
| |
| start() { |
| } |
| |
| show() { |
| this.$playground.show(); |
| } |
| |
| hide() { |
| this.$playground.hide(); |
| } |
| |
| } |
本节重点在于菜单界面的创建,至此简单实现了菜单界面跳转到游戏界面的按钮功能,后续添加实现其他功能。
js
对象文件创建完毕后,前端调用会在用户端进行渲染,其 html
样式仍需要从 /game/css
里调用。
首先下载一些静态资源,如背景图片等:
| wget --output-document=自定义图片名称 图片地址 |
进入 /game/static/css/
,打开 game.css
:
| |
| .ac_game_menu { |
| width: 100%; |
| height: 100%; |
| background-image: url("/static/image/menu/background.png"); |
| background-size: 100% 100%; |
| user-select: none; |
| } |
| |
| |
| .ac_game_menu_field { |
| width = 20vw; |
| position: relative; |
| top: 40vh; |
| left: 19vw; |
| } |
| |
| |
| .ac_game_menu_field_item { |
| color: white; |
| width: 18vw; |
| height: 7vh; |
| font-size: 6vh; |
| font-style: italic; |
| padding: 2vh; |
| text-align: center; |
| background-color: rgba(39, 21, 28, 0.6); |
| border-radius: 20px; |
| letter-spacing: 0.5vw; |
| cursor: pointer; |
| } |
| |
| |
| .ac_game_menu_field_item:hover { |
| transform: scale(1.15); |
| transition: 130ms; |
| } |
实现完菜单界面的对应文件后,我们利用之前设计的打包脚本,将这些文件打包到 /game/static/js/dist
。
回到 scripts
文件夹,运行打包脚本:
最后启动服务查看菜单界面:
| python3 manage.py runserver 0.0.0.0:8000 |