人生就像一盘棋 2021-02-10 00:23
浏览 73

如何在纵向碰撞不存在时检测横向碰撞?

我最近在试着搞模拟生存,在碰撞检测发生了诡异事件

from tkinter import *
import time



class Game:
    def __init__(self):
        self.tk = Tk()
        self.tk.title("模拟生存")
        self.tk.resizable(0, 0)
        self.tk.wm_attributes("-topmost", 1)
        self.canvas = Canvas(self.tk, width = 600, height = 600, \
            highlightthickness = 0)
        self.canvas.pack()
        self.tk.update()
        self.canvas_height = 600
        self.canvas_width = 600
                
        self.sprites = []
        self.running = True

    def mainloop(self):
        while 1:
            if self.running:
                for sprite in self.sprites:
                    sprite.move()

            self.tk.update_idletasks()
            self.tk.update()
            time.sleep(0.01)

class Coords:
    def __init__(self, x1 = 0, y1 = 0, x2 = 0, y2 = 0):
        self.x1 = x1
        self.y1 = y1
        self.x2 = x2
        self.y2 = y2

    def within_x(co1, co2):
        if (co1.x1 > co2.x1 and co1.x1 < co2.x2) \
                or (co1.x2 > co2.x1 and co1.x2 < co2.x2) \
                or (co2.x1 > co1.x1 and co2.x1 < co1.x2) \
                or (co2.x2 > co1.x1 and co2.x2 < co1.x1):
            return True

        return False

    def within_y(co1, co2):
        if (co1.y1 > co2.y1 and co1.y1 < co2.y2) \
                or (co1.y2 > co2.y1 and co1.y2 < co2.y2) \
                or (co2.y1 > co1.y1 and co2.y1 < co1.y2) \
                or (co2.y2 > co1.y1 and co2.y2 < co1.y1):
            return True

        return False

def collided_left(co1, co2):
    if Coords.within_y(co1, co2):
        if co1.x1 <= co2.x2 and co1.x1 >= co2.x1:
            return True

    return False

def collided_right(co1, co2):
    if Coords.within_y(co1, co2):
        if co1.x2 <= co2.x1 and co1.x2 >= co2.x2:
            return True

    return False

def collided_top(co1, co2):
    if Coords.within_x(co1, co2):
        if co1.y1 <= co2.y2 and co1.y1 >= co2.y1:
            return True

    return False

def collided_bottom(y, co1, co2):
    if Coords.within_x(co1, co2):
        y_calc = co1.y2 + y
        if y_calc >= co2.y1 and y_calc <= co2.y2:
            return True

    return False

class Sprite:
    def __init__(self, game):
        self.game = game
        self.endgame = False
        self.coordinates = None

    def move(self):
        pass

    def coords(self):
        return self.coordinates

class StickFigureSprite(Sprite):
    def __init__(self, game):
        Sprite.__init__(self, game)
        self.images_left = [
            PhotoImage(file = "stick-L1.gif"),
            PhotoImage(file = "stick-L2.gif"),
            PhotoImage(file = "stick-L3.gif")
        ]
        self.images_right = [
            PhotoImage(file = "stick-R1.gif"),
            PhotoImage(file = "stick-R2.gif"),
            PhotoImage(file = "stick-R3.gif")
        ]
        self.image = game.canvas.create_image(200, 470, \
            image = self.images_left[0], anchor = 'nw')
        self.x = -2
        self.y = 0
        self.current_image = 0
        self.current_image_add = 1
        self.jump_count = 0
        self.last_time = time.time()
        self.coordinates = Coords()
        game.canvas.bind_all('<KeyPress-Left>', self.turn_left)
        game.canvas.bind_all('<KeyPress-Right>', self.turn_right)
        game.canvas.bind_all('<space>', self.jump)

    def turn_left(self, evt):
        if self.y == 0:
            self.x = -2

    def turn_right(self, evt):
        if self.y == 0:
            self.x = 2

    def jump(self, evt):
        if self.y == 0:
            self.y = -4
            self.jump_count = 0

    def animate(self):
        if self.x != 0 and self.y == 0:
            if time.time() - self.last_time > 0.1:
                self.last_time = time.time()
                self.current_image += self.current_image_add
                if self.current_image >= 2:
                    self.current_image_add = -1

                if self.current_image <= 0:
                    self.current_image_add = 1

        if self.x < 0:
            if self.y != 0:
                self.game.canvas.itemconfig(self.image, \
                    image = self.images_left[2])

            else:
                self.game.canvas.itemconfig(self.image, \
                    image = self.images_left[self.current_image])

        elif self.x > 0:
            if self.y != 0:
                self.game.canvas.itemconfig(self.image, \
                    image = self.images_right[2])

            else:
                self.game.canvas.itemconfig(self.image, \
                    image = self.images_right[self.current_image])

    def coords(self):
        xy = self.game.canvas.coords(self.image)
        self.coordinates.x1 = xy[0]
        self.coordinates.y1 = xy[1]
        self.coordinates.x2 = xy[0] + 27
        self.coordinates.y2 = xy[1] + 30
        return self.coordinates

    def move(self):
        self.animate()
        if self.y < 0:
            self.jump_count += 1
            if self.jump_count > 20:
                self.y = 4
        if self.y > 0:
            self.jump_count -= 1
        co = self.coords()
        left = True
        right = True
        top = True
        bottom = True
        falling = True
        if self.y > 0 and co.y2 >= self.game.canvas_height:
            self.y = 0
            bottom = False
        elif self.y < 0 and co.y2 <= 0:
            self.y = 0
            top = False
        if self.x > 0 and co.x2 >= self.game.canvas_width:
            self.x = 0
            right = False
        elif self.x < 0 and co.x1 <= 0:
            self.x = 0
            left = False
        for sprite in self.game.sprites:
            if sprite == self:
                continue
            sprite_co = sprite.coords()
            if top and self.y < 0 and collided_top(co, sprite_co):
                self.y = -self.y
                top = False
            if bottom and self.y > 0 and collided_bottom(self.y, \
                    co, sprite_co):
                self.y = sprite_co.y1 - co.y2
                if self.y < 0:
                    self.y = 0
                bottom = False
                top = False
            if  bottom and falling and self.y == 0 \
                    and co.y2 < self.game.canvas_height \
                    and collided_bottom(1, co, sprite_co):
                falling = False
            if left and self.x < 0 and collided_left(co, sprite_co):
                self.x = 0
                left = False
                if sprite.endgame:
                    self.game.running = False

            if right and self.x > 0 and collided_right(co, sprite_co):
                self.x = 0
                right = False
                if sprite.endgame:
                    self.game.running = False
        
        if falling and bottom and self.y == 0 \
                and co.y2 < self.game.canvas_height:
            self.y = 4
        self.game.canvas.move(self.image, self.x, self.y)

class Block(Sprite):
    def __init__(self, game, photo_image, x, y, width=25, height=25):
        Sprite.__init__(self, game)
        self.photo_image = photo_image
        self.image = game.canvas.create_image(x, y, \
            image = self.photo_image, anchor = 'nw')
        self.coordinates = Coords(x, y, x + width, y + height)

g = Game()
s = StickFigureSprite(g)
g.sprites.append(s)

gb = PhotoImage(file = "grassBlock.gif")
gb1 = Block(g, gb, 575, 575)
g.sprites.append(gb1)

g.mainloop()  
  • 如图,角色正在走向右下角的草方块(必须是右边,左边似乎没有这个诡异事件)

  • 仔细看右下角,人物走到草方块旁时应该碰撞到然后停下,然而却直接走进了草方块,冒出一个小头。请问这个问题有没有解决办法?

  •  

  • 写回答

1条回答 默认 最新

  • 人生就像一盘棋 2021-02-11 13:23
    关注

     先谢谢大家浏览,不过我终于自己想出了解决方案

    def floor_judge(y):
        if y <= 25:
            return 24
    
        elif y <= 50:
            return 23
    
        elif y <= 75:
            return 22
    
        elif y <= 100:
            return 21
    
        elif y <= 125:
            return 20
    
        elif y <= 150:
            return 19
    
        elif y <= 175:
            return 18
    
        elif y <= 200:
            return 17
    
        elif y <= 225:
            return 16
    
        elif y <= 250:
            return 15
    
        elif y <= 275:
            return 14
    
        elif y <= 300:
            return 13
    
        elif y <= 325:
            return 12
    
        elif y <= 350:
            return 11
    
        elif y <= 375:
            return 10
    
        elif y <= 400:
            return 9
    
        elif y <= 425:
            return 8
    
        elif y <= 450:
            return 7
    
        elif y <= 475:
            return 6
    
        elif y <= 500:
            return 5
    
        elif y <= 525:
            return 4
    
        elif y <= 550:
            return 3
    
        elif y <= 575:
            return 2
    
        else:
            return 1

    我加入了这些代码,进行层次判断

    if self.floor == sprite.floor and co.x2 in range(sprite_co.x1, sprite_co.x2) and self.x > 0:
        self.x = 0

    在主角的代码中,我加入了这个判断,在层次相同的情况下,如果自己的x2进入了对方x1到x2的序列中,且正在向右移动,则停止移动

    评论

报告相同问题?

悬赏问题

  • ¥15 微信会员卡接入微信支付商户号收款
  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题
  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?