-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactored code for scale using OOP and SOLID.
- Reorganized all code into classes. - Restructured code to use inheritance. - Assigned a single responsibility to each class. - Designed classes to be extensible and substitutable. - Decoupled interfaces and used composition. - Used dependency inversion to reduce unnessary complexity.
- Loading branch information
1 parent
e09c6c4
commit 3be512d
Showing
39 changed files
with
848 additions
and
600 deletions.
There are no files selected for viewing
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
from src.ui import Image | ||
|
||
class Character: | ||
def __init__(self, x, y, sprite_path, size, max_speed_x, max_speed_y, | ||
acceleration_x=0, acceleration_y=0, friction_coefficient=0.0, gravity=0, max_health=100): | ||
self.sprite = Image(sprite_path, size) | ||
self.bbox = self.sprite.get_rect(topleft=(x, y)) | ||
|
||
self.x, self.y = x, y | ||
self.max_speed_x, self.max_speed_y = max_speed_x, max_speed_y | ||
self.acceleration_x, self.acceleration_y = acceleration_x, acceleration_y | ||
self.friction_coefficient = friction_coefficient | ||
self.gravity = gravity | ||
self.vx, self.vy = 0, 0 | ||
self.max_health, self.health = max_health, max_health | ||
|
||
def take_damage(self, damage): | ||
self.health -= damage | ||
if self.health <= 0: | ||
self.defeated() | ||
|
||
def defeated(self): | ||
pass | ||
|
||
def accelerate(self, direction): | ||
self.vx += self.acceleration_x * direction[0] | ||
self.vy += self.acceleration_y * direction[1] | ||
|
||
def apply_friction(self, dt): | ||
friction_x = -self.friction_coefficient * self.vx | ||
friction_y = -self.friction_coefficient * self.vy | ||
|
||
self.vx += friction_x #* dt | ||
self.vy += friction_y #* dt | ||
|
||
def compute_new_position(self, dt): | ||
self.apply_friction(dt) | ||
self.vx = max(-self.max_speed_x, min(self.max_speed_x, self.vx)) | ||
self.vy = max(-self.max_speed_y, min(self.max_speed_y, self.vy)) | ||
self.vy += self.gravity * dt | ||
new_x = self.x + self.vx #* dt | ||
new_y = self.y + self.vy #* dt | ||
return new_x, new_y | ||
|
||
def set_position(self, x, y): | ||
self.x, self.y = x, y | ||
self.bbox.x, self.bbox.y = self.x, self.y | ||
self.sprite.position = (self.x, self.y) | ||
|
||
def clamp_position(self, screen): | ||
self.x = max(0, min(screen.get_width() - self.bbox.width, self.x)) | ||
self.y = max(0, min(screen.get_height() - self.bbox.height, self.y)) | ||
self.bbox.x, self.bbox.y = self.x, self.y | ||
|
||
def update(self, dt): | ||
new_x, new_y = self.compute_new_position(dt) | ||
self.set_position(new_x, new_y) | ||
|
||
def draw(self, screen): | ||
self.clamp_position(screen) | ||
self.sprite.draw(screen) | ||
|
||
def handle_input(self, events, keys): | ||
self.handle_events(events) | ||
self.handle_keys(keys) | ||
|
||
def handle_events(self, events): | ||
pass | ||
|
||
def handle_keys(self, keys): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from src.character.character import Character | ||
|
||
class EntangledPair(Character): | ||
def __init__(self, x, y): | ||
super().__init__(x, y, 'entangled_pair.png', (32, 32), 4, 1, 0.9) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import pygame | ||
from src.character.player.player import Player | ||
|
||
class Ghost(Player): | ||
def __init__(self, x, y): | ||
super().__init__(x, y, 'ghost.png') | ||
self.active = False | ||
|
||
def activate(self, x, y): | ||
self.set_position(x, y) | ||
self.active = True | ||
|
||
def deactivate(self): | ||
self.active = False | ||
|
||
def draw(self, screen): | ||
if self.active: | ||
super().draw(screen) | ||
|
||
def update(self, dt): | ||
if self.active: | ||
super().update(dt) | ||
|
||
def handle_keys(self, keys): | ||
if self.active: | ||
if keys[pygame.K_j]: | ||
self.accelerate((-1, 0)) | ||
if keys[pygame.K_l]: | ||
self.accelerate((1, 0)) | ||
if keys[pygame.K_i]: | ||
self.accelerate((0, -1)) | ||
if keys[pygame.K_k]: | ||
self.accelerate((0, 1)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from src.character.character import Character | ||
|
||
class Player(Character): | ||
def __init__(self, x, y, sprite_path, size=(30, 30), max_speed_x=4, max_speed_y=4, | ||
acceleration_x=4, acceleration_y=4, friction_coefficient=0.1, gravity=0, max_health=100): | ||
super().__init__(x, y, sprite_path, size, max_speed_x, max_speed_y, | ||
acceleration_x, acceleration_y, friction_coefficient, gravity, max_health) | ||
self.collected_quarks = 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
import pygame | ||
from src.character.player.player import Player | ||
from src.character.player.ghost import Ghost | ||
from src.character.entangled_pair import EntangledPair | ||
|
||
class Quarky(Player): | ||
def __init__(self, x, y): | ||
super().__init__(x, y, 'quarky.png') | ||
self.level = None | ||
|
||
# Quarky has a 'ghost` that is a temporary copy of himself | ||
# and appears when he uses the superposition ability | ||
self.superposition_active = False | ||
self.ghost = Ghost(self.bbox.x, self.bbox.y) | ||
|
||
# Quarky can get entangled with another instance of himself | ||
# and teleport to his entangled pair when he uses the | ||
# entanglement ability | ||
self.entanglement_active = False | ||
self.entangled_pair = None | ||
|
||
# Quarky can use quantum tunneling to tunnel through | ||
# solid objects when he uses the quantum tunneling ability | ||
self.quantum_tunneling_active = False | ||
|
||
def set_level(self, level): | ||
self.level = level | ||
|
||
def collides_with_goal(self, goal): | ||
return self.bbox.colliderect(goal.rect) | ||
|
||
def collides_with_quark(self, quarks): | ||
for quark in quarks: | ||
if self.bbox.colliderect(quark.bbox): | ||
return quark | ||
return None | ||
|
||
def merge_with_ghost(self): | ||
self.set_position(self.ghost.bbox.x, self.ghost.bbox.y) | ||
self.ghost.deactivate() | ||
|
||
def draw(self, screen): | ||
if self.entangled_pair: | ||
self.entangled_pair.draw(screen) | ||
super().draw(screen) | ||
self.ghost.draw(screen) | ||
|
||
def activate_superposition(self): | ||
self.superposition_active = True | ||
self.ghost.activate(self.x, self.y) | ||
|
||
def deactivate_superposition(self): | ||
if self.superposition_active: | ||
self.superposition_active = False | ||
self.merge_with_ghost() | ||
|
||
def activate_entanglement(self): | ||
self.entanglement_active = True | ||
|
||
def toggle_entanglement(self): | ||
if self.entanglement_active: | ||
if self.entangled_pair: | ||
self.set_position(self.entangled_pair.x, self.entangled_pair.y) | ||
self.entangled_pair = None | ||
self.entanglement_active = False | ||
else: | ||
self.entangled_pair = EntangledPair(self.x, self.y) | ||
|
||
def activate_quantum_tunneling(self): | ||
self.quantum_tunneling_active = True | ||
|
||
def deactivate_quantum_tunneling(self): | ||
if self.quantum_tunneling_active: | ||
self.quantum_tunneling_active = False | ||
|
||
def handle_events(self, events): | ||
super().handle_events(events) | ||
actions = { | ||
pygame.K_m: self.deactivate_superposition, | ||
pygame.K_t: self.deactivate_quantum_tunneling, | ||
pygame.K_e: self.toggle_entanglement, | ||
} | ||
|
||
for event in events: | ||
if event.type == pygame.KEYDOWN: | ||
if event.key in actions: | ||
actions[event.key]() | ||
|
||
def handle_keys(self, keys): | ||
super().handle_keys(keys) | ||
self.ghost.handle_keys(keys) | ||
if keys[pygame.K_LEFT]: | ||
self.accelerate((-1, 0)) | ||
if keys[pygame.K_RIGHT]: | ||
self.accelerate((1, 0)) | ||
if keys[pygame.K_UP]: | ||
self.accelerate((0, -1)) | ||
if keys[pygame.K_DOWN]: | ||
self.accelerate((0, 1)) | ||
|
||
def handle_quark_interaction(self, quark, level): | ||
if quark.interaction == "superposition": | ||
self.activate_superposition() | ||
elif quark.interaction == "entanglement": | ||
self.activate_entanglement() | ||
elif quark.interaction == "quantum_tunneling": | ||
self.quantum_tunneling_active = True | ||
elif quark.interaction == "collect": | ||
self.collected_quarks += 1 | ||
|
||
level.quarks.remove(quark) | ||
|
||
def update(self, dt): | ||
if self.level: | ||
# Update the player's position while checking for collisions | ||
new_x, new_y = self.compute_new_position(dt) | ||
if self.quantum_tunneling_active: | ||
self.set_position(new_x, new_y) | ||
else: | ||
new_bbox = pygame.Rect(new_x, self.y, self.bbox.width, self.bbox.height) | ||
if not self.level.collides_with_wall(new_bbox): | ||
self.set_position(new_x, self.y) | ||
|
||
new_bbox = pygame.Rect(self.x, new_y, self.bbox.width, self.bbox.height) | ||
if not self.level.collides_with_wall(new_bbox): | ||
self.set_position(self.x, new_y) | ||
|
||
# Quarks can be collected regardless of quantum tunneling | ||
quark_collision = self.collides_with_quark(self.level.quarks) | ||
if quark_collision: | ||
self.handle_quark_interaction(quark_collision, self.level) | ||
|
||
# Update the ghost if superposition is active | ||
if self.superposition_active: | ||
self.ghost.update(dt) |
Empty file.
File renamed without changes.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.