当前位置: 首页 > news >正文

Pygame介绍与游戏开发

提供pygame功能介绍的文档:Pygame Front Page — pygame v2.6.0 documentation

基础语法和实现逻辑

与CLI不同,pygame提供了图形化使用界面GUI(graphical user interface)基于图像的界面可以创建一个有图像和颜色的窗口

要让pygame的众多函数可以被调用,首先要调用pygame.init()

然后我们要创建一个surface对象:pygame.display.set_mode((400, 300))

并用pygame.display.set_caption()设置窗口顶部的标题文本

game loop—游戏循环一直在做三件事:处理事件、更新游戏状态、在屏幕上绘制游戏状态

最常见的游戏循环状态就是事件处理(而循环由while True进行)

 while True:#main game loop
       for event in pygame.event.get():

quit函数是一种与init相反的函数,在调用sys.exit前总是先调用pygame.quit()

而进行这一语句的条件则是if event.type==QUIT:

在在for循环的事件和事件处理条件if结束,游戏状态开始更新,pygame.display.update()

它把pygame.display.set_ mode()所返回的Surface对象绘制到屏幕上。

由此,我们就可以创建一个最简单最无聊的屏幕游戏了

import pygame, sys
from pygame.locals import *# 初始化Pygame
pygame.init()# 设置窗口大小和标题
DISPLAYSURF = pygame.display.set_mode((400, 300))
pygame.display.set_caption('Hello World!')# 主游戏循环
while True:# 事件处理for event in pygame.event.get():if event.type == QUIT:pygame.quit()sys.exit()# 更新显示pygame.display.update()

坐标系和图形建立

不管是2D游戏还是3D游戏,我们都需要有空间界定来判断事件发生与否,而这也是所有游戏当中最常见的引发事件方法,为此,我们要建立合适的像素坐标

 这里我们选择使用一个笛卡尔坐标系统来表示一个特定的点:值得注意的是,这里的Y轴坐标从最顶部的0开始,然后向下增加,而不是向上增加,这也是在大多数编程语言当中笛卡尔坐标是最有效的

在有了基本的空间界定以后,我们需要对其进行上色和透明度处理,其中颜色由RGB来表示,为了表示透明度,我们在RGB后面再加上一个大小在0~255的元素其中255表示完全不透明,RGB(0,0,0)为黑色RGB(255,255,255)为白色,想要使用透明颜色进行绘制,就必须使用convert_alpha()方法来创建一个Surface对象

anotherSurface=DISPLAYSURF.convert_alpha()

除了用四个整数构造的元组以外,也可以调用pygame.Color()填入参数

 Rect对象是一种表示矩形区域的方法

 例如,上述代码所表示的是所表示对象左上角位于(10,20)宽度为200像素,高度为300像素

如果想要访问对象最右边的x坐标,就必须要输入spamRect.right,当你对原坐标作出修改,其他坐标会自动算出,相应做出修改

pygame.Rect 提供了丰富的属性,用于描述矩形的位置和尺寸,以下是其主要属性:
基本位置和尺寸属性
•  x:矩形左上角的 x 坐标。
•  y:矩形左上角的 y 坐标。
•  width:矩形的宽度。
•  height:矩形的高度。
•  size:矩形的尺寸,返回一个元组 (width, height)。
边界属性
•  left:矩形左边缘的 x 坐标。
•  right:矩形右边缘的 x 坐标。
•  top:矩形上边缘的 y 坐标。
•  bottom:矩形下边缘的 y 坐标。
中心和角点属性
•  center:矩形的中心点坐标,返回一个元组 (centerx, centery)。
•  centerx:矩形水平中心的 x 坐标。
•  centery:矩形垂直中心的 y 坐标。
•  topleft:矩形左上角的坐标。
•  bottomleft:矩形左下角的坐标。
•  topright:矩形右上角的坐标。
•  bottomright:矩形右下角的坐标。
•  midtop:矩形上边中点的坐标。
•  midleft:矩形左边中点的坐标。
•  midbottom:矩形下边中点的坐标。
•  midright:矩形右边中点的坐标。
简化属性
•  w:与 width 相同,表示矩形的宽度。
•  h:与 height 相同,表示矩形的高度。
这些属性不仅可以用于获取矩形的相关信息,还可以通过赋值来修改矩形的位置或尺寸。

pygame的基本绘制函数

import pygame, sys
from pygame.locals import *pygame.init()# set up the window
DISPLAYSURF = pygame.display.set_mode((500, 400), 0, 32)
pygame.display.set_caption('Drawing')# set up the colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)# draw on the surface object
DISPLAYSURF.fill(WHITE)
pygame.draw.polygon(DISPLAYSURF, GREEN, ((146, 0), (291, 106), (236, 277), (56, 277), (0, 106)))
pygame.draw.line(DISPLAYSURF, BLUE, (60, 60), (120, 60), 4)
pygame.draw.line(DISPLAYSURF, BLUE, (120, 60), (60, 120))
pygame.draw.line(DISPLAYSURF, BLUE, (60, 120), (120, 120), 4)
pygame.draw.circle(DISPLAYSURF, BLUE, (300, 50), 20, 0)
pygame.draw.ellipse(DISPLAYSURF, RED, (300, 250, 40, 80), 1)
pygame.draw.rect(DISPLAYSURF, RED, (200, 150, 100, 50))pixObj = pygame.PixelArray(DISPLAYSURF)
pixObj[480][380] = BLACK
pixObj[482][382] = BLACK
pixObj[484][384] = BLACK
pixObj[486][386] = BLACK
pixObj[488][388] = BLACK
del pixObj# run the game loop
while True:for event in pygame.event.get():if event.type == QUIT:pygame.quit()sys.exit()pygame.display.update()

 在编写代码时,我们往往会为每一种颜色设置常变量,这样会使代码更具有可读性,绘制函数则是根据他们的形状来命名,传递给这些函数的参数,则告诉他们它们在哪一个Surface对象上绘制,将形状绘制到何处

部分函数和方法介绍:

fill(color):会使传递给color参数到任何颜色来填充整个Surface对象

pygame.draw.polygon(surface,color,pointlist,width):多边形是由多个平坦的边组成的形状,surface和color参数告诉函数,将多边形绘制到哪一个surface上,以及用什么颜色绘制,其中:pointlist参数是一个元组或者点的列表(也就是说,用于XY 坐标的元组,或者两个整数的元组的列表)。多边形是通过这样的方式来绘制的,即在每个点以及元组中其后续的点之间绘制线条,然后,从最后的点到第一个点绘制一个线条。你也可以传递点的列表,而不是点的元组。
width参数是可选的。如果你漏掉了这个参数,多边形将会绘制为填充的,就像是屏幕上的绿色多边形那样,会用颜色来填充它。如果确实给width参数传递了一个整数值,则只是绘制出多边形的边框。这个整数表示多边形的边框会有多少个像素那么宽。给width参数传递1,将会绘制一个边框细瘦的多边形,而传递4、10或者20,将会绘制一个边框较粗一些的多边形。如果给width参数传入0,多边形将会是填充的(这和完全漏掉了width参数的效果一样)。

pygame.draw.line(surface, color, start_point, end_point, width) ——这个函数在start_point和end_point参数之间绘制一条直线。

pygame.draw.lines(surface, color, closed, pointlist, width) ——这个函数绘制了从一个点到下一个点的一系列的线条,这和pygame.draw.polygon()函数非常相似。唯一的区别在于如果你给closed参数传递了False,将不会有从pointlist中的最后一个点到第一个点的那条直线了。如果你传递了True,将会绘制从最后一个点到第一个点的直线。

pygame.draw.circle(surface, color, center_point, radius, width) ——该函数绘制一个圆。center_point参数指定了圆的圆心。传递给radius的参数为整数,表示的是圆的半径。

pygame.draw.ellipse(surface, color, bounding_rectangle, width) ——该函数绘制一个椭圆形。bounding_rectangle参数可以是一个pygame.Rect对象或者是4个整数的一个元组,就是表示出一个长方体的形状,由函数自动拟出椭圆。

pygame.draw.rect(surface, color, rectangle_tuple, width) ——该函数绘制一个矩形。

使用PixelArray()可以单个或批量设置像素的颜色,值得注意的是,PixelArray会将surface对象锁定,此时不能够使用blit()方法在其上绘制,诸如png,jpg这样的图像,如果想要查看一个对象是否被锁定了,可以使用get_locked()方法(锁定了会返回True),可以通过del语句删除PixelArray对象,以此outlocked

将图像连成动画需要通过多个图像来让人们的眼睛产生幻觉,通过提高帧率来让动画足够逼真

而pygame.time.Clock对象可以帮助我们确保程序以某一个最大的FPS运行。Clock对象将会在每一次迭代完成后都设置一个小小的暂停。调用一个Clock对象的tick方法,则能够确保无论计算机有多快,游戏都会按相同的速度运行。因此,这条代码应该放在循环的末尾。

 如果只是想要绘制简单的形状,绘制函数已经很好用了,但是实际上在制作游戏的过程中我们往往需要将PNG、JPG、GIF和BMP等文件格式的图像加载到我们的游戏当中——要加载图像,可以将图像名与后缀传递给pygame.image.load()函数,但是由此返回的surface对象和原来的surface对象并非用一个surface对象并非同一个surface对象,因此我们还需要用到位图复制(Blitting),可以将一个surface的内容复制到另一个surface上面,用的是blit()函数

import pygame, sys
from pygame.locals import *# 初始化Pygame
pygame.init()# 设置帧率
FPS = 30
fpsClock = pygame.time.Clock()# 设置窗口
DISPLAYSURF = pygame.display.set_mode((400, 300), 0, 32)
pygame.display.set_caption('Animation')# 定义颜色和图像
WHITE = (255, 255, 255)
catImg = pygame.image.load('cat.png')
catx = 10
caty = 10
direction = 'right'# 主游戏循环
while True:# 填充背景色DISPLAYSURF.fill(WHITE)# 根据方向移动猫if direction == 'right':catx += 5if catx == 280:direction = 'down'elif direction == 'down':caty += 5if caty == 220:direction = 'left'elif direction == 'left':catx -= 5if catx == 10:direction = 'up'elif direction == 'up':caty -= 5if caty == 10:direction = 'right'# 绘制猫图像DISPLAYSURF.blit(catImg, (catx, caty))# 事件处理for event in pygame.event.get():if event.type == QUIT:pygame.quit()sys.exit()# 更新显示并控制帧率pygame.display.update()fpsClock.tick(FPS)

除此之外,我们还会在编写游戏的过程当中用到文本:

想要把文本绘制到屏幕,一共有六步:
1.创建一个pygame.font.Font对象
2.创建一个Surface对象,通过调用Font对象的render()方法,将文本绘制其上
3.通过调用Surface对象的get_rect()方法,从Surface对象创建一个Rect对象
4.通过修改Rect对象的属性之一,来设置其位置。
5.将带有文本的Surface对象复制到pygame.display.set_mode()所返回的Surface对象上
6.调用pygame.display.update(),使显示Surface出现在屏幕上

import pygame, sys
from pygame.locals import *pygame.init()
DISPLAYSURF = pygame.display.set_mode((400, 300))
pygame.display.set_caption('Hello World!')WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
BLUE = (0, 0, 128)fontObj = pygame.font.Font('freesansbold.ttf', 32)
textSurfaceObj = fontObj.render('Hello world!', True, GREEN, BLUE)
textRectObj = textSurfaceObj.get_rect()
textRectObj.center = (200, 150)while True:  # main game loopDISPLAYSURF.fill(WHITE)DISPLAYSURF.blit(textSurfaceObj, textRectObj)for event in pygame.event.get():if event.type == QUIT:pygame.quit()sys.exit()pygame.display.update()

render方法中提供了抗锯齿的图形技术,通过给文本和图形的边缘进行模糊化处理,使其看上不不那么块状化,(给render的第二个参数传入True)

用户体验升级:声音和交互按钮

播放声音可以使用pygame.mixer.Sound()构造函数,以此创建pygame.mixer.Sound对象,要播放音乐时可以调用sound对象的play()方式,停止则使用stop()方式,值得注意的是,sound一次只能加载一个音乐文件,因此我们要加载一个背景声音文件,调用pygame.mixer.music.load()函数并且将要加载的声音文件作为一个字符串参数传递。该函数一共有两个参数第一个表示指定循环的次数,第二个参数表示从音频的多少秒处开始播放。

此外作为能实现交互的游戏我们需要对按钮进行制作Pygame本身并没有直接提供一个现成的Button类或按钮交互功能,但可以通过自定义实现按钮交互。以下是实现按钮交互的基本方法:
创建按钮
1.  定义按钮类:通常需要定义一个Button类,包含按钮的矩形区域(pygame.Rect)、颜色、文本等属性。
2.  绘制按钮:使用pygame.draw.rect()绘制按钮的矩形背景,并通过pygame.font渲染文本。
实现按钮交互
1.  监听鼠标事件:在主循环中,通过pygame.event.get()获取事件,检测鼠标点击事件(pygame.MOUSEBUTTONDOWN)。
2.  判断点击位置:使用pygame.Rect.collidepoint()方法判断鼠标点击位置是否在按钮矩形内。
3.  执行操作:如果点击位置在按钮内,则执行相应的操作,例如打印消息或调用函数。
示例代码
以下是一个简单的按钮实现示例:

import pygamepygame.init()
screen = pygame.display.set_mode((400, 300))
pygame.display.set_caption("Pygame Button Example")class Button:def __init__(self, rect, color, text, font):self.rect = rectself.color = colorself.text = textself.font = fontdef draw(self, surface):pygame.draw.rect(surface, self.color, self.rect)text_surface = self.font.render(self.text, True, (0, 0, 0))text_rect = text_surface.get_rect(center=self.rect.center)surface.blit(text_surface, text_rect)def handle_event(self, event):if event.type == pygame.MOUSEBUTTONDOWN and self.rect.collidepoint(event.pos):print("Button clicked!")button = Button(pygame.Rect(150, 125, 100, 50), (255, 0, 0), "Click Me", pygame.font.Font(None, 36))running = True
while running:for event in pygame.event.get():if event.type == pygame.QUIT:running = Falsebutton.handle_event(event)screen.fill((255, 255, 255))button.draw(screen)pygame.display.flip()pygame.quit()

此外,也有一些第三方库或项目封装了按钮功能,例如pygame-button-interface-switch,可以方便地集成到Pygame项目中。

相关文章:

Pygame介绍与游戏开发

提供pygame功能介绍的文档:Pygame Front Page — pygame v2.6.0 documentation 基础语法和实现逻辑 与CLI不同,pygame提供了图形化使用界面GUI(graphical user interface)基于图像的界面可以创建一个有图像和颜色的窗口 要让py…...

webpack配置方式

1. 基本配置文件 (webpack.config.js)(导出一个对象) 最常见的方式是通过 webpack.config.js 文件来配置 Webpack,导出一个对象。你可以在这个文件中导出一个配置对象,指定入口、输出、加载器、插件等。 // webpack.config.js m…...

10. k8s二进制集群之Kube Scheduler部署

在开始之前需要准备什么?创建kube-scheduler证书请求文件【即证书的生成⓵】根据上面证书配置文件生成kube-scheduler证书【即证书的生成⓶】创建与关联kube-scheduler配置文件(为后面生成系统服务做准备)创建kube-scheduler服务配置文件【准备系统服务⓵】创建kube-schedul…...

java实现8583报文解析技术详解

文章目录 概要整体架构流程技术名词解释技术细节小结概要 ISO 8583协议是金融交易系统中广泛使用的通信协议,用于规范报文的格式和数据交换。解析8583报文是实现金融交易系统的关键技术之一。本文将详细介绍8583报文解析的核心实现,重点关注解析算法和关键代码逻辑。 8583报…...

k8s服务发现有哪些方式?

在 Kubernetes 中,服务发现是指如何让应用程序在集群内互相找到并通信。Kubernetes 提供了多种服务发现的方式,适应不同的使用场景。以下是 Kubernetes 中常见的服务发现方式: 1. 环境变量(Environment Variables) 概…...

【SqlServer】SQL Server Management Studio (SSMS) 下载、安装、配置使用及卸载——保姆级教程

超详细的 SQL Server Management Studio (SSMS) 下载、安装、连接数据库配置及卸载教程 SQL Server Management Studio (SSMS) 是微软提供的图形化管理工具,主要用于连接、管理和开发 SQL Server 数据库。以下是详细的 SSMS 下载、安装、连接数据库以及卸载的完整教…...

[ESP32:Vscode+PlatformIO]添加第三方库 开源库 与Arduino导入第三方库的区别

前言 PlatformIO与Arduino在添加第三方库方面的原理存在显著差异 在PlatformIO中,第三方库的使用是基于项目(工程)的。具体而言,只有当你为一个特定的项目添加了某个第三方库后,该项目才能使用该库。这些第三方库的文…...

音频文件格式——AAC、OGG和FLAC

3.AAC文件格式 3.1 封装格式解析 高级音频编码 (Advanced Audio Coding) 是一种用于有损数字音频压缩的音频编码标准。它被设计为 MP3 格式的继承者,在相同比特率下通常可以获得比 MP3 更高的音质。AAC有两种封装格式: ADIF&am…...

BUU26 [极客大挑战 2019]HardSQL1

输入一些SQL关键词,发现空格,,union,and,by都被过滤了 被过滤,就用like替代 发现登录成功,可以注入 报错注入 注意 1.这里过滤了空格,就用()将内容包裹起来 比如说&#xff1a…...

多光谱成像技术在华为Mate70系列的应用

华为Mate70系列搭载了光谱技术的产物——红枫原色摄像头,这是一款150万像素的多光谱摄像头。 相较于普通摄像头,它具有以下优势: 色彩还原度高:色彩还原准确度提升约 120%,能捕捉更多光谱信息,使拍摄照片色…...

借助 Cursor 快速实现小程序前端开发

借助 Cursor 快速实现小程序前端开发 在当今快节奏的互联网时代,小程序因其便捷性、高效性以及无需下载安装的特点,成为众多企业和开发者关注的焦点。然而,小程序的开发往往需要耗费大量的时间和精力,尤其是在前端开发阶段。幸运…...

【deepseek】ollama chatbox webui 本地部署deepseek 踩坑记录

部署 1、前往Ollama官网下载跨平台工具 官网直达:https://ollama.com/download 2、挑选适合自己设备的模型版本,获取运行指令 访问模型库:https://ollama.com/library/deepseek-r1 ▌配置建议: • 入门级:1.5B版本&…...

在离线的服务器上部署Python的安装库

在离线服务器上部署 Python 安装库(如 SQLAlchemy、pandas、pyodbc 等),可以使用以下方法: 方法 1:在联网机器上下载依赖,拷贝到离线服务器 适用于:服务器完全无法访问互联网。 步骤 1. 在联网…...

计算机网络笔记再战——理解几个经典的协议2

理解互联网与TCP/IP 下面,我们将会开始理解互联网这个东西,进一步的,我们会理解何为TCP/IP 我们的互联网就是一个巨大的网状结构,需要注意的是——每一个网状的节点之间都是使用一个叫做NOC,Network Operation Center…...

设计高效的测试用例:从需求到验证

在现代软件开发过程中,测试用例的设计一直是质量保证(QA)环节的核心。有效的测试用例不仅能够帮助发现潜在缺陷,提升软件质量,还能降低后期修复成本,提高开发效率。尽管如此,如何从需求出发&…...

git reset 命令

git reset 的作用 git reset 是一个非常强大的命令,用于将当前分支的 HEAD(即当前指向的提交)重置到指定的提交。它还可以根据参数的不同,对工作区(Working Directory)和暂存区(Staging Area&a…...

docker被“遗忘”的那些参数该如何拯救

一、docker容器启动时没有指定端口,如何在不删除容器的情况下配置端口呢 在 Docker 中,如果容器启动时没有指定端口映射,可以通过以下步骤在不删除容器的情况下配置端口: 方法 1: 使用 docker commit 和 docker run 提交容器为新…...

BFS算法——广度优先搜索,探索未知的旅程(下)

文章目录 前言一. N叉树的层序遍历1.1 题目链接:https://leetcode.cn/problems/n-ary-tree-level-order-traversal/description/1.2 题目分析:1.3 思路讲解:1.4 代码实现: 二. 二叉树的锯齿形层序遍历2.1 题目链接:htt…...

Python分享20个Excel自动化脚本

在数据处理和分析的过程中,Excel文件是我们日常工作中常见的格式。通过Python,我们可以实现对Excel文件的各种自动化操作,提高工作效率。 本文将分享20个实用的Excel自动化脚本,以帮助新手小白更轻松地掌握这些技能。 1. Excel单…...

pytest+request+yaml+allure 接口自动化测试全解析[手动写的跟AI的对比]

我手动写的:Python3:pytest+request+yaml+allure接口自动化测试_request+pytest+yaml-CSDN博客 AI写的:pytest+request+yaml+allure 接口自动化测试全解析 在当今的软件开发流程中,接口自动化测试扮演着至关重要的角色。它不仅能够提高测试效率,确保接口的稳定性和正确性…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中&#xff0c;我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道&#xff0c;它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

tomcat入门

1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效&#xff0c;稳定&#xff0c;易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...