[{"data":1,"prerenderedAt":1104},["ShallowReactive",2],{"projects-home":3},[4,761,872],{"id":5,"title":6,"additionalTags":7,"body":8,"description":735,"excerpt":736,"extension":737,"featured":738,"meta":739,"name":6,"navigation":738,"openSource":745,"path":746,"projectDate":747,"seo":748,"sitemap":749,"status":753,"stem":754,"subtitle":755,"tags":756,"thumbnail":759,"__hash__":760},"projects/projects/1.portfolio-refresh.md","Portfolio Refresh",[],{"type":9,"value":10,"toc":728},"minimark",[11,15,19,24,47,51,54,58,61,64,67,71,75,78,81,469,472,609,616,637,644,673,677,724],[12,13],"stats-table",{":stats":14},"[{\"label\": \"release date\", \"value\": \"2025\"}]",[16,17,18],"p",{},"Welcome to my 2025 refreshed portfolio.",[20,21,23],"h2",{"id":22},"goals","Goals",[25,26,27,35,41],"ol",{},[28,29,30,34],"li",{},[31,32,33],"strong",{},"Speed"," - It had to be fast and I wanted to get as close to a perfect Lighthouse score as possible.",[28,36,37,40],{},[31,38,39],{},"Modern"," - I wanted to utilize the latest tech, Nuxt, Tailwind, and GSAP for subtle animations & micro-interactions.",[28,42,43,46],{},[31,44,45],{},"Learn Something New"," - Get out of my comfort zone and try new things.",[20,48,50],{"id":49},"results","Results",[52,53],"app-lighthouse-results",{},[20,55,57],{"id":56},"process","Process",[16,59,60],{},"I knew from the very beginning I wanted to stick with Vue but I wanted to take it a step further and explore the Nuxt ecosystem which up to this point I hadn't really had a chance or reason to use.",[16,62,63],{},"Choosing Nuxt lead me to Nuxt UI which brought with it Tailwind, which was another tech that I had minimal experience with but that I wanted to get more familiar with.",[16,65,66],{},"I also knew I wanted to host on Vercel's Edge network as I felt that would get me closer to that perfect Lighthouse score.",[20,68,70],{"id":69},"animations","Animations",[72,73],"app-sticker",{":replayable":74},"true",[16,76,77],{},"The opening sticker animation was made using an SVG that I designed in Adobe Illustrator and then animated the writing in GSAP.",[16,79,80],{},"The entire writing animation is a mere 6 lines of code.",[82,83,88],"pre",{"className":84,"code":85,"language":86,"meta":87,"style":87},"language-vue shiki shiki-themes material-theme-lighter monokai monokai","\u003Cscript setup>\nonMounted(() => {\n    gsap.set(\"#sig-1\", { drawSVG: '0%' });\n    gsap.set(\"#sig-2\", { drawSVG: '0%' });\n    const tl = gsap.timeline({ \n        defaults: { duration: .6, delay: .3, ease: 'power1.inOut' } });\n    tl.to('#sticker', { y: 0, opacity: 1 });\n    tl.to(\"#sig-1\", { drawSVG: '-100%', delay: 0.4 });\n    tl.to(\"#sig-2\", { drawSVG: '100%', delay: -.01 });\n})\n\u003C/script>\n","vue","",[89,90,91,111,132,187,225,254,305,353,400,450,459],"code",{"__ignoreMap":87},[92,93,96,100,104,108],"span",{"class":94,"line":95},"line",1,[92,97,99],{"class":98},"sqipZ","\u003C",[92,101,103],{"class":102},"sDhRb","script",[92,105,107],{"class":106},"s4WCV"," setup",[92,109,110],{"class":98},">\n",[92,112,114,118,122,125,129],{"class":94,"line":113},2,[92,115,117],{"class":116},"sj8bM","onMounted",[92,119,121],{"class":120},"s--uY","(",[92,123,124],{"class":98},"()",[92,126,128],{"class":127},"sMInQ"," =>",[92,130,131],{"class":98}," {\n",[92,133,135,138,141,144,147,151,155,157,160,163,166,169,172,175,178,181,184],{"class":94,"line":134},3,[92,136,137],{"class":120},"    gsap",[92,139,140],{"class":98},".",[92,142,143],{"class":116},"set",[92,145,121],{"class":146},"sFVGM",[92,148,150],{"class":149},"sl1cq","\"",[92,152,154],{"class":153},"seZNR","#sig-1",[92,156,150],{"class":149},[92,158,159],{"class":98},",",[92,161,162],{"class":98}," {",[92,164,165],{"class":146}," drawSVG",[92,167,168],{"class":98},":",[92,170,171],{"class":149}," '",[92,173,174],{"class":153},"0%",[92,176,177],{"class":149},"'",[92,179,180],{"class":98}," }",[92,182,183],{"class":146},")",[92,185,186],{"class":98},";\n",[92,188,190,192,194,196,198,200,203,205,207,209,211,213,215,217,219,221,223],{"class":94,"line":189},4,[92,191,137],{"class":120},[92,193,140],{"class":98},[92,195,143],{"class":116},[92,197,121],{"class":146},[92,199,150],{"class":149},[92,201,202],{"class":153},"#sig-2",[92,204,150],{"class":149},[92,206,159],{"class":98},[92,208,162],{"class":98},[92,210,165],{"class":146},[92,212,168],{"class":98},[92,214,171],{"class":149},[92,216,174],{"class":153},[92,218,177],{"class":149},[92,220,180],{"class":98},[92,222,183],{"class":146},[92,224,186],{"class":98},[92,226,228,231,234,238,241,243,246,248,251],{"class":94,"line":227},5,[92,229,230],{"class":127},"    const",[92,232,233],{"class":120}," tl",[92,235,237],{"class":236},"s-IWT"," =",[92,239,240],{"class":120}," gsap",[92,242,140],{"class":98},[92,244,245],{"class":116},"timeline",[92,247,121],{"class":146},[92,249,250],{"class":98},"{",[92,252,253],{"class":146}," \n",[92,255,257,260,262,264,267,269,273,275,278,280,283,285,288,290,292,295,297,299,301,303],{"class":94,"line":256},6,[92,258,259],{"class":146},"        defaults",[92,261,168],{"class":98},[92,263,162],{"class":98},[92,265,266],{"class":146}," duration",[92,268,168],{"class":98},[92,270,272],{"class":271},"sfpNJ"," .6",[92,274,159],{"class":98},[92,276,277],{"class":146}," delay",[92,279,168],{"class":98},[92,281,282],{"class":271}," .3",[92,284,159],{"class":98},[92,286,287],{"class":146}," ease",[92,289,168],{"class":98},[92,291,171],{"class":149},[92,293,294],{"class":153},"power1.inOut",[92,296,177],{"class":149},[92,298,180],{"class":98},[92,300,180],{"class":98},[92,302,183],{"class":146},[92,304,186],{"class":98},[92,306,308,311,313,316,318,320,323,325,327,329,332,334,337,339,342,344,347,349,351],{"class":94,"line":307},7,[92,309,310],{"class":120},"    tl",[92,312,140],{"class":98},[92,314,315],{"class":116},"to",[92,317,121],{"class":146},[92,319,177],{"class":149},[92,321,322],{"class":153},"#sticker",[92,324,177],{"class":149},[92,326,159],{"class":98},[92,328,162],{"class":98},[92,330,331],{"class":146}," y",[92,333,168],{"class":98},[92,335,336],{"class":271}," 0",[92,338,159],{"class":98},[92,340,341],{"class":146}," opacity",[92,343,168],{"class":98},[92,345,346],{"class":271}," 1",[92,348,180],{"class":98},[92,350,183],{"class":146},[92,352,186],{"class":98},[92,354,356,358,360,362,364,366,368,370,372,374,376,378,380,383,385,387,389,391,394,396,398],{"class":94,"line":355},8,[92,357,310],{"class":120},[92,359,140],{"class":98},[92,361,315],{"class":116},[92,363,121],{"class":146},[92,365,150],{"class":149},[92,367,154],{"class":153},[92,369,150],{"class":149},[92,371,159],{"class":98},[92,373,162],{"class":98},[92,375,165],{"class":146},[92,377,168],{"class":98},[92,379,171],{"class":149},[92,381,382],{"class":153},"-100%",[92,384,177],{"class":149},[92,386,159],{"class":98},[92,388,277],{"class":146},[92,390,168],{"class":98},[92,392,393],{"class":271}," 0.4",[92,395,180],{"class":98},[92,397,183],{"class":146},[92,399,186],{"class":98},[92,401,403,405,407,409,411,413,415,417,419,421,423,425,427,430,432,434,436,438,441,444,446,448],{"class":94,"line":402},9,[92,404,310],{"class":120},[92,406,140],{"class":98},[92,408,315],{"class":116},[92,410,121],{"class":146},[92,412,150],{"class":149},[92,414,202],{"class":153},[92,416,150],{"class":149},[92,418,159],{"class":98},[92,420,162],{"class":98},[92,422,165],{"class":146},[92,424,168],{"class":98},[92,426,171],{"class":149},[92,428,429],{"class":153},"100%",[92,431,177],{"class":149},[92,433,159],{"class":98},[92,435,277],{"class":146},[92,437,168],{"class":98},[92,439,440],{"class":236}," -",[92,442,443],{"class":271},".01",[92,445,180],{"class":98},[92,447,183],{"class":146},[92,449,186],{"class":98},[92,451,453,456],{"class":94,"line":452},10,[92,454,455],{"class":98},"}",[92,457,458],{"class":120},")\n",[92,460,462,465,467],{"class":94,"line":461},11,[92,463,464],{"class":98},"\u003C/",[92,466,103],{"class":102},[92,468,110],{"class":98},[16,470,471],{},"The sticker's dropshadow was made using an SVG filter:",[82,473,477],{"className":474,"code":475,"language":476,"meta":87,"style":87},"language-html shiki shiki-themes material-theme-lighter monokai monokai","\u003Csvg ...>\n  \u003Cdefs>\n      \u003Cfilter id=\"shadow\">\n          \u003CfeDropShadow dx=\"0\" dy=\"6\" stdDeviation=\"7\" flood-opacity=\"0.3\" />\n      \u003C/filter>\n  \u003C/defs>\n\u003C/svg>\n","html",[89,478,479,491,501,524,583,592,601],{"__ignoreMap":87},[92,480,481,483,486,489],{"class":94,"line":95},[92,482,99],{"class":98},[92,484,485],{"class":102},"svg",[92,487,488],{"class":106}," ...",[92,490,110],{"class":98},[92,492,493,496,499],{"class":94,"line":113},[92,494,495],{"class":98},"  \u003C",[92,497,498],{"class":102},"defs",[92,500,110],{"class":98},[92,502,503,506,509,512,515,517,520,522],{"class":94,"line":134},[92,504,505],{"class":98},"      \u003C",[92,507,508],{"class":102},"filter",[92,510,511],{"class":106}," id",[92,513,514],{"class":98},"=",[92,516,150],{"class":149},[92,518,519],{"class":153},"shadow",[92,521,150],{"class":149},[92,523,110],{"class":98},[92,525,526,529,532,535,537,539,542,544,547,549,551,554,556,559,561,563,566,568,571,573,575,578,580],{"class":94,"line":189},[92,527,528],{"class":98},"          \u003C",[92,530,531],{"class":102},"feDropShadow",[92,533,534],{"class":106}," dx",[92,536,514],{"class":98},[92,538,150],{"class":149},[92,540,541],{"class":153},"0",[92,543,150],{"class":149},[92,545,546],{"class":106}," dy",[92,548,514],{"class":98},[92,550,150],{"class":149},[92,552,553],{"class":153},"6",[92,555,150],{"class":149},[92,557,558],{"class":106}," stdDeviation",[92,560,514],{"class":98},[92,562,150],{"class":149},[92,564,565],{"class":153},"7",[92,567,150],{"class":149},[92,569,570],{"class":106}," flood-opacity",[92,572,514],{"class":98},[92,574,150],{"class":149},[92,576,577],{"class":153},"0.3",[92,579,150],{"class":149},[92,581,582],{"class":98}," />\n",[92,584,585,588,590],{"class":94,"line":227},[92,586,587],{"class":98},"      \u003C/",[92,589,508],{"class":102},[92,591,110],{"class":98},[92,593,594,597,599],{"class":94,"line":256},[92,595,596],{"class":98},"  \u003C/",[92,598,498],{"class":102},[92,600,110],{"class":98},[92,602,603,605,607],{"class":94,"line":307},[92,604,464],{"class":98},[92,606,485],{"class":102},[92,608,110],{"class":98},[16,610,611,612,615],{},"and then applied onto the ",[89,613,614],{},"\u003Csvg/>"," using a regular style attribute:",[82,617,619],{"className":474,"code":618,"language":476,"meta":87,"style":87},"\u003Csvg style=\"filter: url('#shadow'); ...\n",[89,620,621],{"__ignoreMap":87},[92,622,623,625,627,630,632,634],{"class":94,"line":95},[92,624,99],{"class":98},[92,626,485],{"class":102},[92,628,629],{"class":106}," style",[92,631,514],{"class":98},[92,633,150],{"class":149},[92,635,636],{"class":153},"filter: url('#shadow'); ...\n",[16,638,639,640,643],{},"The ",[89,641,642],{},"v-gsap-nuxt"," module makes it even easier to animate DOM elements simply through specialized attributes.\nThis is method I used on the work history page to animate the history entries in as the page scrolls.",[82,645,649],{"className":646,"code":647,"language":648,"meta":87,"style":87},"language-vue-html shiki shiki-themes material-theme-lighter monokai monokai","\u003Celement v-gsap.whenVisible.once.stagger.from=\"{ opacity: 0, x: -10, stagger: 0.2 }\" >\n","vue-html",[89,650,651],{"__ignoreMap":87},[92,652,653,655,658,661,663,665,668,670],{"class":94,"line":95},[92,654,99],{"class":98},[92,656,657],{"class":102},"element",[92,659,660],{"class":106}," v-gsap.whenVisible.once.stagger.from",[92,662,514],{"class":98},[92,664,150],{"class":149},[92,666,667],{"class":153},"{ opacity: 0, x: -10, stagger: 0.2 }",[92,669,150],{"class":149},[92,671,672],{"class":98}," >\n",[20,674,676],{"id":675},"technologies-utilized","Technologies Utilized",[678,679,680,690],"table",{},[681,682,683],"thead",{},[684,685,686],"tr",{},[687,688,689],"th",{},"Frontend",[691,692,693,699,704,709,714,719],"tbody",{},[684,694,695],{},[696,697,698],"td",{},"Nuxt",[684,700,701],{},[696,702,703],{},"Vue 3",[684,705,706],{},[696,707,708],{},"Nuxt UI",[684,710,711],{},[696,712,713],{},"Tailwind",[684,715,716],{},[696,717,718],{},"GSAP",[684,720,721],{},[696,722,723],{},"TypeScript",[725,726,727],"style",{},"html pre.shiki code .sqipZ, html code.shiki .sqipZ{--shiki-light:#39ADB5;--shiki-default:#F8F8F2;--shiki-dark:#F8F8F2}html pre.shiki code .sDhRb, html code.shiki .sDhRb{--shiki-light:#E53935;--shiki-default:#F92672;--shiki-dark:#F92672}html pre.shiki code .s4WCV, html code.shiki .s4WCV{--shiki-light:#9C3EDA;--shiki-default:#A6E22E;--shiki-dark:#A6E22E}html pre.shiki code .sj8bM, html code.shiki .sj8bM{--shiki-light:#6182B8;--shiki-default:#A6E22E;--shiki-dark:#A6E22E}html pre.shiki code .s--uY, html code.shiki .s--uY{--shiki-light:#90A4AE;--shiki-default:#F8F8F2;--shiki-dark:#F8F8F2}html pre.shiki code .sMInQ, html code.shiki .sMInQ{--shiki-light:#9C3EDA;--shiki-light-font-style:inherit;--shiki-default:#66D9EF;--shiki-default-font-style:italic;--shiki-dark:#66D9EF;--shiki-dark-font-style:italic}html pre.shiki code .sFVGM, html code.shiki .sFVGM{--shiki-light:#E53935;--shiki-default:#F8F8F2;--shiki-dark:#F8F8F2}html pre.shiki code .sl1cq, html code.shiki .sl1cq{--shiki-light:#39ADB5;--shiki-default:#E6DB74;--shiki-dark:#E6DB74}html pre.shiki code .seZNR, html code.shiki .seZNR{--shiki-light:#91B859;--shiki-default:#E6DB74;--shiki-dark:#E6DB74}html pre.shiki code .s-IWT, html code.shiki .s-IWT{--shiki-light:#39ADB5;--shiki-default:#F92672;--shiki-dark:#F92672}html pre.shiki code .sfpNJ, html code.shiki .sfpNJ{--shiki-light:#F76D47;--shiki-default:#AE81FF;--shiki-dark:#AE81FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":87,"searchDepth":113,"depth":113,"links":729},[730,731,732,733,734],{"id":22,"depth":113,"text":23},{"id":49,"depth":113,"text":50},{"id":56,"depth":113,"text":57},{"id":69,"depth":113,"text":70},{"id":675,"depth":113,"text":676},"Rebuilding my website with modern tech.",null,"md",true,{"items":740},[741,742,743,744],"/projects/crateos/home-dark.jpg","/projects/crateos/home.jpg","/projects/crateos/recall.jpg","/projects/crateos/recall-dark.jpg",false,"/projects/portfolio-refresh","2025-05-01T00:00:00.000Z",{"description":735},{"loc":746,"lastmod":750,"changefreq":751,"priority":752},"2025-05-18","monthly",0.8,"published","projects/1.portfolio-refresh","Gotta go fast",[757,698,718,713,723,758],"VueJS","Git","/projects/portfolio/thumb.webp","QiGZjUMDeFEax3ll1HamWS6r0UfyztBOjGdzkqk-VkQ",{"id":762,"title":763,"additionalTags":764,"body":765,"description":856,"excerpt":736,"extension":737,"featured":738,"meta":857,"name":775,"navigation":738,"openSource":745,"path":859,"projectDate":860,"seo":861,"sitemap":862,"status":753,"stem":863,"subtitle":864,"tags":865,"thumbnail":870,"__hash__":871},"projects/projects/2.crateos-recalls.md","Crateos Recalls",[],{"type":9,"value":766,"toc":854},[767,781,786,789,795,798,850],[16,768,769,776,777,140],{},[770,771,775],"a",{"href":772,"rel":773},"https://crateos.com",[774],"nofollow","CrateOS Recalls"," is a web application that\nI started to push myself, get out of my comfort zone and learn new technologies along the way.\nTutorials and documentation are great but I feel I learn best by ",[778,779,780],"em",{},"building",[782,783],"problem-solution",{"problem":784,"solution":785},"The recall process is often confusing, time consuming, and parents are too busy to dedicate the time & effort.","Make the recall discovery process easier and enable tailored recall alerts on a per-company basis.",[16,787,788],{},"The result is a Solo-SaaS project and the culmination of my experience in designing and developing web applications.",[790,791],"player",{"posterDesc":792,"posterSrc":793,"src":794},"A brief walkthrough of the CrateOS Recalls app.","https://www.crateos.com/images/demo-poster.gif","https://www.crateos.com/media/crateos-recalls-promo-720.mp4",[796,797,676],"h4",{"id":675},[678,799,800,809],{},[681,801,802],{},[684,803,804,806],{},[687,805,689],{},[687,807,808],{},"Backend",[691,810,811,818,826,834,842],{},[684,812,813,815],{},[696,814,703],{},[696,816,817],{},"ExpressJS",[684,819,820,823],{},[696,821,822],{},"Composition API",[696,824,825],{},"Loopback",[684,827,828,831],{},[696,829,830],{},"Pinia",[696,832,833],{},"PostgreSQL",[684,835,836,839],{},[696,837,838],{},"VueUse",[696,840,841],{},"ElasticSearch",[684,843,844,847],{},[696,845,846],{},"Bulma / Buefy",[696,848,849],{},"NodeJS",[851,852],"image-carousel",{":items":853},"[\"/projects/crateos/home-dark.jpg\",\"/projects/crateos/home.jpg\",\"/projects/crateos/recall.jpg\", \"/projects/crateos/recall-dark.jpg\"]",{"title":87,"searchDepth":113,"depth":113,"links":855},[],"Tailored CPSC product recalls for parents & busy people.",{"url":772,"items":858},[741,742,743,744],"/projects/crateos-recalls","2025-01-01T00:00:00.000Z",{"description":856},{"loc":859,"lastmod":750,"changefreq":751,"priority":752},"projects/2.crateos-recalls","Solo Founder + Full Stack + Design  + Branding",[757,866,867,723,868,689,808,869,758],"Bulma","SCSS","Postgres","PWA","/projects/crateos/thumb.webp","ub7Vj1IlE8DRDd4oU1kvD_1eLt2yddpi80dvH8bCmaY",{"id":873,"title":874,"additionalTags":875,"body":876,"description":1085,"excerpt":736,"extension":737,"featured":738,"meta":1086,"name":1087,"navigation":738,"openSource":745,"path":1088,"projectDate":1089,"seo":1090,"sitemap":1091,"status":753,"stem":1093,"subtitle":1094,"tags":1095,"thumbnail":1102,"__hash__":1103},"projects/projects/3.shooting-gallery-for-playdate.md","Shooting Gallery For Playdate",[],{"type":9,"value":877,"toc":1078},[878,881,886,889,895,899,908,916,939,944,948,955,970,976,985,990,997,1006,1011,1020,1029,1033,1036,1047,1054,1058,1068],[12,879],{":stats":880},"[{\"label\": \"release date\", \"value\": \"2023\"}, {\"label\": \"rating\", \"stars\":5 }, {\"label\": \"downloads\", \"value\": \"390+\"}, {\"label\": \"URL\", \"value\": \"itch.io\", \"url\": \"https://limitlis.itch.io/shooting-gallery\"}]",[882,883,885],"h3",{"id":884},"step-right-up","Step right up!",[16,887,888],{},"Aim for the middle and test your mettle against a volley of tricky targets, diabolical ducks, and bewitched bombs as they float tauntingly across your playdate. Use PowerUps to your advantage to reach the top of the high score leaderboard.\nSet a high score and then hand the playdate to a friend to see if they can beat it.",[890,891,892],"blockquote",{},[16,893,894],{},"\"incredibly high polish on the concept\" - LedBetter Games",[882,896,898],{"id":897},"inspiration","Inspiration",[16,900,901,902,907],{},"From the day it was first announced I knew I wanted to make a game for the yellow ",[770,903,906],{"href":904,"rel":905},"https://play.date/",[774],"Playdate"," console and immediately pre-ordered one.",[16,909,910,911,140],{},"Having never written a single line of Lua, I went from designing and building to self-publishing and releasing my first indie game on ",[770,912,915],{"href":913,"rel":914},"https://limitlis.itch.io/shooting-gallery",[774],"itch.io",[917,918,923],"div",{"className":919},[920,921,922],"h-auto","w-auto","aspect-3-2",[16,924,925],{},[926,927],"img",{"alt":928,"className":929,"src":937,"width":938},"Gameplay",[930,931,932,933,934,935,922,936],"not-prose","rounded","h-48","w-full","md:h-full","md:h-48","object-contain","/projects/playdate/gameplay.gif",400,[890,940,941],{},[16,942,943],{},"\"I like the duck game\" – My kids",[882,945,947],{"id":946},"gameplay-mechanics","Gameplay Mechanics",[16,949,950],{},[770,951,954],{"href":87,"className":952},[953],"text-lg","PowerUps",[16,956,957,968],{},[926,958],{"alt":959,"className":960,"src":965,"width":966,"style":967},"Time Bonus",[961,962,963,964],"inline-flex","p-1","object-cover","pointer-none","/projects/playdate/time-bonus.gif",30,"margin: 0; margin-right: 10px; zoom: 1.5; background-color: #b1aea7; aspect-ratio: 1; width: 40px;",[31,969,959],{},[971,972,973],"ul",{},[28,974,975],{},"Adds seconds to the clock to extend your current game.",[16,977,978,982],{},[926,979],{"alt":959,"className":980,"src":981,"width":966,"style":967},[961,962,963,964],"/projects/playdate/phantom-ammo.gif",[31,983,984],{},"Phantom Ammo",[971,986,987],{},[28,988,989],{},"Shoot to stop at a random number and that amount of phantom ammo will be added without a reloading or resetting your hit streak.",[890,991,992],{},[16,993,994],{},[778,995,996],{},"Reloading will be prevented until all phantom rounds are spent.",[16,998,999,1003],{},[926,1000],{"alt":959,"className":1001,"src":1002,"width":966,"style":967},[961,962,963,964],"/projects/playdate/point-bomb.png",[31,1004,1005],{},"Point Bombs",[971,1007,1008],{},[28,1009,1010],{},"Shoot one and a bomb card will appear in your hit streak. Clear the card before the reload counter reaches 0 and receive the points.\nOtherwise those points will be removed from your current score.",[16,1012,1013,1018],{},[926,1014],{"alt":1015,"className":1016,"src":1017,"width":966,"style":967},"Shiny Targets",[961,962,963,964],"/projects/playdate/shiny-target.webp",[31,1019,1015],{},[971,1021,1022],{},[28,1023,1024,1025,1028],{},"Shiny targets will ",[31,1026,1027],{},"2X"," the score for the first three hits, being worth 2, 4, 6, 8 or 10 depending on your accuracy.",[882,1030,1032],{"id":1031},"development-challenges","Development Challenges",[16,1034,1035],{},"Getting the duck's movement just right was pretty challenging early on while I was still figuring out the SDK. I had a general idea of how I wanted the movement to be\nbut most importantly it had to feel mechanical — as if driven by gears. The SDK has built in support for making arcs but getting the random\nmovement took some math to get just right.",[16,1037,1038,1039,1042,1043,1046],{},"Here's a small diagram I made to help me figure out where to place the next arc based on a random ",[31,1040,1041],{},"radius","\nand the duck's current ",[31,1044,1045],{},"X"," position.",[16,1048,1049],{},[926,1050],{"alt":1051,"className":1052,"src":1053,"width":938},"Arc Math",[933],"/projects/playdate/arcmath.webp",[882,1055,1057],{"id":1056},"nerdy-stats","Nerdy Stats",[16,1059,1060,1061,1067],{},"For source control I set up a local ",[770,1062,1066],{"href":1063,"rel":1064,"target":1065},"https://about.gitea.com/",[774],"_blank","Gittea"," instance on my home Network Attached Storage (NAS).",[1069,1070,1071],"client-only",{},[1072,1073,1077],"iframe",{"frameBorder":541,"src":1074,"width":1075,"height":1076},"https://itch.io/embed/1837225?border_width=2&bg_color=18181c&fg_color=a3a5aa&link_color=1fcd9f&border_color=26262f",554,169,"\u003Ca href=\"https://limitlis.itch.io/shooting-gallery\">SHOOTING GALLERY for Playdate by limitlis\u003C/a>",{"title":87,"searchDepth":113,"depth":113,"links":1079},[1080,1081,1082,1083,1084],{"id":884,"depth":134,"text":885},{"id":897,"depth":134,"text":898},{"id":946,"depth":134,"text":947},{"id":1031,"depth":134,"text":1032},{"id":1056,"depth":134,"text":1057},"A carnival inspired game for the Playdate console.",{"url":913},"Shooting Gallery","/projects/shooting-gallery-for-playdate","2023-10-01T00:00:00.000Z",{"description":1085},{"loc":1088,"lastmod":1092,"changefreq":751,"priority":752},"2026-02-22","projects/3.shooting-gallery-for-playdate","Game Design & Development",[1096,1097,1098,1099,1100,1101,758],"Lua","Playdate SDK","Graphic Design","SFX","Game design","Game Development","/projects/playdate/thumb.webp","VNfjA2HH2oLPUMOgxzNMTUpy8Ekr-nOl_rU5F6jh6Ug",1778072416268]