Skip to content

Commit

Permalink
add service classes, finalize week 5 assignment
Browse files Browse the repository at this point in the history
  • Loading branch information
JHNUL committed Dec 7, 2021
1 parent 5d2f022 commit 7215cfc
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 64 deletions.
14 changes: 13 additions & 1 deletion dokumentaatio/arkkitehtuuri.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,16 @@ Kuvassa on sovelluksen persistoima data luokkakuvauksena. Sovelluksessa on pelaa

![Kuva](./images/game.png)

Kuvassa sovelluksen logiikan kannalta olennaisin kokonaisuus eli taso ja siinä vaikuttavat entiteetit. Taso tietää sisällään olevat entiteetit ja tason julkista metodia `move_pac` kutsutaan liikuttamaan Pacia. Taso myös tietää senhetkisen pistetilanteen, koska sen täytyy sitä pystyä manipuloimaan pelitapahtumien perusteella.
Kuvassa sovelluksen logiikan kannalta olennaisin kokonaisuus eli taso ja siinä vaikuttavat entiteetit. Taso tietää sisällään olevat entiteetit ja tason julkista metodia `move_pac` kutsutaan liikuttamaan Pacia. Taso myös tietää senhetkisen pistetilanteen, koska sen täytyy sitä pystyä manipuloimaan pelitapahtumien perusteella.

## Kirjautumistoiminnallisuus

Alla on esitetty uuden ja olemassa olevan pelaajan kirjautuminen. Omalle koneelle ladattavan pelin ollessa kyseessä ei ollut mielekästä lähteä luomaan salasanoja, vaan pelaaja kirjautuu hyväksi katsomallaan nimimerkillä ja mikäli tällaista nimimerkkiä ei ole, se luodaan. Mikään ei käytännössä estä pelaamasta jonkun toisen pelaajan mahdollisesti käyttämällä nimimerkillä.

Uuden pelaajan kirjautumisen sekvenssikaavio.

![Kuva](./images/new_player.png)

Olemassa olevan pelaajan kirjautumisen sekvenssikaavio.

![Kuva](./images/existing_player.png)
Binary file added dokumentaatio/images/existing_player.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dokumentaatio/images/new_player.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion dokumentaatio/tuntikirjanpito.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@
| 4.12 | 2 | harjoitustyön työstöä viikko 5 |
| 5.12 | 5 | harjoitustyön työstöä viikko 5, refaktoria |
| 6.12 | 2 | harjoitustyön työstöä viikko 5, refaktoria |
|yht| 47 |
| 7.12 | 1 | harjoitustyön työstöä viikko 5 |
|yht| 48 |
50 changes: 24 additions & 26 deletions src/game/level.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,40 @@
from datetime import datetime
import pygame
from game.sprites.enemy import Enemy
from game.sprites.nugget import Nugget
from game.sprites.pac import Pac
from game.sprites.wall import Wall
from models.score import Score
from repositories.score_repository import ScoreRepository
from services.score_service import ScoreService
from utils import normalize


class Level:
def __init__(self, level_map, score: Score, score_repository: ScoreRepository):
self.map = level_map
def __init__(self, level_map, score: Score, score_service: ScoreService):
self.is_finished = False
self.pac = None
self.walls = pygame.sprite.Group()
self.nuggets = pygame.sprite.Group()
self.sprites = pygame.sprite.Group()
self.enemies = pygame.sprite.Group()
self.current_score = score
self.is_finished = False
self.score_repo = score_repository
self.sprites = pygame.sprite.Group()
self._map = level_map
self._walls = pygame.sprite.Group()
self._nuggets = pygame.sprite.Group()
self._enemies = pygame.sprite.Group()
self._score_service = score_service
self._create_level()

def _create_level(self):
for y in range(len(self.map)):
for x in range(len(self.map[0])):
cell = self.map[y][x]
for y in range(len(self._map)):
for x in range(len(self._map[0])):
cell = self._map[y][x]
if cell == 0:
self.nuggets.add(Nugget(normalize(x), normalize(y)))
self._nuggets.add(Nugget(normalize(x), normalize(y)))
elif cell == 1:
self.walls.add(Wall(normalize(x), normalize(y)))
self._walls.add(Wall(normalize(x), normalize(y)))
elif cell == 2:
self.pac = Pac(normalize(x), normalize(y))
elif cell == 3:
self.enemies.add(Enemy(normalize(x), normalize(y)))
self._enemies.add(Enemy(normalize(x), normalize(y)))

self.sprites.add(self.pac, self.walls, self.nuggets, self.enemies)
self.sprites.add(self.pac, self._walls, self._nuggets, self._enemies)

def _check_collision(self, sprites, do_kill=False):
return len(pygame.sprite.spritecollide(self.pac, sprites, do_kill))
Expand All @@ -46,14 +45,13 @@ def _increase_score(self):
def _check_collisions(self):
if self.pac.ephemeral:
return
if self._check_collision(self.nuggets, True):
if self._check_collision(self._nuggets, True):
self.current_score.increase()
if len(self.nuggets) == 0:
if len(self._nuggets) == 0:
self.is_finished = True
self.current_score.set_timestamp(datetime.now().timestamp())
self.score_repo.add_score(self.current_score)
self._score_service.add_score(self.current_score)

if self._check_collision(self.enemies):
if self._check_collision(self._enemies):
self.pac.lives -= 1
self.pac.ephemeral = True
if self.pac.lives == 0:
Expand All @@ -62,15 +60,15 @@ def _check_collisions(self):
def reset(self):
if self.pac is not None:
self.pac.kill()
for enemy in self.enemies:
for enemy in self._enemies:
enemy.kill()
self.current_score.reset()
self._create_level()
self.is_finished = False

def _move_enemies(self):
for enemy in self.enemies:
enemy.move(self.walls)
for enemy in self._enemies:
enemy.move(self._walls)
self._check_collisions()

def do_update(self, move_enemies=False, direction=None):
Expand All @@ -79,7 +77,7 @@ def do_update(self, move_enemies=False, direction=None):
if move_enemies:
self._move_enemies()
if direction:
self.pac.move(direction, self.walls)
self.pac.move(direction, self._walls)
self._check_collisions()
if self.pac.ephemeral:
self.pac.count_down()
16 changes: 4 additions & 12 deletions src/game/menus/login_menu.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,23 @@
from datetime import datetime
from pygame import Surface, QUIT
from pygame_menu import Menu

import constants as const
from models.player import Player
from models.score import Score
from repositories.player_repository import PlayerRepository
from services.player_service import PlayerService


class LoginMenu:
def __init__(self, player: Player, player_repository: PlayerRepository, score: Score):
def __init__(self, player: Player, player_service: PlayerService, score: Score):
self._menu = Menu(const.SCREEN_TITLE_LANDING, 500, 300)
self._player = player
self._score = score
self._player_repository = player_repository
self._player_service = player_service
self._name = None
self._init_screen()

def _start_btn_callback(self):
player = self._player_repository.find_player_by_name(self._name)
now = datetime.now().timestamp()
if player is None:
player = self._player_repository.add_player(
Player(name=self._name, last_login=now))
else:
player.set_login_time(now)
self._player_repository.update_player(player)
player = self._player_service.player_login(self._name)
self._player.set_player(player)
self._score.set_player_id(player)
self._menu.disable()
Expand Down
17 changes: 9 additions & 8 deletions src/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@
from repositories.score_repository import ScoreRepository
from db_connection import get_db_connection
from init_db import initialize_db
from services.player_service import PlayerService
from services.score_service import ScoreService


def main():
initialize_db()
connection = get_db_connection()

pygame.init()
pygame.display.set_caption(SCREEN_TITLE_GAME)
pygame.time.set_timer(MOVE_ENEMIES, 300)
Expand All @@ -27,12 +26,13 @@ def main():

player = Player()
score = Score(0)
player_repository = PlayerRepository(connection)
score_repository = ScoreRepository(connection)
level = Level(level_map=MAP, score=score,
score_repository=score_repository)
player_repository = PlayerRepository(get_db_connection())
score_repository = ScoreRepository(get_db_connection())
player_service = PlayerService(player_repository=player_repository)
score_service = ScoreService(score_repository=score_repository)
level = Level(level_map=MAP, score=score, score_service=score_service)
login_menu = LoginMenu(
player=player, player_repository=player_repository, score=score)
player=player, player_service=player_service, score=score)
game_over_menu = GameOverMenu(level)
renderer = Renderer(
level=level,
Expand All @@ -47,4 +47,5 @@ def main():


if __name__ == "__main__":
initialize_db()
main()
Empty file added src/services/__init__.py
Empty file.
19 changes: 19 additions & 0 deletions src/services/player_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from datetime import datetime
from models.player import Player
from repositories.player_repository import PlayerRepository


class PlayerService:
def __init__(self, player_repository: PlayerRepository):
self._player_repository = player_repository

def player_login(self, name: str) -> Player:
now = datetime.now().timestamp()
player = self._player_repository.find_player_by_name(name)
if player is None:
player = self._player_repository.add_player(
Player(name=name, last_login=now))
else:
player.set_login_time(now)
self._player_repository.update_player(player)
return player
13 changes: 13 additions & 0 deletions src/services/score_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from datetime import datetime
from models.score import Score
from repositories.score_repository import ScoreRepository


class ScoreService:
def __init__(self, score_repository: ScoreRepository):
self._score_repository = score_repository

def add_score(self, score: Score) -> Score:
score.set_timestamp(datetime.now().timestamp())
self._score_repository.add_score(score)

33 changes: 17 additions & 16 deletions src/tests/game/level_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from models.score import Score
from repositories.score_repository import ScoreRepository
from db_connection import get_db_connection
from services.score_service import ScoreService
from utils import normalize


Expand All @@ -19,8 +20,8 @@
class TestLevelWithoutEnemy(unittest.TestCase):
def setUp(self):
self.score = Score(value=0, player_id=5)
self.score_repo = ScoreRepository(get_db_connection())
self.level = Level(TEST_MAP, self.score, self.score_repo)
self.score_service = ScoreService(score_repository=ScoreRepository(get_db_connection()))
self.level = Level(TEST_MAP, self.score, self.score_service)

def _move_pac(self, direction, times=1):
loops = 0
Expand Down Expand Up @@ -50,13 +51,13 @@ def test_collecting_nuggets_increases_score(self):
self.assertEqual(self.score.value, 2)

def test_nuggets_are_removed_from_group(self):
self.assertEqual(len(self.level.nuggets), 15)
self.assertEqual(len(self.level._nuggets), 15)
self._move_pac(pygame.K_LEFT)
self._move_pac(pygame.K_UP)
self.assertEqual(len(self.level.nuggets), 13)
self.assertEqual(len(self.level._nuggets), 13)

def test_level_is_finished_when_all_nuggets_are_collected(self):
self.assertEqual(len(self.level.nuggets), 15)
self.assertEqual(len(self.level._nuggets), 15)
self.assertEqual(self.level.is_finished, False)
self._move_pac(pygame.K_LEFT, 2)
self._move_pac(pygame.K_DOWN)
Expand All @@ -65,7 +66,7 @@ def test_level_is_finished_when_all_nuggets_are_collected(self):
self._move_pac(pygame.K_LEFT, 3)
self._move_pac(pygame.K_UP, 3)
self._move_pac(pygame.K_RIGHT, 3)
self.assertEqual(len(self.level.nuggets), 0)
self.assertEqual(len(self.level._nuggets), 0)
self.assertEqual(self.level.is_finished, True)


Expand All @@ -80,9 +81,9 @@ def test_level_is_finished_when_all_nuggets_are_collected(self):
class TestLevelWithEnemy(unittest.TestCase):
def setUp(self):
self.score = Score(value=0)
self.score_repo = ScoreRepository(get_db_connection())
self.level = Level(TEST_MAP_WITH_ENEMY, self.score, self.score_repo)
self.enemy = [x for x in self.level.enemies][0]
self.score_service = ScoreService(score_repository=ScoreRepository(get_db_connection()))
self.level = Level(TEST_MAP_WITH_ENEMY, self.score, self.score_service)
self.enemy = [x for x in self.level._enemies][0]

def _move_pac(self, direction, times=1):
loops = 0
Expand All @@ -93,17 +94,17 @@ def _move_pac(self, direction, times=1):
def test_enemies_can_move(self):
self.assertEqual(self.enemy.rect.x, normalize(1))
self.assertEqual(self.enemy.rect.y, normalize(1))
self.enemy.move(self.level.walls, Direction.RIGHT)
self.enemy.move(self.level.walls, Direction.RIGHT)
self.enemy.move(self.level._walls, Direction.RIGHT)
self.enemy.move(self.level._walls, Direction.RIGHT)
self.assertEqual(self.enemy.rect.x, normalize(3))
self.assertEqual(self.enemy.rect.y, normalize(1))

def test_enemies_cannot_move_through_walls(self):
self.assertEqual(self.enemy.rect.x, normalize(1))
self.assertEqual(self.enemy.rect.y, normalize(1))
self.enemy.move(self.level.walls, Direction.RIGHT)
self.enemy.move(self.level.walls, Direction.UP)
self.enemy.move(self.level.walls, Direction.UP)
self.enemy.move(self.level._walls, Direction.RIGHT)
self.enemy.move(self.level._walls, Direction.UP)
self.enemy.move(self.level._walls, Direction.UP)
self.assertEqual(self.enemy.rect.x, normalize(2))
self.assertEqual(self.enemy.rect.y, normalize(1))

Expand All @@ -114,8 +115,8 @@ def test_life_is_lost_when_pac_moves_into_enemy(self):

def test_life_is_lost_when_enemy_moves_into_pac(self):
self.assertEqual(self.level.pac.lives, 3)
self.enemy.move(self.level.walls, Direction.RIGHT)
self.enemy.move(self.level.walls, Direction.RIGHT)
self.enemy.move(self.level._walls, Direction.RIGHT)
self.enemy.move(self.level._walls, Direction.RIGHT)
self.level.do_update() # to check collisions
self.assertEqual(self.level.pac.lives, 2)

Expand Down

0 comments on commit 7215cfc

Please sign in to comment.