Skip to content

Commit

Permalink
Vertical collision update
Browse files Browse the repository at this point in the history
  • Loading branch information
danielbejcek committed Mar 5, 2024
1 parent eb3c1e4 commit 80dc87d
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 60 deletions.
19 changes: 4 additions & 15 deletions Main/collisions.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,13 @@
import pygame

def platform_collision(screen,character_pos, character_img):
# def platform_collision(screen,character_pos, character_img):
def platform_collision():
platform_list = []
lamp = pygame.Rect(1002, 748, 185, 1)
floor = pygame.Rect(0, 900, 1792, 1)

lamp = pygame.Rect(1002, 700, 185, 10)
platform_list.append(lamp)

floor = pygame.Rect(0, 892, 1792, 10)
platform_list.append(floor)

character_rect = character_img.get_rect(topleft=character_pos)

for collide_point in platform_list:
if character_rect.colliderect(collide_point):
if collide_point == floor:
pygame.draw.rect(screen, (255, 0, 0,), floor)
elif collide_point == lamp:
pygame.draw.rect(screen, (255, 0, 0,), lamp)
else:
pygame.draw.rect(screen, (0, 0, 0,), floor)
pygame.draw.rect(screen, (0, 0, 0,), lamp)
return platform_list

19 changes: 8 additions & 11 deletions Main/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ def __init__(self):
pygame.init()
pygame.display.set_caption("FlashJump")
self.clock = pygame.time.Clock()
self.player = PlayerCharacter(600,300)
self.player = PlayerCharacter(600,700)
self.screen = self.player.screen
self.hitbox = None

def run(self,test_case=False, max_iterations=50):
"""Setting up a test case scenario to a limited number of iterations"""
Expand All @@ -22,24 +23,20 @@ def run(self,test_case=False, max_iterations=50):
"""Main images function"""
draw_background()

print(self.player.touchdown)
"""Test character square"""
character_rect = self.player.image.get_rect(topleft=self.player.img_pos)
pygame.draw.rect(self.screen, (255, 0, 0), character_rect, 2)
"""Manually drawn hitbox for more responsive collision"""
update_hitbox = self.player.update_hitbox(self.player.img_pos[0],self.player.img_pos[1])
self.hitbox = pygame.draw.rect(self.screen, (255, 0, 0), update_hitbox, 2)

"""Method that checks for collision and adjusts the character position accordingly"""
platform = platform_collision(self.screen,self.player.img_pos, self.player.image)
self.player.check_collision(platform)
"""Method that checks for vertical collision and adjusts the character position accordingly"""
platform = platform_collision()
self.player.check_vertical_collision(platform, self.hitbox)

"""Controls the movement of the player character"""
self.player.player_movement()

"""Main method for updating the character's animation (Idle, running, jumping, shooting from a bow)"""
self.player.update_animation()

# print("JUMP:",self.player.jump)
# print("TD:",self.player.touchdown)
# print("PEAK:",self.player.peak)

"""Arrow object animation, method is called only when 'arrow_quiver' list is not empty"""
if self.player.arrow_quiver != []:
Expand Down
45 changes: 21 additions & 24 deletions Main/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,25 @@ def __init__(self, x,y):
self.arrow_quiver = []
self.arrow_duration = 3000

"""Hitbox"""
self.hitbox = None

"""
Variables that help control the movement of the character. When user presses 'Key_A' to run left and right after 'Key_D' to run right,
character will stop and enter 'Idle' animation, until one of the keys is released.
"""
self.motion_left = False
self.motion_right = False

"""Creating a custom hitbox to better control the character collisions"""
def update_hitbox(self,x,y):
self.hitbox = (x + 53, y + 70,55,90)
return self.hitbox

def draw_character(self):
self.screen.blit(pygame.transform.flip(self.image, self.flip, False), self.img_pos)


"""Main method of the player's movement apparatus"""
def player_movement(self):
"""X axis position"""
self.img_pos[0] += (self.movement_x[1] - self.movement_x[0]) * self.x_velocity
Expand Down Expand Up @@ -166,39 +174,27 @@ def player_movement(self):
self.flip = True

"""
Method that checks for character's position.
Method that checks for character's vertical position.
Whenever the player is touching the ground, 'self.touchdown' is set to True.
Whenever player is airborne, 'self.touchdown' is set to False.
Whenever player proceeds to press the SPACE button, 'self.touchdown' is set to False.
The main movement of the character's apparatus is changing according to this variable
"""
def check_collision(self, platform_list):

"""Conditions that set X axis boundaries of the edge of the screen"""
if self.img_pos[0] <= -30:
self.movement_x[0] = False
if self.img_pos[0] >= 1670:
self.movement_x[1] = False

for platform in platform_list:
self.character_rect = self.image.get_rect(topleft=self.img_pos)
def check_vertical_collision(self, platforms, hitbox):
for platform in platforms:
if hitbox.colliderect(platform) and self.jump == False:

self.img_pos[1] = platform.top - (self.image.get_height())

"""Conditions that set Y axis"""
if self.character_rect.colliderect(platform) and self.jump == False:

self.img_pos[1] = platform.top - self.image.get_height()
self.peak = False
self.touchdown = True
self.peak = False
self.action, self.action_divider = 'Idle', 0

pygame.draw.rect(self.screen, (255, 0, 0,), platform)

if pygame.key.get_pressed()[pygame.K_a] or pygame.key.get_pressed()[pygame.K_d]:
self.action, self.action_divider = 'Running', 1
self.action, self.action_divider = 'Running', 1

if pygame.key.get_pressed()[pygame.K_a] and pygame.key.get_pressed()[pygame.K_d]:
self.action, self.action_divider = 'Idle', 0
else:
self.touchdown = False
self.action, self.action_divider = 'Idle', 0


def update_animation(self):
Expand All @@ -207,6 +203,7 @@ def update_animation(self):
We pass 'self.action_divider' that controls the nature of the action (idle, running etc...)
and 'self.frame_index' which allows the animation to always start from index 0 whenever a new action is introduced to prevent a 'list index out of range'.
"""

self.image = animate_character(self.action)[self.action_divider][self.frame_index]

if pygame.time.get_ticks() - self.update_time > 80:
Expand Down Expand Up @@ -234,7 +231,7 @@ def update_animation(self):

"""Once player reaches the 'self.peak', descending sequence is initialized"""
if self.peak:
self.y_velocity += .2
self.y_velocity += .5
self.action, self.action_divider = 'Landing', 6
self.movement_y[0] = False
self.movement_y[1] = True
Expand Down
32 changes: 22 additions & 10 deletions Tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,21 @@ def setUp(self):
self.game = main.Game()

"""Instance of player from PlayerCharacter class"""
self.player = PlayerCharacter(600,895)
self.player = PlayerCharacter(600,700)

"""Instance from main game loop"""
self.game.player = PlayerCharacter(600,895)
self.game.player = PlayerCharacter(600,700)

"""Setting up x, y position from the player instance in the main.Game() which is being updated"""
self.game_pos = self.game.player.img_pos

self.hitbox = self.game.player.hitbox

"""Setting up x, y position from static PlayerCharacter class"""
self.initial_pos = self.player.img_pos

"""Setting up a collision object"""
self.floor_platform = platform_collision(self.game_pos, self.game.player.image)
self.floor_platform = platform_collision()


def tearDown(self):
Expand Down Expand Up @@ -113,6 +115,7 @@ def test_bow_animation(self, mock_get_event):

@patch('pygame.event.get')
def test_attack_animation(self, mock_get_event):
self.game_pos[1] = 600
mock_get_event.return_value = [self.simulate_key_press(pygame.K_q)]
self.game.run(True)
self.assertFalse(self.player.movement_x[0])
Expand All @@ -124,27 +127,36 @@ def test_attack_animation(self, mock_get_event):
After we process 40 iterations of the in-game loop, the character should be now leveled
with the 'self.floor_platform'
"""
def test_collision(self):
def test_collision_floor(self):
self.game_pos[1] = 500
self.assertFalse(self.game.player.touchdown)
self.assertNotEqual(self.game_pos[1], self.floor_platform)
self.game.run(True, 40)

"""Subtracting '151' from the 'self.floor_platform' to compensate for the player's vertical length of the image."""
self.assertEqual(self.game_pos[1], (self.floor_platform-151))
self.assertNotEqual(self.game_pos[1], self.floor_platform[1].top - self.game.player.image.get_height())
self.game.run(True, 80)
self.assertTrue(self.game.player.touchdown)
"""Custom method to test that after player has landed, the difference between the player position and the collision floor is not more than 10 pixels"""
self.assertAlmostEqualsInt(self.game_pos[1],self.floor_platform[1].top - self.game.player.image.get_height(), 10)


def simulate_key_press(self, key):
mock_event_key = MagicMock()
mock_event_key.type = pygame.KEYDOWN
mock_event_key.key = key
return mock_event_key

"""Custom method to assert 'almostEqual' integers"""
def assertAlmostEqualsInt(self, first, second, delta):
if delta >= 10:
self.assertTrue(abs(first - second) <= delta)
else:
self.fail("Delta is not great enough")



class TestAnimationLists(unittest.TestCase):
def setUp(self):
self.game = main.Game()
"""Instance of player from PlayerCharacter class"""
self.player = PlayerCharacter(600, 895)
self.player = PlayerCharacter(600, 500)

"""Setting up x, y position from the player instance in the main.Game() which is being updated"""
self.img_pos = self.game.player.img_pos
Expand Down

0 comments on commit 80dc87d

Please sign in to comment.