-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add flappy block game to graphics projects
- Loading branch information
1 parent
ea574e1
commit 1bf317a
Showing
16 changed files
with
621 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
...esh153-astro-svelte/src/components/projects/graphics/flappy-block-game/ProjectRoot.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
.../nodejs-apps/vighnesh153-astro-svelte/src/pages/projects/graphics/flappy-block-game.astro
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
7 changes: 6 additions & 1 deletion
7
nodejs-tools/nodejs-apps/vighnesh153-astro-svelte/src/pages/projects/graphics/index.astro
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
nodejs-tools/nodejs-lib/graphics-programming/src/flappy-block-game/Block.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
119 changes: 119 additions & 0 deletions
119
nodejs-tools/nodejs-lib/graphics-programming/src/flappy-block-game/Game.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
Oops, something went wrong.