4、简易版web端荒野乱斗账户系统

源码地址https://gitee.com/pxlsdz/hyld

演示地址http://121.199.59.80/hyld/

小技巧:

  • 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云端应用、还是小程序或者什么,即多终端实现。

需要在在主jsHlydGame中添加参数,比如实现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();

其他代码修改的改动较少,在giteecommit查看即可

posted @ 2021-12-24 00:20  pxlsdz  阅读(152)  评论(0编辑  收藏  举报