I made this little game that tests our language skills. It uses one external module, pinyin
, which can be installed via the command prompt command
pip install pinyin
Here is how it goes:
As you can see from the GIF, the game starts with a random selection of characters for the top boxes, and a pronunciation for each corresponding character for the bottom boxes, shuffled, of course.
Every time the user connects a character with the right pronunciation, the score will increase by 10, and the matching boxes will get disabled. Every time the user connects a character with the wrong pronunciation, the score will decrease by 5.
When all the boxes are disabled, the game resets with another random sample of characters, and the score remain the value it was before all the boxes got disabled.
Here is my code:
import pygame
from random import sample, shuffle, choice
import pinyin
pygame.init()
pygame.font.init()
wn = pygame.display.set_mode((600, 400))
words = '的是不我一有大在人了中到資要可以這個你會好為上來就學交也用能如文時沒說他看提那問生過下請天們所多麼小���得之還'
class Text:
def __init__(self, text, borders, font):
self.font = font
self.color = (255, 255, 0)
self.text = self.font.render(text, True, self.color)
width = self.text.get_width()
height = self.text.get_height()
x, y, w, h = borders
self.pos = x + (w - width) / 2, y + (h - height) / 2
def draw(self):
wn.blit(self.text, self.pos)
class Score:
def __init__(self, pos, font=pygame.font.SysFont("Californian FB", 40)):
self.pos = pos
self.font = font
self.value = 0
self.color = (255, 255, 255)
self.up = 10
self.down = 5
self.potential = 0
def score_up(self):
self.value += 10
def score_down(self):
self.value -= 5
self.potential += 10
def draw(self):
wn.blit(self.font.render(str(self.value), True, self.color), self.pos)
class Box:
def __init__(self, bottom, x, y, w, h, word, font=pygame.font.SysFont("microsoftyaheimicrosoftyaheiui", 23)):
self.rect = pygame.Rect(x, y, w, h)
self.inner_rect = pygame.Rect(x + w * .125, y + h * .125, w * .75, h * .75)
self.box_color = (100, 0, 0)
self.port_color = (50, 0, 0)
self.active_color = (20, 0, 0)
self.disabled = False
self.port = pygame.Rect(x + w / 4, y + h, w / 2, h // 8)
self.word = word
if bottom:
self.port.y -= h + h // 8
word = pinyin.get(word)
self.text = Text(word, (x, y, w, h), font)
def over(self, x, y):
return self.rect.collidepoint(x, y)
def disable(self):
self.disabled = True
self.box_color = (255, 50, 50)
def draw(self, active):
if active:
pygame.draw.rect(wn, self.active_color, self.rect)
pygame.draw.rect(wn, self.box_color, self.inner_rect)
else:
pygame.draw.rect(wn, self.box_color, self.rect)
self.text.draw()
if self.disabled:
return
pygame.draw.rect(wn, self.port_color, self.port)
class Game:
def __init__(self, words, x, y):
self.w = 70
self.h = 50
self.box_x_pad = 30
self.box_y_pad = 120
self.words = words
self.in_boxes = list()
self.out_boxes = list()
self.active_in_box = None
self.active_out_box = None
for i, word in enumerate(words):
in_box = Box(False, x + i * (self.w + self.box_x_pad), y, self.w, self.h, word)
self.in_boxes.append(in_box)
shuffle(words)
for i, word in enumerate(words):
out_box = Box(True, x + i * (self.w + self.box_x_pad), y + self.box_y_pad, self.w, self.h, word)
self.out_boxes.append(out_box)
def won(self):
return all(in_box.disabled for in_box in self.in_boxes)
def draw_lines(self, event):
if self.active_in_box:
if self.active_out_box:
pygame.draw.line(wn, (255, 255, 0), self.active_in_box.port.center, self.active_out_box.port.center, 7)
else:
pygame.draw.line(wn, (255, 255, 0), self.active_in_box.port.center, event.pos, 7)
def draw_boxes(self):
for in_box in self.in_boxes:
in_box.draw(in_box == self.active_in_box)
for out_box in self.out_boxes:
out_box.draw(out_box == self.active_out_box)
bg_color = (200, 0, 0)
game = Game(sample(words, 5), 60, 120)
score = Score((60, 50))
running = True
while running:
wn.fill(bg_color)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
for in_box in game.in_boxes:
if in_box.over(*event.pos) and not in_box.disabled:
game.active_in_box = in_box
break
elif event.type == pygame.MOUSEMOTION:
if game.active_in_box:
for out_box in game.out_boxes:
if out_box.over(*event.pos) and not out_box.disabled:
game.active_out_box = out_box
break
else:
game.active_out_box = None
elif event.type == pygame.MOUSEBUTTONUP:
if game.active_in_box and game.active_out_box:
if game.active_out_box.word == game.active_in_box.word:
game.active_out_box.disable()
game.active_in_box.disable()
score.score_up()
if game.won():
game = Game(sample(words, 5), 60, 120)
else:
score.score_down()
game.active_out_box = game.active_in_box = None
game.draw_lines(event)
game.draw_boxes()
score.draw()
pygame.display.update()
pygame.quit()
I want to improve the efficiency of my code, and improve the DRY concept of my code.