Skip to content

Commit fe74180

Browse files
committed
.
1 parent 93a2654 commit fe74180

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+5907
-6
lines changed

.gitmodules

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
; packages
21

32

4-
; plugins
5-
63
[submodule "apps/exts_alfred_claude-search"]
74
path = apps/exts/alfred/claude-search
85
url = [email protected]:cs-magic/exts_alfred_claude-search.git
@@ -15,7 +12,6 @@
1512
path = apps/exts/chrome/claude-artifact-enhancer
1613
url = [email protected]:cs-magic/exts_chrome_claude-artifact-enhancer.git
1714

18-
; apps
1915
[submodule "apps/playground"]
2016
path = apps/playground
2117
url = [email protected]:cs-magic/playground.git
@@ -63,7 +59,7 @@
6359
path = apps/uni-pusher
6460
url = [email protected]:cs-magic/uni-pusher.git
6561

66-
; cases
62+
6763
[submodule "cases/zhijikeji"]
6864
path = cases/zhijikeji
6965
url = [email protected]:cs-magic/cases_zhijikeji.git
@@ -82,3 +78,6 @@
8278
[submodule "apps/docs"]
8379
path = apps/docs
8480
url = [email protected]:MarkShawn2020/nextra-docs.git
81+
[submodule "apps/exts/chrome/auto-sdk"]
82+
path = apps/exts/chrome/auto-sdk
83+
url = [email protected]:MarkShawn2020/auto-sdk.git

apps/badminton-reservation

Submodule badminton-reservation added at 0115320

apps/cs-magic/eval-ai

Submodule eval-ai added at 7650985

apps/cs-magic/poketto

Submodule poketto added at 00b1a79

apps/cs-magic/thinkow

Submodule thinkow added at 058367a

apps/docs

Submodule docs added at 332424d

apps/exts/alfred/claude-search

Submodule claude-search added at 26cf8e7

apps/exts/chrome/auto-sdk

Submodule auto-sdk added at e85c872

apps/exts/chrome/chatbot-exporter

Submodule chatbot-exporter added at 6b0a264

apps/game/fruit/game.js

+193
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
class FruitGame {
2+
constructor() {
3+
this.canvas = document.getElementById('game-canvas');
4+
this.ctx = this.canvas.getContext('2d');
5+
this.scoreElement = document.getElementById('score-value');
6+
this.score = 0;
7+
this.fruits = [];
8+
this.slices = [];
9+
this.lastTime = 0;
10+
this.fruitInterval = 1000;
11+
this.lastFruitTime = 0;
12+
this.gameState = 'playing'; // 'playing', 'gameover'
13+
this.lives = 3;
14+
15+
this.fruitTypes = ['apple', 'orange', 'watermelon', 'pineapple', 'bomb'];
16+
this.fruitImages = {};
17+
this.loadImages();
18+
19+
this.sliceSound = new Audio(this.sliceSoundData);
20+
this.bombSound = new Audio(this.bombSoundData);
21+
this.backgroundMusic = new Audio(this.backgroundMusicData);
22+
this.backgroundMusic.loop = true;
23+
24+
this.resizeCanvas();
25+
window.addEventListener('resize', () => this.resizeCanvas());
26+
this.canvas.addEventListener('touchstart', (e) => this.handleTouch(e));
27+
this.canvas.addEventListener('touchmove', (e) => this.handleTouch(e));
28+
29+
this.backgroundMusic.play();
30+
requestAnimationFrame((time) => this.gameLoop(time));
31+
}
32+
33+
loadImages() {
34+
const imageData = {
35+
apple: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAADu0lEQVR4nO2WW0hjVxjH/+fk5EQTTdTEqGhEU7XeaFAzKipYaWGwdR68oOhM6cVbd2DKdMTLPrQg+lB8qC/zoA/7sA/bUoaWgRkc2u3SbWGLbXG3u2p3x2Rdt2o0Md6SY07P2Qc1JuZoopMMzL7kDwfO+c7v+53/+c4hcI1rXOGIVKXJVqe/Cue5QiEpGo0+EgwGPxVFsYNzHmSMPUcI+XFubs6/J4GsrKy7GGM/AXieEFLDOW8RQnxhGJ8QQl7nnH8D4GYikfhqfn7+z7QFdDrdI5TSXwkhd3DOIYoiKKUghIAQAkIICCEwDON9QRBe45y/xDkPAXhxYWHheFcBnU73EqX0R0JI9eTkJCwWC8xmM4xGIwwGA/R6PXQ6HbRaLTQaDdRqNVQqFZRKJRQKBWQyGaRSKSQSCcRiMYhEIhAEAYIggDEGxhg451hZWUEkEnnbNM0XOOePLi4uTu9KQK1WP0kp/Z4QUjc1NQWr1Qqz2QyTyQSj0Qi9Xg+dTgedTgetVguNRgO1Wg2VSgWlUgmFQgG5XA6ZTAapVAqJRAKxWAyCIEAQBDDGkEwmkUgkEI/HEYvFEI1GEYlEEA6HEQqFEAwGEQgE4Pf7MT8/f4tz/tTy8vLCjgJqtfpZSukPhJCHZ2ZmYLPZYLFYYDabYTKZYDAYoNfrodVqodFooFarodFooFKpoFQqoVAoIJfLIZPJIJVKIZFIIBaLIQgCGGNgjCGZTCKRSCAejyMWiyEajSISiSAcDiMUCiEYDCIQCMDv98Pn82FxcRFra2uIx+PPra6u/rKtwH8m/54QUj8/Pw+73Q6r1QqLxQKz2QyTyQSDwQC9Xg+dTgetVguNRgO1Wg2VSgWlUgmFQgG5XA6ZTAapVAqJRAKxWAzGGBhjSCaTSCQSiMfjiMViiEajiEQiCIfDCIVCCAaDCAQC8Pv98Pl8WFpawvr6OhKJxAurq6vv/k9Ao9G8Qin9jhDS4HQ6YbfbYbPZYLVaYbFYYDabYTQaodfrv6OUNlJKMRgMolarP1AoFM8olcqbCoXiQblc/pBcLq+Uy+UVMpmsXCaTlUmlUolEIhEEQRhjjDHGWDKZTMbj8XgsFovGYrFINBqNhMPhcCgUCgWDwaDf7/f7fD6fz+fzLi8ve1dWVjzr6+sbGxsb0WQy+erq6uqbVwTUavXLlNJvCSGPuFwuOBwO2O122Gw2WK1WWCwWmM1mmEwmGI1GGAwG6PV66HQ6aLVaaLVaqNVqqFQqqFQqKJVKKJVKKBQKyOVyyOVyyGQySKVSSKVSiMViiEQiiEQiCIIAwf8nYIyBMYZkMgnGGBhjYIwhkUggHo8jFoshGo0iEokgHA4jFAohGAwiEAjA7/fD5/NhaWkJa2trSCQSr6+srLxxhf/ENf5l/AUj7hNSCQ3OEQAAAABJRU5ErkJggg==',
36+
orange: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAEkUlEQVR4nO2WXUxbZRjH/+e0PT1tOaWlLR2lHSsshY6xdR+6ZRhkWbyYuAtduMULb9zcjZm6xGS7WLLEZPFqF8bdmGxkZjFZdDExumiMMZlGnU7BAcvaaQcUKC3Q0tNzjhdgpz0t/TrZxW7yJG9Ozvs+z+//vM/7nPcAHuEhh2jdqbVqLRRFOXpFRUUZNpvtpFar/YRl2RjP8zc4jvuB47hxjuOWAKyVlJTIABYBJLa1QK1Wv0hRlEoURYiiCFEUIYoiBEGAIAjgeR48z4PjOMzNzQ3EYrFTAKKCINxfXFz8NaMFarX6OEVRnyqVypN+vx8ejwdOpxMOhwN2ux1WqxUWiwVmsxkmkwlGoxEGgwF6vR46nQ5arRYajQZqtRoqlQpKpRIKhQJyuRxyuRwymQxSqRQSiQRisRgikQgikQiCIEAQBPA8D57nwXEcOI7DysoKlpeXMTc3h+np6R9jsdgbAD5fWlqKZrSAYZjXKYr6RKlUNgYCAXg8HrhcLjidTjgcDtjtdlitVlgsFphMJhiNRhgMBuj1euh0Omi1Wmg0GqjVaqhUKiiVSigUCsjlcshkMkzPRHFvOoJweBGRyBLC4UUsLCwiFFpAMBjC/HwQ9+8HMDs7i5mZGUxNTWFychITExMYHx/H2NgYRkdHMTIygqGhIQwODmJgYAD9/f3o6+tDb28vent7cenSJZw/fx5nz57FmTNncPr0aZw6dQonT57EiRMncPz4cRw7dgxHjx7FkSNH0NHRgfb2drS1taG1tRUtLS1obm5GU1MTGhsb0dDQgPr6etTV1aG2thY1NTWorq5GVVUVKisrUVFRgfLycpSVlaG0tBQlJSUoLi5GUVERCgsLUVBQgPz8fOTl5SE3Nxc5OTnIzs5GVlYWMjMzkZGRgfT0dKSlpSE1NRUpKSlITk5GUlISkpKSYDAYkJeXh9LSUlRXV6O+vh6NjY1oampCS0sLWltb0dbWhra2NrS3t6OjowPt7e1oa2tDa2srWlpa0NzcjKamJjQ2NqKhoQH19fWoq6tDbW0tampqUF1djaqqKlRWVqKiogLl5eUoKytDaWkpiouLUVRUhMLCQuTn5yMvLw+5ubnIyclBdnY2srKykJmZifT0dKSlpSE1NRUpKSlITk5GUlISjEYj8vPzUVZWhpqaGtTX16OxsRHNzc1oaWlBa2sr2tra0N7ejo6ODrS3t6OtrQ2tra1oaWlBc3MzmpqaYLFYkJqaiqSkJBiNRuTn56O0tBTV1dWor69HY2MjmpubH1jQ0dGB9vZ2tLW1obW1FS0tLWhubkZTUxMaGhpQX1+Puro61NbWoqamBtXV1aiqqkJlZSUqKipQXl6OsrIylJaWori4GEVFRSgsLERBQQHy8/ORl5eH3NxcZGdnIysrC5mZmUhPT0daWhpSU1ORkpKC5ORkJCUlwWg0Ii8vD6WlpaiqqkJtbS3q6+vR0NCApqYmNDc3o6WlBa2trQ8s6OjoQHt7O9ra2tDa2oqWlha0tLSgubkZTU1NaGxsRENDA+rr61FXV4fa2lrU1NSguroaVVVVqKysREVFBcrLy1FWVobS0lIUFxejqKgIhYWFKCgoQH5+PvLy8pCbm4vc3Fzk5OQgOzsb2dnZyMrKQmZmJjIyMpCeno60tDSkpaUhNTUVKSkpSE5ORlJSEoxGI/Ly8lBaWorq6mrU19ejsbERTU1NaG5ufmDBQxn/AKZwVa4J1XROAAAAAElFTkSuQmCC',
37+
watermelon: 'data:image/png;base64,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',
38+
pineapple: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAEZElEQVR4nO2WXUybZRTH/+3b0tKWtrSllFIohVIo31TGnAwc4sMSp5kvFzOXLHHJluxqV7vRaLzZzXazxGW72cVMnU4Nl2jijGgUg5sKjsFGGR+lUkAKlEIppS0tpW/7vB5aaPsW6Myu9iRPTp73nPP/n+c5z3kO8D/+5RDdcafWoINCodh3R1VVVVlFRcUpg8HwBcuyMZ7nb3Ic9xPHcWMcxy0BWCsrK5MBLAJIbGuBwWBoUSgUKlEUsbq6ClEUsba2BkEQwPM8eJ4Hx3HgOA5zc3MDKysrpwFERUG4v7i4+HtGCwwGwwmFQvGlUqk8FQgE4PF44HQ64XA4YLfbYbPZYLVaYbFYYDabYTKZYDQaYTAYoNfrodPpoNVqodFooFarodFooFKpoFQqoVAoIJfLIZPJIJVKIZFIIBaLIRKJIAgCBEEAz/PgeR4cx4HjOKysrCAajSIajWJ5eRnLy8uIRqNYWlrC4uIiFhYWMD8/j1AohFAohGAwiLm5OczOzmJmZgbT09OYmprC5OQkJiYmMD4+jrGxMYyOjmJkZATDw8MYGhrC4OAgBgYG0N/fj76+PvT29qKnpwfd3d3o6upCZ2cnOjo6cOHCBZw/fx7nzp3D2bNncebMGZw+fRqnTp3CyZMnceLECRw/fhzHjh3D0aNHceTIERw+fBiHDh3CwYMHceDAAezfvx/79u3D3r17sWfPHjQ3N6OpqQmNjY1oaGhAfX096urqUFtbi5qaGlRXV6OqqgqVlZWoqKhAeXk5ysrKUFpaipKSEhQXF6OoqAiFhYUoKChAfn4+8vLykJubi5ycHGRnZyMrKwuZmZnIyMhAeno60tLSkJqaipSUFCQnJyMpKQlGoxF5eXkoLS1FdXU16uvrH1vQ1NSE5uZm7N69G7t370ZLSwtaWlrQ3NyMpqYmNDY2oqGhAfX19airq0Ntbe1jC6qqqh5bUFFRgfLycpSVlaG0tBQlJSUoLi5GUVERCgsLUVBQgPz8fOTl5SE3Nxc5OTnIzs5GVlYWMjMzkZGRgfT0dKSlpSE1NRUpKSlITk6G0WhEfn4+ysvLUVlZiYqKCpSXl6OsrAylpaUoKSlBcXExioqKUFhYiIKCAuTn5yMvLw+5ubnIyclBdnY2srKykJmZiYyMDKSnpyMtLQ2pqalISUlBcnIyjEYj8vLyUFpaiqqqKlRXV6OmpgbV1dWoqqpCZWUlKioqUF5ejrKyMpSWlqKkpATFxcUoKipCYWEhCgoKkJ+fj7y8POTm5iInJwfZ2dnIyspCZmYmMjIykJ6ejrS0NKSmpj62IC8vD6WlpaiqqqJzUFNTg+rqalRVVaGyshIVFRUoLy9HWVkZSktLUVJSguLiYhQVFaGwsBAFBQXIz89HXl4ecnNzkZOTg+zsbGRlZSEzMxMZGRlIT09HWloaUlNTkZKSguTkZBiNRuTl5aG0tBRVVVWoqalBdXU1qqqqUFlZiYqKCpSXl6OsrAylpaUoKSlBcXExioqKUFhYiIKCAuTn5yMvLw+5ubnIyclBdnY2srKykJmZiYyMDKSnpyMtLQ2pqalISUlBcnIyjEYj8vLyUFpaiqqqKlRXV6OmpgZVVVWorKxERUUFysvLUVZWhtLSUpSUlKC4uBhFRUUoLCxEQUEB8vPzkZeXh9zcXOTk5CA7OxtZWVnIzMxERkYG0tPTkZaWhtTUVKSkpCA5ORlGoxF5eXkoLS1FVVUVqqurUVNTg6qqKlRWVqKiouIfW/A3VKmCVEZZmVsAAAAASUVORK5CYII=',
39+
bomb: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHElEQVR4nO2WW0yb5xXHf7bBYGPAGBuMbQw2mEuAcA2BEAiQNE1aSJq0SdM0bdKLNlGrdlNXqas2VdvUbdLUdZq6Tl2lSpO2qlKvrVRt0qZNXRtCQri5gG2wuRiMsQ02xmDj2++zD4Cv/QJp0qp92JP8pKPvfZ/z/5/znPOcI/A/vsUQPO9JtVoFkUi074qKigpTWVnZKY1G8ynDMFGWZW8wDPMjwzBjDMMsAFgtLS0VASwAiG9rgUaj+Z5IJJKIoojV1VWIooi1tTXwPA+WZcGyLBiGAcMwmJub61tZWTkNICLw/P2FhYVfM1qg0WhOiESiz8Ri8alAIACXywWbzQar1Qqz2QyTyQSj0QiDwQC9Xg+dTgetVguNRgO1Wg2VSgWlUgmFQgG5XA6ZTAapVAqJRAKxWAyRSARBECAIAliWBcuyYBgGDMOA4zhwHIdIJIJwOIxwOIylpSUsLS0hHA5jcXERCwsLmJ+fRygUQigUQjAYxNzcHGZnZzEzM4Pp6WlMTU1hcnISExMTGB8fx9jYGEZHRzEyMoLh4WEMDg5iYGAA/f396Ovrw7Vr19Db24vu7m50dXWhs7MTHR0daG9vx4ULF3D+/HmcO3cOZ8+exZkzZ3D69GmcOnUKJ0+exIkTJ3D8+HEcO3YMR48exZEjR3D48GEcOnQIBw8exIEDB7B//37s27cPe/fuxZ49e9Dc3IympibU1dWhtrYWNTU1qK6uRlVVFSorK1FRUYHy8nKUlZWhtLQUJSUlKC4uRlFREQoLC1FQUIC8vDzk5uYiJycH2dnZyMrKQmZmJjIyMpCeno60tDSkpqYiJSUFycnJSEpKglarhU6nQ2lpKaqrq1FbW4u6ujrU19ejtrYWNTU1qK6uRlVVFSorK1FRUYHy8nKUlZWhtLQUJSUlKC4uRlFREQoLC1FQUIC8vDzk5uYiJycH2dnZyMrKQmZmJjIyMpCeno60tDSkpqYiJSUFycnJ0Gq10Ol0KC0tRXV1NWpra1FXV4f6+no0NDSgoaEBdXV1qK2tRU1NDaqrq1FVVYXKykpUVFSgvLwcZWVlKC0tRUlJCYqLi1FUVISCggLk5eUhNzcXOTk5yM7ORlZWFjIzM5GRkYH09HSkpaUhNTUVKSkpSE5OhlarRW5uLkpKSlBZWYmKigqUl5ejrKwMpaWlKCkpQXFxMYqKilBYWIiCggLk5eUhNzcXOTk5yM7ORlZWFjIzM5GRkYH09HSkpaUhNTUVKSkpSE5OhlarRW5uLkpKSlBVVYXq6mpUV1ejqqoKlZWVqKioQHl5OcrKylBaWoqSkhIUFxejqKgIhYWFKCgoQF5eHnJzc5GTk4Ps7GxkZWUhMzMTGRkZSE9PR1paGlJTU5GSkgKtVovc3FyUlJSgqqoK1dXVqK6uRlVVFSorK1FRUY'
40+
};
41+
this.fruitImages = imageData;
42+
}
43+
44+
resizeCanvas() {
45+
this.canvas.width = window.innerWidth;
46+
this.canvas.height = window.innerHeight;
47+
}
48+
49+
handleTouch(e) {
50+
e.preventDefault();
51+
const touch = e.touches[0];
52+
const rect = this.canvas.getBoundingClientRect();
53+
const x = touch.clientX - rect.left;
54+
const y = touch.clientY - rect.top;
55+
this.checkFruitCut(x, y);
56+
this.slices.push({x, y, time: Date.now()});
57+
}
58+
59+
checkFruitCut(x, y) {
60+
this.fruits.forEach((fruit, index) => {
61+
if (this.isPointInFruit(x, y, fruit)) {
62+
if (fruit.type === 'bomb') {
63+
this.bombSound.play();
64+
this.lives--;
65+
if (this.lives <= 0) {
66+
this.gameState = 'gameover';
67+
}
68+
} else {
69+
this.sliceSound.play();
70+
this.fruits.splice(index, 1);
71+
this.score += fruit.points;
72+
this.scoreElement.textContent = this.score;
73+
this.createFruitSlices(fruit);
74+
}
75+
}
76+
});
77+
}
78+
79+
isPointInFruit(x, y, fruit) {
80+
const dx = x - fruit.x;
81+
const dy = y - fruit.y;
82+
return dx * dx + dy * dy <= fruit.radius * fruit.radius;
83+
}
84+
85+
createFruitSlices(fruit) {
86+
// Create two halves of the fruit
87+
for (let i = 0; i < 2; i++) {
88+
this.fruits.push({
89+
...fruit,
90+
isSlice: true,
91+
rotationSpeed: (Math.random() - 0.5) * 0.2,
92+
speedX: (Math.random() - 0.5) * 5
93+
});
94+
}
95+
}
96+
97+
spawnFruit() {
98+
const type = this.fruitTypes[Math.floor(Math.random() * this.fruitTypes.length)];
99+
const fruit = {
100+
x: Math.random() * this.canvas.width,
101+
y: this.canvas.height,
102+
radius: 30,
103+
speedY: -10 - Math.random() * 5,
104+
rotation: 0,
105+
rotationSpeed: (Math.random() - 0.5) * 0.2,
106+
type: type,
107+
points: type === 'bomb' ? 0 : 10
108+
};
109+
this.fruits.push(fruit);
110+
}
111+
112+
updateFruits(deltaTime) {
113+
this.fruits.forEach((fruit, index) => {
114+
fruit.y += fruit.speedY * deltaTime / 16;
115+
fruit.x += (fruit.speedX || 0) * deltaTime / 16;
116+
fruit.rotation += fruit.rotationSpeed * deltaTime / 16;
117+
fruit.speedY += 0.2; // gravity
118+
if (fruit.y - fruit.radius > this.canvas.height) {
119+
if (!fruit.isSlice && fruit.type !== 'bomb') {
120+
this.lives--;
121+
if (this.lives <= 0) {
122+
this.gameState = 'gameover';
123+
}
124+
}
125+
this.fruits.splice(index, 1);
126+
}
127+
});
128+
}
129+
130+
drawFruits() {
131+
this.fruits.forEach(fruit => {
132+
this.ctx.save();
133+
this.ctx.translate(fruit.x, fruit.y);
134+
this.ctx.rotate(fruit.rotation);
135+
this.ctx.drawImage(this.fruitImages[fruit.type], -fruit.radius, -fruit.radius, fruit.radius * 2, fruit.radius * 2);
136+
this.ctx.restore();
137+
});
138+
}
139+
140+
drawSlices() {
141+
this.ctx.strokeStyle = 'white';
142+
this.ctx.lineWidth = 3;
143+
this.ctx.beginPath();
144+
this.slices.forEach((slice, index) => {
145+
if (index === 0) {
146+
this.ctx.moveTo(slice.x, slice.y);
147+
} else {
148+
this.ctx.lineTo(slice.x, slice.y);
149+
}
150+
if (Date.now() - slice.time > 100) {
151+
this.slices.splice(index, 1);
152+
}
153+
});
154+
this.ctx.stroke();
155+
}
156+
157+
drawLives() {
158+
this.ctx.fillStyle = 'red';
159+
for (let i = 0; i < this.lives; i++) {
160+
this.ctx.fillRect(10 + i * 30, 40, 20, 20);
161+
}
162+
}
163+
164+
gameLoop(currentTime) {
165+
const deltaTime = currentTime - this.lastTime;
166+
this.lastTime = currentTime;
167+
168+
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
169+
170+
if (this.gameState === 'playing') {
171+
if (currentTime - this.lastFruitTime > this.fruitInterval) {
172+
this.spawnFruit();
173+
this.lastFruitTime = currentTime;
174+
}
175+
176+
this.updateFruits(deltaTime);
177+
this.drawFruits();
178+
this.drawSlices();
179+
this.drawLives();
180+
} else if (this.gameState === 'gameover') {
181+
this.ctx.fillStyle = 'black';
182+
this.ctx.font = '48px Arial';
183+
this.ctx.fillText('Game Over', this.canvas.width / 2 - 100, this.canvas.height / 2);
184+
this.ctx.fillText(`Score: ${this.score}`, this.canvas.width / 2 - 70, this.canvas.height / 2 + 60);
185+
}
186+
187+
requestAnimationFrame((time) => this.gameLoop(time));
188+
}
189+
}
190+
191+
window.onload = () => {
192+
new FruitGame();
193+
};

apps/game/fruit/index.html

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!DOCTYPE html>
2+
<html lang="zh-CN">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6+
<title>切水果游戏</title>
7+
<link rel="stylesheet" href="style.css">
8+
</head>
9+
<body>
10+
<div id="game-container">
11+
<canvas id="game-canvas"></canvas>
12+
<div id="score">分数: <span id="score-value">0</span></div>
13+
</div>
14+
<script src="game.js"></script>
15+
</body>
16+
</html>

apps/game/fruit/readme.md

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# 手机网页端切水果游戏
2+
3+
这是一个简单而有趣的切水果游戏,专为手机网页端设计。玩家通过触摸屏幕来切割飞来的水果,获得分数。
4+
5+
## 游戏特点
6+
7+
- 响应式设计,适合各种手机屏幕
8+
- 流畅的动画效果
9+
- 逐渐增加的难度
10+
- 计分系统
11+
12+
## 技术栈
13+
14+
- HTML5
15+
- CSS3
16+
- JavaScript (使用 Canvas API)
17+
18+
## 开发计划
19+
20+
1. 创建基本的游戏界面
21+
2. 实现水果的生成和动画
22+
3. 添加切割检测和效果
23+
4. 实现计分系统
24+
5. 添加音效
25+
6. 优化性能和触摸响应
26+
27+
## 如何运行
28+
29+
1. 克隆此仓库
30+
2. 打开 `index.html` 文件在浏览器中运行
31+
3. 在手机浏览器中访问部署后的URL
32+
33+
## 贡献
34+
35+
欢迎提出建议和改进意见!
36+

apps/game/fruit/style.css

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
body, html {
2+
margin: 0;
3+
padding: 0;
4+
width: 100%;
5+
height: 100%;
6+
overflow: hidden;
7+
background-color: #87CEEB; /* 天蓝色背景 */
8+
}
9+
10+
#game-container {
11+
position: relative;
12+
width: 100%;
13+
height: 100%;
14+
}
15+
16+
#game-canvas {
17+
position: absolute;
18+
top: 0;
19+
left: 0;
20+
width: 100%;
21+
height: 100%;
22+
}
23+
24+
#score {
25+
position: absolute;
26+
top: 10px;
27+
left: 10px;
28+
font-size: 24px;
29+
color: white;
30+
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
31+
z-index: 10;
32+
}

0 commit comments

Comments
 (0)