From 9cfee49590526bf675c169d79d72c9dc85bcfd7e Mon Sep 17 00:00:00 2001
From: brxxh <11dac2t@huhn-online.de>
Date: Fri, 30 May 2025 17:27:11 +0200
Subject: [PATCH] Add tappyplane; Fix design problems

TappyPlane is the new QuickWings using the Kenney assets
---
 examples/CMakeLists.txt                       |   2 +-
 examples/quickwings/CMakeLists.txt            |  23 -
 examples/quickwings/assets/background-day.png | Bin 10361 -> 0 bytes
 examples/quickwings/assets/base.png           | Bin 1963 -> 0 bytes
 examples/quickwings/assets/gameover.png       | Bin 758 -> 0 bytes
 examples/quickwings/assets/message.png        | Bin 1602 -> 0 bytes
 examples/quickwings/assets/pipe-green.png     | Bin 2527 -> 0 bytes
 .../quickwings/assets/yellowbird-downflap.png | Bin 426 -> 0 bytes
 .../quickwings/assets/yellowbird-midflap.png  | Bin 425 -> 0 bytes
 .../quickwings/assets/yellowbird-upflap.png   | Bin 427 -> 0 bytes
 examples/quickwings/quickwings.cpp            | 546 ------------------
 examples/tappyplane/CMakeLists.txt            |  18 +
 .../assets}/Font/kenvector_future.ttf         | Bin
 .../assets}/Font/kenvector_future_thin.ttf    | Bin
 .../assets}/PNG/Letters/letterA.png           | Bin
 .../assets}/PNG/Letters/letterB.png           | Bin
 .../assets}/PNG/Letters/letterC.png           | Bin
 .../assets}/PNG/Letters/letterD.png           | Bin
 .../assets}/PNG/Letters/letterE.png           | Bin
 .../assets}/PNG/Letters/letterF.png           | Bin
 .../assets}/PNG/Letters/letterG.png           | Bin
 .../assets}/PNG/Letters/letterH.png           | Bin
 .../assets}/PNG/Letters/letterI.png           | Bin
 .../assets}/PNG/Letters/letterJ.png           | Bin
 .../assets}/PNG/Letters/letterK.png           | Bin
 .../assets}/PNG/Letters/letterL.png           | Bin
 .../assets}/PNG/Letters/letterM.png           | Bin
 .../assets}/PNG/Letters/letterN.png           | Bin
 .../assets}/PNG/Letters/letterO.png           | Bin
 .../assets}/PNG/Letters/letterP.png           | Bin
 .../assets}/PNG/Letters/letterQ.png           | Bin
 .../assets}/PNG/Letters/letterR.png           | Bin
 .../assets}/PNG/Letters/letterS.png           | Bin
 .../assets}/PNG/Letters/letterT.png           | Bin
 .../assets}/PNG/Letters/letterU.png           | Bin
 .../assets}/PNG/Letters/letterV.png           | Bin
 .../assets}/PNG/Letters/letterW.png           | Bin
 .../assets}/PNG/Letters/letterX.png           | Bin
 .../assets}/PNG/Letters/letterY.png           | Bin
 .../assets}/PNG/Letters/letterZ.png           | Bin
 .../assets}/PNG/Numbers/number0.png           | Bin
 .../assets}/PNG/Numbers/number1.png           | Bin
 .../assets}/PNG/Numbers/number2.png           | Bin
 .../assets}/PNG/Numbers/number3.png           | Bin
 .../assets}/PNG/Numbers/number4.png           | Bin
 .../assets}/PNG/Numbers/number5.png           | Bin
 .../assets}/PNG/Numbers/number6.png           | Bin
 .../assets}/PNG/Numbers/number7.png           | Bin
 .../assets}/PNG/Numbers/number8.png           | Bin
 .../assets}/PNG/Numbers/number9.png           | Bin
 .../assets}/PNG/Planes/planeBlue1.png         | Bin
 .../assets}/PNG/Planes/planeBlue2.png         | Bin
 .../assets}/PNG/Planes/planeBlue3.png         | Bin
 .../assets}/PNG/Planes/planeGreen1.png        | Bin
 .../assets}/PNG/Planes/planeGreen2.png        | Bin
 .../assets}/PNG/Planes/planeGreen3.png        | Bin
 .../assets}/PNG/Planes/planeRed1.png          | Bin
 .../assets}/PNG/Planes/planeRed2.png          | Bin
 .../assets}/PNG/Planes/planeRed3.png          | Bin
 .../assets}/PNG/Planes/planeYellow1.png       | Bin
 .../assets}/PNG/Planes/planeYellow2.png       | Bin
 .../assets}/PNG/Planes/planeYellow3.png       | Bin
 .../assets}/PNG/UI/UIbg.png                   | Bin
 .../assets}/PNG/UI/buttonLarge.png            | Bin
 .../assets}/PNG/UI/buttonSmall.png            | Bin
 .../assets}/PNG/UI/medalBronze.png            | Bin
 .../assets}/PNG/UI/medalGold.png              | Bin
 .../assets}/PNG/UI/medalSilver.png            | Bin
 .../assets}/PNG/UI/tap.png                    | Bin
 .../assets}/PNG/UI/tapLeft.png                | Bin
 .../assets}/PNG/UI/tapRight.png               | Bin
 .../assets}/PNG/UI/tapTick.png                | Bin
 .../assets}/PNG/UI/textGameOver.png           | Bin
 .../assets}/PNG/UI/textGetReady.png           | Bin
 .../assets}/PNG/background.png                | Bin
 .../assets}/PNG/groundDirt.png                | Bin
 .../assets}/PNG/groundGrass.png               | Bin
 .../assets}/PNG/groundIce.png                 | Bin
 .../assets}/PNG/groundRock.png                | Bin
 .../assets}/PNG/groundSnow.png                | Bin
 .../assets}/PNG/puffLarge.png                 | Bin
 .../assets}/PNG/puffSmall.png                 | Bin
 .../assets}/PNG/rock.png                      | Bin
 .../assets}/PNG/rockDown.png                  | Bin
 .../assets}/PNG/rockGrass.png                 | Bin
 .../assets}/PNG/rockGrassDown.png             | Bin
 .../assets}/PNG/rockIce.png                   | Bin
 .../assets}/PNG/rockIceDown.png               | Bin
 .../assets}/PNG/rockSnow.png                  | Bin
 .../assets}/PNG/rockSnowDown.png              | Bin
 .../assets}/PNG/starBronze.png                | Bin
 .../assets}/PNG/starGold.png                  | Bin
 .../assets}/PNG/starSilver.png                | Bin
 .../assets}/Spritesheet/planes.png            | Bin
 .../assets}/Spritesheet/planes.xml            |   0
 .../assets}/Spritesheet/sheet.png             | Bin
 .../assets}/Spritesheet/sheet.xml             |   0
 .../assets}/Vector/vector.svg                 |   0
 .../assets}/Vector/vector.swf                 | Bin
 .../assets}/license.txt                       |   0
 .../assets}/preview.png                       | Bin
 .../assets}/sample.png                        | Bin 81791 -> 81792 bytes
 examples/tappyplane/tappyplane.cpp            | 456 +++++++++++++++
 103 files changed, 475 insertions(+), 570 deletions(-)
 delete mode 100644 examples/quickwings/CMakeLists.txt
 delete mode 100644 examples/quickwings/assets/background-day.png
 delete mode 100644 examples/quickwings/assets/base.png
 delete mode 100644 examples/quickwings/assets/gameover.png
 delete mode 100644 examples/quickwings/assets/message.png
 delete mode 100644 examples/quickwings/assets/pipe-green.png
 delete mode 100644 examples/quickwings/assets/yellowbird-downflap.png
 delete mode 100644 examples/quickwings/assets/yellowbird-midflap.png
 delete mode 100644 examples/quickwings/assets/yellowbird-upflap.png
 delete mode 100644 examples/quickwings/quickwings.cpp
 create mode 100644 examples/tappyplane/CMakeLists.txt
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/Font/kenvector_future.ttf (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/Font/kenvector_future_thin.ttf (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterA.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterB.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterC.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterD.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterE.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterF.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterG.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterH.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterI.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterJ.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterK.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterL.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterM.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterN.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterO.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterP.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterQ.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterR.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterS.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterT.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterU.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterV.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterW.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterX.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterY.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Letters/letterZ.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Numbers/number0.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Numbers/number1.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Numbers/number2.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Numbers/number3.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Numbers/number4.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Numbers/number5.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Numbers/number6.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Numbers/number7.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Numbers/number8.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Numbers/number9.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Planes/planeBlue1.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Planes/planeBlue2.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Planes/planeBlue3.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Planes/planeGreen1.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Planes/planeGreen2.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Planes/planeGreen3.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Planes/planeRed1.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Planes/planeRed2.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Planes/planeRed3.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Planes/planeYellow1.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Planes/planeYellow2.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/Planes/planeYellow3.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/UI/UIbg.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/UI/buttonLarge.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/UI/buttonSmall.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/UI/medalBronze.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/UI/medalGold.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/UI/medalSilver.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/UI/tap.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/UI/tapLeft.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/UI/tapRight.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/UI/tapTick.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/UI/textGameOver.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/UI/textGetReady.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/background.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/groundDirt.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/groundGrass.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/groundIce.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/groundRock.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/groundSnow.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/puffLarge.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/puffSmall.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/rock.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/rockDown.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/rockGrass.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/rockGrassDown.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/rockIce.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/rockIceDown.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/rockSnow.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/rockSnowDown.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/starBronze.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/starGold.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/PNG/starSilver.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/Spritesheet/planes.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/Spritesheet/planes.xml (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/Spritesheet/sheet.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/Spritesheet/sheet.xml (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/Vector/vector.svg (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/Vector/vector.swf (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/license.txt (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/preview.png (100%)
 rename examples/{quickwings/assets/tappybird => tappyplane/assets}/sample.png (99%)
 create mode 100644 examples/tappyplane/tappyplane.cpp

diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 9d4c49a..713b59e 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,3 +1,3 @@
 add_subdirectory(simple)
 add_subdirectory(pong)
-add_subdirectory(quickwings)
\ No newline at end of file
+add_subdirectory(tappyplane)
diff --git a/examples/quickwings/CMakeLists.txt b/examples/quickwings/CMakeLists.txt
deleted file mode 100644
index 5ac3667..0000000
--- a/examples/quickwings/CMakeLists.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-set(quickwings_srcs quickwings.cpp)
-set(quickwings_assets
-    assets/background-day.png
-    assets/base.png
-    assets/pipe-green.png
-    assets/yellowbird-downflap.png
-    assets/yellowbird-midflap.png
-    assets/yellowbird-upflap.png
-    )
-
-set_source_files_properties(${quickwings_assets} PROPERTIES HEADER_FILE_ONLY TRUE)
-
-add_executable(quickwings ${quickwings_srcs} ${quickwings_assets})
-
-target_link_libraries(quickwings paradiso_core)
-
-#
-# copy files to bin/../assets folder
-#
-add_custom_command(TARGET quickwings POST_BUILD
-                   COMMAND ${CMAKE_COMMAND} -E copy_directory
-                   ${CMAKE_CURRENT_SOURCE_DIR}/assets/
-                   $<TARGET_FILE_DIR:quickwings>/assets)
diff --git a/examples/quickwings/assets/background-day.png b/examples/quickwings/assets/background-day.png
deleted file mode 100644
index f9ed139c84f87b86b0ea31e47c729fde44f8b70d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 10361
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
S_a@o^))v>zYp&jX`hNgJt<;$S

diff --git a/examples/quickwings/assets/base.png b/examples/quickwings/assets/base.png
deleted file mode 100644
index 26fa39129aa33fe2b906d9b77751651fee1a2272..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1963
zcmeAS@N?(olHy`uVBq!ia0y~yVEh4O7jUov$xnNd>VN`yna<7unaRlv3>p(lC)#=+
z4iIUZALhETtBKE5#wesPBT(c>;OhrLORjL$>E`A{E$mdxocKs<hlPlYi}-%F|BdUK
zRyQeVG<D409pCL?b6qUTC4Yw{|NFh~A3ovzkz9GVMEdx_EnI#{TC2{U)z3J4o`vJm
zNrin=-rW-ZSkY5|{kX1OXui^_>;J$1i)nn?v$}b`YemTRxlJ2<oO9MDXx|fhcddA3
z>O<y-8<d&3;<apJAF3a{$+cgzY*MG^ht>0<w)I^uUGrQfxWd6A<ym)CsoYo9T*>S*
zx2*m*aWO(Zg09NG6GcCXba-r4*}T8j*?wPU*wMwOZ!c?6?$fdS*ygJ1b-gFV`Ad&Y
zrI*(C`<1(nohVpZ9W63T&i4IQ{#n}}u6|QFzkS~KQWjqRg1oDLR!_QoWA}@vv&3$-
z_wicnU6J`x*5Y={gS~T$g6xBubM_}5IL*1`yz_O_EqY;_R?RD}VLw^=(=~j<ZuY-L
z`;%Wvb1ll?bNjxt9T)+e1s;*b3=DinK$vl=HlH*D1M6c?7srqa#<zDJyMzNpS|7SF
zy*u35p}=>yk%O;PHSfSq=|b^!PEybFoTr4H+OtG!Y2&-LKR@Rz`846h&v&_g^Mtp*
zkK6li=f`daMkW>x0S`_aucd-*5Y7+X4S)YVo-Dm5Rl%VFC}hZJ{^N$jQAIFkJJW6c
z__#Tx&Gp~D{ERFzzrSzZ*Wb1Oti<K*7B|daADH~_OnRQtybqG5&(2SO_n6Io{z_qx
z4GIMxnRfs8eei6D-qH5+8U-)!|M~m(c;>nJKhO9c6SiA??9b1IHFq97|K<l&>(FrE
zDEFVwZ12-{*(KZ6xHY!_O0)YnGyD9vV&C-54-cn{toZw9*TMeFUwuFhWKm*L&;PLR
z<~siw{PP1Bd^=lzX4{vX|I<UhrPq8D^Y*Wq24s~#eayDs{HqICgAvna=|8cx#TKeh
zKKq~iWBD9t<Oh9bpetsczmsC~&^YVN{MUAQA3o2thIm_C|HF5-_s@3Nd4rtu%lyCL
z>$jW#+KXA%oPU1d@ekSg$rBHM{|>aG{>2+vNRV>8dG~tu;U$kht9L#Pw>zzOS#!Q;
z($A^qH=Qmyl|Ct=?&;<?MswqK^-KRT@mvoIAqNGO4YmJ2o{aoIJ4R!-21H2v0o#1p
zwF%%5Jj--@_WAs~57t*Qr>FyCqj5=tbWPD3CqYnvZRLI=x4)+NE!!tyP_#A90m|hq
zVFJl9G@f-kc$*0v4FVzo9}X_;f&_!e9$AnyBa<T|tGvuA53rRE2XBKtpfIX*Gz3ON
eV4y<afw=a<BLRmtHa7$700vK2KbLh*2~7Yj4YySQ

diff --git a/examples/quickwings/assets/gameover.png b/examples/quickwings/assets/gameover.png
deleted file mode 100644
index b1df7f5757198bec3b165e12bc139b94178b8f19..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 758
zcmeAS@N?(olHy`uVBq!ia0vp^2Y^_Mg&9bS>v~=QQY`6?zK#qG8~eHcB(ehe3dtTp
zz6=aistgPb%?u1b{{!il3=E|P3=FRl7#OT(0Cnb1ia+WGRBI666XN>+KTrui5MtpD
zL_lSK7I-{KkT{)kY#vZKPf3tpFwlA?HfDB44p#0zv)_qt0E#mvdAqwXbg;^L06Clm
z9+AZi4BWyX%*Zfnjs#GUy~NYkmHja@4+E3%^IxhvfO@8Rx;Tb-9KSmKVD4c99@ni-
z6IhviFD!5n&tUW5pQ+GrG24IE0*Ai6X|3ym)-4d-(xeqF<asje)fUss|C)WH|I`Ss
zwde}+V$L#Eyt;ZHpO@I)*w`sT3=L;@u}z5mu)`$byG!zG=k>Xn{4@1l2{lx8d|iC}
zkYKRyDWm<|FFuJ}t9rC^!>{QK4!%0C_*=p+*QX@Q8NAMrYM7qS=$9^Qwf?+pTIsI|
zCGtVCjI$QCr5u>jz3JY^c_IhCZ`zXJ&A6fT0E68$WkKP!K@C=i3qLkKP;jW-pxkV6
zz?bQSrNym=jgA5V*M2e{xG(ZRiXrZawnOAgF@|`zH@~7B{=7TI{HpTWi=PdjLO+T#
z<cT%R{PFr%J(FG8^5=OMCC^mG*!a9&_w<vFH%CGE|C;b%nbyL)rZM+6=|nah54q1$
zvF)8#c$QE6{7pg$`YZ=x#I80Zs%%|e@bp-Vae~+s-6*~d2k&Tj3(5sq^cXPg(wV1t
zSGsA(qVL|!W>4oU-o9h?Opt8>ukAa*&$cI$lNeYxFSSTa(s+Mk@;w!X`6s)5n8c(H
zn*t+EwZt`|BqgyV)hf9t6-Y4{85mmX8W`&u8ip8JSQ!{u8Cq%^m{}PZJk+v0jG`eo
aKP5A*61Rp4<&E_~4Gf;HelF{r5}E*LS`Uf<

diff --git a/examples/quickwings/assets/message.png b/examples/quickwings/assets/message.png
deleted file mode 100644
index 9243ab58b2910ae63393eb28ac5867237826d7e0..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1602
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

diff --git a/examples/quickwings/assets/pipe-green.png b/examples/quickwings/assets/pipe-green.png
deleted file mode 100644
index 4664401037bdb50a709674c0a23862fa3aa294a4..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2527
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
TGQ#h~fdaq+V~wu7<WBhq1;ecG

diff --git a/examples/quickwings/assets/yellowbird-downflap.png b/examples/quickwings/assets/yellowbird-downflap.png
deleted file mode 100644
index e9e1c77b9deb38738f6f4d184243143bca2da46b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 426
zcmeAS@N?(olHy`uVBq!ia0vp^N<b{Z!VDyHJB+M=6id3JuOkD)#(wTUiL5}rLb6AY
zF9SoBDg#49GXulV|3LaB14F3+1H-EX1_rAc3=HD=lj4uM0o6(e_=LCu>0k@DU)Otn
z{rdG|yYcmBXZ~0)JZRAQ|NsAjlBe20X~vQuzhDN3XE)M7oFs2|7ml`jQ>%a+&H|6f
zVg?3oVGw3ym^DWND9B#o>Fdh=n3;!xN%;9M)g3^gEKe855Q)pZ7Xx_@DDbdch_c|`
z+Rz#`qc!rtzdq>=sjVsBUE?z}5|%k^4ByAJ!`ka$T!g!ToEOuzDa{u&IhFo(WoYXz
zDx9oRkXI(;$Etnt%hpG8VzmpM7VpkfwA$Ns>~Px5;^<#p`}Q%EMVg;vcHSliv{kjl
zHKHUXu_V<hxhNG#F&G&bTIw1Y>lzw{7+P2v7+D!wY8#kY85lg&vOJ8UAvZrIGp!Q0
Uh6&}3^*{{_p00i_>zopr0M`A6wg3PC

diff --git a/examples/quickwings/assets/yellowbird-midflap.png b/examples/quickwings/assets/yellowbird-midflap.png
deleted file mode 100644
index 2ca3c2d034b2332726bb6157591ee3319900c2fc..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 425
zcmeAS@N?(olHy`uVBq!ia0vp^N<b{Z!VDyHJB+M=6id3JuOkD)#(wTUiL5}rLb6AY
zF9SoBDg#49GXulV|3LaB14F3+1H-EX1_rAc3=HD=lj4uM0o6(e_=LCu>0k@DU)Otn
z{rdG|yYcmBXZ~0)JZRAQ|NsAjlBe20X~vQuzhDN3XE)M7oFs2|7ml`jQ>%a+&H|6f
zVg?3oVGw3ym^DWND9B#o>Fdh=n3;!xN%;9M)g3^gOivfb5Q)pJ7ccT2P~cz*2-_hV
zaZog3q4tiZ*WX=k-CFeW?_KXB9ZGT)DW}32LR~d)aPO9UxKJfwxlGFf6@%Z?=Pl^{
zvG%BD+$I544c4p8tvx5#F1#mwQfZCt4!*T6202kV(`MNHKjQ6|w8gBn>)PVeKuc9i
zTq8<S5=&C8l8aJ-6oZk0p{1^Yv96(Eh@pj*fsvJ=rM7{Ym4U%SEz83w8glbfGSez?
VYnV{pSP#^|;OXk;vd$@?2>@t-i!lHI

diff --git a/examples/quickwings/assets/yellowbird-upflap.png b/examples/quickwings/assets/yellowbird-upflap.png
deleted file mode 100644
index 2f693da65360f492a3b364b2231c4419d9c782af..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 427
zcmeAS@N?(olHy`uVBq!ia0vp^N<b{Z!VDyHJB+M=6id3JuOkD)#(wTUiL5}rLb6AY
zF9SoBDg#49GXulV|3LaB14F3+1H-EX1_rAc3=HD=lj4uM0o6(e_=LCu>0k@DU)Otn
z{rdG|yYcmBXZ~0)JZRAQ|NsAjlBe20X~vQuzhDN3XE)M7oFs2|7ml`jQ>%a+&H|6f
zVg?3oVGw3ym^DWND9B#o>Fdh=n3;!xN%;9M)g3^gY)==*5Q)pZ7b67^DDbdch=}0c
z*w7lWf>q~8UGW7c%d}nbAJ~jk1Y89cDsE;t(-Tx6cDq}mWY$sdu9K+~ws_3@r^r9I
zCHG+9?$S+MuIzlKO>=(;hl+0XPf?aSSe>cdvL$iD>MaNR?LSVG4zn=ZxrY0iGSFJp
z64!{5l*E!$tK_0oAjM#0U}&jpV61Cs7-DE)Wng4wXsK;rW@TXTP|NZ#iiX_$l+3hB
W+!`j7H`W6+FnGH9xvX<aXaWF~4TbLj

diff --git a/examples/quickwings/quickwings.cpp b/examples/quickwings/quickwings.cpp
deleted file mode 100644
index dd51112..0000000
--- a/examples/quickwings/quickwings.cpp
+++ /dev/null
@@ -1,546 +0,0 @@
-/**
- * paradiso - Paradigmen der Softwareentwicklung
- *
- * (c) Copyright 2023-2025 Hartmut Seichter and Contributors
- *
- */
-
-#include <paradiso/bitmap.hpp>
-#include <paradiso/bitmap_io.hpp>
-#include <paradiso/context.hpp>
-#include <paradiso/geometry.hpp>
-#include <paradiso/renderer.hpp>
-#include <paradiso/shader.hpp>
-#include <paradiso/sprite.hpp>
-#include <paradiso/utils.hpp>
-#include <paradiso/vector.hpp>
-#include <paradiso/window.hpp>
-
-#include <chrono>
-#include <thread>
-
-// TODO remove all hard coded 'magic' values!
-
-// TODO - remove global variables
-const int frame_rate = 60;
-bool game_over = false;
-float risky_pos_x;
-float risky_pos_max_x;
-float risky_pos_bottom_y;
-float risky_pos_top_y;
-float risky_pos_bottom_max_y;
-float risky_pos_top_max_y;
-
-struct Background {
-    paradiso::Sprite backgroundLeft;
-    paradiso::Sprite backgroundRight;
-    paradiso::Sprite grassLeft;
-    paradiso::Sprite grassRight;
-
-    paradiso::Sprite* scrolling[2] = {&backgroundLeft, &backgroundRight};
-
-    paradiso::Renderer renderer{};
-
-    // TODO no constructors in rule of zero
-    Background() {
-        auto backgroundImage =
-            paradiso::BitmapIO::get().load("background-day.png");
-        backgroundLeft = paradiso::Sprite{
-            .bitmap = backgroundImage,
-            .pivot = {paradiso::Vector2<float>::make(0.0f, 0.16f)},
-            .scale = {paradiso::Vector2<float>::make(1.01f, 1.3f)}};
-        backgroundRight = paradiso::Sprite{
-            .bitmap = backgroundImage,
-            .pivot = {paradiso::Vector2<float>::make(2.018f, 0.16f)},
-            .scale = {paradiso::Vector2<float>::make(1.01f, 1.3f)}};
-
-        auto grassImage = paradiso::BitmapIO::get().load("base.png");
-        grassLeft = paradiso::Sprite{
-            .bitmap = grassImage,
-            .pivot = {paradiso::Vector2<float>::make(0.0f, -1.0f)},
-            .scale = {paradiso::Vector2<float>::make(1.0f, 0.33333f)}};
-        grassRight = paradiso::Sprite{
-            .bitmap = grassImage,
-            .pivot = {paradiso::Vector2<float>::make(2.0f, -1.0f)},
-            .scale = {paradiso::Vector2<float>::make(1.0f, 0.33333f)}};
-    }
-
-    void draw(const paradiso::Shader& shader) {
-        for (auto sprite : scrolling) {
-            if (game_over == false) {
-                if (sprite->pivot.x() <= -2.0f) {
-                    sprite->pivot.x() += 4.0f;
-                }
-                sprite->pivot.x() -= 0.002f;
-            }
-            shader.set_uniform("pivot", sprite->pivot);
-            shader.set_uniform("scale", sprite->scale);
-            shader.set_uniform("rotation", sprite->rotation);
-            renderer.draw(*sprite, shader);
-        }
-    }
-};
-
-struct Pipe {
-    paradiso::Sprite pipe_top{};
-    paradiso::Sprite pipe_bottom{};
-
-    paradiso::Renderer renderer1{};
-    paradiso::Renderer renderer2{};
-
-    bool paused = false;
-
-    int pipe_spawn_rand_int = rand() % 80 + 15;
-    float pipe_spawn_rand = float(pipe_spawn_rand_int) / 100;
-
-    bool pos_reset = false;
-
-    // TODO no constructors in rule of zero
-
-    Pipe() {
-        auto pipe_image = paradiso::BitmapIO::get().load("pipe-green.png");
-
-        pipe_top = paradiso::Sprite{
-            .bitmap = pipe_image,
-            .pivot = {paradiso::Vector2<float>::make(1.4f,
-                                                     pipe_spawn_rand + 1.0f)},
-            .scale = {paradiso::Vector2<float>::make(
-                ((500.0f - (500.0f - 52.0f)) / 500.0f) * 2.25f,
-                ((700.0f - (700.0f - 320.0f)) / 700.0f) * 2.25f)},
-            .rotation = 3.1415926f};
-        pipe_bottom = paradiso::Sprite{
-            .bitmap = pipe_image,
-            .pivot = {paradiso::Vector2<float>::make(1.4f,
-                                                     pipe_spawn_rand - 1.5f)},
-            .scale = {paradiso::Vector2<float>::make(
-                ((500.0f - (500.0f - 52.0f)) / 500.0f) * 2.25f,
-                ((700.0f - (700.0f - 320.0f)) / 700.0f) * 2.25f)}};
-
-        paused = true;
-    }
-
-    void update() {
-
-        // TODO improve state handling
-
-        if (game_over == true) {
-            paused = true;
-        }
-
-        if (paused == true) {
-            return;
-        } else {
-            pipe_spawn_rand_int = rand() % 80 + 15;
-            pipe_spawn_rand = float(pipe_spawn_rand_int) / 100;
-
-            pipe_top.pivot.x() -= 0.02f;
-            pipe_bottom.pivot.x() -= 0.02f;
-
-            risky_pos_x = pipe_top.pivot.x();
-            risky_pos_max_x = pipe_top.pivot.x() +
-                              ((500.0f - (500.0f - 52.0f)) / 500.0f) * 2.25f;
-
-            risky_pos_top_y = pipe_top.pivot.y();
-            risky_pos_top_max_y = pipe_top.pivot.y() + 10.0f;
-
-            risky_pos_bottom_y = pipe_bottom.pivot.y();
-            risky_pos_bottom_max_y = pipe_bottom.pivot.y() - 10.0f;
-
-            if (pipe_top.pivot.x() <= -1.4f || pipe_bottom.pivot.x() <= -1.4f) {
-                pos_reset = true;
-
-                if (pos_reset == true) {
-                    pipe_top.pivot.y() = pipe_spawn_rand + 1.0f;
-                    pipe_bottom.pivot.y() = pipe_spawn_rand - 1.5;
-
-                    pos_reset = false;
-                }
-
-                pipe_top.pivot.x() = 1.4f;
-                pipe_bottom.pivot.x() = 1.4f;
-            }
-        }
-    }
-
-    void draw(const paradiso::Shader& shader) {
-        shader.set_uniform("pivot", pipe_bottom.pivot);
-        shader.set_uniform("scale", pipe_bottom.scale);
-        renderer1.draw(pipe_bottom, shader);
-
-        shader.set_uniform("pivot", pipe_top.pivot);
-        shader.set_uniform("scale", pipe_top.scale);
-        shader.set_uniform("rotation", pipe_top.rotation);
-        renderer1.draw(pipe_top, shader);
-    }
-};
-
-struct Grass {
-    paradiso::Sprite grassLeft;
-    paradiso::Sprite grassRight;
-    paradiso::Sprite* scrolling[2] = {&grassLeft, &grassRight};
-
-    paradiso::Renderer renderer1{};
-    paradiso::Renderer renderer2{};
-
-    // TODO no constructors in rule of zero
-    Grass() {
-        auto grassImage = paradiso::BitmapIO::get().load("base.png");
-        grassLeft = paradiso::Sprite{
-            .bitmap = grassImage,
-            .pivot = {paradiso::Vector2<float>::make(0.0f, -0.9f)},
-            .scale = {paradiso::Vector2<float>::make(
-                ((500.0f - (500.0f - 504.0f)) / 500.0f) * 2.25f,
-                ((700.0f - (700.0f - 112.0f)) / 700.0f) * 2.25f)}};
-        grassRight = paradiso::Sprite{
-            .bitmap = grassImage,
-            .pivot = {paradiso::Vector2<float>::make(1.002f, -0.9f)},
-            .scale = {paradiso::Vector2<float>::make(
-                ((500.0f - (500.0f - 504.0f)) / 500.0f) * 2.25f,
-                ((700.0f - (700.0f - 112.0f)) / 700.0f) * 2.25f)}};
-    }
-
-    void draw(const paradiso::Shader& shader) {
-        if (game_over == false) {
-            grassLeft.pivot.x() -= 0.02f;
-            grassRight.pivot.x() -= 0.02f;
-
-            if (grassRight.pivot.x() <= 0.0f) {
-                grassLeft.pivot.x() = 1.002f;
-            }
-            if (grassRight.pivot.x() <= -1.002f) {
-                grassRight.pivot.x() = 1.002f;
-            }
-        }
-
-        shader.set_uniform("pivot", grassLeft.pivot);
-        shader.set_uniform("scale", grassLeft.scale);
-        shader.set_uniform("rotation", grassLeft.rotation);
-
-        shader.set_uniform("pivot", grassRight.pivot);
-        shader.set_uniform("scale", grassRight.scale);
-        shader.set_uniform("rotation", grassRight.rotation);
-
-        renderer1.draw(grassLeft, shader);
-        renderer2.draw(grassRight, shader);
-    }
-};
-
-struct QuickWings {
-    paradiso::Renderer renderer1{};
-    paradiso::Renderer renderer2{};
-    paradiso::Renderer renderer3{};
-
-    std::array<paradiso::Sprite, 3> birds;
-    unsigned int flap = 0;
-    unsigned int flapSpeed = 15;  // How many ticks per flap
-    unsigned int flapCounter = 0; // How many ticks since last flap
-
-    float velocity = 0.0f;
-    const float max_velocity = 0.02f;
-
-    const float gravity = -0.002f;
-    const float move_up_velocity = 0.02f;
-
-    bool move_up = false;
-    bool paused = true;
-
-    const float max_pos = 0.95f;
-    const float min_pos = -0.5f;
-
-    float pos = 0.34f;
-
-    float rotation = 0.0f;
-
-    int collision_counter = 0;
-
-    // TODO no constructors in rule of zero
-    QuickWings() {
-        float scaleh = 0.08f;
-        float scalew = 0.158f;
-
-        birds = {
-            paradiso::Sprite{
-                .bitmap =
-                    paradiso::BitmapIO::get().load("yellowbird-downflap.png"),
-                .pivot = {paradiso::Vector2<float>::make(0.0f, 0.0f)},
-                .scale = {paradiso::Vector2<float>::make(scalew, scaleh)}},
-            paradiso::Sprite{
-                .bitmap =
-                    paradiso::BitmapIO::get().load("yellowbird-midflap.png"),
-                .pivot = {paradiso::Vector2<float>::make(0.0f, 0.0f)},
-                .scale = {paradiso::Vector2<float>::make(scalew, scaleh)}},
-            paradiso::Sprite{
-                .bitmap =
-                    paradiso::BitmapIO::get().load("yellowbird-upflap.png"),
-                .pivot = {paradiso::Vector2<float>::make(0.0f, 0.0f)},
-                .scale = {paradiso::Vector2<float>::make(scalew, scaleh)}}};
-    }
-
-    void draw(const paradiso::Shader& shader) {
-        // Update flap state
-        if (flapCounter < flapSpeed) {
-            flapCounter++;
-        } else {
-            flapCounter = 0;
-            flap = (flap + 1) % birds.size();
-        }
-
-        auto bird = birds[flap];
-        bird.pivot.y() = pos;
-        bird.rotation = rotation;
-        shader.set_uniform("pivot", bird.pivot);
-        shader.set_uniform("scale", bird.scale);
-        shader.set_uniform("rotation", bird.rotation);
-
-        switch (flap) {
-        case 0:
-            renderer1.draw(bird, shader);
-            break;
-        case 1:
-            renderer2.draw(bird, shader);
-            break;
-        case 2:
-            renderer3.draw(bird, shader);
-            break;
-        }
-    }
-
-    void update() {
-
-        if (game_over == true) {
-            paused = true;
-        }
-
-        // Stop game
-        if (paused) {
-            return;
-        } else {
-            // Apply gravity
-            velocity += gravity;
-
-            if (move_up)
-                velocity += move_up_velocity - gravity;
-
-            // Cap velocity
-            if (velocity > max_velocity)
-                velocity = max_velocity;
-            if (velocity < -max_velocity)
-                velocity = -max_velocity;
-
-            // Cap position
-            pos += velocity;
-            if (pos < min_pos) {
-                pos = min_pos;
-                velocity = 0.0f;
-                game_over = true;
-            }
-            if (pos > max_pos) {
-                pos = max_pos;
-                velocity = 0.0f;
-                game_over = true;
-            }
-
-            // Update rotation
-            rotation = velocity * 10.0f;
-        }
-
-        float final_risky_pos_top_y = risky_pos_top_y - 1.06f;
-        float final_risky_pos_bottom_y = risky_pos_bottom_y + 1.06f;
-
-        if (risky_pos_x - 0.3f <= 0.0f && risky_pos_max_x >= 0.0f) {
-            if (pos >= final_risky_pos_top_y && pos <= risky_pos_top_max_y) {
-                game_over = true;
-            }
-            if (pos <= final_risky_pos_bottom_y &&
-                pos >= risky_pos_bottom_max_y) {
-                if (collision_counter == 0) {
-                    collision_counter++;
-                } else {
-                    collision_counter = 2;
-                }
-
-                if (collision_counter == 2) {
-                    game_over = true;
-                }
-            }
-        }
-    }
-
-    // keyboard handler
-    void on_keyboard(const paradiso::Window::KeyboardInputStack& input) {
-        if (input.size()) {
-            paused = false;
-
-            if (paused == false) {
-                bool pressed_up =
-                    input.top().key == ' ' || input.top().key == 'W';
-
-                if (input.top().action == 1 && pressed_up) {
-                    move_up = true;
-                } else if (input.top().action == 0 && pressed_up) {
-                    move_up = false;
-                }
-            } else {
-                return;
-            }
-        }
-    }
-};
-
-struct Message {
-    paradiso::Sprite messageSprite;
-    paradiso::Renderer renderer{};
-    bool start = false;
-    float pos = 100.0f;
-
-    Message() {
-        auto messageImage = paradiso::BitmapIO::get().load("message.png");
-        messageSprite = paradiso::Sprite{
-            .bitmap = messageImage,
-            .pivot = {paradiso::Vector2<float>::make(0.0f, 0.0f)},
-            .scale = {paradiso::Vector2<float>::make(0.8f, 0.8f)}};
-    };
-
-    void draw(const paradiso::Shader& shader) {
-        shader.set_uniform("pivot", messageSprite.pivot);
-        shader.set_uniform("scale", messageSprite.scale);
-        renderer.draw(messageSprite, shader);
-    }
-
-    void update() {
-        if (start == true) {
-            messageSprite.pivot.y() = pos;
-        }
-    }
-
-    void on_keyboard(const paradiso::Window::KeyboardInputStack& input) {
-        if (input.size()) {
-            start = true;
-        }
-    }
-};
-
-struct GameOverMessage {
-    paradiso::Sprite messageSprite;
-    paradiso::Renderer renderer{};
-
-    GameOverMessage() {
-        auto messageImage = paradiso::BitmapIO::get().load("gameover.png");
-        messageSprite = paradiso::Sprite{
-            .bitmap = messageImage,
-            .pivot = {paradiso::Vector2<float>::make(0.0f, 0.4f)},
-            .scale = {paradiso::Vector2<float>::make(
-                ((500.0f - (500.0f - 192.0f)) / 500.0f) * 2.25f,
-                ((700.0f - (700.0f - 42.0f)) / 700.0f) * 2.25f)}};
-    };
-
-    void draw(const paradiso::Shader& shader) {
-        shader.set_uniform("pivot", messageSprite.pivot);
-        shader.set_uniform("scale", messageSprite.scale);
-        renderer.draw(messageSprite, shader);
-    }
-};
-
-auto main() -> int {
-    std::srand(std::time(nullptr));
-
-    // Ausgabefenster ... sieht aus als wäre es auf dem Stack
-    auto window = paradiso::Window();
-
-    auto size = paradiso::Size{.width = 500, .height = 700};
-
-    /*
-    window.set_resizecallback([](auto& w) -> void {
-        w.set_size(paradiso::Size{.width = 405, .height = 720});
-    });
-
-*/
-    window
-        .set_size(size) // ... Grösse
-        .set_position(paradiso::Point{.x = 1920 / 2 - 500 / 2,
-                                      .y = 1080 / 2 - 700 / 2}) // ... Position
-        .set_title("PardiSO.FlappyBird")                        // ... Titel
-        .set_visible(true); // ... und jetzt anzeigen!
-
-    // der Fenster Kontext
-    auto ctx = paradiso::Context{};
-
-    // ein Shader (Schattierungsprogramm)
-    auto shader = paradiso::Shader{};
-
-    // wir nutzen einen vorgefertigten shader
-    shader.load_preset(paradiso::Shader::Preset::Sprite);
-
-    // ein viewport stellt die Sicht der Kamera dar, d.h. bei quadratischen
-    // Pixeln sollte hier auch eine dementsprechende Grösse eingestellt
-    // werden
-    ctx.set_viewport(paradiso::Rectangle{
-        .position = paradiso::Point{.x = 0, .y = 0}, .size = size});
-
-    // nothing beats a classic look
-    ctx.set_clearcolor(paradiso::RGBA::from_rgb(0x00, 0x00, 0x00));
-
-    // Asset loader bekommt den Pfad
-
-    paradiso::BitmapIO::get().set_path("assets");
-
-    // Load
-    auto background = Background{};
-    auto grass = Grass{};
-    auto quickwingsapp = QuickWings{};
-    auto pipe = Pipe{};
-    auto message = Message{};
-    auto gameover = GameOverMessage{};
-
-    // timer
-
-    // das update führt den hier mitgegebnen Ausdruck innerhalb der internen
-    // Updates des Fensters auf. Es wird hier auch explizit ein bool gefordert
-    // damit das update auch zu jederzeit unterbrochen werden kann
-    while (window.update([&](paradiso::Window& w) -> bool {
-        ctx.set_viewport(paradiso::Rectangle{
-            .position = paradiso::Point{.x = 0, .y = 0}, .size = size});
-
-        ctx.clear();
-        auto t1 = std::chrono::high_resolution_clock::now();
-
-        // Keyboard and state change + update
-        if (quickwingsapp.paused == false) {
-            pipe.paused = false;
-        }
-
-        pipe.update();
-
-        quickwingsapp.on_keyboard(w.keyboard_input());
-        quickwingsapp.update();
-
-        message.on_keyboard(w.keyboard_input());
-        message.update();
-
-        // Draw
-        background.draw(shader);
-        pipe.draw(shader);
-        grass.draw(shader);
-        message.draw(shader);
-
-        if (game_over == true) {
-            gameover.draw(shader);
-        }
-
-        quickwingsapp.draw(shader);
-
-        // wait for frame rate
-        auto t2 = std::chrono::high_resolution_clock::now();
-        auto duration =
-            std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1);
-        auto wait = std::chrono::microseconds(1000000 / frame_rate) - duration;
-        std::this_thread::sleep_for(wait);
-
-        // Quit
-        return !(w.keyboard_input().size() &&
-                 w.keyboard_input().top().key == 'Q');
-    })) {
-    };
-
-    return 0;
-}
diff --git a/examples/tappyplane/CMakeLists.txt b/examples/tappyplane/CMakeLists.txt
new file mode 100644
index 0000000..7d4f40a
--- /dev/null
+++ b/examples/tappyplane/CMakeLists.txt
@@ -0,0 +1,18 @@
+set(tappyplane_srcs tappyplane.cpp)
+set(tappyplane_assets
+    assets/PNG/background.png
+    )
+
+set_source_files_properties(${tappyplane_assets} PROPERTIES HEADER_FILE_ONLY TRUE)
+
+add_executable(tappyplane ${tappyplane_srcs} ${tappyplane_assets})
+
+target_link_libraries(tappyplane paradiso_core)
+
+#
+# copy files to bin/../assets folder
+#
+add_custom_command(TARGET tappyplane POST_BUILD
+                   COMMAND ${CMAKE_COMMAND} -E copy_directory
+                   ${CMAKE_CURRENT_SOURCE_DIR}/assets/
+                   $<TARGET_FILE_DIR:tappyplane>/assets)
diff --git a/examples/quickwings/assets/tappybird/Font/kenvector_future.ttf b/examples/tappyplane/assets/Font/kenvector_future.ttf
similarity index 100%
rename from examples/quickwings/assets/tappybird/Font/kenvector_future.ttf
rename to examples/tappyplane/assets/Font/kenvector_future.ttf
diff --git a/examples/quickwings/assets/tappybird/Font/kenvector_future_thin.ttf b/examples/tappyplane/assets/Font/kenvector_future_thin.ttf
similarity index 100%
rename from examples/quickwings/assets/tappybird/Font/kenvector_future_thin.ttf
rename to examples/tappyplane/assets/Font/kenvector_future_thin.ttf
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterA.png b/examples/tappyplane/assets/PNG/Letters/letterA.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterA.png
rename to examples/tappyplane/assets/PNG/Letters/letterA.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterB.png b/examples/tappyplane/assets/PNG/Letters/letterB.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterB.png
rename to examples/tappyplane/assets/PNG/Letters/letterB.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterC.png b/examples/tappyplane/assets/PNG/Letters/letterC.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterC.png
rename to examples/tappyplane/assets/PNG/Letters/letterC.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterD.png b/examples/tappyplane/assets/PNG/Letters/letterD.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterD.png
rename to examples/tappyplane/assets/PNG/Letters/letterD.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterE.png b/examples/tappyplane/assets/PNG/Letters/letterE.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterE.png
rename to examples/tappyplane/assets/PNG/Letters/letterE.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterF.png b/examples/tappyplane/assets/PNG/Letters/letterF.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterF.png
rename to examples/tappyplane/assets/PNG/Letters/letterF.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterG.png b/examples/tappyplane/assets/PNG/Letters/letterG.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterG.png
rename to examples/tappyplane/assets/PNG/Letters/letterG.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterH.png b/examples/tappyplane/assets/PNG/Letters/letterH.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterH.png
rename to examples/tappyplane/assets/PNG/Letters/letterH.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterI.png b/examples/tappyplane/assets/PNG/Letters/letterI.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterI.png
rename to examples/tappyplane/assets/PNG/Letters/letterI.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterJ.png b/examples/tappyplane/assets/PNG/Letters/letterJ.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterJ.png
rename to examples/tappyplane/assets/PNG/Letters/letterJ.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterK.png b/examples/tappyplane/assets/PNG/Letters/letterK.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterK.png
rename to examples/tappyplane/assets/PNG/Letters/letterK.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterL.png b/examples/tappyplane/assets/PNG/Letters/letterL.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterL.png
rename to examples/tappyplane/assets/PNG/Letters/letterL.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterM.png b/examples/tappyplane/assets/PNG/Letters/letterM.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterM.png
rename to examples/tappyplane/assets/PNG/Letters/letterM.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterN.png b/examples/tappyplane/assets/PNG/Letters/letterN.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterN.png
rename to examples/tappyplane/assets/PNG/Letters/letterN.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterO.png b/examples/tappyplane/assets/PNG/Letters/letterO.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterO.png
rename to examples/tappyplane/assets/PNG/Letters/letterO.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterP.png b/examples/tappyplane/assets/PNG/Letters/letterP.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterP.png
rename to examples/tappyplane/assets/PNG/Letters/letterP.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterQ.png b/examples/tappyplane/assets/PNG/Letters/letterQ.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterQ.png
rename to examples/tappyplane/assets/PNG/Letters/letterQ.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterR.png b/examples/tappyplane/assets/PNG/Letters/letterR.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterR.png
rename to examples/tappyplane/assets/PNG/Letters/letterR.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterS.png b/examples/tappyplane/assets/PNG/Letters/letterS.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterS.png
rename to examples/tappyplane/assets/PNG/Letters/letterS.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterT.png b/examples/tappyplane/assets/PNG/Letters/letterT.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterT.png
rename to examples/tappyplane/assets/PNG/Letters/letterT.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterU.png b/examples/tappyplane/assets/PNG/Letters/letterU.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterU.png
rename to examples/tappyplane/assets/PNG/Letters/letterU.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterV.png b/examples/tappyplane/assets/PNG/Letters/letterV.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterV.png
rename to examples/tappyplane/assets/PNG/Letters/letterV.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterW.png b/examples/tappyplane/assets/PNG/Letters/letterW.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterW.png
rename to examples/tappyplane/assets/PNG/Letters/letterW.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterX.png b/examples/tappyplane/assets/PNG/Letters/letterX.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterX.png
rename to examples/tappyplane/assets/PNG/Letters/letterX.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterY.png b/examples/tappyplane/assets/PNG/Letters/letterY.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterY.png
rename to examples/tappyplane/assets/PNG/Letters/letterY.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Letters/letterZ.png b/examples/tappyplane/assets/PNG/Letters/letterZ.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Letters/letterZ.png
rename to examples/tappyplane/assets/PNG/Letters/letterZ.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Numbers/number0.png b/examples/tappyplane/assets/PNG/Numbers/number0.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Numbers/number0.png
rename to examples/tappyplane/assets/PNG/Numbers/number0.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Numbers/number1.png b/examples/tappyplane/assets/PNG/Numbers/number1.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Numbers/number1.png
rename to examples/tappyplane/assets/PNG/Numbers/number1.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Numbers/number2.png b/examples/tappyplane/assets/PNG/Numbers/number2.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Numbers/number2.png
rename to examples/tappyplane/assets/PNG/Numbers/number2.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Numbers/number3.png b/examples/tappyplane/assets/PNG/Numbers/number3.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Numbers/number3.png
rename to examples/tappyplane/assets/PNG/Numbers/number3.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Numbers/number4.png b/examples/tappyplane/assets/PNG/Numbers/number4.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Numbers/number4.png
rename to examples/tappyplane/assets/PNG/Numbers/number4.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Numbers/number5.png b/examples/tappyplane/assets/PNG/Numbers/number5.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Numbers/number5.png
rename to examples/tappyplane/assets/PNG/Numbers/number5.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Numbers/number6.png b/examples/tappyplane/assets/PNG/Numbers/number6.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Numbers/number6.png
rename to examples/tappyplane/assets/PNG/Numbers/number6.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Numbers/number7.png b/examples/tappyplane/assets/PNG/Numbers/number7.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Numbers/number7.png
rename to examples/tappyplane/assets/PNG/Numbers/number7.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Numbers/number8.png b/examples/tappyplane/assets/PNG/Numbers/number8.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Numbers/number8.png
rename to examples/tappyplane/assets/PNG/Numbers/number8.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Numbers/number9.png b/examples/tappyplane/assets/PNG/Numbers/number9.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Numbers/number9.png
rename to examples/tappyplane/assets/PNG/Numbers/number9.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Planes/planeBlue1.png b/examples/tappyplane/assets/PNG/Planes/planeBlue1.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Planes/planeBlue1.png
rename to examples/tappyplane/assets/PNG/Planes/planeBlue1.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Planes/planeBlue2.png b/examples/tappyplane/assets/PNG/Planes/planeBlue2.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Planes/planeBlue2.png
rename to examples/tappyplane/assets/PNG/Planes/planeBlue2.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Planes/planeBlue3.png b/examples/tappyplane/assets/PNG/Planes/planeBlue3.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Planes/planeBlue3.png
rename to examples/tappyplane/assets/PNG/Planes/planeBlue3.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Planes/planeGreen1.png b/examples/tappyplane/assets/PNG/Planes/planeGreen1.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Planes/planeGreen1.png
rename to examples/tappyplane/assets/PNG/Planes/planeGreen1.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Planes/planeGreen2.png b/examples/tappyplane/assets/PNG/Planes/planeGreen2.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Planes/planeGreen2.png
rename to examples/tappyplane/assets/PNG/Planes/planeGreen2.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Planes/planeGreen3.png b/examples/tappyplane/assets/PNG/Planes/planeGreen3.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Planes/planeGreen3.png
rename to examples/tappyplane/assets/PNG/Planes/planeGreen3.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Planes/planeRed1.png b/examples/tappyplane/assets/PNG/Planes/planeRed1.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Planes/planeRed1.png
rename to examples/tappyplane/assets/PNG/Planes/planeRed1.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Planes/planeRed2.png b/examples/tappyplane/assets/PNG/Planes/planeRed2.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Planes/planeRed2.png
rename to examples/tappyplane/assets/PNG/Planes/planeRed2.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Planes/planeRed3.png b/examples/tappyplane/assets/PNG/Planes/planeRed3.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Planes/planeRed3.png
rename to examples/tappyplane/assets/PNG/Planes/planeRed3.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Planes/planeYellow1.png b/examples/tappyplane/assets/PNG/Planes/planeYellow1.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Planes/planeYellow1.png
rename to examples/tappyplane/assets/PNG/Planes/planeYellow1.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Planes/planeYellow2.png b/examples/tappyplane/assets/PNG/Planes/planeYellow2.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Planes/planeYellow2.png
rename to examples/tappyplane/assets/PNG/Planes/planeYellow2.png
diff --git a/examples/quickwings/assets/tappybird/PNG/Planes/planeYellow3.png b/examples/tappyplane/assets/PNG/Planes/planeYellow3.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/Planes/planeYellow3.png
rename to examples/tappyplane/assets/PNG/Planes/planeYellow3.png
diff --git a/examples/quickwings/assets/tappybird/PNG/UI/UIbg.png b/examples/tappyplane/assets/PNG/UI/UIbg.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/UI/UIbg.png
rename to examples/tappyplane/assets/PNG/UI/UIbg.png
diff --git a/examples/quickwings/assets/tappybird/PNG/UI/buttonLarge.png b/examples/tappyplane/assets/PNG/UI/buttonLarge.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/UI/buttonLarge.png
rename to examples/tappyplane/assets/PNG/UI/buttonLarge.png
diff --git a/examples/quickwings/assets/tappybird/PNG/UI/buttonSmall.png b/examples/tappyplane/assets/PNG/UI/buttonSmall.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/UI/buttonSmall.png
rename to examples/tappyplane/assets/PNG/UI/buttonSmall.png
diff --git a/examples/quickwings/assets/tappybird/PNG/UI/medalBronze.png b/examples/tappyplane/assets/PNG/UI/medalBronze.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/UI/medalBronze.png
rename to examples/tappyplane/assets/PNG/UI/medalBronze.png
diff --git a/examples/quickwings/assets/tappybird/PNG/UI/medalGold.png b/examples/tappyplane/assets/PNG/UI/medalGold.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/UI/medalGold.png
rename to examples/tappyplane/assets/PNG/UI/medalGold.png
diff --git a/examples/quickwings/assets/tappybird/PNG/UI/medalSilver.png b/examples/tappyplane/assets/PNG/UI/medalSilver.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/UI/medalSilver.png
rename to examples/tappyplane/assets/PNG/UI/medalSilver.png
diff --git a/examples/quickwings/assets/tappybird/PNG/UI/tap.png b/examples/tappyplane/assets/PNG/UI/tap.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/UI/tap.png
rename to examples/tappyplane/assets/PNG/UI/tap.png
diff --git a/examples/quickwings/assets/tappybird/PNG/UI/tapLeft.png b/examples/tappyplane/assets/PNG/UI/tapLeft.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/UI/tapLeft.png
rename to examples/tappyplane/assets/PNG/UI/tapLeft.png
diff --git a/examples/quickwings/assets/tappybird/PNG/UI/tapRight.png b/examples/tappyplane/assets/PNG/UI/tapRight.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/UI/tapRight.png
rename to examples/tappyplane/assets/PNG/UI/tapRight.png
diff --git a/examples/quickwings/assets/tappybird/PNG/UI/tapTick.png b/examples/tappyplane/assets/PNG/UI/tapTick.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/UI/tapTick.png
rename to examples/tappyplane/assets/PNG/UI/tapTick.png
diff --git a/examples/quickwings/assets/tappybird/PNG/UI/textGameOver.png b/examples/tappyplane/assets/PNG/UI/textGameOver.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/UI/textGameOver.png
rename to examples/tappyplane/assets/PNG/UI/textGameOver.png
diff --git a/examples/quickwings/assets/tappybird/PNG/UI/textGetReady.png b/examples/tappyplane/assets/PNG/UI/textGetReady.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/UI/textGetReady.png
rename to examples/tappyplane/assets/PNG/UI/textGetReady.png
diff --git a/examples/quickwings/assets/tappybird/PNG/background.png b/examples/tappyplane/assets/PNG/background.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/background.png
rename to examples/tappyplane/assets/PNG/background.png
diff --git a/examples/quickwings/assets/tappybird/PNG/groundDirt.png b/examples/tappyplane/assets/PNG/groundDirt.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/groundDirt.png
rename to examples/tappyplane/assets/PNG/groundDirt.png
diff --git a/examples/quickwings/assets/tappybird/PNG/groundGrass.png b/examples/tappyplane/assets/PNG/groundGrass.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/groundGrass.png
rename to examples/tappyplane/assets/PNG/groundGrass.png
diff --git a/examples/quickwings/assets/tappybird/PNG/groundIce.png b/examples/tappyplane/assets/PNG/groundIce.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/groundIce.png
rename to examples/tappyplane/assets/PNG/groundIce.png
diff --git a/examples/quickwings/assets/tappybird/PNG/groundRock.png b/examples/tappyplane/assets/PNG/groundRock.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/groundRock.png
rename to examples/tappyplane/assets/PNG/groundRock.png
diff --git a/examples/quickwings/assets/tappybird/PNG/groundSnow.png b/examples/tappyplane/assets/PNG/groundSnow.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/groundSnow.png
rename to examples/tappyplane/assets/PNG/groundSnow.png
diff --git a/examples/quickwings/assets/tappybird/PNG/puffLarge.png b/examples/tappyplane/assets/PNG/puffLarge.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/puffLarge.png
rename to examples/tappyplane/assets/PNG/puffLarge.png
diff --git a/examples/quickwings/assets/tappybird/PNG/puffSmall.png b/examples/tappyplane/assets/PNG/puffSmall.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/puffSmall.png
rename to examples/tappyplane/assets/PNG/puffSmall.png
diff --git a/examples/quickwings/assets/tappybird/PNG/rock.png b/examples/tappyplane/assets/PNG/rock.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/rock.png
rename to examples/tappyplane/assets/PNG/rock.png
diff --git a/examples/quickwings/assets/tappybird/PNG/rockDown.png b/examples/tappyplane/assets/PNG/rockDown.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/rockDown.png
rename to examples/tappyplane/assets/PNG/rockDown.png
diff --git a/examples/quickwings/assets/tappybird/PNG/rockGrass.png b/examples/tappyplane/assets/PNG/rockGrass.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/rockGrass.png
rename to examples/tappyplane/assets/PNG/rockGrass.png
diff --git a/examples/quickwings/assets/tappybird/PNG/rockGrassDown.png b/examples/tappyplane/assets/PNG/rockGrassDown.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/rockGrassDown.png
rename to examples/tappyplane/assets/PNG/rockGrassDown.png
diff --git a/examples/quickwings/assets/tappybird/PNG/rockIce.png b/examples/tappyplane/assets/PNG/rockIce.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/rockIce.png
rename to examples/tappyplane/assets/PNG/rockIce.png
diff --git a/examples/quickwings/assets/tappybird/PNG/rockIceDown.png b/examples/tappyplane/assets/PNG/rockIceDown.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/rockIceDown.png
rename to examples/tappyplane/assets/PNG/rockIceDown.png
diff --git a/examples/quickwings/assets/tappybird/PNG/rockSnow.png b/examples/tappyplane/assets/PNG/rockSnow.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/rockSnow.png
rename to examples/tappyplane/assets/PNG/rockSnow.png
diff --git a/examples/quickwings/assets/tappybird/PNG/rockSnowDown.png b/examples/tappyplane/assets/PNG/rockSnowDown.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/rockSnowDown.png
rename to examples/tappyplane/assets/PNG/rockSnowDown.png
diff --git a/examples/quickwings/assets/tappybird/PNG/starBronze.png b/examples/tappyplane/assets/PNG/starBronze.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/starBronze.png
rename to examples/tappyplane/assets/PNG/starBronze.png
diff --git a/examples/quickwings/assets/tappybird/PNG/starGold.png b/examples/tappyplane/assets/PNG/starGold.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/starGold.png
rename to examples/tappyplane/assets/PNG/starGold.png
diff --git a/examples/quickwings/assets/tappybird/PNG/starSilver.png b/examples/tappyplane/assets/PNG/starSilver.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/PNG/starSilver.png
rename to examples/tappyplane/assets/PNG/starSilver.png
diff --git a/examples/quickwings/assets/tappybird/Spritesheet/planes.png b/examples/tappyplane/assets/Spritesheet/planes.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/Spritesheet/planes.png
rename to examples/tappyplane/assets/Spritesheet/planes.png
diff --git a/examples/quickwings/assets/tappybird/Spritesheet/planes.xml b/examples/tappyplane/assets/Spritesheet/planes.xml
similarity index 100%
rename from examples/quickwings/assets/tappybird/Spritesheet/planes.xml
rename to examples/tappyplane/assets/Spritesheet/planes.xml
diff --git a/examples/quickwings/assets/tappybird/Spritesheet/sheet.png b/examples/tappyplane/assets/Spritesheet/sheet.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/Spritesheet/sheet.png
rename to examples/tappyplane/assets/Spritesheet/sheet.png
diff --git a/examples/quickwings/assets/tappybird/Spritesheet/sheet.xml b/examples/tappyplane/assets/Spritesheet/sheet.xml
similarity index 100%
rename from examples/quickwings/assets/tappybird/Spritesheet/sheet.xml
rename to examples/tappyplane/assets/Spritesheet/sheet.xml
diff --git a/examples/quickwings/assets/tappybird/Vector/vector.svg b/examples/tappyplane/assets/Vector/vector.svg
similarity index 100%
rename from examples/quickwings/assets/tappybird/Vector/vector.svg
rename to examples/tappyplane/assets/Vector/vector.svg
diff --git a/examples/quickwings/assets/tappybird/Vector/vector.swf b/examples/tappyplane/assets/Vector/vector.swf
similarity index 100%
rename from examples/quickwings/assets/tappybird/Vector/vector.swf
rename to examples/tappyplane/assets/Vector/vector.swf
diff --git a/examples/quickwings/assets/tappybird/license.txt b/examples/tappyplane/assets/license.txt
similarity index 100%
rename from examples/quickwings/assets/tappybird/license.txt
rename to examples/tappyplane/assets/license.txt
diff --git a/examples/quickwings/assets/tappybird/preview.png b/examples/tappyplane/assets/preview.png
similarity index 100%
rename from examples/quickwings/assets/tappybird/preview.png
rename to examples/tappyplane/assets/preview.png
diff --git a/examples/quickwings/assets/tappybird/sample.png b/examples/tappyplane/assets/sample.png
similarity index 99%
rename from examples/quickwings/assets/tappybird/sample.png
rename to examples/tappyplane/assets/sample.png
index efccaf41be84dda2d60704f099885b4532ec89b6..55328036a4be96591ded081c18b6f214af3869bf 100644
GIT binary patch
delta 13
UcmezWkEP*1OT!k%dV5AL05Povg8%>k

delta 11
ScmZqp&+`8tOT!k%dV2sRHwAbA

diff --git a/examples/tappyplane/tappyplane.cpp b/examples/tappyplane/tappyplane.cpp
new file mode 100644
index 0000000..cda1265
--- /dev/null
+++ b/examples/tappyplane/tappyplane.cpp
@@ -0,0 +1,456 @@
+/**
+ * paradiso - Paradigmen der Softwareentwicklung
+ *
+ * (c) Copyright 2023-2025 Hartmut Seichter and Contributors
+ *
+ */
+
+#include <paradiso/bitmap.hpp>
+#include <paradiso/bitmap_io.hpp>
+#include <paradiso/context.hpp>
+#include <paradiso/geometry.hpp>
+#include <paradiso/renderer.hpp>
+#include <paradiso/shader.hpp>
+#include <paradiso/sprite.hpp>
+#include <paradiso/utils.hpp>
+#include <paradiso/vector.hpp>
+#include <paradiso/window.hpp>
+
+#include <chrono>
+#include <thread>
+
+#include <iostream>
+
+static const unsigned int FRAME_RATE = 60;
+static const unsigned int WINDOW_WIDTH = 800;
+static const unsigned int WINDOW_HEIGHT = 480;
+static const unsigned int WINDOW_SCALE = 2;
+
+// x,y+h --- x+w,y+h
+//   |          |
+//   |          |
+//   |          |
+//  x,y ----- x+w,y
+struct AABB {
+    paradiso::Vector2<float> position{};
+    paradiso::Vector2<float> size{};
+
+    bool is_colliding_with(const AABB& other) {
+        return position.x() < other.position.x() + other.size.x() &&
+               position.x() + size.x() > other.position.x() &&
+               position.y() < other.position.y() + other.size.y() &&
+               position.y() + size.y() > other.position.y();
+    }
+};
+
+struct Background {
+    static constexpr float SCROLLING_SPEED = 0.003f;
+
+    std::array<paradiso::Sprite, 2> sprites;
+    paradiso::Renderer renderer{};
+
+    paradiso::Bitmap image =
+        paradiso::BitmapIO::get().load("PNG/background.png");
+
+    void init() {
+        sprites = {paradiso::Sprite{
+                       .bitmap = image,
+                       .pivot = {paradiso::Vector2<float>::make(0.0f, 0.0f)},
+                       .scale = {paradiso::Vector2<float>::make(1.0f, 1.0f)}},
+                   paradiso::Sprite{
+                       .bitmap = image,
+                       .pivot = {paradiso::Vector2<float>::make(2.0f, 0.0f)},
+                       .scale = {paradiso::Vector2<float>::make(1.0f, 1.0f)}}};
+    }
+
+    void update() {
+        for (auto& sprite : sprites) {
+            sprite.pivot.x() -= SCROLLING_SPEED;
+            if (sprite.pivot.x() <= -2.0f) {
+                sprite.pivot.x() += 4.0f;
+            }
+        }
+    }
+
+    void draw(const paradiso::Shader& shader) {
+        for (const auto& sprite : sprites) {
+            shader.set_uniform("pivot", sprite.pivot);
+            shader.set_uniform("scale", sprite.scale);
+            shader.set_uniform("rotation", sprite.rotation);
+            renderer.draw(sprite, shader);
+        }
+    }
+};
+
+struct Ground {
+    static constexpr float SCROLLING_SPEED = 0.009f;
+
+    std::array<paradiso::Sprite, 2> sprites;
+    paradiso::Renderer renderer{};
+
+    // Maybe put this into 'init()' because we might use the other textures
+    // like snow, ice, ... and then we can parameterize this.
+    paradiso::Bitmap image =
+        paradiso::BitmapIO::get().load("PNG/groundGrass.png");
+
+    AABB aabb{};
+
+    void init() {
+        // The image's height is 71 px.
+        float scale_y = 71.0f / (float)WINDOW_HEIGHT;
+
+        float pivot_y = -1.0f + scale_y;
+
+        sprites = {
+            paradiso::Sprite{
+                .bitmap = image,
+                .pivot = {paradiso::Vector2<float>::make(0.0f, pivot_y)},
+                .scale = {paradiso::Vector2<float>::make(1.0f, scale_y)}},
+            paradiso::Sprite{
+                .bitmap = image,
+                .pivot = {paradiso::Vector2<float>::make(2.0f, pivot_y)},
+                .scale = {paradiso::Vector2<float>::make(1.0f, scale_y)}}};
+
+        // We'll make the height half the height of the texture.
+        // (If you want 1:1 size, you need to double the scale of the sprite.)
+        aabb = AABB{
+            .position = {paradiso::Vector2<float>::make(-1.0f, -1.0f)},
+            .size = {paradiso::Vector2<float>::make(2.0f, scale_y)}
+        };
+    }
+
+    void update() {
+        for (auto& sprite : sprites) {
+            sprite.pivot.x() -= SCROLLING_SPEED;
+            if (sprite.pivot.x() <= -2.0f) {
+                sprite.pivot.x() += 4.0f;
+            }
+        }
+    }
+
+    void draw(const paradiso::Shader& shader) {
+        for (const auto& sprite : sprites) {
+            shader.set_uniform("pivot", sprite.pivot);
+            shader.set_uniform("scale", sprite.scale);
+            shader.set_uniform("rotation", sprite.rotation);
+            renderer.draw(sprite, shader);
+        }
+    }
+};
+
+struct Rocks {
+    static constexpr float SCROLLING_SPEED = 0.006f;
+    static constexpr float GAP_SIZE = 1.6f;
+
+    paradiso::Sprite top_sprite;
+    paradiso::Sprite bottom_sprite;
+
+    paradiso::Renderer top_renderer{};
+    paradiso::Renderer bottom_renderer{};
+
+    // Maybe put this into 'init()' because we might use the other textures
+    // like snow, ice, ... and then we can parameterize this.
+    paradiso::Bitmap top_image =
+        paradiso::BitmapIO::get().load("PNG/rockGrassDown.png");
+    paradiso::Bitmap bottom_image =
+        paradiso::BitmapIO::get().load("PNG/rockGrass.png");
+
+    AABB top_aabb;
+    AABB bottom_aabb;
+
+    void init(float x) {
+        // The image's size is 108x239 px.
+        float scale_x = 108.0f / (float)WINDOW_WIDTH;
+        float scale_y = 239.0f / (float)WINDOW_HEIGHT;
+        auto scale = paradiso::Vector2<float>{
+            paradiso::Vector2<float>::make(scale_x, scale_y)};
+
+        float top_position_y =
+            1.0f - scale_y + ((float)(std::rand() % 60) / 100) + 0.04f;
+        float bottom_position_y = top_position_y - GAP_SIZE;
+
+        top_sprite = paradiso::Sprite{
+            .bitmap = top_image,
+            .pivot = {paradiso::Vector2<float>::make(x, top_position_y)},
+            .scale = scale};
+
+        bottom_sprite = paradiso::Sprite{
+            .bitmap = bottom_image,
+            .pivot = {paradiso::Vector2<float>::make(x, bottom_position_y)},
+            .scale = scale};
+
+        // We'll make the width half the width of the texture.
+        // (If you want 1:1 size, you need to double the scale of the sprite.)
+        auto size = paradiso::Vector2<float>{
+            paradiso::Vector2<float>::make(scale_x, scale_y * 2)};
+
+        auto top_position =
+            paradiso::Vector2<float>{paradiso::Vector2<float>::make(
+                top_sprite.pivot.x() - size.x() / 2,
+                top_sprite.pivot.y() - size.y() / 2)};
+
+        auto bottom_position =
+            paradiso::Vector2<float>{paradiso::Vector2<float>::make(
+                bottom_sprite.pivot.x() - size.x() / 2,
+                bottom_sprite.pivot.y() - size.y() / 2)};
+
+        top_aabb = AABB{top_position, size};
+        bottom_aabb = AABB{bottom_position, size};
+    }
+
+    void update() {
+        top_sprite.pivot.x() -= SCROLLING_SPEED;
+        bottom_sprite.pivot.x() -= SCROLLING_SPEED;
+
+        // +----------+
+        // |          |
+        // |  #  #-------- the x it is.
+        // |   \      |
+        // +----\-----+
+        //       \
+        //        *------- the x we need.
+
+        // @Efficiency: We could just scroll it with the sprite.
+        top_aabb.position.x() = top_sprite.pivot.x() - top_aabb.size.x() / 2;
+        bottom_aabb.position.x() =
+            bottom_sprite.pivot.x() - bottom_aabb.size.x() / 2;
+
+        if (top_sprite.pivot.x() <= -1.2f) {
+            // Reset.
+            init(1.2f);
+            return;
+        }
+    }
+
+    void draw(const paradiso::Shader& shader) {
+        shader.set_uniform("pivot", top_sprite.pivot);
+        shader.set_uniform("scale", top_sprite.scale);
+        shader.set_uniform("rotation", top_sprite.rotation);
+        top_renderer.draw(top_sprite, shader);
+
+        shader.set_uniform("pivot", bottom_sprite.pivot);
+        shader.set_uniform("scale", bottom_sprite.scale);
+        shader.set_uniform("rotation", bottom_sprite.rotation);
+        bottom_renderer.draw(bottom_sprite, shader);
+    }
+};
+
+struct Plane {
+    static const unsigned int SPRITE_COUNT = 3;
+    static constexpr float GRAVITY = -0.001f;
+    static constexpr float JUMP_VELOCITY = 0.03f;
+    static constexpr float MAX_VELOCITY = 0.03f;
+
+    std::array<paradiso::Sprite, SPRITE_COUNT> sprites;
+    std::array<paradiso::Renderer, SPRITE_COUNT> renderers;
+
+    unsigned int anim_interval = 10;
+    unsigned int anim_counter = 0;
+
+    // The direction where 'current_sprite' should go because the animation
+    // shouldn't loop.
+    int anim_direction = 1;
+
+    unsigned int current_sprite = 0;
+
+    float position_y = 0.5f;
+    float rotation = 0.0f;
+
+    float velocity_y = 0.0f;
+
+    AABB aabb;
+
+    void init() {
+        // The image's size is 88x73 px.
+        float scale_x = 88.0f / (float)WINDOW_WIDTH;
+        float scale_y = 73.0f / (float)WINDOW_HEIGHT;
+
+        auto pivot = paradiso::Vector2<float>{
+            paradiso::Vector2<float>::make(0.0f, position_y)};
+        auto scale = paradiso::Vector2<float>{
+            paradiso::Vector2<float>::make(scale_x, scale_y)};
+
+        sprites = {
+            paradiso::Sprite{.bitmap = paradiso::BitmapIO::get().load(
+                                 "PNG/Planes/planeRed1.png"),
+                             .pivot = pivot,
+                             .scale = scale},
+            paradiso::Sprite{.bitmap = paradiso::BitmapIO::get().load(
+                                 "PNG/Planes/planeRed2.png"),
+                             .pivot = pivot,
+                             .scale = scale},
+            paradiso::Sprite{.bitmap = paradiso::BitmapIO::get().load(
+                                 "PNG/Planes/planeRed3.png"),
+                             .pivot = pivot,
+                             .scale = scale},
+        };
+
+        // We'll make the size half the size of the texture.
+        // (If you want 1:1 size, you need to double the scale of the sprite.)
+        auto size = paradiso::Vector2<float>{
+            paradiso::Vector2<float>::make(scale_x, scale_y)};
+
+        // Center it.
+        auto position = paradiso::Vector2<float>{paradiso::Vector2<float>::make(
+            pivot.x() - size.x() / 2, pivot.y() - size.y() / 2)};
+
+        aabb = AABB{position, size};
+    }
+
+    void update(const paradiso::Window::KeyboardInputStack& input) {
+        if (anim_counter < anim_interval) {
+            anim_counter++;
+        } else {
+            anim_counter = 0;
+
+            current_sprite += anim_direction;
+            if (current_sprite == SPRITE_COUNT - 1) {
+                anim_direction = -1;
+            } else if (current_sprite == 0) {
+                anim_direction = 1;
+            }
+        }
+
+        if (input.size() && input.top().key == ' ' && input.top().action == 1) {
+            velocity_y += JUMP_VELOCITY;
+        } else {
+            velocity_y += GRAVITY;
+        }
+
+        velocity_y = std::clamp(velocity_y, -MAX_VELOCITY, MAX_VELOCITY);
+        position_y += velocity_y;
+
+        // +---------+
+        // |         |
+        // |    #------- the y it is.
+        // |         |
+        // +----#----+
+        //       \     
+        //        *----- the y we need.
+
+        // @Efficiency: We could just add the velocity.
+        aabb.position.y() = position_y - aabb.size.y() / 2;
+
+        rotation = velocity_y * 500.0f;
+    }
+
+    void draw(const paradiso::Shader& shader) {
+        auto sprite = sprites[current_sprite];
+        sprite.rotation = rotation * (std::numbers::pi / 180.0f);
+        sprite.pivot.y() = position_y;
+
+        shader.set_uniform("pivot", sprite.pivot);
+        shader.set_uniform("scale", sprite.scale);
+        shader.set_uniform("rotation", sprite.rotation);
+        renderers[current_sprite].draw(sprite, shader);
+    }
+};
+
+auto main() -> int {
+    std::srand(std::time(nullptr));
+
+    auto canvas_size = paradiso::Size{.width = WINDOW_WIDTH * WINDOW_SCALE,
+                                      .height = WINDOW_HEIGHT * WINDOW_SCALE};
+
+    // Unser Fenster, auf das wir rendern.
+    auto window = paradiso::Window();
+    window
+        .set_size(canvas_size)                             // ... Größe
+        .set_position(paradiso::Point{.x = 200, .y = 200}) // ... Position
+        .set_title("ParadiSO.TappyPlane")                  // ... Titel
+        .set_visible(true); // ... und jetzt anzeigen!
+
+    // Der Fenster Context.
+    auto context = paradiso::Context{};
+
+    // Ein Shader (Schattierungsprogramm).
+    auto shader = paradiso::Shader{};
+
+    // Wir nutzen einen vorgefertigten Shader, der speziell für Sprites ist.
+    shader.load_preset(paradiso::Shader::Preset::Sprite);
+
+    // Ein Viewport stellt die Sicht der Kamera dar, d.h. bei quadratischen
+    // Pixeln sollte hier auch eine dementsprechende Größe eingestellt
+    // werden.
+    context.set_viewport(paradiso::Rectangle{
+        .position = paradiso::Point{.x = 0, .y = 0}, .size = canvas_size});
+
+    // Conflower blue
+    context.set_clearcolor(paradiso::RGBA::from_rgb(0x64, 0x95, 0xED));
+
+    // Der Asset Loader bekommt den Pfad.
+    paradiso::BitmapIO::get().set_path("assets");
+
+    // Wir initialisieren unsere Sachen.
+    auto background = Background{};
+    background.init();
+
+    auto ground = Ground{};
+    ground.init();
+
+    auto rocks1 = Rocks{};
+    rocks1.init(1.2f);
+
+    auto rocks2 = Rocks{};
+    rocks2.init(2.4f);
+
+    auto plane = Plane{};
+    plane.init();
+
+    auto top_aabb =
+        AABB{.position = {paradiso::Vector2<float>::make(-1.0f, 1.0f)},
+             .size = {paradiso::Vector2<float>::make(2.0f, 0.5f)}};
+
+    while (window.update([&](paradiso::Window& window) -> bool {
+        background.update();
+        ground.update();
+
+        rocks1.update();
+        rocks2.update();
+
+        plane.update(window.keyboard_input());
+
+        if (plane.aabb.is_colliding_with(rocks1.top_aabb) ||
+            plane.aabb.is_colliding_with(rocks1.bottom_aabb) ||
+            plane.aabb.is_colliding_with(rocks2.top_aabb) ||
+            plane.aabb.is_colliding_with(rocks2.bottom_aabb) ||
+            plane.aabb.is_colliding_with(top_aabb) ||
+            plane.aabb.is_colliding_with(ground.aabb)) {
+
+            std::cout << "COLLIDING" << std::endl;
+        }
+
+        auto t1 = std::chrono::high_resolution_clock::now();
+
+        context.set_viewport(paradiso::Rectangle{
+            .position = paradiso::Point{.x = 0, .y = 0}, .size = canvas_size});
+        context.clear();
+
+        background.draw(shader);
+
+        plane.draw(shader);
+
+        rocks1.draw(shader);
+        rocks2.draw(shader);
+
+        ground.draw(shader);
+
+        // Einen kurzen Moment warten, um auf 60 FPS zu kommen.
+        auto t2 = std::chrono::high_resolution_clock::now();
+        auto duration =
+            std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1);
+        auto wait = std::chrono::microseconds(1000000 / FRAME_RATE) - duration;
+        std::this_thread::sleep_for(wait);
+
+        if (window.keyboard_input().size() &&
+            window.keyboard_input().top().key == 'Q') {
+            // Update-Loop beenden.
+            return false;
+        }
+
+        return true;
+    })) {
+    };
+
+    return 0;
+}