Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"clean": "rm -rf dist"
},
"dependencies": {
"@minigames-react/dino": "workspace:*",
"@minigames-react/minesweeper": "workspace:*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
Expand Down
27 changes: 27 additions & 0 deletions packages/demo/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React, { useState } from 'react';
import { Minesweeper } from '@minigames-react/minesweeper';
import '@minigames-react/minesweeper/dist/index.css';
import { Dino } from '@minigames-react/dino';
import '@minigames-react/dino/dist/index.css';
import './App.css';

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

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

const handleDinoFinish = (result: { score: number; time: number }) => {
setDinoResult(result);
};

const handleDifficultyChange = (newDifficulty: Difficulty) => {
setDifficulty(newDifficulty);
setGameResult(null);
Expand Down Expand Up @@ -102,6 +109,26 @@ function App() {
</div>
)}
</div>

<div className="game-card">
<h2>🦕 Dino Game</h2>

<div className="game-info">
<p>
<strong>How to play:</strong>
</p>
<p>Press SPACE or ↑ to jump, ↓ to duck</p>
<p>Avoid obstacles and survive as long as you can!</p>
</div>

<Dino onFinish={handleDinoFinish} speed={1} />

{dinoResult && (
<div className="game-result">
🦕 Game Over! Score: {Math.floor(dinoResult.score)} | Time: {dinoResult.time.toFixed(1)}s
</div>
)}
</div>
</div>
</div>
);
Expand Down
50 changes: 50 additions & 0 deletions packages/dino/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# @minigames-react/dino

A Chrome Dino-style game component for React.

## Installation

```bash
npm install @minigames-react/dino
# or
pnpm add @minigames-react/dino
```

## Usage

```tsx
import { Dino } from '@minigames-react/dino';
import '@minigames-react/dino/dist/index.css';

function App() {
const handleFinish = (result) => {
console.log(`Game Over! Score: ${result.score}, Time: ${result.time}s`);
};

return (
<div>
<h1>Dino Game</h1>
<Dino onFinish={handleFinish} speed={1} />
</div>
);
}
```

## Props

- `onFinish?: (result: { score: number; time: number }) => void` - Callback function called when the game ends
- `speed?: number` - Game speed multiplier (default: 1)

## Controls

- **Space** or **↑** - Jump
- **↓** - Duck
- **R** - Restart (when game is over)

## Features

- Classic Chrome Dino game mechanics
- Jump and duck to avoid obstacles
- Progressive difficulty
- Score tracking
- Keyboard controls
35 changes: 35 additions & 0 deletions packages/dino/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "@minigames-react/dino",
"version": "0.1.0",
"description": "Dino game component for React",
"main": "dist/index.js",
"module": "dist/index.esm.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w",
"clean": "rm -rf dist"
},
"keywords": ["react", "dino", "game", "chrome", "t-rex"],
"peerDependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-typescript": "^11.1.6",
"@types/react": "^18.2.48",
"@types/react-dom": "^18.2.18",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"rollup": "^4.9.6",
"rollup-plugin-peer-deps-external": "^2.2.4",
"rollup-plugin-postcss": "^4.0.2",
"tslib": "^2.6.2",
"typescript": "^5.3.3"
},
"files": [
"dist"
]
}
31 changes: 31 additions & 0 deletions packages/dino/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
import postcss from 'rollup-plugin-postcss';

export default {
input: 'src/index.ts',
output: [
{
file: 'dist/index.js',
format: 'cjs',
sourcemap: true,
},
{
file: 'dist/index.esm.js',
format: 'esm',
sourcemap: true,
},
],
plugins: [
peerDepsExternal(),
resolve(),
commonjs(),
typescript({ tsconfig: './tsconfig.json' }),
postcss({
extract: true,
minimize: true,
}),
],
};
66 changes: 66 additions & 0 deletions packages/dino/src/Dino.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
.dino-game {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
padding: 20px;
background: #fff;
}

.dino-controls {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
width: 100%;
}

.control-hint {
display: flex;
gap: 20px;
font-size: 13px;
color: #757575;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

.control-hint span {
padding: 4px 8px;
background: #f5f5f5;
border-radius: 3px;
border: 1px solid #ddd;
}

.restart-button {
padding: 8px 16px;
font-size: 14px;
font-weight: 500;
color: #fff;
background: #535353;
border: none;
border-radius: 3px;
cursor: pointer;
transition: background 0.2s;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

.restart-button:hover {
background: #3a3a3a;
}

.restart-button:active {
transform: scale(0.98);
}

.dino-canvas {
border: 2px solid #535353;
background: #fff;
cursor: pointer;
display: block;
image-rendering: crisp-edges;
image-rendering: pixelated;
}

.dino-canvas:focus {
outline: none;
border-color: #535353;
}
Loading