From 7dc49635838f097ea6f3ab98b6133e2858b2a579 Mon Sep 17 00:00:00 2001 From: naezith Date: Mon, 28 Oct 2019 18:48:51 +0300 Subject: [PATCH] feat(tutorial): flappy bird start step 8 --- tutorials/flappy-bird/step_8/CMakeLists.txt | 76 +++ .../assets/config/game.config.maker.json | 1 + .../step_8/assets/textures/player.png | Bin 0 -> 7947 bytes .../step_8/data/linux/komodo_icon.png | Bin 0 -> 6961 bytes ....antara.gaming.sfml.flappybird.appdata.xml | 20 + .../org.antara.gaming.sfml.flappybird.desktop | 6 + .../data/osx/Packaging_CMakeDMGBackground.tif | Bin 0 -> 95690 bytes .../data/osx/Packaging_CMakeDMGSetup.scpt | 57 ++ .../flappy-bird/step_8/data/osx/kmd_logo.icns | Bin 0 -> 25970 bytes .../data/osx/sfml_flappybird_install.cmake | 35 ++ tutorials/flappy-bird/step_8/flappy-bird.cpp | 522 ++++++++++++++++++ 11 files changed, 717 insertions(+) create mode 100644 tutorials/flappy-bird/step_8/CMakeLists.txt create mode 100644 tutorials/flappy-bird/step_8/assets/config/game.config.maker.json create mode 100644 tutorials/flappy-bird/step_8/assets/textures/player.png create mode 100644 tutorials/flappy-bird/step_8/data/linux/komodo_icon.png create mode 100644 tutorials/flappy-bird/step_8/data/linux/org.antara.gaming.sfml.flappybird.appdata.xml create mode 100644 tutorials/flappy-bird/step_8/data/linux/org.antara.gaming.sfml.flappybird.desktop create mode 100644 tutorials/flappy-bird/step_8/data/osx/Packaging_CMakeDMGBackground.tif create mode 100644 tutorials/flappy-bird/step_8/data/osx/Packaging_CMakeDMGSetup.scpt create mode 100644 tutorials/flappy-bird/step_8/data/osx/kmd_logo.icns create mode 100644 tutorials/flappy-bird/step_8/data/osx/sfml_flappybird_install.cmake create mode 100644 tutorials/flappy-bird/step_8/flappy-bird.cpp diff --git a/tutorials/flappy-bird/step_8/CMakeLists.txt b/tutorials/flappy-bird/step_8/CMakeLists.txt new file mode 100644 index 00000000..a5122c42 --- /dev/null +++ b/tutorials/flappy-bird/step_8/CMakeLists.txt @@ -0,0 +1,76 @@ +if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) + message(FATAL_ERROR "Prevented in-tree build. Please create a build directory outside of the source code and call cmake from there") +endif () + +##! Minimum version of the CMake. +cmake_minimum_required(VERSION 3.14) + +##! C++ Standard needed by the SDK is 17 +set(CMAKE_CXX_STANDARD 17) + +##! Our Project title, here flappy-bird. +project(flappy-bird DESCRIPTION "An awesome flappy-bird" LANGUAGES CXX) + +##! The SDK need's clang as main compiler. +if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + message(FATAL_ERROR "Only Clang is supported (minimum LLVM 8.0)") +endif () + +##! We will let know the SDK if our on Linux +if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + set(LINUX TRUE) +endif () + +##! We include the module from CMake for fetching dependencies +include(FetchContent) + +##! We declare information about the dependance that we want to fetch. +FetchContent_Declare( + antara-gaming-sdk + URL https://github.com/KomodoPlatform/antara-gaming-sdk/archive/master.zip +) + +##! We set extras modules from the SDK that we want to use, here we will use the SFML module. +set(USE_SFML_ANTARA_WRAPPER ON) + +##! We fetch our dependence +FetchContent_MakeAvailable(antara-gaming-sdk) + +##! Calling this macros provided by the sdk will if you are on Apple init the environment for this OS (std::filesystem). +init_apple_env() + +##! Osx bundle icon +set(ICON) +configure_icon_osx(data/osx/kmd_logo.icns ICON kmd_logo.icns) + +##! We create the executable with the project name +add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${ICON} flappy-bird.cpp) + +##! Setting output directory +set_target_properties(${PROJECT_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/" + ) + +##! We link the SDK modules that we want to use to our executable +target_link_libraries(${PROJECT_NAME} PUBLIC antara::world antara::sfml antara::collisions) + +##! Move assets +if (WIN32) + file(COPY assets DESTINATION ${CMAKE_BINARY_DIR}/bin/) + ADD_CUSTOM_COMMAND(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory "${SFML_BINARY_DIR}/lib" "${CMAKE_BINARY_DIR}/bin/" + COMMENT "copying dlls …" + $ + ) + + ADD_CUSTOM_COMMAND(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy "${SFML_SOURCE_DIR}/extlibs/bin/x64/openal32.dll" "${CMAKE_BINARY_DIR}/bin/openal32.dll" + COMMENT "copying dlls …" + $ + ) +endif () + +if (APPLE) + file(COPY assets DESTINATION ${CMAKE_BINARY_DIR}/bin/${PROJECT_NAME}.app/Contents/Resources) +endif() \ No newline at end of file diff --git a/tutorials/flappy-bird/step_8/assets/config/game.config.maker.json b/tutorials/flappy-bird/step_8/assets/config/game.config.maker.json new file mode 100644 index 00000000..6690ed44 --- /dev/null +++ b/tutorials/flappy-bird/step_8/assets/config/game.config.maker.json @@ -0,0 +1 @@ +{"background_color":[0,0,0,255],"canvas_height":1080.0,"canvas_width":1920.0,"custom_canvas_height":true,"custom_canvas_width":true,"native_desktop_mode":false,"scale_mode":"fit","window_height":1080.0,"window_title":"game title","window_width":1920.0} \ No newline at end of file diff --git a/tutorials/flappy-bird/step_8/assets/textures/player.png b/tutorials/flappy-bird/step_8/assets/textures/player.png new file mode 100644 index 0000000000000000000000000000000000000000..52dcda4a3e88bcf67b3cf782a7da9608046c8998 GIT binary patch literal 7947 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 ZG$kE7x;T#s#Xo=O%1J9rRY{lx{|^fGTw4GD literal 0 HcmV?d00001 diff --git a/tutorials/flappy-bird/step_8/data/linux/komodo_icon.png b/tutorials/flappy-bird/step_8/data/linux/komodo_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..89e5dd2886effbf66ae210e622544aac2e58d674 GIT binary patch literal 6961 zcmZ{JXE+<)`+g!pVz1hJwsvf4#NMkYO6_VXMeR`%Go^MFwW+;=8dWsthpMe=)QVD6 zk=P@~&-dm3#s50jbM7;q`@YVb=UmTu&TBIhT}m=mG5`QTsjsK?;1&`8GYH9T->>RC zd<)>G>c;8-KvOFDr8DvEoZD6JfiVCOCV1-?3jkdF&wmR52$Tc>ww(X~r5pf&$v3~# zT={l`#Kllo3vlzlR@_~gdAkDj)wA^n07MP`XTadFfLkd5X@I`5Ht8CamW&kS^5RDw z0Km$vucdAo@@uysw2R#;Yw$~D&2mN@UJn7Lq$AN#aPmIqirN;)tFIgvZDIgvW)Itfd%IcT!Z_=Gz^l zqum|hbYH>CP$OUv=mdBI2pWK(Lyvl_FDs&ngv*7dw}9N|YDB!;vE1FLI(0Y29{Hja zC(hk#i;?aqPUIK%%9L(u@1Pd`=fm!fm^6v$SaA&4$rP)C`HWmb)+0|!3iL4acoj&* z{kHRyXQw492&(XBJE5zS4hkoe8xjMj?(}D~*u|GbToqqx=Z&o%f0iQ<$%Xm-SGY{v zMX$h`Lu^Dkz^~eb%cA4P8=?J>?SyCQc<(Fy2~K7YB2#FW;@L9GT?s67Cjj1(_u|{L zAs%kJ2n6)P2CIp2nC3m|8*$q zy1)crB@oyDrb8wYrlc1)Yj7hLdfzlZGB&O2@#_m6o*(h zMIHWvYrb8{2wVb3TKF`welS4f;7`Fl#O#?TJ~O!A!_WsIWkzR{7L~!sMIubBO5Uqu zO&!m^+XH|Gfh#0I-cu^VX~0e-B_^zxl!v}s9L}ak`t5FP6T}rU$(wy{JZHZm3PX1z59`rev2aL1K(WwNpXSPjV#fP?XNC@Dy1M38nE!m zi5SwNbTD8<{y~Z;o(M0E)o~IqYk64326S1wV!(dJK;Oo?{7YmJ?eQfS2v_gVR}XqY92pB!y+0DiiMx6V%9fUCRin}Hx_bsp(^(aU+W?bYuTa*bJ|I{6$T3)R~=~!=`i5yDs1Q zSkg=u=%QZGg7{HAZi$l};l6;OBQxnE?tu+$8-?0TFaE26(6F7RlJ;o4vQcI_qm!%u zVQhcqv=-FuPjc`V*YHb%Di;7-#Sz;Z?e0DPuOi6tYhP7f;rGTjLEAW1oFEck5_a58 zET{9OY=C^sS$xz~x;d6wGKID71c;XW%arf|=yK1#i1@l>AZe7y+J$7jla~KXxx&nm zD8RJ=uN8?un0Q)&%ik1Ej-tP8Bu0oiO)vhGPyy{+JnUQD z4%X3yY6r27S_tA-+jnAz0kf{@<63iffiB%QmY#?EB8*2JY3U*n=npxX+aWzSz(^23 z6$zytLaO%0$TJUj!+9pm=RcBKdqdw;zI}|j%6aJEIIK@X@5%PA-7#tHw+|-NMrZ7s zrpMOl2c>*i((#3<>x;wp2S8y~WYh8ur>FmM114XY&%4GtB}kMl>=EVW7I4Ga^}4Z1 z&tsHDoh^^}O<%>U$I$Ttpm?ux1fRv(f6F(p_!)w~P0j4fy2H9Y@E7L1Z55M(2fYVd zx(FLw5pma-c>f#5Gw7R;Rjzo&agvueN}>t-4s|Uf{d8*bPTR|jA|Kv*s-}@J$JI|6 zcbfSF@kP_miYe?E;-YBYiI@+?Kfv17WnNMZ+Xp2(SeR+ts;WWq8U@uElQzd=Xy*vV zXPkH-Hr&#Ix{1}W=rb#Q#1F002~aG?}yMwHq8b*+Zt_}&-q^z69niADM1 zwJuUx^3>Zv|9dlkZ+%WosX*Ax)X$t5;*z{KIF4xBiv&;} zrLSUC|4z+Q#5)?*qglXOQ>l?YUhrLao<{|K@Y++(GcfAc-?5!|97pvx+Gu%A?Y03A zQkVEv)T3(D7V7TrEvxi9RjS6}3-*CZYG;HPk?G96s?NE)k5@j+_Q)H*^5LRAv8ud} z9U7>ZZgh%7yrWaq0;7(vuVAx2bc;HwqVr&{ptaE|r4K?sUT<Lk)1nqwmDL$~ zOG4uK6u{KU9KHV-7A^nFOY~*0q0-gSYTjnh@}?}Yp!TCtE3$?S{79;Q6A5^BZ&fpj z(pTo)j;+`Xk=h_T3*}(Pb07H3Y2x$4)Be*QM2D;2vO;yt~K{%KQR=Z{@O7MSg7 zwUSnn`|imrTnRKPUz7A;)^p+afF~qD`uIadEaS+NdC7psksR-#v`@m7KQT|HBA>I_ zr%k}=E}?ec-#OqM4-{glEKjx9Nm1<41BpDfK_#7(Ce(t{)V~)MQObi!)cr>>5SO)^ z5`K%DLnNWtulvitj9Q)m)DIQ>dO~7wNMLjv zYWy!$8MgVz$+i&i8DuBW5v!dOQwIB{h!9u)q=lz4;w{!m2Lzfn_n7`Pt<@n(qrA;6 zbM3cwB|8{>mG1mx`3gZ(XFbl2S#6waZkUFxUJg5Xr=o2KbFr_UN%GYV@qa6AhQQlb zB)WBmVgdBD(Jon^yNb)k-#!OcYPH04(|(f1fWPQQ7g=L@=o<8@N$d)Pb03F1^-YTp zW8A(hvH5MxuP!l#h)%BnhVjl;dRc-LlGD|Dn}oV;B`}L$^dDr+&=AW$;JT4k)Czoi zvCO2k^ue>j)tFbE(R8Ya@$?DMHg=mt=G|v=)xGSK>r29CZZA$J+nP+e%S$>@t9w>n zfdlOrMKgEkUKPLpK}8x|c66wyM4l84d7`)#fDtbC?Ah}>`lP_~v6xmc#)J&*mBrt5 zb3TpccCMn?Ep^zuJrGM#EUQfi9|DMSP<5IuiDR}2 z{MCO>m6P#T31pI*8Y=d!ayWaC{>1BQMyvC5C zc~jpN&n(C>+rk{Z^k))I<9oka~sZ=MMPmIb=kIy<^z|x9f$1^&%|l z&M1)4Vv+*f^U>p!GR5LOITuBx=IR3K{}}7^i@?p)!kKyt#>?5nHprZee1<%UFUR;dLOZ=n-;#5OU_KxXUaI}SbTuU5+= zbym+1ZqkTjt)EI3+EoY>&GLS^W9Ena%zWQXila4n!{YtOljv%|x&q+L9UH8>|7lX*`-Lm%`?k=OR{_t)72y;TMkdUo))R>k=qzUrun@m46mIRd79==DG0Zp!t5VLyf0rn~6j@ z%@(abO#CaiY!3C%KQavf)qjpkwU}0f5Sv$X=d8ks@`kDmVGi!#yV{XVGT-%RR%E1E z$%rzJ-BRBMb7oJ#{*G-fCYHGeEW8<@RHLi%!knVUNB>drA#}S!tcP@F_jSti0pi@h z9+n#fq@C0g;Gjh>R}8l|KuKC?CJ zmR`Ri-8zJy{9%Ao^?EW~Ub1pMYo;A)nZGRdYTmv^8o}Epl&k5Jo8aAPBW6szARyY) z+_7g9G<)Z~GT5abPFrsroef=L&!4(lP5m&V`s99_RT7QOj`OFhS5OnQNb&;Y!lSg0 zUf`J(UF;rp!>FUy9L@2HN%O1Ra74DUXp{frXnLbczi^^c=hk>aW3#skU6*>5{JGC@ zCneX-pw7opaK_U>iT%5b0(FcF<~Q9w7d&zli=ajGea(99=y^!0?6VzG`pAq7)nTNy ziWg;g#*lBSPnqz)lV>^{Zu8y+k|E!300 zdSZvyMSLtZ*7SXaOl~x#oN>QeOrN{ivBRbAdl9!al)(`KHpIi8ldrS1yipu9Y-Eg1 zStCX4`2J+RUQGoRJE>3B-Chc3#?!#2(fg^qxu7kU5r`;FF&mp>CiWG-on0CPMmIvN zs_ie^tMdEkN5)V$ysGZ{fF;?J1YH;v(uY&kTPN(hh=gBjG#jlvMxD@mPIwjPgN2;K zH!a7^jS|2t8o^}>D%w(?HlZBPudhbp7sKn4Q^7$-zKQK9PsZ)QmAg&YqCQ@qpS+lp zKK+cx`OGjn(XR&R$Qa}$%dtSOh(a)@$#{lW$J;`RS_$RK^mZz_-TUco(&$ap=tTq| zSCM>V_=L*q`JpEa>iTn7%AZjgR>@P3pDEQ1eLh+CCNIcIqGE;<(>HzJtPov#E)#l> zeV2w~tl>u3U5Itd}Wv)M9#9E6MM&nSjseA^!|o{8x1rr5NR zRtRQ*nP;4~PsN`ltAK=^7fvGv3eS2F&#>*QeQD*VkIffeTWHjsawXjTK4yAv8f8e+2pk6%XUbXb+Yb~ zpBEZO9GeDq#5|KuJ#Y@?*43bH)ApEpbrVE#U9i5r?ak1nh!4yVTB#$B{0a zq!G|=BOlHr+j{pG9&rOp<>*JYZ=5JAJ30Iht!2K;Zy4Y-O8i<8tur{~d5WpMUDE`c9>Fl0OazrEwkk zF=u9Gm_Z8x{16yeVsr)C~>5Nt<`!|ZUxfy;Hdz%1Fy-?gfhY}4mya3Qy$4rpVYMp zHInqi&x2dJG111euFolS-xd{n)dYj^P*0|7Wv`HW;dtpIE-@r~H6p6glf>sffFi!{I}JK{4+lG^Z2uRBk8(d#wzYASD)UJ{eIln# z_w6s!pM@9fjC1EyZPuFgTg2iR-VQ73@}K16dc`&sqhPP$^G7VojD`XERLT<4PrG~W zdBo&6Mmb``bE4FSqQ_pw&PCivac6%`F%a$8st|PQ*`WV7=RgjVn3F(d7{u2inc4oe zV}73(RrVNe`}A4fy#L^B`J54FAbRqJMXur}=m!GlI+TE z8E#ZPojIz`N!na*6m1j!(e-c^_vR?u2>bFRF0rBPnji2(rrotCMi(_B{*jEu#aoiZt}%+tm*O3tt*{3r7 z35Iz{=13J0dsLIKj^1`ZbwZ{N!fv!|8sk~kIbV5QbgJo`oVxfC9#wt?@qEot8W(zW zW78O37d~`4w}a&!5zBS6`0hE8@KfnhWCN0$R6Y1p%gQuE?x7LZd#>XTj-o>Q zK#_{my=1fYMX)nebiuW4v|-YZ%zdK#iv*g7EAEO`6S6C)?kP`~jv1`*UlFv0^@qV> z$Y597F}Axe!m=8ZrsJVe404g1wLa~Y^ExrNl@5k6F8#?d{ovWuQnDp_*8`Z02l2k7 z24mhuWHOK2(RAX+H;kIFAiR=$oj2xN+V$A4e)>iijz2_R@tGHv?atd`a!-^P?6!Or zJm`JTxJeh2S;A5$FxB2`U^5C{v4MOg5!mPATIbn`_ckc#HPMLgPn`?d_b%A4rLNNG ziLKXflzDG2wEt*Yf`4eVh}skU_%ztwF}xIf$AqqK6tYjSJ+XF9@}-aS`xjS12QY9a zE0g?;l@X1esZx2(8Yi2>brUvHutYwZ`c$R>5J!HGvZRN6IP*TMoxl&NSz7@He}koz zKk~{tA59u>)BiF7HaT8R#1jYylgf$9nGx5l>k}`Z|A-XG5ooJePF+K~VqZV)`iZ#n z<<#Ez*MC29vdp+PY!c80&!b$K-DFy2fCl0p75sA$9x<9t6aV&XhA#NEGoP!IB*9ga z?o?lrzkA>Pp2YNzXD^xuKBS$^nvw~l+ldKfsdUaVlpoxA{YZ0)N_uX_sbr2gr?}`V znWtEpHbo~t^E>cXFnzi6g7}E^bTJ?DWA^)X*E8AcXltOxqoFVC^nvK~ zCEW%l><*s>ReU98c>hM(twd=*qxSUn`$!-_+a|!xIpB$s>&qv%0FaV|DT+xdioxV9 wVUkLc@=B6YB9gZQ$s7%vzW;~d?c?U*9{T?${N=(%-Vy-%+9p~J8cxyw2lim^&;S4c literal 0 HcmV?d00001 diff --git a/tutorials/flappy-bird/step_8/data/linux/org.antara.gaming.sfml.flappybird.appdata.xml b/tutorials/flappy-bird/step_8/data/linux/org.antara.gaming.sfml.flappybird.appdata.xml new file mode 100644 index 00000000..7e6a1046 --- /dev/null +++ b/tutorials/flappy-bird/step_8/data/linux/org.antara.gaming.sfml.flappybird.appdata.xml @@ -0,0 +1,20 @@ + + org.antara.gaming.sfml.flappybird.desktop + MIT + MIT + flappy-bird + flappy-bird tutorial antara gaming sdk + +

Written in c++17

+
+ org.antara.gaming.sfml.flappybird.desktop + https://github.com/KomodoPlatform/antara-gaming-sdk + + + https://www.freedesktop.org/software/appstream/docs/images/scr-examples/geany-good.png + + + + org.antara.gaming.sfml.flappybird.desktop + +
\ No newline at end of file diff --git a/tutorials/flappy-bird/step_8/data/linux/org.antara.gaming.sfml.flappybird.desktop b/tutorials/flappy-bird/step_8/data/linux/org.antara.gaming.sfml.flappybird.desktop new file mode 100644 index 00000000..d525c088 --- /dev/null +++ b/tutorials/flappy-bird/step_8/data/linux/org.antara.gaming.sfml.flappybird.desktop @@ -0,0 +1,6 @@ +[Desktop Entry] +Type=Application +Name=flappy-bird +Exec=flappy-bird +Icon=komodo_icon +Categories=Game; \ No newline at end of file diff --git a/tutorials/flappy-bird/step_8/data/osx/Packaging_CMakeDMGBackground.tif b/tutorials/flappy-bird/step_8/data/osx/Packaging_CMakeDMGBackground.tif new file mode 100644 index 0000000000000000000000000000000000000000..91c4b1309be02edcd057985b52355b2ed1168424 GIT binary patch literal 95690 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 D+gpN` literal 0 HcmV?d00001 diff --git a/tutorials/flappy-bird/step_8/data/osx/Packaging_CMakeDMGSetup.scpt b/tutorials/flappy-bird/step_8/data/osx/Packaging_CMakeDMGSetup.scpt new file mode 100644 index 00000000..2bea22d8 --- /dev/null +++ b/tutorials/flappy-bird/step_8/data/osx/Packaging_CMakeDMGSetup.scpt @@ -0,0 +1,57 @@ +on run argv + set image_name to item 1 of argv + + tell application "Finder" + tell disk image_name + + -- wait for the image to finish mounting + set open_attempts to 0 + repeat while open_attempts < 4 + try + open + delay 1 + set open_attempts to 5 + close + on error errStr number errorNumber + set open_attempts to open_attempts + 1 + delay 10 + end try + end repeat + delay 5 + + -- open the image the first time and save a DS_Store with just + -- background and icon setup + open + set current view of container window to icon view + set theViewOptions to the icon view options of container window + set background picture of theViewOptions to file ".background:background.tif" + set arrangement of theViewOptions to not arranged + set icon size of theViewOptions to 128 + delay 5 + close + + -- next setup the position of the app and Applications symlink + -- plus hide all the window decorationPackaging_CMakeDMGBackground.tif + open + update without registering applications + tell container window + set sidebar width to 0 + set statusbar visible to false + set toolbar visible to false + set the bounds to { 400, 100, 900, 465 } + set position of item "flappy-bird.app" to { 133, 200 } + set position of item "Applications" to { 378, 200 } + end tell + update without registering applications + delay 5 + close + + -- one last open and close so you can see everything looks correct + open + delay 5 + close + + end tell + delay 1 +end tell +end run \ No newline at end of file diff --git a/tutorials/flappy-bird/step_8/data/osx/kmd_logo.icns b/tutorials/flappy-bird/step_8/data/osx/kmd_logo.icns new file mode 100644 index 0000000000000000000000000000000000000000..5977224d9b241f7964492a95bbe371329597bcda GIT binary patch literal 25970 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 literal 0 HcmV?d00001 diff --git a/tutorials/flappy-bird/step_8/data/osx/sfml_flappybird_install.cmake b/tutorials/flappy-bird/step_8/data/osx/sfml_flappybird_install.cmake new file mode 100644 index 00000000..2bda51ae --- /dev/null +++ b/tutorials/flappy-bird/step_8/data/osx/sfml_flappybird_install.cmake @@ -0,0 +1,35 @@ +if (APPLE) + set_target_properties(${PROJECT_NAME} PROPERTIES + MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_NAME}" + RESOURCE data/osx/${PROJECT_NAME}.icns + MACOSX_BUNDLE_ICON_FILE ${PROJECT_NAME} + MACOSX_BUNDLE_SHORT_VERSION_STRING 0.0.1 + MACOSX_BUNDLE_LONG_VERSION_STRING 0.0.1 + MACOSX_BUNDLE_INFO_PLIST "${PROJECT_SOURCE_DIR}/cmake/MacOSXBundleInfo.plist.in") + add_custom_command(TARGET ${PROJECT_NAME} + POST_BUILD COMMAND + ${CMAKE_INSTALL_NAME_TOOL} -add_rpath "@executable_path/../Frameworks/" + $) +endif () + +if (APPLE) + install(TARGETS ${PROJECT_NAME} + BUNDLE DESTINATION . COMPONENT Runtime + RUNTIME DESTINATION bin COMPONENT Runtime + ) + + # Note Mac specific extension .app + set(APPS "\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.app") + + # Directories to look for dependencies + set(DIRS ${CMAKE_BINARY_DIR}) + + install(CODE "include(BundleUtilities) + fixup_bundle(\"${APPS}\" \"\" \"${DIRS}\")") + + set(CPACK_GENERATOR "DRAGNDROP") + set(CPACK_DMG_DS_STORE_SETUP_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/data/osx/Packaging_CMakeDMGSetup.scpt") + set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_CURRENT_SOURCE_DIR}/data/osx/Packaging_CMakeDMGBackground.tif") + set(CPACK_PACKAGE_NAME "${PROJECT_NAME}") + include(CPack) +endif () \ No newline at end of file diff --git a/tutorials/flappy-bird/step_8/flappy-bird.cpp b/tutorials/flappy-bird/step_8/flappy-bird.cpp new file mode 100644 index 00000000..e460000e --- /dev/null +++ b/tutorials/flappy-bird/step_8/flappy-bird.cpp @@ -0,0 +1,522 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//! For convenience +using namespace antara::gaming; + +namespace { + std::random_device rd; // Will be used to obtain a seed for the random number engine + std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd() + float random_float(float lower, float higher) { + std::uniform_real_distribution dist(lower, higher); + return dist(gen); + } +} + +struct flappy_bird_constants { + // Controls + const input::mouse_button jump_button{input::mouse_button::left}; + // Player + const float gravity{2000.f}; + const float jump_force{500.f}; + + // Pipes + const float gap_height{200.f}; + const float column_min{0.2f}; + const float column_max{0.8f}; + const float column_thickness{100.f}; + const float column_distance{400.f}; + const std::size_t column_count{6}; + const float pipe_cap_extra_width{10.f}; + const float pipe_cap_height{50.f}; + const graphics::color pipe_color{92, 181, 61}; + const graphics::outline_color pipe_outline_color{2.0f, graphics::color{76, 47, 61}}; + const float scroll_speed{200.f}; + const std::string player_image_name{"player.png"}; + + // Background + const float ground_thickness{100.0f}; + const float grass_thickness{20.0f}; + const graphics::color background_color{82, 189, 199}; + const graphics::color ground_color{220, 209, 143}; + const graphics::color grass_color{132, 227, 90}; + const graphics::outline_color grass_outline_color{2.0f, graphics::color{76, 47, 61}}; +}; + +// A Flappy Bird column which has two pipes +struct pipe { + entt::entity body{entt::null}; + entt::entity cap{entt::null}; + + void destroy(entt::registry ®istry) { + registry.destroy(body); + registry.destroy(cap); + } +}; + +struct column { + //! Entities representing the Flappy Bird pipes + pipe top_pipe{entt::null}; + pipe bottom_pipe{entt::null}; + + void destroy(entt::registry ®istry, entt::entity entity) { + top_pipe.destroy(registry); + bottom_pipe.destroy(registry); + registry.destroy(entity); + } +}; + +//! Contains all the function that will be used for logic and factory +namespace { + // Factory for pipes, requires to know if it's a top one, position x of the column, and the gap starting position Y + pipe create_pipe(entt::registry ®istry, bool is_top, float pos_x, float gap_start_pos_y) { + // Retrieve constants + const auto canvas_height = registry.ctx().canvas.size.y(); + const auto constants = registry.ctx(); + + // PIPE BODY + // Top pipe is at Y: 0 and bottom pipe is at canvas_height, bottom of the canvas + transform::position_2d body_pos{pos_x, is_top ? 0.f : canvas_height}; + + // Size X is the column thickness, + // Size Y is the important part. + // If it's a top pipe, gap_start_pos_y should be bottom of the rectangle + // So half size should be gap_start_pos_y since center of the rectangle is at 0. + // If it's the bottom pipe, top of the rectangle will be at gap_start_pos_y + gap_height + // So half size should be canvas_height - (gap_start_pos_y + gap_height) + // Since these are half-sizes, and the position is at the screen border, we multiply these sizes by two + math::vec2f body_size{constants.column_thickness, + is_top ? + gap_start_pos_y * 2.0f : + (canvas_height - (gap_start_pos_y + constants.gap_height)) * 2.0f}; + + auto body = geometry::blueprint_rectangle(registry, body_size, constants.pipe_color, body_pos, constants.pipe_outline_color); + + // PIPE CAP + // Let's prepare the pipe cap + // Size of the cap is defined in constants + math::vec2f cap_size{constants.column_thickness + constants.pipe_cap_extra_width, constants.pipe_cap_height}; + + // Position, X is same as the body. Bottom of the cap is aligned with bottom of the body, + // or start of the gap, we will use start of the gap here, minus half of the cap height + transform::position_2d cap_pos{body_pos.x(), + is_top ? + gap_start_pos_y - constants.pipe_cap_height * 0.5f : + gap_start_pos_y + constants.gap_height + constants.pipe_cap_height * 0.5f + }; + + // Construct the cap + auto cap = geometry::blueprint_rectangle(registry, cap_size, constants.pipe_color, cap_pos, constants.pipe_outline_color); + + // Set layers, cap should be in front of body + registry.assign>(cap); + registry.assign>(body); + registry.assign>(cap); + registry.assign>(body); + registry.assign>(cap); + registry.assign>(body); + + // Construct a pipe with body and cap and return it + return {body, cap}; + } + + // Returns a random gap start position Y + float get_random_gap_start_pos(entt::registry ®istry) { + //! Retrieve constants + const auto canvas_height = registry.ctx().canvas.size.y(); + const auto constants = registry.ctx(); + + float top_limit = canvas_height * constants.column_min; + float bottom_limit = canvas_height * constants.column_max - constants.gap_height; + + return random_float(top_limit, bottom_limit); + } + + // Factory to create single column + void create_column(entt::registry ®istry, float pos_x) noexcept { + // Create a fresh entity for a new column + auto entity_column = registry.create(); + + // Get a random gap start position Y, between pipes + float gap_start_pos_y = get_random_gap_start_pos(registry); + + // Create pipes, is_top variable is false for bottom one + auto top_pipe = create_pipe(registry, true, pos_x, gap_start_pos_y); + auto bottom_pipe = create_pipe(registry, false, pos_x, gap_start_pos_y); + + // Make a column from these two pipes and mark it as "column" + registry.assign(entity_column, top_pipe, bottom_pipe); + registry.assign>(entity_column); + registry.assign>(entity_column); + registry.assign>(entity_column); + } + + //! Factory for creating a Flappy Bird columns + void create_columns(entt::registry ®istry) noexcept { + //! Retrieve constants + const auto canvas_width = registry.ctx().canvas.size.x(); + const auto constants = registry.ctx(); + + // Spawn columns out of the screen, out of the canvas + const float column_pos_offset = canvas_width + constants.column_thickness * 2.0f; + + // Create the columns + for(std::size_t i = 0; i < constants.column_count; ++i) { + // Horizontal position (X) increases for every column, keeping the distance + float pos_x = column_pos_offset + i * constants.column_distance; + + create_column(registry, pos_x); + } + } + + //! Factory for creating a Flappy Bird background + void create_background(entt::registry ®istry) noexcept { + //! Retrieve constants + const auto[canvas_width, canvas_height] = registry.ctx().canvas.size; + const auto constants = registry.ctx(); + + // Create Sky + { + // Sky is whole canvas so position is middle of it + transform::position_2d pos{canvas_width * 0.5f, canvas_height * 0.5f}; + + // And the size is full canvas + math::vec2f size{canvas_width, canvas_height}; + + auto sky = geometry::blueprint_rectangle(registry, size, constants.background_color, pos); + registry.assign>(sky); + registry.assign>(sky); + } + + // Create Grass + { + // Ground expands to whole canvas width so position is middle of it, + // But position Y is at top of the ground, so it's canvas height minus ground thickness + transform::position_2d pos{canvas_width * 0.5f, canvas_height - constants.ground_thickness}; + + // Size X is full canvas but the height is defined in constants + // We also make it a bit longer by adding the thickness of the outline to hide the outline at sides + math::vec2f size{canvas_width + constants.grass_outline_color.thickness * 2.0f, constants.grass_thickness}; + + auto grass = geometry::blueprint_rectangle(registry, size, constants.grass_color, pos, constants.grass_outline_color); + registry.assign>(grass); + registry.assign>(grass); + } + + // Create Ground + { + // Ground expands to whole canvas width so position is middle of it, + // But position Y is at bottom of the screen so it's full canvas_height minus half of the ground thickness + transform::position_2d pos{canvas_width * 0.5f, canvas_height - constants.ground_thickness * 0.5f}; + + // Size X is full canvas but the height is defined in constants + math::vec2f size{canvas_width, constants.ground_thickness}; + + auto ground = geometry::blueprint_rectangle(registry, size, constants.ground_color, pos); + registry.assign>(ground); + registry.assign>(ground); + } + } + + //! Factory for creating the player + entt::entity create_player(entt::registry ®istry) { + //! Retrieve constants + const auto [canvas_width, canvas_height] = registry.ctx().canvas.size; + const auto constants = registry.ctx(); + + auto entity = graphics::blueprint_sprite(registry, + graphics::sprite{constants.player_image_name.c_str()}, + transform::position_2d{canvas_width * 0.2f, canvas_height * 0.2f}); + registry.assign>(entity); + registry.assign>(entity); + registry.assign>(entity); + registry.assign>(entity); + + return entity; + } +} + +class column_logic final : public ecs::logic_update_system { +public: + explicit column_logic(entt::registry ®istry) noexcept : system(registry) { } + + void update() noexcept final { + auto& registry = entity_registry_; + + //! Retrieve constants + const auto constants = registry.ctx(); + + // Loop all columns + for(auto entity : registry.view()) { + auto& col = registry.get(entity); + + // Move pipes, and check if they are out of the screen + bool col_out_of_screen = move_pipe(registry, col.top_pipe) || move_pipe(registry, col.bottom_pipe); + + // If column is out of the screen + if(col_out_of_screen) { + // Remove this column + col.destroy(registry, entity); + + // Create a new column at far end + create_column(registry, furthest_pipe_position(registry) + constants.column_distance); + } + } + } + +private: + // Find the most far pipe's position X + float furthest_pipe_position(entt::registry ®istry) { + float furthest = 0.f; + + auto view = registry.view(); + + for(auto entity : view) { + auto& col = registry.get(entity); + float x = entity_registry_.get(col.top_pipe.body).x(); + if(x > furthest) furthest = x; + } + + return furthest; + } + + // Move the pipe and return if it's out of the screen + bool move_pipe(entt::registry ®istry, pipe& pipe) { + // Retrieve constants + const auto constants = registry.ctx(); + + // Get current position of the pipe + auto pos = registry.get(pipe.body); + + // Shift pos X to left by scroll_speed but multiplying with dt because we do this so many times a second, + // Delta time makes sure that it's applying over time, so in one second it will move scroll_speed pixels + auto new_pos_x = pos.x() - constants.scroll_speed * timer::time_step::get_fixed_delta_time(); + + // Set the new position value + registry.assign_or_replace(pipe.body, new_pos_x, pos.y()); + + // Set cap position too + auto cap_pos = registry.get(pipe.cap); + registry.assign_or_replace(pipe.cap, new_pos_x, cap_pos.y()); + + // Return the info about if this pipe is out of the screen + return new_pos_x < -constants.column_thickness * 2.0f; + } +}; + +//! Give a name to our system +REFL_AUTO(type(column_logic)); + +class player_logic final : public ecs::logic_update_system { +public: + player_logic(entt::registry ®istry, entt::entity player_) noexcept : system(registry), player(player_) { } + + void update() noexcept final { + auto& registry = entity_registry_; + + //! Retrieve constants + const auto constants = registry.ctx(); + + // Get current position of the pipe + auto pos = registry.get(player); + + // Add gravity to movement speed, multiply with delta time to apply it over time + movement_speed.set_y(movement_speed.y() + constants.gravity * timer::time_step::get_fixed_delta_time()); + + // Check if jump key is tapped + bool jump_key_pressed = input::is_mouse_button_pressed(constants.jump_button); + bool jump_key_tapped = jump_key_pressed && !jump_key_pressed_last_tick; + jump_key_pressed_last_tick = jump_key_pressed; + + // If jump is tapped, add jump force to the movement speed + if (jump_key_tapped) movement_speed.set_y(-constants.jump_force); + + // Add movement speed to position, but apply over time with delta time + pos += movement_speed * timer::time_step::get_fixed_delta_time(); + + // Set the new position value + registry.assign_or_replace(player, pos); + } + +private: + entt::entity player; + math::vec2f movement_speed{0.f, 0.f}; + bool jump_key_pressed_last_tick = false; +}; + +//! Give a name to our system +REFL_AUTO(type(player_logic)); + +class collision_logic final : public ecs::logic_update_system { +public: + collision_logic(entt::registry ®istry, entt::entity player_, bool& player_died_) noexcept : system(registry), player(player_), player_died(player_died_) { } + + void update() noexcept final { + auto& registry = entity_registry_; + + // Do not check anything if player is already dead + if(player_died) return; + + // Loop all columns to check collisions with the pipes + for(auto entity : registry.view>()) { + // Check collision between player and a collidable object + if(collisions::basic_collision_system::query_rect(registry, player, entity)) { + // Mark player died as true + player_died = true; + } + } + } + +private: + entt::entity player; + bool& player_died; +}; + +//! Give a name to our system +REFL_AUTO(type(collision_logic)); + +class game_scene final : public scenes::base_scene { +public: + game_scene(entt::registry ®istry, ecs::system_manager& system_manager_) noexcept : base_scene(registry), system_manager(system_manager_) { + //! Set the constants that will be used in the program + registry.set(); + + //! Create the columns + create_background(registry); + init_dynamic_objects(registry); + } + + //! Scene name + std::string scene_name() noexcept final { + return "game_scene"; + } + +private: + //! Update the game every tick + void update() noexcept final { + // Retrieve constants + const auto constants = entity_registry_.ctx(); + + // Check if jump key is tapped + bool jump_key_pressed = input::is_mouse_button_pressed(constants.jump_button); + bool jump_key_tapped = jump_key_pressed && !jump_key_pressed_last_tick; + jump_key_pressed_last_tick = jump_key_pressed; + + // If game is not started yet and jump key is tapped + if(!started_playing && jump_key_tapped) { + // Game starts, player started playing + started_playing = true; + resume_physics(); + } + + // If player died, game over, and pause physics + if(player_died) { + player_died = false; + game_over = true; + pause_physics(); + } + + // If game is over, and jump key is pressed, reset game + if(game_over && jump_key_pressed) reset_game(); + } + + void init_dynamic_objects(entt::registry ®istry) { + create_columns(registry); + + auto player = create_player(registry); + + //! Create systems + system_manager.create_system(); + system_manager.create_system(player); + + // Disable physics and everything at start + pause_physics(); + + // Collision system + system_manager.create_system(player, player_died); + + // Reset state values + started_playing = false; + player_died = false; + game_over = false; + } + + void pause_physics() { + system_manager.disable_systems(); + } + + void resume_physics() { + system_manager.enable_systems(); + } + + void destroy_all() { + //! Retrieve the collection of entities from the game scene + auto view = entity_registry_.view>(); + + //! Iterate the collection and destroy each entities + entity_registry_.destroy(view.begin(), view.end()); + + //! Delete systems + system_manager.mark_systems(); + } + + void reset_game() { + destroy_all(); + this->need_reset = true; + } + + void post_update() noexcept final { + if(need_reset) { + //! Reinitialize all these + init_dynamic_objects(entity_registry_); + need_reset = false; + } + } + + ecs::system_manager& system_manager; + + // States + bool started_playing{false}; + bool player_died{false}; + bool game_over{false}; + bool jump_key_pressed_last_tick{false}; + bool need_reset{false}; +}; + +//! Game world +struct flappy_bird_world : world::app { + //! Game entry point + flappy_bird_world() noexcept { + //! Load our graphical system + auto &graphic_system = system_manager_.create_system(); + + //! Load our resources system + entity_registry_.set(entity_registry_); + + //! Load our input system with the window from the graphical system + system_manager_.create_system(graphic_system.get_window()); + + //! Load the scenes manager + auto &scene_manager = system_manager_.create_system(); + + //! Change the current_scene to "game_scene" by pushing it. + scene_manager.change_scene(std::make_unique(entity_registry_, system_manager_), true); + } +}; + +int main() { + //! Declare our world + flappy_bird_world game; + + //! Run the game + return game.run(); +} \ No newline at end of file