Skip to content

Commit

Permalink
feat: add flappy block game to graphics projects
Browse files Browse the repository at this point in the history
  • Loading branch information
vighnesh153 committed Dec 25, 2023
1 parent ea574e1 commit 1bf317a
Show file tree
Hide file tree
Showing 16 changed files with 621 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ const { class: className, id, ...props } = Astro.props;
<footer id={hashTags.footer} class={classes(className, `py-12 grid place-items-center scroll-mt-8`)} {...props}>
<SocialLinks direction="horizontal" class="mb-4 flex sm:hidden" />
<p>
<Link href={externalLinks.githubRepo} color="secondary">Source code</Link> of this website
<slot name="custom-source-code">
<Link href={externalLinks.githubRepo} color="secondary">Source code</Link> of this website
</slot>
</p>
</footer>
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<script lang="ts">
import { onMount } from 'svelte';
import { FlappyBlockGame, CanvasWrapperImpl } from '@vighnesh153/graphics-programming';
import type { CanvasWrapper } from '@vighnesh153/graphics-programming';
let canvasElement: HTMLCanvasElement;
let canvasWrapper: CanvasWrapper;
let game: FlappyBlockGame;
function handleKeyPress(e: KeyboardEvent) {
if (e.key === ' ') {
game.handleSpacebarPress();
}
if (e.key === 'Enter') {
game.handleEnterPress();
}
}
function newGame() {
if (canvasWrapper) {
game = new FlappyBlockGame(canvasWrapper);
canvasElement.focus();
const frames = game.start();
function showNextFrame() {
if (!frames.next().done) {
requestAnimationFrame(showNextFrame);
}
}
showNextFrame();
}
}
onMount(() => {
canvasWrapper = new CanvasWrapperImpl(canvasElement);
newGame();
});
</script>

<canvas
class="mt-6 mx-auto w-full max-w-3xl aspect-video bg-text"
tabindex="0"
bind:this={canvasElement}
on:keypress={handleKeyPress}
>
Sorry your browser doesn't support the canvas element
</canvas>
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ const { title = defaultTitle, description = defaultDescription, navItems, showFo
<div class="mx-auto max-w-[1400px] px-4 pt-[0.05px] sm:px-20">
<slot />
</div>
{showFooter ? <Footer /> : null}
{
showFooter ? (
<Footer>
<slot name="custom-source-code" slot="custom-source-code" />
</Footer>
) : null
}
</main>
</BaseLayout>
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
---
import { type GraphicsProject } from '@vighnesh153/graphics-programming';
import { type GraphicsProject, graphicsProjectSourceCodeLink } from '@vighnesh153/graphics-programming';
import { classes, verifyGraphicsProjectPath } from '@/utils';
import { projectNavItems } from '@/constants';
import ContentLayout from '@/layouts/ContentLayout.astro';
import Link from '@/components/Link.svelte';
interface Props {
project: GraphicsProject;
Expand All @@ -16,9 +17,12 @@ verifyGraphicsProjectPath(project, Astro.request.url);
const title = `Vighnesh Raut | Graphics Projects - ${project.title}`;
---

<ContentLayout title={title} description={project.description} navItems={projectNavItems} showFooter={false}>
<ContentLayout title={title} description={project.description} navItems={projectNavItems} showFooter={true}>
<div class={classes(`mt-28 mb-12 max-w-xl mx-auto lg:max-w-[unset] scroll-mt-8`)}>
<h1 class="text-3xl mb-6 text-center">{project.title}</h1>
<slot />
</div>
<p slot="custom-source-code">
See the <Link href={graphicsProjectSourceCodeLink}>project's source code</Link>
</p>
</ContentLayout>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
import { graphicsProjectsMap } from '@vighnesh153/graphics-programming';
import GraphicsProjectLayout from '@/layouts/GraphicsProjectLayout.astro';
import ProjectRoot from '@/components/projects/graphics/flappy-block-game/ProjectRoot.svelte';
const project = graphicsProjectsMap.flappyBlockGame;
---

<GraphicsProjectLayout project={project}>
<ProjectRoot client:load />
</GraphicsProjectLayout>
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
---
import { graphicsProjectSourceCodeLink } from '@vighnesh153/graphics-programming';
import { classes } from '@/utils';
import { projectNavItems } from '@/constants';
import ContentLayout from '@/layouts/ContentLayout.astro';
import GraphicsProjectsCollection from '@/components/projects/graphics/GraphicsProjectsCollection.svelte';
import Link from '@/components/Link.svelte';
const title = 'Vighnesh Raut | Graphics Projects';
const description = `Graphics programming projects built with HTML Canvas API`;
---

<ContentLayout title={title} description={description} navItems={projectNavItems} showFooter={false}>
<ContentLayout title={title} description={description} navItems={projectNavItems} showFooter={true}>
<div class={classes(`mt-32 mb-12 max-w-xl mx-auto lg:max-w-[unset] scroll-mt-8`)}>
<h1 class="text-3xl mb-8">Graphics Programming Projects</h1>
<GraphicsProjectsCollection client:load />
</div>
<p slot="custom-source-code">
See the <Link href={graphicsProjectSourceCodeLink}>project's source code</Link>
</p>
</ContentLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const bondingParticles: GraphicsProject = {
};

const flappyBlockGame: GraphicsProject = {
imageLink: 'https://i.imgur.com/hKgLkKy.png',
imageLink: 'https://i.imgur.com/wurPeGP.png',
title: 'Flappy Block Game',
id: 'flappy-block-game',
description: 'Flappy block is an infinite world game which is inspired by the infamous "Flappy Bird" game.',
Expand Down Expand Up @@ -130,3 +130,6 @@ export const graphicsProjectsMap = {
} satisfies Record<string, GraphicsProject>;

export const graphicsProjects: GraphicsProject[] = Object.values(graphicsProjectsMap);

export const graphicsProjectSourceCodeLink =
'https://github.com/vighnesh153/vighnesh153-monorepo/tree/main/nodejs-tools/nodejs-lib/graphics-programming/src';
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { CanvasWrapper } from '@/canvas-wrapper';

interface BlockConfig {
readonly coordinate: Coordinate;

readonly color?: string;
readonly width?: number;
readonly height?: number;
readonly velocity?: number;
readonly jumpVelocity?: number;
readonly gravity?: number;
}

interface Coordinate {
x: number;
y: number;
}

export class Block {
readonly canvasWrapper: CanvasWrapper;

readonly color: string;
readonly width: number;
readonly height: number;
readonly jumpVelocity: number;
readonly gravity: number;

private coordinate: Coordinate;
private velocity: number;

get x(): number {
return this.coordinate.x;
}

get y(): number {
return this.coordinate.y;
}

constructor(canvasWrapper: CanvasWrapper, options: BlockConfig) {
this.canvasWrapper = canvasWrapper;

this.color = options.color ?? 'red';
this.width = options.width ?? 20;
this.height = options.width ?? 20;
this.velocity = options.velocity ?? 0;
this.jumpVelocity = options.jumpVelocity ?? -4;
this.gravity = options.gravity ?? 0.2;

this.coordinate = options.coordinate;
}

draw(): void {
const cw = this.canvasWrapper;
const {
color,
width,
height,
coordinate: { x, y },
} = this;

cw.drawFilledRect(x, y, width, height, color);
}

update(): void {
this.coordinate.y += this.velocity;
this.velocity += this.gravity;
}

handleSpacebarPress(): void {
this.velocity = this.jumpVelocity;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { CanvasWrapper } from '@/canvas-wrapper';
import { ScoreTracker } from './ScoreTracker';
import { getCanvasBgColor } from '@/getCanvasBgColor';
import { InfoScreen } from './InfoScreen';
import { Screen } from './Screen';
import { GameplayScreen } from './GameplayScreen';

interface FlappyBlockGameOptions {
readonly bgColor?: string;
readonly defaultColor?: string;
readonly verticalPadding?: number;
}

export class FlappyBlockGame {
readonly canvasWrapper: CanvasWrapper;

readonly verticalPadding: number;
readonly bgColor: string;
readonly defaultColor: string;

readonly scoreTracker = new ScoreTracker();

private infoScreen: InfoScreen;
private gameplayScreen: GameplayScreen;

activeScreen: Screen;
isRunning = false;

constructor(canvasWrapper: CanvasWrapper, options: FlappyBlockGameOptions = {}) {
this.canvasWrapper = canvasWrapper;

this.bgColor = options.bgColor ?? getCanvasBgColor(canvasWrapper);
this.verticalPadding = options.verticalPadding ?? 20;
this.defaultColor = options.defaultColor ?? 'black';

this.infoScreen = this.newInfoScreen();
this.gameplayScreen = this.newGamePlayScreen();

// this.activeScreen = this.infoScreen;
this.activeScreen = this.gameplayScreen;
}

*start() {
this.isRunning = true;
while (this.isRunning) {
this.draw();
this.update();
yield;
}
}

stop() {
this.isRunning = false;
}

handleSpacebarPress() {
this.activeScreen.handleSpacebarPress();
}

handleEnterPress() {
this.activeScreen.handleEnterPress();
}

private draw() {
this.clear();
this.drawBorders();
this.drawScreen();
}

private update() {
this.activeScreen.update();
}

private drawScreen() {
this.activeScreen.draw();
}

private drawBorders() {
const cw = this.canvasWrapper;
const color = this.defaultColor;
const padding = this.verticalPadding;

cw.drawLine(0, padding, cw.width, padding, 2, color);
cw.drawLine(0, cw.height - padding, cw.width, cw.height - padding, 2, color);
}

private changeScreen() {
if (this.activeScreen.type === 'gameplay') {
this.infoScreen = this.newInfoScreen();
this.activeScreen = this.infoScreen;
} else if (this.activeScreen.type === 'info') {
this.scoreTracker.reset();
this.gameplayScreen = this.newGamePlayScreen();
this.activeScreen = this.gameplayScreen;
}
}

private newInfoScreen(): InfoScreen {
return new InfoScreen(this.canvasWrapper, {
scoreTracker: this.scoreTracker,
changeScreen: () => this.changeScreen(),
});
}

private newGamePlayScreen(): GameplayScreen {
return new GameplayScreen(this.canvasWrapper, {
scoreTracker: this.scoreTracker,
verticalPadding: this.verticalPadding,
changeScreen: () => this.changeScreen(),
});
}

clear() {
const rect = this.canvasWrapper.getBoundingClientRect();
const canvasWidth = rect.width;
const canvasHeight = rect.height;
this.canvasWrapper.drawFilledRect(0, 0, canvasWidth, canvasHeight, this.bgColor);
}
}
Loading

0 comments on commit 1bf317a

Please sign in to comment.