From 52665f4b1a78152cd39ed0e40ad0636da9923da7 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Tue, 21 Jul 2020 13:57:41 -0700 Subject: [PATCH] re-record frame dependence section --- content/pong/move_paddle/frame_dependence.md | 35 +++++++++++++++---- static/images/better.gif | Bin 14937 -> 18005 bytes static/images/oh_dear.gif | Bin 10688 -> 7429 bytes 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/content/pong/move_paddle/frame_dependence.md b/content/pong/move_paddle/frame_dependence.md index 7102f8f..c960ccc 100644 --- a/content/pong/move_paddle/frame_dependence.md +++ b/content/pong/move_paddle/frame_dependence.md @@ -8,27 +8,33 @@ Let's do a little experiment. In the PongFEGame constructor, add the following l ```cs ... + + graphics.SynchronizeWithVerticalRetrace = false; + + ... - Window.AllowUserResizing = true; - IsMouseVisible = true; IsFixedTimeStep = false; ... ``` -This means that the game will now run with an *unlocked timestep*. In other words, the game will update as fast as the computer allows us to. By default, FNA tries to make the game update at a rate of 60 times per second. +This means that the game will now run with an *unlocked timestep*. In other words, the game will update as fast as the computer allows us to. By default, FNA tries to make the game update at a rate of 60 times per second, and synchronize with the monitor's refresh rate. Now what happens if we run the game? ![oh dear](/images/oh_dear.gif) -Oh dear. That doesn't seem right at all. +Oh dear. That doesn't seem right at all. The paddle is moving way too fast. But our speed value is only 10. What's going on? -The paddle is moving way too fast. But our speed value is only 10. What's going on? +Remember when I mentioned *frame-dependence* and *delta-time* earlier? This is a classic example of frame-dependence. What's our framerate right now? -Remember when I mentioned *frame-dependence* and *delta-time* earlier? This is a classic example of frame-dependence. Notice that the FPS, or frames-per-second, of the game is around 500 in the above recording. Our motion message when we press the "up" key on the keyboard tells the paddle to move 10 units. +```cs +System.Console.WriteLine(1 / gameTime.ElapsedGameTime.TotalSeconds); +``` -That means every frame we have the Down key held down, the paddle is moving 10 units. Which means, as things stand right now, the paddle is moving about 5000 units per second. And if the framerate changes for some reason, the paddle will move slower or quicker. This means the actual progress of the simulation will be completely different on slower or faster computers. +When I run the game, my console shows that the game is fluctuating at around 19000 frames per second. Our motion message when we press the down arrow key on the keyboard tells the paddle to move 10 units. + +That means every frame we have the Down key held down, the paddle is moving 10 units. Which means, as things stand right now, the paddle is moving about 190,000 units per second. And if the framerate changes for some reason, the paddle will move slower or quicker. This means the actual progress of the simulation will be completely different on slower or faster computers. Even if you use fixed timestep, what if you want to lock the timestep to 30 later? Or 120? The entire behavior of your game will change. @@ -52,3 +58,18 @@ Let's go back to the line of the InputEngine where we send the MotionMessage. Our simulation is now *frame-independent*, which is what we desire. The paddle is definitely moving too slowly now, but that's something we can fix with a bit of value tweaking. It is very important that you take care to multiply things that change over time by the delta-time value, or you risk elements of your game becoming frame-dependent. + +Before we move on, let's reset the values we changed in **PongFEGame**. + +```cs +```cs + ... + + graphics.SynchronizeWithVerticalRetrace = true; + + ... + + IsFixedTimeStep = true; + + ... +``` diff --git a/static/images/better.gif b/static/images/better.gif index daa3170da7b976bca80154bcac6bdf3ff0ffb93a..6926006dace06fcf1a9c83e59d540a33b8c7b6e6 100644 GIT binary patch literal 18005 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

tt|&IJk%za+4KOY#&m>2@&u@%K0IcWJt9* zq?Q?amlb;7KJ+0cl;nlh^Ftq#p-;u3jm)qnR#=ODSQ{s-gBRAx4|_$1b&12e?XBeG zMq^b)1t16JsRA|dEtnxU8mr2W#i|TBgRxjuc_bLlnt5ZZ_Gqj+@nV{n^E{`?E(?IB zm#UhrT8#UwRes~-F>~g<=nC%KoQ;ns8Wr4 zJlZt*+=H0vFz!^h!K+sdp2v(ESVY0(MFp>LW$qfzwTm`+j3nl<9 z>F-tpW{S+w91(0|Fy2KcIX_FuY5cduoVZAi2~# z0Ie#ij5yu^e_~~1t!m6@W#ppLJFMF8Url{5M;0Jw%L1hF7^D-Rhlgfm#<0DWCX9?P z`tu55o6mq)Ng?dCEBif6=dWE=sWsLIMzSDH!@nBR6{rJcpenhq%YeM3&~Ly_0Sr09 zLB)X0n4OkQ>ZlZJYc6`Nv`#HE8CiW)J;(X6R^x@T6GAOU5$SH=87B8Gmo_H;3E&HG z@?V0`QM16;1k!@(G5$CIS};A3YCKjjUBPqwa0;eLn^VRLre9Y?j}=T`KCOC>Ak?=!u~tAH zG8kA;bOxwQ40k=f=H_Rrs`8W-1F+|AQkeva?Iso(Zc~kLR|Ae#DFKQW$E{Tiz}jHu zBol=uO{be)^eep(LByVl==V(vHNaMI?Ej>N0{57F|Is-bm5D$W=4k$%wD1r?UzYSH z&JPWY_9mA7vEIaFAni>|(3$cdCR>_gy7s~QlL>$IrTBNULJe7fRF?%vwK2#K+@Fk> z1zC=h1xQs{fK(ZS{7bE+tHd)aOTF_-NuP8w&oO3|SK5f8IMI}yG9S!jxEuR97H=&a zc@#c#p`>U_hp*8kgF;FJ8D>+gfn#tf*!D`%#mLm)_p5UMEYofR`+vnB8+c0nv2mu} zFZ?lcy7z}U*ZPP2u@Y?|nHBIj)bYz%fd%j3kKyS+IxC>8^`ClSC0S5@MOlDU7=!%4 z{f4|O$dVxokaDsB3C1A*Qor%<1h6#t;G6fq`LkRlgKo-_JQk>YB57r+vNIbCz2#s< z06ZH%Q^;#U^PfvIz!EIgVPP0G^RE&t92$&6`GhpQ!ej%M|)Z7ANNYOP?UB{ zrvNzx$xM&qDlhpH)3yst*$nRq^6xX;^K1ChwSVowZ+4-6^TFRs{lU?<|G#4YpSY4W z8ds`F;!1CzMeap5I;L>dFA?>3Ee$lcSqO-Oe8r-KpmFk&e|gzoQ5a$Ldd7X0re|r; fyZX_Rc|tJnyI%~mdA(~G@o%+$f9;haSuOuB3C)hJ diff --git a/static/images/oh_dear.gif b/static/images/oh_dear.gif index f7bb0ace532353c7f84247ced21ea6b0699a080b..e4fc70461149218d820e98087646baffa2171f9b 100644 GIT binary patch literal 7429 zcmeHLX;c)~x;+X}90Fc70*!I3D5CKaViX!KkLSP6%Aq0aE0zya#p&$gn2m~WAjG!=r!3Y5(B#cln0#F1(5g0{K z6v0r0KoJr}C=>x00$~V@At;7m7(!qOi6In*00Mys1SSxaKrjL!2!tdMia-E~KqLZ_ z2udOti4Y`0k_bg2fI=V&fhh!~5R5_y3Lz*ahGQ5`U^t246ovx=hX@=daFoC?0w)NZByftr0f|E-4wE=a;uwh&BuMK8YXCzpfQ3b2%02lil6~WLnIB8G)mGKNfRVZk~BrqfTAIahAA4QXpEu>iY6(V zqUiPX682X|kL=%f=qtPJwnp>b2x`5~*myoz3%0!(gWt;pn9yLJ$!fSn{BwxO3Y!y6 zCFu>}%Qm_s!=)L&L|J@#zN@J;voUtv{>atN(yRyZ)<^IY52V@6Nw(j}lby?Q6e9cY zhPob<<+i5n4O#r53nBS66OOm}tDMMd&pnjslHyX1|CaAjcK(UHJinv(R72#4t`!BH zWj^irUz;lm)s?<|@)Xy~q9-+elS5CMD~q4r2{c-=hE-MatRZ5>){`w&rG1UqM%PqU zwY0yP|LKM9mg=&>R`LF*H6J4KO?J6QGEWxDKD+SvFx;H#R#P#euKMm}_sFI8;vefn zXv4>=?Z2G@#wbhe@ZJDlV>?d0Vy=2)1Gj@(_=2cHa6us8HZnxG=-Jbimi*>gR zGh=(`nT&A zqsO0xt-h*x7QQabJ~7B*phFyCog?Xu+*YB0IeEMSS2PAzwQ+-ZPEcwy3 z4Y3DSoqPThyy;wewC*>_^Y}wfTly1@%D>tWuYTXNKk>xX7yU`6=6|p;vD3kFK;V;; zHy}j!Td;Vo%)d0TL zNwNkXDym<0>Zpr3g;}qrw~o~tn^Q@*S-ls=?k?Rm zY|FWS)n+`|>^M69i-q@%lIX?W!{d$X!cVl{316^n;(>K;fz-+B8;?=BZR57dmZg^> zyGrjb^0rg#o*6D{_}E)J*>=EOVf)~RQFQ7dYnR)%ZEnnuUq3qfh1IxX#gF)v-%eZ` zDbGIC*D>C4Ch6OqVmQ9~bthUmGM)H!tNpb4O2@aAKkfW6^1I}p3+W$bo(3+Q`?~9e z;$!Wzh|S%71*EP}+lL)wuX(1n+^*~Adz(J_jqCk`xK9|qU9U;|OHoRHR&J4gC_X#p zBTYf$cEj*>0q;pOF<4|64eXEE_PBm)qhaix`4>qeWco#FqGi{gZ@pyQ9i^ro9e=uF z;yR~zcDifHFS=JLN4jRU&y)VVV*2iuf1A?}SFZijl%30~Iclmhc8_mWM=?D|nLQ6s zrW&m))E}&$uY7gA{x50s%$w@Fel9*RaY1anneSjcw?AlQi+I8Mna}5ixnHnanr?E$ zd*4#tSg7?5wb3Ule_kmYyTRIjYVH)=z=#|9@%trfv>cy?HTtnLA5rPc=x`t617So2 z%<63kmfYLK{N&7sEzcHyF>}v`Q+k?Jo3W~r{PV`%@bD8$GcAHX+P{J~9_@4Q15@>_ z&unwXV|*VSUDXFSG6&>QLzgl?oM~#@ttgERT>3maqseJ}(F7K8;?dd_51O1*i(+41 z%7Qjm=hz*dh~p1GWXvqUS=@qh_&96nQBjbyvvQHe zxyzHHo-5JYl5|mM*krN>joQ`zKzVhvUl{XU?(V_Pq|*;4Q?f&*ghRmH*1SZ=BAYl)wi$D+1!C zvaH>1+HIA$B*><+H+EXHyj|Lb4m+|wQ{=JNZ)i`^U&&e7Kj=&8+A|gqxlV34yic_& zoB3JprXTR5e~}$dzj_(>_-M=FGC2}x_m9B8zQ5I}(&n+WqW!GFc~Qwv?myNv0Q2)BaM=FQ}N=5#3*Q*dUpYp0wu zE#)f;&hBdNRC1@w#P1jS9CTGZ6iyQox5D$sn^lix)8!>Gg{ZfyT1Bg-E2{Y{dpO$By=Fz5BW+WXP4pyJ3!wqHZ7MN zbQ?M>(m#^0%kkrip<^}r-%5Dp1>SBiIcojmDrI@mHO0%527O1pX+=r6+wf^C1KGr` zkR~aH&pH}9+jtd3uG`3YFN2CyR#a3fMlJ>z)IFw^RgG?=mqmsy4ZBj-p%}edV|X&g ztE?S#d&N~7y0yy6x*5f*>juM9U{+PXkUbV`MfI4tSKT#Nj)gf=&z8kj-P_C_kMyE? zEn2JY?^2HQ0;s-qX4Opx*%NUh>bW)TUM)YaoJg#p`fX#YTfEtmLNzsD-&(D_rkqSQ zP=kBTWNqQ>sSK-G4eTy^n53M_ah!c|C|33;m;D;|njP|Jl|8OhzAg%weR;~PhHPX{ zOGUH8KJGQD4&`)3&FqM8Y)#i7dq$?79rbIi>7G%})EQ=91)A0NEOgi2wVE4?aIft( zZ`Iy+oEyhtYoBj+*U7!+Citzj1G`#v%7D2^vDt0SL3jN_(cF~8{r1rDR{i6exz{DJ zw}-vm4J!5AbXDu^(QB=SZo}M6y;n4&~sR2h?*A`nhmFqq``~#onO?-D$m=p3}D8nVV^)=L~Q9 z0E@u+_JPJ8feZWsP56O}s{)sjfu`EPWfnop?Soc&1g-K5vfu|Xs)AONL2I-@>nwsd z*at%%!JGVot@*(=Rl(cH;O*LATZ<4o`;Z+TAv^s-?D-+gs*v4e$R2ITUW?E#?L!ZE zggW_!!u(K|s!$dg%GQP+vbb^B{>D*{8^`=^c<^s*G!BhSzT#K_N9p51o}aZ;5=DIz6)ugeull0cBC5!&%3` zfoM7W#Uc<@$B+J1v!?~#)aDm6@?G?AO)(@HwXJ-e+JraI5Y^S%twHp~?8gyEA@|E`G0N!j}#S2Rsv;{1ae7f=hJ*t22SEOE_eC>#)PEqn@{p`QP#o z+~QQuAKl64>G+tXAkIOM;3-J-7w`oFVYMK+Q;@0? zh%JQ~4#F%?VUE90A`s%$!h%j=kxp1*DUv#f2v1Rkzo<$el2wapJ4JOmQN3mIU5Dg* zp2_$9lbZy|^6KQ4&Sa%7xy>@=p+m|e&y>ghDWo7pRh`n+nbNIG>9I`hr5#eAd!`Qf zr)mVLL)EFnovEX`)G^Dn35T>P&$Ma(G_4>_U!6vErp@Wn07E>VDK_Sa7jVTULh)jm zc&SQksuwR~q%UWtujHh!;-*^&(;2e#)vEM0`t)^-j19~Th?B92n_(@?u#shKQ)O(| zXV@|_?U#qPL>ll3l?U%$g)_fEVe%D5F`6A zGy5nf`xrOdLzvBxWuH)GpVVicV&t4==A7Z=oaN^D2y@QMa!^&yMSYGhBlj{h_X;QX zDmT|pn9G&rey_^CuFnl*NP?M?P>v*wD~S+FB4v_jS|#D>B^VX5bl2Jd1gzMzd!_>funh*S8OTSy8ERkFe^RbjWju!m99%Pe}% zDH`AwX@o^XvZ7&C(Wt&?j8QznES};NPjid4!eYIwm{Jwb>5G9?$$ZBWW3Q400VO7) zlEpP8OVuT&hLUAgrOO>lS9+DM3MjP@l`?8dSF20c7)sY!NjEr3Aus8s0I9V|YEvWK zrj~9uNNugk>>SH>c$Mws1eDo}%9u4}yVYfT3}t(*h%X(9173tv00D~#ml}elCfEkz zkX89%$MU0I<;McbJw)Z4n(`Cs@{@-0Q&ttH9V^awRh$i|@DWvYN`rk7CFyQ#_fynv; literal 10688 zcmeI2c~lhFw#E;GOrjzXYzZQoQU+xZ4YU}wor_6uC?%i)rdF|MjA%Q~T`t_SwJv zty*Qfk~x1X7*iuJo;n8r00964fC7L4Kmb4jK*|0JK>&sT3IPlP1O!M3P_lo8U;x7a zg#iWw0tO@uDB1lG3SbnVD8NuapnyaHC0i820E__?0~iJf43HS0WKV(!022Tu07d|U z03-n@+2bJ+z$8FPfRTV80Z9T%7867Pm;xvTFbWV9ASpnN28uucfdPU71Oo^G5E391 zKmde55CTI83LzMT5D-E_2n8VkMj#l0VFZN{3`PhTAz_4q5r85Piohs>q6mf}1d5O- zLZJx25C}tH3_&pj!w>>PNDQGc1P};BATWWT1cDI=K_Dc7Py_-<1R@cbL{JjJNQ58} zl0+yH0TcpJ2uvX;gXjshG5I00}H;1s|CghLPxLpTcI7=#lL zPC_^Z;Q+=V7>8jTg>ekV2^c3~oPu$H;t-0%D2}2yhT;T@lPFH1IKXfS!(j|ZF&x8i z0>eoRr!X84I7HwufujVD5ja8MB!N=|4oDm#ahSwW630lKAaRn!DG~=14pBHv;V6Y; z6i!e$N#PWQ13*K7h5?NN8Ur)|XcEvApaDcf5Dh~#3egxu6A(>8GzHNBrXiSyVH$;L z45kT~CSjU_X@JrYO2a6PqBMrm1WJ=AO`$ZvXb7WWj7BjU!)OAdNsOj28W1!@&@e%x z1dS0iLC_>YQv?l28X{?!q*0Q_NSYvNlB6k;1{4iZG)&PbMPn3AP&7%=6h%*?$F5$n ze%-Pq&MPdq^T>+ntG7gH)?Ew+o!+UBQLonan$)liVZ%XG>2Y!qF}tjl%388*efAnReiM=id&q9FTG zq1SWKFZP8wjm7M~SB({gxlgWf6vpa12=boZ4AGjkrBZO=c^USV{W*ur7hhEH=k9)7 zc{#teI(}KWzGD&bvesTJeoIx+rS`hK+wwopUr^BTNN}LtYWD4zg}%w_g9*c@@!7|P z^b9$7^CMnht?OHb5@(-YKULWA33qex!p`EG;q+9elB2bb*ODPHJ@6FlRx$3Fxre

ps(RcPy2cJ~xw>XL!RUG`qn?pV9eS}?Nh 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