Skip to content

Commit 0bfe61b

Browse files
committed
redis rewritten as a real TP
1 parent ad7b26d commit 0bfe61b

File tree

11 files changed

+1776
-476
lines changed

11 files changed

+1776
-476
lines changed

notebooks/tps/redis/.teacher/README-redis-corrige-nb.md

Lines changed: 234 additions & 102 deletions
Large diffs are not rendered by default.
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#!/usr/bin/env python
2+
3+
from argparse import ArgumentParser
4+
5+
import pygame as pg
6+
from pygame.locals import QUIT
7+
8+
from redis import Redis
9+
10+
from screen import Screen
11+
from player import Player
12+
from others import Others
13+
14+
# 2 differents speeds
15+
#
16+
# if we do too few frames per second,
17+
# after another player moves, we may see it very late
18+
# (worst case: if FRAME_RATE is 4, then the delay may reach 250ms)
19+
#
20+
# so, we set our frame rate higher; BUT on the other hand
21+
# this also results in the player moving too fast
22+
# so FRAMES_PER_MOVE is defined so we move our player only once every n frames
23+
24+
# how often we redisplay the screen
25+
FRAME_RATE = 10
26+
# we move our player that many times slower
27+
FRAMES_PER_MOVE = 3
28+
29+
30+
def main():
31+
32+
parser = ArgumentParser()
33+
parser.add_argument("-s", "--server", default=None,
34+
help="IP adddress for the redis server")
35+
parser.add_argument("-a", "--auto-move", action="store_true",
36+
help="auto move")
37+
parser.add_argument("name")
38+
args = parser.parse_args()
39+
40+
# player's name as provided on the command line
41+
local_player_name = args.name
42+
pg.display.set_caption(f"game: {local_player_name}")
43+
44+
45+
screen = Screen()
46+
W, H = screen.size()
47+
48+
clock = pg.time.Clock()
49+
50+
redis_server = Redis(args.server, decode_responses=True)
51+
52+
player = Player(local_player_name, H, W, redis_server)
53+
player.join()
54+
55+
others = Others(redis_server)
56+
57+
# ask the redis server where the other players are
58+
players = others.fetch_all_players()
59+
screen.display(players)
60+
61+
# type 'a' to toggle auto move
62+
auto_move = args.auto_move
63+
64+
counter = 0
65+
while True:
66+
# sync with the frame rate
67+
clock.tick(FRAME_RATE)
68+
# get the position of other players
69+
players = others.fetch_all_players()
70+
71+
# move the local player
72+
# actually do all this only once every FRAMES_PER_MOVE frames
73+
counter += 1
74+
if counter % FRAMES_PER_MOVE == 0:
75+
counter = 0
76+
if auto_move:
77+
player.random_move()
78+
79+
for event in pg.event.get():
80+
if (event.type == QUIT or
81+
(event.type == pg.KEYDOWN and event.key == pg.K_q)):
82+
player.leave()
83+
return
84+
elif event.type == pg.KEYDOWN and event.key == pg.K_a:
85+
auto_move = not auto_move
86+
else:
87+
player.handle_event(event)
88+
89+
# redisplay accordingly every frame
90+
screen.display(players)
91+
92+
93+
if __name__ == '__main__':
94+
main()
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import random
2+
import json
3+
4+
import pygame as pg
5+
6+
def random_color():
7+
return [random.randint(0, 255) for _ in range(3)]
8+
9+
def random_move():
10+
moves = [(x, y) for x in (-1, 0, 1) for y in (-1, 0, 1) if abs(x+y) == 1]
11+
return random.choice(moves)
12+
13+
14+
15+
class Player:
16+
"""
17+
manage the local player, and broadcast
18+
its position to the redis server
19+
"""
20+
21+
def __init__(self, name, width, height, redis_server):
22+
"""
23+
name is the name of the local player
24+
"""
25+
self.name = name
26+
self.width = width
27+
self.height = height
28+
self.position = [ random.randint(0, self.width-1),
29+
random.randint(0, self.height-1)]
30+
self.color = random_color()
31+
#
32+
self.redis_server = redis_server
33+
34+
35+
def join(self):
36+
"""
37+
add local name to database
38+
with a random color
39+
"""
40+
self.redis_server.hset(
41+
self.name,
42+
mapping = {
43+
'color' : json.dumps(self.color),
44+
'position': json.dumps(self.position),
45+
})
46+
47+
48+
def leave(self):
49+
"""
50+
remove local name from database
51+
"""
52+
self.redis_server.delete(self.name)
53+
54+
55+
def random_move(self):
56+
self.move(*random_move())
57+
58+
def move(self, dx, dy):
59+
self.position[0] += dx
60+
self.position[0] %= self.width
61+
self.position[1] += dy
62+
self.position[1] %= self.height
63+
self.redis_server.hset(self.name, 'position',
64+
json.dumps(self.position))
65+
66+
67+
def handle_event(self, event):
68+
if event.type == pg.KEYDOWN:
69+
match event.key:
70+
case pg.K_UP:
71+
self.move(0, -1)
72+
case pg.K_DOWN:
73+
self.move(0, 1)
74+
case pg.K_RIGHT:
75+
self.move(1, 0)
76+
case pg.K_LEFT:
77+
self.move(-1, 0)
78+
case pg.K_c:
79+
self.color = random_color()
80+
self.redis_server.hset(self.name, 'color',
81+
json.dumps(self.color))
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import pygame
2+
3+
from itertools import product
4+
5+
# la taille du jeu en nombre de cellules
6+
BOARD_SIZE = (20, 20)
7+
BOARD_WIDTH, BOARD_HEIGHT = BOARD_SIZE
8+
9+
# la taille d'une cellule en nombre de pixels
10+
CELL_SIZE = (15, 15)
11+
CELL_WIDTH, CELL_HEIGHT = CELL_SIZE
12+
13+
BLACK = (0, 0, 0)
14+
WHITE = (255, 255, 255)
15+
16+
17+
class Screen:
18+
19+
pygame_inited = False
20+
21+
def __init__(self):
22+
23+
if not Screen.pygame_inited:
24+
pygame.init()
25+
# pygame.display.set_caption("multi-player")
26+
Screen.pygame_inited = True
27+
28+
self.screen = pygame.display.set_mode(
29+
(BOARD_WIDTH*CELL_WIDTH, BOARD_HEIGHT*CELL_HEIGHT))
30+
31+
def size(self):
32+
return BOARD_WIDTH, BOARD_HEIGHT
33+
34+
def draw_cell(self, board_x, board_y, color=WHITE):
35+
screen_x, screen_y = CELL_WIDTH * board_x, CELL_HEIGHT * board_y
36+
for x, y in product(range(CELL_WIDTH), range(CELL_HEIGHT)):
37+
screen_coords = screen_x + x, screen_y + y
38+
self.screen.set_at(screen_coords, color)
39+
40+
def display(self, players):
41+
"""
42+
players is an iterable of dictionaries
43+
'color' -> [r g b], 'position' -> [x, y]
44+
"""
45+
self.screen.fill(BLACK)
46+
for player in players:
47+
x, y = player['position']
48+
color = player['color']
49+
self.draw_cell(x, y, color)
50+
pygame.display.update()

notebooks/tps/redis/ARTEFACTS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
requirements.txt
2+
game.py
3+
player.py
4+
screen.py

0 commit comments

Comments
 (0)