Python Game 🎮 v1.0 for NumWorks, all models.
By Ilyas R. May 2023.
A free project carried out as part of the computer science specialty education.
Learn more about Breakout on: nsi.xyz/breakout (FR)
Breakout v1.0 - 09/05/2023:
- Initial version
from kandinsky import fill_rect as rec, draw_string as txt, get_pixel as get_p from ion import keydown from time import sleep # Breakout 1.0 NumWorks, 09.04.2023 # Par Ilyas R. # https://nsi.xyz/breakout <3 dark_c, light_c, bright_c, game_c, void_c = (40,)*3, (142,)*3, (242,)*3, (148, 113, 222), (255,)*3 red, orange, yellow, green = (240, 160, 160), (240, 200, 160), (240, 240, 160), (200, 240, 200) p_size = 40 p_speed = 3 p_x, p_y = 160, 210 p_color = bright_c b_size = 7 b_dir = [2, -2] b_pos = [160, 180] br_width = 30 br_height = 15 game_speed = 0.01 game_state = "IN_MENU" chars = (121579, 186351, 234191, 188271, 187117, 252783, 252781, 74903) points = {"red": 100, "orange": 80, "yellow": 60, "green": 20} stage, score, pv = 1, 0, 3 level = "" cuboids = [] def menu(): rec(0, 0, 320, 222, dark_c) rec(0, 200, 320, 22, game_c) for k in range(len(chars)): # Display method inspired by @riko_schraf for j in range(19): if chars[k] >> j & 1 == 1: rec(110 + 12 * k + (j % 3) * 3, 40 + (j // 3) * 3, 3, 3, light_c) txt("Score: " + str(score), 160-5*(7+len(max(str(score), str(stage)))), 70, bright_c, dark_c) txt("Stage: " + str(stage), 160-5*(7+len(max(str(score), str(stage)))), 90, bright_c, dark_c) txt("Lives: " + str(pv), 160-5*(7+len(max(str(score), str(stage)))), 110, bright_c, dark_c) if pv > 0: txt("Press OK to play", 80, 150, bright_c, dark_c) else: txt("GAME OVER", 115, 150, bright_c, dark_c) txt("Gameplay by nsi.xyz/breakout", 20, 202, bright_c, game_c) def pad(size, move=0): rec(p_x + move + move * (size // 2), p_y, move * p_speed, 3, dark_c) rec(p_x - size // 2, p_y, size, 3, p_color) def level_generator(stg): lvl = "".join([" " for _ in range(10)])+"*"*(stg//11+1)*10 col = set() for i in (2, 3, 5, 7): if not stg % i: for j in range(i, 10, i): col.add(j) for i in range(stg // 11 + 2): for j in range(10): if j in col: lvl = lvl[:i * 10 + j] + " " + lvl[i * 10 + j + 1:] return lvl def level_constructor(): global level, cuboids rec(0, 0, 320, 222, dark_c) level = level_generator(stage) for i in range(len(level)): if level[i] == "*": rec(1 + (br_width + 2) * (i % 10), 1 + (br_height + 2) * (i // 10), br_width, br_height, set_color(i // 10)) cuboids = [[[1+(br_width+2)*(i % 10), 1+(br_height+2)*(i//10)], [1 + (br_width + 2) * (i % 10) + br_width, 1 + (br_height + 2) * (i // 10) + br_height]] if level[i] == "*" else [] for i in range(len(level))] cuboids += (((0, 0), (0, 222)), ((0, 0), (320, 0)), ((320, 0), (320, 222))) def set_color(line): if line in (0, 1): return red elif line in (2, 3): return orange elif line in (4, 5): return yellow else: return green def speed(stg, hb): return max(0.01-(hb*10**-4)-((stg-1)*10**-5), 0) def new_level(): global game_state, b_pos, p_x, p_y, b_dir, game_speed b_pos, b_dir = [160, 180], [2, -2] p_x, p_y = 160, 210 game_state = "IN_LEVEL" level_constructor() game_speed = speed(stage, len(cuboids)-sum([1 if not i else 0 for i in cuboids])-3) pad(p_size) engine() def velocity(x): vec = [(-2, -1), (-2, -2), (-1, -2), (1, -2), (2, -2), (2, -1)] i = min(round((x-p_x)/(p_size/2)*3+3), len(vec)-1) b_dir[0], b_dir[1] = vec[i] def collision(x, y): global game_state if p_y-abs(b_dir[1])-b_size//2 <= y <= p_y+abs(b_dir[1])-b_size//2 and p_x-p_size//2 <= x <= p_x+p_size//2: velocity(x) rec(p_x - p_size // 2, p_y, p_size, 3, p_color) elif y >= 222: game_state = "G_OVER" return elif entity_around(x, y, 15): collision_manager(x, y) def entity_around(x, y, radius): if get_p(x, y-radius) != dark_c or get_p(x-radius, y-radius) != dark_c or get_p(x+radius, y-radius) != dark_c: return True if get_p(x-radius, y) != dark_c or get_p(x+radius, y) != dark_c: return True if get_p(x, y+radius) != dark_c or get_p(x-radius, y+radius) != dark_c or get_p(x+radius, y+radius) != dark_c: return True return False def collision_manager(x, y): for i in range(len(cuboids)): if cuboids[i] and (i < cuboids[i][0][1]+10 or len(cuboids)-3 <= i <= len(cuboids)): h = b_size//2 x_s, y_s, x_e, y_e = cuboids[i][0][0]-h, cuboids[i][0][1]-h, cuboids[i][1][0]+h, cuboids[i][1][1]+h if y_s-abs(b_dir[1]) <= y <= y_s+abs(b_dir[1]) and x_s <= x <= x_e: b_dir[1] = -b_dir[1] destroy_brick(i) elif x_s-abs(b_dir[0]) <= x <= x_s+abs(b_dir[0]) and y_s <= y <= y_e: b_dir[0] = -b_dir[0] destroy_brick(i) elif x_e-abs(b_dir[0]) <= x <= x_e+abs(b_dir[0]) and y_s <= y <= y_e: b_dir[0] = -b_dir[0] destroy_brick(i) elif y_e-abs(b_dir[1]) <= y <= y_e+abs(b_dir[1]) and x_s <= x <= x_e: b_dir[1] = -b_dir[1] destroy_brick(i) def get_color(i): li = i//10 return "red" if li in (0, 1) else "orange" if li in (2, 3) else "yellow" if li in (4, 5) else "green" def destroy_brick(i): global score, game_speed if type(cuboids[i]) == list: cuboids[i] = [] rec(1 + (br_width + 2) * (i % 10), 1 + (br_height + 2) * (i // 10), br_width, br_height, dark_c) score += points[get_color(i)] game_speed = speed(stage, len(cuboids) - sum([1 if not i else 0 for i in cuboids]) - 3) def ball(x, y, width, height, old=0): rec(x - width // 2, y - height // 2, width, height, dark_c if old else void_c) for i in [(-1, -1,), (-1, 1), (1, -1), (1, 1)]: rec(x + i[0] * (width // 2), y + i[1] * (height // 2), 1, 1, dark_c) def ball_manager(): old_ball_pos = (b_pos[0], b_pos[1]) ball(b_pos[0], b_pos[1], b_size, b_size) b_pos[0] += b_dir[0] b_pos[1] += b_dir[1] collision(b_pos[0], b_pos[1]) sleep(game_speed) ball(old_ball_pos[0], old_ball_pos[1], b_size, b_size, 1) def engine(): global p_x, pv, game_state, stage while game_state not in ("L_CLEAR", "G_OVER"): if keydown(0) and p_x > b_size + p_size // 2: p_x -= p_speed pad(p_size, 1) if keydown(3) and p_x < 320 - b_size - p_size // 2: p_x += p_speed pad(p_size, -1) ball_manager() if len(cuboids)-sum([1 if not i else 0 for i in cuboids]) == 3: game_state = "L_CLEAR" stage += 1 pv += 1 pv -= 1 if game_state == "G_OVER" else 0 menu() def refresh_scoreboard(): txt("Stage: " + str(stage), 160-5*(7+len(max(str(score), str(stage)))), 90, bright_c, dark_c) def breakout(): global stage menu() last_key = -1 while not keydown(51): if keydown(4) or keydown(52): new_level() if keydown(39) and last_key != 39: stage += 10 last_key = 39 if keydown(45) and last_key != 45: stage += 1 last_key = 45 if keydown(40) and last_key != 40: stage = max(stage-10, 1) last_key = 40 if keydown(46) and last_key != 46: stage = max(stage-1, 1) last_key = 46 if keydown(39) or keydown(45) or keydown(40) or keydown(46): refresh_scoreboard() if not (keydown(39) or keydown(45) or keydown(40) or keydown(46)): last_key = -1 if pv == 0: menu() return breakout()