Skip to content

Commit 4f52727

Browse files
committed
Add basic title card.
1 parent e9ea707 commit 4f52727

6 files changed

Lines changed: 131 additions & 27 deletions

File tree

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include src/escape/img/*

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
name='kitty-escape',
77
packages=find_packages(where='src'),
88
package_dir={'': 'src'},
9+
include_package_data=True,
910
entry_points={
1011
'console_scripts': ['kitty-escape = escape.main:main'],
1112
},

src/escape/img/title_card.png

69 KB
Loading

src/escape/main.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@
55

66
def main():
77
pygame.init()
8-
pygame.display.set_mode(state.WINSIZE)
8+
screen = pygame.display.set_mode(state.WINSIZE)
99
pygame.display.set_caption('Kitty Escape')
10-
game_state = state.GameState()
11-
12-
while game_state.active:
13-
game_state.handle_events(pygame.event.get())
10+
state.TitleCard(screen).run()
11+
state.Game(screen).run()
1412

1513

1614
if __name__ == '__main__':

src/escape/state.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,30 @@
11
"""Game state."""
22

3+
import abc
34
import pygame
45
from pygame.locals import *
6+
import os
57

68

79
WINSIZE = (1024, 576)
10+
_RED = (200, 25, 25)
11+
_BLACK = (0, 0, 0)
812

913

1014
def _keypressed(event, key):
1115
return event.type == KEYDOWN and event.key == key
1216

1317

14-
class GameState:
18+
class GameState(abc.ABC):
1519

16-
def __init__(self):
20+
def __init__(self, screen):
21+
self.screen = screen
1722
self.active = True
23+
self.draw()
24+
25+
@abc.abstractmethod
26+
def draw(self):
27+
pass
1828

1929
def handle_events(self, events):
2030
for event in events:
@@ -28,7 +38,30 @@ def handle_quit(self, event):
2838
def handle_fullscreen(self, event):
2939
if not _keypressed(event, K_f):
3040
return
31-
if pygame.display.get_surface().get_flags() & FULLSCREEN:
41+
if self.screen.get_flags() & FULLSCREEN:
3242
pygame.display.set_mode(WINSIZE)
3343
else:
3444
pygame.display.set_mode(WINSIZE, FULLSCREEN)
45+
self.draw()
46+
47+
def run(self):
48+
while self.active:
49+
self.handle_events(pygame.event.get())
50+
51+
52+
class TitleCard(GameState):
53+
54+
def draw(self):
55+
path = os.path.join(os.path.dirname(__file__), 'img', 'title_card.png')
56+
img = pygame.image.load(path)
57+
img = pygame.transform.scale(img.convert_alpha(), WINSIZE)
58+
self.screen.fill(_RED)
59+
self.screen.blit(img, (0, 0))
60+
pygame.display.update()
61+
62+
63+
class Game(GameState):
64+
65+
def draw(self):
66+
self.screen.fill(_BLACK)
67+
pygame.display.update()

tests/state_test.py

Lines changed: 90 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from escape import state
44

5+
import pygame
56
from pygame.locals import *
67

78
import unittest
@@ -15,10 +16,44 @@ def __init__(self, typ, key=None):
1516
self.key = key
1617

1718

19+
class MockGame(state.GameState):
20+
21+
def __init__(self, screen):
22+
self.drawn = 0
23+
super().__init__(screen)
24+
25+
def draw(self):
26+
self.drawn += 1
27+
28+
29+
class MockScreen:
30+
31+
def __init__(self):
32+
self.fullscreen = False
33+
34+
def get_flags(self):
35+
return FULLSCREEN if self.fullscreen else 0
36+
37+
def __getattr__(self, name):
38+
return unittest.mock.MagicMock()
39+
40+
1841
class GameStateTest(unittest.TestCase):
1942

2043
def setUp(self):
21-
self.state = state.GameState()
44+
self.state = MockGame(MockScreen())
45+
46+
def mock_set_mode(self, size, fullscreen=False):
47+
del size # unused
48+
self.state.screen.fullscreen = fullscreen
49+
50+
def test_abstract(self):
51+
with self.assertRaises(TypeError):
52+
state.GameState(MockScreen()) # pytype: disable=not-instantiable
53+
54+
def test_basic(self):
55+
self.assertTrue(self.state.active)
56+
self.assertEqual(self.state.drawn, 1)
2257

2358
def test_quit_x(self):
2459
self.assertTrue(self.state.active)
@@ -30,26 +65,62 @@ def test_quit_q(self):
3065
self.state.handle_quit(MockEvent(KEYDOWN, K_q))
3166
self.assertFalse(self.state.active)
3267

33-
@unittest.mock.patch('pygame.display', autospec=True)
34-
def test_fullscreen(self, display_mock):
35-
display_mock.get_surface.return_value.get_flags.return_value = 0
36-
self.state.handle_fullscreen(MockEvent(KEYDOWN, K_f))
37-
display_mock.set_mode.assert_called_once_with(state.WINSIZE, FULLSCREEN)
38-
39-
@unittest.mock.patch('pygame.display', autospec=True)
40-
def test_unfullscreen(self, display_mock):
41-
display_mock.get_surface.return_value.get_flags.return_value = (
42-
FULLSCREEN)
43-
self.state.handle_fullscreen(MockEvent(KEYDOWN, K_f))
44-
display_mock.set_mode.assert_called_once_with(state.WINSIZE)
45-
46-
@unittest.mock.patch('pygame.display', autospec=True)
47-
def test_multiple_events(self, display_mock):
48-
display_mock.get_surface.return_value.get_flags.return_value = 0
49-
self.state.handle_events([MockEvent(KEYDOWN, K_f), MockEvent(QUIT)])
50-
display_mock.set_mode.assert_called_once_with(state.WINSIZE, FULLSCREEN)
68+
def test_fullscreen(self):
69+
self.state.screen.fullscreen = False
70+
with unittest.mock.patch.object(
71+
pygame.display, 'set_mode', self.mock_set_mode):
72+
self.state.handle_fullscreen(MockEvent(KEYDOWN, K_f))
73+
self.assertTrue(self.state.screen.fullscreen)
74+
self.assertEqual(self.state.drawn, 2)
75+
76+
def test_unfullscreen(self):
77+
self.state.screen.fullscreen = True
78+
with unittest.mock.patch.object(
79+
pygame.display, 'set_mode', self.mock_set_mode):
80+
self.state.handle_fullscreen(MockEvent(KEYDOWN, K_f))
81+
self.assertFalse(self.state.screen.fullscreen)
82+
self.assertEqual(self.state.drawn, 2)
83+
84+
def test_multiple_events(self):
85+
self.state.screen.fullscreen = False
86+
with unittest.mock.patch.object(
87+
pygame.display, 'set_mode', self.mock_set_mode):
88+
self.state.handle_events([MockEvent(KEYDOWN, K_f), MockEvent(QUIT)])
89+
self.assertTrue(self.state.screen.fullscreen)
90+
self.assertEqual(self.state.drawn, 2)
5191
self.assertFalse(self.state.active)
5292

93+
def test_run(self):
94+
self.state.screen.fullscreen = False
95+
with unittest.mock.patch.object(
96+
pygame.display, 'set_mode', self.mock_set_mode):
97+
with unittest.mock.patch.object(pygame.event, 'get') as mock_get:
98+
mock_get.return_value = [
99+
MockEvent(KEYDOWN, K_f),
100+
MockEvent(KEYDOWN, K_f),
101+
MockEvent(KEYDOWN, K_q),
102+
]
103+
self.state.run()
104+
self.assertFalse(self.state.screen.fullscreen)
105+
self.assertEqual(self.state.drawn, 3)
106+
self.assertFalse(self.state.active)
107+
108+
109+
class TitleCardTest(unittest.TestCase):
110+
111+
def test_init(self):
112+
with unittest.mock.patch('pygame.display', autospec=True):
113+
with unittest.mock.patch('pygame.image', autospec=True):
114+
with unittest.mock.patch('pygame.transform', autospec=True):
115+
state.TitleCard(MockScreen())
116+
117+
118+
class GameTest(unittest.TestCase):
119+
120+
def test_init(self):
121+
with unittest.mock.patch('pygame.display', autospec=True):
122+
state.Game(MockScreen())
123+
53124

54125
if __name__ == '__main__':
55126
unittest.main()

0 commit comments

Comments
 (0)