本节内容是项目结构的划分与游戏菜单界面的设计。
1. 项目总体设计
(1)系统设计
menu
:菜单页面;
playground
:游戏界面;
settings
:设置界面。
(2)文件结构
templates
:管理 HTML 文件;
urls
:管理路由,即链接与函数的对应关系;
views
:管理 HTTP 函数;
models
:管理数据库数据;
static
:管理静态文件,比如:
css
:对象的格式,比如位置、长宽、颜色、背景、字体大小等;
js
:对象的逻辑,比如对象的创建与销毁、事件函数、移动、变色等;
image
:图片;
audio
:声音;
……
consumers
:管理 WebSocket 函数。
(3)素材地址
背景图片:
下载方式:wget --output-document=自定义图片名称 图片地址
;
本地上传:scp -P 20000 .\xxx.jpeg asanosaki@<公网IP>:
。
jQuery
库:
<link rel="stylesheet" href="http://<公网IP>:8000/static/css/jquery-ui.min.css">
;
<script src="http://<公网IP>:8000/static/js/jquery-3.6.1.min.js"></script>
。
2. 全局设置与项目结构创建
为了后期方便项目的维护管理,首先先将 game
中的 urls.py
、models.py
、views.py
删除,将其创建为一个目录,并在这三个目录下创建好 __init__.py
文件,注释掉上一节中在总 URL 文件中的配置信息,然后创建好 static
目录。
接着进行一些项目的全局设置,首先设置一下项目的时区,打开 ~/djangoapp/djangoapp/settings.py
,修改 TIME_ZONE
和 USE_TZ
:
1 2 3 TIME_ZONE = 'Asia/Shanghai' USE_TZ = False
如果 USE_TZ
设置为 True
时,Django 会使用系统默认设置的时区,即 America/Chicago
,此时的 TIME_ZONE
不管有没有设置都不起作用。
注意:由于我们是在云服务器上开发的,如果是 Windows 则设置 TIME_ZONE
是无效的,Django 会使用本机的时间。
然后将自己创建的 App 加载进来,找到 INSTALLED_APPS
,将 game/apps.py
添加进来:
1 2 3 4 5 6 7 8 9 INSTALLED_APPS = [ 'game.apps.GameConfig' , 'django.contrib.admin' , 'django.contrib.auth' , 'django.contrib.contenttypes' , 'django.contrib.sessions' , 'django.contrib.messages' , 'django.contrib.staticfiles' , ]
找到 STATIC_URL = 'static/'
,在其附近添加几行:
1 2 3 4 5 6 import os STATIC_ROOT = os.path.join(BASE_DIR, 'static' ) STATIC_URL = 'static/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media' ) MEDIA_URL = 'media/'
我们在 game/static/
中创建 image/menu/
目录用来存放菜单界面的背景,将图片 background.png
放入该目录中即可在自己的网址上访问这张图片:http://<公网IP>:8000/static/image/menu/background.png
。
一般 CSS 文件只需要一个就行,因此只需要在 game/static/css/
中创建一个 game.css
文件即可。JS 文件最后一般会有很多,因此在 game/static/js/
中创建两个目录:dist
和 src
,分别表示最终合并在一起生成的 js
文件以及许多 js
源文件,我们可以写一个脚本完成合并操作,在 ~/djangoapp/
目录下创建一个 scripts
目录,然后在该目录中编写一个 compress_game_js.sh
文件:
1 2 3 4 5 6 7 # ! /bin/bash JS_PATH=/home/asanosaki/djangoapp/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
添加可执行权限:
1 chmod +x compress_game_js.sh
我们执行一下该脚本:./compress_game_js.sh
,可以看到 ~/djangoapp/game/static/js/dist/
中多了一个 game.js
文件。
此时我们先将代码上传至 Git:
1 2 3 4 cd ~/djangoapp/ git add . git commit -m 'create project structure' git push
3. 创建HTML
我们先在 templates
目录下创建三个目录:menu
、playground
、settings
。由于项目是前后端分离的,最后可以放在多种不同的终端上运行,因此我们再建一个 multiends
目录。
在 static/src
目录下也创建三个目录:menu
、playground
、settings
,然后再创建一个文件 zbase.js
,表示总文件,由于打包工具是按照字典序打包的,该文件中为总的 Class,会调用前面三个目录中的 Class,JS 在调用之前必须定义好,因此在打包时需要保证前面三个目录中的文件在 zbase.js
之前被打包,因此加一个字典序最大的字母在首部。
在 zbase.js
中定义好总类:
1 2 3 4 class AcGame { constructor (id ) { } }
在 templates/multiends/
中创建 web.html
,文件内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 {% load static %} <head > <link rel ="stylesheet" href ="http://<公网IP>:8000/static/css/jquery-ui.min.css" > <script src ="http://<公网IP>:8000/static/js/jquery-3.6.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_1" > </div > <script > $(document ).ready (function ( ) { let ac_game = new AcGame ("ac_game_1" ); }); </script > </body >
4. 创建Views与更新URL
我们先在 views
目录下创建三个目录:menu
、playground
、settings
,这三个目录都是存放 Python 文件的,因此每个目录下都需要一个 __init__.py
文件。
然后再在 views
目录下创建一个 index.py
作为总函数,该函数只会在 Web 端被调用,主要作用是用来返回上一节中的 HTML 文件的:
1 2 3 4 from django.shortcuts import renderdef index (request ): return render(request, 'multiends/web.html' )
现在我们开始写路由,先在 urls
目录下创建三个目录:menu
、playground
、settings
,在每个目录下都创建一个 __init__.py
文件。接着同样创建一个 index.py
,用来将所有该路径下其它目录中的路径 Include 进来,可以参考总 URL 文件编写。
先在三个目录中也创建好 index.py
,内容如下:
1 2 3 from django.urls import pathurlpatterns = []
此前在 views
目录中实现的 index.py
为总函数,即整个项目只有一个主链接,因此 urls
目录中的 index.py
也要将其 Include 进来:
1 2 3 4 5 6 7 8 9 from django.urls import path, includefrom game.views.index import indexurlpatterns = [ 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' )), ]
最后修改一下总 URL 文件(~/djangoapp/djangoapp/
中的 urls.py
):
1 2 3 4 5 6 7 from django.contrib import adminfrom django.urls import path, includeurlpatterns = [ path('' , include('game.urls.index' )), path('admin/' , admin.site.urls), ]
此时梳理一下路由顺序:首先会进入到 ~/djangoapp/djangoapp/
中的 urls.py
中,然后发现浏览器链接中没有带后缀(例如 admin/
),所以会进到 game.urls.index
中,由于没有后缀因此又调用第一个路由,也就是直接调用 game.views.index
中的 index
函数,该函数会渲染 multiends/web.html
里面的内容。
Tips:浏览器中按 F12 打开控制台后如果看到报错:The Cross-Origin-Opener-Policy header has been ignored, because the URL's origin was untrustworthy. It was defined either in the final response or a redirect.
,表示出现了跨域问题,在 settings.py
中添加如下代码即可:
1 SECURE_CROSS_ORIGIN_OPENER_POLICY = 'None'
最后将代码上传至 Git:
1 2 3 git add . git commit -m 'modify html & js & views & urls' git push
5. 创建菜单
我们需要创建一个菜单对象,首先在 static/js/src/menu/
目录中创建一个 zbase.js
文件,内容如下:
1 2 3 4 5 6 7 8 9 10 11 class AcGameMenu { constructor (root ) { this .root = root; this .$menu = $(` <div class='ac_game_menu'> </div> ` ) this .root .$ac_game .append (this .$menu ); } }
然后在 game.css
中定义相应的样式:
1 2 3 4 5 6 .ac_game_menu { width : 100% ; height : 100% ; background-image : url ('/static/image/menu/background.png' ); background-size : 100% 100% ; }
最后需要更新 static/js/src/
中的 zbase.js
文件:
1 2 3 4 5 6 7 class AcGame { constructor (id ) { this .id = id; this .$ac_game = $('#' + id); this .menu = new AcGameMenu (this ); } }
此时即可在页面中看到自己的背景图片(注意更新完 JS 文件后都需要执行一下打包脚本 compress_game_js.sh
)。
Tips:如果修改完 CSS 文件后网页没有变化说明页面把 CSS 文件缓存下来了,可以按 F12 打开控制台,在 Network 选项卡中勾选上 Disable cache
。
现在我们在菜单界面添加几个按钮,首先修改菜单目录中的 zbase.js
文件(修改完记得运行打包脚本):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class AcGameMenu { constructor (root ) { this .root = root; this .$menu = $(` <div class='ac_game_menu'> <div class='ac_game_menu_btgroup'> <div class='ac_game_menu_btgroup_bt ac_game_menu_btgroup_bt_single'> 单人模式 </div> <br> <div class='ac_game_menu_btgroup_bt ac_game_menu_btgroup_bt_multi'> 多人模式 </div> <br> <div class='ac_game_menu_btgroup_bt ac_game_menu_btgroup_bt_settings'> 设置 </div> </div> </div> ` ); this .root .$ac_game .append (this .$menu ); this .$single = this .$menu .find ('.ac_game_menu_btgroup_bt_single' ); this .$multi = this .$menu .find ('.ac_game_menu_btgroup_bt_multi' ); this .$settings = this .$menu .find ('.ac_game_menu_btgroup_bt_settings' ); } }
然后修改 game.css
设置一下按钮的样式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 .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_btgroup { width : 20vw ; position : relative; top : 35vh ; left : 19vw ; } .ac_game_menu_btgroup_bt { height : 7vh ; width : 18vw ; color : white; font-size : 6vh ; line-height : 7vh ; font-style : italic; padding : 2vh ; cursor : pointer; text-align : center; background-color : rgba (39 , 21 , 28 , 0.6 ); border-radius : 10px ; letter-spacing : 0.5vw ; } .ac_game_menu_btgroup_bt :hover { transform : scale (1.2 ); transition : 100ms ; }
现在我们实现点击按钮切换页面的功能,需要给每个按钮绑定一个函数,我们可以定义一个 start
函数放在构造函数中,表示对象被创建出来时需要执行的一些初始化操作,即在 start
中可以绑定一些事件。
首先我们先把游戏界面的简易版本写出来,在 static/js/src/playground/
目录中创建一个 zbase.js
文件,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class AcGamePlayground { constructor (root ) { this .root = root; this .$playground = $(` <div> 游戏界面 </div> ` ); this .root .$ac_game .append (this .$playground ); this .start (); } start ( ) { this .hide (); } show ( ) { this .$playground .show (); } hide ( ) { this .$playground .hide (); } }
然后更新一下总的 zbase.js
文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 class AcGame { constructor (id ) { this .id = id; this .$ac_game = $('#' + id); this .menu = new AcGameMenu (this ); this .playground = new AcGamePlayground (this ); this .start (); } start ( ) { } }
最后在菜单界面中设置一下按钮点击的响应操作,点击单人模式按钮即可跳转到 AcGamePlayground
界面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 class AcGameMenu { constructor (root ) { this .root = root; this .$menu = $(` <div class='ac_game_menu'> <div class='ac_game_menu_btgroup'> <div class='ac_game_menu_btgroup_bt ac_game_menu_btgroup_bt_single'> 单人模式 </div> <br> <div class='ac_game_menu_btgroup_bt ac_game_menu_btgroup_bt_multi'> 多人模式 </div> <br> <div class='ac_game_menu_btgroup_bt ac_game_menu_btgroup_bt_settings'> 设置 </div> </div> </div> ` ); this .root .$ac_game .append (this .$menu ); this .$single = this .$menu .find ('.ac_game_menu_btgroup_bt_single' ); this .$multi = this .$menu .find ('.ac_game_menu_btgroup_bt_multi' ); this .$settings = this .$menu .find ('.ac_game_menu_btgroup_bt_settings' ); this .start (); } start ( ) { this .add_listening_events (); } add_listening_events ( ) { let outer = this ; this .$single .click (function ( ) { outer.hide (); outer.root .playground .show (); }); this .$multi .click (function ( ) { }); this .$settings .click (function ( ) { }); } show ( ) { this .$menu .show (); } hide ( ) { this .$menu .hide (); } }
最后将代码上传至 Git:
1 2 3 git add . git commit -m 'modify html & css & menu & playground' git push
上一章:Django学习笔记-概述与项目环境配置 。
下一章:Django学习笔记-创建游戏界面 。