Files
libakgl/docs/tutorials/assets/sidescroller/tiles.png

9 lines
1.4 KiB
Plaintext
Raw Normal View History

Add two tutorial games that build, run in CI, and cannot drift examples/sidescroller and examples/jrpg are complete programs, built with the library and exercised headless by ctest. The chapters quote them with `c excerpt=examples/...` blocks rather than restating the code, so a chapter cannot drift from a program that compiles -- the excerpt check fails the moment the source moves. 34 excerpts in one chapter, 21 in the other. The two are complementary. The sidescroller is the physics tutorial: gravity, a jump, coins, hazards. The JRPG is the content-pipeline tutorial: a town map, NPCs spawned from map objects, four-way per-facing animation, a text box, a follower. Both smoke tests drive real SDL_Events through akgl_controller_handle_event and step the physics clock at a fixed 1/60s rather than sleeping, so a scripted run is deterministic and finishes in under five seconds. Writing them is what turned up most of the defects recorded in the next commit, because a game exercises paths a unit test does not. Each workaround says in the chapter which library gap forced it: - collision is written in a custom movementlogicfunc, because akgl_physics_arcade_collide raises AKERR_API and akgl_physics_simulate never calls collide at all; - the sidescroller cancels the step's own gravity when it blocks downward, because otherwise a quarter-pixel of penetration makes the *horizontal* sweep report blocked and the character walks backwards a tile at a time; - both clear movement_controls_face on every map-spawned actor, because the default facefunc leaves a stopped actor with no facing bit, no sprite, and no draw; - the JRPG's follower gets a renderfunc that nulls obj->parent for the duration of the draw, because a child's offset is counted twice. Assets are CC0 from three Kenney packs, vendored with per-pack licence text, per-file provenance, and the geometry contract in docs/tutorials/assets/README.md. CC0 specifically rather than merely free: a reader who copies a tutorial into their own game inherits no obligation. scripts/fetch_tutorial_assets.sh refreshes them in the shape mkcontrollermappings.sh was fixed into for 0.5.0 -- it checks curl's status, refuses a pack page that does not say CC0, verifies the archive and the staged dimensions, and leaves the tracked bytes untouched on any failure. Both failure paths were tested, and a no-op refresh is byte-identical. Co-Authored-By: Claude Code <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 20:59:00 -04:00
<EFBFBD>PNG

IHDR<00>`h d<>gAMA<00><> <0B>a-PLTEڤ<>ˁ^<5E><>yCJ_<4A><5F><01><><EFBFBD>49<34><39> <20>h;<3B><><EFBFBD>,<2C><>٤<EFBFBD><D9A4><EFBFBD><<3C><><EFBFBD><15>c<EFBFBD>tRNS@<40><>f<04>IDATX<54>ݘ<EFBFBD>k<EFBFBD>Fǧ09{<17><1C><>/<2F>[<5B>#8<38><7F><EFBFBD><EFBFBD>
<EFBFBD>pl<EFBFBD>n1ƥHe<48><65><EFBFBD><EFBFBD>c<EFBFBD><63>Tˆ <08>H' <09>p<EFBFBD>R<EFBFBD><52><13><>2o~H3<48>i%<25><><EFBFBD>c<EFBFBD><63>3;<3B><><EFBFBD><EFBFBD>Ǜ<EFBFBD><10>Yf<59><66>z<EFBFBD>l<EFBFBD><6C><EFBFBD>¼<EFBFBD>><3E><03><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>><3E><><EFBFBD> <14><>x<EFBFBD><78><EFBFBD>~<7E><03> <20><04><>@<40><>ԗ<EFBFBD>Bb<42><62><EFBFBD><EFBFBD>
o<16>!<21><18>@k<>X <0C><><EFBFBD>"`<16><1E><>ԲzXT<58>p<EFBFBD>(3߲Rz
q<EFBFBD><EFBFBD><EFBFBD>@<40><>'ŷ/<1A>Ӏ<EFBFBD>+<2B>̇}<07>-C<>-<2D><><EFBFBD><EFBFBD>220%a<><61>G<01><><1A><><p<>-<2D>F:"<22><10><><68>X<EFBFBD>m{Jy{Vi<56><69><EFBFBD><EFBFBD><EFBFBD>
iW<06>),<2C>FՕU̿<55><CCBF><EFBFBD><EFBFBD><EFBFBD><EE90B3>.<2E><>dg:<3A><><EFBFBD><EFBFBD>N+kWH@<40><><EFBFBD><EFBFBD>KʩR<CAA9><52><EFBFBD>CL<>l qB><3E><><EFBFBD>=ϲOY<1C>@<40><><EFBFBD><EFBFBD>z<EFBFBD>Kj<4B>r<EFBFBD><72><EFBFBD><EFBFBD>H<><48>E<EFBFBD><45><08><><EFBFBD>'<27><00>$u}<7D><><EFBFBD>S<EFBFBD>:<<3C><>RI9qC<71>`<60><><EFBFBD>̖<EFBFBD>f_?P[<5B><>G<EFBFBD>N<EFBFBD>z<EFBFBD><7A>:<1F>Z<><5A> y|<7C><>sp^==(<1E>H<>4<EFBFBD><34><EFBFBD><EFBFBD><EFBFBD><EFBFBD>k<EFBFBD><6B><00><>_<EFBFBD><5F>`<60><><1C>
<EFBFBD>e<EFBFBD><EFBFBD>k@<40><>ݼH<><04><><EFBFBD>L S<><53><EFBFBD>q |$<24><><EFBFBD><EFBFBD><EFBFBD>`<1D><>u<EFBFBD>n<EFBFBD><02><>X<>w<EFBFBD><19><>Σ@<40><>\<5C><><EFBFBD>e`<60><>Q}м<><D0BC>~'<27>.<2E><> f<>2 lL<>W<EFBFBD>8<EFBFBD><38><EFBFBD>?<3F>_<EFBFBD><5F>-q<>%V<>;<3B>wV<>e ^ oe WJ<03><15>q<EFBFBD>X8<58>I<EFBFBD><00>I\<5C><><06>"<22>_!@O<11><>c<EFBFBD><63><EFBFBD><EFBFBD>a@c<1F>7<EFBFBD>{<7B>D<1C>ݨB<DDA8>ނ<EFBFBD><DE82>s1<73> <0B>1m<14><><08>_<EFBFBD>yp^c<>}<7D>Z<EFBFBD>R<>.g<>j<EFBFBD><6A><EFBFBD>BV+S<>I<EFBFBD> <0A>a#<23><><EFBFBD><EFBFBD><EFBFBD>Ya.<2E><> <09><>I! t <0B><><00><><EFBFBD>L<EFBFBD>^(<28><14>Z<1F>zy <0C>PS^,<19><>}t<08><>3a<><61><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>u<EFBFBD><75><EFBFBD>nZ;z<12>!M#v<><76><EFBFBD>Z<EFBFBD><5A><EFBFBD>4<EFBFBD><34><EFBFBD>DrECz/{Wz<57>J;<3B><>L! e(ZG<5A>Z<EFBFBD><5A><EFBFBD>9<1E>U<EFBFBD>];0Ҁ= <09>+<2B><>@G<>< <09>.D<><44>=<3D><> <18>|(5<><35>_<EFBFBD><5F>n" <10>a<EFBFBD><61>4<EFBFBD><34>@(<28>L!<21>2y<><79>2<><32>J<EFBFBD><4A><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0=<3D>ۋ<EFBFBD><DB8B>iP@ٔ<08><><0E><><EFBFBD>4<EFBFBD><34>6?E<><45>\<5C>'6<> W6<57>?E<><45><EFBFBD>@<40>+e.i<><69><EFBFBD>]<5D><><77>-<2D><>v<17><><EFBFBD><EFBFBD>N^˧\<19><><EFBFBD>ߩ<EFBFBD>~snXy3e<33><65><EFBFBD>M IJ<><C4B2><EFBFBD><EFBFBD>2f>y<><79>g<>l<EFBFBD><6C><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>5z><3E>i-K<>f<01> N<00><><EFBFBD>+<2B>"<22>į<01> '<27> -N<17><><EFBFBD>8<><38><EFBFBD>p5)Vh<>L<EFBFBD><03>l<EFBFBD>! <10>Ǚ<EFBFBD><C799>J<02>><13><>3<EFBFBD>|<7C>x<EFBFBD>j<07><><EFBFBD><04>|<08>kt<><74><EFBFBD>T<EFBFBD>zm<7A><6D><EFBFBD>iB>|<7C>3b+M<>j<EFBFBD> $<24>'Kvc<0E>b[>D<15><1C>bm<><6D>.}<7D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><0F>U<EFBFBD><55><EFBFBD>2<><32><EFBFBD><EFBFBD><EFBFBD>2<10>5b<35>+<2B>tb<74>k <07><><EFBFBD>"D<><44><EFBFBD><00>A<EFBFBD><41><EFBFBD><EFBFBD><EFBFBD>*<2A> n'<04><><EFBFBD><EFBFBD><EFBFBD>n<> <0C><>ó<EFBFBD> SƼ<0F>$a <20><><00>d0<64><30><07>x<05><><EFBFBD>Dz<44>_lu<07>IEND<4E>B`<60>