2022-11-23 18:03:16 +00:00
|
|
|
import curses
|
|
|
|
import random
|
|
|
|
import threading
|
|
|
|
import time
|
|
|
|
from math import fabs
|
|
|
|
|
2022-11-24 12:13:45 +00:00
|
|
|
import maze.modules.maze as m1
|
|
|
|
|
2022-11-23 18:03:16 +00:00
|
|
|
quit = threading.Event()
|
|
|
|
|
|
|
|
|
|
|
|
class Scores:
|
2022-11-30 15:57:28 +00:00
|
|
|
"""Class object to take care of score"""
|
|
|
|
|
2022-11-23 19:23:26 +00:00
|
|
|
def __init__(self, screen):
|
2022-11-23 18:03:16 +00:00
|
|
|
self.score = 0
|
2022-11-23 19:23:26 +00:00
|
|
|
self.screen = screen
|
2022-11-23 18:03:16 +00:00
|
|
|
self.collision_count = 0
|
|
|
|
self.speed_multiplier = 0.20
|
|
|
|
self.speed_calc = lambda speed: speed - 0.02 if self.score % 30 == 0 else speed
|
|
|
|
|
|
|
|
def scoreupdate(self):
|
|
|
|
self.score += 10
|
|
|
|
self.collision_count += 1
|
|
|
|
self.speed_multiplier = self.speed_calc(self.speed_multiplier)
|
2022-11-23 19:23:26 +00:00
|
|
|
self.scoreupdater()
|
2022-11-23 18:03:16 +00:00
|
|
|
return self.speed_multiplier
|
|
|
|
|
2022-11-23 19:23:26 +00:00
|
|
|
def scoreupdater(self):
|
2022-11-24 12:13:45 +00:00
|
|
|
y, x = self.screen.getmaxyx()
|
2022-11-23 19:23:26 +00:00
|
|
|
self.screen.addstr(0, x - 5, str(self.score))
|
|
|
|
|
2022-11-23 18:03:16 +00:00
|
|
|
|
|
|
|
class Ball:
|
2022-11-30 15:57:28 +00:00
|
|
|
"""Class object to store ball coordinates, predict ball movement, detect collision"""
|
|
|
|
|
2022-11-23 18:03:16 +00:00
|
|
|
def __init__(self, y, x, screen):
|
|
|
|
self.ball_dx = 1
|
|
|
|
self.ball_dy = 1
|
|
|
|
self.speed_multipliery = random.choice([1, 2])
|
|
|
|
self.speed_multiplierx = random.choice([1, 2])
|
|
|
|
self.ball_dy *= self.speed_multipliery
|
|
|
|
self.ball_dx *= self.speed_multiplierx
|
|
|
|
self.ball_coords = [y // 2, x // 2]
|
|
|
|
self.y = y
|
|
|
|
self.x = x
|
|
|
|
self.y_border = [0, y]
|
|
|
|
self.x_border = [0, x]
|
|
|
|
self.screen = screen
|
|
|
|
|
|
|
|
def move(self):
|
|
|
|
raw_calc_to_movey = lambda y: y + self.ball_dy
|
|
|
|
raw_calc_to_movex = lambda x: x + self.ball_dx
|
|
|
|
raw_movey = raw_calc_to_movey(
|
|
|
|
self.ball_coords[0]
|
|
|
|
) # Gives raw about to move coords without speed alter
|
|
|
|
raw_movex = raw_calc_to_movex(self.ball_coords[1])
|
|
|
|
|
|
|
|
speed_altery = lambda y: int(y / fabs(y)) # Gives unit speed in the current dir
|
|
|
|
speed_alterx = lambda x: int(x / fabs(x))
|
|
|
|
calc_to_movey = (
|
|
|
|
lambda y: y + speed_altery(self.ball_dy)
|
|
|
|
if checky(raw_movey)
|
|
|
|
else y + self.ball_dy
|
|
|
|
) # assign same dir movement coords
|
|
|
|
calc_to_movex = (
|
|
|
|
lambda x: x + speed_alterx(self.ball_dx)
|
|
|
|
if checkx(raw_movex)
|
|
|
|
else x + self.ball_dx
|
|
|
|
)
|
|
|
|
checky = (
|
|
|
|
lambda y: True
|
|
|
|
if (y in self.y_border)
|
|
|
|
or (y >= self.y_border[1])
|
|
|
|
or (y <= self.y_border[0] + 1)
|
|
|
|
else False
|
|
|
|
) # Gives True if out of bound coords
|
|
|
|
checkx = (
|
|
|
|
lambda x: True
|
|
|
|
if (x in self.x_border)
|
|
|
|
or (x >= self.x_border[1] - 1)
|
|
|
|
or (x <= self.x_border[0] + 1)
|
|
|
|
else False
|
|
|
|
)
|
|
|
|
|
|
|
|
actual_game_checky = (
|
|
|
|
lambda y: True if (y <= self.y_border[0]) else False
|
|
|
|
) # Gives true if ball at top
|
|
|
|
|
|
|
|
to_movey = calc_to_movey(self.ball_coords[0]) # Moving here after speed alter
|
|
|
|
to_movex = calc_to_movex(self.ball_coords[1])
|
|
|
|
old_ball = self.ball_coords.copy()
|
|
|
|
collision = False
|
|
|
|
pos = self.screen.instr(to_movey, to_movex, 1).decode("utf-8")
|
|
|
|
if pos == "=" or pos == "[" or pos == "]":
|
|
|
|
collision = True
|
|
|
|
if (
|
|
|
|
actual_game_checky(to_movey) or collision
|
|
|
|
): # Deflect ball if top border/collision
|
|
|
|
self.ball_dy *= -1
|
|
|
|
elif to_movey >= self.y_border[1] and not collision:
|
|
|
|
return [None, None], [None, None], "OVER"
|
|
|
|
if checkx(to_movex):
|
|
|
|
self.ball_dx *= -1
|
|
|
|
self.ball_coords[0] += self.ball_dy
|
|
|
|
self.ball_coords[1] += self.ball_dx
|
|
|
|
if collision:
|
|
|
|
return self.ball_coords, old_ball, "collision"
|
|
|
|
return self.ball_coords, old_ball, "nocollision"
|
|
|
|
|
|
|
|
|
|
|
|
class Player:
|
2022-11-30 15:57:28 +00:00
|
|
|
"""Class object of the paddle"""
|
|
|
|
|
2022-11-23 18:03:16 +00:00
|
|
|
def __init__(self, y, x):
|
|
|
|
self.y = y
|
|
|
|
self.x = x
|
|
|
|
self.paddle = "[=======]"
|
|
|
|
self.paddle_posx = x // 2
|
|
|
|
self.paddle_posy = y - 1 # Top of paddle
|
|
|
|
|
|
|
|
def player_move(self, dir):
|
|
|
|
if dir == "LEFT" and self.paddle_posx > 1:
|
|
|
|
self.paddle_posx -= 1
|
|
|
|
if dir == "RIGHT" and self.paddle_posx + 10 < self.x:
|
|
|
|
self.paddle_posx += 1
|
|
|
|
return self.paddle_posy, self.paddle_posx
|
|
|
|
|
|
|
|
|
|
|
|
def player_movement(screen, player):
|
2022-11-30 15:57:28 +00:00
|
|
|
"""Function to control player movement"""
|
2022-11-23 18:03:16 +00:00
|
|
|
global quit
|
|
|
|
screen.keypad(True)
|
|
|
|
while 1:
|
|
|
|
# f.write("player running\n")
|
|
|
|
if quit.is_set():
|
|
|
|
break
|
|
|
|
old_player_coordsy = player_coordsy = player.paddle_posy
|
|
|
|
old_player_coordsx = player_coordsx = player.paddle_posx
|
|
|
|
key = screen.getch()
|
|
|
|
if key == 27:
|
|
|
|
quit.set()
|
|
|
|
elif key == curses.KEY_LEFT:
|
|
|
|
player_coordsy, player_coordsx = player.player_move("LEFT")
|
|
|
|
elif key == curses.KEY_RIGHT:
|
|
|
|
player_coordsy, player_coordsx = player.player_move("RIGHT")
|
|
|
|
screen.addstr(old_player_coordsy, old_player_coordsx, " ")
|
|
|
|
screen.addstr(player_coordsy, player_coordsx, player.paddle)
|
|
|
|
|
|
|
|
|
|
|
|
def ball_movement(screen, ball, score):
|
2022-11-30 15:57:28 +00:00
|
|
|
"""Function to control ball movement and detect end of game"""
|
2022-11-23 18:03:16 +00:00
|
|
|
y, x = screen.getmaxyx()
|
|
|
|
while 1:
|
|
|
|
# f.write("ball running\n")
|
|
|
|
if quit.is_set():
|
|
|
|
break
|
|
|
|
speed_multi = score.speed_multiplier
|
|
|
|
time.sleep(speed_multi)
|
|
|
|
ball_coords = ball.move()
|
|
|
|
old_ball_posy, old_ball_posx = ball_coords[1]
|
|
|
|
ball_posy, ball_posx = ball_coords[0]
|
|
|
|
collision = ball_coords[2]
|
|
|
|
if collision == "OVER":
|
|
|
|
finalscore = score.score
|
2022-11-30 12:57:18 +00:00
|
|
|
screen.addstr(
|
|
|
|
y // 2 - 1,
|
|
|
|
x // 2 - 3,
|
|
|
|
"GAME OVER!",
|
|
|
|
curses.color_pair(1) | curses.A_BOLD,
|
|
|
|
)
|
|
|
|
screen.addstr(
|
|
|
|
y // 2,
|
|
|
|
x // 2 - 5,
|
|
|
|
"The Score is: " + str(finalscore),
|
|
|
|
curses.color_pair(3) | curses.A_BOLD,
|
|
|
|
)
|
2022-11-27 17:59:24 +00:00
|
|
|
time.sleep(0.25)
|
2022-11-23 18:03:16 +00:00
|
|
|
quit.set()
|
2022-11-27 17:59:24 +00:00
|
|
|
time.sleep(1.75)
|
2022-11-23 18:03:16 +00:00
|
|
|
break
|
|
|
|
elif collision == "collision":
|
|
|
|
score.scoreupdate()
|
|
|
|
screen.addch(old_ball_posy, old_ball_posx, " ")
|
2022-11-27 17:59:24 +00:00
|
|
|
screen.addch(ball_posy, ball_posx, "⬤", curses.color_pair(1) | curses.A_BOLD)
|
2022-11-23 18:03:16 +00:00
|
|
|
screen.refresh()
|
|
|
|
|
|
|
|
|
|
|
|
def main(screen):
|
2022-11-30 15:57:28 +00:00
|
|
|
"""Initialises color pairs, spins up two seperate threads for ball and player"""
|
2022-11-24 12:13:45 +00:00
|
|
|
global quit
|
|
|
|
quit.clear()
|
2022-11-23 18:03:16 +00:00
|
|
|
screen.clear()
|
|
|
|
screen.refresh()
|
|
|
|
screen.nodelay(True)
|
|
|
|
curses.curs_set(False)
|
|
|
|
screen.keypad(True)
|
|
|
|
y, x = screen.getmaxyx()
|
2022-11-26 18:09:00 +00:00
|
|
|
curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLACK)
|
2022-11-27 17:59:24 +00:00
|
|
|
curses.init_pair(3, curses.COLOR_YELLOW, curses.COLOR_BLACK)
|
2022-11-24 12:13:45 +00:00
|
|
|
screen.border(0, 0, 0, " ", 0, 0, " ", " ")
|
2022-11-23 18:03:16 +00:00
|
|
|
ball = Ball(y, x, screen)
|
2022-11-23 19:23:26 +00:00
|
|
|
score = Scores(screen)
|
2022-11-23 18:03:16 +00:00
|
|
|
player = Player(y, x)
|
2022-11-24 12:13:45 +00:00
|
|
|
ball_thread = None
|
2022-11-23 18:03:16 +00:00
|
|
|
ball_thread = threading.Thread(
|
|
|
|
target=ball_movement,
|
|
|
|
args=(
|
|
|
|
screen,
|
|
|
|
ball,
|
|
|
|
score,
|
|
|
|
),
|
|
|
|
)
|
2022-11-24 12:13:45 +00:00
|
|
|
player_thread = None
|
2022-11-23 18:03:16 +00:00
|
|
|
player_thread = threading.Thread(
|
|
|
|
target=player_movement,
|
|
|
|
args=(
|
|
|
|
screen,
|
|
|
|
player,
|
|
|
|
),
|
|
|
|
)
|
2022-11-23 19:23:26 +00:00
|
|
|
screen.addstr(0, x - 13, " ")
|
|
|
|
screen.addstr(0, x - 12, "Score: 0")
|
2022-11-23 18:03:16 +00:00
|
|
|
ball_thread.start()
|
|
|
|
player_thread.run()
|
2022-11-24 12:13:45 +00:00
|
|
|
time.sleep(1)
|
2022-11-26 18:09:00 +00:00
|
|
|
m1.play(screen, executeguest=True, outerscore=score.score, outergame="pong")
|
2022-11-27 20:02:47 +00:00
|
|
|
maze.menu.menu(stdscr)
|
|
|
|
return
|