Sunteți pe pagina 1din 22

ProgrammingGraphicsI:IntroductiontoGenerativeArt

JoshuaDavis

ASSIGNMENT

Yourassignmentistoprogramgraphicsandcreateagenerativepattern.Youwillbeabletoapplythis
patternanywherebutIamgoingtoteachyoutoprepareitforprint.Byunderstandingtheprogramming
behindsomeofthemostinterestinggenerativeart,youwillbeabletogrowyourconceptandcraftskillsto
createabeautifulworkofart.

DELIVERABLE

Uploadanimageofyourfinalgenerativeartpiece.Acompletedprojectincludesprocessimagesofhowyou
arrivedatyourfinalpiece.

PROJECTSTEPS

EnvironmentSetup

1. DownloadProcessing
DownloadProcessingfromhttp://processing.org
2. DownloadSublimeText2
DownloadSublimeText2fromhttp://www.sublimetext.com/2
3. AddSublimeText2PackageControl
FindinformationaboutSublimeText2PackageControlherehttps://sublime.wbond.net
InSublimeText2opentheconsoleView/ShowConsoleandintheinputfieldatthebottom
paste:
importurllib2,ospf='PackageControl.sublimepackage'ipp=sublime.installed_packages_path()
os.makedirs(ipp)ifnotos.path.exists(ipp)elseNoneurllib2.install_opener(urllib2.build_opener(
urllib2.ProxyHandler()))open(os.path.join(ipp,pf),'wb').write(urllib2.urlopen(
'http://sublime.wbond.net/'+pf.replace('','%20')).read())print('PleaserestartSublimeTexttofinish
installation')
HitreturnandRESTARTSublimeText2forchangestotakeeffect.
4. InstallProcessingPackage
WithinSublimeText2navigateto:
SublimeText2/Preferences/PackageControl
Fromnewlyopenedsubmenuclick:
PackageControl:InstallPackage
Fromnewlyopenedsubmenu/inputfieldtype"processing"andclicktoinstalltoinstallthe
ProcessingbundleintoSublimeText2(7:30minonthe"WorkingwithSublimeText2"video)
Processingshouldnowbeanavailablelanguagewhenyouclickbottomright"PlainText"areaof
SublimeText2.
5. Install"processingjava"
Wenowneedtoaddprocessingjavatoourcomputer.
Todothislaunchprocessingtheapplicationandnavigate/click:
Tools/Install"processingjava"
ThiswillinstallprocessingjavaonyourmachinesothatcodewritteninSublimeText2actually
runs.
(10:50minonthe"WorkingwithSublimeText2"video)
6. Change"Build"inSublimeText2
Tochange"Build"inSublimeText2sothatitmimics"Build"inProcessingnavigateinSublimeText
2to:
SublimeText2/Preferences/KeyBindingDefault
and
SublimeText2/Preferences/KeyBindingUser
inDefaultpressfind(command+f)andtype"build"aroundline232copy:
{"keys":["super+b"],"command":"build"}
andpasteintoUserandmakechangefrom"super+b"to"super+r"
[
{"keys":["super+r"],"command":"build"}
]
HitsaveandnowTools/Buildshouldnowbetiedto"command+r"onthekeyboard
7. OSXusersinstall"SizeUp"
Needhelporganizingwindows?UseSizeUptohelppositionwindowsincertainquadrantsofthe
screen.Windowsusersalreadyhavethisfunctionality.
http://www.irradiatedsoftware.com/sizeup
8. OSXusersinstall"Caffeine"
Lookingtomakepausesorwalkawayabitwithoutyourcomputergoingtosleep?OSXuserscan
install"Caffeine"fromtheAppStore.
https://itunes.apple.com/us/app/caffeine/id411246225?mt=12
9. WorkingwithSublimeText2Snippets
Downloadtheattachedsnippet.zipfromthe"FinalEnvironmentSetupTips"video.
OpenyourLibraryfolder:
Finder/Go/GotoFolderandtype~/Libraryandclick"Go"
Fromthishiddenfoldernavigateto:
Library/ApplicationSupport/SublimeText2/Packages/Processing/Snippets
Copy"hype_setup.sublimesnippet"tothisSnippetsfolder
Closefinder.NowwithinSublimeText2,selectProcessingfrombottomrightlanguageselectorand
starttyping"hype"and"hype_setup"shouldbeavailable.
(10:00minonthe"FinalEnvironmentSetupTips"video)

IntrotoProcessingandHYPE

1. DownloadHYPE
AllofthesourcecodeforHYPElivesonGithub.Themostcurrentbuildcanbefoundinsideofthe
stagingbranch:
https://github.com/hype/HYPE_Processing/tree/staging
Intherighthandsubmenuclick"DownloadZIP"
Thiszipfilecontainsallofthenecessarycodethatwewillneedinordertocreateourprojects.
2. CheckoutZIPfilecontents
Examplesarepostedonthehttp://hypeframework.orgwebsite,thecontentsofthewebsitearealso
mirroredinthe"website"folderintheZIP.
HYPEisalibraryofcodethatperformcertaintasksanisolatedviewofeachoftheclassesand
whattheydo,canbefoundinthe"pde"folder.Alloftheseindividualfileshavebeencombinedand
concatenatedinto1singleMASTERfile,HYPE.pde.
AswewritenewclassesItrytomakeasmanyexamplesaspossibleillustratingthefunctionalityof
thatclass.Bydiggingaroundthe"examples"folderyoucanfindsomepremadeblocksofcodeI
havewrittenshowcasingsomepossibleuses.Ifafolderhasseveralexamplesusuallythefirstfew
examples...example_001,example_002,etc...areasbasicaspossible.Howeverastheexamples
progressanexamplemightbecomemoredifficultasIshowcasemixingthatclasswithother
classestocreateevenmorerobustinteraction,animationsand/oreffects.
Whenfirstdivingintoexamplesbesuretostartwith:examples/H_BASICSasittriestointroduce
coreconceptsusingHYPE.
3. LocateHYPE.pde
InsideofthezipfileyouwillfindHYPE.pde,thiscontainstheentireHYPEuniverse!Thisfilewillbe
copyandpastedintoeveryprojectwecreate.
projectName(folder)
build(folder)
build.pde
HYPE.pde
Everyprojectwillhavethisbasestructure.
4. .JARversus.PDE
Processingandit'scommunityofdevelopershavecreatedseveralexternallibrariesthatperforma
wholemultitudeoftasksfromaudiosynthesistousingtheKinect.Mostoftheselibrariesare
packagedinto1single.JARfile.
WiththeintroductionofProcessing2andProcessingJS,wecanactuallypublishsketchesto
HTML5usingthecanvasobject.HoweveryoucannotpublishtoProcessingJSusingexternal
librariesusing.JARfiles.
SinceIliketheideaofsomeofourprojectsbeingdisplayedandinteractedwithviathewebanda
webbrowser.HYPEwasdevelopedusingthe.PDEformat.
5. HYPEAS3
ThefirstversionofHYPEwascreatedforAdobeFlashanditsscriptinglanguageActionScriptwith
mygoodfriendBrandenHall.WhenIdecidedtomovetoProcessingIwantedtotakesomeofthe
corefunctionalityoftheAS3versionandfixsomeoftheissuesandfeedbackthatexistedwiththe
AS3versionofHYPE.
forexample,letssaywewantedtocreateacompositionof25assetsina5x5grid.Intheold
versionofHYPEImighthavewrittensomethinglikethis:
varnumAssets:int=25
varlayout:GridLayout=newGridLayout(50,50,100,100,5)
avariableforhowmanyassetsIwanttopainttoscreenandalsousetheGridLayoutclasstogive
thecodesomeinformationabouthowtodrawthatgrid.
butwhatis50,50,100,100,5?There'snoinformationaboutwhatthesenumbersdo.soIhadto
writethecodelikethiswithacomment:
varnumAssets:int=25
//xStart,yStart,xSpacing,ySpacing,columns
varlayout:GridLayout=newGridLayout(50,50,100,100,5)
Nowyouhavesomeinformationwhatthosenumbersarestartthegrid50onthexaxis,50onthe
yaxis,what'sthespacingbetweentheassets,andhowmanycolumnsshouldtherebe.Somajor
feedbackwashowrigidandobscuretheargumentswereinthecode.IfIwasgoingtostartover
withanewlanguageandanewlibrary,IwantedtomakechangestotheHYPEprocessingversion
sothatitcouldbeasclearandasflexibleasitcouldbe.
6. HYPEprocessing
Asstatedbefore
IfIwasgoingtostartoverwithanewlanguageandanewlibrary,Iwantedtomakechangestothe
HYPEprocessingversionsothatitcouldbeasclearandasflexibleasitcouldbe.
Sowelookedat2conceptsthatwethinkwouldmakethisnewrewriteasbestasitcouldbe
usingaFluentinterfaceandMethodChaining.
http://en.wikipedia.org/wiki/Fluent_interface
http://en.wikipedia.org/wiki/Method_chaining
soletslookatwritingthesamecodelikewedidinthepreviousHYPEAS3version:
intnumAssets=25
HGridLayoutlayout=newHGridLayout()
layout.startX(50)
layout.startY(50)
layout.spacing(100,100)
layout.cols(5)
sohereyoucanseeinthisexamplewehavenoneedforacomment.Whenwecreateour
HGridLayoutwhichweassigntolayoutthenextfewlineshandlethejoboftalkingtolayoutand
passingitsomeinformationlikestartX,startYspacingandcolumns.Wecanrearrangetheorder
organizeithoweveryou'dlike.Butjosh,you'resaying,thisseemslikealotmorecodefromthe
previousexample?WellletslookatMethodchainingyoucanactuallywritethisexactcodealsolike
this:
HGridLayoutlayout=newHGridLayout().startX(21).startY(21).spacing(26,26).cols(24)
Prettyawesome!youcancreateHGridLayoutandthenstart"chaining"theinformation,oneright
aftertheother.Orsometimes,tomakeitmorereadable,Icanaddhardreturnsandtabslikethis:
HGridLayoutlayout=newHGridLayout()
.startX(50)
.startY(50)
.spacing(100,100)
.cols(5)

theseconceptsIthinkmakeitmucheasiertowritecodebutarealsomajordeparturesfromhow
peoplehavetypicallywrittencodeinProcessingandJava.Sorememberthatifyou'renewto
programmingthiswayofwritingcodeisONLYspecifictoHYPEanddoesnotworkwithprocessing
codewritingtutorialsandtextbooks.

DrawingVisualAssets

1. Findathemetomakeartassets
TurkishWarriors,JapaneseKimonos,KittensandChainsaws?
Watchthe"DrawingVisualAssets"videointhisvideoIhavepickedformsfromthebook
"MongolianNationalOrnaments".Thinkaboutwhatkindofformsyouwanttouseasassetsthatwill
populatethecodethatwewriteinthenextsection.
LookatsometheformsIhavecollectedandwheretheycomefrom.Theycancomefrominternet
searches,books(olderthebetter),freedrawing(sketchbooks),architecture,fleamarkets,etc.
There'sawholeworldofformandtexturethat'sgoingtogetafreshnewlookbyabstractingitinto
code.
2. Breakapart,embraceabstraction
Watchthe"DrawingAbstraction"video.Rememberthatasinglemasterdrawingcanbebroken
apartintoseveralparts.Thoseabstractedpartscandosomeunexpectedthings,becausethey
mightbetakenfromsomethingfamiliar,theymightbringsomevisualcomforttotheviewer.Yetthe
viewermaynotbeabletopinpointwhy.
Takingabstractedassets,placedintocodeandgeneratedonscreenwillcreatenewformand
texture.
Forexample:


http://pinterest.com/pin/180495897536927022/
ThisisaMayanformIdrew.WhenabstractedandplacedintocodeitstillfeelsMayan,but
becomessomethingnew.Areinterpretationofsomethingfamiliarinaesthetic.


http://pinterest.com/pin/180495897536927018/
http://pinterest.com/pin/180495897536927010/
3. Drawavisualasset
Watchthe"DrawingTimelapse"video.YesIlovetodrawinFlash!it'stheclosestI'llcometothe
oldMacromediaFreehandstyleofdrawing.
Drawacircle
Usecircleto"createasymbol"
Makefourlayers
Placeyourcircleonallfourlayers
Rotateeachlayerby90degrees(rotation0,90,180,270)
YouONLYneedtodrawoneside(Idrawtherighthalf)
Copythehalf,pasteandflip
Nowoneprongofthedrawingiscomplete,butbecauseweduplicatedandrotated,allprongsare
done!
Breakapart(command+b)sothatthedrawingisnot4duplicatedsymbolsbutisonevectordrawing
onstage(nosymbols,justvectors).
Usepaintbuckettofillareaswithgrays
4. Prepareyourfinalasset
Watchthe"FinalAssetPrep"video.HowwesaveourvectorbaseddrawingintoSVGissuper
important.Let'stakeamomenttolookatmysteps
SelectartworkinFlash
ClickFile/Export/ExportSelection
Saveas.FXG
Open.FXGinIllustrator
InIllustratorselectacompoundpath
ClickObject/CompoundPath/Release
Thiswillbreakthevectorsintoseparate"Paths"asopposedtobeinggroupedintoonelargerobject.
Thismeanstherandomcoloringinoursketchwillhavethepossibilityofrandomcolorsasopposed
tooneuniversalcolor.
Selectand"GROUP"artworkinillustratorthatIwanttogetthesamecolor.Forexamplegrouping
twoeyesinafacesothatbotheyesreceivethesamerandomcolor.

PaintingtotheScreen

1. Writeyourbasiccode
Letsstartwiththevideo"Basics/LineandRect".Thisistheverybasicamountofcodeyou'llwrite
inprocessing.ThisalsodemonstratessomeofthebasicsnippetfunctionalityofSublimeText2.The
codewritteninthisvideosectionisintheattached"basics.zip"file.
2. Experimentwithmovingandrotation
Movingontothevideo"Basics/Rotation".Ifyou'renewtoprocessingthishelpsgetabasic
understandingofhowthingsgetpaintedtoscreen.Forexample,wedon'tactuallyrotatetherectwe
rotatetheentirecanvasofthesketch.
Agoodanalogyisdrawingonasheetofpaperwhenyou'redrawingyoumight,movetheposition
ofthepaperupanddown.Youmightalsorotatethepaperwhiledrawingboxes.Sotheboxes
themselvesweren'trotatedthepaperwasrotated.
Thecodewritteninthisvideosectionisinthe"basics.zip"filefromthepreviousvideotutorial.Use
theseexamplestohelpvisualizehowstagerotationisworking.
3. UsingtheMatrixStack
Inthenextvideo"Basics/Matrix/pushandpop"IillustratehowusingtheMatrixStackcanbeused
topositionthingsonscreen.Thecodewritteninthisvideosectionisintheattached"matrix.zip"file.
http://processing.org/reference/pushMatrix_.html
pushMatrix()
Dosomepositioningstuffs
popMatrix()
Reseteverythingback
WithinpushMatrixandpopMatrixwecanusetranslate(x,y,z)tomovethex,y,andzcoordinatesof
thestageandwecanuserotate()torotatethestage.Whenallissaidanddoneafterthe
popMatrixtranslategetsresetbackto0,0,0forx,y,zandrotatebackto0.Rememberourdrawing
onapieceofpaperanalogy:wedon'tdrawtherectata45degreeangle.Weturnthepaper45
degreesandsimplydrawaperfectsquare.popMatrixthenrotatesthesheetofpaperbackto0.If
you'renowviewingthesheetofpapertherect"appears"rotated45degrees.
4. Usecodeforrotationandcolor
In"rotation.zip"Isimplywanttoaddsomeanimationtomysketchbyhavingthesquaresrotate.
Thisfilehelpsusunderstandthe"setup"and"draw"functionsandsomeofthethingswehavetodo
whenpaintinganimationthescreen.Noticeifwedon'taddbackground()tothedrawfunction,the
screendoesn'tclearandwearerepeatedlypaintingtherecttothescreen(leavestrails).
In"color.zip"Iaddcodeforrandomcolortothefillofmyrect.Butsincethiscodeisinthedraw
functionandthedrawfunctionbeingaloop,itthinkseveryframeoftheanimationIwantanew
randomcolor.InordertogetonlyonecolorIwouldhavetoprepickarandomcolorinsetupand
storeitsomewheresothatwhenitpaintstherectinthedrawfunctionitappliestheprepickedcolor.
AlloftheseannoyanceswouldleadmetobuildthingsacertainwayintheprocessingportofHYPE.
Inthenextprojectsteps/videos,westartexploringusingHYPEandhowwecancircumventsomeof
theseproblems.
5. StartprocessingwithHYPE
We'renowmovingontothe"HYPE/Basics"videotutorialandtheassociated"HYPE_basics.zip"
file.Nowwe'llstartusingHYPE.pdeinoursketchesandshowhowHYPEcircumventsthose
previousroadblocks.
Aswewritesomecodelet'sthinkaboutsomeimportantthingstoremember:
1.insetup()weneedtotellprocessingthatwe'reusinganexternallibrarybyadding:
H.init(this)
andwecanchainsomeargumentslikeabackgroundcolor.Areweusing3D?shouldweclearor
repeatpaintthebackground?etc.
H.init(this).background(#202020).use3D(false).autoClear(true)
2.createsomeHYPEspecificdrawableslikeusingHRectinsteadofprocessing'srect():
HRectd
d=newHRect()
d.size(50).rotation(45).anchorAt(H.CENTER).loc(100,height/2)
wecanthenchainsomeargumentsfortherectlikestrokeWeight(),stroke(color),fill(color),
noStroke(),noFill(),anchor(x,y),anchorAt(HConstants),scale(),size(width,height),width(),height(),
loc(x,y,z),alpha(),rotation(),visibility(true/false),etccheck/pde/HDrawable.pdeforalistofallthe
thingsyoucando.
andthenfinallyafterwehavesetallofthepropertieswewantthisHRecttohaveweneedto:
H.add(d)
thinkofitlikethis.add()storesallofthepropertiesforyourHRect.sothatweaskhypetopaint
whatitstoredtoscreen:
3.H.drawStage()
itwillpaintthatvisualassetwithallofthepropertiesthatyouset.EvenifH.drawStage()livesinthe
loopdraw()function.Ifwepickedarandomcolor,thatrandomcolorisstoredandiscarriedoverto
thedraw()function.Ifyou'renewtoprogrammingthissavesahugeheadacheofhavingto
understandtheideaofprepickingcolorsandstoringtheminsetup()manually.SimplyHYPE
handlesallofthisstuffforyou.
CanIgetanAmen?

step2introducesHRotateandmakesrotatingvisualassetspainless.
step4savestherandomlychosencolorautomagicallywhenH.drawStage()iscalledinthedraw()
function.
6. PaintdrawableswithHYPE
Inthenextvideo"HYPE/Drawables"andassociatedcodeexamplesin"HYPE_objects.zip"werun
throughthemanydifferenttypesofthingsyoucanpaintwithonscreen.ThingslikeHRect,HEllipse,
HPath,HBox,HSphere,HImage,andHShape.
Allofthecodeexampleusethesamebasicstructure:
1.H.init()
2.forloop/runsomethingasetnumberoftimes/howmanythingsdowewanttopaintonscreen?
3.drawwithsomethingandsetsomeproperties
4.H.drawStage()
Whileit'sgreatthatIshowcasealotofthedrawablesinHYPEit'sbesttoreallydigestHShape.
HShapeiswhatwillusetopaintSVGartinourproject.Soletstakesometimetofocusonsomeof
thepropertiesassociatedwithHShape.
Firstletsnoticewehaveafoldercalled"data"andthisiswherewewillplaceanyandallofour
SVGartwork.
thenwillpoint/loadinourSVGartworkbywritingthefollowing:
d=newHShape("filename.svg")
nextletslookatthepropertyof.enableStyle()bydefault.enableStyle(true),thismeanswhatever
stylingIdidinIllustratorthiswillgetcarriedoverintoourprocessingsketchsoanystrokeandfill
colors,etc.IfIset.enableStyle(false)thismeansdisableanystylingdoneinillustratorbecause
we'regoingtooverridethestylingfromwithinprocessing.
Someofthethingswecanoverrideare:
.strokeWeight(1)
.strokeJoin(ROUND)/ROUNDorMITER(square)
.strokeCap(ROUND)/ROUNDorMITER(square)
.stroke()/color
.noStroke/don'tdisplayastroke
.fill/color
.noFill/don'tdisplayafill
.size()/setwidthandheight
.width()/setonlywidth
.height()/setonlyheight
.scale()/scaleartworkbasedonartwork'soriginalsize
.rotate()/setrotation0to360
.loc(x,y,z)/setpositionofartworkonscreen/zonlyworkswhenusingP3D
.anchor(x,y)/settheartwork'sregistrationpoint/thispointisusedin.loc()and.rotate()
.anchorAt(HConstants)/useapresetregistrationposition
H.LEFT
H.RIGHT
H.CENTER_X
H.TOP
H.BOTTOM
H.CENTER_Y
H.CENTER
H.TOP_LEFT
H.TOP_RIGHT
H.BOTTOM_LEFT
H.BOTTOM_RIGHT
H.CENTER_LEFT
H.CENTER_RIGHT
H.CENTER_TOP
H.CENTER_BOTTOM
forexampleifyouwantedtheregistrationanchoredinthe"bottom/right"oftheartwork
.anchorAt(H.BOTTOM_RIGHT)
AgainthisideaofregistrationanchoringissomethingborrowedfromworkinginFlashand
positioning/animatingartworkaroundthispointusingeither.anchor()or.anchorAt()Ihopeisuseful
toeverybody.

WorkingwithColor

1. Commitcolortheft
Inthevideo"TheColorThief's"I'msharingsomeofmythoughtsonwheretohuntforcolor
inspiration.Agreatstartingpointistominethecoloroutofimages.Wesimplysearchfor.JPG's
whichcandisplaymillionsofcolorsandsavethemto.GIF'swhichhaveacolortableassociated
withthem.Thestepsareasfollows:
1.Searchforanimagethathasgoodcolors.
2.OpentheimageinPhotoshop
3.Selectfile/saveforweb
4.Intoprightselectthepreset"GIF32NoDither"
5.UseeyedroppertoolandtrashcaninColorTabletoremoveunwantedcolors
6.SaveGIF
7.DownloadColorPickingToolandopenGIF
8.Youcansortcolorchips,hold"control"andclickchipstodelete
9.Whenfinishedclick"ViewColorList"
10.Thenclick"ViewForProcessing"
11.Click"CopyDataToClipBoard"
12.Pastecolors,HEXdata,inourprocessingsketches
Starttousethetrickandthistooltostartbuildingsomegreatcolorcombinations!
Don'tforgettogive/https://twitter.com/michaelSvendsenahugeInternetHighFiveforpackaging
uptheColorPickingToolasadownloadableAirApp.
2. UseKulertocreatecolors
Inthevideo"ExpandingKuler"wedon'thavetoworkwithphotographs,wecanuseaKuler
Screenshotandworkwithgradientstobuildimagesthatwecan"SaveforWeb".
UseKuler'sbase5colorsandexpandthemintoamuchlargerrangeofcolors.
Savethemasa"master.gif"andloadthemintothecolorpickingtool.
3. Createacolorpool
Inthevideo"HColorPool"westartusingthefirstofthreecolorcapableclasseswithintheHYPE
framework.Thiscodebestsuitsthe"ColorTheft"fromimagesvideoaswewillstarttobuild
collectionsofcolors.Thecodewritteninthevideosectionisinthe"HColorPool.zip"downloadable
zipfile.
TheHColorPoolclassisbestdefinedin3easysteps:
Createaninstanceof"HColorPool"andgiveitthenameof"colors"
1.HColorPoolcolors
Defineaselectionofcolors
2.colors=newHColorPool(#FFFFFF,#F7F7F7,#ECECEC,#333333,#0095a8,#00616f,
#FF3300,#FF6600)
Maprandomlypickedcolorstoourobjectsbeingpaintedonscreen.
3..fill(colors.getColor())
Withthesethreeeasysteps,whenthe"for"loopruns100times,thefillisgettingassigneda
randomcolor.Noticethatwehaveeightcolors.Thismeanseverycolorhasa1/8chanceofgetting
randomlypicked.Usingthisprocessmeansthedistributionofcolor,whilerandom,shouldappear
evenlydistributedacrossthe100objects.
Letsmoveonto"step2"withintheHColorPoolfolderandrethinkitemtwoinourthreeeasysteps.
Ifthecodewaswrittenlikethis:
colors=newHColorPool()
.add(#FFFFFF,10)
.add(#ECECEC)
.add(#CCCCCC)
.add(#333333)
.add(#0095a8)
.add(#00616f)
.add(#FF3300)
.add(#FF6600)

What'sactuallyhappeningiswe'rebuildingalistof17colors.Thefirsttencolorsinthislistof17
colorsisactuallythesamecolorofWHITE#FFFFFF.Sowhenthecoderuns,andpicksarandom
numberfrom0to16,iftherandomnumberthatselectedis0,1,2,3,4,5,6,7,8or9,theartworkis
goingtogetfilledwithwhite.
Thisis"ColorWeighting".
Averysimplewayforustodefinewhichcolorshaveahigherprobabilityofgettingpickedoverother
colors.Inour"Step2"examplethecodeshouldlooklikethis:
colors=newHColorPool()
.add(#FFFFFF,9)
.add(#ECECEC,9)
.add(#CCCCCC,9)
.add(#333333,3)
.add(#0095a8,2)
.add(#00616f,2)
.add(#FF3300)
.add(#FF6600)


Adominanceofthelightcolors,#FFFFFF,#ECECEC,and#CCCCCC,asmallamountofdarkgray
#333333,andsubtletaperingoftealblues#0095a8and00616f,andthenourorangesbeingthe
rarestcolorstohitthescreen,#FF3300and#FF6600.Mostofmyfilesarestructuredthisway,asI
tendtowanttouserandomnessbutcontroltheprobability.
4. ApplycolorwithHPixelColorist
Inthevideo"HPixelColorist"westartusingthesecondofthreecolorcapableclasseswithinthe
HYPEframework.Thecodewritteninthevideosectionisinthe"HPixelColorist.zip"downloadable
zipfile.
IhavetothankErikNatzke/http://www.natzke.com/forshowingmethistricksomanyyearsago
sittingonabeachinSaTuna,SpaininthebeautifulCostaBravaregion.
Simplyput:ratherthanstealingcolorOUTofphotograph,whynotusethephotographitselfasa
mapofthemovementofcoloracrossaspecificwidthandheight?Sinceanimageismadeupof
pixels,ifIweretorandomlygenerateanartassetandthatassetgotattachedatanxaxisof120
andayaxisof42(120,42)Icouldgotothephotograph,movetothexandyof(120,42)andwe
wouldfindasinglepixelatthatlocation,samplewhatcolorthatpixelisandpullthatcolorintothefill
ofourartasset.
Doingsowouldmeanthatwecoulduseawidearrayofrandomtechniquestopaintstuffonscreen
butsamplethecolorfromthecolorstructureofaphotograph.Forexample,afloweroraportrait,
likeErikdoesinthefollowingimages.


InHYPE,theHPixelColoristclassisalsobestdefinedin3easysteps:
Createaninstanceof"HPixelColorist"andgiveitthenameof"colors"
1.HPixelColoristcolors
TellHPixelColoristwhichimagetouseforthecolorsampling.
2.colors=newHPixelColorist("kelp.jpg").fillOnly()
Anyofourcolorclassescanbetoldwhattocolorusing.fillOnly(),.strokeOnly(),orfillAndStroke()
Thelaststep,slightlydifferentthaninHColorPool,aftertheartassethasbeenattached,samplethe
pixelonthephotographintheexactsamexandyaxisthatthe"Anchor"gotrandomlyaffixedto.
3.colors.applyColor(d)

Don'tforgetusingaGaussianBluronaphotographfromwithinPhotoshopisgoingtosmoothout
theblendingofcolorsandmayproduceamoreharmoniousflowofcolorsonscreen.

Thiszipfilehasfivestepsshowcasingdifferentsamplingscenarios.Onlystepfiveisabitdifferent
byusingthefollowingcode:
.stroke(colors.getColor(d.x(),d.y()))
.fill(colors.getColor(d.x(),d.y()),100)
ThisisonlyusedifyouarelookingtoapplycolortoboththeStrokeandtheFill,buthaveanalpha
of100appliedtotheFillassetsonly.Pleasenoticethatwhenusingd.x()andd.y()that.loc()would
needtobemovedaboveanyd.x()andd.y()callsoritwillreturn0forbothvalueseverytime.
5. BlendcolorswithHColorField
Inthevideo"HColorField"westartusingthelastofthethreecolorcapableclasseswithintheHYPE
framework.Thecodewritteninthevideosectionisinthe"HColorField.zip"downloadablezipfile.
Thisclassallowsustospecifyradialgradientsinspace.You'dseecolorsblendingifweaddtwo
pointsandtheradiusoftheradialgradientsarelargeenoughtooverlap.
InHYPE,theHColorFieldclassisalsobestdefinedinthreeeasysteps:
Createaninstanceof"HColorField"andgiveitthenameof"colors"
1.HColorFieldcolors
TellHColorFieldthewidthandheightofthefield.Passitapointoflocation(x,y).Thenpassita
colortouse,andfinallytheradiusofthegradient.Thelastthingwewanttouseiswhattocolor,
.fillOnly().
2.
colors=newHColorField(width,height)
.addPoint(width/2,height/2,#FF3300,0.3)//x,y,color,radius
.fillOnly()

Anyofourcolorclassescanbetoldwhattocolorusing.fillOnly(),.strokeOnly(),orfillAndStroke()
Thelaststep,aftertheartassethasbeenattached,samplethecolorfield,whichislookingatthisx,
y,color,andradiusinformationtoprovideacolorwhichgetspulledintotheartasset.
3.colors.applyColor(d)

Don'tforgetthatusing.fill(#000000)or.fill(#ffffff)affectswhatcolorthegradienttransitionsto.
Don'tforgetthatusingmultiplepointswithlargerradius'swillcausetheradialgradientstointeract
andblendcolors.Forexample,apointofredandapointofbluethatoverlapwouldblendpurple
wheretheyoverlapwitheachother.

HGridLayout

1. SpecifyyourdrawingwithHDrawablePool+HRect
Inthevideo"HDrawablePool+HRect",beforewecanstartworkingwithlayoutit'sbestforusto
coverthe"glue"that'sgoingtotieallofthesethingswe'reassemblingtogether.Thecodewrittenin
thevideosectionisinthe"HDrawablePool.zip"downloadablezipfile.
WhileHDrawablePoolhasanabundanceoffeatures,what'simportantinthecontextofthisclass,is
itallowsustodothefollowing:
1.Specifythenumberofassetsbeingpaintedtoscreen
2.Specifywhichassetsaregettingpaintedtoscreen
3.LikeHColorPool,weighttheprobabilityofcertainassetsgettingpaintedmorethanothers
4.Assignlayoutclasses
Theattacheddownloadablezipfile,hasthreesteps,whichisusedacrossthenextthreevideos.
Thisvideousesonlystepone,whichpaintswithHRect.Let'stakesometimetobreakdown
HDrawablePool.
FirstcreateaninstanceofHDrawablePool,callingit"pool".
1.HDrawablePoolpool
Nowletsdefinehowmanyassetsthepoolwilldrawwith.
2.pool=newHDrawablePool(100)
Whereshouldthepoolpainttheseassets?Inthecaseofthesefileweregoingtobepaintingassets
tothestage.
3.pool.autoAddToStage()
Whatassetsisthepoolusingtopaintwith?
.add(newHRect(),20)
.add(newHRect().rounding(10))
Herewe'repaintingwith2HRect's,thesecondhavingroundedcornerswitharadiusof10.
However,thefirstHRectisweighted,addingitself20times.Runningthesketchshouldpaintthe
screenwithadominanceofHRectwithoutroundedcorners.
NextwedefinewhathappenstoeachoftheindividualHRect'sthatgetpaintedtoscreen.
4.
.onCreate(
newHCallback(){
publicvoidrun(Objectobj){
HDrawabled=(HDrawable)obj
d
.strokeWeight(1)
.stroke(#FF3300)
.fill(#111111)
.size((int)random(25,125))
.rotate((int)random(360))
.loc((int)random(width),(int)random(height))
.anchorAt(H.CENTER)

}
}
)
FinallyweaskforALLofour100objectstogetpaintedonscreenatonce.
5..requestAll()

We'llcontinuetousethisbasestructureforeveryexamplemovingforward.HDrawablePool
becomesthefoundation/gluethattiesmanyofourseparateblocksofcodeintoonefinelytuned
runningmachineofawesome.
Hoorayforawesome!


2. ApplySVGassetswithHDrawablePool+HShape
Inthevideo"HDrawablePool+HShape1",we'llcontinuetoworkwithHDrawablePoolbutadd
workingwithexternalSVGassetswhichwemakeinIllustrator.Thecodewritteninthevideosection
isinthe"HDrawablePool.zip"downloadablezipfile,folder/step2.
Justlikethestep1example,thefoundationofthecodeisthesamewithafewminordetails.
1.Createa"data"folder
2.Addour6SVGassetswithinthisfolder
3.Changeour.add()toworkwithHShapeinsteadofHRect
.add(newHShape("svg1.svg"))
.add(newHShape("svg2.svg"))
.add(newHShape("svg3.svg"))
.add(newHShape("svg4.svg"))
.add(newHShape("svg5.svg"))
.add(newHShape("svg6.svg"),20)
Withthischange,runningthesketchshouldbepaintingonscreenwithour6externalSVGassets
however,"svg6.svg"shouldhavedominanceonscreensince20instancesofitwereweightedin
theHDrawablePool.
Finallywealsoadd:
4.HColorPoolcolors/d.randomColors(colors.fillOnly())
whichshouldbepaintingalloftheindividualfillsoftheattachedSVGwithrandomcolors.

Takenotethisartworkissimplevectorassets,geometricshapeswithawidthof50pixelsanda
heightof50pixels.Paintingmany"simple"shapesonscreenwillnotbecometoobusy.Keepthisin
mindaswemoveontothenextexercise.

TakenotethattypicallywhenworkingwithSVGassetsIusethefollowingcode:
.strokeJoin(ROUND)
.strokeCap(ROUND)
Asthiswilldisplaybettervisualresultsonscreenandwhenoutputtingtoavectorbasedfileformat
attheendofthisclass.

3. ApplycomplexSVGassetswithHDrawablePool+HShape2
Inthevideo"HDrawablePool+HShape2",we'llcontinueagaintoworkwithHDrawablePoolbut
addworkingwithexternalSVGassetswhichwemakeinIllustrator.Thecodewritteninthevideo
sectionisinthe"HDrawablePool.zip"downloadablezipfile,folder/step3.
Justlikeinthesteptwoexample,thefoundationofthecodeisthesamewithafewminordetails.
1.pool=newHDrawablePool(50)
Becausethissetofassetsismuchmorecomplexthaninthepreviousstep2example,it'sbestto
lowerthenumberofassetsgettingpaintedaswemightrunintosomeissueswithcrashingoroutof
memoryerrors.
2.changeour.add()toworkwiththenewsetofSVGassets
.add(newHShape("mongo1.svg"))
.add(newHShape("mongo2.svg"))
.add(newHShape("mongo3.svg"))
.add(newHShape("mongo4.svg"))
.add(newHShape("mongo5.svg"))
.add(newHShape("mongo6.svg"))
Finallywealsoedit:
3..size((int)random(200,400))
You'llfindyouneedtotailorthecreationpropertieswiththeartworkgettingused.SincetheseSVG
assetshavelotsofdetails,thesedetailsdon'ttendtoreadwellatsmallerscalesonscreen.


Takenotethisartworkhasmuchmorecomplexvectorassets.Thisideaofcreatingcomplexityfrom
simplicityreallystartstoresonateatthispoint.Iftheassetsbeingusedareverycomplexinnature
andyoumakethemistakeofpaintingtomanyofthemonscreen.Thecomplexitywithincomplexity
isgoingtostarttocomplicateormuddytheclarityofthecomposition.
Unlessyou'reamoreismoreasalifemantra,themorecomplextheartworkgets,thelessyou'll
wanttopaintonscreen.
4. ControldisplaywithHGridLayoutclass
Inthevideo"HGridLayout",we'llfinallybeaddingthefinalpieceofthepuzzlebyaddingalayout
classtohelpuscontrolhowthingscandisplayedonscreen.Thecodewritteninthevideosectionis
inthe"HGridLayout.zip"downloadablezipfile.
SostartingwiththeadjustmentsimplementedinHDrawablePool,we'llattachalayoutclasstothe
code.Aslongasyoudon'tspecifyany.loc()within.onCreate()HDrawablePoolwilluseANYlayout
classtoset.loc()automagically.
inordertousealayoutclass,only1blockofcodeneedstobeaddedtoyoursketch.I'veaddedthis
blockofcoderightafter.add()ofmySVGassets.
1.
.layout(
newHGridLayout()
.startX(25)
.startY(25)
.spacing(50,50)
.cols(11)
)
Whenattachingthisparticularclass,wehavesomeargumentsthatneedtobepassedwiththe
classinordertodescribetheinstructionsforvisualdisplayonscreen.
1..startX()//wheredoesthisgrid,thewholething,startonthexaxis?
2..startY()//wheredoesthisgrid,thewholething,startontheyaxis?
NOTE:thatthisisbasedoff.anchor()or.anchorAt().Ifyourartworkis.anchorAt(H.CENTER),and
inthecaseofthisfiletheartworkis50x50,thenusinga.startX(0)anda.startY(0)yourgridwould
be25onBOTHxandysince.anchorhasmoved25pixelsinordertocenter.
Nextletsdescribethespacingofeachcell:
3..spacing(50,50)//what'stheamountofpixelsofeachcellforthewidthandheight.
Sinceourartworkis50x50,webuildagridthathasnospacingbetweenthevisualassets.Ifour
artworkwas100x100thenusing.spacing(50,50)cell2ofthegridwouldoverlap50pixelsofcell1,
andsoon.Ifourartworkwas50x50andweused.spacing(60,60)thentherewouldbea10pixel
gutterbetweenvisualassets.
Thelastthingwedescribeinourlayoutis:
4..cols(11)//howmanycellsperrow
sincewecanlookat:
pool=newHDrawablePool(121)
121/11=11Soweknowthatinthissamplefilewerebuildingaperfect11x11grid.

NOTE:Wecouldstillhavepool=newHDrawablePool(100)andlayoutwillstillbuildthegriditwill
justbe21cellsshortofbeingaperfectgrid.

folder/step2
Inthismodification,weonlypaintwith.add(newHShape("svg6.svg"))andplaywiththeideaof
randomlyrotatingeachcellby90degreejumps..rotate((int)random(4)*90)whichwillrotateeither
0,90,180,or270(pleasedon'tforgetthatarotationof0isthesameasarotationof360)

folder/step3
InthismodificationwepaintwithallSVGassetsbutintroducerandomsizesbasedon50pixel
jumps,.size(50+((int)random(4)*50))whichwouldgiveus50,100,150,and200
Toclarifywhy,letsbreakitdown
Focusonthiscode(int)random(4)*50)thiswouldgiveusthis:
0*50=0
1*50=50
2*50=100
3*50=150
Sincesettingasizeof0(0*50=0)wouldbeinvisibleonscreenthisiswhywestartthecode
witha50+randomStuff
0*50=0+50=50
1*50=50+50=100
2*50=100+50=150
3*50=150+50=200

Besuretocheckouttheseprojectwhichallusethecodeyounowhave:
http://pinterest.com/praystation/244thesocialgrid/thisprojectevenusestheSVGassetsprovided
inHGridLayout/step2GroupHUG
and
http://pinterest.com/praystation/194aimhighkeepmoving/
http://pinterest.com/praystation/158gridfiligree/
Foryoutextile/patternfreaksIanxiouslyawaittheendlesspatternsyoushalldazzleuswith.
UsingrandomnesswithinstructureisatrickIhaveusedforyearstomakethingsthatare
aestheticallypleasingonscreenwhilestillembracingtheunexpected.

Futurethinking:
http://pinterest.com/pin/180495897536926335/
It'saHGridLayoutthexspacingistight,theyspacingislooseandanHOscillatorusesaSine
wavetotwisteachrow.

HShapeLayout

1. HShapeLayout

Inthevideo"HShapeLayout",we'llbeworkingwithourlastlayoutclass.Thecodewritteninthe
videosectionisinthe"HShapeLayout.zip"downloadablezipfile.
Thisissimplyoneofmyfavoritelayoutstoworkwithwe'llagainbeembracingrandombut
definingwherethatrandomhappens.HShapeLayoutusesa.target()topassinashapetousefor
theattachingandstickingofassets..target()canbepassedmanythingsHRect,HEllipse,etcbut
myfavoriteisHImage,andspecificallytransparentPNG's.
soletsbreakdownournewsetofsteps:
1.
.layout(
newHShapeLayout()
.target(
newHImage("shapeMap.png")
)
)
HerewecreateaninstanceofHShapeLayout,passitanargument.target()anddefineourexternal
PNGtousenewHImage("shapeMap.png")
2.toggleovertophotoshopandcreateanewimage600x600
3.createanewlayer
4.hidethebackgroundlayer
5.definesomeshapes,youcouldusesquares,circles,type,paintbrushtofreedraw,whatever.
6.file/saveforweb
7.selecttheupperrightpresetPNG24whichsupportstransparency
8.saveas"shapeMap.png"withinyourdatafolderofyoursketch
9.togglebacktoSublimeText2andbuildsketch
10.watchheadexplode.
Sowhat'shappeninghere?WellHShapeLayout,whenpassedatransparentPNGisrandomly
pickingxandyvaluesonyourimageandifthexandyvaluereturnsatransparentpixelit
repicksanewxandycoordinate.Itwillkeepdoingthisuntiltherandomlyselectedxandy
coordinateisaNONtransparentpixel.IfithitsaNONtransparentpixelitsimplyattachestheSVG
.anchortothesuccessfulxandycoordinate.
Whatwereleftwithonscreenisamethodofrandomly"STICKING"assetstowhateverformsand
shapesyoudefinedwithinyourPNG.
HUZZAH!

Ican'tbegintotellyouhowmuchIusethisinthegenerativepostersIdoforclients,forexample
Deadmau5,akaJoelZimmermanaskedmetosomegraphicsforaEuropeanTourPosterthe
theme?cuttheheadinhalfandshowtheinnergearsandworkingsofamau5head.
http://pinterest.com/praystation/230deadmau5gearhead/
SoIdrewupsomegearsandstuffandusedHShapeLayouttoattachthoseassetstotheformof
themau5head.


Outputtedthisbacktoavectorfileandmaskedthegeneratedoutputtosaidmau5head.

IthensentoverthegrayscalecompositiontoJoelwhichIalwaysdonevercoloralways
grayscale.Clientscangetsuperhunguponcolor,bypresentingtheworkingrayscale,Joelcan
offerfeedbackontextureandnotgethunguponmycolorselections.
ThenIsendoveraroundofcompositionsusingHColorPoolanddifferentbanksofcolorsblue
wasthewinner.


FinallyweInternetHighFiveeachother,ourchakrasalign,theuniversesingsandaunicorndies.
(orsoI'vebeentold)

someotherexamples:
theassets/http://pinterest.com/pin/180495897536882294/
theshape/http://pinterest.com/pin/180495897536882291/
theassets/http://pinterest.com/pin/180495897536881931/
theshape/http://pinterest.com/pin/180495897536881934/
andsomeofmyfavsusingtype:
http://www.flickr.com/photos/joshuadavis/3420913987/in/set72157613080257958
http://www.flickr.com/photos/joshuadavis/3420912953/in/set72157613080257958
http://www.flickr.com/photos/joshuadavis/3420911767/in/set72157613080257958

OutputFiles

1. letsRender/bad
Inthevideo"letsRender/bad",we'llbelookingatwaysofgettingourrandomlygenerated
compositionsoutofprocessingandintoaformatwecanediteitherinPhotoshoporIllustrator.The
codewritteninthesevideosectionsisinthe"letsRender.zip"downloadablezipfile.
Sometimesit'sbesttolookatthebadwayofdoingthingstofullyunderstandthelimitations.
Inthisstep1exampleweonlyadd1lineofcode:
1.saveFrame("render.png")
thedefaultuseofrenderingiseasy,butleavesmuchtobedesired.WhiletheuseofsaveFrame()
supportsmanydifferentimageformats
saveFrame("render.jpg")
saveFrame("render.png")
saveFrame("render.tif")
saveFrame("render.tga")
SomeformatsarebetterthanotherscompressionversusnocompressionbutI'mdrawntothe
PNGformatdespitenotgettinganyinitialtransparency.Let'sfixsomeoftheseissuesinthenext
videosegment.
2. letsRender/better
Inthevideo"letsRender/better",we'llbelookingatwaysofgettingourrandomlygenerated
compositionsoutofprocessingandintoaformatwecanediteitherinPhotoshoporIllustrator.The
codewritteninthesevideosectionsisinthe"letsRender.zip"downloadablezipfile.
Let'senhanceourabilitytorendertoapixelbasedformatwithafewadditionstothecode.
1.withinsetup()callanewfunctionsaveHiRes(2)wherewepassascaleFactor
2.noLoop()onlyfirethedraw()functiononce
3.haveadraw()functionwithacalltoH.drawStage()
4.createanewfunctioncalledsaveHiRes()
voidsaveHiRes(intscaleFactor){
PGraphicshires=createGraphics(width*scaleFactor,height*scaleFactor,JAVA2D)
beginRecord(hires)
hires.scale(scaleFactor)
if(hires==null){
H.drawStage()
}else{
H.stage().paintAll(hires,false,1)//PGraphics,uses3D,alpha
}
endRecord()
hires.save("render.png")
}
Ifwe'rerenderingtoPhotoshopandapixelbasedimagethenthisisthefileforyou.Eventhough
oursketchis600x600saveHiRes(intscaleFactor)allowsustocreatealargerimage1200x1200
bycallingsaveHiRes(2)
wecanalsorendertoPNGWITHtransparencybycallingH.init(this).background(H.CLEAR)
Renderingthistoatransparentlargerimagejustmeanswehavemoreendlesspossibilitieswithin
photoshopwecanlayeritemsandcreatelargercompositionsthanwecouldwithstep1.
3. letsRender/BEST
Inthevideo"letsRender/BEST",we'llbelookingatwaysofgettingourrandomlygenerated
compositionsoutofprocessingandintoaformatwecanediteitherinPhotoshoporIllustrator.The
codewritteninthesevideosectionsisinthe"letsRender.zip"downloadablezipfile.
There'snodenyingthisismyJAM!
IfwereworkingwithvectorbasedassetsthenIwanttogetbacktoavectorbasedrender.While
similartothepixelbasedoutputinstep2,thereareafewmodificationsweneedtorunthrough.
1.importprocessing.pdf.*we'llbeoutputtingtoPDFsoweneedtoimportprocessingPDFlibraryin
orderforthistowork.
2.H.init(this).background(#202020)noneedforH.CLEAR
3.createanewfunctioncallcalledsaveVector()againnoneedforascaleFactor
4.makechangestoournewfunction:
voidsaveVector(){
PGraphicstmp=null
tmp=beginRecord(PDF,"render.pdf")
if(tmp==null){
H.drawStage()
}else{
H.stage().paintAll(tmp,false,1)//PGraphics,uses3D,alpha
}
endRecord()
}
Withallofthisinplacewecanworkwithvectorbasedassetsandgetbacktoavectorbasedoutput
render.Forme,thisisthemostidealscenario,becauseitoffersfurthermodificationinillustrator
colorchanges,additions,deletions,etc.Anythingcanbemodified.Whileinthestep2example,
oncesomethingisrenderedtoapixelbasedimagemakingchangestothatimageisnotas
flexible.
Hoorayforvectors!
4. letsRender/finaledits
Inthevideo"letsRender/finaledits",we'llbelookingatwaysofgettingourrandomlygenerated
compositionsoutofprocessingandintoaformatwecanediteitherinPhotoshoporIllustrator.The
codewritteninthesevideosectionsisinthe"letsRender.zip"downloadablezipfile.
Inthisexample,ourbasefileisfromHGridLayout/step3.Itusessomerandomrotationand
randomsizingthatwouldrequiresomefurthereditswithinillustrator.
forexample:
1.selectingallthesamestrokecolorswithinillustratorandgivethem1universalstrokeweight.
astheSVGattachedinoursketchchangessizes,sodoesthesizeofthestrokeweights.
2.usetheappearancepaletteto"doubleup"yourstrokes1atastrokeweightof1andanotherata
strokeweightof3butwitha20%transparencythissoftblendingofweight'swhenbeingprinted
addsasoftnessthatIuseinallofmyoutputtedprints.
3.addingcolorsandmakingcolorgroups,because
4.the"recolorartwork"buttoninthetoolbarallowsustoexperimentwithrerandomizingthecolor
mappings.
Withthealreadyexistingcolorsormaybeanentirelynewsetofcolorsaddedintoacolorgroup.

Obviouslythemorecomfortableyouarewithillustratorthebetteryourvisualresultsaregoingto
be.
Thisisjustthebeginningforsomeofyouinanentirelynewworldofrandompossibility.

ProjectInspirations

1. StudentGallery
BasedonsomeoftheprojectsthatyouareworkingonandpostingintheStudentGallery...I
thoughtIwouldcreatesomevideosand.ZIPfilesthatshowsomethingsyoucantry.
KeepPostingtheAwesome!

AdditionalResources
Suggestion:
Atthispoint,Iwouldcomplete:
Sectionfour"Paintingtothescreen"andsectionfive"WorkingwithColor".
InthesesectionsIwillprovidesomesampleSVGfilestoworkwith.Ifeltitwasimportanttocover
drawingassetsfirst,eventhoughit'sprobablythelastthingyou'lldo.
Why?
Becauseoneblockofcodeusingarandomlayoutclassandarandomcolorclasssisartwork
agnostic.Itdoesn'tcarewhatthedrawingsare.Infactyoucouldtakeoneproject,feeditdifferent
colorsandartworkandnevertouchthe"base"codebutyou'dhaveaninfinitenumberof
possibilities.
SoletswritesomeCODE!

S-ar putea să vă placă și