feat: implement Suika Game (Watermelon Game)

Browser-based physics puzzle game where players drop fruits that merge
into larger fruits on collision, using Matter.js for 2D physics and
Canvas2D for rendering. Includes 11-fruit progression chain, scoring,
game-over detection, mouse/touch input, and Vitest test suite.
This commit is contained in:
2026-04-12 10:26:38 +07:00
parent 00d6bb117b
commit fbec9c89fd
19 changed files with 2385 additions and 0 deletions

35
src/merger.test.js Normal file
View File

@@ -0,0 +1,35 @@
import { describe, it, expect } from 'vitest';
import { computeMergePoints, computeMidpoint } from './merger.js';
import { FRUITS } from './fruits.js';
describe('merger', () => {
describe('computeMergePoints', () => {
it('returns points of the next tier fruit', () => {
expect(computeMergePoints(0)).toBe(FRUITS[1].points); // Cherry -> Strawberry points
expect(computeMergePoints(3)).toBe(FRUITS[4].points); // Dekopon -> Persimmon points
expect(computeMergePoints(9)).toBe(FRUITS[10].points); // Melon -> Watermelon points
});
it('returns 66 when merging two watermelons (tier 10)', () => {
expect(computeMergePoints(10)).toBe(66);
});
});
describe('computeMidpoint', () => {
it('calculates the midpoint of two bodies', () => {
const bodyA = { position: { x: 100, y: 200 } };
const bodyB = { position: { x: 300, y: 400 } };
const mid = computeMidpoint(bodyA, bodyB);
expect(mid.x).toBe(200);
expect(mid.y).toBe(300);
});
it('handles same position', () => {
const bodyA = { position: { x: 150, y: 250 } };
const bodyB = { position: { x: 150, y: 250 } };
const mid = computeMidpoint(bodyA, bodyB);
expect(mid.x).toBe(150);
expect(mid.y).toBe(250);
});
});
});