I am constructing a recreation (shock) in pygame and I used to be having hassle with tile-based collision detection. There are 5 several types of non-empty tiles (proven beneath) that may be rotated in 90 diploma increments and flipped on each the x-axis and y-axis.
Merely put, adjusting the delta time allowed the participant to move by gadgets they actually should not have. So, I developed an algorithm to transform the tile set right into a vector map, which may then be collided utilizing arithmetic, making a second vector from the place on the final body and the place within the present bodyYou are able to do a comparability to see if the 2 traces collide, proper?
Effectively, sure, however probably not. Floating level errors trigger the collision to easily not be recorded beneath sure circumstances. For context, I offered the next collision algorithm:
def vectorcollide(self,vector,line):
#calculate the slopes of each traces
#get offset of perform. If it's a vertical line, offset behaves barely totally different: it's the x worth.
strive:
moveslope = (vector(0)(1)-vector(1)(1))/(vector(0)(0)-vector(1)(0))
moveoffset = vector(0)(1)-moveslope*vector(0)(0)
besides ZeroDivisionError:
moveslope = "cringe"
moveoffset = vector(0)(0)
strive:
lineslope = (line(0)(1)-line(1)(1))/(line(0)(0)-line(1)(0))
lineoffset = line(0)(1)-lineslope*line(0)(0)
besides ZeroDivisionError:
lineslope = "cringe"
lineoffset = line(0)(0)
textual content = pygame.font.SysFont("Comedian Sans MS", 100)
state.show.blit(textual content.render(f"{lineslope}", 0, (255,0,0)),(line(0)(0),line(0)(1)))
#discover level that may lie on each traces in the event that they have been infinite
if lineslope == "cringe":
if moveslope == "cringe":
#particular contingency if each traces are vertical
if lineoffset == moveoffset:
if line(0)(1)>=vector(0)(1) and line(0)(1)<=vector(1)(1):
return (lineoffset,line(0)(1))
elif line(1)(1)>=vector(0)(1) and line(1)(1)<=vector(1)(1):
return (lineoffset,line(0)(1))
else:
return None
else:
return None
else:
y = lineoffset*moveslope+moveoffset
level = (lineoffset,y)
#if level is definitely in each traces:
if (level(1) <= line(0)(1) and level(1) >= line(1)(1)) or (level(1) >= line(0)(1) and level(1) <= line(1)(1)):
if (level(1) <= vector(0)(1) and level(1) >= vector(1)(1)) or (level(1) >= vector(0)(1) and level(1) <= vector(1)(1)):
if (level(0) <= line(0)(0) and level(0) >= line(1)(0)) or (level(0) >= line(0)(0) and level(0) <= line(1)(0)):
if (level(0) <= vector(0)(0) and level(0) >= vector(1)(0)) or (level(0) >= vector(0)(0) and level(0) <= vector(1)(0)):
#return that time
return level
return None
else:
if moveslope == "cringe":
#particular contingency for vertical moveslope
if moveoffset <= line(0)(0) and moveoffset >= line (1)(0) or moveoffset >= line(0)(0) and moveoffset <= line (1)(0):
y = moveoffset*lineslope+lineoffset
if (y <= vector(0)(1) and y >= vector(1)(1)) or (y >= vector(0)(1) and y <= vector(1)(1)):
return (moveoffset,y)
else:
return None
else:
return None
else:
if moveslope == lineslope:
#particular contingency for 2 traces with the identical slope
if moveoffset == lineoffset:
xtru,ytru = False,False
if (line(0)(1)>=vector(0)(1) and line(0)(1)>=vector(1)(1))or(line(1)(1)>=vector(0)(1) and line(1)(1)>=vector(1)(1)):
ytru = True
if (line(0)(0)>=vector(0)(0) and line(0)(0)>=vector(1)(0))or(line(1)(0)>=vector(0)(0) and line(1)(0)>=vector(1)(0)):
xtru = True
if xtru and ytru:
return (vector(1))
else:
return None
else:
return None
else:
x = (lineoffset-moveoffset)/(moveslope-lineslope)
#contingency plan for horizontal traces
if lineslope == 0:
y = line(0)(1)
else:
y = moveslope*x+moveoffset
level = (x,y)
#pygame.draw.rect(state.show,(0,255,0), (level(0)-8,level(1)-8,16,16))
#if level is definitely in each traces:
if (level(1) <= line(0)(1) and level(1) >= line(1)(1)) or (level(1) >= line(0)(1) and level(1) <= line(1)(1)):
if (level(1) <= vector(0)(1) and level(1) >= vector(1)(1)) or (level(1) >= vector(0)(1) and level(1) <= vector(1)(1)):
if (level(0) <= line(0)(0) and level(0) >= line(1)(0)) or (level(0) >= line(0)(0) and level(0) <= line(1)(0)):
if (level(0) <= vector(0)(0) and level(0) >= vector(1)(0)) or (level(0) >= vector(0)(0) and level(0) <= vector(1)(0)):
#return that time
return level
#by default, return nothing
return None
At this level, I’ve limped the system by working the outdated tile-based system after the vector-based one, thus choosing up any slack (there are nonetheless some buggy collisions, nevertheless it’s higher than nothing ™).
Which brings me to my query: How do different individuals, particularly these within the business, clear up these issues? I’ve seen ideas about including a margin of error to collisions, however the quantity of multiplication and division concerned would in all probability imply that the margin must be fairly massive.
Others within the business should have methods to beat this – they’ve been utilizing vectors to collide for years. So what is the trick?
EDIT: As per @DMGregory’s request, I added some further context. Moreover, it has given me good floor to begin from. this challenge… however not all video games use a tiling system, particularly 3D ones! So I am nonetheless open to any recommendation individuals may give me on how such a factor is often performed, which I can use in later tasks.
