diff --git a/src/diary/entries/201029 b/src/diary/entries/201029 index 17318df..546f240 100644 --- a/src/diary/entries/201029 +++ b/src/diary/entries/201029 @@ -56,6 +56,29 @@ Set the locale in your script, somewhere like _ready() or on a 'change language'
Now that everything's in place, you can keep adding new ids + translations, and Godot will automatically use your changes in-game.

+
+

step 6 - insert values into text

+
+Languages differ in syntax, so use format strings.
+
+In your spreadsheet, write %s where your inserted text will go. +
+
+(image: in the .CSV, id= character_level, en= Level %s, ja= レバル %s)
+
+
+Then in your script, write tr("key") % inserted_val in place of the formatted string.
+
+
+(image: in the script, set_text(tr("character_level") % String(level))
+
+
+Now the formatted string will appear in-game.
+
+
+(image: screenshot: Level 1)(image: screenshot: レベル 1)
+
+

that's the basics

(image: blessfrey screenshot in Japanese)
diff --git a/src/diary/entries/201210 b/src/diary/entries/201210 new file mode 100644 index 0000000..aa57bf7 --- /dev/null +++ b/src/diary/entries/201210 @@ -0,0 +1,28 @@ + +

common tropes from media

+december 10, 2020
+#writing
+
+
+I like collecting common tropes from games I play. Maybe it can inspire some game beats? Here's a few of them listed with some games I've seen them in ~
+
+If you're worried about spoilers, games mentioned are The Cat Lady, Dreamfall: The Longest Journey, Fire Emblem, Guild Wars, Guild Wars 2, Half-Life, Mass Effect, Neverwinter Nights 2, Oblivion, Persona 4, Planescape: Torment, RuneScape 2 +
+ +
diff --git a/src/diary/entries/210101 b/src/diary/entries/210101 index 0207208..43a4d59 100644 --- a/src/diary/entries/210101 +++ b/src/diary/entries/210101 @@ -40,12 +40,14 @@ I didn't keep a diary very well this month;; This is mostly pieced together from
  • added summon + bleeding keywords
  • added Skillmaker support for generating skills that use those keywords
  • maintain this website a little
  • +
  • found a Linux alternative for OneNote that I finally like - CherryTree. I use it to store research and develop ideas for blessfrey :)

  • week 5, december 27-31


    -#dia #events #story
    +#dia #events #refactoring #story

    +
    +

    thursday, january 21

    + +
    +

    friday, january 22

    + +
    +

    saturday, january 23

    + +
    +

    week 5, january 24-30


    +#
    +
    +

    sunday, january 24

    + +
    +

    tuesday, january 26

    + +
    +

    thursday, january 28

    + +
    +

    friday, january 29

    + +
    +

    week 6, january 31


    +#
    +
    diff --git a/src/diary/entries/210204 b/src/diary/entries/210204 index de9ad3b..ee86344 100644 --- a/src/diary/entries/210204 +++ b/src/diary/entries/210204 @@ -1,13 +1,28 @@ - -

    web development resources

    -october 15, 2020
    -#accessibility #color #css #html #webdesign
    -
    -I'll collect frequently used resources for web design here.
    -
    - + +

    new year's resolution - making the most of 2021

    +february 4, 2021
    +
    +
    +2020 was a year of loss and difficult changes. I was largely unproductive in game development, web development, social media, and just about every aspect of my life. Most of a year passed without much to show for it. 2021 probably isn't going to be any better, but I will be. Now when I pray, "Father, thank you for this day," I won't take a normal, healthy day for granted and make the most of what I've been given.
    +
    +Honestly, it's a special kind of prolonged suffering to be separated from people for a year. Going out is such a fantasy to me now, no matter how masked and socially distant. Simple grocery shopping has become an event that I celebrate with my cutest clothes and hair. I even started wearing makeup to make outings just that much more special. To learn fun colorful makeup, I started watching small beauty youtubers. For a such a frivolous topic, their videos incorporate a lot of self-reflection about the wastefulness of large collections. It got me thinking about the wastefulness of my 2020 and how I want to spend 2021.
    +

    +

    panning makeup


    +Online beauty communities value the concept of panning. Against a consumer landscape of constant releases and rising quality of affordable drugstore + indie brands, it's aspirational to be content with what you already have. Panning means reaching the bottom packaging of a product, like this Instagram girl did. #projectpan and #panporn are full of well-loved makeup.
    +
    +
    View this post on Instagram

    A post shared by Curated By Léah (@_curatedbyleah)

    + +
    +Panning is difficult. I used to wear a full face of makeup for work. Besides some complexion products, I had one lipstick, four eyeshadow singles, and one blush. Even after using an extremely minimal collection daily for two years, there were noticeable dips but no pans in my color cosmetics.
    +
    +If you buy more than a palette or two, it's easy to buy more makeup than you could ever use in your life. Even worse, cream products dry up within a year or two. Panners find that excess wasteful, so they cut back on spending and intentionally enjoy their makeup to the fullest before it expires.
    +
    +There's another angle to panning. Since so many releases are limited edition, there's a natural tendency to save your favorite makeup for special occasions. That's equally wasteful, since it's more likely to mold than empty. If it's your favorite, you should wear it every single day.
    +

    +

    panning other areas of life


    +I guess the concept is obvious, but I find a lot of wisdom in that mindset. The concept can be applied anywhere - videogame backlogs, unread book collections, stocked up baking ingredients, unused art supplies, ignored MOOCs, forgotten exercise equipment, and hoarded assets and libraries. For each item in those areas, I could have been developing skills, gaining new perspectives, and having fun. Otherwise, it's just junk taking up space in my apartment and hard drive.
    +
    +In 2021, even if I have to do it all alone at home, I'm going to be more intentional about enjoying my hobbies. I've already finished 2 books, sewn 4 face masks, started an art journal, and gotten further than ever in Planescape: Torment.
    +
    +Happy (belated) New Year. Enjoy 2021. :)
    +
    diff --git a/src/diary/entries/210218 b/src/diary/entries/210218 index f9611bd..ae8ca12 100644 --- a/src/diary/entries/210218 +++ b/src/diary/entries/210218 @@ -1,28 +1,18 @@ - -

    my favorite GDC talks

    -january 7, 2020
    -#gamedesign #marketing
    + +

    Writing Resources

    +february 18, 2021
    +

    -I really should be keeping a list of these with descriptions, so why not keep them in an article?
    -
    -

    Automated Testing and Instant Replays in Retro City Rampage


    -Vblank Entertainment's Brian Provinciano (2015)
    -log button inputs to replay the game, for use in preproducing bugs, sharing replays on the community leaderboard, running cutscenes, and even controlling AI. It is 100% accurate in deterministic engines but also helpful in less deterministic engines. +Blessfrey has a story and character arcs. Let's get more confident with our story with online resources.

    +

    plot



    -
    -

    Empathizing with Steam: How People Shop for Your Game


    -Chris Zukowski (2020)
    -tips for how to design your Steam store page based on Zukowski's screenshare and shopping diary observations of ordinary people shopping on Steam
    -
    +

    general



    diff --git a/src/diary/201210 b/src/diary/entries/extra/201210 similarity index 100% rename from src/diary/201210 rename to src/diary/entries/extra/201210 diff --git a/src/diary/entries/extra/210218 b/src/diary/entries/extra/210218 new file mode 100644 index 0000000..f9611bd --- /dev/null +++ b/src/diary/entries/extra/210218 @@ -0,0 +1,28 @@ + +

    my favorite GDC talks

    +january 7, 2020
    +#gamedesign #marketing
    +
    +I really should be keeping a list of these with descriptions, so why not keep them in an article?
    +
    +

    Automated Testing and Instant Replays in Retro City Rampage


    +Vblank Entertainment's Brian Provinciano (2015)
    +log button inputs to replay the game, for use in preproducing bugs, sharing replays on the community leaderboard, running cutscenes, and even controlling AI. It is 100% accurate in deterministic engines but also helpful in less deterministic engines. +
    + +
    +
    +

    Empathizing with Steam: How People Shop for Your Game


    +Chris Zukowski (2020)
    +tips for how to design your Steam store page based on Zukowski's screenshare and shopping diary observations of ordinary people shopping on Steam
    +
    + +
    diff --git a/src/diary/entries/210304 b/src/diary/entries/extra/210304 similarity index 100% rename from src/diary/entries/210304 rename to src/diary/entries/extra/210304 diff --git a/src/diary/entries/extra/chesterton-magic b/src/diary/entries/extra/chesterton-magic new file mode 100644 index 0000000..adbf3cc --- /dev/null +++ b/src/diary/entries/extra/chesterton-magic @@ -0,0 +1,15 @@ + +

    Magic: A Fantastic Comedy in a Prelude and Three Acts - G.K. Chesterton (1913)

    +january 8, 2020
    +
    +
    +Did you know G.K. Chesterton wrote a play? Its existence really surprised me while browsing Project Gutenberg. I know him mostly as the author of The Everlasting Man and lots of other books about philosophy and religion. He's not stuffy, though. His style is so poetic and dramaticized through use of personification, he makes the topics as enjoyable as fiction...at least, from what I remember. It's been 10 years since I read anything else by him.
    +
    +Apparently, George Bernard Shaw wrote a letter pressuring him into drama because he felt he was wasting his talent on journalist. (According to Chesterton University's Lecture 25: Magic by Dale Ahlquist)
    +"I shall deliberately destroy your credit as an essayist, as a journalist, as a critic, as a Liberal, as everything that offers your laziness as a refuge, until starvation and shame drive you to serious dramatic parturition. I shall repeat my public challenge to you; vaunt my superiority; insult your corpulence; torture Belloc; if necessary, call on you and steal your wife’s affections by intellectual and athletic displays, until you contribute something to British drama." (also from that link)
    +
    +You can read Magic, too, at Project Gutenberg. Plays are meant to be performed, though, so hopefully you can find something on Youtube at least.
    +
    + +
    + diff --git a/src/diary/entries/extra/clayton-drinker-of-souls b/src/diary/entries/extra/clayton-drinker-of-souls new file mode 100644 index 0000000..9d8f148 --- /dev/null +++ b/src/diary/entries/extra/clayton-drinker-of-souls @@ -0,0 +1,14 @@ + +

    Drinker of Souls - Jo Clayton (1986)

    +january 8, 2020
    +
    +
    +I usually read classics or philosophy, so I thought I'd cut loose and read my first 80s science fiction novel: Drinker of Souls, from Jo Clayton's Drinker of Souls trilogy. Unfortunately, Clayton's novels are probably all out of print and won't be entering the public domain for a long, long time. I found mine at a thrift store.
    +
    +I just picked up a random scifi book, but apparently the Skeen Trilogy by this author is more popular.
    +
    +Review here +
    +I read half of the next book, Blue Magic, but it was kind of boring and the characters were less interesting for me. It explored more parallel worlds, all with dramatically different levels of technology and magic. It had that 'wizards using computers' aesthetic that isn't done often enough. The setting reminded me of the Sigil in Planescape: Torment, how characters from all over get trapped in Brann's world. There was the guy from a futuristic trapped there with his phaser, like that number tattoo guy in the Buried Village who tells you about his cyberpunk world.
    +
    + diff --git a/src/diary/entries/extra/flightrising-badges b/src/diary/entries/extra/flightrising-badges new file mode 100644 index 0000000..8d4dfe0 --- /dev/null +++ b/src/diary/entries/extra/flightrising-badges @@ -0,0 +1,132 @@ + +

    FlightRising badges

    +january 8, 2020
    +
    +
    +Privately hosting my collection of community badges, in case imgur goes up in flames.
    +
    +Fire - Lava Bank - 1/21
    +(image: FlightRising badge) +(image: FlightRising badge)
    +
    +Fire - Snowy Safari Zone - 1/21
    +(image: FlightRising badge)
    +
    +Fire - WildFire Lottery - 1/21
    +(image: FlightRising badge) +(image: FlightRising badge)
    +
    +Fire vs Light - 12/20
    +(image: FlightRising badge) +(image: FlightRising badge)
    +
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge)
    +
    +Arcane - 9/20
    +(image: FlightRising badge)
    +
    +Water - Dom Push - 9/20
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +Fire - Flameforger's Festival - Exalts, Geyser's Grocery Games - 8/20
    +(image: FlightRising badge)(image: FlightRising badge) +(image: FlightRising badge) +
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +Fire - Pyro's Kitchen Window Bonsai - 8/20
    +(image: FlightRising commission) +(image: FlightRising commission) +(image: FlightRising commission) +(image: FlightRising commission) +(image: FlightRising commission) +
    +Fire - Lava Bank - 8/20
    +(image: FlightRising badge) +
    +Lightning - Thundercrack Carnivale - 7/20
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +Fire - Shocking Safari Zone - 7/20
    +(image: FlightRising badge) +
    +Fire - Baldwin's Brew for the Bank Over 9000 - 7/20
    +(image: FlightRising badge) +(image: FlightRising badge) +
    +Ice - 7/20
    +(image: FlightRising badge) +(image: FlightRising badge) +
    +Arcane - 7/20
    +personality quiz result: Starseeker
    +(image: FlightRising badge) +
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +Fire - Shining Safari Zone - 7/20
    +(image: FlightRising badge) +
    +Fire - Trash for Cash - 7/20
    +(image: FlightRising badge) +(image: FlightRising badge) +
    +Wind vs Plague - 6-7/20
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +Fire - Subspecies Raffle - 5-6/20
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +
    +Last updated: 1/29/21
    +
    diff --git a/src/diary/entries/extra/ideabox b/src/diary/entries/extra/ideabox index a453c32..fc68604 100644 --- a/src/diary/entries/extra/ideabox +++ b/src/diary/entries/extra/ideabox @@ -1,6 +1,7 @@ abyssal whip adamantine airship +alchemy aloe alpine amber fossil @@ -15,6 +16,9 @@ apothecary apricot asterism atelier +aura +baby's breath +backhoe bad cat Baldur bamboo @@ -25,6 +29,7 @@ bell tower birthday dress birthstone black bear +black market The Black Hand black knight black water @@ -32,6 +37,7 @@ black widow blackguard bloodstone blue and yellow +blue bell blue blood blue rose bluebell @@ -42,37 +48,51 @@ bubble bath bubble tea bunny boy buried treasure +butter cake butterfly woman +café camel candlelight +candy store +caravan cashmere castle cat café cat familiar cat man +catnip catacombs +cathedral celestial cemetery +centaur chained to rocks chain mail +chalcedony chameleon chamomile chandelier charmeuse cheese bread +chiffon chimera chives chocolate factory chronomancer +chrysanthemum cipher citadel +citrine city of the dead clipart +clover coin flip cold iron confetti constellation +cookie cutter copycat +coral cotton couture cove @@ -81,6 +101,7 @@ crazy quilt Crossroad Keep crucibled crystal sea +cucumber daeva dark horse dark hour @@ -95,14 +116,17 @@ dire wolf dollhouse donkey doppelgänger +double life dragonfruit dragonstone dreamweaver +dump truck Dymer dystopia ectoplasm edelweiss egg hunt +El Dorado elemental elipse elixir of life @@ -146,6 +170,7 @@ geode ghost orchid ghost ship ghost town +gingham girl in the internet girl in white glow stick @@ -170,9 +195,15 @@ happy place haunted house headscarf heart +heather hermit +hermit crab holly +holy grail +honeycomb honeydew +honeysuckle +horizon hot air balloon hot and cold game hot cocoa @@ -183,11 +214,14 @@ imp incense invisible man iridescence +iris ironwood +ivory jack-o'-lantern jacquard -jade +jade chain jasmine +jellyfish juicebox kaleidoscope kesi silk @@ -204,8 +238,11 @@ lair lamentation lavender lemonade +licorice life-giver lighthouse +lily +lip gloss lip oil Little Red Riding Hood lizardman @@ -222,9 +259,12 @@ love letter love potion low poly lullaby +lunar eclipse +lust macramé mages guild magic carpet +malachite man in the moon mandrake manna @@ -243,13 +283,19 @@ meteorite metropolis miasma Midas Touch +Milky Way millennial moon +mind game miniature +mink +mirage +mire mirror of Venus mirror on the wall mithril monastery money tree +monk's hood monkey and bear moon rock moonflower @@ -261,21 +307,27 @@ moth mudskipper mural muse +naga necromancer nightlight nocturnality +nymph oneiromancer oblivion odalisque +olive omen opal orb +orchid orichalcum orphan palace panda eyes paper crane paper fan +paper lantern +paragon pearl periwinkle personality test @@ -316,9 +368,12 @@ reclining woman red reverse trap road roller +rogue rooibos tea rose gold rose petal +rose quartz +rosemary runestone s'more sailor fuku @@ -326,10 +381,12 @@ Sanctum sandalwood sandcastle sandman +sandstone sanguine, my brother sardonic satire satyr +scone scrying pool scythe sea foam @@ -354,7 +411,9 @@ skeleton skipping stone slide puzzle slime +smartphone smoke and mirrors +smoothie snow globe soma soulmate @@ -367,18 +426,21 @@ spice cookie spirit animal spy stained-glass +star sapphire stardust stargazer starry sky statuesque -sticker +sticker book stinky cat +stone circle stone face stone people storm cloud strawberries and cream strawberry blonde strawberry shortcake +streusel sunflower swamp light swan song @@ -393,9 +455,12 @@ three women tide pool tiger's eye toasted marshmallow +topaz topiary +toy kingdom treasure trails tree of life +treehouse trick or treat trickster tulip @@ -406,11 +471,14 @@ unicorn horn unstoppable mailman urban legend utopia +vampire +Venice vanity of vanities Venus waiting room waking dream walled city +wallflower wampus cat wandering eye wanderlust @@ -419,6 +487,7 @@ watchmen on the wall water bearer water nymph waterfall room +waterlily weeping willow Whip-Poor-Will whisper @@ -427,12 +496,14 @@ will-o'-wisp wind chimes wings wishing well +wisteria witchhouse witching hour wizard tower wolf's-bane woman and serpent the woodsman +workshop wormwood wreath wyvern diff --git a/src/diary/entries/extra/reading-journal b/src/diary/entries/extra/reading-journal new file mode 100644 index 0000000..2237eff --- /dev/null +++ b/src/diary/entries/extra/reading-journal @@ -0,0 +1,36 @@ + +

    reading journal

    +january 8, 2020
    +
    +
    +I'll collect summaries, thoughts, and excerpts as I read. I used to read so much more. I should read more.
    +
    +reading now
    + +
    +
    +books to read next
    + +
    +
    +completed books
    + +
    diff --git a/src/diary/entries/extra/stop-the-steal b/src/diary/entries/extra/stop-the-steal new file mode 100644 index 0000000..69660a1 --- /dev/null +++ b/src/diary/entries/extra/stop-the-steal @@ -0,0 +1,7 @@ + +

    March for Trump

    +january 6, 2020
    +
    +
    +Today, the March for Trump resulted in a Capitol break-in. The photos are like something out of a videogame. I took them from Twitter, so I can't easily credit.
    +
    diff --git a/src/static/css/box.css b/src/static/css/box.css index 0f26d70..e0ba04e 100755 --- a/src/static/css/box.css +++ b/src/static/css/box.css @@ -59,42 +59,27 @@ body { .nav-bar { grid-area: 1 / 1 / 2 / 7; - display: flex; - flex-direction:column; - justify-content:flex-end; background-image: url(../img/ele/navbar.png); height: 86px; width: 800px; } .nav-index { grid-area: 1 / 2 / 2 / 3; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-game { grid-area: 1 / 3 / 2 / 4; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-diary { grid-area: 1 / 4 / 2 / 5; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-presskit { grid-area: 1 / 5 / 2 / 6; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } diff --git a/src/static/css/diary.css b/src/static/css/diary.css index 167690b..e5b8152 100755 --- a/src/static/css/diary.css +++ b/src/static/css/diary.css @@ -54,42 +54,27 @@ ul { list-style-position: inside; } } .nav-bar { grid-area: 1 / 1 / 2 / 7; - display: flex; - flex-direction:column; - justify-content:flex-end; background-image: url(../img/ele/navbar.png); height: 86px; width: 800px; } .nav-index { grid-area: 1 / 2 / 2 / 3; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-game { grid-area: 1 / 3 / 2 / 4; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-diary { grid-area: 1 / 4 / 2 / 5; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-presskit { grid-area: 1 / 5 / 2 / 6; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } diff --git a/src/static/css/feature.css b/src/static/css/feature.css index 54ce8ee..3e10ae2 100644 --- a/src/static/css/feature.css +++ b/src/static/css/feature.css @@ -54,42 +54,27 @@ ul { list-style-position: inside; } } .nav-bar { grid-area: 1 / 1 / 2 / 7; - display: flex; - flex-direction:column; - justify-content:flex-end; background-image: url(../img/ele/navbar.png); height: 86px; width: 800px; } .nav-index { grid-area: 1 / 2 / 2 / 3; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-game { grid-area: 1 / 3 / 2 / 4; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-diary { grid-area: 1 / 4 / 2 / 5; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-presskit { grid-area: 1 / 5 / 2 / 6; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } diff --git a/src/static/css/game.css b/src/static/css/game.css index caa2f6c..403a492 100644 --- a/src/static/css/game.css +++ b/src/static/css/game.css @@ -62,42 +62,27 @@ ul { list-style-position: inside; } .nav-bar { grid-area: 1 / 1 / 2 / 7; - display: flex; - flex-direction:column; - justify-content:flex-end; background-image: url(../img/ele/navbar.png); height: 86px; width: 800px; } .nav-index { grid-area: 1 / 2 / 2 / 3; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-game { grid-area: 1 / 3 / 2 / 4; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-diary { grid-area: 1 / 4 / 2 / 5; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-presskit { grid-area: 1 / 5 / 2 / 6; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } diff --git a/src/static/css/index.css b/src/static/css/index.css index cea4705..ee53ee7 100755 --- a/src/static/css/index.css +++ b/src/static/css/index.css @@ -53,42 +53,27 @@ a { } .nav-bar { grid-area: 1 / 1 / 2 / 7; - display: flex; - flex-direction:column; - justify-content:flex-end; background-image: url(../img/ele/navbar.png); height: 86px; width: 800px; } .nav-index { grid-area: 1 / 2 / 2 / 3; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-game { grid-area: 1 / 3 / 2 / 4; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-diary { grid-area: 1 / 4 / 2 / 5; - display: flex; - flex-direction: column; - justify-content: flex-end; padding-bottom: 3px; position: relative; } .nav-presskit { grid-area: 1 / 5 / 2 / 6; - display: flex; - flex-direction: column; - justify-content: flex-end; padding-bottom: 3px; position: relative; } diff --git a/src/static/css/presskit.css b/src/static/css/presskit.css index fa6e721..fd37a6f 100644 --- a/src/static/css/presskit.css +++ b/src/static/css/presskit.css @@ -26,9 +26,6 @@ ul { list-style-position: inside; } .whitespace { grid-area: 1 / 1 / 2 / 4; - display: flex; - flex-direction:column; - justify-content:center; align-items: center; background-color: #900C3F; } @@ -47,9 +44,6 @@ ul { list-style-position: inside; } .nav-grid { grid-area: 2 / 2 / 3 / 3; - display: flex; - flex-direction:column; - justify-content:flex-end; display: grid; grid-template-columns: auto repeat(4, 70px) auto; grid-template-rows: 90px; @@ -61,42 +55,27 @@ ul { list-style-position: inside; } .nav-bar { grid-area: 1 / 1 / 2 / 7; - display: flex; - flex-direction:column; - justify-content:flex-end; background-image: url(../img/ele/navbar.png); height: 86px; width: 800px; } .nav-index { grid-area: 1 / 2 / 2 / 3; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-game { grid-area: 1 / 3 / 2 / 4; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-diary { grid-area: 1 / 4 / 2 / 5; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-presskit { grid-area: 1 / 5 / 2 / 6; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } diff --git a/src/static/css/projects.css b/src/static/css/projects.css index 3b53ba5..1cb5680 100644 --- a/src/static/css/projects.css +++ b/src/static/css/projects.css @@ -55,42 +55,27 @@ ul { list-style-position: inside; } .nav-bar { grid-area: 1 / 1 / 2 / 7; - display: flex; - flex-direction:column; - justify-content:flex-end; background-image: url(../img/ele/navbar.png); height: 86px; width: 800px; } .nav-index { grid-area: 1 / 2 / 2 / 3; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-game { grid-area: 1 / 3 / 2 / 4; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-diary { grid-area: 1 / 4 / 2 / 5; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } .nav-presskit { grid-area: 1 / 5 / 2 / 6; - display: flex; - flex-direction:column; - justify-content:flex-end; padding-bottom: 3px; position: relative; } diff --git a/src/static/img/ent/internationalization_formatcsv.png b/src/static/img/ent/internationalization_formatcsv.png new file mode 100644 index 0000000..76f9bb1 Binary files /dev/null and b/src/static/img/ent/internationalization_formatcsv.png differ diff --git a/src/static/img/ent/internationalization_formatgame.png b/src/static/img/ent/internationalization_formatgame.png new file mode 100644 index 0000000..f29316d Binary files /dev/null and b/src/static/img/ent/internationalization_formatgame.png differ diff --git a/src/static/img/ent/internationalization_formatgame2.png b/src/static/img/ent/internationalization_formatgame2.png new file mode 100644 index 0000000..271c411 Binary files /dev/null and b/src/static/img/ent/internationalization_formatgame2.png differ diff --git a/src/static/img/ent/internationalization_formatscript.png b/src/static/img/ent/internationalization_formatscript.png new file mode 100644 index 0000000..9f38436 Binary files /dev/null and b/src/static/img/ent/internationalization_formatscript.png differ diff --git a/src/static/img/ent/internationalization_japanese.png b/src/static/img/ent/internationalization_japanese.png index 87a491a..b981196 100644 Binary files a/src/static/img/ent/internationalization_japanese.png and b/src/static/img/ent/internationalization_japanese.png differ diff --git a/src/static/img/fr/badge/0QLVhCv.png b/src/static/img/fr/badge/0QLVhCv.png new file mode 100644 index 0000000..28dca6e Binary files /dev/null and b/src/static/img/fr/badge/0QLVhCv.png differ diff --git a/src/static/img/fr/badge/1532000966.png b/src/static/img/fr/badge/1532000966.png new file mode 100644 index 0000000..59d4575 Binary files /dev/null and b/src/static/img/fr/badge/1532000966.png differ diff --git a/src/static/img/fr/badge/3ukZc7M.png.gif b/src/static/img/fr/badge/3ukZc7M.png.gif new file mode 100644 index 0000000..246f7ee Binary files /dev/null and b/src/static/img/fr/badge/3ukZc7M.png.gif differ diff --git a/src/static/img/fr/badge/4hr3mkF.png b/src/static/img/fr/badge/4hr3mkF.png new file mode 100644 index 0000000..048dbf1 Binary files /dev/null and b/src/static/img/fr/badge/4hr3mkF.png differ diff --git a/src/static/img/fr/badge/5jRjhgz.png b/src/static/img/fr/badge/5jRjhgz.png new file mode 100644 index 0000000..0005bfa Binary files /dev/null and b/src/static/img/fr/badge/5jRjhgz.png differ diff --git a/src/static/img/fr/badge/6sma760.png b/src/static/img/fr/badge/6sma760.png new file mode 100644 index 0000000..31d0854 Binary files /dev/null and b/src/static/img/fr/badge/6sma760.png differ diff --git a/src/static/img/fr/badge/9fWw4WY.png b/src/static/img/fr/badge/9fWw4WY.png new file mode 100644 index 0000000..235c484 Binary files /dev/null and b/src/static/img/fr/badge/9fWw4WY.png differ diff --git a/src/static/img/fr/badge/A6QWEY1.png b/src/static/img/fr/badge/A6QWEY1.png new file mode 100644 index 0000000..3a22a39 Binary files /dev/null and b/src/static/img/fr/badge/A6QWEY1.png differ diff --git a/src/static/img/fr/badge/ASvvnTt.png b/src/static/img/fr/badge/ASvvnTt.png new file mode 100644 index 0000000..3aafae8 Binary files /dev/null and b/src/static/img/fr/badge/ASvvnTt.png differ diff --git a/src/static/img/fr/badge/BQ0130S.png b/src/static/img/fr/badge/BQ0130S.png new file mode 100644 index 0000000..8039ccb Binary files /dev/null and b/src/static/img/fr/badge/BQ0130S.png differ diff --git a/src/static/img/fr/badge/Balloons.png b/src/static/img/fr/badge/Balloons.png new file mode 100644 index 0000000..e64aaf0 Binary files /dev/null and b/src/static/img/fr/badge/Balloons.png differ diff --git a/src/static/img/fr/badge/Cake.png b/src/static/img/fr/badge/Cake.png new file mode 100644 index 0000000..cd87235 Binary files /dev/null and b/src/static/img/fr/badge/Cake.png differ diff --git a/src/static/img/fr/badge/Candles.png b/src/static/img/fr/badge/Candles.png new file mode 100644 index 0000000..9650b36 Binary files /dev/null and b/src/static/img/fr/badge/Candles.png differ diff --git a/src/static/img/fr/badge/Cauldron1.gif b/src/static/img/fr/badge/Cauldron1.gif new file mode 100644 index 0000000..7324c83 Binary files /dev/null and b/src/static/img/fr/badge/Cauldron1.gif differ diff --git a/src/static/img/fr/badge/G130THg.png b/src/static/img/fr/badge/G130THg.png new file mode 100644 index 0000000..922b311 Binary files /dev/null and b/src/static/img/fr/badge/G130THg.png differ diff --git a/src/static/img/fr/badge/GgpglGe.png b/src/static/img/fr/badge/GgpglGe.png new file mode 100644 index 0000000..2180bb9 Binary files /dev/null and b/src/static/img/fr/badge/GgpglGe.png differ diff --git a/src/static/img/fr/badge/JkzY8tq.png b/src/static/img/fr/badge/JkzY8tq.png new file mode 100644 index 0000000..3ef9f7e Binary files /dev/null and b/src/static/img/fr/badge/JkzY8tq.png differ diff --git a/src/static/img/fr/badge/KBPvEjz.png b/src/static/img/fr/badge/KBPvEjz.png new file mode 100644 index 0000000..b765346 Binary files /dev/null and b/src/static/img/fr/badge/KBPvEjz.png differ diff --git a/src/static/img/fr/badge/Kp99Tes.png b/src/static/img/fr/badge/Kp99Tes.png new file mode 100644 index 0000000..3bdacb3 Binary files /dev/null and b/src/static/img/fr/badge/Kp99Tes.png differ diff --git a/src/static/img/fr/badge/LYPRI6F.png b/src/static/img/fr/badge/LYPRI6F.png new file mode 100644 index 0000000..5a8402e Binary files /dev/null and b/src/static/img/fr/badge/LYPRI6F.png differ diff --git a/src/static/img/fr/badge/PartyHat.png b/src/static/img/fr/badge/PartyHat.png new file mode 100644 index 0000000..73ef8ee Binary files /dev/null and b/src/static/img/fr/badge/PartyHat.png differ diff --git a/src/static/img/fr/badge/Pixel_Trash_for_Cash_v2.png b/src/static/img/fr/badge/Pixel_Trash_for_Cash_v2.png new file mode 100644 index 0000000..5da2aa3 Binary files /dev/null and b/src/static/img/fr/badge/Pixel_Trash_for_Cash_v2.png differ diff --git a/src/static/img/fr/badge/Qku4U0s.png b/src/static/img/fr/badge/Qku4U0s.png new file mode 100644 index 0000000..dddea66 Binary files /dev/null and b/src/static/img/fr/badge/Qku4U0s.png differ diff --git a/src/static/img/fr/badge/R1I3CHl.png b/src/static/img/fr/badge/R1I3CHl.png new file mode 100644 index 0000000..a23b3dc Binary files /dev/null and b/src/static/img/fr/badge/R1I3CHl.png differ diff --git a/src/static/img/fr/badge/Saa8Z5q.png b/src/static/img/fr/badge/Saa8Z5q.png new file mode 100644 index 0000000..daeb6df Binary files /dev/null and b/src/static/img/fr/badge/Saa8Z5q.png differ diff --git a/src/static/img/fr/badge/SjrQCts.png b/src/static/img/fr/badge/SjrQCts.png new file mode 100644 index 0000000..396af2b Binary files /dev/null and b/src/static/img/fr/badge/SjrQCts.png differ diff --git a/src/static/img/fr/badge/TPdrafh.png b/src/static/img/fr/badge/TPdrafh.png new file mode 100644 index 0000000..f946c4b Binary files /dev/null and b/src/static/img/fr/badge/TPdrafh.png differ diff --git a/src/static/img/fr/badge/TikpO8M.png b/src/static/img/fr/badge/TikpO8M.png new file mode 100644 index 0000000..a0dd078 Binary files /dev/null and b/src/static/img/fr/badge/TikpO8M.png differ diff --git a/src/static/img/fr/badge/UBTHVjT.png b/src/static/img/fr/badge/UBTHVjT.png new file mode 100644 index 0000000..5303bed Binary files /dev/null and b/src/static/img/fr/badge/UBTHVjT.png differ diff --git a/src/static/img/fr/badge/Ugwb1bB.png b/src/static/img/fr/badge/Ugwb1bB.png new file mode 100644 index 0000000..b09a370 Binary files /dev/null and b/src/static/img/fr/badge/Ugwb1bB.png differ diff --git a/src/static/img/fr/badge/Vsjjk1F.png b/src/static/img/fr/badge/Vsjjk1F.png new file mode 100644 index 0000000..64bf704 Binary files /dev/null and b/src/static/img/fr/badge/Vsjjk1F.png differ diff --git a/src/static/img/fr/badge/WvP-OOF-t1.png b/src/static/img/fr/badge/WvP-OOF-t1.png new file mode 100644 index 0000000..68c1216 Binary files /dev/null and b/src/static/img/fr/badge/WvP-OOF-t1.png differ diff --git a/src/static/img/fr/badge/WvP-OOF-t2.png b/src/static/img/fr/badge/WvP-OOF-t2.png new file mode 100644 index 0000000..144f9a0 Binary files /dev/null and b/src/static/img/fr/badge/WvP-OOF-t2.png differ diff --git a/src/static/img/fr/badge/XUdWkkW.gif b/src/static/img/fr/badge/XUdWkkW.gif new file mode 100644 index 0000000..385f63b Binary files /dev/null and b/src/static/img/fr/badge/XUdWkkW.gif differ diff --git a/src/static/img/fr/badge/Y6Uxj5O.png b/src/static/img/fr/badge/Y6Uxj5O.png new file mode 100644 index 0000000..d5657e6 Binary files /dev/null and b/src/static/img/fr/badge/Y6Uxj5O.png differ diff --git a/src/static/img/fr/badge/ZVJmarp.png b/src/static/img/fr/badge/ZVJmarp.png new file mode 100644 index 0000000..107405f Binary files /dev/null and b/src/static/img/fr/badge/ZVJmarp.png differ diff --git a/src/static/img/fr/badge/aFpsZk8.png b/src/static/img/fr/badge/aFpsZk8.png new file mode 100644 index 0000000..bc94532 Binary files /dev/null and b/src/static/img/fr/badge/aFpsZk8.png differ diff --git a/src/static/img/fr/badge/aaDmWw4.png b/src/static/img/fr/badge/aaDmWw4.png new file mode 100644 index 0000000..6d78f33 Binary files /dev/null and b/src/static/img/fr/badge/aaDmWw4.png differ diff --git a/src/static/img/fr/badge/b1AOHoJ.gif b/src/static/img/fr/badge/b1AOHoJ.gif new file mode 100644 index 0000000..df29273 Binary files /dev/null and b/src/static/img/fr/badge/b1AOHoJ.gif differ diff --git a/src/static/img/fr/badge/berniecg_copy.gif b/src/static/img/fr/badge/berniecg_copy.gif new file mode 100644 index 0000000..02009b4 Binary files /dev/null and b/src/static/img/fr/badge/berniecg_copy.gif differ diff --git a/src/static/img/fr/badge/bm199ed.png b/src/static/img/fr/badge/bm199ed.png new file mode 100644 index 0000000..3afa2f5 Binary files /dev/null and b/src/static/img/fr/badge/bm199ed.png differ diff --git a/src/static/img/fr/badge/d2Sm0UO.png b/src/static/img/fr/badge/d2Sm0UO.png new file mode 100644 index 0000000..0a77388 Binary files /dev/null and b/src/static/img/fr/badge/d2Sm0UO.png differ diff --git a/src/static/img/fr/badge/dqixKfS.png b/src/static/img/fr/badge/dqixKfS.png new file mode 100644 index 0000000..a30508e Binary files /dev/null and b/src/static/img/fr/badge/dqixKfS.png differ diff --git a/src/static/img/fr/badge/ebTXM7P.png b/src/static/img/fr/badge/ebTXM7P.png new file mode 100644 index 0000000..8a66964 Binary files /dev/null and b/src/static/img/fr/badge/ebTXM7P.png differ diff --git a/src/static/img/fr/badge/fHfgR7b.png b/src/static/img/fr/badge/fHfgR7b.png new file mode 100644 index 0000000..8557db9 Binary files /dev/null and b/src/static/img/fr/badge/fHfgR7b.png differ diff --git a/src/static/img/fr/badge/gmc2rJz.png b/src/static/img/fr/badge/gmc2rJz.png new file mode 100644 index 0000000..7a3858b Binary files /dev/null and b/src/static/img/fr/badge/gmc2rJz.png differ diff --git a/src/static/img/fr/badge/hogZwcV.png b/src/static/img/fr/badge/hogZwcV.png new file mode 100644 index 0000000..b58cca1 Binary files /dev/null and b/src/static/img/fr/badge/hogZwcV.png differ diff --git a/src/static/img/fr/badge/j8UN9lFU_o.png b/src/static/img/fr/badge/j8UN9lFU_o.png new file mode 100644 index 0000000..8f3cc73 Binary files /dev/null and b/src/static/img/fr/badge/j8UN9lFU_o.png differ diff --git a/src/static/img/fr/badge/jp31RUVs_o.png b/src/static/img/fr/badge/jp31RUVs_o.png new file mode 100644 index 0000000..1c53e70 Binary files /dev/null and b/src/static/img/fr/badge/jp31RUVs_o.png differ diff --git a/src/static/img/fr/badge/jy44Pp7.png b/src/static/img/fr/badge/jy44Pp7.png new file mode 100644 index 0000000..8ba41b1 Binary files /dev/null and b/src/static/img/fr/badge/jy44Pp7.png differ diff --git a/src/static/img/fr/badge/kEdMEAr.png b/src/static/img/fr/badge/kEdMEAr.png new file mode 100644 index 0000000..f9a684c Binary files /dev/null and b/src/static/img/fr/badge/kEdMEAr.png differ diff --git a/src/static/img/fr/badge/l3XfYkQ.gif b/src/static/img/fr/badge/l3XfYkQ.gif new file mode 100644 index 0000000..ce2ac96 Binary files /dev/null and b/src/static/img/fr/badge/l3XfYkQ.gif differ diff --git a/src/static/img/fr/badge/lc8YzxOr_o.png b/src/static/img/fr/badge/lc8YzxOr_o.png new file mode 100644 index 0000000..6a71e7d Binary files /dev/null and b/src/static/img/fr/badge/lc8YzxOr_o.png differ diff --git a/src/static/img/fr/badge/nZVpG4qA_o.png b/src/static/img/fr/badge/nZVpG4qA_o.png new file mode 100644 index 0000000..a58ab9a Binary files /dev/null and b/src/static/img/fr/badge/nZVpG4qA_o.png differ diff --git a/src/static/img/fr/badge/ooqpaDf.png b/src/static/img/fr/badge/ooqpaDf.png new file mode 100644 index 0000000..882f772 Binary files /dev/null and b/src/static/img/fr/badge/ooqpaDf.png differ diff --git a/src/static/img/fr/badge/p1lH9gN.png b/src/static/img/fr/badge/p1lH9gN.png new file mode 100644 index 0000000..d098ec0 Binary files /dev/null and b/src/static/img/fr/badge/p1lH9gN.png differ diff --git a/src/static/img/fr/badge/q2tTUld.png b/src/static/img/fr/badge/q2tTUld.png new file mode 100644 index 0000000..8858baa Binary files /dev/null and b/src/static/img/fr/badge/q2tTUld.png differ diff --git a/src/static/img/fr/badge/qjHFcDc3_o.png b/src/static/img/fr/badge/qjHFcDc3_o.png new file mode 100644 index 0000000..96c71e8 Binary files /dev/null and b/src/static/img/fr/badge/qjHFcDc3_o.png differ diff --git a/src/static/img/fr/badge/rlMOyL9.png b/src/static/img/fr/badge/rlMOyL9.png new file mode 100644 index 0000000..5f6c7bc Binary files /dev/null and b/src/static/img/fr/badge/rlMOyL9.png differ diff --git a/src/static/img/fr/badge/t5oWqxC.gif b/src/static/img/fr/badge/t5oWqxC.gif new file mode 100644 index 0000000..2b2c739 Binary files /dev/null and b/src/static/img/fr/badge/t5oWqxC.gif differ diff --git a/src/static/img/fr/badge/tcCHz91.png b/src/static/img/fr/badge/tcCHz91.png new file mode 100644 index 0000000..ba5d618 Binary files /dev/null and b/src/static/img/fr/badge/tcCHz91.png differ diff --git a/src/static/img/fr/badge/uC4Bb27.png b/src/static/img/fr/badge/uC4Bb27.png new file mode 100644 index 0000000..5c79dc6 Binary files /dev/null and b/src/static/img/fr/badge/uC4Bb27.png differ diff --git a/src/static/img/fr/badge/vhzV2z9.png b/src/static/img/fr/badge/vhzV2z9.png new file mode 100644 index 0000000..d462ade Binary files /dev/null and b/src/static/img/fr/badge/vhzV2z9.png differ diff --git a/src/static/img/fr/badge/vnh3Mff.png b/src/static/img/fr/badge/vnh3Mff.png new file mode 100644 index 0000000..156d32d Binary files /dev/null and b/src/static/img/fr/badge/vnh3Mff.png differ diff --git a/src/static/img/fr/badge/w6nm2ozw_o.png b/src/static/img/fr/badge/w6nm2ozw_o.png new file mode 100644 index 0000000..cd92572 Binary files /dev/null and b/src/static/img/fr/badge/w6nm2ozw_o.png differ diff --git a/src/static/img/fr/badge/wBDxnV5.png b/src/static/img/fr/badge/wBDxnV5.png new file mode 100644 index 0000000..68035ab Binary files /dev/null and b/src/static/img/fr/badge/wBDxnV5.png differ diff --git a/src/static/img/fr/badge/wpbQeQK.png b/src/static/img/fr/badge/wpbQeQK.png new file mode 100644 index 0000000..93c3abb Binary files /dev/null and b/src/static/img/fr/badge/wpbQeQK.png differ diff --git a/src/static/img/fr/badge/wvpfire.png b/src/static/img/fr/badge/wvpfire.png new file mode 100644 index 0000000..af7a62d Binary files /dev/null and b/src/static/img/fr/badge/wvpfire.png differ diff --git a/src/static/img/fr/badge/wvpwind.png b/src/static/img/fr/badge/wvpwind.png new file mode 100644 index 0000000..5e93bd0 Binary files /dev/null and b/src/static/img/fr/badge/wvpwind.png differ diff --git a/src/static/img/fr/badge/xDr8a1W.png b/src/static/img/fr/badge/xDr8a1W.png new file mode 100644 index 0000000..d599a6c Binary files /dev/null and b/src/static/img/fr/badge/xDr8a1W.png differ diff --git a/src/static/img/fr/badge/xQhJ1xN.png b/src/static/img/fr/badge/xQhJ1xN.png new file mode 100644 index 0000000..927dab6 Binary files /dev/null and b/src/static/img/fr/badge/xQhJ1xN.png differ diff --git a/src/static/img/fr/badge/xtPgVlw.png b/src/static/img/fr/badge/xtPgVlw.png new file mode 100644 index 0000000..6c0dafa Binary files /dev/null and b/src/static/img/fr/badge/xtPgVlw.png differ diff --git a/src/static/img/fr/badge/yNi4cd2.png b/src/static/img/fr/badge/yNi4cd2.png new file mode 100644 index 0000000..5996be6 Binary files /dev/null and b/src/static/img/fr/badge/yNi4cd2.png differ diff --git a/src/static/img/fr/badge/yaVmX6u.png b/src/static/img/fr/badge/yaVmX6u.png new file mode 100644 index 0000000..e831c71 Binary files /dev/null and b/src/static/img/fr/badge/yaVmX6u.png differ diff --git a/src/static/img/fr/badge/z9l1QrF.png b/src/static/img/fr/badge/z9l1QrF.png new file mode 100644 index 0000000..0d6b79c Binary files /dev/null and b/src/static/img/fr/badge/z9l1QrF.png differ diff --git a/src/static/img/fr/badge/zizf7QON_o.png b/src/static/img/fr/badge/zizf7QON_o.png new file mode 100644 index 0000000..c134628 Binary files /dev/null and b/src/static/img/fr/badge/zizf7QON_o.png differ diff --git a/src/static/img/fr/comm/BJ41FcK.gif b/src/static/img/fr/comm/BJ41FcK.gif new file mode 100644 index 0000000..85a37ba Binary files /dev/null and b/src/static/img/fr/comm/BJ41FcK.gif differ diff --git a/src/static/img/fr/comm/Lqh2ToP.gif b/src/static/img/fr/comm/Lqh2ToP.gif new file mode 100644 index 0000000..d5e1cb5 Binary files /dev/null and b/src/static/img/fr/comm/Lqh2ToP.gif differ diff --git a/src/static/img/fr/comm/XRywlxo.png b/src/static/img/fr/comm/XRywlxo.png new file mode 100644 index 0000000..4e18748 Binary files /dev/null and b/src/static/img/fr/comm/XRywlxo.png differ diff --git a/src/static/img/fr/comm/dNdPm9U.gif b/src/static/img/fr/comm/dNdPm9U.gif new file mode 100644 index 0000000..9dffffe Binary files /dev/null and b/src/static/img/fr/comm/dNdPm9U.gif differ diff --git a/src/static/img/fr/comm/upFf3lM.gif b/src/static/img/fr/comm/upFf3lM.gif new file mode 100644 index 0000000..2b3f71e Binary files /dev/null and b/src/static/img/fr/comm/upFf3lM.gif differ diff --git a/src/views/box.tpl b/src/views/box.tpl index 965b2da..704c7de 100644 --- a/src/views/box.tpl +++ b/src/views/box.tpl @@ -1,70 +1,9 @@ % rebase('frame.tpl') -
    +


    How did you find this page?
    It's my secret page.
    -
    -

    Website To-Do

    -
      -
    • Write some diary entries
    • -
    • Make sure their dates + filenames match
    • -
    • Make sure their tags are formatted correctly
    • -
    • Proofread
    • -
    • Make sure their formatting is consistent
    • -
    • ALSO
    • -
    • make presskit page decent
    • -
    • update art assets
    • -
    -
    -
    -

    Planning Articles

    -
      -
    • 8/6 - blessfrey
    • -
    • 8/20 - pixel joy
    • -
    • 9/1 - DIARY
    • -
    • 9/3 - jam
    • -
    • 9/17 - coroutines
    • -
    • 10/1 - DIARY
    • -
    • 10/15 - making of blessfrey.me
    • -
    • 10/29 - Japanese
    • -
    • 11/1 - DIARY
    • -
    • 11/12 - skills + super methods
    • -
    • 11/26 - pretendOS
    • -
    • 12/1 - DIARY
    • -
    • 12/10 - AI diagram
    • -
    • 12/24 - AI code - https://twitter.com/lilchimchooree/status/1206399601881812994
    • -
    • 1/1- DIARY
    • -
    • 1/7 - inventory system diagram
    • -
    • 1/21 - Graphics
    • -
    • 2/4 - web design resources
    • -
    • 2/18 - GDC
    • -
    • 2/1 - DIARY
    • -
    • 3/1 - DIARY
    • -
    • 4/1 - DIARY
    • -
    -
    -
    -

    Try to Do...

    -

    Weekly, Monthly

    -
      -
    • Keep monthly journal up to date
    • -
    • Add an article every week or two
    • -
    • Convert old infographics into articles
    • -
    -

    Sometime

    -
      -
    • Update Trello and share it
    • -
    • Diary - Add snippet art assets
    • -
    • Game - Add slideshow for story
    • -
    • Graphics - Concept Art
    • -
    • Graphics - Character Sheets
    • -
    • Graphics - Screenshots, GIFs
    • -
    • Graphics - Music
    • -
    • Graphics - Trailer
    • -
    • Just...better art and writing for everything...
    • -
    -

    Articles, Resources

      @@ -75,97 +14,5 @@


    -

    Books, Plays

    -
      -
    • Beowulf
    • -
    • Candide
    • -
    • The Canterbury Tales
    • -
    • The Divine Comedy - Inferno
    • -
    • Dracula
    • -
    • The Faerie Queene
    • -
    • The Flowers of Evil
    • -
    • Gulliver's Travels
    • -
    • Iliad
    • -
    • Metamorphoses
    • -
    • Odyssey
    • -
    • Paradise Lost
    • -
    • The Waste Land
    • -
    -
    -
    -

    Shopping

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Regular PriceSale PriceBrandProductURL
    $24$12 on Primer DayUrban DecayEyeshadow Primer Potionhttps://www.urbandecay.com/eyeshadow-primer-potion/UD515.html?dwvar_UD515_color=Original
    $30$21 on Black Friday, same + minis basket week afterBiossanceSqualane + Zinc Sheer Mineral Sunscreenhttps://biossance.com/collections/all/products/squalane-zinc-sheer-mineral-sunscreen-spf30
    $15.99???NeutrogenaSheer Zinc Face Dry Touch Sunscreen SPF 50https://www.ulta.com/sheer-zinc-face-dry-touch-sunscreen-spf-50?productId=xlsImpprod15721137
    $6.99$0.97Crystal DynamicsLegacy of Kain: Defiancehttps://www.gog.com/game/legacy_of_kain_defiance
    $6.99$0.97Crystal DynamicsLegacy of Kain: Blood Omen 2https://www.gog.com/game/legacy_of_kain_blood_omen_2
    $59.99$29.99ObsidianTHE OUTER WORLDShttps://www.gog.com/game/the_outer_worlds
    $59.99???PlatinumGamesASTRAL CHAINhttps://www.humblebundle.com/store/astral-chain
    $59.99???NintendoSuper Mario Odysseyhttps://www.humblebundle.com/store/super-mario-odyssey
    $59.99???NintendoPokémon Mystery Dungeon™: Rescue Team DX https://www.humblebundle.com/store/pokemon-mystery-dungeon-rescue-team-dx
    -
    -
    +
    diff --git a/src/views/contact.tpl b/src/views/contact.tpl index d88fbaa..c45fc55 100644 --- a/src/views/contact.tpl +++ b/src/views/contact.tpl @@ -1,13 +1,13 @@ % rebase('frame.tpl') -
    -

    contact

    -

    general + business

    - I would love to hear from you once blessfrey.me is functional and my dev email is set up. Won't be long.
    +
    +

    chimchooree

    +

    contact - general + business

    + Reach me through Twitter as @lilchimchooree or Discord as chimchooree#7250.

    - You can always reach me through Twitter as @lilchimchooree.
    -
    - Press can snag a copy of my presskit at the presskit page. -

    +

    a few personal pages

    +
      +
    • Books
    • +
    diff --git a/upload.sh b/upload.sh new file mode 100755 index 0000000..3580d0e --- /dev/null +++ b/upload.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +scp -r src/ vps: +ssh vps diff --git a/vps/201210 b/vps/201210 new file mode 100644 index 0000000..6ea3c37 --- /dev/null +++ b/vps/201210 @@ -0,0 +1,35 @@ + +

    slimeAI - state transition diagram

    +december 10, 2020
    +#ai #programming
    +
    +
    +blessfrey's slimes use finite state machines. Finite state machines (FSM) are models with a finite number of states that either decide to generate output or transition to a new state based on input. They can only be in one state at a time.
    +
    +
    +

    why use a finite state machine?


    +Because they are simple and flexible, while still allowing for interesting behavior. FSMs reflect our own mental model of how slimes behave (attack mode, wander mode, sleep mode, etc). These different modes or states are written as manageable chunks that easy to code, debug, update, and refactor. It's also efficient with processor time, since the behavior is abstracted to basic conditionals.
    +
    +A state can be as broad or specific as you need, so long as it's granular. So they can be more easily debugged and swapped out with one another, it's a good idea to have one entry point and one exit point for all your states.
    +
    +Of course, since FSMs can be used for anything with states and transitions. You can think of specific menus, mechanics or even your entire game in terms of states. I'm just using them here for understanding the AI for my slime monster.
    +
    +
    +

    designing AI


    +Planning ahead is extra important, since any dead-ends will halt your slime. I used a state transition diagram to design the slime's AI. In the diagram, circles represent states and arrows represent transitions, triggered by some kind of event. I marked the initial state with a star, but Buckland recommends a double circle.
    +
    +The slime is a simple creature. It idles, chases anything that gets too close, and attacks until its target dies. Here's the diagram version of that:
    +
    +(image: a state transition diagram for slime ai.)
    +
    +
    +The states are Idle, Choose Target, Attack, and Move to Target. The initial state is Idle.
    +
    +If there's a valid target, the slime enters Choose Target. If there's no longer a valid target, it returns to Idle. If it successfully gets a target, it begins moving to target. If the target becomes invalid, it returns to Idle. Once the target is in attack range, it enters Attack. If the foe moves out of range, it returns to Move to Target. If the target becomes invalid, it returns to Choose Target. And the cycle continues.
    +
    +No matter how you follow the arrows, there are no dead-ends and all states can be reached eventually, so it'll work okay when it's implemented as code. <3
    +
    +
    +

    reference


    +Programming Game AI by Example by Mat Buckland. It's an easy to understand introduction to game math + AI concepts. The code examples are in C++, but they are still useful for understanding the underlying principles. I didn't even know where to begin before I started reading and it got me pretty decent groundwork for AI creatures with different behavior that reacts to the players.<3
    +
    diff --git a/vps/diary/201210 (copy) b/vps/diary/201210 (copy) new file mode 100644 index 0000000..6ea3c37 --- /dev/null +++ b/vps/diary/201210 (copy) @@ -0,0 +1,35 @@ + +

    slimeAI - state transition diagram

    +december 10, 2020
    +#ai #programming
    +
    +
    +blessfrey's slimes use finite state machines. Finite state machines (FSM) are models with a finite number of states that either decide to generate output or transition to a new state based on input. They can only be in one state at a time.
    +
    +
    +

    why use a finite state machine?


    +Because they are simple and flexible, while still allowing for interesting behavior. FSMs reflect our own mental model of how slimes behave (attack mode, wander mode, sleep mode, etc). These different modes or states are written as manageable chunks that easy to code, debug, update, and refactor. It's also efficient with processor time, since the behavior is abstracted to basic conditionals.
    +
    +A state can be as broad or specific as you need, so long as it's granular. So they can be more easily debugged and swapped out with one another, it's a good idea to have one entry point and one exit point for all your states.
    +
    +Of course, since FSMs can be used for anything with states and transitions. You can think of specific menus, mechanics or even your entire game in terms of states. I'm just using them here for understanding the AI for my slime monster.
    +
    +
    +

    designing AI


    +Planning ahead is extra important, since any dead-ends will halt your slime. I used a state transition diagram to design the slime's AI. In the diagram, circles represent states and arrows represent transitions, triggered by some kind of event. I marked the initial state with a star, but Buckland recommends a double circle.
    +
    +The slime is a simple creature. It idles, chases anything that gets too close, and attacks until its target dies. Here's the diagram version of that:
    +
    +(image: a state transition diagram for slime ai.)
    +
    +
    +The states are Idle, Choose Target, Attack, and Move to Target. The initial state is Idle.
    +
    +If there's a valid target, the slime enters Choose Target. If there's no longer a valid target, it returns to Idle. If it successfully gets a target, it begins moving to target. If the target becomes invalid, it returns to Idle. Once the target is in attack range, it enters Attack. If the foe moves out of range, it returns to Move to Target. If the target becomes invalid, it returns to Choose Target. And the cycle continues.
    +
    +No matter how you follow the arrows, there are no dead-ends and all states can be reached eventually, so it'll work okay when it's implemented as code. <3
    +
    +
    +

    reference


    +Programming Game AI by Example by Mat Buckland. It's an easy to understand introduction to game math + AI concepts. The code examples are in C++, but they are still useful for understanding the underlying principles. I didn't even know where to begin before I started reading and it got me pretty decent groundwork for AI creatures with different behavior that reacts to the players.<3
    +
    diff --git a/vps/diary/entries/200806 b/vps/diary/entries/200806 new file mode 100644 index 0000000..6f6bdd4 --- /dev/null +++ b/vps/diary/entries/200806 @@ -0,0 +1,21 @@ + +

    what is blessfrey?

    +august 6, 2020
    +#gamedescription
    +
    +blessfrey is a 2D action RPG developed for PC by chimchooree.
    +
    + + (image: Lots of Angels and other characters at a shopping center) +
    +
    +The game is designed to pit your skill + creativity against a series of combat + puzzle challenges while exploring the depths of the downtown dungeon.
    +
    +Class progression is freeform, and virtually no decision is permanent. At character creation, you will choose a permanent First Class, but you can unlock several new classes for multiclassing through gameplay. Through swapping out Second Classes, you can find a combination to express your playstyle.
    +
    +Each class has its own style of skills associated with it. Skills are individual powers gained through gameplay which give specific effects according to their rules. Your skillbar only has 8 skill slots and can only be edited in safe areas. The challenge comes from building winning strategies + synergies against the next area.
    +
    +Skills are gained through exploration of the game world. As you encounter enemies, meet people, and reach new areas, you will translate those experiences into new skills. There are multiple paths to learning, so you can focus on parts of the game you prefer.
    +
    +blessfrey has been lots of fun to work on. I hope you enjoy it once a demo and eventually a game drops.
    +
    diff --git a/vps/diary/entries/200820 b/vps/diary/entries/200820 new file mode 100644 index 0000000..4ad4f7f --- /dev/null +++ b/vps/diary/entries/200820 @@ -0,0 +1,13 @@ + +

    free pixel font

    +august 20, 2020
    +#assets
    +
    +pixel joy is a small, round sans-serif pixel font, made using FontStruct's FontStructor for an old version of blessfrey. Freely use and edit for your personal and commercial projects. No credit needed.
    +
    +Download it from FontStruct.
    +
    +
    image: pixel joy font preview

    +
    +Font released under public domain. Sample text in the preview image is from Imogen Heap's "Pocket Sun," and the colors are from Adigun Polack's AAP-64 palette. :)
    +
    diff --git a/vps/diary/entries/200901 b/vps/diary/entries/200901 new file mode 100644 index 0000000..e714b75 --- /dev/null +++ b/vps/diary/entries/200901 @@ -0,0 +1,87 @@ + +

    august 2020: new server, new site

    +september 1, 2020
    +#apache #css #html #nginx #php #server #website
    +
    +

    tuesday, august 4

    + +
    +

    wednesday, august 5

    + +
    +

    thursday, august 6

    + +
    +

    friday, august 7

    + +
    +

    saturday, august 8

    + +
    +

    sunday, august 9

    + +
    +

    monday, august 10

    + +
    +

    saturday, august 15

    + +
    +

    monday, august 17

    + +
    +

    august 18 - august 21

    + +
    +

    saturday, august 22

    + +
    +

    sunday, august 23

    + +
    +

    monday, august 24

    + +
    +

    tuesday, august 25

    + +
    +

    wednesday, august 26

    + +
    diff --git a/vps/diary/entries/200903 b/vps/diary/entries/200903 new file mode 100644 index 0000000..4539c38 --- /dev/null +++ b/vps/diary/entries/200903 @@ -0,0 +1,76 @@ + +

    my first game jam - #weeklygamejam

    +september 3, 2020
    +#gamejam
    +
    +WeeklyGameJam is a weekly theme-based game jam hosted through itch.io. It's fairly laid-back for a jam, giving you a full week's time, allowing for premade/stock assets and code, and being understanding towards late submissions. Most people make videogames, but any kind of game is allowed. At the end of the week, streamers will play and critique the submissions while the devs hang out in their chatrooms.
    +
    +
    (image: Key art of Elwell and Small Thing, buried in dogs)

    +
    +
    +

    small thing that makes things

    +
    +I participated in Week 85 under the theme Offspring, submitting my game on February 27, 2019. My game was Small Thing That Makes Things, an adventure platformer. You can play it on itch.io.
    +
    +You play as Hamish T. Elwell, the hero accountant of an overcrowded animal shelter, investigating the recent explosion of the local stray population. You can walk, jump on platforms, collect items, and chat with NPCs. There's multiple endings, depending on your choices.
    +
    +
    +

    positives

    +
    +For a week-made game, I think STTMT is pretty cute, and I'm pretty happy with it.:)
    +
    +I actually finished a game, and someone actually finished playing it on a stream. That's really cool, even if STTMT isn't all that good. The deadline forced me to make final decisions, complete features, and move on, and there's a lot of value in that.
    +
    +The short time-frame forced me to get around to every aspect of game development, many of which I had never done before. I had to learn how to export a Godot project, upload an HTML5 game to itch, and make sure the exported game was complete and playable. Lots of the features were first-times for me, too. I've never written code for platformer movements or moving cameras. This also was the first time I've really gotten branching and conditional dialog working in Godot, which was a skill I immediately applied to blessfrey.
    +
    +
    +

    mistakes

    +
    +I recolored OPP's pixel art and lost the high contrast for the rock ledges. They blend into the rocky background, so you can't tell you can jump on them. I didn't even notice until Joshua McLean pointed this out during his stream. Having more eyes on your game is so important.
    +
    +Also the level design is just not interesting. I spent lots of time on the choices and adventure game aspects, while the platforming as an extreme afterthought. It's a game jam, though, what do you expect?
    +
    +I took the easy way out with animation. I might have learned more working from scratch, but modifying OPP's sprites to suit my character designs was way faster when I was already struggling to finish on time.
    +
    +
    +

    screenshots + progression

    +
    + + (image: Elwell and Small Thing in a jumble of dogs) +
    +Experimenting with Small Thing's summoning mechanic. In this version, the characters are just blocks with collision that can move around the flat, empty world with WASD.
    +

    + + (gif: Elwell rides a broken-physics dog across the valley) +
    +The dog spawning physics was (and still is) really broken, so dogs go flying pretty frequently. It was reliable enough in this version to be used as a moving platform.
    +

    + + (image: Elwell watches the rainfall of dogs from his window) +
    +Dogs rain down upon Elwell's animal shelter in the finished version.
    +

    + + (image: Dialog) +
    +Dialog between Elwell and his boss.
    +
    +
    +
    +

    conclusion

    +
    +If you're looking for a jam to jump into, WeeklyGameJam is a cute one to try. You aren't too rushed, you get to watch people play your game, you get useful criticism, and the community is pretty chill. The themes are always inspiring, too.<3
    +
    +
    +

    credits

    + +
    diff --git a/vps/diary/entries/200917 b/vps/diary/entries/200917 new file mode 100644 index 0000000..314a064 --- /dev/null +++ b/vps/diary/entries/200917 @@ -0,0 +1,81 @@ + +

    coroutines in godot engine

    +september 17, 2020
    +#programming
    +
    +Coroutines are functions that, instead of running to completion, can yield until certain criteria are met. Godot Engine supports coroutines through yield ( Object object=null, String signal=""), resume, and the GDScriptFunctionState object.
    +
    +

    why use a coroutine?

    +
    +Coroutines allow for scripted game scenarios that respond dynamically to the player and the changing game world. They let you bounce between functions, step-by-step, and respond to interruptions. This means functions can be automatically called at the completion of other functions, animations, player actions, in-game events, or timers. Add in interruptions and conditionals, and you have a tool for building a responsive game world.
    +
    +
    +

    stoplight example

    +
    +As a basic example of coroutines in Godot Engine, I made a stoplight. Follow along with my code on GitLab.
    +
    +In my example, the light changes every few seconds, going from green, yellow, then finally red. The light changes immediately if the Walk Button is pressed. This project demonstrates methods that can wait, resume, and be affected through player action.
    +
    +
    + + (gif: demonstration) +
    +
    +
    +
    +

    how does it work?

    +
    +

    node hierarchy

    +
    +(image: node hierarchy - Root is a node named Main. It's children are TextureRect BG, AnimatedSprite Stoplight, Sprite WalkButton, and a Label. Stoplight's child is a Sprite. WalkButton's child is a TextureButton.)
    +
    +
    +
    +I have a TextureRect background, an AnimatedSprite stoplight, a Sprite walk button with a TextureButton, and a label for displaying a timer. Since this is a simple example, most of the code is attached to the root. It's better to have code closer to where it's being used and to watch your separation of concerns in real projects, though.
    +
    +
    +

    animation

    +
    +
    +(image: the AnimatedSprite Stoplight has 4 animations - default (which is no light), green, red, and yellow.)
    +

    +The light is changed by setting its animation to one of these options. Each is one-frame - just the stoplight with the one or none of the lights colored in.
    +
    +
    +

    the code

    +
    +This project has two scripts: Main.gd, which is attached to the root node, and Label.gd, which is attached to the Label.
    +
    +Main.gd - code available on GitLab
    +
    +(image: Main script.)
    +
    +
    +Label.gd - code available on GitLab
    +
    +(image: Label script.)
    +
    +
    +
    +

    how the code works

    +
    +At _ready(), wait() is assigned to the GDScriptFunctionState result and is called for the first color, green. _ready() yields until the given function wait() is completed.
    +
    +The wait method yields for the given amount of seconds then sets the stoplight to the given color.
    +
    +At wait()'s completion, _ready() calls wait() for yellow, then red. Each is called one at a time, waiting for the color to complete before moving on.
    +
    +
    +

    interrupting the stoplight

    +
    +The Wait Button interrupts the wait times between colors. Before _ready() yields, it connects the 'pressed' signal on the Wait Button.
    +
    +If the Wait Button is clicked during wait()'s yield, the GDScriptFunctionState result resumes immediately, ignoring wait()'s yield timer. This time, result has a string arg 'interrupted on green', so it will print the result, change the stoplight's color, then print 'done: green'. The wait method is complete, so _ready() resumes and calls wait() for the next color.
    +
    +
    +

    applications

    +
    +The outcomes in this example be swapped out for anything. I use coroutines in blessfrey's skills to manage the flow of phases from activation, different phases of effects, cooldown, and interactions with any counters. I also use it in the basic weapon attack so the character continuously swings at the rate of his attack speed until he cancels, uses a skill, or moves. It could also be used for something like cars that stop and honk when the player walks in front of them and drive off once the path is clear.
    +
    +Coroutines enable lots of practical ways to improve the flow and interactivity of your game, so just keep experimenting.
    +
    diff --git a/vps/diary/entries/201001 b/vps/diary/entries/201001 new file mode 100644 index 0000000..d71229e --- /dev/null +++ b/vps/diary/entries/201001 @@ -0,0 +1,37 @@ + +

    september 2020: bye php, hello bottle

    +october 1, 2020
    +#bottle #css #git #html #regex #regularexpressions #website
    +
    +

    wednesday, september 2

    + +
    +

    friday, september 18

    + +
    +

    friday, september 25

    + +
    +

    saturday, september 26

    + +
    +

    wednesday, september 30

    + +
    diff --git a/vps/diary/entries/201015 b/vps/diary/entries/201015 new file mode 100644 index 0000000..1e95006 --- /dev/null +++ b/vps/diary/entries/201015 @@ -0,0 +1,68 @@ + +

    making of blessfrey.me

    +october 15, 2020
    +#bottle #css #html #simpletemplate #webdesign #webdev
    +
    +blessfrey.me is a personal website I use to showcase projects + blog my process. I originally wrote it in PHP, but now it's written in Bottle, a Python web framework.
    +
    +
    +

    why not use a premade blogging platform like WordPress?


    +blessfrey.me's needs are fairly simple - just some static pages and a blog page. Generalized blogging platforms are overkill. I don't need support for multiple users, localization, e-commerce, and so on. Unused features only bog down the website, potentially contributing to poor performance + security vulnerabilities.
    +
    +Also, it's just fun to write my own. I'm learning a lot as I take my website from initial sketches, to Hello World, to various prototypes, to something polished enough to show my friends. Also, since it can be considered a programming portfolio, it just makes sense that it itself should be something I programmed.
    +
    +
    +

    why Bottle?


    +I originally wrote blessfrey.me in PHP. I switched to Bottle after looking for a templating engine. Bottle comes with SimpleTemplate and can do everything PHP can do but faster + with less verbosity. Plus, you get to write in Python, which is always fun.
    +
    +
    +

    how does blessfrey.me work?


    +

    SimpleTemplate


    +Instead of a static collection of HTML pages on my server, blessfrey.me's pages are constructed from SimpleTemplate templates and filled in using a Bottle script upon request.
    +
    +Every page uses the frame template below, so the basic skeleton is consistent and code for repetitive elements only has to exist in one place. Each page's content is made unique by bringing in a different template as {{!base}}. (Double curly brackets refer to variables, and exclamation marks disable escaping.)
    +
    +(image: basic template code.)
    +
    +(The code can be found on Pastebin.)
    +
    +The header template below (brought in at % include('header.tpl')) has some variables, too, which are supplied by the Bottle script. If Bottle doesn't provide a title, it defaults to 'blessfrey.me.' Variables can also be used in paths and URLs.
    +
    +(image: header template code.)
    +
    +(The code can be found on Pastebin.)
    +
    +You can insert Python code into the templates for dynamic pages. Below is an excerpt of the template for the diary page. This code fills the page with diary entry previews using a for loop. Not shown is the first line % rebase('frame.tpl'), which tells SimpleTemplate to insert this content at the {{!base}} variable in the frame template.
    +
    +(image: diary snippet code from diary template.)
    +
    +(The code can be found on Pastebin.)
    +
    +The Bottle script sends the max number of snippets per page (the limit) and a list of lists containing all the diary snippets. It receives the page number from the URL. For the snippets that will appear on the given page, it converts the list data into HTML code to be displayed in the browser.
    +
    +
    +

    Bottle


    +Bottle takes URLs and generates the corresponding web page upon request. Each URL is tied to a method, which returns a template and a dictionary of data to be used in the template. Since Bottle is a Python framework, you have access to all the Python libraries you need.
    +
    +(image: Bottle script excerpt for diary routes.)
    +
    +(The code can be found on Pastebin.)
    +
    +This is what the methods for specific routes look like. So every time you go to blessfrey.me/diary, one of the above methods is called, depending on whether also you supplied an integer. To generate the page content, it calls a lot of Python functions to find my diary entries, convert them into previews for the snippets section + headlines for the sidebar, and get the current time for the footer.
    +
    +
    +
    +

    CSS


    +The website is styled using CSS, heavily relying on the CSS Grid and a bit of Flexbox. CSS Grids can be used inside CSS Grids, so my pages are generally blocked out, with smaller internal grids managing specific content.
    +
    +(image: CSS Grid traced over screenshot of projects page.)
    +
    +
    +The projects page is an example of nested grids. Almost every page uses the yellow general layout. The content unique to the projects page is mapped out in green, with a section for the header, featured projects, and other projects. The other projects use a 2-column grid in blue to evenly space out all the little thumbnails.
    +
    +The CSS code for project's general grid + the nested unfeatured grid are shown below.
    +
    +(image: projects css code.)
    +
    +(The code can be found on Pastebin, but you can always see a web page's CSS by right-clicking and viewing the source.)
    +
    diff --git a/vps/diary/entries/201029 b/vps/diary/entries/201029 new file mode 100644 index 0000000..546f240 --- /dev/null +++ b/vps/diary/entries/201029 @@ -0,0 +1,88 @@ + +

    blessfrey in japanese

    +october 29, 2020
    +#internationalization #localization
    +
    +Instead of hard-coding text, keep it in a spreadsheet instead. It's easier to organize, edit, and it also makes possible future translations a much smoother process.
    +
    +I followed along with GoTut's "Localisation in Godot" guide, but the process is pretty simple. It's a great guide, so honestly just follow theirs instead. I'll echo the process here in case it's taken down, though.
    +
    +

    step 1 - make your spreadsheet

    +
    +
    + + (image: spreadsheet with three columns - id, en, and ja. id has ids, en has English text, and ja has Japanese text.) +
    +
    +
    +Instead of writing your text directly into Godot, refer to the text by ids instead. These ids will be kept in the first column of your spreadsheet. Don't use spaces.
    +
    +The rest of the columns will hold the corresponding text in different languages. Name these columns after the language's locale code. English's is en, and Japanese's is ja. You can find the more codes in the Godot Docs.
    +It works just fine if you're only using one language. If you have multiple languages but don't provide a translation for a specific id, whenever your game is set to that language, references to that script will show blank text.
    +
    +Save your spreadsheet as a .CSV file.
    +
    +
    +

    step 2 - import your spreadsheet

    +
    +Make sure your .CSV spreadsheet is in your game folder, so Godot can automatically import files. Wherever you import your text, make sure you check 'Comma' for the delimiter or separator options. You'll get a few .TRANSLATION files.
    +
    +
    +(image: Project Settings>Localization>Translations shows a TRANSLATION file for each language.)
    +
    +
    +From Godot's top menu, go to Project>Project Settings...>Localization>Translations and add all your .TRANSLATION files. They'll be right next to wherever you saved your .CSV.
    +
    +
    +

    step 3 - refer to your ids in your scripts

    +
    +
    +(image: example of an id used in a script)
    +
    +
    +It's really simple stuff. Anywhere you would have written a string, like "quit", you instead use its id wrapped in tr(). So instead of label.set_text("quit"), you'd write label.set_text(tr("quit_game")). In this example, the id is "quit_game" and its corresponding text in English is "quit." +
    +
    +

    step 4 - set the game's language

    +
    +
    +(image: example of setting the locale in a script)
    +
    +
    +Set the locale in your script, somewhere like _ready() or on a 'change language' button. Here's the line for setting the locale: TranslationServer.set_locale("ja") +
    +
    +

    step 5 - continue adding to your spreadsheet

    +
    +Now that everything's in place, you can keep adding new ids + translations, and Godot will automatically use your changes in-game.
    +
    +
    +

    step 6 - insert values into text

    +
    +Languages differ in syntax, so use format strings.
    +
    +In your spreadsheet, write %s where your inserted text will go. +
    +
    +(image: in the .CSV, id= character_level, en= Level %s, ja= レバル %s)
    +
    +
    +Then in your script, write tr("key") % inserted_val in place of the formatted string.
    +
    +
    +(image: in the script, set_text(tr("character_level") % String(level))
    +
    +
    +Now the formatted string will appear in-game.
    +
    +
    +(image: screenshot: Level 1)(image: screenshot: レベル 1)
    +
    +
    +

    that's the basics

    +
    +(image: blessfrey screenshot in Japanese)
    +
    +
    +It all comes together for an old screenshot of blessfrey's main menu in my broken Japanese. やべーな!
    +
    diff --git a/vps/diary/entries/201101 b/vps/diary/entries/201101 new file mode 100644 index 0000000..a2b35af --- /dev/null +++ b/vps/diary/entries/201101 @@ -0,0 +1,85 @@ + +

    october 2020: a blog that works

    +november 1, 2020
    +#css #html #python #webdev #website
    +
    +

    week 1


    +#bottle #python #regularexpression #website
    +
    +

    thursday, october 1


    + +
    +

    friday, october 2


    + +
    +

    saturday, october 3


    + +
    +

    week 2


    +#bottle #python #website
    +
    +

    sunday, october 4


    + +
    +

    monday, october 5


    + +
    +

    tuesday, october 6


    + +
    +

    wednesday, october 7


    + +
    +

    saturday, october 10


    + +
    +

    tuesday, october 13


    + +
    +

    tuesday, october 16


    + +
    +

    saturday, october 17


    + +
    +

    monday, october 19


    + +
    diff --git a/vps/diary/entries/201112 b/vps/diary/entries/201112 new file mode 100644 index 0000000..3aaf6d6 --- /dev/null +++ b/vps/diary/entries/201112 @@ -0,0 +1,39 @@ + +

    tidying up my skill phases

    +november 12, 2020
    +#programming #skills
    +
    +In Godot Engine, you can call methods from a parent class by prefixing it with a period (.). So to access the move() method from a parent, call .move(). This is called a super method.
    +
    +Being called super doesn't mean there isn't a better way, though. I used to use super methods to build customs skills in blessfrey, but subfunctions is tidier.
    +
    +(Just so you know, blessfrey's skills have a number of phases of effects that must happen in order: skill press > activation > initial phase > main phase > end phase > cooldown.)
    +
    +
    +

    the old way


    +Initially, I used super methods to give each phase custom effects and call the next phase. This was messy. If I ever redesigned the flow of the skill phases, I'd have to edit every single skill script. It also causes a lot of repetitive code in the individual skill scripts while the base script is tiny. The one-time script being the small one is no fair.
    +
    +(image: GDscript code using old method)
    +
    +(You can see the old method's code on Pastebin.) +
    +
    +

    the new way


    +
    +Instead, I can bring all the repetitive steps into the base class, sandwiching in a subfunction where the custom effects would take place. Now I only need to add what makes my skill unique inside the subfunction.
    +
    +I named the subfunction after its main function and added an underscore to the front. So in the base script, I fit _functionality(user, action_target) into functionality(user, action_target). Then the individual skill scripts only need the subfunction, none of the other repetitive code from before. The subfunction is empty in the base class and filled with unique code in the child classes. Since skills inherit, the unique _functionality subfunction will be called automatically from the base script's functionality.
    +
    +
    + + (image: GDscript code using new method) + +
    +(You can see the new method's code on Pastebin.) +
    +
    +

    problem solved!


    +
    +The base script holds all the lengthy code in one place, while I only need to write the unique effects in all the hundreds of skill scripts. That saves me time making, refactoring, and maintaining skills. Yay.
    +
    + diff --git a/vps/diary/entries/201126 b/vps/diary/entries/201126 new file mode 100644 index 0000000..53738ee --- /dev/null +++ b/vps/diary/entries/201126 @@ -0,0 +1,49 @@ + +

    pretendOS - a game inspired by windows XP

    +november 26, 2020
    +#sideproject
    +
    +Getting started with blessfrey's AI was overwhelming, so I took a break and worked on a new game. I didn't get very far. It's not even on my hard drive anymore. It's cute, though.
    +
    +Unlike blessfrey, where coding takes up 90% of the effort, pretendOS is mostly graphical assets + sounds with barely any functionality. It's a UI game, after all. Since it's a game requiring a completely opposite skill-set, I was able to make progress on something while reading up on game AI. I also got to work on new things like particle effects.
    +
    +
    +

    Inspiration

    +
    +

    Windows XP

    +The game takes strong aesthetic inspiration from Windows XP. It almost fits the 90s vaporwave trend, but I'm too young to really remember Windows 95. I obviously have nostalgia for it as my first operating system (as far as I remember - I was a toddler then), but I mostly knew it as the Lego Island machine propped up in the dining room. As my family upgraded computers over the years, Windows never really impacted me as anything more than something that can run some videogames and whatever popular web browser of the time. That is, until Windows XP.
    +
    +XP really hooked me. It was the first operating system I spent as much time exploring as I spent using software. XP's edition of Paint was my favorite yet, I loved fiddling with the themes and accessibility options, especially Microsoft Sam, Rover, and Clippy. I started watching YouTube videos on how to use the Command Prompt. XP was just fun to use. I've found better desktop environments and operating systems since, but I never got over that aesthetic: smooth, blended graphics with hard pixel edges in 32-bit color with an alpha channel, right at the cusp between pixel art and vector graphics. Vaporwave for me is Luna olive green, or the "Fisher-Price interface" as Ars Technica users called it.
    +
    +(image: Wikipedia excerpt: Critics who did not like the theme characterized it as a 'Fisher-Price interface'.)
    +(screenshot from Wikipedia - referencing articles from PCWorld and Ars Technica)
    +
    +
    +There were a few other experiences behind the game, too.
    +
    +

    Mother's Day E-Card

    +I finally got my husband to try Godot Engine, and he used it to make a digital Mother's Day card for his mom. (Cute.) Opening the card displayed a 3D heart (a "cardioid") that bounced to the beat of a song while 2D cardioid particles rained down. It was all programmatically generated using geometry instead of 3D + 2D assets, so the application was very small. He made the graphics side of things look really interesting, and I wanted to play around with particles, too. Just...not as fancy;;
    +
    +

    Secret Little Haven

    +I also just played a cute pretend OS game on itch called Secret Little Haven It's quite short, very story-driven, and kind of buggy, telling Alex's struggle with gender identity through IMs. Honestly, pretend OS games and coming-of-age chat sims are nothing special, but Secret Little Haven's believability makes it really stand out. Instead of defending against cheesy + inaccurate deep web hacking attempts, you use an in-game terminal to get around child locks set by Alex's dad. Those terminal puzzles are the most realistic and relatable hacking I've seen in these games. SLH isn't super sophisticated or in-depth, but it shows how cute and believable a pretend OS game can be. I'd love to make a little environment like that, that's as fun to fiddle around with as XP.
    +
    +
    +

    pretendOS

    +
    +So what's pretendOS? Like I said, not much besides pictures. I only worked on it for a few days.
    +
    +What really bogged it down was Cat Chat. I wanted an AI chat personality that talked like a cat. I could do that, but that kind of thing takes a lot of time, when this project was really just procrastinating working on AI.
    +
    +The rest is cute, though. The icon winks when you click it, the cursor's kinda 2000s-free-animated-cursors, and it's got those Fisher-Price colors and bubbly sounds everywhere that I liked as a kid.
    +
    +
    + + (image: pretend desktop with a Cat Chat application) +
    +
    +
    +
    +

    the future

    +
    +It's cute. I'd like it to be finished in some way. I went ahead and cloned my old repo. Maybe I'll fill it out with more applications during a game jam or something or at least finally get that cool Secret Little Haven curved screen shader working.
    +
    diff --git a/vps/diary/entries/201201 b/vps/diary/entries/201201 new file mode 100644 index 0000000..fcd2e30 --- /dev/null +++ b/vps/diary/entries/201201 @@ -0,0 +1,33 @@ + +

    november 2020: dear diary

    +december 1, 2020
    +#blogging #bottle #skills #webdev
    +
    +

    on topic

    +Between the 8th and 15th, I wrote a Python script for generating Godot skill scenes from JSON files. As opposed to the questionnaire script I used before, this one can generate multiple skills at a click of a button. It isn't a perfect solution either, though, since my JSON script and the skills I have in the game aren't synced. It'd be better for the skills to be something like JSON files that are read by the game at run-time, unless that would be too costly. That way, I only edit skills in one location and don't need to worry about different versions.
    +
    +Skill inheritance is more sophisticated now and allows the script to generate a lot of the functionality of most types of skills now.
    +
    +I spend a lot of time on how to make skills because this is a core mechanic of my game, and I plan to have a hundred or more of them. I need an efficient way to update and create the game's skill pool.
    +
    +On November 24, 2020, I finally added a diary navigation bar under the diary snippets, so you don't have to scroll back up to go to the next page anymore. I was really putting that off for how essential that is.
    +
    +On November 25, 2020, I began retroactively adding diary entries based on old tweets. I added one for my pixel font, one for my Weekly Game Jam submission, one for my inventory system diagram, and one for blessfrey's graphic updates. I finally got Bottle to support self-hosted images instead of using Imgur for everything (lol), and fixed lots of bugs related to actually having embedded images in articles.
    +
    +As cool as it is to work on gamedev, this website is also a priority for me as a sort of portfolio. So it would be nice to have lots of articles about my process and different projects. It would be super nice to have pretty graphics everywhere, but as usual, the placeholders are probably going to stay around for a while since they're already half-decent-looking.
    +
    +November 26, 2020 is Thanksgiving during a pandemic. Wrote up an article for my pretendOS game and my coroutines example. Also, the diary shows 8 snippets per page instead of 4. I finally have enough articles to test an optimal amount shown per page.
    +
    +November 27, 2020 is Black Friday. I ordered navy eye shadow and fancy sunscreen.<3 Added an article for skill phases + super methods and slimeAI's state transition diagram.
    +
    +November 28, 2020 is my birthday. <3 I replaced the game page with a projects page with pretty CSS grid formatting and little thumbnail links to different projects, either to diary entries or git repos.
    +
    +November 29, 2020, I make sure all the thumbnails are consistent sizes for the projects page make the images and descriptions into links. I also add a thumbnail for the website itself because why not? It doesn't have anything suitable to link to, so I wrote up an article explaining blessfrey.me's development. I touched up the presskit page and added a PDF download to the page. Downloads are way easier to add than I thought they'd be - seriously took me less than a minute. The presskit page is still ugly, but at least it has better images on it now. I'm getting close to actually letting people see my website (even though it's been publicly accessible pretty much since August but whatever), so I went through my articles again and improved their readability and removed most stuff that isn't really relevant.
    +
    +November 30, 2020, I reordered the diary entries again. The daily diaries really should be released after the month is over instead of on the last day of the month. Duh. Also, the 3-week-nonstop-earworm of Seungri's "Let's Talk About Love" finally went away. It was becoming pathological.
    +
    +

    off-topic


    +I joined a Japanese manga translation group on a whim and now provide Japanese-to-English transcripts for a new chapter of a manga about every week and a half. It wasn't obvious, but understanding Japanese is a different skill than rewriting Japanese into English while keeping the jokes, character voice, and cliffhangers/foreshadowing intact;;
    +
    +Also, Election Day-turned-Weeks took up a few extra days of nonstop news watching than it usually does, even though I tuned out long before Georgia was called.
    +
    diff --git a/vps/diary/entries/201210 b/vps/diary/entries/201210 new file mode 100644 index 0000000..aa57bf7 --- /dev/null +++ b/vps/diary/entries/201210 @@ -0,0 +1,28 @@ + +

    common tropes from media

    +december 10, 2020
    +#writing
    +
    +
    +I like collecting common tropes from games I play. Maybe it can inspire some game beats? Here's a few of them listed with some games I've seen them in ~
    +
    +If you're worried about spoilers, games mentioned are The Cat Lady, Dreamfall: The Longest Journey, Fire Emblem, Guild Wars, Guild Wars 2, Half-Life, Mass Effect, Neverwinter Nights 2, Oblivion, Persona 4, Planescape: Torment, RuneScape 2 +
    + +
    diff --git a/vps/diary/entries/201224 b/vps/diary/entries/201224 new file mode 100644 index 0000000..321224f --- /dev/null +++ b/vps/diary/entries/201224 @@ -0,0 +1,43 @@ + +

    blessfrey graphic updates + mockups

    +december 24, 2020
    +#mockups #screenshots
    +
    +I iterate over the graphics periodically, so I can practice without worrying about polish. Here's some screenshots of different styles I've tried. (Though April 23, 2019's is actually a mockup, that style did run in-engine for a few weeks.)
    +
    +
    + + (image: Cassia and Bad Cat on the pink carpet tilemap) +
    +August 15, 2018 - Early experimenting with Godot Engine. Collision was just added for sprites and walls. The buttons to the right are for switching between characters (who each have different skillbars).
    +

    + + (image: Angel in a periwinkle room full of Bad Cats) +
    +January 13, 2019 - Videogame perspective is so different from perspective in illustration. Scale of characters vs environment is another quirk of games I had 0 experience with. I was vaguely going for an old Western RPG style with tall, somewhat realistic sprites with non-distinct faces. Something like Divine Divinity.
    +

    + + (image: Angel blasting a neighborhood coyote with fire) +
    +April 23, 2019 - This is a mockup, but the game did look like this for a while. The fireball projectile didn't come until later, though. Here, I was trying to get a little more of a top-down view but not really. Instead of cats, Angel's fighting with a coyote. The government stopped removing coyotes from my old neighborhood, so they killed all the neighborhood cats except one and I saw him running away from a big coyote during a storm, so maybe he's gone now, too. It's just not right.
    +

    + + (image: Angel and Chloe in front of a slanted house) +
    +May 25, 2019 - The slanted edition was so annoying. It's not isometric, it's just at an obscure angle because I drew these assets more for fun than to actually be practical. I do reuse the tree + bushes a lot, though. I also tried a more chibi sprite because they are soo common, might as well try it out.
    +

    + + (image: Lots of Angels and other characters at a shopping center) +
    +June 29, 2019 - Trying a shopping center level now. It's reeally spaced apart. It's inspired by a real shopping center;;
    +

    + + (image: Angel and some slimes in a cavern) +
    +July 25, 2020 - There's some missing in this gap, so I'll add in more pics if I find any. This is the first version of a cavern level for the blessfrey demo. It's inspired by local caves.
    +

    +
    +

    you're up to date.

    +
    +Hope you enjoyed seeing the different art I've used for blessfrey over the years. Even if I never really polish anything, it's nice to iterate to get a sense of game art and blessfrey's personal style. Hopefully it ends up looking okay okay when I do start polishing. But until then, in the words of YandereDev, "All art is placeholder."
    +
    diff --git a/vps/diary/entries/210101 b/vps/diary/entries/210101 new file mode 100644 index 0000000..43a4d59 --- /dev/null +++ b/vps/diary/entries/210101 @@ -0,0 +1,55 @@ + +

    december 2020: holiday season☆

    +january 1, 2021
    +
    +
    +I didn't keep a diary very well this month;; This is mostly pieced together from my git history. I did play Legacy of Kain: Soul Reaver and Planescape: Torment a lot, though.
    +
    +

    week 1, december 1-5


    +#python
    +
    + +
    +

    week 2, december 6-12


    +#python
    +
    + +
    +

    week 3, december 13-19


    +
    + +
    +

    week 4, december 20-26


    +#python #skills #statuseffects
    +
    + +
    +

    week 5, december 27-31


    +#dia #events #refactoring #story
    +
    + +
    diff --git a/vps/diary/entries/210107 b/vps/diary/entries/210107 new file mode 100644 index 0000000..9c73ad3 --- /dev/null +++ b/vps/diary/entries/210107 @@ -0,0 +1,40 @@ + +

    inventory as a system diagram

    +january 7, 2021
    +#design #systemdiagram #gamemechanics
    +
    +System diagrams illustrate how components interact within a system. It saves so much headache to step back and plan with a system diagram before jumping into code.
    +
    +
    +

    stop + plan before coding


    +I want to move blessfrey's inventory into an app on the player character's smartphone. Before, it was displayed in a random pop-up window. It was poorly planned, so the programmatic inventory and the UI were too tightly coupled to easily pop into the phone screen. Instead of wrestling, it's easier to start over and actually plan before I code this time.
    +
    +
    +

    list out your nouns


    +A simple way to start thinking about a system is to list out its nouns + verbs. Jot down the entities that interact with your system.
    +
    +
    (image: system diagram for inventory)

    +
    +For blessfrey's inventory, that's the inventory (programmatic), the player character, the inventory app (UI), and base items. The inventory app is related to the smartphone and inventory items. Items are related to floor items, which are related to rooms.
    +
    +(blessfrey has three different kinds of items.
    +

    +Floor + Inventory Items hold a base item inside them that gets popped out and traded around as the item gets expressed in different forms.)
    +
    +

    connect your nouns with verbs


    +I wrote the entities in pink and moved them around until the placement was decently readable. Then I connected the concepts with arrows. These arrows represent the verbs, which I explicitly labeled in yellow.
    +
    +The flow of these arrows can be very important. If you are modeling AI, for instance, no matter what path the program takes, there shouldn't be dead-ends. Seeing mistakes like that is easier with a diagram than lines of code. Otherwise, the flow is always generally useful for figuring out which methods are needed for each class and how they connect.
    +
    +
    +

    write the code


    +At this point, coding is a bit easier now that it's in some ways a transcription of the diagram. The entities are data (classes or objects), and the arrows are logic (methods).
    +
    +
    +

    conclusion


    +Your diagram doesn't have to be fancy or formal to get the point across to yourself, and it just takes a minute to save all the headache later. Don't skip this step or you'll have to rewrite the inventory system just to display it in a different window.
    +
    diff --git a/vps/diary/entries/210121 b/vps/diary/entries/210121 new file mode 100644 index 0000000..21d9fd7 --- /dev/null +++ b/vps/diary/entries/210121 @@ -0,0 +1,13 @@ + +

    web development resources

    +january 21, 2021
    +#accessibility #color #css #html #webdesign
    +
    +I'll collect frequently used resources for web design here.
    +
    + diff --git a/vps/diary/entries/210201 b/vps/diary/entries/210201 new file mode 100644 index 0000000..ea2280b --- /dev/null +++ b/vps/diary/entries/210201 @@ -0,0 +1,155 @@ + +

    january 2020: new year

    +february 1, 2021
    +
    +
    +

    week 1, january 1-2


    +
    +
    +

    friday, january 1 - New Year's

    + +
    +

    week 2, january 3-9


    +#character #refactor
    +
    +

    sunday, january 3

    + +
    +

    monday, january 4

    + +
    +

    wednesday, january 6

    + +
    +

    thursday, january 7

    + +
    +

    friday, january 8

    + +
    +

    saturday, january 9

    + +
    +

    week 3, january 10-16


    +#character #refactor
    +

    monday, january 10

    + +
    +

    tuesday, january 11

    + +
    +

    thursday, january 14

    + +
    +

    friday, january 15

    + +
    +

    saturday, january 16

    + +
    +

    week 4, january 17-23


    +#fogofwar #refactor #writing
    +
    +

    sunday, january 17

    + +
    +

    monday, january 18

    + +
    +

    tuesday, january 19

    + +
    +

    wednesday, january 20 - President Biden's Inauguration

    +
  • Wrote branching dialog in Dia. I need to get used to the hotkeys, so I can write faster. I should write more. Before the pandemic, I wrote at least a vignette every day, even if there were lots of duds.
  • + +
    +

    thursday, january 21

    + +
    +

    friday, january 22

    + +
    +

    saturday, january 23

    + +
    +

    week 5, january 24-30


    +#
    +
    +

    sunday, january 24

    + +
    +

    tuesday, january 26

    + +
    +

    week 6, january 31


    +#
    +
    diff --git a/vps/diary/entries/210204 b/vps/diary/entries/210204 new file mode 100644 index 0000000..ee86344 --- /dev/null +++ b/vps/diary/entries/210204 @@ -0,0 +1,28 @@ + +

    new year's resolution - making the most of 2021

    +february 4, 2021
    +
    +
    +2020 was a year of loss and difficult changes. I was largely unproductive in game development, web development, social media, and just about every aspect of my life. Most of a year passed without much to show for it. 2021 probably isn't going to be any better, but I will be. Now when I pray, "Father, thank you for this day," I won't take a normal, healthy day for granted and make the most of what I've been given.
    +
    +Honestly, it's a special kind of prolonged suffering to be separated from people for a year. Going out is such a fantasy to me now, no matter how masked and socially distant. Simple grocery shopping has become an event that I celebrate with my cutest clothes and hair. I even started wearing makeup to make outings just that much more special. To learn fun colorful makeup, I started watching small beauty youtubers. For a such a frivolous topic, their videos incorporate a lot of self-reflection about the wastefulness of large collections. It got me thinking about the wastefulness of my 2020 and how I want to spend 2021.
    +

    +

    panning makeup


    +Online beauty communities value the concept of panning. Against a consumer landscape of constant releases and rising quality of affordable drugstore + indie brands, it's aspirational to be content with what you already have. Panning means reaching the bottom packaging of a product, like this Instagram girl did. #projectpan and #panporn are full of well-loved makeup.
    +
    +
    View this post on Instagram

    A post shared by Curated By Léah (@_curatedbyleah)

    + +
    +Panning is difficult. I used to wear a full face of makeup for work. Besides some complexion products, I had one lipstick, four eyeshadow singles, and one blush. Even after using an extremely minimal collection daily for two years, there were noticeable dips but no pans in my color cosmetics.
    +
    +If you buy more than a palette or two, it's easy to buy more makeup than you could ever use in your life. Even worse, cream products dry up within a year or two. Panners find that excess wasteful, so they cut back on spending and intentionally enjoy their makeup to the fullest before it expires.
    +
    +There's another angle to panning. Since so many releases are limited edition, there's a natural tendency to save your favorite makeup for special occasions. That's equally wasteful, since it's more likely to mold than empty. If it's your favorite, you should wear it every single day.
    +

    +

    panning other areas of life


    +I guess the concept is obvious, but I find a lot of wisdom in that mindset. The concept can be applied anywhere - videogame backlogs, unread book collections, stocked up baking ingredients, unused art supplies, ignored MOOCs, forgotten exercise equipment, and hoarded assets and libraries. For each item in those areas, I could have been developing skills, gaining new perspectives, and having fun. Otherwise, it's just junk taking up space in my apartment and hard drive.
    +
    +In 2021, even if I have to do it all alone at home, I'm going to be more intentional about enjoying my hobbies. I've already finished 2 books, sewn 4 face masks, started an art journal, and gotten further than ever in Planescape: Torment.
    +
    +Happy (belated) New Year. Enjoy 2021. :)
    +
    diff --git a/vps/diary/entries/210218 b/vps/diary/entries/210218 new file mode 100644 index 0000000..ae8ca12 --- /dev/null +++ b/vps/diary/entries/210218 @@ -0,0 +1,18 @@ + +

    Writing Resources

    +february 18, 2021
    +
    +
    +Blessfrey has a story and character arcs. Let's get more confident with our story with online resources.
    +
    +

    plot


    + +
    +

    general


    + +
    diff --git a/vps/diary/entries/210304 b/vps/diary/entries/210304 new file mode 100644 index 0000000..249c7af --- /dev/null +++ b/vps/diary/entries/210304 @@ -0,0 +1,94 @@ + +

    questionnaire for making a fantasy race

    +march 4, 2021, 2020
    +#design #lore #worldbuilding
    +
    +

    Aspects of Culture

    +General things to consider about your fantasy race to fill out their culture. Obviously not every point is going to be relevant.
    +
    +

    Basics

    + +
    +

    Lifecycles

    + +
    +

    Religion + Legend

    + +
    +

    Climate

    + +
    +

    History

    + +
    +

    Culture

    + +
    +

    Others

    + +
    diff --git a/vps/diary/entries/extra/.gdc-Automated-Testing-code-backup.swp b/vps/diary/entries/extra/.gdc-Automated-Testing-code-backup.swp new file mode 100644 index 0000000..e729514 Binary files /dev/null and b/vps/diary/entries/extra/.gdc-Automated-Testing-code-backup.swp differ diff --git a/vps/diary/entries/extra/200918 b/vps/diary/entries/extra/200918 new file mode 100644 index 0000000..37b82b5 --- /dev/null +++ b/vps/diary/entries/extra/200918 @@ -0,0 +1,28 @@ + +

    my favorite GDC talks

    +september 18, 2020
    +game design, marketing
    +
    +I really should be keeping a list of these with descriptions, so why not keep them in an article?
    +
    +

    Automated Testing and Instant Replays in Retro City Rampage


    +Vblank Entertainment's Brian Provinciano (2015)
    +log button inputs to replay the game, for use in preproducing bugs, sharing replays on the community leaderboard, running cutscenes, and even controlling AI. It is 100% accurate in deterministic engines but also helpful in less deterministic engines. +
    + +
    +
    +

    Empathizing with Steam: How People Shop for Your Game


    +Chris Zukowski (2020)
    +tips for how to design your Steam store page based on Zukowski's screenshare and shopping diary observations of ordinary people shopping on Steam
    +
    + +
    diff --git a/vps/diary/entries/extra/201210 b/vps/diary/entries/extra/201210 new file mode 100644 index 0000000..6ea3c37 --- /dev/null +++ b/vps/diary/entries/extra/201210 @@ -0,0 +1,35 @@ + +

    slimeAI - state transition diagram

    +december 10, 2020
    +#ai #programming
    +
    +
    +blessfrey's slimes use finite state machines. Finite state machines (FSM) are models with a finite number of states that either decide to generate output or transition to a new state based on input. They can only be in one state at a time.
    +
    +
    +

    why use a finite state machine?


    +Because they are simple and flexible, while still allowing for interesting behavior. FSMs reflect our own mental model of how slimes behave (attack mode, wander mode, sleep mode, etc). These different modes or states are written as manageable chunks that easy to code, debug, update, and refactor. It's also efficient with processor time, since the behavior is abstracted to basic conditionals.
    +
    +A state can be as broad or specific as you need, so long as it's granular. So they can be more easily debugged and swapped out with one another, it's a good idea to have one entry point and one exit point for all your states.
    +
    +Of course, since FSMs can be used for anything with states and transitions. You can think of specific menus, mechanics or even your entire game in terms of states. I'm just using them here for understanding the AI for my slime monster.
    +
    +
    +

    designing AI


    +Planning ahead is extra important, since any dead-ends will halt your slime. I used a state transition diagram to design the slime's AI. In the diagram, circles represent states and arrows represent transitions, triggered by some kind of event. I marked the initial state with a star, but Buckland recommends a double circle.
    +
    +The slime is a simple creature. It idles, chases anything that gets too close, and attacks until its target dies. Here's the diagram version of that:
    +
    +(image: a state transition diagram for slime ai.)
    +
    +
    +The states are Idle, Choose Target, Attack, and Move to Target. The initial state is Idle.
    +
    +If there's a valid target, the slime enters Choose Target. If there's no longer a valid target, it returns to Idle. If it successfully gets a target, it begins moving to target. If the target becomes invalid, it returns to Idle. Once the target is in attack range, it enters Attack. If the foe moves out of range, it returns to Move to Target. If the target becomes invalid, it returns to Choose Target. And the cycle continues.
    +
    +No matter how you follow the arrows, there are no dead-ends and all states can be reached eventually, so it'll work okay when it's implemented as code. <3
    +
    +
    +

    reference


    +Programming Game AI by Example by Mat Buckland. It's an easy to understand introduction to game math + AI concepts. The code examples are in C++, but they are still useful for understanding the underlying principles. I didn't even know where to begin before I started reading and it got me pretty decent groundwork for AI creatures with different behavior that reacts to the players.<3
    +
    diff --git a/vps/diary/entries/extra/210218 b/vps/diary/entries/extra/210218 new file mode 100644 index 0000000..f9611bd --- /dev/null +++ b/vps/diary/entries/extra/210218 @@ -0,0 +1,28 @@ + +

    my favorite GDC talks

    +january 7, 2020
    +#gamedesign #marketing
    +
    +I really should be keeping a list of these with descriptions, so why not keep them in an article?
    +
    +

    Automated Testing and Instant Replays in Retro City Rampage


    +Vblank Entertainment's Brian Provinciano (2015)
    +log button inputs to replay the game, for use in preproducing bugs, sharing replays on the community leaderboard, running cutscenes, and even controlling AI. It is 100% accurate in deterministic engines but also helpful in less deterministic engines. +
    + +
    +
    +

    Empathizing with Steam: How People Shop for Your Game


    +Chris Zukowski (2020)
    +tips for how to design your Steam store page based on Zukowski's screenshare and shopping diary observations of ordinary people shopping on Steam
    +
    + +
    diff --git a/vps/diary/entries/extra/210304 b/vps/diary/entries/extra/210304 new file mode 100644 index 0000000..249c7af --- /dev/null +++ b/vps/diary/entries/extra/210304 @@ -0,0 +1,94 @@ + +

    questionnaire for making a fantasy race

    +march 4, 2021, 2020
    +#design #lore #worldbuilding
    +
    +

    Aspects of Culture

    +General things to consider about your fantasy race to fill out their culture. Obviously not every point is going to be relevant.
    +
    +

    Basics

    + +
    +

    Lifecycles

    + +
    +

    Religion + Legend

    + +
    +

    Climate

    + +
    +

    History

    + +
    +

    Culture

    + +
    +

    Others

    + +
    diff --git a/vps/diary/entries/extra/chesterton-magic b/vps/diary/entries/extra/chesterton-magic new file mode 100644 index 0000000..adbf3cc --- /dev/null +++ b/vps/diary/entries/extra/chesterton-magic @@ -0,0 +1,15 @@ + +

    Magic: A Fantastic Comedy in a Prelude and Three Acts - G.K. Chesterton (1913)

    +january 8, 2020
    +
    +
    +Did you know G.K. Chesterton wrote a play? Its existence really surprised me while browsing Project Gutenberg. I know him mostly as the author of The Everlasting Man and lots of other books about philosophy and religion. He's not stuffy, though. His style is so poetic and dramaticized through use of personification, he makes the topics as enjoyable as fiction...at least, from what I remember. It's been 10 years since I read anything else by him.
    +
    +Apparently, George Bernard Shaw wrote a letter pressuring him into drama because he felt he was wasting his talent on journalist. (According to Chesterton University's Lecture 25: Magic by Dale Ahlquist)
    +"I shall deliberately destroy your credit as an essayist, as a journalist, as a critic, as a Liberal, as everything that offers your laziness as a refuge, until starvation and shame drive you to serious dramatic parturition. I shall repeat my public challenge to you; vaunt my superiority; insult your corpulence; torture Belloc; if necessary, call on you and steal your wife’s affections by intellectual and athletic displays, until you contribute something to British drama." (also from that link)
    +
    +You can read Magic, too, at Project Gutenberg. Plays are meant to be performed, though, so hopefully you can find something on Youtube at least.
    +
    + +
    + diff --git a/vps/diary/entries/extra/clayton-drinker-of-souls b/vps/diary/entries/extra/clayton-drinker-of-souls new file mode 100644 index 0000000..9d8f148 --- /dev/null +++ b/vps/diary/entries/extra/clayton-drinker-of-souls @@ -0,0 +1,14 @@ + +

    Drinker of Souls - Jo Clayton (1986)

    +january 8, 2020
    +
    +
    +I usually read classics or philosophy, so I thought I'd cut loose and read my first 80s science fiction novel: Drinker of Souls, from Jo Clayton's Drinker of Souls trilogy. Unfortunately, Clayton's novels are probably all out of print and won't be entering the public domain for a long, long time. I found mine at a thrift store.
    +
    +I just picked up a random scifi book, but apparently the Skeen Trilogy by this author is more popular.
    +
    +Review here +
    +I read half of the next book, Blue Magic, but it was kind of boring and the characters were less interesting for me. It explored more parallel worlds, all with dramatically different levels of technology and magic. It had that 'wizards using computers' aesthetic that isn't done often enough. The setting reminded me of the Sigil in Planescape: Torment, how characters from all over get trapped in Brann's world. There was the guy from a futuristic trapped there with his phaser, like that number tattoo guy in the Buried Village who tells you about his cyberpunk world.
    +
    + diff --git a/vps/diary/entries/extra/entry-template b/vps/diary/entries/extra/entry-template new file mode 100644 index 0000000..b824736 --- /dev/null +++ b/vps/diary/entries/extra/entry-template @@ -0,0 +1,67 @@ + +

    title in lowercase

    +date in lowercase
    +#accessibility #ai #apache #blogging #bottle #color #css #design #gamedescription #gamedesign #gamejam #gamemechanics #git #html #internationalization #json #localization #marketing #mockup #nginx #php #programming #python #regex #regularexpression #server #simpletemplate #skills #systemdiagram #webdev #webdesign #website
    +
    +term is etc.
    +
    +Capitalize some words.
    +
    + +
    +
    +

    lowercase

    + +
    + +
    +How to spell words...
    +
    + +
    +

    subtitle


    +spacing like this
    +
    +
    + + (image: Lots of Angels and other characters at a shopping center) +

    +

    subsubtitle with BrandName or CSS or chloe

    +

    +
    + (image: Lots of Angels and other characters at a shopping center) +
    +
    diff --git a/vps/diary/entries/extra/flightrising-badges b/vps/diary/entries/extra/flightrising-badges new file mode 100644 index 0000000..cfe0e6d --- /dev/null +++ b/vps/diary/entries/extra/flightrising-badges @@ -0,0 +1,116 @@ + +

    FlightRising badges

    +january 8, 2020
    +
    +
    +A favorite activity in FR is collecting badges from community-run events. If I back them up here, I won't lose as many. :)
    +
    +Fire - Lava Bank - 1/21
    +(image: FlightRising badge)
    +(image: FlightRising badge)
    +
    +Fire vs Light - 12/20
    +(image: FlightRising badge)
    +(image: FlightRising badge)
    +
    +(image: FlightRising badge)
    +(image: FlightRising badge)
    +(image: FlightRising badge)
    +(image: FlightRising badge)
    +(image: FlightRising badge)
    +(image: FlightRising badge)
    +(image: FlightRising badge)
    +
    +Arcane - 9/20
    +(image: FlightRising badge)
    +
    +Water - Dom Push - 9/20
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +Fire - Flameforger's Festival - Exalts, Geyser's Grocery Games - 8/20
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +Fire - Lava Bank - 8/20
    +(image: FlightRising badge) +
    +Lightning - Thundercrack Carnivale - 7/20
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +Fire - Shocking Safari Zone - 7/20
    +(image: FlightRising badge) +
    +Fire - Baldwin's Brew for the Bank Over 9000 - 7/20
    +(image: FlightRising badge) +(image: FlightRising badge) +
    +Ice - 7/20
    +(image: FlightRising badge) +(image: FlightRising badge) +
    +Arcane - 7/20
    +personality quiz result: Starseeker
    +(image: FlightRising badge) +
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +Fire - Shining Safari Zone - 7/20
    +(image: FlightRising badge) +
    +Fire - Trash for Cash - 7/20
    +(image: FlightRising badge) +(image: FlightRising badge) +
    +Wind vs Plague - 6-7/20
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    +Fire - Subspecies Raffle - 5-6/20
    +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +(image: FlightRising badge) +
    diff --git a/vps/diary/entries/extra/gdc-Automated-Testing-code-backup b/vps/diary/entries/extra/gdc-Automated-Testing-code-backup new file mode 100644 index 0000000..3b55ce8 --- /dev/null +++ b/vps/diary/entries/extra/gdc-Automated-Testing-code-backup @@ -0,0 +1,288 @@ +/******************************************************************************/ +// SIMPLE INPUT RECORD/PLAYBACK +// (c) 2015 Brian Provinciano +// +// You are free to use this code for your own purposes, no strings attached. +// +// This is a very basic sample to record and playback button input. +// It's most useful when activated on startup, deactivated on shutdown for +// global button recording/playback. +// +// For details on more advanced implementations, see my GDC 2015 session: +// -> Automated Testing and Instant Replays in Retro City Rampage +// The slides and full video will be available on the GDC Vault at a later date. +/******************************************************************************/ + + +/******************************************************************************/ +// wrap it so it can be conditionally compiled in. +// for example, set INPUTREPLAY_CAN_RECORD to 1 to play the game and record the input, set it to 0 when done +// INPUTREPLAY_CAN_RECORD takes priority over INPUTREPLAY_CAN_PLAYBACK + +#define INPUTREPLAY_CAN_PLAYBACK 1 +#define INPUTREPLAY_CAN_RECORD 1 + +#define INPUTREPLAY_INCLUDED (INPUTREPLAY_CAN_PLAYBACK || INPUTREPLAY_CAN_RECORD) +/******************************************************************************/ + +#if INPUTREPLAY_INCLUDED + +#define INPUT_BUTTONS_TOTAL 32 // up to 32 +#define MAX_REC_LEN 0x8000 // the buffer size for storing RLE compressed button input (x each button) + +/******************************************************************************/ +typedef struct +{ + unsigned short *rledata; + unsigned short rlepos; + unsigned short datalen; + unsigned short currentrun; +} ButtonRec; +/******************************************************************************/ + +// if INPUTREPLAY_CAN_RECORD, as soon as this class is instanced, it will automatically record when instanced/created. +// statically creating this as a global will blanket the entire play session +// +// if INPUTREPLAY_CAN_PLAYBACK, playback will begin as soon as LoadFile() is used +// +class SimpleInputRec +{ + unsigned int m_buttonstate; + ButtonRec m_buttons[INPUT_BUTTONS_TOTAL]; + bool m_bRecording; + + unsigned char* m_data; + +public: + SimpleInputRec() + : m_buttonstate(0) + , m_data(NULL) + , m_bRecording(true) + { + } + + ~SimpleInputRec() + { + if(m_data) + { +#if INPUTREPLAY_CAN_RECORD + WriteToFile(); +#endif + delete[] m_data; + } + } + + // run each frame before the game uses the live button input. + // when recording, it saves the live input + // during playback, it overwrites the live input + void Update(bool bForce = false); + + // to start a playback +#if INPUTREPLAY_CAN_PLAYBACK + bool LoadFile(KSTR szfilename); +#endif + + // to finish recording +#if INPUTREPLAY_CAN_RECORD + void WriteToFile(); +#endif + +}; + +/******************************************************************************/ + +void SimpleInputRec::Update(bool bForce) +{ +#if INPUTREPLAY_CAN_RECORD + if(m_bRecording) + { + unsigned int newbuttons = nesinput.buttons; + + // allocate and initialize + if(!m_data) + { + m_data = new unsigned char[INPUT_BUTTONS_TOTAL * MAX_REC_LEN * 2]; + unsigned short* dataptr = (unsigned short*)m_data; + + for(int i=0; i>i)&1; + btn.rledata[btn.rlepos++] = (bit<<15) | btn.currentrun; + } + btn.currentrun = bForce? 0 : 1; + } + else + { + ++btn.currentrun; + } + } + + m_buttonstate = newbuttons; + } +#endif + +#if INPUTREPLAY_CAN_PLAYBACK + if(!m_bRecording) + { + bool bIsRunning = false; + for(int i=0; i>15)&1)<> 8, f); + } + for(int i=0; i diff --git a/vps/diary/entries/extra/gdc-design-steam-store b/vps/diary/entries/extra/gdc-design-steam-store new file mode 100644 index 0000000..619bb0e --- /dev/null +++ b/vps/diary/entries/extra/gdc-design-steam-store @@ -0,0 +1,36 @@ + +

    my favorite GDC talks: Empathizing with Steam: How People Shop for Your Game by Chris Zukowski (2020)

    +september 18, 2020
    +marketing, sale, steam, wishlist
    +
    +Empathizing with Steam: How People Shop for Your Game by Chris Zukowski (2020) - tips for how to design your Steam store page based on Zukowski's screenshare and shopping diary observations of ordinary people shopping on Steam +
      +
    • Essentially, make your gameplay genre absolutely clear within the first 4 screenshots and in the short description so that people will wishlist your game to buy during a seasonal Steam Sale.
    • +
    • Approach your wishlisters as complete newcomers. Jazz up your Steam page before a Steam Sale. Release an update, post in your forums, put a Santa hat on your character. When wishlisters return to your page, they will see an active game and be sold on it all over again.
    • +
    • His conclusions are very similar to how I shop on Steam, except I could care less for the tag section.
    • +
    • first 4 images are shown when hovering over thumbnail in Steam. Make them represent the pillars of your gameplay, so the genre is clear.
    • +
    • don't try to coerce new audiences into trying your game. try to find your audience and show them exactly what they are looking for. +
    • include UI in screenshots, so gamers can decipher the genre and some gameplay mechanics
    • +
    • Gamers naturally compare new games with the leading games of their genres to decide whether they will enjoy it.
    • +
    • indie romance authors (who compete on a market of 8 million vs. steam's 40 thousand) use clear visual language in their coverart: tartan kilt + sword + distant castle = highland romance; animal behind a hunk = shapeshifter romance; woman in front of group of hunks = reverse harem. So a reader who sees a cover with multiple guys and a wolf, she knows it's a reverse harem of shape-shifting wolf boys without any descriptions or trailers.
    • +
    • applying the wisdom of the romance authors, understand your audience's genre interests as sub-sub-sub-genres and make your genre crystal clear in your store page.
    • +
    • Apply the tropes of your genre. The FPS coverart guy with the gun on all CoD and BF games, the two Street Fighter healthbars on the top of any fighter game
    • +
    • Part 4 - How to manage a Steam sale
    • +
    • People check their wishlist during sales, looking for discounts.
    • +
    • People don't remember why they wishlisted games, so your page must look fresh even to your wishlist crew. Before a sale, post an update, theme your capsule image, post an announcement, upload a small patch, and comment in the forums.
    • +
    • People remember games that are always on sale. Frequent sales increase familiarity.
    • +
    • Power users use gg.deals or steamdb to track historic lows. Strategically staircase your way down over time. Coincide your all-time-lows with Big Steam Sales. Harness the fear of missing out.
    • +
    • How to get from wishlist to cart
    • +
    • Before clicking 'buy,' they check developer and publisher for someone they recognize or trust. They check 'more from this studio' to check familiarity with the dev's other games.
    • +
    • Release more games to build this trust and familiarity.
    • +
    • They check the 'relevant to you' bar to see if the genre matches games they've played and that friends with similar taste also like the game.
    • +
    • How to manage your sales pricing
    • +
    • How to get from cart to library
    • +
    • After loading cart, they ask their friends whether they should go for it.
    • +
    • Your current customers have to become ambassadors to complete this purchase loop. Treat them well!
    • +
    • Abandon cart recovery in other online retailers beckons shoppers back before the sale ends. Steam lacks this, potentially losing devs 10% in revenue - https://www.annexcloud.com/blog/31-shopping-cart-abandonment-statistics-for-2018/
    • +
    • Do a second marketing push during the last day of a sale.
    • +
    • 5 - How to wishlisters into buyers
    • +
    • +
    +
    diff --git a/vps/diary/entries/extra/ideabox b/vps/diary/entries/extra/ideabox new file mode 100644 index 0000000..fc68604 --- /dev/null +++ b/vps/diary/entries/extra/ideabox @@ -0,0 +1,514 @@ +abyssal whip +adamantine +airship +alchemy +aloe +alpine +amber fossil +ambrosia +amulet +anachronism +anagram +animal parade +aphrodisiac +apple +apothecary +apricot +asterism +atelier +aura +baby's breath +backhoe +bad cat +Baldur +bamboo +bandit camp +bandit king +basil +bell tower +birthday dress +birthstone +black bear +black market +The Black Hand +black knight +black water +black widow +blackguard +bloodstone +blue and yellow +blue bell +blue blood +blue rose +bluebell +bonfire +box garden +breath of life +bubble bath +bubble tea +bunny boy +buried treasure +butter cake +butterfly woman +café +camel +candlelight +candy store +caravan +cashmere +castle +cat café +cat familiar +cat man +catnip +catacombs +cathedral +celestial +cemetery +centaur +chained to rocks +chain mail +chalcedony +chameleon +chamomile +chandelier +charmeuse +cheese bread +chiffon +chimera +chives +chocolate factory +chronomancer +chrysanthemum +cipher +citadel +citrine +city of the dead +clipart +clover +coin flip +cold iron +confetti +constellation +cookie cutter +copycat +coral +cotton +couture +cove +crab +crazy quilt +Crossroad Keep +crucibled +crystal sea +cucumber +daeva +dark horse +dark hour +dark paradise +death's-head hawkmoth +deep space +diadem +Diana +diorama +dimetrodon +dire wolf +dollhouse +donkey +doppelgänger +double life +dragonfruit +dragonstone +dreamweaver +dump truck +Dymer +dystopia +ectoplasm +edelweiss +egg hunt +El Dorado +elemental +elipse +elixir of life +emberlight +Entrana +eventide +epitaph +Epsom salt +eternal youth +ettin +evil twin +fable +falling leaves +fairy lights +fairy ring +faun +favored soul +femme covert +femme fatale +fiery sword +fire ball +fire opal +firebrand +fishing village +floating +flower woman +flying +folklore +fountain of youth +forge +fortress +freezing fog +fringe +frog prince +fullness of time +gallows +Garden of Eden +gargoyle +genie +geode +ghost orchid +ghost ship +ghost town +gingham +girl in the internet +girl in white +glow stick +glow-in-the-dark stars +goblin +gold rush +gold standard +golden apple +golden orb weaver +golem +gray weather +griffon +grove +guild +guilty pleasure +hall of monuments +halo +hand of God +the hanged man +hanging garden +happy place +haunted house +headscarf +heart +heather +hermit +hermit crab +holly +holy grail +honeycomb +honeydew +honeysuckle +horizon +hot air balloon +hot and cold game +hot cocoa +hydrangea +igari makeup +illuminated text +imp +incense +invisible man +iridescence +iris +ironwood +ivory +jack-o'-lantern +jacquard +jade chain +jasmine +jellyfish +juicebox +kaleidoscope +kesi silk +kigurumi +kingdom +La Belle Sans Merci +labyrinth +lady cat +Lady of Shallot +Lady of the Lake +lady in black +lake of fire +lair +lamentation +lavender +lemonade +licorice +life-giver +lighthouse +lily +lip gloss +lip oil +Little Red Riding Hood +lizardman +lobster +locket +Lokasenna +loner +loom +lost city +lost continent +lost soul +lotus +love letter +love potion +low poly +lullaby +lunar eclipse +lust +macramé +mages guild +magic carpet +malachite +man in the moon +mandrake +manna +marine +Mars +mask +masquerade +mead of poetry +mean girl +melon soda +memento mori +memoir +mercury rivers and lakes +metamorphosis +meteorite +metropolis +miasma +Midas Touch +Milky Way +millennial moon +mind game +miniature +mink +mirage +mire +mirror of Venus +mirror on the wall +mithril +monastery +money tree +monk's hood +monkey and bear +moon rock +moonflower +moonglow +moonstone +morning glory +mossy cobblestone +moth +mudskipper +mural +muse +naga +necromancer +nightlight +nocturnality +nymph +oneiromancer +oblivion +odalisque +olive +omen +opal +orb +orchid +orichalcum +orphan +palace +panda eyes +paper crane +paper fan +paper lantern +paragon +pearl +periwinkle +personality test +phantom residue +phantom thief +pharisee +philosopher's stone +pickpocketing +pilgrimage +pixie stick +pinwheel +planetary weather +plastic vampire fangs +plushie +poetry and prose +pomegranate +poppy +post-rock +pretzel +princess of Kentucky +principality +prism +prison planet +poinsettia +popcorn +porcelain +propaganda +prophecy +proverb +psalm +pseudonym +pumpkin carving +quiz show +rainbow +raw honey +reaper +reclining woman +red +reverse trap +road roller +rogue +rooibos tea +rose gold +rose petal +rose quartz +rosemary +runestone +s'more +sailor fuku +Sanctum +sandalwood +sandcastle +sandman +sandstone +sanguine, my brother +sardonic +satire +satyr +scone +scrying pool +scythe +sea foam +sea glass +sea of stars +sea storm +seastrand +secret garden +secret passageway +secret room +seven deadly sins +seven heavenly virtues +shapeshifter +sheep +shipwreck +shoegaze +shooting star +silk +silk embroidery +singing sword +skeleton +skipping stone +slide puzzle +slime +smartphone +smoke and mirrors +smoothie +snow globe +soma +soulmate +space cowboy +spooky chews +squid +spellbook +spelunking +spice cookie +spirit animal +spy +stained-glass +star sapphire +stardust +stargazer +starry sky +statuesque +sticker book +stinky cat +stone circle +stone face +stone people +storm cloud +strawberries and cream +strawberry blonde +strawberry shortcake +streusel +sunflower +swamp light +swan song +sword in the stone +taffy +talking forest +tatting +tea garden +tears of Guthix +terrarium +three women +tide pool +tiger's eye +toasted marshmallow +topaz +topiary +toy kingdom +treasure trails +tree of life +treehouse +trick or treat +trickster +tulip +tungsten +underwater +underworld +unicorn horn +unstoppable mailman +urban legend +utopia +vampire +Venice +vanity of vanities +Venus +waiting room +waking dream +walled city +wallflower +wampus cat +wandering eye +wanderlust +wasp lady +watchmen on the wall +water bearer +water nymph +waterfall room +waterlily +weeping willow +Whip-Poor-Will +whisper +white Christmas +will-o'-wisp +wind chimes +wings +wishing well +wisteria +witchhouse +witching hour +wizard tower +wolf's-bane +woman and serpent +the woodsman +workshop +wormwood +wreath +wyvern +yak +Yggdrasil +Ys +zealot +zoo diff --git a/vps/diary/entries/extra/reading-journal b/vps/diary/entries/extra/reading-journal new file mode 100644 index 0000000..2237eff --- /dev/null +++ b/vps/diary/entries/extra/reading-journal @@ -0,0 +1,36 @@ + +

    reading journal

    +january 8, 2020
    +
    +
    +I'll collect summaries, thoughts, and excerpts as I read. I used to read so much more. I should read more.
    +
    +reading now
    +
      +
    • The Goddess of Atvatabar: being the history of the discovery of the interior world, and conquest of Atvatabar - William R. Bradshaw (1892)
    • +
    • An American Tragedy - Theodore Dreiser (1925)
    • +
    • How Few Remain - Harry Turtledove (1997)
    • +
    +
    +
    +books to read next
    +
      +
    • The Divine Comedy - Dante Alighieri (1320)
    • +
    • The Pilgrim's Progress from This World, to That Which Is to Come - John Bunyan (1678)
    • +
    • The Faerie Queen - Edmund Spenser (1590)
    • +
    • Waiting for Godot - Samuel Beckett (1953)
    • +
    • Metamorphoses - Ovid (8)
    • +
    • The Canterbury Tales - Geoffrey Chaucer (1320)
    • +
    • Phantastes - George MacDonald (1858)
    • +
    • The Lady of Shalott - Alfred Tennyson (1833, 1842)
    • +
    +
    +
    +completed books
    +
      +
    • Candide - Voltaire (1759)
    • +
    • Drinker of Souls - Jo Clayton (1986)
    • +
    • Making of a Bigot - Rose Macaulay (1914)
    • +
    • Magic: A Fantastic Comedy in a Prelude and Three Acts - G.K. Chesterton (1913)
    • +
    +
    diff --git a/vps/diary/entries/extra/stop-the-steal b/vps/diary/entries/extra/stop-the-steal new file mode 100644 index 0000000..69660a1 --- /dev/null +++ b/vps/diary/entries/extra/stop-the-steal @@ -0,0 +1,7 @@ + +

    March for Trump

    +january 6, 2020
    +
    +
    +Today, the March for Trump resulted in a Capitol break-in. The photos are like something out of a videogame. I took them from Twitter, so I can't easily credit.
    +
    diff --git a/vps/entries/200806 b/vps/entries/200806 new file mode 100644 index 0000000..6f6bdd4 --- /dev/null +++ b/vps/entries/200806 @@ -0,0 +1,21 @@ + +

    what is blessfrey?

    +august 6, 2020
    +#gamedescription
    +
    +blessfrey is a 2D action RPG developed for PC by chimchooree.
    +
    + + (image: Lots of Angels and other characters at a shopping center) +
    +
    +The game is designed to pit your skill + creativity against a series of combat + puzzle challenges while exploring the depths of the downtown dungeon.
    +
    +Class progression is freeform, and virtually no decision is permanent. At character creation, you will choose a permanent First Class, but you can unlock several new classes for multiclassing through gameplay. Through swapping out Second Classes, you can find a combination to express your playstyle.
    +
    +Each class has its own style of skills associated with it. Skills are individual powers gained through gameplay which give specific effects according to their rules. Your skillbar only has 8 skill slots and can only be edited in safe areas. The challenge comes from building winning strategies + synergies against the next area.
    +
    +Skills are gained through exploration of the game world. As you encounter enemies, meet people, and reach new areas, you will translate those experiences into new skills. There are multiple paths to learning, so you can focus on parts of the game you prefer.
    +
    +blessfrey has been lots of fun to work on. I hope you enjoy it once a demo and eventually a game drops.
    +
    diff --git a/vps/entries/200820 b/vps/entries/200820 new file mode 100644 index 0000000..4ad4f7f --- /dev/null +++ b/vps/entries/200820 @@ -0,0 +1,13 @@ + +

    free pixel font

    +august 20, 2020
    +#assets
    +
    +pixel joy is a small, round sans-serif pixel font, made using FontStruct's FontStructor for an old version of blessfrey. Freely use and edit for your personal and commercial projects. No credit needed.
    +
    +Download it from FontStruct.
    +
    +
    image: pixel joy font preview

    +
    +Font released under public domain. Sample text in the preview image is from Imogen Heap's "Pocket Sun," and the colors are from Adigun Polack's AAP-64 palette. :)
    +
    diff --git a/vps/entries/200901 b/vps/entries/200901 new file mode 100644 index 0000000..e714b75 --- /dev/null +++ b/vps/entries/200901 @@ -0,0 +1,87 @@ + +

    august 2020: new server, new site

    +september 1, 2020
    +#apache #css #html #nginx #php #server #website
    +
    +

    tuesday, august 4

    +
      +
    • CentOS VPS obtained through OVH. Always wanted a server.
    • +
    +
    +

    wednesday, august 5

    +
      +
    • design the website
    • +
    • prototype of website running on the server
    • +
    +
    +

    thursday, august 6

    + +
    +

    friday, august 7

    +
      +
    • decide to use PHP for manage blessfrey's blog
    • +
    • set up a local Apache server for practice. It was a little confusing!
    • +
    • wrote a vaguely functioning Hello World script in PHP
    • +
    +
    +

    saturday, august 8

    +
      +
    • added images to live site despite conflicts with Linux's security
    • +
    +
    +

    sunday, august 9

    + +
    +

    monday, august 10

    + +
    +

    saturday, august 15

    +
      +
    • Made a Python script that spits out new skill scenes for Godot after answering a little command line questionnaire. I could make it an plugin for the engine, but it would be a lot slower to develop + functionally no better.
    • +
    • Maybe I can rewrite it later in JSON, since Godot can read JSON.
    • +
    +
    +

    monday, august 17

    +
      +
    • Research PHP + MySQL while attending. I think MySQL is overkill for my purposes, since all my articles couldn't possibly be that much data. It might be interesting for analyzing data, though, like adding a word cloud of the most common tags or a search feature. I'll keep things simple for now.
    • +
    +
    +

    august 18 - august 21

    +
      +
    • Help run a FlightRising community event while trying out ArcheAge, since my friends play it.
    • +
    • I told a friend I would play Go with him soon but was too busy with the raffle. Then someone told him I was online a lot in ArcheAge...oops...that looked bad lol. It wasn't like I played more than a few minutes at a time. I'm sorry, friend;;
    • +
    • finally get access to the code for an MMO some friends work on. I start familiarizing myself with the code and start planning my new feature.
    • +
    +
    +

    saturday, august 22

    +
      +
    • I work on pagination. The concept boggles my mind, but I can break it into pieces to solve like any other problem.
    • +
    +
    +

    sunday, august 23

    +
      +
    • I work on my friends' MMO more. I make my own branch and make my first changes. The work environment is Windows-only, and the server is live with active players. Pretty cool experience.
    • +
    +
    +

    monday, august 24

    +
      +
    • Still working on pagination in PHP to create a navigation bar for my development blog.
    • +
    +
    +

    tuesday, august 25

    +
      +
    • Play around with CSS + HTML for the website. The CSS Grid didn't exist the last time I used CSS (for 2000s petsite profiles), so I'm more comfortable with floats. The Grid looks so worth learning, though, for more consistent and responsive web design.
    • +
    +
    +

    wednesday, august 26

    +
      +
    • Get the landing page looking okay while using the CSS Grid.
    • +
    +
    diff --git a/vps/entries/200903 b/vps/entries/200903 new file mode 100644 index 0000000..4539c38 --- /dev/null +++ b/vps/entries/200903 @@ -0,0 +1,76 @@ + +

    my first game jam - #weeklygamejam

    +september 3, 2020
    +#gamejam
    +
    +WeeklyGameJam is a weekly theme-based game jam hosted through itch.io. It's fairly laid-back for a jam, giving you a full week's time, allowing for premade/stock assets and code, and being understanding towards late submissions. Most people make videogames, but any kind of game is allowed. At the end of the week, streamers will play and critique the submissions while the devs hang out in their chatrooms.
    +
    +
    (image: Key art of Elwell and Small Thing, buried in dogs)

    +
    +
    +

    small thing that makes things

    +
    +I participated in Week 85 under the theme Offspring, submitting my game on February 27, 2019. My game was Small Thing That Makes Things, an adventure platformer. You can play it on itch.io.
    +
    +You play as Hamish T. Elwell, the hero accountant of an overcrowded animal shelter, investigating the recent explosion of the local stray population. You can walk, jump on platforms, collect items, and chat with NPCs. There's multiple endings, depending on your choices.
    +
    +
    +

    positives

    +
    +For a week-made game, I think STTMT is pretty cute, and I'm pretty happy with it.:)
    +
    +I actually finished a game, and someone actually finished playing it on a stream. That's really cool, even if STTMT isn't all that good. The deadline forced me to make final decisions, complete features, and move on, and there's a lot of value in that.
    +
    +The short time-frame forced me to get around to every aspect of game development, many of which I had never done before. I had to learn how to export a Godot project, upload an HTML5 game to itch, and make sure the exported game was complete and playable. Lots of the features were first-times for me, too. I've never written code for platformer movements or moving cameras. This also was the first time I've really gotten branching and conditional dialog working in Godot, which was a skill I immediately applied to blessfrey.
    +
    +
    +

    mistakes

    +
    +I recolored OPP's pixel art and lost the high contrast for the rock ledges. They blend into the rocky background, so you can't tell you can jump on them. I didn't even notice until Joshua McLean pointed this out during his stream. Having more eyes on your game is so important.
    +
    +Also the level design is just not interesting. I spent lots of time on the choices and adventure game aspects, while the platforming as an extreme afterthought. It's a game jam, though, what do you expect?
    +
    +I took the easy way out with animation. I might have learned more working from scratch, but modifying OPP's sprites to suit my character designs was way faster when I was already struggling to finish on time.
    +
    +
    +

    screenshots + progression

    +
    + + (image: Elwell and Small Thing in a jumble of dogs) +
    +Experimenting with Small Thing's summoning mechanic. In this version, the characters are just blocks with collision that can move around the flat, empty world with WASD.
    +

    + + (gif: Elwell rides a broken-physics dog across the valley) +
    +The dog spawning physics was (and still is) really broken, so dogs go flying pretty frequently. It was reliable enough in this version to be used as a moving platform.
    +

    + + (image: Elwell watches the rainfall of dogs from his window) +
    +Dogs rain down upon Elwell's animal shelter in the finished version.
    +

    + + (image: Dialog) +
    +Dialog between Elwell and his boss.
    +
    +
    +
    +

    conclusion

    +
    +If you're looking for a jam to jump into, WeeklyGameJam is a cute one to try. You aren't too rushed, you get to watch people play your game, you get useful criticism, and the community is pretty chill. The themes are always inspiring, too.<3
    +
    +
    +

    credits

    + +
    diff --git a/vps/entries/200917 b/vps/entries/200917 new file mode 100644 index 0000000..314a064 --- /dev/null +++ b/vps/entries/200917 @@ -0,0 +1,81 @@ + +

    coroutines in godot engine

    +september 17, 2020
    +#programming
    +
    +Coroutines are functions that, instead of running to completion, can yield until certain criteria are met. Godot Engine supports coroutines through yield ( Object object=null, String signal=""), resume, and the GDScriptFunctionState object.
    +
    +

    why use a coroutine?

    +
    +Coroutines allow for scripted game scenarios that respond dynamically to the player and the changing game world. They let you bounce between functions, step-by-step, and respond to interruptions. This means functions can be automatically called at the completion of other functions, animations, player actions, in-game events, or timers. Add in interruptions and conditionals, and you have a tool for building a responsive game world.
    +
    +
    +

    stoplight example

    +
    +As a basic example of coroutines in Godot Engine, I made a stoplight. Follow along with my code on GitLab.
    +
    +In my example, the light changes every few seconds, going from green, yellow, then finally red. The light changes immediately if the Walk Button is pressed. This project demonstrates methods that can wait, resume, and be affected through player action.
    +
    +
    + + (gif: demonstration) +
    +
    +
    +
    +

    how does it work?

    +
    +

    node hierarchy

    +
    +(image: node hierarchy - Root is a node named Main. It's children are TextureRect BG, AnimatedSprite Stoplight, Sprite WalkButton, and a Label. Stoplight's child is a Sprite. WalkButton's child is a TextureButton.)
    +
    +
    +
    +I have a TextureRect background, an AnimatedSprite stoplight, a Sprite walk button with a TextureButton, and a label for displaying a timer. Since this is a simple example, most of the code is attached to the root. It's better to have code closer to where it's being used and to watch your separation of concerns in real projects, though.
    +
    +
    +

    animation

    +
    +
    +(image: the AnimatedSprite Stoplight has 4 animations - default (which is no light), green, red, and yellow.)
    +

    +The light is changed by setting its animation to one of these options. Each is one-frame - just the stoplight with the one or none of the lights colored in.
    +
    +
    +

    the code

    +
    +This project has two scripts: Main.gd, which is attached to the root node, and Label.gd, which is attached to the Label.
    +
    +Main.gd - code available on GitLab
    +
    +(image: Main script.)
    +
    +
    +Label.gd - code available on GitLab
    +
    +(image: Label script.)
    +
    +
    +
    +

    how the code works

    +
    +At _ready(), wait() is assigned to the GDScriptFunctionState result and is called for the first color, green. _ready() yields until the given function wait() is completed.
    +
    +The wait method yields for the given amount of seconds then sets the stoplight to the given color.
    +
    +At wait()'s completion, _ready() calls wait() for yellow, then red. Each is called one at a time, waiting for the color to complete before moving on.
    +
    +
    +

    interrupting the stoplight

    +
    +The Wait Button interrupts the wait times between colors. Before _ready() yields, it connects the 'pressed' signal on the Wait Button.
    +
    +If the Wait Button is clicked during wait()'s yield, the GDScriptFunctionState result resumes immediately, ignoring wait()'s yield timer. This time, result has a string arg 'interrupted on green', so it will print the result, change the stoplight's color, then print 'done: green'. The wait method is complete, so _ready() resumes and calls wait() for the next color.
    +
    +
    +

    applications

    +
    +The outcomes in this example be swapped out for anything. I use coroutines in blessfrey's skills to manage the flow of phases from activation, different phases of effects, cooldown, and interactions with any counters. I also use it in the basic weapon attack so the character continuously swings at the rate of his attack speed until he cancels, uses a skill, or moves. It could also be used for something like cars that stop and honk when the player walks in front of them and drive off once the path is clear.
    +
    +Coroutines enable lots of practical ways to improve the flow and interactivity of your game, so just keep experimenting.
    +
    diff --git a/vps/entries/201001 b/vps/entries/201001 new file mode 100644 index 0000000..d71229e --- /dev/null +++ b/vps/entries/201001 @@ -0,0 +1,37 @@ + +

    september 2020: bye php, hello bottle

    +october 1, 2020
    +#bottle #css #git #html #regex #regularexpressions #website
    +
    +

    wednesday, september 2

    +
      +
    • Study examples of my favorite blogs, popular blogs, and just any blogs I can find from modern gaming, retro gaming, tech, cooking, beauty, and any genre
    • +
    • Determine essential features for my blog
    • +
    • Plan design of blog
    • +
    +
    +

    friday, september 18

    +
      +
    • decided to switch from PHP to Bottle
    • +
    • Hello World in Bottle
    • +
    • created templates for main pages
    • +
    • Used Bottle to fill values in a template using variables
    • +
    • Used Bottle to avoid repeating HTML code in navigation pane, header, and footer
    • +
    +
    +

    friday, september 25

    +
      +
    • Diary snippets are formatted from data taken from their articles. The article preview is cut to the character limit.
    • +
    +
    +

    saturday, september 26

    +
      +
    • Updated the blessfrey.me script to serve static content like CSS stylesheets + images. Now the pages are actually styled.
    • +
    +
    +

    wednesday, september 30

    +
      +
    • fix bugs for blessfrey.me's static pages - no footer in the middle of the body, no unclosed <ul> tags from diary entry snippets breaking the CSS.
    • +
    • w3's Nu Html Checker (lol @ the nu name) is really handy for automatically checking whether all my HTML tags are closed and CSS is valid, especially the parts generated through Bottle + SimpleTemplate.
    • +
    +
    diff --git a/vps/entries/201015 b/vps/entries/201015 new file mode 100644 index 0000000..1e95006 --- /dev/null +++ b/vps/entries/201015 @@ -0,0 +1,68 @@ + +

    making of blessfrey.me

    +october 15, 2020
    +#bottle #css #html #simpletemplate #webdesign #webdev
    +
    +blessfrey.me is a personal website I use to showcase projects + blog my process. I originally wrote it in PHP, but now it's written in Bottle, a Python web framework.
    +
    +
    +

    why not use a premade blogging platform like WordPress?


    +blessfrey.me's needs are fairly simple - just some static pages and a blog page. Generalized blogging platforms are overkill. I don't need support for multiple users, localization, e-commerce, and so on. Unused features only bog down the website, potentially contributing to poor performance + security vulnerabilities.
    +
    +Also, it's just fun to write my own. I'm learning a lot as I take my website from initial sketches, to Hello World, to various prototypes, to something polished enough to show my friends. Also, since it can be considered a programming portfolio, it just makes sense that it itself should be something I programmed.
    +
    +
    +

    why Bottle?


    +I originally wrote blessfrey.me in PHP. I switched to Bottle after looking for a templating engine. Bottle comes with SimpleTemplate and can do everything PHP can do but faster + with less verbosity. Plus, you get to write in Python, which is always fun.
    +
    +
    +

    how does blessfrey.me work?


    +

    SimpleTemplate


    +Instead of a static collection of HTML pages on my server, blessfrey.me's pages are constructed from SimpleTemplate templates and filled in using a Bottle script upon request.
    +
    +Every page uses the frame template below, so the basic skeleton is consistent and code for repetitive elements only has to exist in one place. Each page's content is made unique by bringing in a different template as {{!base}}. (Double curly brackets refer to variables, and exclamation marks disable escaping.)
    +
    +(image: basic template code.)
    +
    +(The code can be found on Pastebin.)
    +
    +The header template below (brought in at % include('header.tpl')) has some variables, too, which are supplied by the Bottle script. If Bottle doesn't provide a title, it defaults to 'blessfrey.me.' Variables can also be used in paths and URLs.
    +
    +(image: header template code.)
    +
    +(The code can be found on Pastebin.)
    +
    +You can insert Python code into the templates for dynamic pages. Below is an excerpt of the template for the diary page. This code fills the page with diary entry previews using a for loop. Not shown is the first line % rebase('frame.tpl'), which tells SimpleTemplate to insert this content at the {{!base}} variable in the frame template.
    +
    +(image: diary snippet code from diary template.)
    +
    +(The code can be found on Pastebin.)
    +
    +The Bottle script sends the max number of snippets per page (the limit) and a list of lists containing all the diary snippets. It receives the page number from the URL. For the snippets that will appear on the given page, it converts the list data into HTML code to be displayed in the browser.
    +
    +
    +

    Bottle


    +Bottle takes URLs and generates the corresponding web page upon request. Each URL is tied to a method, which returns a template and a dictionary of data to be used in the template. Since Bottle is a Python framework, you have access to all the Python libraries you need.
    +
    +(image: Bottle script excerpt for diary routes.)
    +
    +(The code can be found on Pastebin.)
    +
    +This is what the methods for specific routes look like. So every time you go to blessfrey.me/diary, one of the above methods is called, depending on whether also you supplied an integer. To generate the page content, it calls a lot of Python functions to find my diary entries, convert them into previews for the snippets section + headlines for the sidebar, and get the current time for the footer.
    +
    +
    +
    +

    CSS


    +The website is styled using CSS, heavily relying on the CSS Grid and a bit of Flexbox. CSS Grids can be used inside CSS Grids, so my pages are generally blocked out, with smaller internal grids managing specific content.
    +
    +(image: CSS Grid traced over screenshot of projects page.)
    +
    +
    +The projects page is an example of nested grids. Almost every page uses the yellow general layout. The content unique to the projects page is mapped out in green, with a section for the header, featured projects, and other projects. The other projects use a 2-column grid in blue to evenly space out all the little thumbnails.
    +
    +The CSS code for project's general grid + the nested unfeatured grid are shown below.
    +
    +(image: projects css code.)
    +
    +(The code can be found on Pastebin, but you can always see a web page's CSS by right-clicking and viewing the source.)
    +
    diff --git a/vps/entries/201029 b/vps/entries/201029 new file mode 100644 index 0000000..17318df --- /dev/null +++ b/vps/entries/201029 @@ -0,0 +1,65 @@ + +

    blessfrey in japanese

    +october 29, 2020
    +#internationalization #localization
    +
    +Instead of hard-coding text, keep it in a spreadsheet instead. It's easier to organize, edit, and it also makes possible future translations a much smoother process.
    +
    +I followed along with GoTut's "Localisation in Godot" guide, but the process is pretty simple. It's a great guide, so honestly just follow theirs instead. I'll echo the process here in case it's taken down, though.
    +
    +

    step 1 - make your spreadsheet

    +
    +
    + + (image: spreadsheet with three columns - id, en, and ja. id has ids, en has English text, and ja has Japanese text.) +
    +
    +
    +Instead of writing your text directly into Godot, refer to the text by ids instead. These ids will be kept in the first column of your spreadsheet. Don't use spaces.
    +
    +The rest of the columns will hold the corresponding text in different languages. Name these columns after the language's locale code. English's is en, and Japanese's is ja. You can find the more codes in the Godot Docs.
    +It works just fine if you're only using one language. If you have multiple languages but don't provide a translation for a specific id, whenever your game is set to that language, references to that script will show blank text.
    +
    +Save your spreadsheet as a .CSV file.
    +
    +
    +

    step 2 - import your spreadsheet

    +
    +Make sure your .CSV spreadsheet is in your game folder, so Godot can automatically import files. Wherever you import your text, make sure you check 'Comma' for the delimiter or separator options. You'll get a few .TRANSLATION files.
    +
    +
    +(image: Project Settings>Localization>Translations shows a TRANSLATION file for each language.)
    +
    +
    +From Godot's top menu, go to Project>Project Settings...>Localization>Translations and add all your .TRANSLATION files. They'll be right next to wherever you saved your .CSV.
    +
    +
    +

    step 3 - refer to your ids in your scripts

    +
    +
    +(image: example of an id used in a script)
    +
    +
    +It's really simple stuff. Anywhere you would have written a string, like "quit", you instead use its id wrapped in tr(). So instead of label.set_text("quit"), you'd write label.set_text(tr("quit_game")). In this example, the id is "quit_game" and its corresponding text in English is "quit." +
    +
    +

    step 4 - set the game's language

    +
    +
    +(image: example of setting the locale in a script)
    +
    +
    +Set the locale in your script, somewhere like _ready() or on a 'change language' button. Here's the line for setting the locale: TranslationServer.set_locale("ja") +
    +
    +

    step 5 - continue adding to your spreadsheet

    +
    +Now that everything's in place, you can keep adding new ids + translations, and Godot will automatically use your changes in-game.
    +
    +

    that's the basics

    +
    +(image: blessfrey screenshot in Japanese)
    +
    +
    +It all comes together for an old screenshot of blessfrey's main menu in my broken Japanese. やべーな!
    +
    diff --git a/vps/entries/201101 b/vps/entries/201101 new file mode 100644 index 0000000..a2b35af --- /dev/null +++ b/vps/entries/201101 @@ -0,0 +1,85 @@ + +

    october 2020: a blog that works

    +november 1, 2020
    +#css #html #python #webdev #website
    +
    +

    week 1


    +#bottle #python #regularexpression #website
    +
    +

    thursday, october 1


    +
      +
    • blessfrey.me's diary properly displays snippets for all articles: a header taken from the title, a truncated view of the article, the date + a place for social media share links, and a link to the article.
    • +
    • Cleaning the snippets enough to look okay and not break the page was a challenge. I used regular expressions to remove HTML link + header tags, which is apparently a lost cause Stack Overflow users stand against daily, hourly even. It's not so bad if it's not user content and the content is pretty predictable, right? +
    • Pythex is useful for checking whether your regular expression will catch your target strings
    • +
    • First command line git merge. I usually do it on the website. It's really simple - switch to the branch you're merging the second branch into, type 'git merge second-branch' (second-branch = name of the second branch obviously), and fix any conflicts.
    • +
    +
    +

    friday, october 2


    +
      +
    • All articles are kept in the same folder. There's really no reason to split them up. If I want to differentiate types of articles, I can use tags or something.
    • +
    • Set up blog navigation
    • +
    +
    +

    saturday, october 3


    +
      +
    • Blog removes HTML tags through regex patterns.
    • +
    • Fixed footer strangely appearing in the middle of the body on pages.
    • +
    +
    +

    week 2


    +#bottle #python #website
    +
    +

    sunday, october 4


    +
      +
    • Started using absolute paths when needed. Diary snippet links to articles work now. Articles use CSS now.
    • +
    • Improved navigation for diary. The number link cluster around the current page stays static in length - very early pages compensate by adding more links to the right
    • +
    +
    +

    monday, october 5


    +
      +
    • made 'latest' box in sidebar of diary + articles with working links to the 5 latest articles
    • +
    +
    +

    tuesday, october 6


    +
      +
    • researched + added a robots.txt, sitemap, nofollow links
    • +
    • added social media share links to all snippets that allow you to share the title and a link to Twitter, Facebook, or email. Not sure if Facebook or email work because I don't feel like getting Facebook or connecting email to my browser.
    • +
    +
    +

    wednesday, october 7


    +
      +
    • Added a simple Contact page.
    • +
    • Moved diary entries under a diary directory for that /diary/whatever-entry URL, so people like me can backspace on that URL to get to the higher level page.
    • +
    +
    +

    saturday, october 10


    +
      +
    • For testing, all colors were taken from the latest colors on random color websites, and all divs are stark. Instead, I have added margins, padding, sans-serif font choices, and an okay color palette. I'll pick something more true-to-brand later, but at least it isn't embarrassing now.
    • +
    +
    +

    tuesday, october 13


    +
      +
    • updated site skillbar nav background art.
    • +
    • continue working on CSS files.
    • +
    • made Twitter timeline's background transparent on index page
    • +
    +
    +

    tuesday, october 16


    +
      +
    • edit game and presskit pages and some diary entries
    • +
    • for site navigation, CSS buttons are now image links with superimposed text. I think keeping text as text instead of part of images helps with accessibility. I use a lot of foreign websites, so personally, I like websites where I can copy + paste.
    • +
    +
    +

    saturday, october 17


    +
      +
    • worked at the cafe today. Since my husband's battery is dead, he finally read some May I Ask For One Final Thing? I love that manga!!
    • +
    • Refactored the main Bottle script. Before, I wrote it hard and fast, so it was reading all the diary entries multiple times per refresh. It's not only cleaner now, it also only reads the files twice.
    • +
    +
    +

    monday, october 19


    +
      +
    • did some sketches for the story slideshow for the game page. they are an iteration of some cg art for the real game, too. I really don't draw enough...
    • +
    • added the 'recommended articles' section to the bottom of diary entries.
    • +
    • added 'extra' articles, for articles that are unlisted from the main directory. I'm using it to include more GDC talk notes per talk while keeping the GDC talk article general and summarized.
    • +
    +
    diff --git a/vps/entries/201112 b/vps/entries/201112 new file mode 100644 index 0000000..3aaf6d6 --- /dev/null +++ b/vps/entries/201112 @@ -0,0 +1,39 @@ + +

    tidying up my skill phases

    +november 12, 2020
    +#programming #skills
    +
    +In Godot Engine, you can call methods from a parent class by prefixing it with a period (.). So to access the move() method from a parent, call .move(). This is called a super method.
    +
    +Being called super doesn't mean there isn't a better way, though. I used to use super methods to build customs skills in blessfrey, but subfunctions is tidier.
    +
    +(Just so you know, blessfrey's skills have a number of phases of effects that must happen in order: skill press > activation > initial phase > main phase > end phase > cooldown.)
    +
    +
    +

    the old way


    +Initially, I used super methods to give each phase custom effects and call the next phase. This was messy. If I ever redesigned the flow of the skill phases, I'd have to edit every single skill script. It also causes a lot of repetitive code in the individual skill scripts while the base script is tiny. The one-time script being the small one is no fair.
    +
    +(image: GDscript code using old method)
    +
    +(You can see the old method's code on Pastebin.) +
    +
    +

    the new way


    +
    +Instead, I can bring all the repetitive steps into the base class, sandwiching in a subfunction where the custom effects would take place. Now I only need to add what makes my skill unique inside the subfunction.
    +
    +I named the subfunction after its main function and added an underscore to the front. So in the base script, I fit _functionality(user, action_target) into functionality(user, action_target). Then the individual skill scripts only need the subfunction, none of the other repetitive code from before. The subfunction is empty in the base class and filled with unique code in the child classes. Since skills inherit, the unique _functionality subfunction will be called automatically from the base script's functionality.
    +
    +
    + + (image: GDscript code using new method) + +
    +(You can see the new method's code on Pastebin.) +
    +
    +

    problem solved!


    +
    +The base script holds all the lengthy code in one place, while I only need to write the unique effects in all the hundreds of skill scripts. That saves me time making, refactoring, and maintaining skills. Yay.
    +
    + diff --git a/vps/entries/201126 b/vps/entries/201126 new file mode 100644 index 0000000..53738ee --- /dev/null +++ b/vps/entries/201126 @@ -0,0 +1,49 @@ + +

    pretendOS - a game inspired by windows XP

    +november 26, 2020
    +#sideproject
    +
    +Getting started with blessfrey's AI was overwhelming, so I took a break and worked on a new game. I didn't get very far. It's not even on my hard drive anymore. It's cute, though.
    +
    +Unlike blessfrey, where coding takes up 90% of the effort, pretendOS is mostly graphical assets + sounds with barely any functionality. It's a UI game, after all. Since it's a game requiring a completely opposite skill-set, I was able to make progress on something while reading up on game AI. I also got to work on new things like particle effects.
    +
    +
    +

    Inspiration

    +
    +

    Windows XP

    +The game takes strong aesthetic inspiration from Windows XP. It almost fits the 90s vaporwave trend, but I'm too young to really remember Windows 95. I obviously have nostalgia for it as my first operating system (as far as I remember - I was a toddler then), but I mostly knew it as the Lego Island machine propped up in the dining room. As my family upgraded computers over the years, Windows never really impacted me as anything more than something that can run some videogames and whatever popular web browser of the time. That is, until Windows XP.
    +
    +XP really hooked me. It was the first operating system I spent as much time exploring as I spent using software. XP's edition of Paint was my favorite yet, I loved fiddling with the themes and accessibility options, especially Microsoft Sam, Rover, and Clippy. I started watching YouTube videos on how to use the Command Prompt. XP was just fun to use. I've found better desktop environments and operating systems since, but I never got over that aesthetic: smooth, blended graphics with hard pixel edges in 32-bit color with an alpha channel, right at the cusp between pixel art and vector graphics. Vaporwave for me is Luna olive green, or the "Fisher-Price interface" as Ars Technica users called it.
    +
    +(image: Wikipedia excerpt: Critics who did not like the theme characterized it as a 'Fisher-Price interface'.)
    +(screenshot from Wikipedia - referencing articles from PCWorld and Ars Technica)
    +
    +
    +There were a few other experiences behind the game, too.
    +
    +

    Mother's Day E-Card

    +I finally got my husband to try Godot Engine, and he used it to make a digital Mother's Day card for his mom. (Cute.) Opening the card displayed a 3D heart (a "cardioid") that bounced to the beat of a song while 2D cardioid particles rained down. It was all programmatically generated using geometry instead of 3D + 2D assets, so the application was very small. He made the graphics side of things look really interesting, and I wanted to play around with particles, too. Just...not as fancy;;
    +
    +

    Secret Little Haven

    +I also just played a cute pretend OS game on itch called Secret Little Haven It's quite short, very story-driven, and kind of buggy, telling Alex's struggle with gender identity through IMs. Honestly, pretend OS games and coming-of-age chat sims are nothing special, but Secret Little Haven's believability makes it really stand out. Instead of defending against cheesy + inaccurate deep web hacking attempts, you use an in-game terminal to get around child locks set by Alex's dad. Those terminal puzzles are the most realistic and relatable hacking I've seen in these games. SLH isn't super sophisticated or in-depth, but it shows how cute and believable a pretend OS game can be. I'd love to make a little environment like that, that's as fun to fiddle around with as XP.
    +
    +
    +

    pretendOS

    +
    +So what's pretendOS? Like I said, not much besides pictures. I only worked on it for a few days.
    +
    +What really bogged it down was Cat Chat. I wanted an AI chat personality that talked like a cat. I could do that, but that kind of thing takes a lot of time, when this project was really just procrastinating working on AI.
    +
    +The rest is cute, though. The icon winks when you click it, the cursor's kinda 2000s-free-animated-cursors, and it's got those Fisher-Price colors and bubbly sounds everywhere that I liked as a kid.
    +
    +
    + + (image: pretend desktop with a Cat Chat application) +
    +
    +
    +
    +

    the future

    +
    +It's cute. I'd like it to be finished in some way. I went ahead and cloned my old repo. Maybe I'll fill it out with more applications during a game jam or something or at least finally get that cool Secret Little Haven curved screen shader working.
    +
    diff --git a/vps/entries/201201 b/vps/entries/201201 new file mode 100644 index 0000000..fcd2e30 --- /dev/null +++ b/vps/entries/201201 @@ -0,0 +1,33 @@ + +

    november 2020: dear diary

    +december 1, 2020
    +#blogging #bottle #skills #webdev
    +
    +

    on topic

    +Between the 8th and 15th, I wrote a Python script for generating Godot skill scenes from JSON files. As opposed to the questionnaire script I used before, this one can generate multiple skills at a click of a button. It isn't a perfect solution either, though, since my JSON script and the skills I have in the game aren't synced. It'd be better for the skills to be something like JSON files that are read by the game at run-time, unless that would be too costly. That way, I only edit skills in one location and don't need to worry about different versions.
    +
    +Skill inheritance is more sophisticated now and allows the script to generate a lot of the functionality of most types of skills now.
    +
    +I spend a lot of time on how to make skills because this is a core mechanic of my game, and I plan to have a hundred or more of them. I need an efficient way to update and create the game's skill pool.
    +
    +On November 24, 2020, I finally added a diary navigation bar under the diary snippets, so you don't have to scroll back up to go to the next page anymore. I was really putting that off for how essential that is.
    +
    +On November 25, 2020, I began retroactively adding diary entries based on old tweets. I added one for my pixel font, one for my Weekly Game Jam submission, one for my inventory system diagram, and one for blessfrey's graphic updates. I finally got Bottle to support self-hosted images instead of using Imgur for everything (lol), and fixed lots of bugs related to actually having embedded images in articles.
    +
    +As cool as it is to work on gamedev, this website is also a priority for me as a sort of portfolio. So it would be nice to have lots of articles about my process and different projects. It would be super nice to have pretty graphics everywhere, but as usual, the placeholders are probably going to stay around for a while since they're already half-decent-looking.
    +
    +November 26, 2020 is Thanksgiving during a pandemic. Wrote up an article for my pretendOS game and my coroutines example. Also, the diary shows 8 snippets per page instead of 4. I finally have enough articles to test an optimal amount shown per page.
    +
    +November 27, 2020 is Black Friday. I ordered navy eye shadow and fancy sunscreen.<3 Added an article for skill phases + super methods and slimeAI's state transition diagram.
    +
    +November 28, 2020 is my birthday. <3 I replaced the game page with a projects page with pretty CSS grid formatting and little thumbnail links to different projects, either to diary entries or git repos.
    +
    +November 29, 2020, I make sure all the thumbnails are consistent sizes for the projects page make the images and descriptions into links. I also add a thumbnail for the website itself because why not? It doesn't have anything suitable to link to, so I wrote up an article explaining blessfrey.me's development. I touched up the presskit page and added a PDF download to the page. Downloads are way easier to add than I thought they'd be - seriously took me less than a minute. The presskit page is still ugly, but at least it has better images on it now. I'm getting close to actually letting people see my website (even though it's been publicly accessible pretty much since August but whatever), so I went through my articles again and improved their readability and removed most stuff that isn't really relevant.
    +
    +November 30, 2020, I reordered the diary entries again. The daily diaries really should be released after the month is over instead of on the last day of the month. Duh. Also, the 3-week-nonstop-earworm of Seungri's "Let's Talk About Love" finally went away. It was becoming pathological.
    +
    +

    off-topic


    +I joined a Japanese manga translation group on a whim and now provide Japanese-to-English transcripts for a new chapter of a manga about every week and a half. It wasn't obvious, but understanding Japanese is a different skill than rewriting Japanese into English while keeping the jokes, character voice, and cliffhangers/foreshadowing intact;;
    +
    +Also, Election Day-turned-Weeks took up a few extra days of nonstop news watching than it usually does, even though I tuned out long before Georgia was called.
    +
    diff --git a/vps/entries/201224 b/vps/entries/201224 new file mode 100644 index 0000000..321224f --- /dev/null +++ b/vps/entries/201224 @@ -0,0 +1,43 @@ + +

    blessfrey graphic updates + mockups

    +december 24, 2020
    +#mockups #screenshots
    +
    +I iterate over the graphics periodically, so I can practice without worrying about polish. Here's some screenshots of different styles I've tried. (Though April 23, 2019's is actually a mockup, that style did run in-engine for a few weeks.)
    +
    +
    + + (image: Cassia and Bad Cat on the pink carpet tilemap) +
    +August 15, 2018 - Early experimenting with Godot Engine. Collision was just added for sprites and walls. The buttons to the right are for switching between characters (who each have different skillbars).
    +

    + + (image: Angel in a periwinkle room full of Bad Cats) +
    +January 13, 2019 - Videogame perspective is so different from perspective in illustration. Scale of characters vs environment is another quirk of games I had 0 experience with. I was vaguely going for an old Western RPG style with tall, somewhat realistic sprites with non-distinct faces. Something like Divine Divinity.
    +

    + + (image: Angel blasting a neighborhood coyote with fire) +
    +April 23, 2019 - This is a mockup, but the game did look like this for a while. The fireball projectile didn't come until later, though. Here, I was trying to get a little more of a top-down view but not really. Instead of cats, Angel's fighting with a coyote. The government stopped removing coyotes from my old neighborhood, so they killed all the neighborhood cats except one and I saw him running away from a big coyote during a storm, so maybe he's gone now, too. It's just not right.
    +

    + + (image: Angel and Chloe in front of a slanted house) +
    +May 25, 2019 - The slanted edition was so annoying. It's not isometric, it's just at an obscure angle because I drew these assets more for fun than to actually be practical. I do reuse the tree + bushes a lot, though. I also tried a more chibi sprite because they are soo common, might as well try it out.
    +

    + + (image: Lots of Angels and other characters at a shopping center) +
    +June 29, 2019 - Trying a shopping center level now. It's reeally spaced apart. It's inspired by a real shopping center;;
    +

    + + (image: Angel and some slimes in a cavern) +
    +July 25, 2020 - There's some missing in this gap, so I'll add in more pics if I find any. This is the first version of a cavern level for the blessfrey demo. It's inspired by local caves.
    +

    +
    +

    you're up to date.

    +
    +Hope you enjoyed seeing the different art I've used for blessfrey over the years. Even if I never really polish anything, it's nice to iterate to get a sense of game art and blessfrey's personal style. Hopefully it ends up looking okay okay when I do start polishing. But until then, in the words of YandereDev, "All art is placeholder."
    +
    diff --git a/vps/entries/210101 b/vps/entries/210101 new file mode 100644 index 0000000..0207208 --- /dev/null +++ b/vps/entries/210101 @@ -0,0 +1,53 @@ + +

    december 2020: holiday season☆

    +january 1, 2021
    +
    +
    +I didn't keep a diary very well this month;; This is mostly pieced together from my git history. I did play Legacy of Kain: Soul Reaver and Planescape: Torment a lot, though.
    +
    +

    week 1, december 1-5


    +#python
    +
    +
      +
    • worked on Skillmaker, a Python script that can use JSON data to generate skill scenes + scripts for Godot Engine
    • +
    • Skillmaker can generate descriptions that fit a standard format. It's not used in-game, though, it's just plopped in a comment on the skill script. In the future, I want Skillmaker to generate a CSV file, so Godot can read in the generated description instead of the text being hard-coded inside the engine. That way, editing + translating will be easier.
    • +
    • those descriptions use variables. In the future, those variables will allow skill values to grow with the character's stats.
    • +
    +
    +

    week 2, december 6-12


    +#python
    +
    +
      +
    • updated Skillmaker's readme, since expected input has changed a lot
    • +
    • after 8 years, Cyberpunk 2077 finally came out. I can't do $59.99 + 100GB, so the closest I can do is watch Batman Beyond instead.
    • +
    • lots of FlightRising. my flight competed against Light for Dominance. They won, but they had to raffle off a priceless Kickstarter item during the final hours to flip us off the top. I can't imagine how costly that win was for Light, and even then, it wasn't definitive...I wish I tried harder.
    • +
    +
    +

    week 3, december 13-19


    +
    +
      +
    • probably nothing really very productive
    • +
    • finished reading Voltaire's Candide. Not sure if it was the best year for a literary attack against the optimistic view that everything turns out for the best, but it's a fun + easy read nonetheless.
    • +
    • started reading William Bradshaw's The Goddess of Atvatabar, a Utopian hollow Earth novel. If inner earth is interesting, I attached a list to a dragon...credits go to all the article writers I didn't credit
    • +
    +
    +

    week 4, december 20-26


    +#python #skills #statuseffects
    +
    +
      +
    • Merry Christmas!!
    • +
    • (keywords are the smallest component of a skill - reusable segments of code for producing a skill effect)
    • +
    • added summon + bleeding keywords
    • +
    • added Skillmaker support for generating skills that use those keywords
    • +
    • maintain this website a little
    • +
    +
    +

    week 5, december 27-31


    +#dia #events #story
    +
    +
      +
    • I finally found a diagram editor I like - Dia :) It's in Mint's package manager, too.
    • +
    • it's nice for planning branching the flow of events and branching dialog. I wrote a few events with it and made an outline for the game.
    • +
    • I keep the events in my GDD repository now. I used to keep these all over the place, in paper + text documents. (Why didn't I do this earlier?)
    • +
    +
    diff --git a/vps/entries/210107 b/vps/entries/210107 new file mode 100644 index 0000000..d744e21 --- /dev/null +++ b/vps/entries/210107 @@ -0,0 +1,40 @@ + +

    inventory as a system diagram

    +october 1, 2020
    +#design #systemdiagram #gamemechanics
    +
    +System diagrams illustrate how components interact within a system. It saves so much headache to step back and plan with a system diagram before jumping into code.
    +
    +
    +

    stop + plan before coding


    +I want to move blessfrey's inventory into an app on the player character's smartphone. Before, it was displayed in a random pop-up window. It was poorly planned, so the programmatic inventory and the UI were too tightly coupled to easily pop into the phone screen. Instead of wrestling, it's easier to start over and actually plan before I code this time.
    +
    +
    +

    list out your nouns


    +A simple way to start thinking about a system is to list out its nouns + verbs. Jot down the entities that interact with your system.
    +
    +
    (image: system diagram for inventory)

    +
    +For blessfrey's inventory, that's the inventory (programmatic), the player character, the inventory app (UI), and base items. The inventory app is related to the smartphone and inventory items. Items are related to floor items, which are related to rooms.
    +
    +(blessfrey has three different kinds of items.
    +
      +
    • Base Item: holds all the data regardless of how the item is currently expressed
    • +
    • Floor Item: sits on the ground and gets picked up by characters.
    • +
    • Inventory Item: displayed in inventories, store windows, containers, etc
    • +

    +Floor + Inventory Items hold a base item inside them that gets popped out and traded around as the item gets expressed in different forms.)
    +
    +

    connect your nouns with verbs


    +I wrote the entities in pink and moved them around until the placement was decently readable. Then I connected the concepts with arrows. These arrows represent the verbs, which I explicitly labeled in yellow.
    +
    +The flow of these arrows can be very important. If you are modeling AI, for instance, no matter what path the program takes, there shouldn't be dead-ends. Seeing mistakes like that is easier with a diagram than lines of code. Otherwise, the flow is always generally useful for figuring out which methods are needed for each class and how they connect.
    +
    +
    +

    write the code


    +At this point, coding is a bit easier now that it's in some ways a transcription of the diagram. The entities are data (classes or objects), and the arrows are logic (methods).
    +
    +
    +

    conclusion


    +Your diagram doesn't have to be fancy or formal to get the point across to yourself, and it just takes a minute to save all the headache later. Don't skip this step or you'll have to rewrite the inventory system just to display it in a different window.
    +
    diff --git a/vps/entries/210204 b/vps/entries/210204 new file mode 100644 index 0000000..de9ad3b --- /dev/null +++ b/vps/entries/210204 @@ -0,0 +1,13 @@ + +

    web development resources

    +october 15, 2020
    +#accessibility #color #css #html #webdesign
    +
    +I'll collect frequently used resources for web design here.
    +
    +
      +
    • CSS Grid Generator - build a basic CSS Grid by changing the number of columns + rows, adjusting their dimensions, and adding containers.
    • +
    • W3's Nu Html Checker - automatically check the validity of your HTML + CSS.
    • +
    • WebAIM's Contrast Checker - check whether your font color contrasts well against your background color, at least in the eyes of a computer.
    • +
    • Coolors - select and lock colors then generate palettes by pressing space. Click on a color to view shades + tints, so you can tweak contrast without losing hues.
    • +
    diff --git a/vps/entries/210218 b/vps/entries/210218 new file mode 100644 index 0000000..f9611bd --- /dev/null +++ b/vps/entries/210218 @@ -0,0 +1,28 @@ + +

    my favorite GDC talks

    +january 7, 2020
    +#gamedesign #marketing
    +
    +I really should be keeping a list of these with descriptions, so why not keep them in an article?
    +
    +

    Automated Testing and Instant Replays in Retro City Rampage


    +Vblank Entertainment's Brian Provinciano (2015)
    +log button inputs to replay the game, for use in preproducing bugs, sharing replays on the community leaderboard, running cutscenes, and even controlling AI. It is 100% accurate in deterministic engines but also helpful in less deterministic engines. +
    + +
    +
    +

    Empathizing with Steam: How People Shop for Your Game


    +Chris Zukowski (2020)
    +tips for how to design your Steam store page based on Zukowski's screenshare and shopping diary observations of ordinary people shopping on Steam
    +
    +
      +
    • Essentially, make your gameplay genre absolutely clear within the first 4 screenshots and in the short description so that people will wishlist your game to buy during a seasonal Steam Sale.
    • +
    • Approach your wishlisters as complete newcomers. Jazz up your Steam page before a Steam Sale. Release an update, post in your forums, put a Santa hat on your character. When wishlisters return to your page, they will see an active game and be sold on it all over again.
    • +
    • His conclusions are very similar to how I shop on Steam, except I could care less for the tag section.
    • +
    • The romantic indie fiction section on Amazon dwarves the indie game section on Steam. To be immediately visible to their audience, romance authors follow a clear visual language on their covers to communicate their genres and sub-genres. Zukowski uses this as an extreme method for attracting your audience using the tropes of your genre, pointing out common UI elements and the shooter guy on every FPS cover.
    • +
    • More notes @ /diary/entries/extra/gdc-design-steam-store +
    +
    diff --git a/vps/entries/210304 b/vps/entries/210304 new file mode 100644 index 0000000..249c7af --- /dev/null +++ b/vps/entries/210304 @@ -0,0 +1,94 @@ + +

    questionnaire for making a fantasy race

    +march 4, 2021, 2020
    +#design #lore #worldbuilding
    +
    +

    Aspects of Culture

    +General things to consider about your fantasy race to fill out their culture. Obviously not every point is going to be relevant.
    +
    +

    Basics

    +
      +
    • Basic Needs
    • +
    • Reproduction
    • +
    • Survival
    • +
    • Climate
    • +
    • Enemies
    • +
    • Allies
    • +
    +
    +

    Lifecycles

    +
      +
    • Birth - how and where are offspring born? who is allowed to give birth?
    • +
    • Parenthood
    • +
    • Childhood
    • +
    • Coming of Age
    • +
    • Love
    • +
    • Mating
    • +
    • Marriage
    • +
    • Death
    • +
    • Education
    • +
    • Career
    • +
    +
    +

    Religion + Legend

    +
      +
    • Dominant Religions
    • +
    • Denominations
    • +
    • Cults
    • +
    • Atheism
    • +
    • Religious Figures
    • +
    • Central themes of the religious teachings
    • +
    • Explanations for the natural world - how the world came to be? the origin of Man?
    • +
    • Afterlife - where do they go after they die?
    • +
    • Evidence for religion
    • +
    • Local legends
    • +
    +
    +

    Climate

    +
      +
    • Preferred climate, climates inhabitted
    • +
    • How do they adapt to their climate?
    • +
    • Danger
    • +
    • How does their climate connect and separate them from other cultures?
    • +
    • What raw materials are available to them?
    • +
    • What seasons do they have?
    • +
    • Weather
    • +
    +
    +

    History

    +
      +
    • How is history recorded and shared? Is it accurate?
    • +
    • Origin of their people, nation
    • +
    • Significant events - expansion, wars, diaspora, exile, mass murder, transfers of power
    • +
    • Local history - early settlement, original population, development, local heroes, times that national events or figures that visited the local area
    • +
    +
    +

    Culture

    +
      +
    • Cultural Identity
    • +
    • Housing
    • +
    • Cuisine, Dining
    • +
    • Leading Industries, Imports, Exports, Trade
    • +
    • Class Stratification, Castes
    • +
    • Factions, Politics
    • +
    • Gender, Gender Roles
    • +
    • Race, Sub-race - Where and when did the other races or subraces arrive? Where do they tend to live? Influence on the greater culture, and vice versa? Race relations? Stereotypes? How are biracial people perceived?
    • +
    • Foreign culture - immigration policies to and from, perception of immigrants
    • +
    • Crime - Forms of crime, punishment
    • +
    • Health
    • +
    • Beauty, Fashion - Beauty Standards/Desired traits for mating, Differences among different demographics + factions, Influences
    • +
    • Rituals, Holidays, Festivals, Fairs, Masquerades
    • +
    • Language
    • +
    • Naming practices - when are names received? how many names are given? are names ever changed? what are naming conventions and how do they differ among the different factions? are there naming authorities or rules?
    • +
    • Etiquette
    • +
    • Art - Architecture
    • +
    • Entertainment - sports, hobbies
    • +
    • Symbols, Color associations
    • +
    +
    +

    Others

    +
      +
    • Time
    • +
    • +
    +
    diff --git a/vps/entries/extra/.gdc-Automated-Testing-code-backup.swp b/vps/entries/extra/.gdc-Automated-Testing-code-backup.swp new file mode 100644 index 0000000..e729514 Binary files /dev/null and b/vps/entries/extra/.gdc-Automated-Testing-code-backup.swp differ diff --git a/vps/entries/extra/200918 b/vps/entries/extra/200918 new file mode 100644 index 0000000..37b82b5 --- /dev/null +++ b/vps/entries/extra/200918 @@ -0,0 +1,28 @@ + +

    my favorite GDC talks

    +september 18, 2020
    +game design, marketing
    +
    +I really should be keeping a list of these with descriptions, so why not keep them in an article?
    +
    +

    Automated Testing and Instant Replays in Retro City Rampage


    +Vblank Entertainment's Brian Provinciano (2015)
    +log button inputs to replay the game, for use in preproducing bugs, sharing replays on the community leaderboard, running cutscenes, and even controlling AI. It is 100% accurate in deterministic engines but also helpful in less deterministic engines. +
    + +
    +
    +

    Empathizing with Steam: How People Shop for Your Game


    +Chris Zukowski (2020)
    +tips for how to design your Steam store page based on Zukowski's screenshare and shopping diary observations of ordinary people shopping on Steam
    +
    +
      +
    • Essentially, make your gameplay genre absolutely clear within the first 4 screenshots and in the short description so that people will wishlist your game to buy during a seasonal Steam Sale.
    • +
    • Approach your wishlisters as complete newcomers. Jazz up your Steam page before a Steam Sale. Release an update, post in your forums, put a Santa hat on your character. When wishlisters return to your page, they will see an active game and be sold on it all over again.
    • +
    • His conclusions are very similar to how I shop on Steam, except I could care less for the tag section.
    • +
    • The romantic indie fiction section on Amazon dwarves the indie game section on Steam. To be immediately visible to their audience, romance authors follow a clear visual language on their covers to communicate their genres and sub-genres. Zukowski uses this as an extreme method for attracting your audience using the tropes of your genre, pointing out common UI elements and the shooter guy on every FPS cover.
    • +
    • More notes @ /diary/entries/extra/gdc-design-steam-store +
    +
    diff --git a/vps/entries/extra/entry-template b/vps/entries/extra/entry-template new file mode 100644 index 0000000..b824736 --- /dev/null +++ b/vps/entries/extra/entry-template @@ -0,0 +1,67 @@ + +

    title in lowercase

    +date in lowercase
    +#accessibility #ai #apache #blogging #bottle #color #css #design #gamedescription #gamedesign #gamejam #gamemechanics #git #html #internationalization #json #localization #marketing #mockup #nginx #php #programming #python #regex #regularexpression #server #simpletemplate #skills #systemdiagram #webdev #webdesign #website
    +
    +term is etc.
    +
    +Capitalize some words.
    +
    +
      +
    • CSS, HTML, JSON, PHP
    • +
    • CSS Grid, Flexbox
    • +
    • MMO, RPG
    • +
    • NPC, WASD, XP
    • +
    • .CSV
    • +
    • IM, PC, UI, URL, VPS
    • +
    • GDC, YouTube
    • +
    • 2D, 3D
    • +
    • First Class, Second Class
    • +
    +
    +
    +

    lowercase

    +
      +
    • blessfrey, chimchooree, pixel joy, pixel sparrow
    • +
    • gamedev, webdev
    • +
    +
    +
      +
    • coroutine
    • +
    • lol
    • +
    +
    +How to spell words...
    +
    +
      +
    • Chatroom
    • +
    • Cooldown
    • +
    • Eye Shadow
    • +
    • Freeform
    • +
    • Gameplay
    • +
    • Hello World
    • +
    • Multiclassing
    • +
    • Mockup
    • +
    • Petsite
    • +
    • Playstyle
    • +
    • Plugin
    • +
    • Premade
    • +
    • Skillbar
    • +
    • Subfunction
    • +
    • Videogame
    • +
    • Web Page
    • +
    +
    +

    subtitle


    +spacing like this
    +
    +
    + + (image: Lots of Angels and other characters at a shopping center) +

    +

    subsubtitle with BrandName or CSS or chloe

    +

    +
    + (image: Lots of Angels and other characters at a shopping center) +
    +
    diff --git a/vps/entries/extra/gdc-Automated-Testing-code-backup b/vps/entries/extra/gdc-Automated-Testing-code-backup new file mode 100644 index 0000000..3b55ce8 --- /dev/null +++ b/vps/entries/extra/gdc-Automated-Testing-code-backup @@ -0,0 +1,288 @@ +/******************************************************************************/ +// SIMPLE INPUT RECORD/PLAYBACK +// (c) 2015 Brian Provinciano +// +// You are free to use this code for your own purposes, no strings attached. +// +// This is a very basic sample to record and playback button input. +// It's most useful when activated on startup, deactivated on shutdown for +// global button recording/playback. +// +// For details on more advanced implementations, see my GDC 2015 session: +// -> Automated Testing and Instant Replays in Retro City Rampage +// The slides and full video will be available on the GDC Vault at a later date. +/******************************************************************************/ + + +/******************************************************************************/ +// wrap it so it can be conditionally compiled in. +// for example, set INPUTREPLAY_CAN_RECORD to 1 to play the game and record the input, set it to 0 when done +// INPUTREPLAY_CAN_RECORD takes priority over INPUTREPLAY_CAN_PLAYBACK + +#define INPUTREPLAY_CAN_PLAYBACK 1 +#define INPUTREPLAY_CAN_RECORD 1 + +#define INPUTREPLAY_INCLUDED (INPUTREPLAY_CAN_PLAYBACK || INPUTREPLAY_CAN_RECORD) +/******************************************************************************/ + +#if INPUTREPLAY_INCLUDED + +#define INPUT_BUTTONS_TOTAL 32 // up to 32 +#define MAX_REC_LEN 0x8000 // the buffer size for storing RLE compressed button input (x each button) + +/******************************************************************************/ +typedef struct +{ + unsigned short *rledata; + unsigned short rlepos; + unsigned short datalen; + unsigned short currentrun; +} ButtonRec; +/******************************************************************************/ + +// if INPUTREPLAY_CAN_RECORD, as soon as this class is instanced, it will automatically record when instanced/created. +// statically creating this as a global will blanket the entire play session +// +// if INPUTREPLAY_CAN_PLAYBACK, playback will begin as soon as LoadFile() is used +// +class SimpleInputRec +{ + unsigned int m_buttonstate; + ButtonRec m_buttons[INPUT_BUTTONS_TOTAL]; + bool m_bRecording; + + unsigned char* m_data; + +public: + SimpleInputRec() + : m_buttonstate(0) + , m_data(NULL) + , m_bRecording(true) + { + } + + ~SimpleInputRec() + { + if(m_data) + { +#if INPUTREPLAY_CAN_RECORD + WriteToFile(); +#endif + delete[] m_data; + } + } + + // run each frame before the game uses the live button input. + // when recording, it saves the live input + // during playback, it overwrites the live input + void Update(bool bForce = false); + + // to start a playback +#if INPUTREPLAY_CAN_PLAYBACK + bool LoadFile(KSTR szfilename); +#endif + + // to finish recording +#if INPUTREPLAY_CAN_RECORD + void WriteToFile(); +#endif + +}; + +/******************************************************************************/ + +void SimpleInputRec::Update(bool bForce) +{ +#if INPUTREPLAY_CAN_RECORD + if(m_bRecording) + { + unsigned int newbuttons = nesinput.buttons; + + // allocate and initialize + if(!m_data) + { + m_data = new unsigned char[INPUT_BUTTONS_TOTAL * MAX_REC_LEN * 2]; + unsigned short* dataptr = (unsigned short*)m_data; + + for(int i=0; i>i)&1; + btn.rledata[btn.rlepos++] = (bit<<15) | btn.currentrun; + } + btn.currentrun = bForce? 0 : 1; + } + else + { + ++btn.currentrun; + } + } + + m_buttonstate = newbuttons; + } +#endif + +#if INPUTREPLAY_CAN_PLAYBACK + if(!m_bRecording) + { + bool bIsRunning = false; + for(int i=0; i>15)&1)<> 8, f); + } + for(int i=0; i diff --git a/vps/entries/extra/gdc-design-steam-store b/vps/entries/extra/gdc-design-steam-store new file mode 100644 index 0000000..619bb0e --- /dev/null +++ b/vps/entries/extra/gdc-design-steam-store @@ -0,0 +1,36 @@ + +

    my favorite GDC talks: Empathizing with Steam: How People Shop for Your Game by Chris Zukowski (2020)

    +september 18, 2020
    +marketing, sale, steam, wishlist
    +
    +Empathizing with Steam: How People Shop for Your Game by Chris Zukowski (2020) - tips for how to design your Steam store page based on Zukowski's screenshare and shopping diary observations of ordinary people shopping on Steam +
      +
    • Essentially, make your gameplay genre absolutely clear within the first 4 screenshots and in the short description so that people will wishlist your game to buy during a seasonal Steam Sale.
    • +
    • Approach your wishlisters as complete newcomers. Jazz up your Steam page before a Steam Sale. Release an update, post in your forums, put a Santa hat on your character. When wishlisters return to your page, they will see an active game and be sold on it all over again.
    • +
    • His conclusions are very similar to how I shop on Steam, except I could care less for the tag section.
    • +
    • first 4 images are shown when hovering over thumbnail in Steam. Make them represent the pillars of your gameplay, so the genre is clear.
    • +
    • don't try to coerce new audiences into trying your game. try to find your audience and show them exactly what they are looking for. +
    • include UI in screenshots, so gamers can decipher the genre and some gameplay mechanics
    • +
    • Gamers naturally compare new games with the leading games of their genres to decide whether they will enjoy it.
    • +
    • indie romance authors (who compete on a market of 8 million vs. steam's 40 thousand) use clear visual language in their coverart: tartan kilt + sword + distant castle = highland romance; animal behind a hunk = shapeshifter romance; woman in front of group of hunks = reverse harem. So a reader who sees a cover with multiple guys and a wolf, she knows it's a reverse harem of shape-shifting wolf boys without any descriptions or trailers.
    • +
    • applying the wisdom of the romance authors, understand your audience's genre interests as sub-sub-sub-genres and make your genre crystal clear in your store page.
    • +
    • Apply the tropes of your genre. The FPS coverart guy with the gun on all CoD and BF games, the two Street Fighter healthbars on the top of any fighter game
    • +
    • Part 4 - How to manage a Steam sale
    • +
    • People check their wishlist during sales, looking for discounts.
    • +
    • People don't remember why they wishlisted games, so your page must look fresh even to your wishlist crew. Before a sale, post an update, theme your capsule image, post an announcement, upload a small patch, and comment in the forums.
    • +
    • People remember games that are always on sale. Frequent sales increase familiarity.
    • +
    • Power users use gg.deals or steamdb to track historic lows. Strategically staircase your way down over time. Coincide your all-time-lows with Big Steam Sales. Harness the fear of missing out.
    • +
    • How to get from wishlist to cart
    • +
    • Before clicking 'buy,' they check developer and publisher for someone they recognize or trust. They check 'more from this studio' to check familiarity with the dev's other games.
    • +
    • Release more games to build this trust and familiarity.
    • +
    • They check the 'relevant to you' bar to see if the genre matches games they've played and that friends with similar taste also like the game.
    • +
    • How to manage your sales pricing
    • +
    • How to get from cart to library
    • +
    • After loading cart, they ask their friends whether they should go for it.
    • +
    • Your current customers have to become ambassadors to complete this purchase loop. Treat them well!
    • +
    • Abandon cart recovery in other online retailers beckons shoppers back before the sale ends. Steam lacks this, potentially losing devs 10% in revenue - https://www.annexcloud.com/blog/31-shopping-cart-abandonment-statistics-for-2018/
    • +
    • Do a second marketing push during the last day of a sale.
    • +
    • 5 - How to wishlisters into buyers
    • +
    • +
    +
    diff --git a/vps/entries/extra/ideabox b/vps/entries/extra/ideabox new file mode 100644 index 0000000..a453c32 --- /dev/null +++ b/vps/entries/extra/ideabox @@ -0,0 +1,443 @@ +abyssal whip +adamantine +airship +aloe +alpine +amber fossil +ambrosia +amulet +anachronism +anagram +animal parade +aphrodisiac +apple +apothecary +apricot +asterism +atelier +bad cat +Baldur +bamboo +bandit camp +bandit king +basil +bell tower +birthday dress +birthstone +black bear +The Black Hand +black knight +black water +black widow +blackguard +bloodstone +blue and yellow +blue blood +blue rose +bluebell +bonfire +box garden +breath of life +bubble bath +bubble tea +bunny boy +buried treasure +butterfly woman +camel +candlelight +cashmere +castle +cat café +cat familiar +cat man +catacombs +celestial +cemetery +chained to rocks +chain mail +chameleon +chamomile +chandelier +charmeuse +cheese bread +chimera +chives +chocolate factory +chronomancer +cipher +citadel +city of the dead +clipart +coin flip +cold iron +confetti +constellation +copycat +cotton +couture +cove +crab +crazy quilt +Crossroad Keep +crucibled +crystal sea +daeva +dark horse +dark hour +dark paradise +death's-head hawkmoth +deep space +diadem +Diana +diorama +dimetrodon +dire wolf +dollhouse +donkey +doppelgänger +dragonfruit +dragonstone +dreamweaver +Dymer +dystopia +ectoplasm +edelweiss +egg hunt +elemental +elipse +elixir of life +emberlight +Entrana +eventide +epitaph +Epsom salt +eternal youth +ettin +evil twin +fable +falling leaves +fairy lights +fairy ring +faun +favored soul +femme covert +femme fatale +fiery sword +fire ball +fire opal +firebrand +fishing village +floating +flower woman +flying +folklore +fountain of youth +forge +fortress +freezing fog +fringe +frog prince +fullness of time +gallows +Garden of Eden +gargoyle +genie +geode +ghost orchid +ghost ship +ghost town +girl in the internet +girl in white +glow stick +glow-in-the-dark stars +goblin +gold rush +gold standard +golden apple +golden orb weaver +golem +gray weather +griffon +grove +guild +guilty pleasure +hall of monuments +halo +hand of God +the hanged man +hanging garden +happy place +haunted house +headscarf +heart +hermit +holly +honeydew +hot air balloon +hot and cold game +hot cocoa +hydrangea +igari makeup +illuminated text +imp +incense +invisible man +iridescence +ironwood +jack-o'-lantern +jacquard +jade +jasmine +juicebox +kaleidoscope +kesi silk +kigurumi +kingdom +La Belle Sans Merci +labyrinth +lady cat +Lady of Shallot +Lady of the Lake +lady in black +lake of fire +lair +lamentation +lavender +lemonade +life-giver +lighthouse +lip oil +Little Red Riding Hood +lizardman +lobster +locket +Lokasenna +loner +loom +lost city +lost continent +lost soul +lotus +love letter +love potion +low poly +lullaby +macramé +mages guild +magic carpet +man in the moon +mandrake +manna +marine +Mars +mask +masquerade +mead of poetry +mean girl +melon soda +memento mori +memoir +mercury rivers and lakes +metamorphosis +meteorite +metropolis +miasma +Midas Touch +millennial moon +miniature +mirror of Venus +mirror on the wall +mithril +monastery +money tree +monkey and bear +moon rock +moonflower +moonglow +moonstone +morning glory +mossy cobblestone +moth +mudskipper +mural +muse +necromancer +nightlight +nocturnality +oneiromancer +oblivion +odalisque +omen +opal +orb +orichalcum +orphan +palace +panda eyes +paper crane +paper fan +pearl +periwinkle +personality test +phantom residue +phantom thief +pharisee +philosopher's stone +pickpocketing +pilgrimage +pixie stick +pinwheel +planetary weather +plastic vampire fangs +plushie +poetry and prose +pomegranate +poppy +post-rock +pretzel +princess of Kentucky +principality +prism +prison planet +poinsettia +popcorn +porcelain +propaganda +prophecy +proverb +psalm +pseudonym +pumpkin carving +quiz show +rainbow +raw honey +reaper +reclining woman +red +reverse trap +road roller +rooibos tea +rose gold +rose petal +runestone +s'more +sailor fuku +Sanctum +sandalwood +sandcastle +sandman +sanguine, my brother +sardonic +satire +satyr +scrying pool +scythe +sea foam +sea glass +sea of stars +sea storm +seastrand +secret garden +secret passageway +secret room +seven deadly sins +seven heavenly virtues +shapeshifter +sheep +shipwreck +shoegaze +shooting star +silk +silk embroidery +singing sword +skeleton +skipping stone +slide puzzle +slime +smoke and mirrors +snow globe +soma +soulmate +space cowboy +spooky chews +squid +spellbook +spelunking +spice cookie +spirit animal +spy +stained-glass +stardust +stargazer +starry sky +statuesque +sticker +stinky cat +stone face +stone people +storm cloud +strawberries and cream +strawberry blonde +strawberry shortcake +sunflower +swamp light +swan song +sword in the stone +taffy +talking forest +tatting +tea garden +tears of Guthix +terrarium +three women +tide pool +tiger's eye +toasted marshmallow +topiary +treasure trails +tree of life +trick or treat +trickster +tulip +tungsten +underwater +underworld +unicorn horn +unstoppable mailman +urban legend +utopia +vanity of vanities +Venus +waiting room +waking dream +walled city +wampus cat +wandering eye +wanderlust +wasp lady +watchmen on the wall +water bearer +water nymph +waterfall room +weeping willow +Whip-Poor-Will +whisper +white Christmas +will-o'-wisp +wind chimes +wings +wishing well +witchhouse +witching hour +wizard tower +wolf's-bane +woman and serpent +the woodsman +wormwood +wreath +wyvern +yak +Yggdrasil +Ys +zealot +zoo diff --git a/vps/index.py b/vps/index.py new file mode 100644 index 0000000..127173f --- /dev/null +++ b/vps/index.py @@ -0,0 +1,312 @@ +import datetime, os, re +from bottle import error, response, route, run, static_file, template, TEMPLATE_PATH + +def list_rec(page): + loc = 'diary/entries/' + result = [] + rec = [] + comment = "" + if isinstance(page, int): + # Collect recommended articles from comment line + with open('diary/entries/' + str(page)) as f: + comment = f.readline() + comment = comment.replace('','') + comment = comment.replace(' ','') + comment = clean(comment) + rec = comment.split(',') + # Convert into array for template to display + for article in rec: + if is_it_time(article): + path = loc + article + data = [] + try: + with open(path) as f: + f.readline() + data.append(clean(f.readline().replace('
    ',''))) + data.append(path) + result.append(data) + except EnvironmentError: + print("No article @ " + path) + return result + +# List latest 5 articles as headline links +def list_headlines(articles): + loc = 'diary/entries/' + result = [] + text = [] + for article in articles: + path = loc + article + b = [] + b.append(path) + with open(path) as f: + f.readline() + text = f.readline() + b.append(clean(text.replace('
    ',''))) + result.append(b) + return result + +# Return title of article, formatted for sharing via social media +def find_social_title(text): + return clean(text[1]).replace(' ','+') + +# Return URL of article +def find_url(path): + return '/' + path.replace('.tpl','') + +# Return clean timestamp +def find_timestamp(text): + return text[2].replace('
    ','') + +# Return clean title +def find_title(text): + return clean(text[1]) + +# Return article as list of lines of text +def article2list(article, loc): + text = [] + with open(loc + article) as f: + text = f.readlines() + return text + +def retrieve_article(page, loc): + text = [] + string = "" + with open(loc + str(page)) as f: + text = f.readlines() + for line in text: + string += line + return string + +# Return list of snippets using list of articles +def list_snippets(articles): + loc = 'diary/entries/' + limit = 4 + total = len(articles) + result = [] + + for article in articles: + path = loc + article + text = [] + a = [] + length = 0 + text = article2list(article, loc) + a.append(find_title(text)) + a.append(prepare_article(text, path)) + a.append(find_timestamp(text)) + a.append(find_url(path)) + a.append(find_social_title(text)) + result.append(a) + return result + +# Return line count of file +def count_lines(fname): + with open(fname) as f: + for linenum, line in enumerate(f,1): + pass + return linenum + +# Return article text without HTML header +def find_content(text): + length = len(text) + content = "" + # form a string from relevant lines of the article + pos = 0 + for line in text: + # skip to line 5 + if pos > 4 and pos < length: + content += line + pos += 1 + return content + +# Snip article and close any open list tags +def prepare_article(text, path): + content = snip_article(find_content(text), path) + if content.count('
      ') > content.count('
    '): + content += '' + return content + +# Remove links, line breaks from snippet +def clean(result): + result = result.replace('\n','') + result = result.replace('
    ','') + result = re.sub(r'', '', result) + result = re.sub(r'', '', result) + result = re.sub(r'', '', result) + result = result.replace('','') + result = re.sub(r'','',result) + result = re.sub(r'','',result) + result = result.replace('
    ','') + result = result.replace('
    ','') + result = result.replace('','') + result = result.replace('','') + return result + +# Return first 300 words of article + " ... " +def snip_article(article, path): + article = clean(article) + limit = 300 + result = article[0:min(len(article),limit)] + result = result.rsplit(' ',1)[0] + return result + " ... " + +# Sort diary - newest to oldest +def sort_files(files): + files.sort(reverse=True) + return files + +def curate_files(files): + # remove folders + if 'raw' in files: + files.remove('raw') + if 'extra' in files: + files.remove('extra') + # remove + clean = [] + for f in files: + if is_it_time(f): + clean.append(f) + return clean + +def is_it_time(date): + today = datetime.datetime.now() + today_string = today.strftime("%y") + today.strftime("%m") + today.strftime("%d") + return int(date) <= int(today_string) + +# Return list of all diary entries (exclude raws + extras) +def gather_files(loc): + files = os.listdir(loc) + return files + +def gather_and_sort(loc): + return sort_files(curate_files(gather_files(loc))) + +def fill_ideabox(): + box = [] + with open('diary/entries/extra/ideabox') as f: + for line in f: + box.append(line) + return box + +## Static ## + +# Serve CSS +@route('/static/css/') +def serve_css(filename): + return static_file(filename, root='static/css') + +# Serve images +@route('/static/img/') +def serve_img(filename): + return static_file(filename, root='static/img') + +# Serve unlisted articles +@route('/static/extra/') +def serve_extra(filename): + return static_file(filename, root='static/extra', mimetype='text/plain', download=True) + +## Routes ## + +# 404 Error Page +@error(404) +def error404(error): + return "unfortunately, a 404 error" + +# Downloads +@route('/download/') +def download(filename): + return static_file(filename, root='static/extra', download=filename) + +# Home Page - Index Template +@route('/') +def index(): + """home page""" + loc = 'diary/entries/' + info = {'css': 'index', 'news': list_headlines(gather_and_sort(loc)[0:10]), 'title': 'chimchooree\'s dev space - blessfrey', 'year': datetime.datetime.now()} + return template('index.tpl', info) + +# Projects Page - Game Template - system, character, story info +@route('/projects') +def projects(): + """projects page""" + info = {'css': 'projects', 'title': 'chimchooree projects', 'year': datetime.datetime.now()} + return template('projects.tpl', info) + +# Presskit Page - Presskit Template - product, developer info +@route('/presskit') +def presskit(): + """press page""" + info = {'css': 'presskit', 'title': 'blessfrey - presskit', 'year': datetime.datetime.now()} + return template('presskit.tpl', info) + +# Start on first Diary page if no page given +@route('/diary') +def diary2(): + return diary(0) + +# Diary Page - Diary Template - list all articles +@route('/diary/') +def diary(page): + """diary page""" + loc = 'diary/entries/' + assert isinstance(page, int) + info = {'css': 'diary', 'title': 'blessfrey - developer diary', 'year': datetime.datetime.now(), 'snippets': list_snippets(gather_and_sort(loc)), 'latest': list_headlines(gather_and_sort(loc)[0:5]), 'total': len(curate_files(gather_files(loc))), 'limit': 8, 'cluster': 3, 'page': page} + return template('diary.tpl', info) + +# Entry Page - Feature Template - for articles +@route('/diary/entries/') +def entry(page): + """diary entry""" + if not is_it_time(page): + return error404(404) + loc = 'diary/entries/' + info = {'css': 'feature', 'title': 'blessfrey - developer diary', 'year': datetime.datetime.now(), 'entry': retrieve_article(page, loc), 'recommends': list_rec(page), 'articles': "Articles", 'latest': list_headlines(gather_and_sort(loc)[0:5]), 'page': page} + abs_app_dir_path = os.path.dirname(os.path.realpath(__file__)) + abs_views_path = os.path.join(abs_app_dir_path, 'views') + TEMPLATE_PATH.insert(0, abs_views_path ) + return template(os.path.join(abs_views_path,'feature.tpl'), info) + +# Extra Page - Feature Template - for unlisted articles +@route('/diary/entries/extra/') +def extra(page): + """diary extra""" + loc = 'diary/entries/extra/' + info = {'css': 'feature', 'title': 'blessfrey - developer diary', 'year': datetime.datetime.now(), 'entry': retrieve_article(page, loc), 'recommends': list_rec(page), 'articles': "Articles", 'latest': list_headlines(gather_and_sort('diary/entries/')[0:5]), 'page': page} + abs_app_dir_path = os.path.dirname(os.path.realpath(__file__)) + abs_views_path = os.path.join(abs_app_dir_path, 'views') + TEMPLATE_PATH.insert(0, abs_views_path ) + return template(os.path.join(abs_views_path,'feature.tpl'), info) + +# Personal Page - Box Template +@route('/box') +def box(): + """personal page""" + info = {'css': 'box', 'title': 'chimchooree\'s personal page', 'year': datetime.datetime.now()} + return template('box.tpl', info) + +# Credits Page - Credits Template +@route('/credits') +def credits(): + """credits page""" + info = {'css': 'box', 'title': 'blessfrey - credits', 'year': datetime.datetime.now()} + return template('credits.tpl', info) + + +# Contact Page - Contact Template +@route('/contact') +def contact(): + """contact page""" + info = {'css': 'box', 'title': 'blessfrey - contact chimchooree', 'year': datetime.datetime.now()} + return template('contact.tpl', info) + +# Idea Box Page - Box Template +@route('/ideabox') +def ideabox(): + """idea box page""" + info = {'css': 'box', 'title': 'blessfrey - idea box - a collection of inspiring concepts', 'words': fill_ideabox(), 'limit': 5, 'year': datetime.datetime.now()} + return template('ideabox.tpl', info) + +## Main ## + +if __name__ == '__main__': + run(host='127.0.0.1', port=9001) diff --git a/vps/robots.txt b/vps/robots.txt new file mode 100644 index 0000000..617187a --- /dev/null +++ b/vps/robots.txt @@ -0,0 +1,74 @@ +# default +User-agent: * +Allow: / +Disallow: /box/ +Disallow: /diary/entries/raw/ + +# advertising +User-agent: AdsBot-Google* +User-agent: Mediapartners-Google* +Disallow: / + +# trouble, referencing https://aardling.com/robots.txt and others +User-agent: AhrefsBot +Disallow: / +User-agent: DOC +Disallow: / +User-agent: Download Ninja +Disallow: / +User-agent: EasouSpider +Disallow: / +User-agent: Exabot +Disallow: / +User-agent: Fetch +Disallow: / +User-agent: grub-client +Disallow: / +User-agent: HTTrack +Disallow: / +User-agent: larbin +Disallow: / +User-agent: libwww +Disallow: / +User-agent: linko +Disallow: / +User-agent: Microsoft.URL.Control +Disallow: / +User-agent: MSIECrawler +Disallow: / +User-agent: NPBot +Disallow: / +User-agent: Offline Explorer +Disallow: / +User-agent: sitecheck.internetseer.com +Disallow: / +User-agent: SiteSnagger +Disallow: / +User-agent: Teleport +Disallow: / +User-agent: TeleportPro +Disallow: / +User-agent: UbiCrawler +Disallow: / +User-agent: Vagabondo +Disallow: / +User-agent: WebCopier +Disallow: / +User-agent: WebReaper +Disallow: / +User-agent: WebStripper +Disallow: / +User-agent: WebZIP +Disallow: / +User-agent: wget +Disallow: / +User-agent: Xenu +Disallow: / +User-agent: Zao +Disallow: / +User-agent: Zealbot +Disallow: / +User-agent: ZyBORG +Disallow: / + +Sitemap: http://www.blessfrey.me/sitemap.xml diff --git a/vps/sitemap.xml b/vps/sitemap.xml new file mode 100644 index 0000000..c807fb5 --- /dev/null +++ b/vps/sitemap.xml @@ -0,0 +1,47 @@ + + + + + + + http://www.blessfrey.me/ + + 2020-10-04 + + monthly + + 0.7 + + + + + + http://www.blessfrey.me/diary/ + + weekly + + 0.8 + + + + + + http://www.blessfrey.me/game/ + + monthly + + 0.6 + + + + + + http://www.blessfrey.me/presskit/ + + monthly + + 0.6 + + + + diff --git a/vps/static/css/box.css b/vps/static/css/box.css new file mode 100755 index 0000000..e0ba04e --- /dev/null +++ b/vps/static/css/box.css @@ -0,0 +1,121 @@ +* { + padding:25; + margin:25; +} + +a { + text-decoration: none; +} +a:link { + color: red; +} +a:visited { + color: hotpink; +} +a:hover { + color: green; +} +a:active { + color: blue; +} +mark { + background-color: #900C3F; + color: hotpink; +} +ul { list-style-position: inside; } + +.grid { + display: grid; + grid-template-columns: auto 800px auto; + grid-template-rows: 25px 90px auto; + grid-column-gap: 0px; + grid-row-gap: 0px; +} + +body { + background-color: #e5c5d1; + color: #900C3F; +} + +.whitespace { grid-area: 1 / 1 / 2 / 4; } +.blessfrey-logo { grid-area: 1 / 2 / 2 / 3; } +.body-row { grid-area: 3 / 1 / 4 / 4; } +.content { grid-area: 3 / 2 / 4 / 3; } + +.nav-row { grid-area: 2 / 1 / 3 / 4; } +.nav-grid { + grid-area: 2 / 2 / 3 / 3; + display: flex; + flex-direction:column; + justify-content:flex-end; + display: grid; + grid-template-columns: auto repeat(4, 70px) auto; + grid-template-rows: 90px; + grid-column-gap: 17px; + grid-row-gap: 0px; + align-items: end; + justify-items: center; +} + +.nav-bar { + grid-area: 1 / 1 / 2 / 7; + background-image: url(../img/ele/navbar.png); + height: 86px; + width: 800px; +} +.nav-index { + grid-area: 1 / 2 / 2 / 3; + padding-bottom: 3px; + position: relative; +} +.nav-game { + grid-area: 1 / 3 / 2 / 4; + padding-bottom: 3px; + position: relative; +} +.nav-diary { + grid-area: 1 / 4 / 2 / 5; + padding-bottom: 3px; + position: relative; +} +.nav-presskit { + grid-area: 1 / 5 / 2 / 6; + padding-bottom: 3px; + position: relative; +} +.nav-link { + position: absolute; + top: 45%; + left: 50%; + transform: translate(-50%, -50%) +} +.nav-link a { + font-size: 18px; +} + +.nav-link a:link { + color: #66C7F4; +} +.nav-link a:visited { + color: #CB9CF2; +} +.nav-link a:hover { + color: #F9B3D7; +} +.nav-link a:active { + color: #f463ad; +} + +table, th, td { + border: 1px solid #330532; +} + +th, td { + padding: 5px; +} + +.footer-content { + padding-top: 5px; + text-align: right; + overflow: hidden; +} diff --git a/vps/static/css/diary.css b/vps/static/css/diary.css new file mode 100755 index 0000000..e5b8152 --- /dev/null +++ b/vps/static/css/diary.css @@ -0,0 +1,244 @@ +* { + padding:0; + margin:0; +} + +a { + text-decoration: none; +} + +ul { list-style-position: inside; } + +.grid { + display: grid; + grid-template-columns: auto 533px 267px auto; + grid-template-rows: 25px 90px 40px auto 40px auto; + grid-column-gap: 0px; + grid-row-gap: 0px; +} + +.whitespace { + grid-area: 1 / 1 / 2 / 5; + display: flex; + flex-direction:column; + justify-content:center; + align-items: center; + background-color: #900C3F; +} + +.blessfrey-logo { + grid-area: 1 / 2 / 2 / 4; + padding-top: 5px; + color: #FBDAEC; +} + +/* navigation pane */ + +.nav-row { + grid-area: 2 / 1 / 3 / 5; + background-color: #900C3F; +} + +.nav-grid { + grid-area: 2 / 2 / 3 / 4; + display: flex; + flex-direction:column; + justify-content:flex-end; + display: grid; + grid-template-columns: auto repeat(4, 70px) auto; + grid-template-rows: 90px; + grid-column-gap: 17px; + grid-row-gap: 0px; + align-items: end; + justify-items: center; +} +.nav-bar { + grid-area: 1 / 1 / 2 / 7; + background-image: url(../img/ele/navbar.png); + height: 86px; + width: 800px; +} +.nav-index { + grid-area: 1 / 2 / 2 / 3; + padding-bottom: 3px; + position: relative; +} +.nav-game { + grid-area: 1 / 3 / 2 / 4; + padding-bottom: 3px; + position: relative; +} +.nav-diary { + grid-area: 1 / 4 / 2 / 5; + padding-bottom: 3px; + position: relative; +} +.nav-presskit { + grid-area: 1 / 5 / 2 / 6; + padding-bottom: 3px; + position: relative; +} +.nav-link { + position: absolute; + top: 45%; + left: 50%; + transform: translate(-50%, -50%) +} +.nav-link a { + font-size: 18px; +} +.nav-link a:link { + color: #66C7F4; +} +.nav-link a:visited { + color: #CB9CF2; +} +.nav-link a:hover { + color: #F9B3D7; +} +.nav-link a:active { + color: #f463ad; +} + +/* Body */ + +.dir-row { + grid-area: 3 / 2 / 4 / 4; + background-color: #080410; + color: #F9B3D7; +} + +.diary-dir { + background-color: #080410; + color: #F9B3D7; + font-size: 20px; + padding-top: 5px; +} +.diary-dir a:link { + color: #C9C2D6; +} +.diary-dir a:visited { + color: #C9C2D6; +} +.diary-dir a:hover { + color: #F9B3D7; +} +.diary-dir a:active { + color: #f463ad; +} +.diary-dir.top { + grid-area: 3 / 1 / 4 / 5; +} + +.body-row { + grid-area: 4 / 1 / 5 / 5; + background-color: #080410; +} + +.diary-pages { + grid-area: 4 / 2 / 5 / 3; +} + +.snippet { + background-color: #C9C2D6; + color: #080410; + padding: 20px; + margin-top: 0px; + margin-bottom: 30px; +} +.snippet a:link { + color: #401231; +} +.snippet a:visited { + color: #401231; +} +.snippet a:hover { + color: #902771; +} +.snippet a:active { + color: #900C3F; +} + +.sidebar { + grid-area: 4 / 3 / 5 / 4; + display: grid; + grid-template-columns: auto; + grid-template-rows: repeat(4, auto); + grid-column-gap: 0px; + grid-row-gap: 0px; + align-content: start; + padding-left: 7px; +} +.sidebar a:link { + color: #C9C2D6; +} +.sidebar a:visited { + color: #C9C2D6; +} +.sidebar a:hover { + color: #F9B3D7; +} +.sidebar a:active { + color: #F9B3D7; +} +.about-box { + grid-area: 4 / 3 / 5 / 4; + background-color: #581845; + color: #F9B3D7; + text-align: center; + margin: 15px; + padding: 5px; + margin-top: 0px; + padding-bottom: 15px; +} +.twitter-box { + grid-area: 5 / 3 / 6 / 4; + background-color: #581845; + color: #F9B3D7; + text-align: center; + margin: 15px; + padding: 5px; + padding-bottom: 15px; +} +.latest { + grid-area: 6 / 3 / 7 / 4; + background-color: #581845; + color: #F9B3D7; + text-align: center; + list-style-position: inside; + margin: 15px; + padding: 5px; +} +.latest-text { + text-align: left; + list-style-position: inside; + padding: 5px; +} +.disclosure { + grid-area: 7 / 3 / 8 / 4; + background-color: #581845; + color: #F9B3D7; + text-align: center; + margin: 15px; + padding: 5px; + padding-bottom: 15px; +} + +.diary-dir.bottom { + grid-area: 5 / 1 / 6 / 5; +} + +.footer-row { + grid-area: 6 / 1 / 7 / 5; + background-color: #080410; +} + +.footer-content { + background-color: #080410; + color: #F9B3D7; + padding-top: 5px; + padding-right: 25px; + box-shadow: 0 100vh 0 100vh #581845; + text-align: right; + overflow: hidden; +} diff --git a/vps/static/css/feature.css b/vps/static/css/feature.css new file mode 100644 index 0000000..3e10ae2 --- /dev/null +++ b/vps/static/css/feature.css @@ -0,0 +1,218 @@ +* { + padding:0; + margin:0; +} + +a { + text-decoration: none; +} + +ul { list-style-position: inside; } + +.grid { + display: grid; + grid-template-columns: auto 533px 267px auto; + grid-template-rows: 25px 90px repeat(3, auto); + grid-column-gap: 0px; + grid-row-gap: 0px; +} + +.whitespace { + grid-area: 1 / 1 / 2 / 5; + display: flex; + flex-direction:column; + justify-content:center; + align-items: center; + background-color: #900C3F; +} + +.blessfrey-logo { + grid-area: 1 / 2 / 2 / 4; + padding-top: 5px; + color: #FBDAEC; +} + +/* navigation pane */ + +.nav-row { + grid-area: 2 / 1 / 3 / 5; + background-color: #900C3F; +} + +.nav-grid { + grid-area: 2 / 2 / 3 / 4; + display: flex; + flex-direction:column; + justify-content:flex-end; + display: grid; + grid-template-columns: auto repeat(4, 70px) auto; + grid-template-rows: 90px; + grid-column-gap: 17px; + grid-row-gap: 0px; + align-items: end; + justify-items: center; +} +.nav-bar { + grid-area: 1 / 1 / 2 / 7; + background-image: url(../img/ele/navbar.png); + height: 86px; + width: 800px; +} +.nav-index { + grid-area: 1 / 2 / 2 / 3; + padding-bottom: 3px; + position: relative; +} +.nav-game { + grid-area: 1 / 3 / 2 / 4; + padding-bottom: 3px; + position: relative; +} +.nav-diary { + grid-area: 1 / 4 / 2 / 5; + padding-bottom: 3px; + position: relative; +} +.nav-presskit { + grid-area: 1 / 5 / 2 / 6; + padding-bottom: 3px; + position: relative; +} +.nav-link { + position: absolute; + top: 45%; + left: 50%; + transform: translate(-50%, -50%) +} +.nav-link a { + font-size: 18px; +} +.nav-link a:link { + color: #66C7F4; +} +.nav-link a:visited { + color: #CB9CF2; +} +.nav-link a:hover { + color: #F9B3D7; +} +.nav-link a:active { + color: #f463ad; +} + +/* Body */ + +.body-row { + grid-area: 3 / 1 / 5 / 5; + background-color: #080410; +} + +.diary-entry { + grid-area: 3 / 2 / 4 / 3; + background-color: #C9C2D6; + color: #080410; + padding: 20px; + margin-top: 40px; + margin-bottom: 30px; +} + +.sidebar { + grid-area: 3 / 3 / 5 / 4; + display: grid; + grid-template-columns: auto; + grid-template-rows: repeat(4, auto); + grid-column-gap: 0px; + grid-row-gap: 0px; + align-content: start; + padding-left: 7px; + margin-top: 40px; +} +.sidebar a:link { + color: #C9C2D6; +} +.sidebar a:visited { + color: #C9C2D6; +} +.sidebar a:hover { + color: #F9B3D7; +} +.sidebar a:active { + color: #F9B3D7; +} +.about-box { + grid-area: 1 / 1 / 2 / 2; + background-color: #581845; + color: #F9B3D7; + text-align: center; + margin: 15px; + padding: 5px; + margin-top: 0px; + padding-bottom: 15px; +} +.twitter-box { + grid-area: 2 / 1 / 3 / 2; + background-color: #581845; + color: #F9B3D7; + text-align: center; + margin: 15px; + padding: 5px; + padding-bottom: 15px; +} +.latest { + grid-area: 3 / 1 / 4 / 2; + background-color: #581845; + color: #F9B3D7; + text-align: center; + list-style-position: inside; + margin: 15px; + padding: 5px; +} +.latest-text { + text-align: left; + list-style-position: inside; + padding: 5px; +} +.disclosure { + grid-area: 4 / 1 / 5 / 2; + background-color: #581845; + color: #F9B3D7; + text-align: center; + margin: 15px; + padding: 5px; + padding-bottom: 15px; +} + +.recommend { + grid-area: 4 / 2 / 5 / 3; + background-color: #080410; + color: #F9B3D7; + display: grid; + grid-template-columns: auto auto auto; + grid-template-rows: auto auto; + grid-column-gap: 0px; + grid-row-gap: 0px; + padding: 5px; +} +.more { grid-area: 1 / 1 / 2 / 4; } +.rec-box { grid-area: 2 / 2 / 3 / 3; } + +.snip { + width: 100px; + float: left; + margin: 50px; +} + +.footer-row { + grid-area: 5 / 1 / 6 / 5; + background-color: #080410; +} + +.footer-content { + background-color: #080410; + color: #F9B3D7; + padding-top: 5px; + padding-right: 25px; + box-shadow: 0 100vh 0 100vh #581845; + text-align: right; + overflow: hidden; +} diff --git a/vps/static/css/game.css b/vps/static/css/game.css new file mode 100644 index 0000000..403a492 --- /dev/null +++ b/vps/static/css/game.css @@ -0,0 +1,157 @@ +* { + padding:0; + margin:0; + font-family: trebuchet ms; arial; calibri; gill sans; helvetica neue; candara; geneva; verdana; sans-serif; +} + +a { + text-decoration: none; +} +ul { list-style-position: inside; } + +.textbox { + margin: 20px; + padding: 20px; + background-color: #C9C2D6; + color: #080410; +} + +.grid { + display: grid; + grid-template-columns: auto 800px auto; + grid-template-rows: 25px 90px 1fr 100px; + grid-column-gap: 0px; + grid-row-gap: 0px; +} + +.whitespace { + grid-area: 1 / 1 / 2 / 4; + display: flex; + flex-direction:column; + justify-content:center; + align-items: center; + background-color: #900C3F; +} + +.blessfrey-logo { + grid-area: 1 / 2 / 2 / 3; + padding-top: 5px; + color: #FBDAEC; +} + +/* navigation pane */ + +.nav-row { + grid-area: 2 / 1 / 3 / 4; + background-color: #900C3F; +} + +.nav-grid { + grid-area: 2 / 2 / 3 / 3; + display: flex; + flex-direction:row; + justify-content:flex-end; + display: grid; + grid-template-columns: auto repeat(4, 70px) auto; + grid-template-rows: 90px; + grid-column-gap: 17px; + grid-row-gap: 0px; + align-items: end; + justify-items: center; +} + +.nav-bar { + grid-area: 1 / 1 / 2 / 7; + background-image: url(../img/ele/navbar.png); + height: 86px; + width: 800px; +} +.nav-index { + grid-area: 1 / 2 / 2 / 3; + padding-bottom: 3px; + position: relative; +} +.nav-game { + grid-area: 1 / 3 / 2 / 4; + padding-bottom: 3px; + position: relative; +} +.nav-diary { + grid-area: 1 / 4 / 2 / 5; + padding-bottom: 3px; + position: relative; +} +.nav-presskit { + grid-area: 1 / 5 / 2 / 6; + padding-bottom: 3px; + position: relative; +} +.nav-link { + position: absolute; + top: 45%; + left: 50%; + transform: translate(-50%, -50%) +} +.nav-link a { + font-size: 18px; +} +.nav-link a:link { + color: #66C7F4; +} +.nav-link a:visited { + color: #CB9CF2; +} +.nav-link a:hover { + color: #F9B3D7; +} +.nav-link a:active { + color: #f463ad; +} + +/* Body */ + +.body-row { + grid-area: 3 / 1 / 4 / 4; + background-color: #080410; +} + +.pages { + grid-area: 3 / 2 / 4 / 3; + display: grid; + grid-template-columns: 1fr; + grid-template-rows: repeat(4, auto); + grid-column-gap: 0px; + grid-row-gap: 0px; + background-color: #080410; + word-wrap: break-word; +} + +.desc { + grid-area: 1 / 1 / 2 / 2; + background-color:; +} +.story { + grid-area: 2 / 1 / 3 / 2; + background-color:; +} +.system { + grid-area: 3 / 1 / 4 / 2; + background-color:; +} +.graphics { + grid-area: 4 / 1 / 5 / 2; + background-color:; +} + +.footer-row { + grid-area: 4 / 1 / 5 / 4; + background-color: #900C3F; +} + +.footer-content { + background-color: #581845; + padding-top: 5px; + text-align: right; + overflow: hidden; + box-shadow: 0 100vh 0 100vh #581845; +} diff --git a/vps/static/css/index.css b/vps/static/css/index.css new file mode 100755 index 0000000..ee53ee7 --- /dev/null +++ b/vps/static/css/index.css @@ -0,0 +1,184 @@ +* { + padding:0; + margin:0; + font-family: trebuchet ms; arial; calibri; gill sans; helvetica neue; candara; geneva; verdana; sans-serif; +} + +a { + text-decoration: none; +} + +.grid { + display: grid; + grid-template-columns: auto 75px 400px 25px 225px 75px auto; + grid-template-rows: 25px 90px 457px auto; + grid-column-gap: 0px; + grid-row-gap: 0px; +} + +.whitespace { + grid-area: 1 / 1 / 2 / 8; + display: flex; + flex-direction:column; + justify-content:center; + align-items: center; + background-color: #900C3F; +} + +.blessfrey-logo { + grid-area: 1 / 3 / 2 / 6; + padding-top: 5px; + color: #FBDAEC; +} + +/* navigation pane */ + +.nav-row { + grid-area: 2 / 1 / 3 / 8; + background-color: #900C3F; +} + +.nav-grid { + grid-area: 2 / 2 / 3 / 7; + display: flex; + flex-direction:row; + justify-content:flex-end; + display: grid; + grid-template-columns: auto repeat(4, 70px) auto; + grid-template-rows: 90px; + grid-column-gap: 17px; + grid-row-gap: 0px; + align-items: end; + justify-items: center; +} +.nav-bar { + grid-area: 1 / 1 / 2 / 7; + background-image: url(../img/ele/navbar.png); + height: 86px; + width: 800px; +} +.nav-index { + grid-area: 1 / 2 / 2 / 3; + padding-bottom: 3px; + position: relative; +} +.nav-game { + grid-area: 1 / 3 / 2 / 4; + padding-bottom: 3px; + position: relative; +} +.nav-diary { + grid-area: 1 / 4 / 2 / 5; + padding-bottom: 3px; + position: relative; +} +.nav-presskit { + grid-area: 1 / 5 / 2 / 6; + padding-bottom: 3px; + position: relative; +} +.nav-link { + position: absolute; + top: 45%; + left: 50%; + transform: translate(-50%, -50%) +} +.nav-link a { + font-size: 18px; +} +.nav-link a:link { + color: #66C7F4; +} +.nav-link a:visited { + color: #CB9CF2; +} +.nav-link a:hover { + color: #F9B3D7; +} +.nav-link a:active { + color: #f463ad; +} + +/* Body */ + +.body-row { + grid-area: 3 / 1 / 4 / 8; + background-color: #080410; +} + +.social { + grid-area: 3 / 6 / 4 / 7; + justify-content: center; +} + +.bg { + grid-area: 3 / 3 / 4 / 6; + background-color:; + background-image: url(../img/bg/homeBG.png); + width: 650px; + height: 457px; +} + +.footer-row { + grid-area: 4 / 1 / 5 / 8; + background-color: #900C3F; +} + +.tweets { + grid-area: 4 / 3 / 5 / 4; + margin-right: 0px; + margin-left: 0px; + margin-top: 10px; + margin-bottom: 5px; +} + +.news { + grid-area: 4 / 5 / 5 / 6; + display: flex; + flex-direction:column; + background-color: #581845; + color: #F9B3D7; + height: 85px; + overflow-y: scroll; + margin-right: 0px; + margin-left: 0px; + margin-top: 15px; + margin-bottom: 0px; + padding-top: 5px; + padding-right: 5px; + padding-bottom: 5px; + padding-left: 8px; +} + +.news a:link { + color: #F9B3D7; +} +.news a:visited { + color: #F9B3D7; +} +.news a:hover { + color: #f463ad; +} +.news a:active { + color: #f463ad; +} + +.headline { + margin-right: 0px; + margin-left: 0px; + margin-top: 0px; + margin-bottom: 0px; + padding-top: 3px; + padding-right: 1px; + padding-bottom: 3px; + padding-left: 1px; +} + +.footer-content { + background-color: #581845; + color: #F9B3D7; + padding-top: 5px; + text-align: right; + overflow: hidden; + box-shadow: 0 100vh 0 100vh #581845; +} diff --git a/vps/static/css/presskit.css b/vps/static/css/presskit.css new file mode 100644 index 0000000..fd37a6f --- /dev/null +++ b/vps/static/css/presskit.css @@ -0,0 +1,165 @@ +* { + padding:0; + margin:0; + font-family: trebuchet ms; arial; calibri; gill sans; helvetica neue; candara; geneva; verdana; sans-serif; +} + +a { + text-decoration: none; +} +ul { list-style-position: inside; } + +.textbox { + margin: 20px; + padding: 20px; + background-color: #C9C2D6; + color: #080410; +} + +.grid { + display: grid; + grid-template-columns: auto 800px auto; + grid-template-rows: 25px 90px 1fr 100px; + grid-column-gap: 0px; + grid-row-gap: 0px; +} + +.whitespace { + grid-area: 1 / 1 / 2 / 4; + align-items: center; + background-color: #900C3F; +} + +.blessfrey-logo { grid-area: 1 / 2 / 2 / 3; + padding-top: 5px; + color: #FBDAEC; +} + +/* navigation pane */ + +.nav-row { + grid-area: 2 / 1 / 3 / 4; + background-color: #900C3F; +} + +.nav-grid { + grid-area: 2 / 2 / 3 / 3; + display: grid; + grid-template-columns: auto repeat(4, 70px) auto; + grid-template-rows: 90px; + grid-column-gap: 17px; + grid-row-gap: 0px; + align-items: end; + justify-items: center; +} + +.nav-bar { + grid-area: 1 / 1 / 2 / 7; + background-image: url(../img/ele/navbar.png); + height: 86px; + width: 800px; +} +.nav-index { + grid-area: 1 / 2 / 2 / 3; + padding-bottom: 3px; + position: relative; +} +.nav-game { + grid-area: 1 / 3 / 2 / 4; + padding-bottom: 3px; + position: relative; +} +.nav-diary { + grid-area: 1 / 4 / 2 / 5; + padding-bottom: 3px; + position: relative; +} +.nav-presskit { + grid-area: 1 / 5 / 2 / 6; + padding-bottom: 3px; + position: relative; +} +.nav-link { + position: absolute; + top: 45%; + left: 50%; + transform: translate(-50%, -50%) +} +.nav-link a { + font-size: 18px; +} + +.nav-link a:link { + color: #66C7F4; +} +.nav-link a:visited { + color: #CB9CF2; +} +.nav-link a:hover { + color: #F9B3D7; +} +.nav-link a:active { + color: #f463ad; +} + +/* Body */ + +.body-row { + grid-area: 3 / 1 / 4 / 4; + background-color: #080410; +} + +.pages { + grid-area: 3 / 2 / 4 / 3; + display: grid; + grid-template-columns: 800px; + grid-template-rows: repeat(9, auto); + grid-column-gap: 0px; + grid-row-gap: 0px; + background-color: #; + word-wrap: break-word; +} + +.fact { + grid-area: 1 / 1 / 2 / 2; +} +.desc { + grid-area: 2 / 1 / 3 / 2; +} +.features { + grid-area: 3 / 1 / 4 / 2; +} +.dev { + grid-area: 4 / 1 / 5 / 2; +} +.videos { + grid-area: 5 / 1 / 6 / 2; +} +.graphics { + grid-area: 6 / 1 / 7 / 2; + justify-content:center; + align-items: center; +} +.contact { + grid-area: 7 / 1 / 8 / 2; +} +.credits { + grid-area: 8 / 1 / 9 / 2; +} +.permissions { + grid-area: 9 / 1 / 10 / 2; +} + +.footer-row { + grid-area: 4 / 1 / 5 / 4; + background-color: #080410; +} + +.footer-content { + background-color: #080410; + color: #F9B3D7; + padding-top: 5px; + text-align: right; + overflow: hidden; + box-shadow: 0 100vh 0 100vh #581845; +} diff --git a/vps/static/css/projects.css b/vps/static/css/projects.css new file mode 100644 index 0000000..1cb5680 --- /dev/null +++ b/vps/static/css/projects.css @@ -0,0 +1,199 @@ +* { + padding:0; + margin:0; + font-family: trebuchet ms; arial; calibri; gill sans; helvetica neue; candara; geneva; verdana; sans-serif; +} + +a { + text-decoration: none; +} +ul { list-style-position: inside; } + +.grid { + display: grid; + grid-template-columns: auto 800px auto; + grid-template-rows: 25px 90px repeat(2, auto); + grid-column-gap: 0px; + grid-row-gap: 0px; +} + +.whitespace { + grid-area: 1 / 1 / 2 / 4; + display: flex; + flex-direction:column; + justify-content:center; + align-items: center; + background-color: #900C3F; +} + +.blessfrey-logo { + grid-area: 1 / 2 / 2 / 3; + padding-top: 5px; + color: #FBDAEC; +} + +/* navigation pane */ + +.nav-row { + grid-area: 2 / 1 / 3 / 4; + background-color: #900C3F; +} + +.nav-grid { + grid-area: 2 / 2 / 3 / 3; + display: flex; + flex-direction:column; + justify-content:flex-end; + display: grid; + grid-template-columns: auto repeat(4, 70px) auto; + grid-template-rows: 90px; + grid-column-gap: 17px; + grid-row-gap: 0px; + align-items: end; + justify-items: center; +} + +.nav-bar { + grid-area: 1 / 1 / 2 / 7; + background-image: url(../img/ele/navbar.png); + height: 86px; + width: 800px; +} +.nav-index { + grid-area: 1 / 2 / 2 / 3; + padding-bottom: 3px; + position: relative; +} +.nav-game { + grid-area: 1 / 3 / 2 / 4; + padding-bottom: 3px; + position: relative; +} +.nav-diary { + grid-area: 1 / 4 / 2 / 5; + padding-bottom: 3px; + position: relative; +} +.nav-presskit { + grid-area: 1 / 5 / 2 / 6; + padding-bottom: 3px; + position: relative; +} +.nav-link { + position: absolute; + top: 45%; + left: 50%; + transform: translate(-50%, -50%) +} +.nav-link a { + font-size: 18px; +} + +.nav-link a:link { + color: #66C7F4; +} +.nav-link a:visited { + color: #CB9CF2; +} +.nav-link a:hover { + color: #F9B3D7; +} +.nav-link a:active { + color: #f463ad; +} + +/* Body */ + +.body-row { + grid-area: 3 / 1 / 4 / 4; + background-color: #080410; +} + +.content { + grid-area: 3 / 2 / 4 / 3; + display: grid; + grid-template-columns: repeat(2, 400px); + grid-template-rows: 90px repeat(2, auto); + grid-column-gap: 0px; + grid-row-gap: 0px; +} + +.project-header { + grid-area: 1 / 1 / 2 / 3; + color: #F9B3D7; + font-size: 15px; + margin-top: 25px; + padding-top: 10px; + padding-left: 10px; +} + +.featured { + grid-area: 2 / 1 / 3 / 3; +} + +.featured-box { +} + +.featured-desc { + color: #F9B3D7; + font-size: 25px; + text-align: right; + margin-right: 10px; +} + +.featured-desc a:link { + color: #66C7F4; +} +.featured-desc a:visited { + color: #CB9CF2; +} +.featured-desc a:hover { + color: #F9B3D7; +} +.featured-desc a:active { + color: #f463ad; +} + +.more { + grid-area: 3 / 1 / 4 / 3; + width: 800px; + display: grid; + grid-template-columns: auto auto; +} + +.more-box { +} + +.more-desc { + color: #F9B3D7; + font-size: 18px; + text-align: center; + margin-right: 10px; +} + +.more-desc a:link { + color: #66C7F4; +} +.more-desc a:visited { + color: #CB9CF2; +} +.more-desc a:hover { + color: #F9B3D7; +} +.more-desc a:active { + color: #f463ad; +} + +.footer-row { + grid-area: 4 / 1 / 5 / 4; + background-color: #080410; +} + +.footer-content { + background-color: #080410; + color: #F9B3D7; + padding-top: 5px; + text-align: right; + overflow: hidden; + box-shadow: 0 100vh 0 100vh #581845; +} diff --git a/vps/static/css/template b/vps/static/css/template new file mode 100644 index 0000000..3bd398b --- /dev/null +++ b/vps/static/css/template @@ -0,0 +1,16 @@ +.parent { +display: grid; +grid-template-columns: auto 800px auto; +grid-template-rows: 25px 90px repeat(2, auto); +grid-column-gap: 0px; +grid-row-gap: 0px; +} + +.whitespace { grid-area: 1 / 1 / 2 / 4; } +.logo { grid-area: 1 / 2 / 2 / 3; } +.nav-row { grid-area: 2 / 1 / 3 / 4; } +.nav-bar { grid-area: 2 / 2 / 3 / 3; } +.body-row { grid-area: 3 / 1 / 4 / 4; } +.content { grid-area: 3 / 2 / 4 / 3; } +.footer-row { grid-area: 4 / 1 / 5 / 4; } + diff --git a/vps/static/extra/SimpleInputRec.cpp b/vps/static/extra/SimpleInputRec.cpp new file mode 100644 index 0000000..03b4e43 --- /dev/null +++ b/vps/static/extra/SimpleInputRec.cpp @@ -0,0 +1,288 @@ +/******************************************************************************/ +// SIMPLE INPUT RECORD/PLAYBACK +// (c) 2015 Brian Provinciano +// +// You are free to use this code for your own purposes, no strings attached. +// +// This is a very basic sample to record and playback button input. +// It's most useful when activated on startup, deactivated on shutdown for +// global button recording/playback. +// +// For details on more advanced implementations, see my GDC 2015 session: +// -> Automated Testing and Instant Replays in Retro City Rampage +// The slides and full video will be available on the GDC Vault at a later date. +/******************************************************************************/ + + +/******************************************************************************/ +// wrap it so it can be conditionally compiled in. +// for example, set INPUTREPLAY_CAN_RECORD to 1 to play the game and record the input, set it to 0 when done +// INPUTREPLAY_CAN_RECORD takes priority over INPUTREPLAY_CAN_PLAYBACK + +#define INPUTREPLAY_CAN_PLAYBACK 1 +#define INPUTREPLAY_CAN_RECORD 1 + +#define INPUTREPLAY_INCLUDED (INPUTREPLAY_CAN_PLAYBACK || INPUTREPLAY_CAN_RECORD) +/******************************************************************************/ + +#if INPUTREPLAY_INCLUDED + +#define INPUT_BUTTONS_TOTAL 32 // up to 32 +#define MAX_REC_LEN 0x8000 // the buffer size for storing RLE compressed button input (x each button) + +/******************************************************************************/ +typedef struct +{ + unsigned short *rledata; + unsigned short rlepos; + unsigned short datalen; + unsigned short currentrun; +} ButtonRec; +/******************************************************************************/ + +// if INPUTREPLAY_CAN_RECORD, as soon as this class is instanced, it will automatically record when instanced/created. +// statically creating this as a global will blanket the entire play session +// +// if INPUTREPLAY_CAN_PLAYBACK, playback will begin as soon as LoadFile() is used +// +class SimpleInputRec +{ + unsigned int m_buttonstate; + ButtonRec m_buttons[INPUT_BUTTONS_TOTAL]; + bool m_bRecording; + + unsigned char* m_data; + +public: + SimpleInputRec() + : m_buttonstate(0) + , m_data(NULL) + , m_bRecording(true) + { + } + + ~SimpleInputRec() + { + if(m_data) + { +#if INPUTREPLAY_CAN_RECORD + WriteToFile(); +#endif + delete[] m_data; + } + } + + // run each frame before the game uses the live button input. + // when recording, it saves the live input + // during playback, it overwrites the live input + void Update(bool bForce = false); + + // to start a playback +#if INPUTREPLAY_CAN_PLAYBACK + bool LoadFile(KSTR szfilename); +#endif + + // to finish recording +#if INPUTREPLAY_CAN_RECORD + void WriteToFile(); +#endif + +}; + +/******************************************************************************/ + +void SimpleInputRec::Update(bool bForce) +{ +#if INPUTREPLAY_CAN_RECORD + if(m_bRecording) + { + unsigned int newbuttons = nesinput.buttons; + + // allocate and initialize + if(!m_data) + { + m_data = new unsigned char[INPUT_BUTTONS_TOTAL * MAX_REC_LEN * 2]; + unsigned short* dataptr = (unsigned short*)m_data; + + for(int i=0; i>i)&1; + btn.rledata[btn.rlepos++] = (bit<<15) | btn.currentrun; + } + btn.currentrun = bForce? 0 : 1; + } + else + { + ++btn.currentrun; + } + } + + m_buttonstate = newbuttons; + } +#endif + +#if INPUTREPLAY_CAN_PLAYBACK + if(!m_bRecording) + { + bool bIsRunning = false; + for(int i=0; i>15)&1)<> 8, f); + } + for(int i=0; iattached. +// +// This is a very basic sample to record and playback button input. +// It's most useful when activated on startup, deactivated on shutdown for +// global button recording/playback. +// +// For details on more advanced implementations, see my GDC 2015 session: +// -> Automated Testing and Instant Replays in Retro City Rampage +// The slides and full video will be available on the GDC Vault at a later date. +/******************************************************************************/ + + +/******************************************************************************/ +// wrap it so it can be conditionally compiled in. +// for example, set INPUTREPLAY_CAN_RECORD to 1 to play the game and record the input, set it to 0 when done +// INPUTREPLAY_CAN_RECORD takes priority over INPUTREPLAY_CAN_PLAYBACK + +#define INPUTREPLAY_CAN_PLAYBACK 1 +#define INPUTREPLAY_CAN_RECORD 1 + +#define INPUTREPLAY_INCLUDED (INPUTREPLAY_CAN_PLAYBACK || INPUTREPLAY_CAN_RECORD) +/******************************************************************************/ + +#if INPUTREPLAY_INCLUDED + +#define INPUT_BUTTONS_TOTAL 32 // up to 32 +#define MAX_REC_LEN 0x8000 // the buffer size for storing RLE compressed button input (x each button) + +/******************************************************************************/ +typedef struct +{ + unsigned short *rledata; + unsigned short rlepos; + unsigned short datalen; + unsigned short currentrun; +} ButtonRec; +/******************************************************************************/ + +// if INPUTREPLAY_CAN_RECORD, as soon as this class is instanced, it will automatically record when instanced/created. +// statically creating this as a global will blanket the entire play session +// +// if INPUTREPLAY_CAN_PLAYBACK, playback will begin as soon as LoadFile() is used +// +class SimpleInputRec +{ + unsigned int m_buttonstate; + ButtonRec m_buttons[INPUT_BUTTONS_TOTAL]; + bool m_bRecording; + + unsigned char* m_data; + +public: + SimpleInputRec() + : m_buttonstate(0) + , m_data(NULL) + , m_bRecording(true) + { + } + + ~SimpleInputRec() + { + if(m_data) + { +#if INPUTREPLAY_CAN_RECORD + WriteToFile(); +#endif + delete[] m_data; + } + } + + // run each frame before the game uses the live button input. + // when recording, it saves the live input + // during playback, it overwrites the live input + void Update(bool bForce = false); + + // to start a playback +#if INPUTREPLAY_CAN_PLAYBACK + bool LoadFile(KSTR szfilename); +#endif + + // to finish recording +#if INPUTREPLAY_CAN_RECORD + void WriteToFile(); +#endif + +}; + +/******************************************************************************/ + +void SimpleInputRec::Update(bool bForce) +{ +#if INPUTREPLAY_CAN_RECORD + if(m_bRecording) + { + unsigned int newbuttons = nesinput.buttons; + + // allocate and initialize + if(!m_data) + { + m_data = new unsigned char[INPUT_BUTTONS_TOTAL * MAX_REC_LEN * 2]; + unsigned short* dataptr = (unsigned short*)m_data; + + for(int i=0; i>i)&1; + btn.rledata[btn.rlepos++] = (bit<<15) | btn.currentrun; + } + btn.currentrun = bForce? 0 : 1; + } + else + { + ++btn.currentrun; + } + } + + m_buttonstate = newbuttons; + } +#endif + +#if INPUTREPLAY_CAN_PLAYBACK + if(!m_bRecording) + { + bool bIsRunning = false; + for(int i=0; i>15)&1)<> 8, f); + } + for(int i=0; i +
    +

    + How did you find this page?
    + It's my secret page.
    +
    +

    Articles, Resources

    +
      +
    • https://love2dev.com/blog/customize-bulleted-list/ - cute CSS, use custom bullets
    • +
    • https://support.google.com/webmasters/answer/96569?hl=en - SEO, sponsored, user, and nofollow link parameters
    • +
    • https://support.google.com/webmasters/answer/6062598?hl=en&ref_topic=6061961 - Google robots.txt tester
    • +
    • add <meta name=”robots” content=”noindex,nofollow”> to pages to not index or follow links on that page
    • +
    +
    +
    +
    + diff --git a/vps/views/contact.tpl b/vps/views/contact.tpl new file mode 100644 index 0000000..c45fc55 --- /dev/null +++ b/vps/views/contact.tpl @@ -0,0 +1,13 @@ +% rebase('frame.tpl') + +
    +

    chimchooree

    +

    contact - general + business

    + Reach me through Twitter as @lilchimchooree or Discord as chimchooree#7250.
    +
    +

    a few personal pages

    +
      +
    • Books
    • +
    +
    + diff --git a/vps/views/credits.tpl b/vps/views/credits.tpl new file mode 100644 index 0000000..387f5f4 --- /dev/null +++ b/vps/views/credits.tpl @@ -0,0 +1,70 @@ +% rebase('frame.tpl') + +

    Credits


    +
    +game + art by chimchooree
    +(all assets are placeholder)
    +
    +game engine: godot engine, by Juan Linietsky, Ariel Manzur and contributors
    +
    +background music: "straight"
    +Benjamin "Bensound" Tissot
    +https://www.bensound.com/royalty-free-music/track/straight
    +license: Creative Commons License
    +
    +background music: "energy"
    +Benjamin "Bensound" Tissot
    +https://www.bensound.com/royalty-free-music/track/energy
    +license: Creative Commons License
    +
    +background music: "save"
    +LokiF
    +https://opengameart.org/content/gui-sound-effects
    +license: Public Domain CC0
    +
    +door sound: "Abandoned Villa- Thailand! Door Knocker & Door Knocking Sound Effects"
    +freetousesounds https://freetousesounds.bandcamp.com/album/abandoned-villa-thailand-door-knocker-door-knocking-sound-effects
    +license: Attribution 3.0 Unported (CC BY 3.0)
    +
    +click sound: "Click 1" from the UI SFX set
    +Kenney Vleugels
    +https://www.kenney.nl/assets/ui-audio
    +license: Public Domain CC0
    +
    +wrong sound: "Wrong 02"
    +https://www.noiseforfun.com/2012-sound-effects/wrong-02/
    +license: CC-BY-ND 3.0 Attribution license
    +
    +skill failure sound: "Negative" from the GUI Sound Effects set
    +LokiF
    +https://opengameart.org/content/gui-sound-effects
    +license: Public Domain CC0
    +
    +appraise sound: "Shimmer Glimmer Magic"
    +The Berklee College of Music
    +submitted to Open Game Art by qubodup
    +https://opengameart.org/content/shimmer-glitter-magic
    +license: CC-BY 3.0
    +
    +summon sound: "Elemental Spell"
    +Iwan "qubodup" Gabovitch
    +https://opengameart.org/content/elemental-spell
    +license: CC Attribution-ShareAlike 3.0 Unported
    +Copyright 2012 Iwan 'qubodup' Gabovitch http://qubodup.net qubodup@gmail.com | License: CC Attribution-ShareAlike 3.0 Unported http://creativecommons.org/licenses/by-sa/3.0/
    +
    +bingo win sound: "Positive"
    +Lokif
    +https://opengameart.org/content/gui-sound-effects
    +license: Public Domain CC0
    +
    +font: JFドットjiskan16 (JF Dot Jiskan16)
    +Sony Corp
    +http://jikasei.me/font/jf-dotfont/
    +license: Public Domain, stored in art/Fonts/Documentation/JF Dot Jiskan16/readme.txt
    +
    +font: pixel joy
    +chimchooree
    +https://fontstruct.com/fontstructions/show/1596262/pixel-joy
    +license: Public Domain
    +

    + diff --git a/vps/views/diary-boxes.tpl b/vps/views/diary-boxes.tpl new file mode 100644 index 0000000..1d1666e --- /dev/null +++ b/vps/views/diary-boxes.tpl @@ -0,0 +1,37 @@ + + diff --git a/vps/views/diary.tpl b/vps/views/diary.tpl new file mode 100644 index 0000000..824ede0 --- /dev/null +++ b/vps/views/diary.tpl @@ -0,0 +1,161 @@ +% rebase('frame.tpl') +% import re +
    +
    +
    + % max_pages = int((total - 1) / limit) +<% + # page never below 0 + if page <= 0: + page = 0 + end + # page never over maximum + if page > max_pages: + page = max_pages + end +%> + % # << is always active link pointing to 0 + << + + % # < points to 0 if page 0 or below + % if page <= 0: + < + % # < points to previous page otherwise + % else: + < + % end + + % # fill out number cluster to the left when page is high + % if max_pages > cluster and page > max_pages - cluster: + % for j in range(cluster - max_pages + page): + {{max_pages - cluster * 2 + j}} + % end + % end + + % # form cluster of number links around page + % for i in range(max(0,page - cluster), min(max_pages + 1,page + cluster + 1)): + % # bold current page number + % if i == page: + {{i}} + % # form neighboring numbers into links + % else: + {{i}} + % end + % end + + % # fill out number cluster to the right when page is low + % if page <= cluster - 1 and max_pages > page + cluster: + % for j in range(cluster - page): + {{page + j + cluster + 1}} + % end + % end + + % # > points to max if page is at or above maximum + % if page >= max_pages: + > + % # > point to next page otherwise + % else: + > + % end + + % # >> is always active link to maximum page + >> +
    +
    + + + +
    + % for s in snippets[page * limit:page * limit + limit]: +
    +
    +

    {{!s[0]}}

    +
    +
    + {{!s[1]}} +
    +
    + {{!s[2]}} + • + • + % message = "Hey,+check+out+this+post:+" + s[1] + ".,+" + s[3] + % message = message.replace('+','\+') + % message = re.sub('\s+?','+', message) + % message = message.replace('\\','') + % message = re.sub('<.*?>','', message) + • +
    + +
    + % end +
    +
    +
    + % max_pages = int((total - 1) / limit) +<% + # page never below 0 + if page <= 0: + page = 0 + end + # page never over maximum + if page > max_pages: + page = max_pages + end +%> + % # << is always active link pointing to 0 + << + + % # < points to 0 if page 0 or below + % if page <= 0: + < + % # < points to previous page otherwise + % else: + < + % end + + % # fill out number cluster to the left when page is high + % if max_pages > cluster and page > max_pages - cluster: + % for j in range(cluster - max_pages + page): + {{max_pages - cluster * 2 + j}} + % end + % end + + % # form cluster of number links around page + % for i in range(max(0,page - cluster), min(max_pages + 1,page + cluster + 1)): + % # bold current page number + % if i == page: + {{i}} + % # form neighboring numbers into links + % else: + {{i}} + % end + % end + + % # fill out number cluster to the right when page is low + % if page <= cluster - 1 and max_pages > page + cluster: + % for j in range(cluster - page): + {{page + j + cluster + 1}} + % end + % end + + % # > points to max if page is at or above maximum + % if page >= max_pages: + > + % # > point to next page otherwise + % else: + > + % end + + % # >> is always active link to maximum page + >> +
    +
    +% include diary-boxes.tpl diff --git a/vps/views/feature.tpl b/vps/views/feature.tpl new file mode 100644 index 0000000..8b7c7ec --- /dev/null +++ b/vps/views/feature.tpl @@ -0,0 +1,28 @@ +% rebase('frame.tpl') + + +
    + {{!entry}} +
    +
    + +% include diary-boxes.tpl + +
    + % if len(recommends) > 0: +

    more like this...

    + % end +
    + % if len(recommends) > 0: + % for s in recommends: +
    +
    + {{!s[0]}} +
    +
    + % end + % end +
    +
    + + diff --git a/vps/views/footer.tpl b/vps/views/footer.tpl new file mode 100644 index 0000000..0522f4b --- /dev/null +++ b/vps/views/footer.tpl @@ -0,0 +1,6 @@ + +
    + +
    diff --git a/vps/views/frame.tpl b/vps/views/frame.tpl new file mode 100644 index 0000000..8807186 --- /dev/null +++ b/vps/views/frame.tpl @@ -0,0 +1,26 @@ + + + + +% include('header.tpl') + + + + +
    + +% include('logo-bar.tpl') + +% include('nav.tpl') + +
    + +{{!base}} + +
    + +% include('footer.tpl') + + + + diff --git a/vps/views/game.tpl b/vps/views/game.tpl new file mode 100644 index 0000000..ad648ee --- /dev/null +++ b/vps/views/game.tpl @@ -0,0 +1,85 @@ +% rebase('frame.tpl') + +
    +
    + Blessfrey is an action rpg made in Godot Engine. Follow its development on Twitter @lilchimchooree
    +
    +
    +

    Story


    +
    + The main character suddenly transfers to a rural foreign town at the end of the year.
    + Her uncle is nowhere to be found, so she's left to her own devices for the summer.
    +
    +
    + Her classmates let her in on the rumor that the local shopping center is haunted at night, with strange lights and noises.
    + On a dare haunted sleepover, she discovers that the mall fills with slimes at night, bubbling up from secret tunnels underneath the stores.
    +
    +
    + But there's more than slimes beneath the city. There's a whole secret world down there.
    +
    +
    +
    +

    System


    +
    + In this build-based RPG, you explore the depths of the downtown dungeon with your customizable AI teammates.
    +
    +

    Socialize


    + During the adventure, your conversations with characters that will affect how they view you.
    +
    + In conversations, you select dialogue choices that will affect your relationship with characters and influence future events.
    +
    + CG illustrations will highlight particular moments in the story.
    +

    + +

    Learn


    + Unlock skills through gameplay. Meeting characters, reaching areas, fighting masses of the same enemy type, consuming items, and other mechanics will contribute to new skills learned.
    +
    + Each skill has different routes for unlocking, so they will be available regardless of playstyle.
    +
    + Your experiences will also unlock more detailed UI information.
    +
    +
    + +

    Build


    + Your dual class will determine the skills available to you. You choose your first class at start, but you will unlock more classes to use as your second class.
    +
    + Your skillbar only has 8 slots and can only hold 1 elite skill. Experiment and plan ahead to find skill synergies and build strategies. You can also change the dual classes and skillbars of your teammates.
    +
    + Pump your stat points into stats to increase the effectiveness of their associated skills. Gain stat points through story progression and level ups.
    +
    + Your second class, stat points, and skillbar can be freely changed in safe areas and are never unlearned or replaced.
    +
    +
    + +

    Battle


    + In this action rpg, you and your teammares will battle foes using default weapon attacks and skills from your skillbars.
    +
    + Weapons have different attack rates, ranges, and possible damage.
    +
    + Skills give specific effects according to their rules. They generally have an energy cost, an activation time, a cooldown time, and a target. Their powers range from dealing or healing damage, inflicting various conditions, interrupting opposing skills, and other abilities that are in-line with their associated class.
    +
    + Foes use the same dual class, skillbar build system, so you must not only learn how to use your skills but to defend against them.
    +

    + +
    +
    +

    Graphics

    +
    + + in-engine screenshot of the schoolyard + + + character concept art of Angel, Chloe, and Tessa + +
    + + in-engine footage of pathfinding projectile + + + screenshot of the godot editor + +
    +
    +
    + + diff --git a/vps/views/header.tpl b/vps/views/header.tpl new file mode 100644 index 0000000..9c96506 --- /dev/null +++ b/vps/views/header.tpl @@ -0,0 +1,3 @@ + {{title or 'blessfrey.me'}} + + diff --git a/vps/views/ideabox.tpl b/vps/views/ideabox.tpl new file mode 100644 index 0000000..24c104e --- /dev/null +++ b/vps/views/ideabox.tpl @@ -0,0 +1,23 @@ +% rebase('frame.tpl') +% import math + + +
    +
    +

    ideabox☆

    + My personal collection of inspiring concepts + favorite things. Many are from nature, culture, mythology, literature, music, art, and beauty. Some are personal concepts. Some are from existing IPs. You can use them, too, if they help you.
    +
    + + % for i in range(math.ceil(len(words) / limit)): + + % for j in range(limit): + % if j + i * limit < len(words): + + % end + % end + + % end +
    {{words[j + i * limit]}}
    +
    +
    + diff --git a/vps/views/index.tpl b/vps/views/index.tpl new file mode 100644 index 0000000..9c221fc --- /dev/null +++ b/vps/views/index.tpl @@ -0,0 +1,24 @@ +% rebase('frame.tpl') +% import random + + +
    + + + + + +
    +
    .      •        . news ☆            ..   .
    +
    +
      + % for n in news: + % bullet = random.choice(['.','•','☆','★']) +
    • {{bullet}} {{!n[1]}}
    • + % end +
    +
    +
    .            ★            ..             •           .            ☆
    +
    diff --git a/vps/views/logo-bar.tpl b/vps/views/logo-bar.tpl new file mode 100644 index 0000000..1e7c234 --- /dev/null +++ b/vps/views/logo-bar.tpl @@ -0,0 +1,5 @@ +
    + + diff --git a/vps/views/nav.tpl b/vps/views/nav.tpl new file mode 100644 index 0000000..37583e6 --- /dev/null +++ b/vps/views/nav.tpl @@ -0,0 +1,37 @@ + + + diff --git a/vps/views/presskit.tpl b/vps/views/presskit.tpl new file mode 100644 index 0000000..8348d83 --- /dev/null +++ b/vps/views/presskit.tpl @@ -0,0 +1,96 @@ +% rebase('frame.tpl') + +
    + +
    +

    blessfrey

    + (Presskit available as a PDF)

    +
    +
    +

    Fact Sheet

    +
      +
    • Description: Build synergies across your skillbar and teammates to explore the dungeon under the local shopping center.
    • +
    • Developer: chimchooree, US indie dev
    • +
    • Genre: Singleplayer Action RPG
    • +
    • Release Date: Spring 2030
    • +
    • Platforms: Linux, Windows, possibly more
    • +
    • Engine: Godot Engine
    • +
    • Website: blessfrey.me
    • +
    • Contact + Social: Twitter @lilchimchooree
    • +

    +
    + +
    +

    Description

    +
    + Blessfrey is the first commercial game in development by US-based indie game developer chimchooree.
    +
    + Blessfrey is a 2D action RPG set in a rural town riddled with secret tunnels and dungeons. The multiclass and skill system emphasizes player skill, personal expression, and exploration. Delve deeper under the town by discovering new skills, building synergies within your skillbar, and recruiting AI teammates.
    +
    +
    + +
    +

    Features

    +
      +
    • Try tens of possible dual-class combinations
    • +
    • Experiment with hundreds of possible skillbar combinations
    • +
    • Freely relocate skill points and swap out skills in safe areas. Few class progression decisions are permanent.
    • +
    • Learn new skills through exploration and gameplay
    • +
    • Explore an underground world
    • +

    +
    + +
    +

    Developer

    +
    + chimchooree is learning to code through making her dream game, automating the boring stuff, and taking online classes. See some of her pubic code on GitLab and some of her design process on her blog and on Twitter.
    +
    + Her most complex projects are blessfrey, a 2D action RPG written in Godot Engine's GDScript and Cat Store, a text-based cat show and breeding sim written in Java using IntelliJ.
    +
    + + + +
    +

    Graphics

    +
    +
    + + image: blessfrey screenshot: Angel in front of the Mock School +
    +
    + + (image: Lots of Angels and other characters at a shopping center) +
    +
    + + (image: Angel and some slimes in a cavern) +
    + + +
    +
    + +
    +

    Contact

    +
    + Please message me on Twitter @lilchimchooree. +
    + +
    +

    Credits

    +
      +
    • Code, Art, Design: chimchooree
    • +
    • Engine: Godot Engine
    • +
    • Full Credits
    • +

    +
    + +
    +

    Permission

    +
    + Freely use all of the content on this page, even for commercial use, at your own risk.
    +
    +
    + + + diff --git a/vps/views/projects.tpl b/vps/views/projects.tpl new file mode 100644 index 0000000..52b513f --- /dev/null +++ b/vps/views/projects.tpl @@ -0,0 +1,59 @@ +% rebase('frame.tpl') + + + + diff --git a/vps/views/wordbox.tpl b/vps/views/wordbox.tpl new file mode 100644 index 0000000..23d93d1 --- /dev/null +++ b/vps/views/wordbox.tpl @@ -0,0 +1,152 @@ +% rebase('frame.tpl') + +
    +

    + My personal collection of inspiring concepts. Many are from nature, culture, mythology, literature, music, art, and beauty. Some are personal concepts. Some are from existing IPs.
    +
    +

    Website To-Do

    +
      +
    • Write some diary entries
    • +
    • Make sure their dates + filenames match
    • +
    • Make sure their tags are formatted correctly
    • +
    • Proofread
    • +
    • Make sure their formatting is consistent
    • +
    • ALSO
    • +
    • make presskit page decent
    • +
    • update art assets
    • +
    +
    +
    +

    Articles

    +
      +
    • 8/6 - blessfrey
    • +
    • 8/20 - pixel joy
    • +
    • 9/1 - DIARY
    • +
    • 9/3 - jam
    • +
    • 9/17 - coroutines
    • +
    • 10/1 - DIARY
    • +
    • 10/15 - making of blessfrey.me
    • +
    • 10/29 - Japanese
    • +
    • 11/1 - DIARY
    • +
    • 11/12 - skills + super methods
    • +
    • 11/26 - pretendOS
    • +
    • 12/1 - DIARY
    • +
    • 12/10 - AI diagram
    • +
    • 12/24 - AI code - https://twitter.com/lilchimchooree/status/1206399601881812994
    • +
    • 1/1- DIARY
    • +
    • 1/7 - inventory system diagram
    • +
    • 1/21 - Graphics
    • +
    • 2/4 - web design resources
    • +
    • 2/18 - GDC
    • +
    • 2/1 - DIARY
    • +
    • 3/1 - DIARY
    • +
    • 4/1 - DIARY
    • +
    +
    +
    +

    Try to Do...

    +

    Weekly, Monthly

    +
      +
    • Keep monthly journal up to date
    • +
    • Add an article every week or two
    • +
    • Convert old infographics into articles
    • +
    +

    Sometime

    +
      +
    • Update Trello and share it
    • +
    • Diary - Add snippet art assets
    • +
    • Game - Add slideshow for story
    • +
    • Graphics - Concept Art
    • +
    • Graphics - Character Sheets
    • +
    • Graphics - Screenshots, GIFs
    • +
    • Graphics - Music
    • +
    • Graphics - Trailer
    • +
    • Just...better art and writing for everything...
    • +
    +
    +
    +

    Articles, Resources

    +
      +
    • https://love2dev.com/blog/customize-bulleted-list/ - cute CSS, use custom bullets
    • +
    • https://support.google.com/webmasters/answer/96569?hl=en - SEO, sponsored, user, and nofollow link parameters
    • +
    • https://support.google.com/webmasters/answer/6062598?hl=en&ref_topic=6061961 - Google robots.txt tester
    • +
    • add <meta name=”robots” content=”noindex,nofollow”> to pages to not index or follow links on that page
    • +
    +
    +
    +

    Lowest Sale Price

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Regular PriceSale PriceBrandProductURL
    $24$12 on Primer DayUrban DecayEyeshadow Primer Potionhttps://www.urbandecay.com/eyeshadow-primer-potion/UD515.html?dwvar_UD515_color=Original
    $30$21 on Black FridayBiossanceSqualane + Zinc Sheer Mineral Sunscreenhttps://biossance.com/collections/all/products/squalane-zinc-sheer-mineral-sunscreen-spf30
    $15.99???NeutrogenaSheer Zinc Face Dry Touch Sunscreen SPF 50https://www.ulta.com/sheer-zinc-face-dry-touch-sunscreen-spf-50?productId=xlsImpprod15721137
    $6.99$0.97Crystal DynamicsLegacy of Kain: Defiancehttps://www.gog.com/game/legacy_of_kain_defiance
    $6.99$0.97Crystal DynamicsLegacy of Kain: Blood Omen 2https://www.gog.com/game/legacy_of_kain_blood_omen_2
    $59.99$29.99ObsidianTHE OUTER WORLDShttps://www.gog.com/game/the_outer_worlds
    $59.99???PlatinumGamesASTRAL CHAINhttps://www.humblebundle.com/store/astral-chain
    $59.99???NintendoSuper Mario Odysseyhttps://www.humblebundle.com/store/super-mario-odyssey
    $59.99???NintendoPokémon Mystery Dungeon™: Rescue Team DX https://www.humblebundle.com/store/pokemon-mystery-dungeon-rescue-team-dx
    +
    +
    +