鱼C论坛

 找回密码
 立即注册
查看: 2931|回复: 12

小球摩擦碰撞

[复制链接]
发表于 2022-8-8 16:08:48 | 显示全部楼层
本帖最后由 鱼cpython学习者 于 2022-8-8 16:12 编辑
  1. if each.control:
复制代码

判断的确实是小球是否受控,但你看这个判断,它是被包在碰撞判断里的。
也就是说,当小球碰撞的时候,会检测该小球是否受控,受控的话就让其失控
  1. each.side[0] = -1
  2. each.side[1] = -1
复制代码

这两句我的看法是这样的:
在游戏刚开始时,所有的speed都为正数,负数的只有side
而到了后期,玩家控制过一些小球,就会出现速度为负数的情况,因为有
  1.                 if event.key == K_w:  #W,上
  2.                     for each in group:
  3.                         if each.control:
  4.                             each.speed[1] -= 1
  5.                         
  6.                 if event.key == K_a:  #a,左
  7.                     for each in group:
  8.                         if each.control:
  9.                             each.speed[0] -= 1
复制代码

那么就要把方向调成-1,相当于对速度取反,因为碰撞就会设置self.control = False
而在Ball.move方法中,self.control如果为False,那么就需要side参与计算,如果取反速度的话,还有side可能影响运动方向
我说的有点乱,举个例子
假设一个小球A速度为[5, 3], 方向为[1, -1],移动方向为向下,向左
过了一会它变成受控状态,此时Ball.move判断self.control为True,调用self.rect.move(self.speed),代表self.side不用参与运算
又过了一会,经过玩家的操控,A的速度为[-5, 3], 方向仍然为[1, -1],移动方向为向上,向右,因为此时不依靠side来指定移动方向了
此时,A和另一个小球B碰撞,B方向取反,往反方向移动。A失控,self.control变为False
那么此时A应该往反方向移动,即向下,向左移动,为[5, -3]
如果把A的速度取反,变为[5, -3],移动方向为向下,向左,似乎是正确的
但在Ball.move方法中,判断self.control为False,那么调用self.rect = self.rect.move((self.side[0] * self.speed[0], self.side[1] * self.speed[1]))
那么此时传给self.rect.move()的,则是(5 * 1, -3 * -1),即(5, 3),移动方向为向下,向右
这样就不是完全的反方向了。
而把A的方向设为[-1, -1],传给self.rect.move的,是(-5 * -1, 3 * -1),为[5, -3],刚好是我们想要的目标
我说的可能不太清楚,你可以琢磨一下,如果我的看法有错误请指出
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-8-10 19:26:31 | 显示全部楼层
lzb1001 发表于 2022-8-10 17:15
感谢大神分析和指点,

关于:

为什么肯定失控?碰撞有两种可能,一种是两个失控的小球碰撞,另一种是当玩家控制了一个小球并移动它时,不小心让这个被控制的小球和另一个失控的小球碰撞
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-8-11 10:50:02 | 显示全部楼层
lzb1001 发表于 2022-8-10 23:56
烦请大神看下下面的注释是否正确?

each.side[0] = -1 # X轴横向坐标向左?

从这个变量的字面意思来看确实是这样。当然你也可以写对速度取反,只要意思理解就行
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-8-11 11:58:12 | 显示全部楼层
本帖最后由 鱼cpython学习者 于 2022-8-11 12:02 编辑
lzb1001 发表于 2022-8-11 11:35
对速度取反?

1、side不是方向吗?如果方向取反,不是应该是each.side[0] = -each.side[0]吗?


好吧,是我表述有歧义了,先道个歉
1.side确实是方向,但这里不是方向取反。在这个判断里,小球会从受控状态变为不受控状态。而不受控状态的运动是用速率+方向描述的,这个你能理解对吧
而受控状态的运动是速度描述,这个速度是带方向的,即取值是有正负的,原来用于描述方向的side变量被弃用。
那么从受控改为不受控状态,小球运动的计算就会复用side变量。因为Ball.move方法定义了
  1. if self.control: #如果是玩家控制,就还是带方向的速度
  2.         self.rect = self.rect.move(self.speed)
  3. else:
  4.         self.rect = self.rect.move((self.side[0] * self.speed[0], \
  5.                                                     self.side[1] * self.speed[1])) #移动的速度就变为速度的大小乘以方向了
复制代码

而我们知道,小球受碰撞后要向反方向运动,在这个情景里,一个受控的小球和一个不受控的小球碰撞。不受控的小球很简单,对方向取反,因为不受控的小球是速率和方向严格分开描述的
而受控的小球就难了,因为受控后就用带方向的速度描述运动,而原来的用于描述方向的side变量被弃用了
现在这个受控的小球要变成不受控状态,还要朝反方向运动,还要考虑side变量的复用
那么最好的方法,就是把描述方向的side变量变成[-1, -1]
因为小球变成不受控状态了,运动的计算就变成
  1. self.rect = self.rect.move((self.side[0] * self.speed[0], self.side[1] * self.speed[1]))
复制代码
                                         
  1. self.rect = self.rect.move((-1 * self.speed[0], -1 * self.speed[1]))
复制代码
            
那么不就等于对self.speed取反了吗,而self.speed又是带方向的速度,那么效果就是小球往反方向运动了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-8-19 18:39:31 | 显示全部楼层
lzb1001 发表于 2022-8-18 23:00
@鱼cpython学习者

大神你好!以下你第一次解说的节选,其中标记为红色字体的内容是否有错?

好吧,实在抱歉实在抱歉,我每一个方向都写反了
第一个改成向右,向上
第二个改成向左,向下
第三个改成向右,向上
第四个同上
第五个是对的,向右,向下
实在抱歉,给你带来了麻烦
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-9-22 19:19

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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