【问题标题】:Why is the math of my stacking game not working?为什么我的堆叠游戏的数学不起作用?
【发布时间】:2020-10-29 19:59:59
【问题描述】:

这是我的第一个 pygame 项目,它是一个堆叠游戏。我制作游戏的想法是,任何不接触底座的棋子都会被切掉,然后一直持续到你的棋子变得太小或到达屏幕顶部为止。我的游戏的问题在于,如果你只将棋子堆叠在右侧,它就可以工作。但是,如果您开始向左堆叠,它就会分崩离析。我已经检查了很多次数学,但它仍然不起作用。它通过取底部棋子的基数 x 位置,然后减去或加上顶部棋子的 x 位置来计算被切掉的部分。

import pygame
import time
pygame.init()
win=pygame.display.set_mode((800,800))
pygame.display.set_caption("Stacking Game")
length=200 #The length of you CURRENT piece, the one that is moving
base=0 #X pos of the PREVIOUS stacked piece
x=0 #X pos of current piece
y=750 #y pos of current piece
blocks=0 #How many blocks have been stacked
difference=0
speed=5
direction=1
running=1
lengthbase=0 #Length of the PREVIOUS stacked piece
while (running==1):
    pygame.time.delay(10)
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            pygame.quit()
    if direction==1: 
        if x>800-length:
            direction=0
        else:
            x+=speed
    else:
        if direction==0:
            if x<0:
                direction=1
            else:
                x-=speed
    pygame.draw.rect(win,(0),(0,0,800,y+50)) #Blacks out the screen from the current piece to the top, leaving previously stacked pieces
    pygame.draw.rect(win,(255,0,0),(x,y,length,50))
    if blocks==16: #16 is the maximum number of blocks on the screen
        pygame.quit()
        print("You win!")
    if event.type==pygame.KEYDOWN and event.key==pygame.K_SPACE:
        if blocks==0: #Since the math is all based off the previous piece's length and position, this inserts the information of the first piece. We now know the position and length of the first stacked piece
            base=x
            lengthbase=200
        else:
            if x>base and x<(base+lengthbase): #The current piece should always be the same size and the previous piece, so it can either be stacked perfectly, to the right, or to the left. This calulates data when it is stacked to the right.
                difference=(x+length)-(base+lengthbase)
                length=length-difference
                pygame.draw.rect(win,(0),(0,0,800,y+50))
                pygame.draw.rect(win,(255,0,0),(x,y,length,50)) #Draws the new piece at the same position as the current piece, but with the new length
            else:
                if (x+length)>base and (x+length)<(base+lengthbase): #Calculates if the piece is stacked to the left.
                    difference=base-x
                    length=length-difference
                    pygame.draw.rect(win,(0),(0,0,800,y+50))
                    pygame.draw.rect(win,(255,0,0),(x+difference,y,length,50)) #If it was drawn on x, the stacked piece and the one below it would not be aligned. It has to move a distance of difference
                else:
                    pygame.quit()
                    print("You lost.")
        base=x #The stacked piece then becomes the bases for the next piece
        lengthbase=length
        speed+=1 
        blocks+=1
        y-=50
        time.sleep(0.5)
    pygame.display.update()

【问题讨论】:

  • 我认为更好地解释游戏的预期行为会有所帮助。运行它似乎没有帮助......似乎空格键是为了触发一个事件,但这对我不起作用。我想你可能有缩进问题,所有代码都应该在事件处理循环中?
  • 对我来说,代码运行良好,两边的红色东西都被砍掉了

标签: python math pygame collision-detection


【解决方案1】:

您必须评估范围 [x1, x1+w1] 和 [x2, x2+w2] 是否重叠。

不重叠:

x1      x1+w1
  +----+
            +----+
          x2      x2+w2
           x1      x1+w1
             +----+
  +----+
x2      x2+w2

重叠

x1                x1+w1
  +--------------+
       +----+
     x2      x2+w2
     x1      x1+w1
       +----+
  +---------------+
x2                 x2+w2
x1           x1+w1
  +---------+
       +----------+
     x2            x2+w2
     x1            x1+w1
       +----------+
  +----------+
x2            x2+w2

这意味着如果范围重叠

x1 < x2+w2 and x2 < x1+w1

您不需要左右两个单独的案例。只需评估这些区域是否重叠。用minmax计算公共区域的开始和结束:

if x < base + lengthbase and base < x + length:
    start = max(x, base)
    end = min(x+length, base+lengthbase)
    x = start
    length = end - start 
    pygame.draw.rect(win,(0),(0,0,800,y+50))
    pygame.draw.rect(win,(255,0,0),(x,y,length,50))
else:
    pygame.quit()
    print("You lost.")

这可以进一步简化:

start = max(x, base)
end = min(x+length, base+lengthbase)
if start < end:  
    x, length = start, end - start
    pygame.draw.rect(win,(0),(0,0,800,y+50))
    pygame.draw.rect(win,(255,0,0),(x,y,length,50))
else:
    # [...]

旁注:您必须在事件循环中处理事件,而不是在事件循环之后:

while running==1:
    pygame.time.delay(10)
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            pygame.quit()

        if event.type==pygame.KEYDOWN and event.key==pygame.K_SPACE:
            if blocks==0:
                base=x
                lengthbase=200
            else:
                start = max(x, base)
                end = min(x+length, base+lengthbase)
                if start < end:  
                    x, length = start, end - start
                    pygame.draw.rect(win,(0),(0,0,800,y+50))
                    pygame.draw.rect(win,(255,0,0),(x,y,length,50))
                else:
                    pygame.quit()
                    print("You lost.")
            base, lengthbase = x, length 
            speed += 1 
            blocks += 1
            y -= 50
            time.sleep(0.5)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-06
    • 1970-01-01
    • 2021-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-02
    • 1970-01-01
    相关资源
    最近更新 更多