如何在Python Kivy开发的2D头球游戏中实现碰撞处理?
头球游戏碰撞逻辑实现问题
我要给一款头球类型的游戏实现碰撞逻辑,已经定义了Ball类和Player类,希望通过物理模拟实现两者的流畅交互。之前尝试用向量计算力并应用到代码里,但一直没成功:水平方向碰撞时球和玩家的交互效果很差,而且球会陷入玩家的矩形碰撞体中。
以下是当前未包含碰撞逻辑的Python代码:
from kivy.app import App from kivy.uix.widget import Widget from kivy.properties import NumericProperty, ReferenceListProperty, ObjectProperty from kivy.vector import Vector from kivy.clock import Clock from kivy.core.window import Window class Ball(Widget): velocity_x = NumericProperty(0) velocity_y = NumericProperty(0) velocity = ReferenceListProperty(velocity_x, velocity_y) gravity = 0.2 bounce_factor = 0.7 mass = 1.0 max_velocity = 10 def move(self): self.velocity_y -= self.gravity self.pos = Vector(*self.velocity) + self.pos # 检测球是否落地 if self.y < 0: self.y = 0 self.velocity_y *= -self.bounce_factor # 避免落地后仍有向下的速度 if self.velocity_y < 0 and self.y == 0: self.velocity_y = 0 # 设置最大速度限制 if self.velocity_y > self.max_velocity: self.velocity_y = self.max_velocity if self.velocity_x > self.max_velocity: self.velocity_x = self.max_velocity class Player(Widget): velocity_x = NumericProperty(0) velocity_y = NumericProperty(0) velocity = ReferenceListProperty(velocity_x, velocity_y) jump_strength = 15 gravity = 0.5 speed = 10 mass = 2.0 def move(self): self.velocity_y -= self.gravity self.pos = Vector(*self.velocity) + self.pos # 确保玩家不会掉到屏幕下方 if self.y < 0: self.y = 0 class GameScreen(Widget): ball = ObjectProperty(None) player = ObjectProperty(None) def __init__(self, **kwargs): super(GameScreen, self).__init__(**kwargs) self._keyboard = Window.request_keyboard(self._keyboard_closed, self) self._keyboard.bind(on_key_down=self._on_keyboard_down, on_key_up=self._on_keyboard_up) def _keyboard_closed(self): self._keyboard.unbind(on_key_down=self._on_keyboard_down, on_key_up=self._on_keyboard_up) self._keyboard = None def _on_keyboard_down(self, keyboard, keycode, text, modifiers): if keycode[1] == 'd': self.player.velocity_x = self.player.speed elif keycode[1] == 'a': self.player.velocity_x = -self.player.speed elif keycode[1] == 'spacebar': self.player.velocity_y = self.player.jump_strength return True def _on_keyboard_up(self, keyboard, keycode): if keycode[1] == 'a' and self.player.velocity_x < 0: self.player.velocity_x = 0 elif keycode[1] == 'd' and self.player.velocity_x > 0: self.player.velocity_x = 0 return True def serve_ball(self): self.ball.center = self.center self.ball.velocity = Vector(0, -1) def update(self, dt): self.ball.move() self.player.move() # 球碰到上下边界反弹 if (self.ball.y < 0) or (self.ball.top > self.height): self.ball.velocity_y *= -1 # 球碰到左右边界反弹 if (self.ball.x < 0) or (self.ball.right > self.width): self.ball.velocity_x *= -1 # 玩家碰到顶部边界停止上升 if self.player.top >= self.height: self.player.velocity_y *= 0 self.player.y = self.height - self.player.height # 玩家碰到左边界停止左移 if self.player.x < 0: self.player.velocity_x *= 0 self.player.x = 0 # 玩家碰到右边界停止右移 if self.player.right > self.width: self.player.velocity_x *= 0 self.player.x = self.width - self.player.width class SoccerApp(App): def build(self): game = GameScreen() game.serve_ball() Clock.schedule_interval(game.update, 1.0 / 60.0) return game if __name__ == '__main__': SoccerApp().run()
对应的.kv文件代码:
<Ball>: size: 25, 25 canvas: Ellipse: pos: self.pos size: self.size <Player>: size: 50, 50 canvas: Rectangle: pos: self.pos size: self.size <GameScreen>: ball: game_ball player: game_player Label: font_size: 70 center_x: root.width / 2 - 30 top: root.top - 50 text: "0" Label: font_size: 70 center_x: root.width * 2 / 4 + 30 top: root.top - 50 text: "0" Ball: id: game_ball center: self.parent.center Player: id: game_player center_x: root.width * 1 / 4 center_y: root.height * 1/6
内容的提问来源于stack exchange,提问作者Petr Michovský
相关产品推荐
相关产品推荐

