鱼C论坛

 找回密码
 立即注册
查看: 4301|回复: 21

[已解决]关于飞机大战中敌方飞机初始化位置的疑问

[复制链接]
发表于 2022-10-15 11:14:44 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
代码如下:


self.left, self.top = randint(0, self.width - self.rect.width), randit(-5 * self.height, 0)

------------------------------------------
Windows 10 专业版 | Python 3.7.6
------------------------------------------

【我的问题】我的疑问是:

1、横坐标为何是(0, self.width - self.rect.width)区间范围内随机取值,而不是(0, self.width)?

2、纵坐标取值范围区间(-5 * self.height, 0)其中的-5 * self.height是什么意思没看懂

******************************

感谢大神不吝赐教,为新手解疑释惑。

赠人玫瑰,手有余香,好人一生平安!
最佳答案
2022-10-15 22:26:50
lzb1001 发表于 2022-10-15 21:15
那为什么:

横坐标是(0, self.width - self.rect.width)而不是(0, self.width)?

注意这张图片,白色区域表示整个游戏窗口,所有在此区域内的图像都是玩家可见的,外面灰色区域都是不可见的。
红色矩形标识敌机的外边框,如果敌机的位置恰好是(self.width, 0),由于锚点在红色矩形框的左上角,所以敌机恰好出现在不可见区域,即使生成了敌机玩家也看不到,这样做就没意义了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-10-15 19:11:38 | 显示全部楼层
横坐标随机取值就是为了模拟敌机可以在背景顶端随机位置出现,只出现在一个位置,那这个不用玩也可以活下去

randit(-5 * self.height, 0)就是在背景外生成敌机的高度,这样保证敌机不会一下全部出现在屏幕上。

两个意思连在一起就是,会在背景顶端生成一个长方形区域,面积为 -5 * self.height*self.rect.width
敌机就是随机出现在这块区域
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-15 21:15:53 | 显示全部楼层
小伤口 发表于 2022-10-15 19:11
横坐标随机取值就是为了模拟敌机可以在背景顶端随机位置出现,只出现在一个位置,那这个不用玩也可以活下去 ...

那为什么:

横坐标是(0, self.width - self.rect.width)而不是(0, self.width)?

纵坐标取值范围区间(-5 * self.height, 0)为什么不是其他数字比如(5 * self.height, 0)或(-10 * self.height, 0)?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-15 22:20:40 | 显示全部楼层
lzb1001 发表于 2022-10-15 21:15
那为什么:

横坐标是(0, self.width - self.rect.width)而不是(0, self.width)?

从语法上来说横坐标写成(0, self.width)肯定是没问题的,但是从逻辑上来说就有潜在的问题了。

因为任意一个飞机对象默认都是以矩形左上角为锚点定位的,假设设置计算随机位置的时候横坐标恰好取值等于self.width,那就意味着这架飞机刚好出现在游戏窗口最右边,此时飞机对象的左边缘游戏窗口的右边缘对齐,如此一来飞机确实生成了,但是游戏窗口内完全看不到它。self.rect.width指的是飞机自身的宽度,那么(0, self.width - self.rect.width)就使得飞机的随机横坐标无论如何都是可见的,重点在于这架飞机在游戏窗口内是可见的。

第二个问题和前一个问题有联系,游戏窗口的坐标体系中左上角的坐标是原点(0, 0),横坐标向右为正,向左为负;纵坐标向下为正,向上为负。所以纵坐标的取值范围(-5*self.height, 0)的意思就是在游戏窗口上方不可见区域生成敌机,然后敌机逐步向下飞行。设置成(-10*self.height, 0)也可以,不过敌机出现的时机就会延后,因为飞机需要飞行更长时间才会出现在游戏窗口的可见区域中。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-15 22:24:44 | 显示全部楼层
lzb1001 发表于 2022-10-15 21:15
那为什么:

横坐标是(0, self.width - self.rect.width)而不是(0, self.width)?

1 飞机自身是有宽度所以位置至少要保证距离背景最右边要有一个飞机的宽度,不然有可能
飞机有部分会在墙里

2背景左上角坐标(0,0)y轴向下,x轴向右 所以如果你用(-10 * self.height, 0)是可以的,只不过敌机到达屏幕会需要一段时间,但是你(5 * self.height, 0)那敌机就会直接在背景上半部分生成,那也不算飞机大战了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-15 22:26:50 | 显示全部楼层    本楼为最佳答案   
lzb1001 发表于 2022-10-15 21:15
那为什么:

横坐标是(0, self.width - self.rect.width)而不是(0, self.width)?

注意这张图片,白色区域表示整个游戏窗口,所有在此区域内的图像都是玩家可见的,外面灰色区域都是不可见的。
红色矩形标识敌机的外边框,如果敌机的位置恰好是(self.width, 0),由于锚点在红色矩形框的左上角,所以敌机恰好出现在不可见区域,即使生成了敌机玩家也看不到,这样做就没意义了
Snipaste_2022-10-15_22-23-11.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-15 23:16:18 | 显示全部楼层
谢谢两位大神上面的解答,那么对于如下这句代码:

self.rect.left, self.rect.top = (self.width - self.rect.width) // 2, self.height - self.rect.height - 60

1、希望飞机在游戏框内横坐标轴中间的位置,不存在左右边框的问题,为何不用self.width // 2,而用(self.width - self.rect.width) // 2?
2、可否根据以上代码看出或画出飞机在游戏框内的大致位置?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-16 08:40:05 | 显示全部楼层
lzb1001 发表于 2022-10-15 23:16
谢谢两位大神上面的解答,那么对于如下这句代码:

self.rect.left, self.rect.top = (self.width - self ...

看来你还是没有理解锚点,希望下面的图片能帮助你理解坐标系统以及锚点

锚点

锚点

坐标计算

坐标计算
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-16 11:40:25 | 显示全部楼层
Brick_Porter 发表于 2022-10-16 08:40
看来你还是没有理解锚点,希望下面的图片能帮助你理解坐标系统以及锚点

谢谢大神的图,

rect.left、rect.top是分别指的是飞机左上角那个点的横、纵坐标,对吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-16 12:02:44 | 显示全部楼层
lzb1001 发表于 2022-10-16 11:40
谢谢大神的图,

rect.left、rect.top是分别指的是飞机左上角那个点的横、纵坐标,对吗?

是的,self.rect.left表示敌机左边缘,它的值就是左上角那个点的横坐标;self.rect.top标识敌机上边缘,它的值就是左上角那个点的纵坐标。

我再补充一点,不论是游戏窗口还是显示在窗口中的一个一个Surface对象,它们都有自己的坐标系统,这个系统的原点都在左上角,这是我们修改不了的。
除了原点之外还有一个锚点,当需要判断或者计算与其他Surface对象的位置关系时就要用到锚点了,它是判定的基准。它默认和原点重合,但是我们可以修改锚点,让它处在其他位置
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-16 12:31:44 | 显示全部楼层
Brick_Porter 发表于 2022-10-16 12:02
是的,self.rect.left表示敌机左边缘,它的值就是左上角那个点的横坐标;self.rect.top标识敌机上边缘, ...

请大神帮忙看看以下的左边的图和右边的表是否正确……

微信截图_20221012163220.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-16 12:45:11 | 显示全部楼层
lzb1001 发表于 2022-10-16 12:31
请大神帮忙看看以下的左边的图和右边的表是否正确……


左边的图是正确的,但是右边的表有点问题。C点的纵坐标是rect.bottom = rect.top + rect.height = rect.y + rect.height,不等于rect.x,rect.x是横坐标,此处需要纵坐标
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-16 13:23:26 | 显示全部楼层
Brick_Porter 发表于 2022-10-16 12:45
左边的图是正确的,但是右边的表有点问题。C点的纵坐标是rect.bottom = rect.top + rect.height = rect ...

非常感谢大神的解答和指导
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-16 22:41:01 | 显示全部楼层
lzb1001 发表于 2022-10-16 13:23
非常感谢大神的解答和指导

可以给他设置最佳哦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-16 23:31:03 | 显示全部楼层
小伤口 发表于 2022-10-16 22:41
可以给他设置最佳哦

谢谢提醒,本应两位大神都应点“最佳”才是
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-16 23:45:45 | 显示全部楼层
lzb1001 发表于 2022-10-16 23:31
谢谢提醒,本应两位大神都应点“最佳”才是

共同学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-17 08:15:46 | 显示全部楼层
Brick_Porter 发表于 2022-10-16 08:40
看来你还是没有理解锚点,希望下面的图片能帮助你理解坐标系统以及锚点

083909wjt6n4nn2tnetnmd.png.thumb.jpg

横坐标self.rect.left = (self.width - self.rect.width) // 2

大神,从你画的上面这张图我还是没想通怎么得出上面这个公式
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-17 08:25:03 | 显示全部楼层
lzb1001 发表于 2022-10-17 08:15
横坐标self.rect.left = (self.width - self.rect.width) // 2

大神,从你画的上面这张图我还是没 ...

我们用代码对比一下,你稍等
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-17 08:59:10 | 显示全部楼层
lzb1001 发表于 2022-10-17 08:15
横坐标self.rect.left = (self.width - self.rect.width) // 2

大神,从你画的上面这张图我还是没 ...
import sys

import pygame


# 游戏窗口的宽度和高度
SCREEN_WIDTH = 300
SCREEN_HEIGHT = 400

# 矩形的宽度和高度
RECT_WIDTH = 50
RECT_HEIGHT = 80

# 设置颜色
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)

pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))


while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    # 设置游戏背景为白色
    screen.fill(WHITE)

    # 绘制第一个红色矩形,坐标为(SCREEN_WIDTH//2, 50)
    pygame.draw.rect(
        screen, RED,
        (SCREEN_WIDTH//2, 50, RECT_WIDTH, RECT_HEIGHT)  # 前两个数字表示位置,后两个表示大小
    )
    # 绘制第二个绿色矩形,坐标为((SCREEN_WIDTH-RECT_WIDTH)//2, 150)
    pygame.draw.rect(
        screen, GREEN,
        ((SCREEN_WIDTH-RECT_WIDTH)//2, 150, RECT_WIDTH, RECT_HEIGHT)  # 前两个数字表示位置,后两个表示大小
    )

    pygame.display.flip()
两个绘制在游戏窗口中的矩形它们的大小相同,只有颜色与位置不一样。运行程序你会发现绿色的矩形确实处于游戏窗口中间位置,而红色则不是。

原因在于,你在计算矩形的横坐标时把矩形看作了一个点。如果绘制一个点,那么用self.width//2确实就是横坐标的值,但别忘了我们绘制的是矩形,矩形自身是有宽度的。不考虑宽度就会导致最终矩形偏右而不是在正中间。

(self.width - self.rect.width) // 2意思就是先用游戏窗口的宽度减去矩形的宽度,这个差值就是矩形距离游戏窗口边缘的总边距,然后把总边距除以2,得到的就是左右两边的边距。继而我们可以得到这样的表达式:游戏窗口宽度 = 左边距 + 矩形宽度 + 右边距。由于左右边距相等,所以矩形就居中显示了。现在可以理解了吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-17 11:08:03 | 显示全部楼层
Brick_Porter 发表于 2022-10-17 08:59
两个绘制在游戏窗口中的矩形它们的大小相同,只有颜色与位置不一样。运行程序你会发现绿色的矩形确实处 ...

(self.width - self.rect.width) // 2意思就是先用游戏窗口的宽度减去矩形的宽度,这个差值就是矩形距离游戏窗口边缘的总边距,然后把总边距除以2


代码我能看懂,就是不理解为什么这样计算的结果就是横坐标的中点
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-26 01:26

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表