Ce modeste programme permet de créer une représentation graphique des tables de
multiplication. C'est lorsque j'ai découvert la vidéo faîte par le vidéaste
de la chaîne Micmaths sur youtube que j'ai eu l'envie de le recréer moi-même. J'ai choisi d'utiliser la bibliothéque pygame pour concevoir la GUI de ce programme. Et comme d'habitude, je n'ai pas utilisé la POO.
-------------------------------------------------------------------
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#############################
##########08/06/16###########
#############################
#from pygame import display, event, init, key, font, time
import pygame
from pygame.locals import *
from pygame.draw import circle, line
from math import cos, sin, pi
from random import randint
from os import popen
def getSystemResolutionOnLinux():
screen = popen("xrandr -q -d :0").readlines()[0]
tmp = screen.split()
return int( tmp[7] ), int( tmp[9][:-1] )
def create_points(bg, pc, modulo):
dtheta = 2 * pi / modulo
alpha = 0
for i in range(modulo):
alpha = dtheta * i
pc[i] = [ POS_CIRCLE[X] + int( R * sin(alpha) ) , POS_CIRCLE[Y] - int( R * cos(alpha) ) ]
if ( i + 1 ) % ( modulo // 51 + 1 ) == 0 :#pour aérer le dessin (+ beau)
circle(bg, BROWN, pc[i], R_, 0)
def create_texts(bg, texts, pos_texts, pc, modulo):
dtheta = 2 * pi / modulo
alpha = 0
for i in range(modulo):
if ( i + 1 ) % ( modulo // 51 + 1 ) == 0 :#pour aérer le dessin (+ beau)
alpha = dtheta * i
pos_texts[i].centerx = pc[i][X] + int( EPS * sin(alpha) )
pos_texts[i].centery = pc[i][Y] - int( EPS * cos(alpha) )
bg.blit(texts[i], pos_texts[i])
def create_lines(bg, pc, table, modulo):
x = 0.0
for i in range(modulo):
x = table * i
x %= modulo
line(bg, GREEN, pc[i], pos_arriv(x, float(modulo)), 1)
def pos_arriv(b, modulo):
x = float(POS_CIRCLE[X]) + R * sin( b / modulo * 2 * pi )
y = float(POS_CIRCLE[Y]) - R * cos( b / modulo * 2 * pi )
return ( int(round(x)) , int(round(y)) )
def init(texts, pos_texts, textsPara, pos_textsPara, pos_circles, font, modulo, tps, type_var, pause, var):
textsPara += [ font.render( "variable : " + str(TYPE_VAR[type_var]), 1, BLACK) ]
textsPara += [ font.render( "pause = " + str(pause), 1, BLACK) ]
textsPara += [ font.render( "f = " + str( 1 / tps[DELAY][type_var] * 1e3 ) + " Hz", 1, BLACK) ]
textsPara += [ font.render( "sens : " + str(SENS[var]), 1, BLACK) ]
for i in range(len(textsPara)) :
pos_textsPara += [ textsPara[i].get_rect() ]
pos_textsPara[i].x = 0.02 * WIDTH_SC
pos_textsPara[i].y = ( 0.02 + i * 0.05 ) * HEIGH_SC
for i in range(modulo):
pos_circles += [ [0,0] ]
texts += [ font.render(str(i), 1, BLACK) ]
pos_texts += [ texts[i].get_rect() ]
pos_texts[i].centerx = 0
pos_texts[i].centery = 0
def reinit(texts, pos_texts, pos_circles, font, modulo):
if len(pos_circles) < modulo:
pos_circles += [ [0,0] ]
texts += [ font.render(str(len(texts)), 1, BLACK) ]
pos_texts += [ texts[-1].get_rect() ]
pos_texts[-1].centerx = 0
pos_texts[-1].centery = 0
else:
pos_circles = pos_circles[:-1]
texts = texts[:-1]
pos_texts = pos_texts[:-1]
def reinitFont(bg, text_title, textpos, texts, font, table, modulo):
text_title = font.render("Table de " + str(table) + " modulo " + str(modulo), 1, BLACK)
textpos = text_title.get_rect()
textpos.centerx = bg.get_rect().centerx
textpos.centery = bg.get_rect().centery
bg.fill(WHITE)
bg.blit(text_title, textpos)
def reinitFontPara(bgFont, textsPara, pos_textsPara, font, tps, type_var, pause, var):
textsPara[0] = font.render( "variable : " + str(TYPE_VAR[type_var]), 1, BLACK)
textsPara[1] = font.render( "pause = " + str(pause), 1, BLACK)
textsPara[2] = font.render( "f = " + str( 1 / tps[DELAY][type_var] * 1e3 ) + " Hz", 1, BLACK)
textsPara[3] = font.render( "sens : " + str(SENS[var]), 1, BLACK)
bgFont.fill(WHITE)
for i in range(len(textsPara)) :
bgFont.blit(textsPara[i], pos_textsPara[i])
def main():
#init var
table = randint(20,500) * 10e-1
modulo = randint(100,119)
start = True
pos_circles = []
texts = []
textsPara = []
pos_texts = []
pos_textsPara = []
tps = [ 0.0 , 0.0 , [ 20.0 , 100.0 ] ]
pause = False
var = INCREASE
type_var = MODULO
# Initialisation de la fenêtre d'affichage
pygame.init()
screen = pygame.display.set_mode((WIDTH_SC, HEIGH_SC))
pygame.display.set_caption("Dessiner les tables de multiplication")
pygame.key.set_repeat (500, 30)
# Remplissage de l'arrière-plan
bg = pygame.Surface(screen.get_size())
bg.fill(WHITE)
# Remplissage de l'arrière-plan font
bgFont = pygame.Surface((WIDTH_SC * 0.22, HEIGH_SC * 0.22))
bgFont.fill(WHITE)
# Affichage d'un texte
font = pygame.font.SysFont("arial", FONT_SIZE)
text_title = font.render("Table de " + str(table) + " modulo " + str(modulo), 1, BLACK)
textpos = text_title.get_rect()
textpos.centerx = bg.get_rect().centerx
textpos.centery = bg.get_rect().centery
bg.blit(text_title, textpos)
init(texts, pos_texts, textsPara, pos_textsPara, pos_circles, font, modulo, tps, type_var, pause, var)
reinitFontPara(bgFont, textsPara, pos_textsPara, font, tps, type_var, pause, var)
# Boucle d'évènements
while 1:
tps[PRES] = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
elif event.type == KEYDOWN and (event.unicode == 'x' or event.unicode == 'X') and 1 < modulo:
modulo -= 1
reinitFont(bg, text_title, textpos, texts, font, table, modulo)
reinit(texts, pos_texts, pos_circles, font, modulo)
start = True
elif event.type == KEYDOWN and (event.unicode == 'c' or event.unicode == 'C'):
modulo += 1
reinitFont(bg, text_title, textpos, texts, font, table, modulo)
reinit(texts, pos_texts, pos_circles, font, modulo)
start = True
elif event.type == KEYDOWN and (event.unicode == 'q' or event.unicode == 'Q'):
table -= 1.0
reinitFont(bg, text_title, textpos, texts, font, table, modulo)
start = True
elif event.type == KEYDOWN and ( event.unicode == 's' or event.unicode == 'S' ) :
table -= 0.01
reinitFont(bg, text_title, textpos, texts, font, table, modulo)
start = True
elif event.type == KEYDOWN and ( event.unicode == 'd' or event.unicode == 'D' ) :
table += 0.01
reinitFont(bg, text_title, textpos, texts, font, table, modulo)
start = True
elif event.type == KEYDOWN and (event.unicode == 'f' or event.unicode == 'F'):
table += 1.0
reinitFont(bg, text_title, textpos, text, font, table, modulo)
start = True
elif ( event.type == MOUSEBUTTONDOWN and event.button == MB_MIDDLE ) or ( event.type == KEYDOWN and event.key == K_SPACE ) :
if pause:
pause = False
else:
pause = True
reinitFontPara(bgFont, textsPara, pos_textsPara, font, tps, type_var, pause, var)
start = True
elif ( event.type == MOUSEBUTTONDOWN and event.button == MB_RIGHT ) or ( event.type == KEYDOWN and event.key == K_BACKSPACE ) :
if var:
var = DECREASE
else:
var = INCREASE
reinitFontPara(bgFont, textsPara, pos_textsPara, font, tps, type_var, pause, var)
start = True
elif ( event.type == MOUSEBUTTONDOWN and event.button == MB_LEFT ) or ( event.type == KEYDOWN and ( event.unicode == 't' or event.unicode == 'T' ) ) :
if type_var == TABLE :
type_var = MODULO
else:
type_var = TABLE
reinitFontPara(bgFont, textsPara, pos_textsPara, font, tps, type_var, pause, var)
start = True
elif ( event.type == MOUSEBUTTONDOWN and event.button == MBSW_UP ) :#ajout d'un hertz
if 10.1 < tps[DELAY][type_var] :
tps[DELAY][type_var] = tps[DELAY][type_var] / ( 1.0 + tps[DELAY][type_var] * 1e-3 )
reinitFontPara(bgFont, textsPara, pos_textsPara, font, tps, type_var, pause, var)
start = True
elif ( event.type == MOUSEBUTTONDOWN and event.button == MBSW_DOWN ) :
if tps[DELAY][type_var] < 999.9 :
tps[DELAY][type_var] = tps[DELAY][type_var] / ( 1.0 - tps[DELAY][type_var] * 1e-3 )
reinitFontPara(bgFont, textsPara, pos_textsPara, font, tps, type_var, pause, var)
start = True
if not(pause) and ( tps[DELAY][type_var] <= tps[PRES] - tps[PAST] ):
if type_var == TABLE:
if var == DECREASE:
table -= 0.01
else:
table += 0.01
else:
if var == DECREASE:
if modulo != 1:
modulo -= 1
else:
pause = True
else:
modulo += 1
reinit(texts, pos_texts, pos_circles, font, modulo)
reinitFont(bg, text_title, textpos, texts, font, table, modulo)
start = True
tps[PAST] = tps[PRES]
if start == True:
if not pause :
circle(bg, BRIGHTBLUE, POS_CIRCLE, R, THICKNESS)
create_points(bg, pos_circles, modulo)
create_lines(bg, pos_circles, table, modulo)
create_texts(bg, texts, pos_texts, pos_circles, modulo)
screen.blit(bg, (0, 0))
screen.blit(bgFont, (0, 0))
pygame.display.flip()
start = False
#############################
#########constantes##########
#############################
WIDTH_SC = getSystemResolutionOnLinux()
HEIGH_SC = int( WIDTH_SC[1] * 0.9 )
WIDTH_SC = int( WIDTH_SC[0] * 0.9 )
#Mouse Button, Scroll Wheel
MB_LEFT, MB_MIDDLE, MB_RIGHT, MBSW_UP, MBSW_DOWN = 1, 2, 3, 4, 5
R = int( HEIGH_SC * 0.45 )
R_ = int( 4 * WIDTH_SC / 1366 )
POS_CIRCLE = (WIDTH_SC/2, HEIGH_SC/2)
THICKNESS = 1
FONT_SIZE = int( 32 * WIDTH_SC / 1366 )
EPS = int( 30 * WIDTH_SC / 1366 )
# R G B
WHITE = (250, 250, 250)
BLACK = ( 10, 10, 10)
GREEN = ( 0, 155, 0)
BRIGHTBLUE = ( 0, 50, 255)
BROWN = (174, 94, 0)
#############################
########enumerations#########
#############################
PAST, PRES, DELAY = 0, 1, 2
INCREASE, DECREASE = 1, 0
TABLE, MODULO = 0, 1
X, Y = 0, 1
#############################
########dictionnaires########
#############################
TYPE_VAR = { TABLE : "TABLE" , MODULO : "MODULO" }
SENS = { DECREASE : "<-" , INCREASE : "->" }
if __name__ == '__main__' : main()
-------------------------------------------------------------------
Prise en main :
q : table -= 1.00
s : table -= 0.01
d : table += 0.01
f : table += 1.00
x : modulo -= 1
c : modulo += 1
clique molette/barre d'espace : arrêter/reprendre l'animation
clique droit/backspace : incrémentation/desincrémentation
clique gauche/t : variation de la valeur de la table/modulo
molette haut/bas : augmenter/diminuer la vitesse de l'animation (linéaire)
possible de réitérer une commande en restant appuyé sur une touche
-------------------------------------------------------------------
vidéo de Micmaths à ce sujet :
https://www.youtube.com/watch?v=-X49VQgi86E
et de Mathologer aussi :
https://www.youtube.com/watch?v=qhbuKbxJsk8
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.