import { fromEvent, of, interval, combineLatest, generate, noop } from 'rxjs';
import { map, mergeMap, pluck, startWith, scan, toArray, takeWhile, tap } from 'rxjs/operators';
import { gameSize } from './constants';
import { Player, Ball, GameObject } from './interfaces';
import { render } from './html-renderer';
const createGameObject = (x, y) => ({ x, y });
const player$ = combineLatest(
of({ ...createGameObject(gameSize - 2, (gameSize / 2) - 1), score: 0, lives: 3 }),
fromEvent(document, 'keyup').pipe(startWith({ code: '' }), pluck('code'))
const ball$ = combineLatest(
of({ ...createGameObject(gameSize / 2, (gameSize - 3)), dirX: 1, dirY: 1 }),
map(([ball, _]: [Ball, number]) => (
ball.dirX *= ball.x > 0 ? 1 : -1,
ball.dirY *= (ball.y > 0 && ball.y < gameSize - 1) ? 1 : -1,
const bricks$ = generate(1, x => x < 8, x => x + 1)
mergeMap(r => generate(r % 2 === 0 ? 1 : 0, x => x < gameSize, x => x + 2)
.pipe(map(c => createGameObject(r, c)))
const processGameCollisions = (_, [player, ball, bricks]: [Player, Ball, GameObject[]])
: [Player, Ball, GameObject[]] => (
(collidingBrickIndex => collidingBrickIndex > -1
? (bricks.splice(collidingBrickIndex, 1), ball.dirX *= -1, player.score++)
)(bricks.findIndex(e => e.x === ball.x && e.y === ball.y)),
ball.dirX *= player.x === ball.x && player.y === ball.y ? -1 : 1,
ball.x > player.x ? (player.lives-- , ball.x = (gameSize / 2) - 3) : noop,
combineLatest(player$, ball$, bricks$)
scan<[Player, Ball, GameObject[]], [Player, Ball, GameObject[]]>(processGameCollisions),
takeWhile(([player]: [Player, Ball, GameObject[]]) => player.lives > 0)