Skip to content

Commit 676a8b5

Browse files
Copilotuanid
andauthored
Redesign dino game to match Chrome T-Rex visual style (#2)
* Initial plan * Add dino game package with full implementation Co-authored-by: uanid <35264628+uanid@users.noreply.github.com> * Fix score increment rate and game loop performance Co-authored-by: uanid <35264628+uanid@users.noreply.github.com> * Fix onFinish callback duplication and score display formatting Co-authored-by: uanid <35264628+uanid@users.noreply.github.com> * Floor score in onFinish callback and add frame rate comment Co-authored-by: uanid <35264628+uanid@users.noreply.github.com> * Improve dino game visual design to match Chrome T-Rex game Co-authored-by: uanid <35264628+uanid@users.noreply.github.com> * Fix code review issues: score overflow, eye position, CSS order Co-authored-by: uanid <35264628+uanid@users.noreply.github.com> * Fix ducking T-Rex eye visibility with white background Co-authored-by: uanid <35264628+uanid@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: uanid <35264628+uanid@users.noreply.github.com>
1 parent 3ff9547 commit 676a8b5

12 files changed

Lines changed: 861 additions & 0 deletions

File tree

packages/demo/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"clean": "rm -rf dist"
1111
},
1212
"dependencies": {
13+
"@minigames-react/dino": "workspace:*",
1314
"@minigames-react/minesweeper": "workspace:*",
1415
"react": "^18.2.0",
1516
"react-dom": "^18.2.0"

packages/demo/src/App.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React, { useState } from 'react';
22
import { Minesweeper } from '@minigames-react/minesweeper';
33
import '@minigames-react/minesweeper/dist/index.css';
4+
import { Dino } from '@minigames-react/dino';
5+
import '@minigames-react/dino/dist/index.css';
46
import './App.css';
57

68
interface GameResult {
@@ -26,6 +28,7 @@ const difficulties: Record<Difficulty, DifficultyConfig> = {
2628
function App() {
2729
const [difficulty, setDifficulty] = useState<Difficulty>('easy');
2830
const [gameResult, setGameResult] = useState<GameResult | null>(null);
31+
const [dinoResult, setDinoResult] = useState<{ score: number; time: number } | null>(null);
2932
const [key, setKey] = useState(0);
3033

3134
const config = difficulties[difficulty];
@@ -34,6 +37,10 @@ function App() {
3437
setGameResult(result);
3538
};
3639

40+
const handleDinoFinish = (result: { score: number; time: number }) => {
41+
setDinoResult(result);
42+
};
43+
3744
const handleDifficultyChange = (newDifficulty: Difficulty) => {
3845
setDifficulty(newDifficulty);
3946
setGameResult(null);
@@ -102,6 +109,26 @@ function App() {
102109
</div>
103110
)}
104111
</div>
112+
113+
<div className="game-card">
114+
<h2>🦕 Dino Game</h2>
115+
116+
<div className="game-info">
117+
<p>
118+
<strong>How to play:</strong>
119+
</p>
120+
<p>Press SPACE or ↑ to jump, ↓ to duck</p>
121+
<p>Avoid obstacles and survive as long as you can!</p>
122+
</div>
123+
124+
<Dino onFinish={handleDinoFinish} speed={1} />
125+
126+
{dinoResult && (
127+
<div className="game-result">
128+
🦕 Game Over! Score: {Math.floor(dinoResult.score)} | Time: {dinoResult.time.toFixed(1)}s
129+
</div>
130+
)}
131+
</div>
105132
</div>
106133
</div>
107134
);

packages/dino/README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# @minigames-react/dino
2+
3+
A Chrome Dino-style game component for React.
4+
5+
## Installation
6+
7+
```bash
8+
npm install @minigames-react/dino
9+
# or
10+
pnpm add @minigames-react/dino
11+
```
12+
13+
## Usage
14+
15+
```tsx
16+
import { Dino } from '@minigames-react/dino';
17+
import '@minigames-react/dino/dist/index.css';
18+
19+
function App() {
20+
const handleFinish = (result) => {
21+
console.log(`Game Over! Score: ${result.score}, Time: ${result.time}s`);
22+
};
23+
24+
return (
25+
<div>
26+
<h1>Dino Game</h1>
27+
<Dino onFinish={handleFinish} speed={1} />
28+
</div>
29+
);
30+
}
31+
```
32+
33+
## Props
34+
35+
- `onFinish?: (result: { score: number; time: number }) => void` - Callback function called when the game ends
36+
- `speed?: number` - Game speed multiplier (default: 1)
37+
38+
## Controls
39+
40+
- **Space** or **** - Jump
41+
- **** - Duck
42+
- **R** - Restart (when game is over)
43+
44+
## Features
45+
46+
- Classic Chrome Dino game mechanics
47+
- Jump and duck to avoid obstacles
48+
- Progressive difficulty
49+
- Score tracking
50+
- Keyboard controls

packages/dino/package.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"name": "@minigames-react/dino",
3+
"version": "0.1.0",
4+
"description": "Dino game component for React",
5+
"main": "dist/index.js",
6+
"module": "dist/index.esm.js",
7+
"types": "dist/index.d.ts",
8+
"scripts": {
9+
"build": "rollup -c",
10+
"dev": "rollup -c -w",
11+
"clean": "rm -rf dist"
12+
},
13+
"keywords": ["react", "dino", "game", "chrome", "t-rex"],
14+
"peerDependencies": {
15+
"react": "^18.0.0",
16+
"react-dom": "^18.0.0"
17+
},
18+
"devDependencies": {
19+
"@rollup/plugin-commonjs": "^25.0.7",
20+
"@rollup/plugin-node-resolve": "^15.2.3",
21+
"@rollup/plugin-typescript": "^11.1.6",
22+
"@types/react": "^18.2.48",
23+
"@types/react-dom": "^18.2.18",
24+
"react": "^18.2.0",
25+
"react-dom": "^18.2.0",
26+
"rollup": "^4.9.6",
27+
"rollup-plugin-peer-deps-external": "^2.2.4",
28+
"rollup-plugin-postcss": "^4.0.2",
29+
"tslib": "^2.6.2",
30+
"typescript": "^5.3.3"
31+
},
32+
"files": [
33+
"dist"
34+
]
35+
}

packages/dino/rollup.config.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import resolve from '@rollup/plugin-node-resolve';
2+
import commonjs from '@rollup/plugin-commonjs';
3+
import typescript from '@rollup/plugin-typescript';
4+
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
5+
import postcss from 'rollup-plugin-postcss';
6+
7+
export default {
8+
input: 'src/index.ts',
9+
output: [
10+
{
11+
file: 'dist/index.js',
12+
format: 'cjs',
13+
sourcemap: true,
14+
},
15+
{
16+
file: 'dist/index.esm.js',
17+
format: 'esm',
18+
sourcemap: true,
19+
},
20+
],
21+
plugins: [
22+
peerDepsExternal(),
23+
resolve(),
24+
commonjs(),
25+
typescript({ tsconfig: './tsconfig.json' }),
26+
postcss({
27+
extract: true,
28+
minimize: true,
29+
}),
30+
],
31+
};

packages/dino/src/Dino.css

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
.dino-game {
2+
display: flex;
3+
flex-direction: column;
4+
align-items: center;
5+
gap: 20px;
6+
padding: 20px;
7+
background: #fff;
8+
}
9+
10+
.dino-controls {
11+
display: flex;
12+
flex-direction: column;
13+
align-items: center;
14+
gap: 10px;
15+
width: 100%;
16+
}
17+
18+
.control-hint {
19+
display: flex;
20+
gap: 20px;
21+
font-size: 13px;
22+
color: #757575;
23+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
24+
}
25+
26+
.control-hint span {
27+
padding: 4px 8px;
28+
background: #f5f5f5;
29+
border-radius: 3px;
30+
border: 1px solid #ddd;
31+
}
32+
33+
.restart-button {
34+
padding: 8px 16px;
35+
font-size: 14px;
36+
font-weight: 500;
37+
color: #fff;
38+
background: #535353;
39+
border: none;
40+
border-radius: 3px;
41+
cursor: pointer;
42+
transition: background 0.2s;
43+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
44+
}
45+
46+
.restart-button:hover {
47+
background: #3a3a3a;
48+
}
49+
50+
.restart-button:active {
51+
transform: scale(0.98);
52+
}
53+
54+
.dino-canvas {
55+
border: 2px solid #535353;
56+
background: #fff;
57+
cursor: pointer;
58+
display: block;
59+
image-rendering: crisp-edges;
60+
image-rendering: pixelated;
61+
}
62+
63+
.dino-canvas:focus {
64+
outline: none;
65+
border-color: #535353;
66+
}

0 commit comments

Comments
 (0)