Skip to content

Commit fcd7846

Browse files
committed
Update README - prepare for Netlify deployment
1 parent bbe70bf commit fcd7846

File tree

2 files changed

+161
-13
lines changed

2 files changed

+161
-13
lines changed

README.md

Lines changed: 161 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,37 @@
22

33
A childhood memory Tetris game built with Angular 10 and Akita.
44

5+
<details>
6+
<summary>Table Of Content</summary>
7+
<p>
8+
9+
- [Angular Tetris](#angular-tetris)
10+
- [Working Game](#working-game)
11+
- [Why?](#why)
12+
- [Who is this for?](#who-is-this-for)
13+
- [How to play](#how-to-play)
14+
- [Before playing](#before-playing)
15+
- [Playing game](#playing-game)
16+
- [Techstack](#techstack)
17+
- [Development Challenge](#development-challenge)
18+
- [Tetris Core](#tetris-core)
19+
- [Akita state management + dev tool support](#akita-state-management--dev-tool-support)
20+
- [Customizing Piece](#customizing-piece)
21+
- [Animation](#animation)
22+
- [Web Audio API](#web-audio-api)
23+
- [Keyboard handling](#keyboard-handling)
24+
- [Features and Roadmap](#features-and-roadmap)
25+
- [Phase 1 - Angular Tetris basic functionality](#phase-1---angular-tetris-basic-functionality)
26+
- [Phase 2 - Firebase high score, service worker, more sounds effect, more animation](#phase-2---firebase-high-score-service-worker-more-sounds-effect-more-animation)
27+
- [Time spending](#time-spending)
28+
- [Setting up development environment 🛠](#setting-up-development-environment-)
29+
- [Author: Trung Vo ✍️](#author-trung-vo-️)
30+
- [Credits and references](#credits-and-references)
31+
- [Contributing](#contributing)
32+
- [License](#license)
33+
</p>
34+
</details>
35+
536
## Working Game
637

738
Check out the **working game** -> https://tetris.trungk18.com
@@ -97,7 +128,7 @@ And let me emphasize it again, I didn't write the brain of the game from scratch
97128
Although you don't dispatch any action, Akita will still do it undo the hood as the Update action. And you still can see the data with [Redux DevTools][redux-devtool]. Remember to put that option into your `AppModule`
98129

99130
```ts
100-
imports: [BrowserModule, environment.production ? [] : AkitaNgDevtools.forRoot()];
131+
imports: [environment.production ? [] : AkitaNgDevtools.forRoot()];
101132
```
102133

103134
I turn it on all the time on [tetris.trungk18.com][angular-tetris], you can open the DevTools and start seeing the data flow.
@@ -106,26 +137,133 @@ I turn it on all the time on [tetris.trungk18.com][angular-tetris], you can open
106137

107138
> Note: opening the DevTools could reduce the performance of the game significantly. I recommended you turn it off when you want to archive a high score 🤓
108139
109-
### Web Audio API
140+
### Customizing Piece
110141

111-
There are many sound effects in the game such as when you press space, or left, right. In reality, all of the sounds were a reference to a single file [assets/tetris-sound.mp3][sounds].
142+
I defined a base [Piece class][piece-class] for a piece. And for each type of piece, it will extend from the same base class to inherit the same capability
143+
[piece-class]: src/app/interface/piece/piece.ts
112144

113-
I don't have much experience working with audio before but the Web Audio API looks very promising. You could do more with it.
145+
```ts
146+
export class Piece {
147+
x: number;
148+
y: number;
149+
rotation = PieceRotation.Deg0;
150+
type: PieceTypes;
151+
shape: Shape;
152+
next: Shape;
153+
154+
private _shapes: Shapes;
155+
private _lastConfig: Partial<Piece>;
156+
157+
constructor(x: number, y: number) {
158+
this.x = x;
159+
this.y = y;
160+
}
114161

115-
- See the [official documentation][webaudio]
116-
- See how I load the mp3 file and store it in [sound-manager.service.ts][sound-manager]
162+
store(): Piece {
163+
this._lastConfig = {
164+
x: this.x,
165+
y: this.y,
166+
rotation: this.rotation,
167+
shape: this.shape
168+
};
169+
return this._newPiece();
170+
}
117171

118-
### Animation
172+
//code removed for brevity
173+
}
174+
```
119175

120-
I rewrote the animation with RxJS. See the comparison below for the simple dinosaurs running animation at the beginning of the game.
176+
For example, I have a piece L. I create a new class name [PieceL][piecel]. I will contain the shape of L in four different rotation so that I don't have to mess up with the math to do minus plus on the XY axis. And I think defining in that way makes the code self-express better. If you see 1, it means on the matrix it will be filled, 0 mean empty tile.
121177

122-
You could do a lot of stuff if you know RxJS well enough :) I think I need to strengthen my RxJS knowledge soon enough as well. Super powerful.
178+
If my team member needs to maintain the code, I hope he will understand what I was trying to write immediately. Or maybe not 🤣
123179

124-
![Angular Tetris][compare02]
180+
One import property of the Piece is the `next` property to display the piece shape on the decoration box for the upcoming piece.
125181

126-
The actual result doesn't look very identical but it is good enough in my standard.
182+
[piecel]: src/app/interface/piece/L.ts
127183

128-
![Angular Tetris][compare02-result]
184+
```ts
185+
const ShapesL: Shapes = [];
186+
ShapesL[PieceRotation.Deg0] = [
187+
[0, 0, 0, 0],
188+
[1, 0, 0, 0],
189+
[1, 0, 0, 0],
190+
[1, 1, 0, 0]
191+
];
192+
193+
ShapesL[PieceRotation.Deg90] = [
194+
[0, 0, 0, 0],
195+
[0, 0, 0, 0],
196+
[1, 1, 1, 0],
197+
[1, 0, 0, 0]
198+
];
199+
//code removed for brevity
200+
201+
];
202+
203+
export class PieceL extends Piece {
204+
constructor(x: number, y: number) {
205+
super(x, y);
206+
this.type = PieceTypes.L;
207+
this.next = [
208+
[0, 0, 1, 0],
209+
[1, 1, 1, 0]
210+
];
211+
this.setShapes(ShapesL);
212+
}
213+
}
214+
```
215+
216+
Now is the interesting part, you create a custom piece by yourself. Simply create a new class that extends from `Piece` with different rotations.
217+
218+
For instance, I will define a new piece call F with class name [`PieceF`][piecef]. That is how it should look like.
219+
220+
[piecef]: https://github.com/trungk18/angular-tetris/blob/feature/pieceF/src/app/interface/piece/F.ts
221+
222+
```ts
223+
const ShapesF: Shapes = [];
224+
ShapesF[PieceRotation.Deg0] = [
225+
[1, 0, 0, 0],
226+
[1, 1, 0, 0],
227+
[1, 0, 0, 0],
228+
[1, 1, 0, 0]
229+
];
230+
231+
export class PieceF extends Piece {
232+
constructor(x, y) {
233+
super(x, y);
234+
this.type = PieceTypes.F;
235+
this.next = [
236+
[1, 0, 1, 0],
237+
[1, 1, 1, 1]
238+
];
239+
this.setShapes(ShapesF);
240+
}
241+
}
242+
```
243+
244+
And the last step, go to [PieceFactory][piecefactory] to add the new PieceF into the available pieces.
245+
246+
[piecefactory]: src/app/factory/piece-factory.ts
247+
248+
```ts
249+
export class PieceFactory {
250+
private _available: typeof Piece[] = [];
251+
252+
constructor() {
253+
//code removed for brevity
254+
this._available.push(PieceF);
255+
}
256+
}
257+
```
258+
259+
And you're all set, this is the result. See how easy it is to understand the code and add a custom piece that you like.
260+
261+
The source code for that custom piece F, you can see at [feature/pieceF][feature/piecef] branch.
262+
263+
![Angular Tetris Piece F][piecef-demo]
264+
265+
[feature/piecef]: https://github.com/trungk18/angular-tetris/tree/feature/pieceF
266+
[piecef-demo]: src/assets/readme/piecef-demo.gif
129267

130268
### Animation
131269

@@ -139,6 +277,15 @@ The actual result doesn't look very identical but it is good enough in my standa
139277

140278
![Angular Tetris][compare02-result]
141279

280+
### Web Audio API
281+
282+
There are many sound effects in the game such as when you press space, or left, right. In reality, all of the sounds were a reference to a single file [assets/tetris-sound.mp3][sounds].
283+
284+
I don't have much experience working with audio before but the Web Audio API looks very promising. You could do more with it.
285+
286+
- See the [official documentation][webaudio]
287+
- See how I load the mp3 file and store it in [sound-manager.service.ts][sound-manager]
288+
142289
### Keyboard handling
143290

144291
I planned to use [@ngneat/hotkeys][hotkeys] but I decided to use `@HostListener` instead. A simple implementation could look like:
@@ -172,10 +319,11 @@ See more at [containers/angular-tetris/angular-tetris.component.ts][hotkeys-impl
172319
- [x] Local storage high score
173320
- [x] Sounds effects
174321

175-
### Phase 2 - Firebase high score, more sounds effect, more animation
322+
### Phase 2 - Firebase high score, service worker, more sounds effect, more animation
176323

177324
> TBD
178325
326+
- [ ] Offline mode (play without internet connection)
179327
- [ ] Firebase high score
180328
- [ ] More sound effects
181329
- [ ] More animations

src/assets/readme/piecef-demo.gif

63.2 KB
Loading

0 commit comments

Comments
 (0)