Skip to content
GitLab
Next
Menu
Projects
Groups
Snippets
Help
What's new
4
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Matthew Odle
python-concept-examples
Commits
5b41fdf9
Commit
5b41fdf9
authored
Jan 11, 2022
by
Matthew Odle
Browse files
add logic for calculating rect overlap area
parent
1c86236a
Changes
2
Hide whitespace changes
Inline
Side-by-side
pygame-rect-collision-with-math/
main
.py
→
pygame-rect-collision-with-math/
rect_exact_overlap_check
.py
View file @
5b41fdf9
File moved
pygame-rect-collision-with-math/rect_m
atch
_check.py
→
pygame-rect-collision-with-math/rect_m
ost_overlap
_check.py
View file @
5b41fdf9
...
...
@@ -6,6 +6,7 @@ work out mathematically how to compare rects using dict lookup
instead of a loop.
"""
import
json
import
math
import
pygame
from
pygame.locals
import
(
...
...
@@ -13,6 +14,11 @@ from pygame.locals import (
K_DOWN
,
K_LEFT
,
K_RIGHT
,
# vim movement keys
K_h
,
K_j
,
K_k
,
K_l
,
)
# set up colors
...
...
@@ -53,6 +59,12 @@ rect_colors = {
f
'
{
start_x
}
,
{
end_y
}
'
:
GREEN
,
}
player_rect
=
pygame
.
Rect
(
(
start_x
-
move_speed
*
4
,
start_y
),
(
rect_side
,
rect_side
)
)
display_rects
=
[]
def
main
():
pygame
.
init
()
...
...
@@ -69,12 +81,9 @@ def main():
match_rect
=
screen
.
get_rect
(
topleft
=
(
0
,
20
))
value_rect
=
screen
.
get_rect
(
topleft
=
(
20
,
40
))
# set up value holders
x_value
=
start_x
-
move_speed
*
4
y_value
=
start_y
# set up a clock to handle framereate
clock
=
pygame
.
time
.
Clock
()
make_rects
(
screen
)
# run until the user asks to quit
running
=
True
...
...
@@ -86,16 +95,17 @@ def main():
# adjust coordinates based on input
pressed_keys
=
pygame
.
key
.
get_pressed
()
if
pressed_keys
[
K_UP
]:
y_value
+=
-
move_speed
if
pressed_keys
[
K_DOWN
]:
y_value
+=
move_speed
if
pressed_keys
[
K_LEFT
]:
x_value
+=
-
move_speed
if
pressed_keys
[
K_RIGHT
]:
x_value
+=
move_speed
if
pressed_keys
[
K_UP
]
or
pressed_keys
[
K_j
]
:
player_rect
.
y
+=
-
move_speed
if
pressed_keys
[
K_DOWN
]
or
pressed_keys
[
K_k
]
:
player_rect
.
y
+=
move_speed
if
pressed_keys
[
K_LEFT
]
or
pressed_keys
[
K_h
]
:
player_rect
.
x
+=
-
move_speed
if
pressed_keys
[
K_RIGHT
]
or
pressed_keys
[
K_l
]
:
player_rect
.
x
+=
move_speed
quadrant_matched
=
get_quadrant
(
x_value
,
y_value
)
#quadrant_matched = get_quadrant(player_rect.x, player_rect.y)
quadrant_matched
=
check_overlap
(
player_rect
)
# fill the background with black
screen
.
fill
(
BLACK
)
...
...
@@ -104,8 +114,8 @@ def main():
#pygame.draw.circle(screen, (0, 0, 255), (250, 250), 75)
# render the text into the font object
pos_surf
=
font
.
render
(
f
'
{
x_value
}
,
{
y_value
}
'
,
True
,
WHITE
,
BLACK
)
snap_surf
=
font
.
render
(
f
'
{
snap
(
x_value
)
}
,
{
snap
(
y_value
)
}
'
,
True
,
WHITE
,
BLACK
)
pos_surf
=
font
.
render
(
f
'
{
player_rect
.
x
}
,
{
player_rect
.
y
}
'
,
True
,
WHITE
,
BLACK
)
snap_surf
=
font
.
render
(
f
'
{
snap
(
player_rect
.
x
)
}
,
{
snap
(
player_rect
.
y
)
}
'
,
True
,
WHITE
,
BLACK
)
match_surf
=
font
.
render
(
f
'matched?'
,
True
,
WHITE
,
BLACK
)
value_surf
=
font
.
render
(
f
'
{
quadrant_matched
}
'
,
True
,
WHITE
,
BLACK
)
...
...
@@ -115,7 +125,7 @@ def main():
screen
.
blit
(
match_surf
,
match_rect
)
screen
.
blit
(
value_surf
,
value_rect
)
make
_rects
(
screen
,
x_value
,
y_value
)
draw
_rects
(
screen
)
make_grid
(
screen
)
# flip the display; i.e. make it visible
...
...
@@ -136,10 +146,51 @@ def snap(value):
def
get_quadrant
(
x
,
y
):
snap_x
=
snap
(
x
)
snap_y
=
snap
(
y
)
print
(
'unit is:'
,
rect_side
,
' coords:'
,
x
,
y
,
' snapped:'
,
snap_x
,
snap_y
)
#print('unit is:',rect_side,' coords:',x,y,' snapped:',snap_x,snap_y)
return
rect_topleft_points
.
get
(
f
'
{
snap_x
}
,
{
snap_y
}
'
)
def
check_overlap
(
actor
):
x
=
actor
.
x
y
=
actor
.
y
# get snapped coordinates
offset_x
=
actor
.
width
offset_y
=
actor
.
height
check_points
=
{
'quad1'
:
{
'x'
:
snap
(
x
),
'y'
:
snap
(
y
)},
'quad2'
:
{
'x'
:
snap
(
x
)
+
offset_x
,
'y'
:
snap
(
y
)},
'quad3'
:
{
'x'
:
snap
(
x
)
+
offset_x
,
'y'
:
snap
(
y
)
+
offset_y
},
'quad4'
:
{
'x'
:
snap
(
x
),
'y'
:
snap
(
y
)
+
offset_y
},
}
# do rectangle math to find most overlapped
results
=
{}
most_overlapped
=
'none'
most_overlapped_area
=
0
for
key
,
value
in
check_points
.
items
():
overlapped_with
=
rect_topleft_points
.
get
(
f
'
{
value
.
get
(
"x"
)
}
,
{
value
.
get
(
"y"
)
}
'
)
overlap
=
calculate_rect_overlap
(
actor
,
value
)
if
overlapped_with
else
(
0
,
0
)
overlap_area
=
overlap
[
0
]
*
overlap
[
1
]
if
overlap_area
>
most_overlapped_area
:
most_overlapped_area
=
overlap_area
most_overlapped
=
overlapped_with
results
[
key
]
=
{
'overlaps_with'
:
overlapped_with
if
overlap_area
else
'no'
,
'overlap_dims'
:
overlap
if
overlap_area
else
'no'
,
'overlap_area'
:
overlap_area
,
}
print
(
json
.
dumps
(
results
,
indent
=
4
,
sort_keys
=
True
))
return
most_overlapped
def
calculate_rect_overlap
(
actor
,
target
):
x_overlap
=
max
(
0
,
min
(
target
.
get
(
'x'
)
+
rect_side
,
actor
.
x
+
actor
.
width
)
-
max
(
actor
.
x
,
target
.
get
(
'x'
)))
y_overlap
=
max
(
0
,
min
(
target
.
get
(
'y'
)
+
rect_side
,
actor
.
y
+
actor
.
height
)
-
max
(
actor
.
y
,
target
.
get
(
'y'
)))
return
x_overlap
,
y_overlap
def
make_grid
(
screen
):
start_height
=
rect_side
*
2
y
=
start_height
...
...
@@ -165,17 +216,19 @@ def make_grid(screen):
x
+=
rect_side
def
make_rects
(
screen
,
player_x
,
player_y
):
def
draw_rects
(
screen
):
# draw display rects
for
entry
in
display_rects
:
pygame
.
draw
.
rect
(
screen
,
rect_colors
[
f
'
{
entry
.
x
}
,
{
entry
.
y
}
'
],
entry
,
border_radius
=
10
)
# draw player rect
pygame
.
draw
.
rect
(
screen
,
WHITE
,
player_rect
,
border_radius
=
10
)
def
make_rects
(
screen
):
# draw target rects
for
coord
in
rect_topleft_points
.
keys
():
x
,
y
=
coord
.
split
(
','
)
#print(x, y)
new_rect
=
pygame
.
Rect
((
int
(
x
),
int
(
y
)),
(
rect_side
,
rect_side
))
pygame
.
draw
.
rect
(
screen
,
rect_colors
[
coord
],
new_rect
,
border_radius
=
10
)
# draw player rect
player_rect
=
pygame
.
Rect
((
player_x
,
player_y
),
(
rect_side
,
rect_side
))
pygame
.
draw
.
rect
(
screen
,
WHITE
,
player_rect
,
border_radius
=
10
)
display_rects
.
append
(
pygame
.
Rect
((
int
(
x
),
int
(
y
)),
(
rect_side
,
rect_side
)))
if
__name__
==
'__main__'
:
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment