wxPython和pycairo练习记录4

这篇博客介绍了在wxPython和pycairo中实现坦克游戏的碰撞检测和转向策略。作者通过判断坦克的相对位置和方向来决定碰撞后的转向行为,并提供了相应的代码示例。在碰撞检测中,使用了矩形类的Intersects方法。此外,还展示了玩家和敌方坦克的键盘控制以及自动行走逻辑。

wxPython和pycairo练习记录4

继续写碰撞检测。

4.1 判断碰撞的条件

碰撞,即两个坦克车身产生重合。
在这里插入图片描述

因为这里的坦克是四方向的,所以可碰撞的区域概括为编号4和5,不可碰撞区域概括为6和7。已知的是坦克左上角定位点,及坦克的宽高。假设玩家坦克坐标为(x, y),宽高为(w, h),其他敌方坦克以编号作下标。

先以正相邻的4号区域来看,4和坦克碰撞,得到条件:
abs(x4 - x) < w4
那么 x 坐标相同且 y 坐标不同的的4567都满足这个条件,所以同时还需要判断 y 坐标:
abs(y4 - y) < h4

再代入编号1234567,发现符合预期。

当然,wxPython 自带的矩形类 wx.Rect 的方法 Intersects 也可以实现同样的效果。

4.2 碰撞后的转向问题

碰撞后谁转向?谁撞了谁?已知两个坦克的前进方向和坐标,可以通过坐标差判断相对位置。

同方向相撞>>,位置在后的转向。
相对方向相撞><,都转向。
不同轴方向相撞>^^>,撞向侧面的那个转向。

4.3 代码

还是有问题:1.相对方向碰撞时用SetDirection不转向,但是用ChangeDirection可以,这两个方法都是修改_direction,也不知道错在哪;2.转向时依然有重合的地方。

    def CheckCollisions(self):
        # checked = [] # 存储已检测过的坦克对象
        for tank1 in self.enemies:
            for tank2 in self.enemies:
                # 忽略自身和已检测过的坦克
                if tank1 is tank2:
                # if tank1 is tank2 or tank2 in checked:
                    continue

                rect1 = tank1.GetRect()
                rect2 = tank2.GetRect()
                x1, y1, w1, w2 = rect1
                x2, y2, w2, h2 = rect2
                direction1 = tank1.GetDirection()
                direction2 = tank2.GetDirection()

                if rect1.Intersects(rect2):
                    # 同方向相撞>>,位置在后的转向。
                    # 不同轴方向相撞>^或^>,撞向侧面的那个转向。
                    # print(wx.WXK_UP, wx.WXK_DOWN, wx.WXK_LEFT, wx.WXK_RIGHT)
                    # 315 317 314 316
                    if abs(direction1 - direction2) != 2:
                    # if direction1 == direction2 or abs(direction1 - direction2) == 1 or abs(direction1 - direction2) == 3:
                        if direction1 == wx.WXK_UP and y1 >= y2:
                            tank1.SetDirection(wx.WXK_DOWN)
                        elif direction1 == wx.WXK_DOWN and y1 <= y2:
                            tank1.SetDirection(wx.WXK_UP)
                        elif direction1 == wx.WXK_LEFT and x1 >= x2:
                            tank1.SetDirection(wx.WXK_RIGHT)
                        elif direction1 == wx.WXK_RIGHT and x1 <= x2:
                            tank1.SetDirection(wx.WXK_LEFT)
                        else:
                            direction2 = (direction2 <= 315) and (direction2 + 2) or (direction2 - 2)
                            tank2.SetDirection(direction2)
                    # 相对方向相撞><,都转向。
                    else:
                    # elif abs(direction1 - direction2) == 2:
                        # TODO: 哪里错了?
                        # tank1.SetDirection(direction2)
                        # tank2.SetDirection(direction1)
                        tank1.ChangeDirection(direction1)
                        tank2.ChangeDirection(direction2)
            # checked.append(tank1)

4.4 效果

在这里插入图片描述

# -*- coding: utf-8 -*-
# example2.py

import random
import wx
import wx.lib.wxcairo
import cairo
import board
from display import MovieClip


class cv(board.cv):
    """
    常量,用类属性避免使用全局变量
    """
    # 面板尺寸
    BOARD_WIDTH = 600
    BOARD_HEIGHT = 400


class Tank(MovieClip):
    def __init__(self, *args, **kwargs):
        super(Tank, self).__init__(*args, **kwargs)
        self._speed = 10 # 移动速度
   
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值