《Python多人游戏项目实战》第三节 在窗口上显示玩家ID以及对话内容

news2025/2/28 17:56:39

目录

3.1 显示不同的人物图片

3.2 显示玩家ID

3.3 显示玩家对话内容

3.4 完整代码下载地址


本节只是在上一节内容的基础上加一些小功能:显示不同的人物图片、在人物头顶上显示玩家ID以及人物头顶上显示一个聊天对话框。大家可以把这一节内容当做一个过渡,用来巩固下多人游戏程序中pickle的用法。程序完成后的运行结果如下:

本项目结构显示如下:

├── SimHei.ttf                # 字体文件

├── client.py                  # 客户端代码

├── pics                        # 图片文件夹

│   ├── 1.png

│   ├── 2.png

│   ├── 3.png

│   ├── 4.png

│   ├── 5.png

│   └── 6.png

├── player.py                # 包含Player类

└── server.py                # 服务端代码

在client.py中我们一共导入了以下模块或库:

import sys
import pygame
import pickle
import socket
from player import Player
from random import randint

在player.py中我们一共导入了以下模块或库:

import pygame
import random

在server.py中我们一共导入了以下模块或库:

import socket
import pickle
from player import Player
from threading import Thread

3.1 显示不同的人物图片

pics文件夹下有6个人物方位图,玩家打开游戏窗口时,程序都会从这6个方位图中随机选择一张进行显示。因为是随机的,所以其他玩家的人物图片可能跟当前玩家的一样,也可能不一样。

首先修改Player类:

# player.py
class Player:
    def __init__(self, p_id, x, y,  pic_num, frame_width, frame_height):
        self.id = p_id
        self.dis = 3
        self.x = x
        self.y = y

        self.pic_num = pic_num      # 1
        self.frame_width = frame_width
        self.frame_height = frame_height
        self.frame_num = 0
        self.frame_rect = (self.frame_num * self.frame_width, 0 * self.frame_height,
                           self.frame_width, self.frame_height)

        self.current_dir = "下"
        self.last_dir = self.current_dir
    
    ...

代码解释如下:

1. 在初始化函数中加一个pic_num变量用来保存玩家显示的人物图片编号,这样就能从服务端传送过来的数据中知道某个玩家用的什么人物图了。

接着修改GameWindow类:

# client.py
class GameWindow:
    def __init__(self):
        ...

        self.pic_dict = {                                   # 1
            1: pygame.image.load("./pics/1.png"),
            2: pygame.image.load("./pics/2.png"),
            3: pygame.image.load("./pics/3.png"),
            4: pygame.image.load("./pics/4.png"),
            5: pygame.image.load("./pics/5.png"),
            6: pygame.image.load("./pics/6.png")
        }
        frame_width = self.pic_dict[1].get_width() // 4     # 2
        frame_height = self.pic_dict[1].get_height() // 4

        self.player = Player(p_id=None,
                             x=randint(0, self.width-frame_width),
                             y=randint(0, self.height-frame_height),
                             pic_num=randint(1, 6),         # 3
                             frame_width=frame_width,
                             frame_height=frame_height)

        ...

    ...

    def update_window(self):
        self.window.fill((255, 255, 255))

        self.player.move()
        self.player.draw(self.window, self.pic_dict[self.player.pic_num])   # 4

        other_players_data = pickle.loads(self.send_player_data())
        self.update_other_players_data(other_players_data)

        pygame.display.update()

    def update_other_players_data(self, data):
        for player in data.values():
            player.draw(self.window, self.pic_dict[player.pic_num])         # 5

    ...

代码解释如下:

1. 创建一个pic_dict字典变量,用来保存各个人物方位图对象,字典的键就是图片编号。

2. 因为所有人物方位图的大小都是一样的,所以这里就直接通过第一张方位图获取帧的宽高值。

3. 随机获取1-6之间的整数,这样就可以随机选择一张人物方位图了。

4. & 5. 根据pic_num值从pic_dict字典中选择对应的人物方位图,然后绘制到窗口上。

运行结果如下:

3.2 显示玩家ID

很多游戏会把玩家的id或名称显示在人物图片上方,并跟随人物移动,如下图所示。

这点其实很好实现,因为我们已经将玩家id值保存在Player对象的id属性中,所以只需要将这个id值绘制到窗口上就可以了。

将Player类的draw()函数修改如下:

# player.py
def draw(self, win, pic):
    win.blit(pic, (self.x, self.y), self.frame_rect)

    font = pygame.font.SysFont("Arial", 10)          # 1
    id_text = font.render(self.id, True, (150, 150, 150))
    win.blit(id_text, (self.x + round(self.frame_width/2) - round(id_text.get_width()/2), self.y - id_text.get_height()))

代码解释如下:

1. 设置文字字体并将文本绘制到人物图片的正上方。

运行结果如下:

3.3 显示玩家对话内容

如果要聊天的话,玩家就会在文本输入框中输入消息,然后按下回车键发送,其他玩家随后也会收到该玩家发送的消息。Pygame没有提供一个文本输入框控件,如果要自己实现的话会增加很多跟本教程主题无关的代码。所以为了保持代码简洁,笔者就预先设置好一些聊天内容,然后随机发送一条。

修改Player类:

# player.py
class Player:
    def __init__(self, p_id, x, y,  pic_num, frame_width, frame_height):
        ...

        self.message = ""           # 1

    ...

    def speak(self):                # 2
        messages_list = ["你好", "最近咋样", "我在打怪呢", "你说的有道理", "你哪里人", "不玩了,去吃饭了", "待会再玩", "今天很开心"]
        self.message = random.choice(messages_list)

代码解释如下: 

1. message变量用来存储玩家要发送消息。

2. speak()函数会随机生成一条聊天消息,并保存在message变量中。

修改GameWindow类:

# client.py
class GameWindow:
    def __init__(self):
        ...

        self.all_players_messages = []      # 1
        self.max_messages_shown = 6         # 2

        self.port = 5000
        self.host = "127.0.0.1"
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        self.connect()

    ...

    def send_player_data(self):
        data = {
            "id": self.player.id,
            "player": self.player
        }
        self.sock.send(pickle.dumps(data))
        self.player.message = ""            # 3
        return self.sock.recv(2048)

    def update_window(self):
        self.window.fill((255, 255, 255))

        self.player.move()
        self.player.draw(self.window, self.pic_dict[self.player.pic_num])
        if randint(0, 1000) < 50:           # 4
            self.player.speak()
        self.update_messages(self.player)   # 5

        other_players_data = pickle.loads(self.send_player_data())
        self.update_other_players_data(other_players_data)

        pygame.display.update()

    def update_other_players_data(self, data):
        for player in data.values():
            player.draw(self.window, self.pic_dict[player.pic_num])
            self.update_messages(player)    # 6

    def update_messages(self, player):
        if player.message:
            self.all_players_messages.insert(0, f"{player.id}: {player.message}")
            if len(self.all_players_messages) > self.max_messages_shown:
                self.all_players_messages.pop()

        font_size = 12
        font = pygame.font.Font("SimHei.ttf", font_size)
        for i, msg in enumerate(self.all_players_messages):
            msg_text = font.render(msg, True, (150, 150, 150))
            self.window.blit(msg_text, (0, self.height-(font_size*(i+1))))

代码解释如下:

1. 所有玩家的消息都会存储在all_players_messages列表变量中。

2. max_messages_shown变量用来控制在窗口上显示的聊天消息数。

3. 当前玩家的数据被发送到服务器后,就要清空Player对象的message属性,否则其他玩家会重复收到一条不变的消息。

4. 使用随机数来模拟玩家聊天。

5. update_messages()函数是重点,在该函数中,我们首先判断玩家数据中的message变量是否有值,有的话说明有发送消息,那就将这个值插到all_players_messages列表开头。如果消息总数大于max_messages_shown变量的值,那就把列表中最后一条聊天消息删除掉,不再显示。最后将所有聊天内容都显示到窗口左下角。为了解决Pygame中文显示的问题,笔者这里使用了另外的SimHei.ttf字体,已放入到项目文件夹中。

6. 接收到其他玩家的数据后,要记得调用update_messages()函数更新聊天内容。

运行结果如下:

3.4 完整代码下载地址

链接:https://pan.baidu.com/s/1chQ5c94X07Oi3Iv_eX3xDg  

密码:9qbz

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/94414.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【OpenCV-Python】教程:6-2 Pose Estimation (姿态估计)

OpenCV Python Pose Estimation (姿态估计) 【目标】 利用calib3d模块在图像中创建一些3D效果。 【理论】 这是一小部分。在上一节中&#xff0c;已经找到了摄像机矩阵&#xff0c;失真系数等。给定一个图案图像&#xff0c;我们可以利用上面的信息来计算它的姿态&#xff…

【云原生进阶之容器】第一章Docker核心技术1.5.2节——cgroups原理剖析

2 cgroups原理解析 上面是说的cgroups 是内核提供的功能,但现在我们在用户空间想使用的是cgroup的功能。其原理是:linux 内核有一个很强大的模块叫做VFS(vritual File System),VFS 把具体的文件系统的细节隐藏起来,给用户态进程提供一个完备的文件系统API接口。linux 也是通…

昆仑万维重磅发布AIGC全系列算法与模型,领跑未来

2022年12月15日&#xff0c;昆仑万维在北京举行AIGC技术发布会&#xff0c;会上昆仑万维CEO方汉正式发布了「昆仑天工」AIGC全系列算法与模型&#xff0c;并宣布模型开源。「昆仑天工」旗下模型包括天工巧绘SkyPaint、天工乐府SkyMusic、天工妙笔SkyText、天工智码SkyCode&…

[附源码]Python计算机毕业设计高校学科竞赛报名系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

四、移动手机自动化测试

移动手机自动化测试4.1 Appium 介绍4.1.1 Appium 中的常用术语1. Session2. Desired Capabilities3. Appium Server4.1.2 Appium 服务关键字Appium 服务相关参数的说明4.1 Appium 介绍 Appium 是一个开源、跨平台的自动化测试工具&#xff0c;可以用来测试 Native 及混合的移动…

Web3中文|Reddit用户在Polygon上铸造了超500万个NFT

Reddit用户通过Collectible Avatars 计划&#xff0c;已经铸造了超过 500 万个NFT。 Reddit的NFT头像是在以太坊扩展网络Polygon上铸造的&#xff0c;大多数都是免费赠送给Reddit用户。 在NFT销量下滑和加密货币市场动荡的情况下&#xff0c;Reddit对NFT头像的推动是一个罕见…

Spring 之类元数据封装—MetadataReader

在 Spring 中最喜欢干的事情就是将多个参数封装到一个对象&#xff0c;这里就挑选一个例子讲讲——MetadataReader&#xff0c;这个对象是将一个类封装成了三部分&#xff1a;File 文件本身&#xff0c;类元数据&#xff0c;注解元数据。 MetadataReader 元数据对象 先看下这…

架构设计(四):CDN

架构设计&#xff08;四&#xff09;&#xff1a;CDN 作者&#xff1a;Grey 原文地址&#xff1a; 博客园&#xff1a;架构设计&#xff08;四&#xff09;&#xff1a;CDN CSDN&#xff1a;架构设计&#xff08;四&#xff09;&#xff1a;CDN CDN 全称 Content delivery…

Redis面试准备

1. redis网站 Redis Redis文档中心 -- Redis中国用户组&#xff08;CRUG&#xff09; 数据库排名网站&#xff1a;DB-Engines - Knowledge Base of Relational and NoSQL Database Management Systems 2. 基础知识 磁盘中的寻址速度是毫秒级&#xff0c;内存中寻址速度是纳…

[ vulhub漏洞复现篇 ] struts2远程代码执行漏洞s2-048(CVE-2017-9791)

一、漏洞编号 s2-048 CVE-2017-9791二、影响范围 Apache Struts 2.3.x系列中启用了struts2-struts1-plugin插件的版本三、漏洞描述 Apache Struts2 2.3.x 系列启用了struts2-struts1-plugin 插件并且存在 struts2-showcase 目录,其漏洞成因是当ActionMessage接收客户可控的参…

【论文精读】Focal Inverse Distance Transform Maps for Crowd Localization

文章目录摘要主要贡献主要内容一、FIDT二、LMDS三。I-SSIM loss摘要 在本文中&#xff0c;我们关注人群定位任务&#xff0c;这是人群分析的一个重要课题。基于回归的方法大多使用卷积神经网络( CNN )对密度图进行回归&#xff0c;在极度稠密的场景中无法准确定位实例&#xf…

跨境卖家如何以最少量的预算建立品牌知名度?

关键词&#xff1a;跨境卖家、品牌知名度 什么是品牌知名度&#xff1f; 品牌知名度反映了您的目标受众对您的品牌的了解、认可和记忆程度。 为什么品牌知名度至关重要&#xff1f; 当您的目标受众需要您提供的产品或服务时&#xff0c;您希望他们考虑您的品牌。为此&#xf…

windows下nginx隐藏HTTP 请求头文件中的Server信息

简介 本文主要是隐藏HTTP 请求头文件中的Server信息 解决问题主要分下面几步 一、准备编译所需要的环境 二、修改nginx源码改变配置 三、编译nginx源码生成新的nginx.exe 四、替换nginx.exe&#xff0c;重新启动nginx 1. 准备所需环境 环境都需要准备好&#xff0c;因为编译是…

精品spring boot+MySQL线上点餐系统vue

《spring bootMySQL线上点餐系统》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 使用技术&#xff1a; 操作系统&#xff1a;Windows 10、Windows 7、Windows 8 开发语言&#xff1a;Java 使用框架&#xff1a;spring boot 前端技术&#xff…

大数据毕业设计人体跌倒检测系统

文章目录前言1 实现方法传统机器视觉算法基于机器学习的跌倒检测SVM简介SVM跌倒检测原理算法流程算法效果实现代码深度学习跌倒检测最终效果网络原理最后前言 背景和意义 在美国&#xff0c;每年在65岁以上老人中&#xff0c;平均每3人中就有1人发生意外跌倒&#xff0c;每年…

[附源码]Node.js计算机毕业设计关于人脸识别的实验教学管理系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

嵌入式分享合集122

一、分析电容降压电路工作原理 电容降压电路&#xff0c;因其成本低廉、体积小而被广泛地使用&#xff0c;此一优点足以掩盖其它所有缺点&#xff1a;输出电流小&#xff08;一般控制在100mA以内&#xff09;&#xff0c;与市电直通非隔离而存在安全隐患&#xff0c;输出电压波…

饥荒服务器搭建(windows)

文章目录1. 获取服务器票据2. 新建游戏存档3. 饥荒服务器配置1. 获取服务器票据 步骤1&#xff1a;登录Klei官网 步骤2&#xff1a;点击菜单栏游戏——选择饥荒服务器 步骤3&#xff1a;创建服务器获取票据&#xff0c;后面将会用到。 2. 新建游戏存档 步骤1&#xff1a;下载…

Python开发游戏?也太好用了吧

程序员宝藏库&#xff1a;https://gitee.com/sharetech_lee/CS-Books-Store 当然可以啦&#xff01; 现在日常能够用到和想到的场景&#xff0c;绝大多数都可以用Python实现。 效果怎么样暂且不提&#xff0c;但是得益于丰富的第三方工具包&#xff0c;的确让Python能够很容易…

二进制包安装公有云版k8s

目录公有云版k8s的架构是怎样的公有云中创建k8s实例的过程如下二进制法创建k8s的一般过程Kubernetes的重要性check nodes每台服务器执行基线配置CA rootetcd HA cluster根据CA根证书创建etcd的专有CA证书将etcd注册成为systemd服务配置各master节点的etcd.confansible配置各个m…