4、简易版web端荒野乱斗账户系统
小技巧:
ctrl + r
搜索历史指令,右方向键选择,回车直接执行python3 manage.py shell
进入django
项目交互界面,有提示自动补全功能。setting.py
中的debug
选项改成True
,这样就会输出后端错误信息。qq
截图,按住ctrl
键,然后在按c
就可以取色
用户数据模块
在 models
里创建数据表
game/Django
里创建一个新模块,就相当于创建一个新表。如下创建一个 player
类,记得添加 __init__.py
。
# /home/sdz/project/hyld/game/models
models
|-- __init__.py
|-- __pycache__
| `-- __init__.cpython-38.pyc
`-- player
|-- __init__.py
`-- player.py
player.py
如下:
from django.db import models
from django.contrib.auth.models import User
class Player(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
photo = models.URLField(max_length=256, blank=True)
def __str__(self):
return str(self.user)
在 admin.py
中注册自定义表
想让自己定义的表出现在后台管理页,则将其在 # /home/sdz/project/hyld/game/admin.py
中注册。
admin.py
如下。
from django.contrib import admin
from game.models.player.player import Player
# Register your models here.
admin.site.register(Play)
执行migrations
每次新定义数据表后,需要执行命令将其同步到数据库里。
# /home/sdz/project/hyld
python3 manage.py makemigrations
python3 manage.py migrate
多终端实现
整个游戏是一个先后端分离项目,为了能让后端知道前端是来自web、还是Acwing云端应用、还是小程序或者什么,即多终端实现。
需要在在主js
类HlydGame
中添加参数,比如实现AcWing
的云端应用,需要在初始化时将 AcWingOS
实例传入,以获取 AcWing
提供的各种接口。
在 game/static/js/src/palyground/zbase.js
中:
export class Hyld {
// 构造函数
constructor(id, AcwingOS) {
// 这个id是前端传进来的div的id
this.id = id;
// 我们要找这个div中的id的话,jquery中要使用('#'+id).
this.$hyld = $('#' + id);
this.AcwingOS = AcwingOS;
// 登录注册窗口
this.settings = new Settings(this);
// 创建一个菜单界面,赋值给menu
this.menu = new HyldMenu(this);
// 创建一个游戏,赋值给playground
this.playground = new HyldPlayground(this);
this.start();
}
start() {
}
}
后端接口
getinfo
在 game/views/settings/getinfo.py
中定义返回用户数据的逻辑,每一次刷新或者访问网页首先调用该接口。
from django.http import JsonResponse
from game.models.player.player import Player
def getinfo_acapp(request):
player = Player.objects.all()[0]
return JsonResponse({
'result': "success",
'username': player.user.username,
'photo': player.photo,
})
def getinfo_web(request):
user = request.user
if not user.is_authenticated:
return JsonResponse({
'result': "未登录"
})
else:
player = Player.objects.all()[0]
return JsonResponse({
'result': "success",
'username': player.user.username,
'photo': player.photo,
})
def getinfo(request):
platform = request.GET.get('platform')
if platform == "ACAPP":
return getinfo_acapp(request)
# elif platform == "WEB":
else:
return getinfo_web(request)
登入登出
在 game/views/settings/login.py
:
from django.http import JsonResponse
from django.contrib.auth import authenticate, login
def signin(request):
data = request.GET
username = data.get("username")
password = data.get("password")
user = authenticate(username=username, password=password)
if not user:
return JsonResponse({
'result': "用户名或密码不正确"
})
login(request, user)
return JsonResponse({
'result': "success"
})
在 game/views/settings/logout.py
:
from django.http import JsonResponse
from django.contrib.auth import logout
def signout(request):
user = request.user
if not user.is_authenticated:
return JsonResponse({
'result': "success"
})
logout(request)
return JsonResponse({
'result': "success"
})
实现注册
在 game/views/settings/register.py
:
from django.http import JsonResponse
from django.contrib.auth import login
from django.contrib.auth.models import User
from game.models.player.player import Player
def register(request):
data = request.GET
username = data.get("username", "").strip()
password = data.get("password", "").strip()
password_confirm = data.get("password_confirm", "").strip()
if not username or not password:
return JsonResponse({
'result': "用户和密码不能为空"
})
if password != password_confirm:
return JsonResponse({
'result': "两次密码不一致"
})
if User.objects.filter(username=username).exists():
return JsonResponse({
'result': "用户名已存在"
})
user = User(username=username)
user.set_password(password)
user.save()
Player.objects.create(user=user, photo="https://img2.baidu.com/it/u=2161949891,656888789&fm=26&fmt=auto")
login(request, user)
return JsonResponse({
'result': "success"
})
路由 urls
在 game/urls/settings/index.py
:
from django.urls import path, include
from game.views.settings.getinfo import getinfo
from game.views.settings.login import signin
from game.views.settings.logout import signout
from game.views.settings.register import register
urlpatterns = [
path("getinfo/", getinfo, name="settings_getinfo"),
path("login/", signin, name="settings_login"),
path("logout/", signout, name="settings_logout"),
path("register/", register, name="settings_register"),
]
如上我们把后端的接口调好了。
前端页面
使用ajax调用后端接口
在 game/static/js/src/settings/zbase.js
中:
class Settings {
constructor(root) {
this.root = root;
this.platform = "WEB";
if (this.root.AcWingOS) this.platform = "ACAPP";
this.username = "";
this.photo = "";
this.$settings = $(`
<div class="hyld-settings">
<div class="hyld-settings-login">
<div class="hyld-settings-title">
登录
</div>
<div class="hyld-settings-username">
<div class="hyld-settings-item">
<input type="text" placeholder="用户名">
</div>
</div>
<div class="hyld-settings-password">
<div class="hyld-settings-item">
<input type="password" placeholder="密码">
</div>
</div>
<div class="hyld-settings-submit">
<div class="hyld-settings-item">
<button>登录</button>
</div>
</div>
<div class="hyld-settings-error-message">
</div>
<div class="hyld-settings-option">
注册
</div>
<br>
<div class="hyld-settings-acwing">
<img width="30" src="https://app820.acapp.acwing.com.cn/static/image/settings/acwing_logo.png">
<br>
<div>
AcWing一键登录
</div>
</div>
</div>
<div class="hyld-settings-register">
<div class="hyld-settings-title">
注册
</div>
<div class="hyld-settings-username">
<div class="hyld-settings-item">
<input type="text" placeholder="用户名">
</div>
</div>
<div class="hyld-settings-password hyld-settings-password-first">
<div class="hyld-settings-item">
<input type="password" placeholder="密码">
</div>
</div>
<div class="hyld-settings-password hyld-settings-password-second">
<div class="hyld-settings-item">
<input type="password" placeholder="确认密码">
</div>
</div>
<div class="hyld-settings-submit">
<div class="hyld-settings-item">
<button>注册</button>
</div>
</div>
<div class="hyld-settings-error-message">
</div>
<div class="hyld-settings-option">
登录
</div>
<br>
<div class="hyld-settings-acwing">
<img width="30" src="https://app820.acapp.acwing.com.cn/static/image/settings/acwing_logo.jpg">
<br>
<div>
AcWing一键登录
</div>
</div>
</div>
</div>
`);
this.$login = this.$settings.find(".hyld-settings-login");
this.$login_username = this.$login.find(".hyld-settings-username input");
this.$login_password = this.$login.find(".hyld-settings-password input");
this.$login_submit = this.$login.find(".hyld-settings-submit button");
this.$login_error_message = this.$login.find(".hyld-settings-error-message");
this.$login_register = this.$login.find(".hyld-settings-option");
this.$login.hide();
this.$register = this.$settings.find(".hyld-settings-register");
this.$register_username = this.$register.find(".hyld-settings-username input");
this.$register_password = this.$register.find(".hyld-settings-password-first input");
this.$register_password_confirm = this.$register.find(".hyld-settings-password-second input");
this.$register_submit = this.$register.find(".hyld-settings-submit button");
this.$register_error_message = this.$register.find(".hyld-settings-error-message");
this.$register_login = this.$register.find(".hyld-settings-option");
this.$register.hide();
this.root.$hyld.append(this.$settings);
this.start();
}
start() {
this.getinfo();
this.add_listening_events();
}
add_listening_events() {
this.add_listening_events_login();
this.add_listening_events_register();
}
add_listening_events_login() {
let outer = this;
this.$login_register.click(function() {
outer.register();
});
this.$login_submit.click(function() {
outer.login_on_remote();
});
}
add_listening_events_register() {
let outer = this;
this.$register_login.click(function() {
outer.login();
});
this.$register_submit.click(function() {
outer.register_on_remote();
});
}
login_on_remote() { // 在远程服务器上登录
let outer = this;
let username = this.$login_username.val();
let password = this.$login_password.val();
this.$login_error_message.empty();
$.ajax({
url: "https://app820.acapp.acwing.com.cn/settings/login/",
type: "GET",
data: {
username: username,
password: password,
},
success: function(resp) {
console.log(resp);
if (resp.result === "success") {
location.reload();
} else {
outer.$login_error_message.html(resp.result);
}
}
});
}
register_on_remote() { // 在远程服务器上注册
let outer = this;
let username = this.$register_username.val();
let password = this.$register_password.val();
let password_confirm = this.$register_password_confirm.val();
this.$register_error_message.empty();
$.ajax({
url: "https://app820.acapp.acwing.com.cn/settings/register/",
type: "GET",
data: {
username: username,
password: password,
password_confirm: password_confirm,
},
success: function(resp) {
console.log(resp);
if (resp.result === "success") {
location.reload(); // 刷新页面
} else {
outer.$register_error_message.html(resp.result);
}
}
});
}
logout_on_remote() { // 在远程服务器上登出
if (this.platform === "ACAPP") return false;
$.ajax({
url: "https://app820.acapp.acwing.com.cn/settings/logout/",
type: "GET",
success: function(resp) {
console.log(resp);
if (resp.result === "success") {
location.reload();
}
}
});
}
register() { // 打开注册界面
this.$login.hide();
this.$register.show();
}
login() { // 打开登录界面
this.$register.hide();
this.$login.show();
}
getinfo() {
let outer = this;
$.ajax({
url: "https://app820.acapp.acwing.com.cn/settings/getinfo/",
type: "GET",
data: {
platform: outer.platform,
},
success: function(resp) {
if (resp.result === "success") {
outer.username = resp.username;
outer.photo = resp.photo;
outer.hide();
outer.root.menu.show();
} else {
outer.login();
}
}
});
}
hide() {
this.$settings.hide();
}
show() {
this.$settings.show();
}
}
在 game/static/css/game.css
中:
.hyld-menu {
width: 100%;
height: 100%;
background-image: url("/static/image/menu/background.gif");
background-size: 100% 100%;
user-select: none;
}
.hyld-menu-field {
width: 20vw;
position: relative;
top: 40%;
left: 20%;
}
.hyld-playground {
width: 100%;
height: 100%;
user-select: none;
}
.hyld-menu-field-item{
color:white; /*字体颜色*/
height:6vh; /*字体高度*/
width:18vw; /*字体的宽度*/
font-size:4vh; /*字体大小*/
font-style:italic; /*设置为斜体,默认是正体*/
/* padding:2vh; 字体矩形中字体边框和字体中间间隔的大小*/
text-align:center; /*设置居中,默认左对齐*/
background-color:rgba(39,21,28,0.6); /*设置背景颜色*/
border-radius:10px; //字体角圆弧半径*/
letter-spacing:0.5vw; /*两个字之间的宽度*/
cursor:pointer; /*控制我们鼠标落在字体上的样式,pointer是指小手的样式*/
}
.hyld-menu-field-item:hover {
transform: scale(1.2);
transition: 100ms;
}
.hyld-settings {
width: 100%;
height: 100%;
background-image: url("/static/image/menu/background.gif");
background-size: 100% 100%;
user-select: none;
}
.hyld-settings-login {
height: 41vh;
width: 20vw;
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(0, 0, 0, 0.7);
border-radius: 5px;
}
.hyld-settings-title {
color: white;
font-size: 3vh;
text-align: center;
padding-top: 2vh;
margin-bottom: 2vh;
}
.hyld-settings-username {
display: block;
height: 7vh;
}
.hyld-settings-password {
display: block;
height: 7vh;
}
.hyld-settings-submit {
display: block;
height: 7vh;
}
.hyld-settings-acwing {
display: block;
height: 7vh;
}
.hyld-settings-item {
width: 100%;
height: 100%;
}
.hyld-settings-item > input {
width: 90%;
line-height: 3vh;
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.hyld-settings-item > button {
color: white;
width: 90%;
line-height: 3vh;
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #4CAF50;
border-radius: 5px;
}
.hyld-settings-error-message {
color: red;
font-size: 0.8vh;
display: inline;
float: left;
padding-left: 1vw;
}
.hyld-settings-option {
color: white;
font-size: 2vh;
display: inline;
float: right;
padding-right: 1vw;
cursor: pointer;
}
.hyld-settings-acwing > img {
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
cursor: pointer;
display: block;
}
.hyld-settings-acwing > div {
color: white;
font-size: 1.5vh;
text-align: center;
display: block;
}
.hyld-settings-register {
height: 49vh;
width: 20vw;
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(0, 0, 0, 0.7);
border-radius: 5px;
}
canvas
用图片填充圆形
game/static/js/src/playground/player/zbase.js
中修改
this.img = new Image();
this.img.src = "图片地址";
this.ctx.save();
this.ctx.beginPath();
this.ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
this.ctx.stroke();
this.ctx.clip();
this.ctx.drawImage(this.img, this.x - this.radius, this.y - this.radius, this.radius * 2, this.radius * 2);
this.ctx.restore();
其他代码修改的改动较少,在gitee
上commit
查看即可