I'm gonnatalkaboutthemodelviewcontrollerapproachtoorganizing a programandhowthedifferentcomponentsofthisexampleworktogetherinthemainJsfile.
Then I'm gonnatalkabouthowthisstructureincreases, maintainabilityandmodularity, asalways, feelfreetousethecommentssectionandbesuretocheckoutthelinkstothesourcecodeandworkingexampleinthevideodescriptionAndifyoulearnsomething, givethisvideoalike.
Sobasically, what I havehereisjustanexampleof a modelviewcontrollerarchitecturewhereyouseparateoutyourgamelogicfromyourdisplaylogic, andyoualsoseparateoutyourcontrollerlogic.
So I havemygamelogicstoredinthegameclassdisplaylogicinthedisplayclassinthecontrollerlogicinthecontrollerclass, andeachoneofthesehandlesitsownbusiness, andit's totallyseparatefromtheother.
So I'm notgonnarunintoanyissueswithhavingreferencestothegamelogicinsideofthedisplay.
Youdon't needtohaveyourownindividualfiles, butitmakesit a loteasiertojustusedthesedifferentthingsandotherapplications.
If I chooseto, forexample, theengine, I mightwanttousethisfixedtimestepengineinsideofanotherapplicationatsomepoint, soit's nicetojuststoreinitsownfile.
Sobasicallywhat I'm tryingtosayis, I wanttokeepthingsasorganizedaspossibleforthisrabbittrapgame, and I wantyouguystokindofthinkaboutorganizationofcodebeforeyoustartdeveloping a game.
If I hadwrittenobjectliberals, I couldput a referencetogamedotcolordirectlyinsideofthedisplays.
Rendercolorfunction.
Orbetteryet, I probablywouldn't haveevenhadherundercolorfunction.
I wouldjusthave a rendermethodthathandledrenderingtheentirething.
Thereason I havetohearisbecauserendercolordraws a colorto a buffercanvasandthendisplayedoutRenderrendersthatbuffercanvastothefinalanswerincampusthatyousee.
Sotheoldversionofhow I wrotemycodeorjustthesloppywaythat I writemycodewouldjustbetoputtoobjectliberalsonthemainJsfileandwhatwouldbedisplayedwon't begame, and I wouldhave a referencetogamedotcolorinsideofmyrender, functionanddisplaywouldjustdrawthatcolordirectlytothecampus.
Nowthereasonthisisbadisbecause, say, I wanttochangethenameofmycolorvariabletoHughif I goaheadand I have a referencetogamedotcolorinsideofmydisplayand I changedthevariablecolortoHughinsideofmygameobject.
Now, allof a sudden I'm editingmygameclassormygameobjecttochangethatvaluetoHugh, and I havetogointomydisplayobjectandchangeallthereferencestogamedotcolortogamedotHugh.
Nowthat's a pain.
I don't wannahavetodothat, andit's unnecessary, so I don't seewhy I doitanyway.
Withthismethod, the M V C approach, youdon't actuallyhavetohaveanyinternalreferencestoanyothercomponents.
I justaddmyeventlistenersforthescreenresizeandthekeyboardinputs.
And I justresizemyscreeninitially, Somycanvasfitsthescreen.
When I startupand I startmyengine, everythingrunstheway I expectedto.
SousingtheNBCapproachorjustseparatingoutthedifferentcomponentsyourgameuntillogicalgroupsis a reallygreatwaytokeepyourcodemaintainableandmodular, and I'm gonnagetintowhyinthenextpartofthisvideo.
Sonow I wanttotalkabouthowthisapproachmakesthingsmoremodularandmoreeasytomaintain.
Soobviouslyrightoffthebat, it's a lotmoreorganized.
Youcanseethatclearly I havemydifferentcomponentsreferencehereandinStanShadehereinonesinglelineeachratherthanhavingbig, sprawlingobjectliberalstofind.
Andbyseparatingthesethingsoutintotheirownclasses, I havetheoptionofputtingthemintotheirownfiles, whichmakesthingsevenmoreorganized, because I couldhaveallofthesedifferentclassesrightontopofeachotherinonebigfile.
Or I couldseparatethemlike I didintotheirownfiles.
Andnow, if I wanttoeditthegamelogic, I onlyhavetodealwith 42 linesofcode, apparently, insteadofhavingtosearchthroughonebigfile.
Thenthere's theotherthing I mentionedwhereyoudon't haveinternalreferencestoeonecomponentinsideofanothercomponent.
Andlike I said, thenit's a loteasiertojustworkwithpublicmethodsandhaveyourcomponentscommunicateviapublicmethods.
KindoflikeishappeningrighthereintherenderfunctionDisplayisinteractingwithgamethrough a publicmethodcalledrendercolor, ratherthanhavinganinternalreferencetogamedotcolor, whichwouldbe a lothardertomaintain.
Becauseif I changegamedotcolorinthegameobject, I'm gonnahavetogothroughdisplayandeditallofthosereferencestogamedarkcolor.
Sothisisanotherwayitlendsitselftomaintainability.
Now, whataboutmodularity?
Okay, well, I'vegot a engineclassdownhere, whichisbasically a fixedtimestepengine.
Now, I canusethisengineinanyapplicationthat I wantto.
Andit's veryeasyformetodothatbecausethisis a totallyselfcontainedclassthat I storeinitsownfile.
Now I don't havetostoreinitsownfile, butbystoringitinitsownfile, I canveryeasilyjustreferencethatsinglefileinanotherapplicationandthenallof a sudden, bam, I have a perfectlygoodgameenginefor a wholeanothergame, and I didn't evenhavetowritecodefor I alreadyhaditonhand.
Butif I weretohavethatgameengineintegratedintoallmyothercomponents, itwouldbe a lotharderformetoextractthetheenginecomponentsfrom, say, thegamelogic.
Andthatjustisn't verymodular.
Thewethaveitsetupnowisvery, verymodular.
Anditwillsaveme a lotoftimeinthefuturewhen I need a gameengineobject.
Sosometimes I writemycodethiswayformostofmytutorials.
I justthrowstufftogetherinonefilebecause I wanteverythingtobethereforyouguystoseeupfront.
I don't wannahavetobringthingsinfromotherapplications, butthisishow I wouldgoaboutwriting a morestructuredapplication.
Andthat's what I'm tryingtodo.
I'm tryingtowritethisgamerabbittrap, And I justwantedtobeverystructured, and I wanteverythinggosmoothly.
Sousingthe M V C approachandseparatingmygamelogicfrommydisplaylogicandmycontrollerlogicisjustgonnamakeeverythinggosupersmooththroughoutthiswholeprocess.
Soanyway, I hopethisisbeen a goodexplanationofhoweverythingisgonnabeforthisrabbittrapthing.
And I hopeyouguysareinterestedinwhat's gonnacomebecause I expectedtobe a reallycoolgamebefore I wrapthingsup, I wanttotalkaboutmyHTMLforthisexample.
So I actuallyamgoingtodo a wholebunchofpartsinthisseries.
Andratherthanhavingtouploadthespreadsheetforthisexample 1000 timesmygethomepageorhaveremainedparts I have I don't wanttouploadthismultipletimesmygethomepagebecause I don't wannawastememoryspace.
So I'm justgonnausethesamegraphics.
I'm gonnausethesamehtmlfiveandCSSfile, and I'm justgoingtowritenewJavaScriptfilesasneedbesothat's gonnakeepthememoryfootprintonmygethub.
Paige a littlebitsmallerforthiswhole, uh, Siri's that I'm doing.
I'm dynamicallydeterminingwhichjobscriptfilestoloadbasedon a U.
R l variablespecifyingthepartnumbers.
Sowhen I comeintomyactualhtmlpagehereand I lookatmyyour l totherabbittrapthateachteamwillfileattheendofit, thereis a questionmarkand a onewhichisthepartnumberforthisexample.
Now, if I wantedtogettheparttoo, I wouldjustcomeinandtypetwo.
I haven't actuallymadetypedParttwoyet, butthat's howyouwouldaccessParttwo.
So I'm accessingthesedifferentpartswith a girlvariable.
Thatisjustthepart.
And I have a defaulttoewhereifyoudon't specifyanything, itjustbringsyoupartone.
Sothat's what I'm doingandthisbigchunkofcodeintheminimal.
ThemiddleofmyHTMLfileistakingcareofthatforme.
Soitjustitdefinesallthesources I'm gonnause.
Andthat's justthesefiles.
Here.
Itgetsthegirlvariableorthatpartnumberfrommygirlthatnooneafterthequestionmarkandthenitgoesaheadcheckstoseeiftheviablepart, ifthereisnopartspecified, itjustsetsittopartone, andthenitjustloopsthroughanadds a scripttagforeverysinglejobscriptfileintheapplication.
So I'm alwaysgonnahavecontrollerdisplayenginegameMaineandmanifestosjustmyscriptforthevideo, and I'm justgonnaadd a newscriptforeachoneofthose, and I'm gonnaatit.
I'm gonnapartstogetherthe u R l orthesourceattributestomatchwhicheverparliament.
Sohopefullythatwas a goodexplanationofhow I'm actuallygettingthesethingsin.
Soinpartone, I hadtofindmythreedifferentclasses, mycontroller, mydisplayandmygame.
I alsohadmyengineclassandmymainJsfile.
Soalltheseareupdatedforparttwo.
That's whythefoulnamehas a 02 afterit.
Theonesfrompartonelikeengine.
I haven't changedsincePartonethathas a partone.
Sothat's mynamingconvention.
ThatamusingReally?
Theonlythingthat I changedmajorlybesidesthecodethatwentintomakingtheexampleworkwas I tooktheeventlistenersoutofthedisplayandthecontrollerclasses.
Sothekeydown, upactualeventhandlerfunction, I handintotheeventadamantlistenermethodinmymainJsfile.
I'm actuallydefiningthoseinsideofmymainfilenow, sothiswouldbeonethat I movedoutthatkey, downupeventlistenerandtheresizeeventlistener.
Actually, eventhandlers.
That's whattheseare.
Soif I comeallthewaydowntothebottomofmymainjazzfile, youcouldseethemaddingtheseeventlistenerstothewindowobject.
And I'm justhandinginthemethodsthat I defineinsideofmymainJsfileintotheseeventlisteners.
Sothat's oneofthechanges I made.
I decidedtomakethatchangebecause I didn't thinkthatmyeventhandlingsystemwasreallysomething I wantedtoputinsideofmyindividualclassesinmyindividualcomponents.
Andthereasonforthatis a lotoftimesinsideofthese, I'm gonnahavetodointeractionswithmultiplecomponentsinmygame.
So, forexample, theresizecomponentactuallyneedstoehandletwodifferentcomponentsandhavetheminteracted.
Soif I comeinhereand I justah, changethistosomethinglike 000000 That's gonnabethecolorblackIf I comeinthereandsaveitandthenrefreshmyscreenNow, I'm nolongergonnahavethattrailinggraphicbehindmyplayerwheneverhejumps.
Butif I comebackinhereandchangebackcontrol Z a bunchoftimesgetridofthatandthatandsaveandcomebackhere.
Now, allof a sudden I getmytrailinggraphicsbehindmyplayerwheneverhejumps.
Anditlookslikehehasjust a cooltrailoffadinggraphicsbehindhim.
Soif I have a bunchofclassesthat I'm throwingintoanexternalcontext, sayyourgameisgonnarunonanotherwebsiteandit's gonnabepartoftheglobalscopeofthatwebsite, youdon't wantyourclassesandstufftobejustfloatingaroundwithalltheothervariablenamesandclassnamesthatotherdevelopershavedefined.
If I pressrightonmykeyboard, I'm gonnaadd 0.5 pixelstohisexvelocityandthenfindthatupdatefunctionThat's justgonnaaddhis X and Y velocitytohis X and Y locationsinthecanvas, respectively.
So, Alex, let's take a lookinsideofthemainJsfileandseewherealloftheseairbeingemployed, whichisgonnabeinsideoftheupdatefunction.
Sothereason I havemyupdatefunctionsallovertheplace.
I haveoneformyplayer.
I haveoneformyworld.
I haveoneofmymainJavaScriptfileisbecause I'm doingdifferentthingsinsideofallofthem, and I wanttokeepallofmyobjectsasselfcontainedaspossible.
Allright, sonow I justtalkedaboutwhatactuallymakesthegamelogicwork.
Andthatis, ofcourse, thegameclassitself.
Storingthegameoh, tofile.
Sonow I havetotalkabouthow I'm gettingkeyboardinputandrelayingthattothegameclasssoitcanactuallytakethatinputanddosomethingwithit.
So I justshowedyouinsidethemainfileherethat I'm I'm conveyingthekeyboardsinputviathecontroller, objecttothegameobjectandtellingthegameobjecttodosomethingwiththeplayersposition, likemovelefttomoverightorjump.
If I comeallthewaytothebottom, youcansee, I'm addingthekeydownandkeyuplistenertothekeydownupfunction, which I'm definingalsoinsideofmymainfile.
Andthatisjustgoingtocallthecontrollerskeydown, upmethodandhandintheeventdottypeandtheevent, dockeycode, whichweusetodeterminewhatthetypeis, whetherit's a downpresseranduppressandthekeycodeisjustgonnaturnwhichkeyonthekeyboardimpressingSo 37 30 and 39 aretheleftupandrightarrowkeysonthekeyboard.
Sobasically, thiscontrollercostjustgetskeyboardinputandthenwerelaythatinputtothegamecomponentrighthereinthemainJsfileinsideofitsupdatefunction, whichiscalledoneveryframeofanimationmanagedbyourengine, which I'm gonnatalkaboutlateroninthisvideo, soreallysimplyjustcheckstoseeiftheleftrightandupkeysareactiveandthenitgoesaheadanditcaused a playermovementfunction.
Andyou'regonnagetfunctionalitythatlookslikethisinstead, you'rejustgonnabeabletojumponetimeandonLeejumpwhenyoupressthekeyratherthanjumpingjustcontinuouslyifyouhave a keyhelddown, Allright, sonowthatyouknowhowtodefinetheplayer, objectintheworld, objectinourgameclassandyouknowhowtogetuserinputtoactuallycontrolthisguyandmovingaroundscreen, theonlythingleftishowtodrawthisguy.
Sohowweredrawingtheplayerobjectandtheworlditself?
Tothiscampuselementiswiththedisplayclasssoinsideofdisplayclass I justtofind a bufferin a contextofmycanvasoftheseairtoahto d renderingcontextscanvasrenderingcontexts.
So I'm settingthatuprighthereintheinitializationportionofmymainJsfile.
Let's getbackinthedisplayandtalk a littlebitmoreaboutit.
So I'veadded a coupleofdifferentfunctions.
I havethefillfunctionormethod.
Allitdoesistake a coloranddrawittothebuffer, whichrememberstheoffscreencampus, whichisthendrawnbytherenderfunctiontoouronscreencampusthatdrawsthisoffscreenbuffercanvastotheonscreendisplaycampusthatyouactuallyseeinthebrowserwindow.
Sothefilmmethodjustfillsthebufferwithcolor.
Renderrendersthatbuffertothescreendraw a rectangle, justdrawsthisrectanglehere.
That's what I'm handinginintermsof X Y.
Withinheightandcolor.
Itjustdrawsthattothebuffers.
Well, I'm actuallyroundingdownthe X and Y positionsoftherectanglethat I'm handinginthiswayitdoesn't renderiton 1/2 pixel, soLet's seewhathappenswhen I takethiscoatoutfirst.
Let's take a lookatwhatthisguyactuallylookslikemovingaroundthescreen.
Soprettysmooth.
Nothingweirdgoingon.
Alltheedgeslookprettystraight.
If I comeinhereand I justputin X andwhy, though, let's take a lookandseeifanythingchanges.
Asyoucansee, itlooks a littlebitfunky.
I mean, it's it's hardtotellbecause I havethisbackground.
Youseehowhisedgesey'rekindofmessedupthere, kindofwavering, a littlebit, kindoflookslikehe's justfadingaroundinsteadofjustsittingontheexactpixelhe's meanttositon.
Well, thatisactuallybecausehe's sittingonhalfpixelsfromtimetotime, andyoucanfixthatbyroundingdownthevaluesyoupassintoyourdrawmethodsowecangofromthiswhichlooks a littlebitfunkytothis, whichnowlooksreallysharpandnotsofunky.
Itallitsbasis, basicallythebestwecangeton a HTMLfivecampus.
Sonowletmesetbackmybackgroundcolortothewayitwasbeforesowecouldhave a nicefadingeffectthatfollowsthecharacteraround.
Refreshmyscreen.
Andsothat's what I'm gonnausetodrawmyrectangletothescreenandroundhimtothenearestfullpicks a locationwithmaththoughtfloorsohedoesn't getthatweirdbluraroundtheedges.
Nowlet's take a lookatthemainJsfile, andthat's whereallofthesethey'regonnabecalled.
Actually, I thinkinsideofactually, no, I'm wrong.
Let's justtake a lookatthemainJsfileandseewheretheseguysarecalled.
I thinkit's gonnabeinsideoftherenderfunction.
I don't lookatthiscodein a littlebit, sowehavedisplayedoutPhil.
Sowecalleddisplayedout, Phil, that's gonnafillourbackgroundcolorwiththisnice, darkgrayherewe'regonnacalldraw a rectangleandhandinthegamedotworlddotplayer, whichis a rectanglewe'regonnahandinallthosevaluesaswellasthecolorvalue.
It's goingtosubtract 32 pixelsfrombothofthosetogiveusthisnice 16 pixelmarginoneithersideofourdisplaycampus, which I havethreefreshsoitgoesbacktothewayit's supposedtobe.
Sothat's whatthat's doing.
Those 32 pixelsthenisgonnahandinanaspectratioofourGameworld, whichisgonnabejusttheheightdividedbythewidthofourgameworld.
Sonowlet's take a lookinsideofthedisplayobjectsresizemethodandseewhatit's actuallydoing.
Otherwise, wedon't have a Maxwithscenario, have a maxheightscenario, andit's gonnasetthecamp's heighttothemaxheight, andit's goingtosetthewithtotheheightdividedbytheheightwidthratio.
Sothiscodeisbasicallygonnaallowmetodothisif I comeinhereand I changedthescaleofmywindow.
Asyoucansee, it's alwaysgonnakeepitcentered.
Rightnow, I have a maxheightsituation, and I have a shorterwithinmygameworld.
Buttheaspectratioremainsthesame.
Andhere I'm gonnagobackdownsomewherearoundhere.
I'm gonnachangeoverfrom a maxheightsituationto a Maxwithsituation.