<?phpnamespace Tests;use App\Scene\LevelScene;use App\Scene\PauseScene;use App\Scene\PlayScene;use App\Scene\ResultScene;use App\Scene\TitleScene;use App\Sim\Lumi;use JumPHP\Testing\GameTestCase;/** The game played like a player does: with clicks on the bar and on the Lumikins. */final class PlayTest extends GameTestCase{ private function click(float $x, float $y, int $frames = 2): void { $mouse = $this->game->engine->input->getMouse(); $mouse->move($x, $y); $mouse->down(1); $this->game->run(1); $mouse->up(1); $this->game->run($frames); } private function play(int $level): PlayScene { $scene = $this->game->start(PlayScene::class, ['level' => $level]); self::assertInstanceOf(PlayScene::class, $scene); return $scene; } public function testTheTitleShowsALevelPlayingItself(): void { $this->game->start(TitleScene::class); $this->game->run(240); self::assertInstanceOf(TitleScene::class, $this->game->scene()); } public function testClickingPlayOpensTheLevelMapAndTheFirstLevel(): void { $this->game->start(TitleScene::class); $this->click(240, 160, 40); self::assertInstanceOf(LevelScene::class, $this->game->scene()); $this->click(40, 60, 40); self::assertInstanceOf(PlayScene::class, $this->game->scene()); } public function testClickingALumikinWithTheShovelMakesItDig(): void { $scene = $this->play(0); $this->game->run(150); $world = $scene->world(); $lumi = $world->lumis[0]; self::assertSame(Lumi::WALK, $lumi->state); [$bx, $by] = PlayScene::buttons()['dig']; $this->click($bx + 10, $by + 10); $this->click($lumi->x - $scene->camX(), $lumi->y - 6); self::assertSame(Lumi::DIG, $lumi->state); self::assertSame(2, $world->skills['dig']); $this->game->run(60); self::assertGreaterThan(120, $lumi->y); } public function testDiggingThroughTheLedgeBringsEveryoneHome(): void { $scene = $this->play(0); $this->game->press('fast'); $this->game->run(60); $lumi = $scene->world()->lumis[0]; while ($lumi->x < 110) { $this->game->run(1); } $this->click($lumi->x - $scene->camX(), $lumi->y - 6); $this->game->run(900); self::assertInstanceOf(ResultScene::class, $this->game->scene()); self::assertTrue($this->game->peek('result')['won']); self::assertSame(10, $scene->world()->saved); } public function testDraggingTheLevelScrollsIt(): void { $scene = $this->play(1); $mouse = $this->game->engine->input->getMouse(); $before = $scene->camX(); $mouse->move(400, 40); $mouse->down(1); $this->game->run(1); $mouse->move(250, 40); $this->game->run(2); $mouse->up(1); $this->game->run(1); self::assertEqualsWithDelta($before + 150, $scene->camX(), 1); } public function testThePauseButtonFreezesTheLevel(): void { $scene = $this->play(0); $this->game->run(100); [$bx, $by] = PlayScene::buttons()['pause']; $this->click($bx + 10, $by + 10); self::assertInstanceOf(PauseScene::class, $this->game->scene()); $tick = $scene->world()->tick; $this->game->run(60); self::assertSame($tick, $scene->world()->tick); $this->game->press('pause', 3); self::assertInstanceOf(PlayScene::class, $this->game->scene()); } public function testPressingTheBurstButtonTwiceEndsTheLevelLost(): void { $scene = $this->play(0); $this->game->run(120); [$bx, $by] = PlayScene::buttons()['nuke']; $this->click($bx + 10, $by + 10); self::assertFalse($scene->world()->nuked); $this->click($bx + 10, $by + 10); self::assertTrue($scene->world()->nuked); $this->game->run(400); self::assertInstanceOf(ResultScene::class, $this->game->scene()); self::assertFalse($this->game->peek('result')['won']); } public function testZoomingInKeepsTheClicksOnTheLumikins(): void { $scene = $this->play(0); $this->game->run(150); $lumi = $scene->world()->lumis[0]; $scene->zoomAt(2.0, $lumi->x - $scene->camX(), $lumi->y - 6); self::assertEqualsWithDelta(2.0, $scene->zoom(), 0.01); $this->game->run(2); $this->click(($lumi->x - $scene->camX()) * 2, ($lumi->y - 6 - $scene->camY()) * 2); self::assertSame(Lumi::DIG, $lumi->state); $scene->zoomAt(0.2, 240, 100); self::assertSame(1.0, $scene->zoom()); self::assertSame(0.0, $scene->camY()); } private function finger(string $type, int $id, float $x, float $y): void { $f = new \stdClass(); $f->fingerId = $id; $f->x = $x; $f->y = $y; $e = new \stdClass(); $e->type = $type === 'down' ? \SDL_FINGERDOWN : ($type === 'up' ? \SDL_FINGERUP : \SDL_FINGERMOTION); $e->tfinger = $f; $this->game->scene()->pinch()->handle($e, $this->game->engine->sdl->getRenderer()); } public function testPinchingZoomsAndLiftingOneFingerDoesNotMoveTheCamera(): void { $scene = $this->play(1); $this->game->run(5); $mouse = $this->game->engine->input->getMouse(); $mouse->move(200, 100); $mouse->down(1); // the first finger is also the mouse (SDL) $this->finger('down', 1, 0.40, 0.40); $this->game->run(1); $this->finger('down', 2, 0.45, 0.40); for ($i = 1; $i <= 10; $i++) { // the fingers move apart $this->finger('move', 1, 0.40 - $i * 0.01, 0.40); $this->finger('move', 2, 0.45 + $i * 0.01, 0.40); $this->game->run(1); } self::assertGreaterThan(1.5, $scene->zoom()); $cam = [$scene->camX(), $scene->camY()]; $this->finger('up', 2, 0.55, 0.40); // one finger lifts, the other one slides $mouse->move(120, 60); $this->game->run(3); self::assertSame($cam, [$scene->camX(), $scene->camY()]); $mouse->up(1); $this->finger('up', 1, 0.30, 0.40); $this->game->run(2); self::assertFalse($scene->pinch()->active()); } public function testALostFingerUpDoesNotLeaveAPinchOn(): void { $scene = $this->play(1); $this->finger('down', 1, 0.4, 0.4); $this->finger('down', 2, 0.5, 0.4); self::assertTrue($scene->pinch()->active()); $this->game->run(15); // no finger-up ever came, the mouse is not held self::assertFalse($scene->pinch()->active()); } public function testEveryLanguageDrawsItsTexts(): void { $lang = $this->game->engine->lang; foreach ($lang->available() as $code) { $lang->setLang($code); $this->game->start(LevelScene::class); $this->game->run(2); $this->play(0); $this->game->run(3); } $lang->setLang('en'); self::assertGreaterThanOrEqual(14, count($lang->available())); }}