up to date with server

small-nav
chimchooree 4 years ago
parent 9a18189000
commit 2224957b7c

@ -1,35 +0,0 @@
<h1>9 weekly roundup</h1>
august 4-8, 2020
css, html, php, server, website<br>
<br>
<h2>tuesday, august 4</h2>
<ul>
<li>CentOS VPS obtained through OVH. Yay! We've always wanted a server.</li>
</ul>
<h2>wednesday, august 5</h2>
<ul>
<br>
<li>design the website</li>
<li>prototype of website running on the server</li>
<li>J set up automation with Jenkins + Ansible</li>
</ul>
<br>
<h2>thursday, august 6</h2>
<ul>
<li>create some placeholder graphics, articles + css</li>
<li>add a <a href="https://publish.twitter.com/#">Twitter timeline embed</a></li>
</ul>
<br>
<h2>friday, august 7</h2>
<ul>
<li>decide to use PHP for manage blessfrey's blog</li>
<li>set up a local Apache server for practice. <a href="200807.html">It was a little confusing!</a></li>
<li>wrote a vaguely functioning Hello, World! script in PHP
</ul>
<br>
<h2>saturday, august 8</h2>
<ul>
<li>forgot to bid on the Skull of Death in the <a href="http://www.verpets.com/auctions/">Auction House</a>...aw man...</li>
<li>added images to live site <a href="200808.html">despite conflicts with Linux's security</a></li>
</ul>
<br>

@ -1,5 +1,7 @@
<h1>8 what is blessfrey? </h1> <!--200918-->
<h1>what is blessfrey? </h1>
august 10, 2020<br> august 10, 2020<br>
pitch<br>
<br> <br>
<b>Blessfrey</b> is a 2D action RPG developed for PC by me, chimchooree. <br> <b>Blessfrey</b> is a 2D action RPG developed for PC by me, chimchooree. <br>
<br> <br>
@ -9,8 +11,7 @@ Class progression is freeform, and virtually no decision is permanent. At charac
<br> <br>
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. <br> 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. <br>
<br> <br>
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. <br> 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. <br>
<br> <br>
Blessfrey has been lots of fun to work on. I hope you enjoy it once a demo and eventually a game drops. <br> Blessfrey has been lots of fun to work on. I hope you enjoy it once a demo and eventually a game drops. <br>
<br> <br>
chimchooree<br>

@ -1,45 +0,0 @@
<h1>7 all weekly updates</h1>
august 13, 2020<br>
<br>
I've kept a more or less consistent private development diary for blessfrey since 2018. Here are the bulleted highlights, broken into weekly portions. I mostly keep it for myself to track progress. <br>
<br>
Meaningful discussions on design + process are expanded in separate feature articles. <br>
<br>
As a note, Blessfrey's working name is Dungeon Girls, but there's other projects floating around in there. Also, names of people are usually changed for privacy. <br>
<br>
Weekly diary pages are below.
<br>
<?php
//Convert Weekly Summary to Snippet
function snip_post($file) {
$post = fopen($file, "r") or die("Unable to load articles.");
fgets($post);
echo "<h1>".fgets($post)."</h1>";
echo fgets($post)."<br>";
echo " ... <a href={$file}>Keep Reading</a>";
echo "<br><br>";
}
// Iterate over Diary Pages + Snip
function convert_files($files) {
rsort($files);
foreach ($files as $file) {
snip_post($file);
}
}
// Collect files
function gather_files() {
$files = array();
foreach (glob("../weekly/*.*") as $file) {
$files[] = $file;
}
return $files;
}
// Flow - collect files + convert to snippets
// it should be reverse order..newest first
convert_files(gather_files());
?>
<br><br>

@ -1,36 +0,0 @@
<h1>6 weekly roundup</h1>
august 9-15, 2020
apache, automation, css, html, jenkins, nginx, php, server, website<br>
<br>
<h2>monday, august 9</h2>
<ul>
<li>second week of <a href="https://flightrising.com/main.php?p=dominance">dom</a>! yeah!</li>
<li>studied PHP with <a href="https://www.w3schools.com/php/php_intro.asp">W3Schools</a>
</ul>
<h2>wednesday, august 5</h2>
<ul>
<li>design the website</li>
<li>prototype of website running on the server</li>
<li>J set up automation with Jenkins + Ansible</li>
</ul>
<br>
<h2>thursday, august 6</h2>
<ul>
<li>create some placeholder graphics, articles + css</li>
<li>add a <a href="https://publish.twitter.com/#">Twitter timeline embed</a></li>
</ul>
<br>
<h2>friday, august 7</h2>
<ul>
<li>decide to use PHP for manage blessfrey's blog</li>
<li>set up a local Apache server with PHP for practice. <a href="200807.html">It was a little confusing!</a></li>
<li>wrote a vaguely functioning Hello, World! script in PHP
</ul>
<br>
<h2>saturday, august 8</h2>
<ul>
<li>forgot to bid on the Skull of Death in the auction house...aw man...</li>
<li>added images to live site <a href="200808.html">despite conflicts with Linux's security</a></li>
</ul>
<br>

@ -0,0 +1,104 @@
<!--200931,201031-->
<h1>august 2020: new server, new site</h1>
august 31, 2020<br>
apache, css, html, nginx, php, server, website<br>
<br>
<h2>tuesday, august 4</h2>
<ul>
<li>CentOS VPS obtained through OVH. Yay! We've always wanted a server.</li>
</ul>
<br>
<h2>wednesday, august 5</h2>
<ul>
<li>design the website</li>
<li>prototype of website running on the server</li>
</ul>
<br>
<h2>thursday, august 6</h2>
<ul>
<li>create some placeholder graphics, articles + css</li>
<li>add a <a href="https://publish.twitter.com/#">Twitter timeline embed</a></li>
</ul>
<br>
<h2>friday, august 7</h2>
<ul>
<li>decide to use PHP for manage blessfrey's blog</li>
<li>set up a local Apache server for practice. It was a little confusing!</li>
<li>wrote a vaguely functioning Hello, World! script in PHP</li>
</ul>
<br>
<h2>saturday, august 8</h2>
<ul>
<li>forgot to bid on the Skull of Death in the <a href="http://www.verpets.com/auctions/">Auction House</a>...aw man...</li>
<li>added images to live site despite conflicts with Linux's security</li>
</ul>
<br>
<h2>sunday, august 9</h2>
<ul>
<li>second week of <a href="https://flightrising.com/main.php?p=dominance">dom</a>! yeah!</li>
<li>studied PHP with <a href="https://www.w3schools.com/php/php_intro.asp">W3Schools</a></li>
</ul>
<br>
<h2>monday, august 10</h2>
<ul>
<li>studied PHP with <a href="https://www.w3schools.com/php/php_intro.asp">W3Schools</a></li>
</ul>
<br>
<h2>wednesday, august 12</h2>
<ul>
<li>J met his old co-worker, and he wanted to see my website. Oops. I don't have one yet...</li>
</ul>
<br>
<h2>friday, august 14</h2>
<ul>
<li>I'm getting more popular with J's friends. Happy.</li>
</ul>
<br>
<h2>saturday, august 15</h2>
<ul>
<li>Made a Python script that spits out new skill scenes for Godot after answering a little command line questionnaire. I could make it an add-on for the engine, but it would be a lot slower to develop and functionally no better.</li>
<li>Maybe I can rewrite it later in JSON, since Godot can read JSON.</li>
</ul>
<br>
<h2>sunday, august 16</h2>
<ul>
<li>First time attending for a conquest. Flameforger's is next week. Go Fire!</li>
</ul>
<br>
<h2>monday, august 17</h2>
<ul>
<li>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.</li>
</ul>
<br>
<h2>august 18 - august 21</h2>
<ul>
<li>Attend for the Fire Flight while trying out a new mmo - ArcheAge, since my friends play it.</li>
<li>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 all the time in ArcheAge...oops...that looked bad lol. It wasn't like I played more than a few minutes at a time until the late evening.</li>
<li>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.</li>
</ul>
<br>
<h2>saturday, august 22</h2>
<ul>
<li>I work on pagination. The concept boggles my mind, but I can break it into pieces to solve like any other problem.</li>
</ul>
<br>
<h2>sunday, august 23</h2>
<ul>
<li>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 - lots of new problems for me, but really interesting experience. </li>
</ul>
<br>
<h2>monday, august 24</h2>
<ul>
<li>Still working on pagination in PHP to create a navigation bar for my development blog. </li>
</ul>
<br>
<h2>tuesday, august 25</h2>
<ul>
<li>Play around with CSS + HTML for the website. The CSS Grid didn't exist the last time I used CSS (for petsite profiles lol), so I'm more comfortable with floats. The Grid looks so worth learning, though, for more consistent and responsive web design. </li>
</ul>
<br>
<h2>wednesday, august 26</h2>
<ul>
<li>Get the landing page looking okay while using the CSS Grid. </li>
</ul>
<br>

@ -1,6 +1,28 @@
<h1>5 my favorite GDC talks </h1> <!--200810-->
<h1>my favorite GDC talks </h1>
september 18, 2020<br> september 18, 2020<br>
game design, marketing<br>
<br> <br>
I really should be keeping a list of these with descriptions, so why not keep them in an article?<br> I really should be keeping a list of these with descriptions, so why not keep them in an article? <br>
<br>
<h2><a href="https://www.youtube.com/watch?v=W20t1zCZv8M">Automated Testing and Instant Replays in Retro City Rampage </a></h2><br>
Vblank Entertainment's Brian Provinciano (2015) <br>
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.
<br>
<ul>
<li><a href="/static/extra/SimpleInputRec.cpp">I backed up the code he shared here. </a> It is a simple example of how to record and playback button input, written in C++.</li>
</ul>
<br>
<br>
<h2><a href="https://www.youtube.com/watch?v=UJiv14uPOac">Empathizing with Steam: How People Shop for Your Game </a></h2><br>
Chris Zukowski (2020) <br>
tips for how to design your Steam store page based on Zukowski's screenshare and shopping diary observations of ordinary people shopping on Steam <br>
<br>
<ul>
<li>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. </li>
<li>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. </li>
<li>His conclusions are very similar to how I shop on Steam, except I could care less for the tag section. </li>
<li>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. </li>
<li>More notes @ <a href="/diary/entries/extra/gdc-design-steam-store">/diary/entries/extra/gdc-design-steam-store </a>
</ul>
<br> <br>
Work on it later.<br>

@ -1,13 +0,0 @@
<h1>4 weekly roundup</h1>
september 13-19, 2020
bottle<br>
<br>
<h2>friday, september 18</h2>
<ul>
<li>switched from PHP to Bottle</li>
<li>hello world in Bottle</li>
<li>created templates for main pages</li>
<li>Used Bottle to fill values in a template using variables</li>
<li>Used Bottle to avoid repeating html code in navigation pane, header, and footer</li>
</ul>
<br>

@ -1,14 +0,0 @@
<h1>3 weekly roundup</h1>
september 20-26, 2020
bottle<br>
<br>
<h2>friday, september 25</h2>
<ul>
<li>Diary snippets are formated from data taken from their articles. The article preview is cut to the character limit.</li>
</ul>
<br>
<h2>saturday, september 26</h2>
<ul>
<li>Updated the blessfrey.me script to serve static content like CSS stylesheets + images. Now the pages are actually styled.</li>
</ul>
<br>

@ -0,0 +1,40 @@
<!--200831,201031-->
<h1>september 2020: bye php, hello bottle</h1>
september 30, 2020
bottle, css, git, html, regex, regular expressions, website<br><br>
<br>
<h2>tuesday, september 1</h2>
<ul>
<li>sick day</li>
</ul>
<br>
<h2>wednesday, september 2</h2>
<ul>
<li>Look at examples of my favorite blogs, popular blogs, and just any blogs I can find from modern game, retro game, tech, cooking, any genre.</li>
</ul>
<br>
<h2>friday, september 18</h2>
<ul>
<li>switched from PHP to Bottle</li>
<li>hello world in Bottle</li>
<li>created templates for main pages</li>
<li>Used Bottle to fill values in a template using variables</li>
<li>Used Bottle to avoid repeating html code in navigation pane, header, and footer</li>
</ul>
<br>
<h2>friday, september 25</h2>
<ul>
<li>Diary snippets are formatted from data taken from their articles. The article preview is cut to the character limit.</li>
</ul>
<br>
<h2>saturday, september 26</h2>
<ul>
<li>Updated the blessfrey.me script to serve static content like CSS stylesheets + images. Now the pages are actually styled.</li>
</ul>
<br>
<h2>wednesday, september 30</h2>
<ul>
<li>Working on the website in the first time in a while;; </li>
<li>blessfrey.me's static pages look as intended - no footer in the middle of the body, no unclosed &lt;ul&gt; tags from diary entry previews breaking the CSS.</li>
<li>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. </li>
</ul>

@ -1,11 +0,0 @@
<h1>2 why bottle over php? </h1>
october 1, 2020<br>
<br>
<b>Bottle</b> is a Python framework for server-side web development.<br>
<br>
It's useful because it lets you reuse code for HTML, supports simple HTML templating, and is Python, which is a fun scripting language to use with tons of libraries.<br>
<br>
<b>PHP</b> is an old server language. It's very verbose, doesn't natively support templating, has extreme differences between versions which makes it confusing to research the fastest approaches, and its documentation is confusing. At least, amusingly, each documentation page has an open comment section underneath it, filled with conflicting and frustrated opinions, some dating back to when I was a toddler. <br>
<br>
It's still good to practice with, since it's a widely used web development language, and I feel like understanding it brings me closer to the PHP petsites of the mid-2000s which I dearly love.<br>
<br>

@ -1,17 +0,0 @@
<h1>1 this week</h1>
september 27-october 3, 2020
bottle, css, git, html, regex, regular expressions, website<br>
<br>
<h2>wednesday, august 9</h2>
<ul>
<li>Working on the website in the first time in a while;; </li>
<li>blessfrey.me's static pages look as intended - no footer in the middle of the body, no unclosed &lt;ul&gt; tags from diary entry previews breaking the CSS.</li>
<li>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. </li>
</ul>
<h2>thursday, october 1</h2>
<ul>
<li>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.</li>
<li>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, <a href="https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags">which is apparently a lost cause Stack Overflow users stand against daily, hourly even</a>. It's not so bad if it's not user content, and the content is pretty predictable, right?
<li>Pythex @ https://pythex.org/ is useful for checking whether your regular expression will catch your target strings</li>
<li>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.</li>
</ul>

@ -0,0 +1,9 @@
<!--200902,201001-->
<h1>web development resources</h1>
october 10, 2020<br>
accessibility, color, css, html, web design<br>
<br>
<ul>
<li><a href="https://validator.w3.org/nu/#textarea">W3's Nu Html Checker</a> - automatically check the validity of your html + css.</li>
<li><a href="https://webaim.org/resources/contrastchecker/">WebAIM's Contrast Checker</a> - check whether your font color contrasts well against your background color, at least in the eyes of a computer</li>
<li><a href="https://coolors.co/75dbcd-c9dbba-dcdba8-f5cda7-faa381">Coolors</a> - 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.</li>

@ -0,0 +1,86 @@
<!--200831,200931-->
<h1>october 2020: a blog that works</h1>
october 31, 2020<br>
css, html, python, website<br>
<br>
<h2>week 1 </h2><br>
bottle, python, regular expressions, website <br>
<h3>thursday, october 1 </h3><br>
<ul>
<li>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.</li>
<li>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, <a href="https:/git sta/stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags">which is apparently a lost cause Stack Overflow users stand against daily, hourly even</a>. It's not so bad if it's not user content, and the content is pretty predictable, right?
<li>Pythex @ https://pythex.org/ is useful for checking whether your regular expression will catch your target strings</li>
<li>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.</li>
<li>Blog removes html tags through regex patterns.</li>
<li>Fixed footer strangely appearing in the middle of the body on pages.</li>
</ul>
<br>
<h3>friday, october 2 </h3><br>
<ul>
<li>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.</li>
<li>set up blog navigation</li>
</ul>
<br>
<h3>saturday, october 3 </h3><br>
<ul>
<li>Blog removes html tags through regex patterns.</li>
<li>fixed footer strangely appearing in the middle of the body on pages.</li>
</ul>
<br>
<h2>week 2 </h2><br>
bottle, python, website<br>
<h3>sunday, october 4 </h3><br>
<ul>
<li>Started using absolute paths when needed. Diary snippet links to articles work now. Articles use CSS now.</li>
<li>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</li>
</ul>
<br>
<h3>monday, october 5 </h3><br>
<ul>
<li>made 'latest' box in sidebar of diary and articles with working links to the 5 latest articles</li>
<li>Made a simple page for myself that isn't linked anywhere</li>
</ul>
<br>
<h3>tuesday, october 6 </h3><br>
<ul>
<li>researched and added a robots.txt, sitemap, nofollow links</li>
<li>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.</li>
</ul>
<br>
<h3>wednesday, october 7 </h3><br>
<ul>
<li>Added a simple Contact page.</li>
<li>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.</li>
</ul>
<br>
<h3>saturday, october 10 </h3><br>
<ul>
<li>For testing, all colors were taken from the latest colors on random color websites, and all divs are stark. I 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.</li>
</ul>
<br>
<h3>tuesday, october 13</h3><br>
<ul>
<li>updated site skillbar nav background art.</li>
<li>continue working on CSS files.</li>
<li>made Twitter timeline's background transparent on index page</li>
</ul>
<br>
<h3>tuesday, october 16</h3><br>
<ul>
<li>edit game and presskit pages and some diary entries</li>
<li>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.</li>
</ul>
<br>
<h3>saturday, october 17 </h3><br>
<ul>
<li>worked at the cafe today. Since his battery is dead, he finally read some May I Ask For One Final Thing? I love that manga!</li>
<li>Refactored the main Bottle script. I wrote it hard and fast, so it was reading all the diary entries multiple times per refresh. It's not only cleaner, it also only reads the files twice.</li>
</ul>
<br>
<h3>monday, october 19 </h3><br>
<ul>
<li>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...been getting back into reading manga again, and it's inspiring me to draw more.</li>
<li>added the 'recommended articles' section to the bottom of diary entries.</li>
<li>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.</li>
</ul>
<br>

@ -0,0 +1,288 @@
<code>/******************************************************************************/</code>
<code>// SIMPLE INPUT RECORD/PLAYBACK</code>
<code>// (c) 2015 Brian Provinciano</code>
<code>//</code>
<code>// You are free to use this code for your own purposes, no strings attached.</code>
//
// 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<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
btn.rledata = dataptr;
dataptr += MAX_REC_LEN;
btn.rlepos = 0;
btn.currentrun = 0;
btn.datalen = MAX_REC_LEN;
}
}
// write RLE button bit streams
for(int i=0; i<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
if(bForce || (newbuttons&(1<<i)) != (m_buttonstate&(1<<i)) || btn.currentrun==0x7FFF)
{
if(btn.currentrun)
{
int bit = (m_buttonstate>>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<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
if(btn.rledata)
{
bIsRunning = true;
if(!btn.currentrun && btn.rlepos<btn.datalen)
{
unsigned short value = btn.rledata[btn.rlepos++];
btn.currentrun = value&0x7FFF;
m_buttonstate &= ~(1<<i);
m_buttonstate |= ((value>>15)&1)<<i;
--btn.currentrun;
}
else
{
if(btn.currentrun)
{
--btn.currentrun;
}
else if(btn.rlepos==btn.datalen)
{
btn.rledata = NULL;
}
}
}
}
if(bIsRunning)
{
// TODO: this is where you can overwrite the live button state to the prerecorded one
systeminput.buttons = m_buttonstate;
}
}
#endif
}
/******************************************************************************/
#if INPUTREPLAY_CAN_PLAYBACK
bool SimpleInputRec::LoadFile(KSTR szfilename)
{
for(int i=0; i<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
btn.datalen = 0;
btn.rledata = NULL;
btn.rlepos = 0;
btn.currentrun = 0;
}
delete[] m_data;
m_bRecording = false;
if(fcheckexists(szfilename))
{
FILE* f = fopen(szfilename, "wb");
if(f)
{
// WARNING: You'll want to do more error checking, but just to keep it simple...
fseek(f,0,SEEK_END);
unsigned long filelen = ftell(f);
fseek(f,0,SEEK_SET);
m_data = new unsigned char[filelen];
fread(m_data, 1, filelen, f);
fclose(f);
unsigned char* bufptr = m_data;
int numbuttons = bufptr[0] | (bufptr[1]<<8);
bufptr += 2;
if(numbuttons <= INPUT_BUTTONS_TOTAL)
{
for(int i=0; i<numbuttons; ++i)
{
ButtonRec& btn = m_buttons[i];
btn.datalen = bufptr[0] | (bufptr[1]<<8);
bufptr += 2;
}
for(int i=0; i<numbuttons; ++i)
{
ButtonRec& btn = m_buttons[i];
if(btn.datalen)
{
// WARNING: Endian dependent for simplcicity
btn.rledata = (unsigned short*)bufptr;
bufptr += btn.datalen*2;
}
}
}
return true;
}
}
return false;
}
#endif
/******************************************************************************/
#if INPUTREPLAY_CAN_RECORD
void SimpleInputRec::WriteToFile()
{
if(m_data && m_bRecording)
{
Update(true);
FILE* f = fopen("_autorec.rec","wb");
if(f)
{
fputc(INPUT_BUTTONS_TOTAL, f);
fputc(0, f);
for(int i=0; i<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
fputc((unsigned char)btn.rlepos, f);
fputc(btn.rlepos >> 8, f);
}
for(int i=0; i<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
// WARNING: Endian dependent for simplcicity
fwrite(btn.rledata, 2, btn.rlepos, f);
}
fclose(f);
}
}
}
#endif
/******************************************************************************/
#endif // INPUTREPLAY_INCLUDED
</code>

@ -1,11 +1,13 @@
<h1>my favorite GDC talks </h1> <!--200918-->
<h1>my favorite GDC talks: Empathizing with Steam: How People Shop for Your Game by Chris Zukowski (2020) </h1>
september 18, 2020<br> september 18, 2020<br>
<br> marketing, sale, steam, wishlist<br>
I really should be keeping a list of these with descriptions, so why not keep them in an article?<br>
<br> <br>
<a href="https://www.youtube.com/watch?v=UJiv14uPOac">Empathizing with Steam: How People Shop for Your Game by Chris Zukowski (2020)</a> - tips for how to design your Steam store page based on Zukowski's screenshare and shopping diary observations of ordinary people shopping on Steam <a href="https://www.youtube.com/watch?v=UJiv14uPOac">Empathizing with Steam: How People Shop for Your Game by Chris Zukowski (2020)</a> - tips for how to design your Steam store page based on Zukowski's screenshare and shopping diary observations of ordinary people shopping on Steam
<ul> <ul>
<li>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 Steam sale.</li> <li>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.</li>
<li>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.</li>
<li>His conclusions are very similar to how I shop on Steam, except I could care less for the tag section.</li>
<li>first 4 images are shown when hovering over thumbnail in Steam. Make them represent the pillars of your gameplay, so the genre is clear.</li> <li>first 4 images are shown when hovering over thumbnail in Steam. Make them represent the pillars of your gameplay, so the genre is clear.</li>
<li>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. <li>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.
<li>include UI in screenshots, so gamers can decipher the genre and some gameplay mechanics</li> <li>include UI in screenshots, so gamers can decipher the genre and some gameplay mechanics</li>

@ -1,38 +0,0 @@
import os
import glob
def file_to_string(f):
text = ""
with open(f, 'r') as n:
text = n.read()
n.close()
return text
def fill_text(f):
return file_to_string(f) #file_to_string('res/head.txt') + file_to_string(f) + file_to_string('res/tail.txt')
def create_files(files, directory):
for f in files:
print(f)
n = open(directory + '/' + os.path.basename(f), "w")
n.write(fill_text(f))
n.close()
def collect_raw(d):
return glob.glob(d)
def clear_articles():
files = glob.glob('../*')
print(files)
if '../raw' in files:
files.remove('../raw')
for f in files:
os.remove(f)
def main():
clear_articles()
create_files(collect_raw('entries/*'), '..')
## Start Program ##
main()

@ -1,35 +0,0 @@
<h1>9 weekly roundup</h1>
august 4-8, 2020
css, html, php, server, website<br>
<br>
<h2>tuesday, august 4</h2>
<ul>
<li>CentOS VPS obtained through OVH. Yay! We've always wanted a server.</li>
</ul>
<h2>wednesday, august 5</h2>
<ul>
<br>
<li>design the website</li>
<li>prototype of website running on the server</li>
<li>J set up automation with Jenkins + Ansible</li>
</ul>
<br>
<h2>thursday, august 6</h2>
<ul>
<li>create some placeholder graphics, articles + css</li>
<li>add a <a href="https://publish.twitter.com/#">Twitter timeline embed</a></li>
</ul>
<br>
<h2>friday, august 7</h2>
<ul>
<li>decide to use PHP for manage blessfrey's blog</li>
<li>set up a local Apache server for practice. <a href="200807.html">It was a little confusing!</a></li>
<li>wrote a vaguely functioning Hello, World! script in PHP
</ul>
<br>
<h2>saturday, august 8</h2>
<ul>
<li>forgot to bid on the Skull of Death in the <a href="http://www.verpets.com/auctions/">Auction House</a>...aw man...</li>
<li>added images to live site <a href="200808.html">despite conflicts with Linux's security</a></li>
</ul>
<br>

@ -1,16 +0,0 @@
<h1>8 what is blessfrey? </h1>
august 10, 2020<br>
<br>
<b>Blessfrey</b> is a 2D action RPG developed for PC by me, chimchooree. <br>
<br>
The game is designed to pit your skill + creativity against a series of combat + puzzle challenges while exploring the depths of the downtown dungeon. <br>
<br>
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. <br>
<br>
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. <br>
<br>
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. <br>
<br>
Blessfrey has been lots of fun to work on. I hope you enjoy it once a demo and eventually a game drops. <br>
<br>
chimchooree<br>

@ -1,45 +0,0 @@
<h1>7 all weekly updates</h1>
august 13, 2020<br>
<br>
I've kept a more or less consistent private development diary for blessfrey since 2018. Here are the bulleted highlights, broken into weekly portions. I mostly keep it for myself to track progress. <br>
<br>
Meaningful discussions on design + process are expanded in separate feature articles. <br>
<br>
As a note, Blessfrey's working name is Dungeon Girls, but there's other projects floating around in there. Also, names of people are usually changed for privacy. <br>
<br>
Weekly diary pages are below.
<br>
<?php
//Convert Weekly Summary to Snippet
function snip_post($file) {
$post = fopen($file, "r") or die("Unable to load articles.");
fgets($post);
echo "<h1>".fgets($post)."</h1>";
echo fgets($post)."<br>";
echo " ... <a href={$file}>Keep Reading</a>";
echo "<br><br>";
}
// Iterate over Diary Pages + Snip
function convert_files($files) {
rsort($files);
foreach ($files as $file) {
snip_post($file);
}
}
// Collect files
function gather_files() {
$files = array();
foreach (glob("../weekly/*.*") as $file) {
$files[] = $file;
}
return $files;
}
// Flow - collect files + convert to snippets
// it should be reverse order..newest first
convert_files(gather_files());
?>
<br><br>

@ -1,36 +0,0 @@
<h1>6 weekly roundup</h1>
august 9-15, 2020
apache, automation, css, html, jenkins, nginx, php, server, website<br>
<br>
<h2>monday, august 9</h2>
<ul>
<li>second week of <a href="https://flightrising.com/main.php?p=dominance">dom</a>! yeah!</li>
<li>studied PHP with <a href="https://www.w3schools.com/php/php_intro.asp">W3Schools</a>
</ul>
<h2>wednesday, august 5</h2>
<ul>
<li>design the website</li>
<li>prototype of website running on the server</li>
<li>J set up automation with Jenkins + Ansible</li>
</ul>
<br>
<h2>thursday, august 6</h2>
<ul>
<li>create some placeholder graphics, articles + css</li>
<li>add a <a href="https://publish.twitter.com/#">Twitter timeline embed</a></li>
</ul>
<br>
<h2>friday, august 7</h2>
<ul>
<li>decide to use PHP for manage blessfrey's blog</li>
<li>set up a local Apache server with PHP for practice. <a href="200807.html">It was a little confusing!</a></li>
<li>wrote a vaguely functioning Hello, World! script in PHP
</ul>
<br>
<h2>saturday, august 8</h2>
<ul>
<li>forgot to bid on the Skull of Death in the auction house...aw man...</li>
<li>added images to live site <a href="200808.html">despite conflicts with Linux's security</a></li>
</ul>
<br>

@ -1,13 +0,0 @@
<h1>4 weekly roundup</h1>
september 13-19, 2020
bottle<br>
<br>
<h2>friday, september 18</h2>
<ul>
<li>switched from PHP to Bottle</li>
<li>hello world in Bottle</li>
<li>created templates for main pages</li>
<li>Used Bottle to fill values in a template using variables</li>
<li>Used Bottle to avoid repeating html code in navigation pane, header, and footer</li>
</ul>
<br>

@ -1,14 +0,0 @@
<h1>3 weekly roundup</h1>
september 20-26, 2020
bottle<br>
<br>
<h2>friday, september 25</h2>
<ul>
<li>Diary snippets are formated from data taken from their articles. The article preview is cut to the character limit.</li>
</ul>
<br>
<h2>saturday, september 26</h2>
<ul>
<li>Updated the blessfrey.me script to serve static content like CSS stylesheets + images. Now the pages are actually styled.</li>
</ul>
<br>

@ -1,11 +0,0 @@
<h1>2 why bottle over php? </h1>
october 1, 2020<br>
<br>
<b>Bottle</b> is a Python framework for server-side web development.<br>
<br>
It's useful because it lets you reuse code for HTML, supports simple HTML templating, and is Python, which is a fun scripting language to use with tons of libraries.<br>
<br>
<b>PHP</b> is an old server language. It's very verbose, doesn't natively support templating, has extreme differences between versions which makes it confusing to research the fastest approaches, and its documentation is confusing. At least, amusingly, each documentation page has an open comment section underneath it, filled with conflicting and frustrated opinions, some dating back to when I was a toddler. <br>
<br>
It's still good to practice with, since it's a widely used web development language, and I feel like understanding it brings me closer to the PHP petsites of the mid-2000s which I dearly love.<br>
<br>

@ -1,17 +0,0 @@
<h1>1 this week</h1>
september 27-october 3, 2020
bottle, css, git, html, regex, regular expressions, website<br>
<br>
<h2>wednesday, august 9</h2>
<ul>
<li>Working on the website in the first time in a while;; </li>
<li>blessfrey.me's static pages look as intended - no footer in the middle of the body, no unclosed &lt;ul&gt; tags from diary entry previews breaking the CSS.</li>
<li>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. </li>
</ul>
<h2>thursday, october 1</h2>
<ul>
<li>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.</li>
<li>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, <a href="https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags">which is apparently a lost cause Stack Overflow users stand against daily, hourly even</a>. It's not so bad if it's not user content, and the content is pretty predictable, right?
<li>Pythex @ https://pythex.org/ is useful for checking whether your regular expression will catch your target strings</li>
<li>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.</li>
</ul>

@ -1,5 +0,0 @@
% rebase('feature.tpl')
<div class="body-row"> </div>
<div class="diary-entry">

@ -1,3 +0,0 @@
</div>
% include diary-boxes.tpl

@ -1,25 +1,63 @@
import datetime, os, re import datetime, os, re
from bottle import error, route, run, static_file, template, TEMPLATE_PATH from bottle import error, response, route, run, static_file, template, TEMPLATE_PATH
loc = 'diary/entries/' def list_rec(page):
loc = 'diary/entries/'
result = []
rec = []
comment = ""
if isinstance(page, int):
with open('diary/entries/' + str(page)) as f:
comment = f.readline()
comment = comment.replace('<!--','')
comment = comment.replace('-->','')
comment = comment.replace(' ','')
comment = clean(comment)
rec = comment.split(',')
for article in rec:
path = loc + article
data = []
with open(path) as f:
f.readline()
data.append(clean(f.readline().replace('<br>','')))
data.append(path)
result.append(data)
return result
def list_headlines(articles): def list_headlines(articles):
loc = 'diary/entries/'
result = [] result = []
text = [] text = []
for article in articles: for article in articles:
path = loc + article path = loc + article
with open(path) as f:
text = f.readlines()
b = [] b = []
b.append(path) b.append(path)
b.append(clean(text[0].replace('<br>',''))) with open(path) as f:
f.readline()
text = f.readline()
b.append(clean(text.replace('<br>','')))
result.append(b) result.append(b)
return result return result
def retrieve_article(page): def find_social_title(text):
return clean(text[1]).replace(' ','+')
def find_url(path):
return '/' + path.replace('.tpl','')
def find_timestamp(text):
return text[2].replace('<br>','')
def find_title(text):
return clean(text[1])
def article2list(article, loc):
text = []
with open(loc + article) as f:
text = f.readlines()
return text
def retrieve_article(page, loc):
text = [] text = []
string = "" string = ""
with open(loc + str(page)) as f: with open(loc + str(page)) as f:
@ -29,6 +67,7 @@ def retrieve_article(page):
return string return string
def list_snippets(articles): def list_snippets(articles):
loc = 'diary/entries/'
limit = 4 limit = 4
total = len(articles) total = len(articles)
result = [] result = []
@ -38,18 +77,12 @@ def list_snippets(articles):
text = [] text = []
a = [] a = []
length = 0 length = 0
with open(loc + article) as f: text = article2list(article, loc)
text = f.readlines() a.append(find_title(text))
length = len(text) a.append(prepare_article(text, path))
a.append(clean(text[0])) # title a.append(find_timestamp(text))
content = snip_article(find_content(article, length), path) a.append(find_url(path))
a.append(find_social_title(text))
if content.count('<ul>') > content.count('</ul>'):
content += '</ul>'
a.append(content) # snippet
a.append(text[1].replace('<br>','')) # timestamp
a.append('/' + path.replace('.tpl','')) # URL
a.append(clean(text[0]).replace(' ','+')) # social media title
result.append(a) result.append(a)
return result return result
@ -59,15 +92,27 @@ def count_lines(fname):
pass pass
return linenum return linenum
def find_content(article, length): def find_content(text):
length = len(text)
content = "" content = ""
with open(loc + article) as f: # form a string from relevant lines of the article
for pos, line in enumerate(f): #with open(loc + article) as f:
if pos > 1 and pos < length: pos = 0
content += line for line in text:
# skip to line 5
if pos > 4 and pos < length:
content += line
pos += 1
return content
def prepare_article(text, path):
content = snip_article(find_content(text), path)
if content.count('<ul>') > content.count('</ul>'):
content += '</ul>'
return content return content
def clean(result): def clean(result):
result = result.replace('\n','')
result = result.replace('<br>','') result = result.replace('<br>','')
result = re.sub(r'<a href=.*?>', '', result) result = re.sub(r'<a href=.*?>', '', result)
result = result.replace('</a>','') result = result.replace('</a>','')
@ -87,9 +132,12 @@ def sort_files(files):
files.sort(reverse=True) files.sort(reverse=True)
return files#list(reversed(files)) return files#list(reversed(files))
def gather_files(): def gather_files(loc):
files = os.listdir(loc) files = os.listdir(loc)
files.remove('raw') if 'raw' in files:
files.remove('raw')
if 'extra' in files:
files.remove('extra')
return files return files
# Static # Static
@ -102,6 +150,10 @@ def serve_css(filename):
def serve_img(filename): def serve_img(filename):
return static_file(filename, root='static/img') return static_file(filename, root='static/img')
@route('/static/extra/<filename:re:.*\.cpp>')
def serve_extra(filename):
return static_file(filename, root='static/extra', mimetype='text/plain', download=True)
# Routes # Routes
@error(404) @error(404)
@ -111,7 +163,8 @@ def error404(error):
@route('/') @route('/')
def index(): def index():
"""home page""" """home page"""
info = {'css': 'index', 'news': list_headlines(sort_files(gather_files())[0:10]), 'title': 'chimchooree\'s dev space - blessfrey', 'year': datetime.datetime.now()} loc = 'diary/entries/'
info = {'css': 'index', 'news': list_headlines(sort_files(gather_files(loc))[0:10]), 'title': 'chimchooree\'s dev space - blessfrey', 'year': datetime.datetime.now()}
return template('index.tpl', info) return template('index.tpl', info)
@route('/game') @route('/game')
@ -133,14 +186,26 @@ def diary2():
@route('/diary/<page:int>') @route('/diary/<page:int>')
def diary(page): def diary(page):
"""diary page""" """diary page"""
loc = 'diary/entries/'
assert isinstance(page, int) assert isinstance(page, int)
info = {'css': 'diary', 'title': 'blessfrey - developer diary', 'year': datetime.datetime.now(), 'snippets': list_snippets(sort_files(gather_files())), 'latest': list_headlines(sort_files(gather_files())[0:5]), 'total': len(gather_files()), 'limit': 4, 'cluster': 3, 'page': page} info = {'css': 'diary', 'title': 'blessfrey - developer diary', 'year': datetime.datetime.now(), 'snippets': list_snippets(sort_files(gather_files(loc))), 'latest': list_headlines(sort_files(gather_files(loc))[0:5]), 'total': len(gather_files(loc)), 'limit': 4, 'cluster': 3, 'page': page}
return template('diary.tpl', info) return template('diary.tpl', info)
@route('/diary/entries/<page:int>') @route('/diary/entries/<page:int>')
def entry(page): def entry(page):
"""diary entry""" """diary entry"""
info = {'css': 'feature', 'title': 'blessfrey - developer diary', 'year': datetime.datetime.now(), 'entry': retrieve_article(page), 'recommends': [['title','content','anchor'],['title','content','anchor'],['title','content','anchor']], 'articles': "Articles", 'latest': list_headlines(sort_files(gather_files())[0:5]), 'page': page} 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(sort_files(gather_files(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)
@route('/diary/entries/extra/<page>')
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(sort_files(gather_files('diary/entries/'))[0:5]), 'page': page}
abs_app_dir_path = os.path.dirname(os.path.realpath(__file__)) abs_app_dir_path = os.path.dirname(os.path.realpath(__file__))
abs_views_path = os.path.join(abs_app_dir_path, 'views') abs_views_path = os.path.join(abs_app_dir_path, 'views')
TEMPLATE_PATH.insert(0, abs_views_path ) TEMPLATE_PATH.insert(0, abs_views_path )
@ -164,6 +229,5 @@ def contact():
info = {'css': 'box', 'title': 'blessfrey - contact chimchooree', 'year': datetime.datetime.now()} info = {'css': 'box', 'title': 'blessfrey - contact chimchooree', 'year': datetime.datetime.now()}
return template('contact.tpl', info) return template('contact.tpl', info)
## Main ##
if __name__ == '__main__': if __name__ == '__main__':
run() run(host='127.0.0.1', port=9001)

@ -6,28 +6,13 @@
a { a {
text-decoration: none; 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; } ul { list-style-position: inside; }
.grid { .grid {
display: grid; display: grid;
grid-template-columns: auto 533px 267px auto; grid-template-columns: auto 533px 267px auto;
grid-template-rows: 25px 90px 40px repeat(4, 1fr) auto; grid-template-rows: 25px 90px 40px repeat(2, auto);
grid-column-gap: 0px; grid-column-gap: 0px;
grid-row-gap: 0px; grid-row-gap: 0px;
} }
@ -38,16 +23,20 @@ ul { list-style-position: inside; }
flex-direction:column; flex-direction:column;
justify-content:center; justify-content:center;
align-items: center; align-items: center;
background-color: #3B429F; background-color: #900C3F;
} }
.blessfrey-logo { grid-area: 1 / 2 / 2 / 4; } .blessfrey-logo {
grid-area: 1 / 2 / 2 / 4;
padding-top: 5px;
color: #FBDAEC;
}
/* navigation pane */ /* navigation pane */
.nav-row { .nav-row {
grid-area: 2 / 1 / 3 / 5; grid-area: 2 / 1 / 3 / 5;
background-color: #AA7DCE; background-color: #900C3F;
} }
.nav-grid { .nav-grid {
@ -58,12 +47,11 @@ ul { list-style-position: inside; }
display: grid; display: grid;
grid-template-columns: auto repeat(4, 70px) auto; grid-template-columns: auto repeat(4, 70px) auto;
grid-template-rows: 90px; grid-template-rows: 90px;
grid-column-gap: 8px; grid-column-gap: 17px;
grid-row-gap: 0px; grid-row-gap: 0px;
align-items: end; align-items: end;
justify-items: center; justify-items: center;
} }
.nav-bar { .nav-bar {
grid-area: 1 / 1 / 2 / 7; grid-area: 1 / 1 / 2 / 7;
display: flex; display: flex;
@ -79,6 +67,7 @@ ul { list-style-position: inside; }
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-game { .nav-game {
grid-area: 1 / 3 / 2 / 4; grid-area: 1 / 3 / 2 / 4;
@ -86,6 +75,7 @@ ul { list-style-position: inside; }
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-diary { .nav-diary {
grid-area: 1 / 4 / 2 / 5; grid-area: 1 / 4 / 2 / 5;
@ -93,6 +83,7 @@ ul { list-style-position: inside; }
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-presskit { .nav-presskit {
grid-area: 1 / 5 / 2 / 6; grid-area: 1 / 5 / 2 / 6;
@ -100,100 +91,160 @@ ul { list-style-position: inside; }
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-link {
/* nav buttons */ position: absolute;
top: 45%;
.button { left: 50%;
background-color: #000000; transform: translate(-50%, -50%)
color: #ce50ce;
font-size: 16px;
border: 2px solid #f7dd8e;
height: 48px;
width: 70px;
text-decoration: none;
display: flex;
flex-direction:column;
justify-content:center;
align-items: center;
} }
.nav-link a {
.button:hover { font-size: 18px;
background-color: #723777; }
color: #ce50ce; .nav-link a:link {
font-size: 16px; color: #66C7F4;
border: 2px solid #f7dd8e; }
height: 48px; .nav-link a:visited {
width: 70px; color: #CB9CF2;
text-decoration: none; }
display: flex; .nav-link a:hover {
flex-direction:column; color: #F9B3D7;
justify-content:center; }
align-items: center; .nav-link a:active {
color: #f463ad;
} }
/* Body */ /* Body */
.dir-row { .dir-row {
grid-area: 3 / 1 / 4 / 5; grid-area: 3 / 2 / 4 / 4;
background-color: #F5D7E3; background-color: #080410;
color: #F9B3D7;
} }
.diary-dir { .diary-dir {
grid-area: 3 / 2 / 4 / 4; grid-area: 3 / 1 / 4 / 5;
background-color: #900C3F; 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;
} }
.body-row { .body-row {
grid-area: 4 / 1 / 8 / 5; grid-area: 4 / 1 / 5 / 5;
background-color: #b56c4d; background-color: #080410;
} }
.diary-pages { .diary-pages {
grid-area: 4 / 2 / 8 / 3; grid-area: 4 / 2 / 5 / 3;
background-color: #F4A5AE; }
padding: 5px;
.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 { .about-box {
grid-area: 4 / 3 / 5 / 4; grid-area: 4 / 3 / 5 / 4;
background-color: #993759; background-color: #581845;
color: #F9B3D7;
text-align: center; text-align: center;
margin: 15px;
padding: 5px;
margin-top: 0px;
padding-bottom: 15px;
} }
.twitter-box { .twitter-box {
grid-area: 5 / 3 / 6 / 4; grid-area: 5 / 3 / 6 / 4;
background-color: #faa275; background-color: #581845;
color: #F9B3D7;
text-align: center; text-align: center;
margin: 15px;
padding: 5px;
padding-bottom: 15px;
} }
.latest { .latest {
grid-area: 6 / 3 / 7 / 4; grid-area: 6 / 3 / 7 / 4;
background-color: #ff8c61; background-color: #581845;
color: #F9B3D7;
text-align: center; text-align: center;
list-style-position: inside; list-style-position: inside;
margin: 15px;
padding: 5px;
} }
.latest-text { .latest-text {
background-color: #512806;
text-align: left; text-align: left;
list-style-position: inside; list-style-position: inside;
padding: 5px;
} }
.disclosure { .disclosure {
grid-area: 7 / 3 / 8 / 4; grid-area: 7 / 3 / 8 / 4;
background-color: #ce6a85; background-color: #581845;
color: #F9B3D7;
text-align: center; text-align: center;
margin: 15px;
padding: 5px;
padding-bottom: 15px;
} }
.footer-row { .footer-row {
grid-area: 8 / 1 / 9 / 5; grid-area: 5 / 1 / 6 / 5;
background-color: #A8577E; background-color: #080410;
} }
.footer-content { .footer-content {
background-color: pink; background-color: #080410;
color: #F9B3D7;
padding-top: 5px; padding-top: 5px;
padding-right: 25px; padding-right: 25px;
box-shadow: 0 100vh 0 100vh #581845; box-shadow: 0 100vh 0 100vh #581845;

@ -6,22 +6,7 @@
a { a {
text-decoration: none; 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; } ul { list-style-position: inside; }
.grid { .grid {
@ -38,16 +23,20 @@ ul { list-style-position: inside; }
flex-direction:column; flex-direction:column;
justify-content:center; justify-content:center;
align-items: center; align-items: center;
background-color: #3B429F; background-color: #900C3F;
} }
.blessfrey-logo { grid-area: 1 / 2 / 2 / 4; } .blessfrey-logo {
grid-area: 1 / 2 / 2 / 4;
padding-top: 5px;
color: #FBDAEC;
}
/* navigation pane */ /* navigation pane */
.nav-row { .nav-row {
grid-area: 2 / 1 / 3 / 5; grid-area: 2 / 1 / 3 / 5;
background-color: #AA7DCE; background-color: #900C3F;
} }
.nav-grid { .nav-grid {
@ -58,18 +47,16 @@ ul { list-style-position: inside; }
display: grid; display: grid;
grid-template-columns: auto repeat(4, 70px) auto; grid-template-columns: auto repeat(4, 70px) auto;
grid-template-rows: 90px; grid-template-rows: 90px;
grid-column-gap: 8px; grid-column-gap: 17px;
grid-row-gap: 0px; grid-row-gap: 0px;
align-items: end; align-items: end;
justify-items: center; justify-items: center;
} }
.nav-bar { .nav-bar {
grid-area: 1 / 1 / 2 / 7; grid-area: 1 / 1 / 2 / 7;
display: flex; display: flex;
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
align-items: bottom;
background-image: url(../img/ele/navbar.png); background-image: url(../img/ele/navbar.png);
height: 86px; height: 86px;
width: 800px; width: 800px;
@ -79,135 +66,165 @@ ul { list-style-position: inside; }
display: flex; display: flex;
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
align-items: bottom;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-game { .nav-game {
grid-area: 1 / 3 / 2 / 4; grid-area: 1 / 3 / 2 / 4;
display: flex; display: flex;
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
align-items: bottom;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-diary { .nav-diary {
grid-area: 1 / 4 / 2 / 5; grid-area: 1 / 4 / 2 / 5;
display: flex; display: flex;
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
align-items: bottom;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-presskit { .nav-presskit {
grid-area: 1 / 5 / 2 / 6; grid-area: 1 / 5 / 2 / 6;
display: flex; display: flex;
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
align-items: bottom;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-link {
/* nav buttons */ position: absolute;
top: 45%;
.button { left: 50%;
background-color: #000000; transform: translate(-50%, -50%)
color: #ce50ce;
font-size: 16px;
border: 2px solid #f7dd8e;
height: 48px;
width: 70px;
text-decoration: none;
display: flex;
flex-direction:column;
justify-content:center;
align-items: center;
} }
.nav-link a {
.button:hover { font-size: 18px;
background-color: #723777; }
color: #ce50ce; .nav-link a:link {
font-size: 16px; color: #66C7F4;
border: 2px solid #f7dd8e; }
height: 48px; .nav-link a:visited {
width: 70px; color: #CB9CF2;
text-decoration: none; }
display: flex; .nav-link a:hover {
flex-direction:column; color: #F9B3D7;
justify-content:center; }
align-items: center; .nav-link a:active {
color: #f463ad;
} }
/* Body */ /* Body */
.body-row { .body-row {
grid-area: 3 / 1 / 5 / 5; grid-area: 3 / 1 / 5 / 5;
background-color: #b56c4d; background-color: #080410;
} }
.diary-entry { .diary-entry {
grid-area: 3 / 2 / 4 / 3; grid-area: 3 / 2 / 4 / 3;
background-color: #aa2055; background-color: #C9C2D6;
padding: 5px; color: #080410;
padding: 20px;
margin-top: 40px;
margin-bottom: 30px;
} }
.sidebar ( .sidebar {
grid-area: 3 / 3 / 5 / 4; grid-area: 3 / 3 / 5 / 4;
background-color: #b56c4d;
display: grid; display: grid;
grid-template-columns: auto; grid-template-columns: auto;
grid-template-rows: repeat(4, auto); grid-template-rows: repeat(4, auto);
grid-column-gap: 0px; grid-column-gap: 0px;
grid-row-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 { .about-box {
grid-area: 1 / 1 / 2 / 2; grid-area: 1 / 1 / 2 / 2;
background-color: #993759; background-color: #581845;
color: #F9B3D7;
text-align: center;
margin: 15px;
padding: 5px;
margin-top: 0px;
padding-bottom: 15px;
} }
.twitter-box { .twitter-box {
grid-area: 2 / 1 / 3 / 2; grid-area: 2 / 1 / 3 / 2;
background-color: #faa275; background-color: #581845;
color: #F9B3D7;
text-align: center;
margin: 15px;
padding: 5px;
padding-bottom: 15px;
} }
.latest { .latest {
grid-area: 3 / 1 / 4 / 2; grid-area: 3 / 1 / 4 / 2;
background-color: #ff8c61; background-color: #581845;
color: #F9B3D7;
text-align: center;
list-style-position: inside;
margin: 15px;
padding: 5px;
} }
.latest-text { .latest-text {
background-color: #512806;
text-align: left; text-align: left;
list-style-position: inside;
padding: 5px;
} }
.disclosure { .disclosure {
grid-area: 4 / 1 / 5 / 2; grid-area: 4 / 1 / 5 / 2;
background-color: #ce6a85; background-color: #581845;
color: #F9B3D7;
text-align: center;
margin: 15px;
padding: 5px;
padding-bottom: 15px;
} }
.recommend { .recommend {
grid-area: 4 / 2 / 5 / 3; grid-area: 4 / 2 / 5 / 3;
background-color: #F5D7E3; background-color: #080410;
color: #F9B3D7;
display: grid; display: grid;
grid-template-columns: auto repeat(3, 100px) auto; grid-template-columns: auto auto auto;
grid-template-rows: auto; grid-template-rows: auto auto;
grid-column-gap: 0px; grid-column-gap: 0px;
grid-row-gap: 0px; grid-row-gap: 0px;
padding: 5px; padding: 5px;
} }
.more { grid-area: 1 / 1 / 2 / 4; }
.rec-box { grid-area: 2 / 2 / 3 / 3; }
.more { grid-area: 1 / 1 / 2 / 6; } .snip {
.snip1 { grid-area: 2 / 2 / 3 / 3; } width: 100px;
.snip2 { grid-area: 2 / 3 / 3 / 4; } float: left;
.snip3 { grid-area: 2 / 4 / 3 / 5; } margin: 50px;
}
.footer-row { .footer-row {
grid-area: 5 / 1 / 6 / 5; grid-area: 5 / 1 / 6 / 5;
background-color: #A8577E; background-color: #080410;
} }
.footer-content { .footer-content {
background-color: #5c374c; background-color: #080410;
color: #F9B3D7;
padding-top: 5px; padding-top: 5px;
padding-right: 25px; padding-right: 25px;
box-shadow: 0 100vh 0 100vh #581845; box-shadow: 0 100vh 0 100vh #581845;

@ -1,31 +1,19 @@
* { * {
padding:0; padding:0;
margin:0; margin:0;
font-family: trebuchet ms; arial; calibri; gill sans; helvetica neue; candara; geneva; verdana; sans-serif;
} }
a { a {
text-decoration: none; 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; } ul { list-style-position: inside; }
.textbox { .textbox {
margin: 20px; margin: 20px;
padding: 20px;
background-color: #C9C2D6;
color: #080410;
} }
.grid { .grid {
@ -42,27 +30,31 @@ ul { list-style-position: inside; }
flex-direction:column; flex-direction:column;
justify-content:center; justify-content:center;
align-items: center; align-items: center;
background-color: #3B429F; background-color: #900C3F;
} }
.blessfrey-logo { grid-area: 1 / 2 / 2 / 3; } .blessfrey-logo {
grid-area: 1 / 2 / 2 / 3;
padding-top: 5px;
color: #FBDAEC;
}
/* navigation pane */ /* navigation pane */
.nav-row { .nav-row {
grid-area: 2 / 1 / 3 / 4; grid-area: 2 / 1 / 3 / 4;
background-color: #AA7DCE; background-color: #900C3F;
} }
.nav-grid { .nav-grid {
grid-area: 2 / 2 / 3 / 3; grid-area: 2 / 2 / 3 / 3;
display: flex; display: flex;
flex-direction:column; flex-direction:row;
justify-content:flex-end; justify-content:flex-end;
display: grid; display: grid;
grid-template-columns: auto repeat(4, 70px) auto; grid-template-columns: auto repeat(4, 70px) auto;
grid-template-rows: 90px; grid-template-rows: 90px;
grid-column-gap: 8px; grid-column-gap: 17px;
grid-row-gap: 0px; grid-row-gap: 0px;
align-items: end; align-items: end;
justify-items: center; justify-items: center;
@ -83,6 +75,7 @@ ul { list-style-position: inside; }
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-game { .nav-game {
grid-area: 1 / 3 / 2 / 4; grid-area: 1 / 3 / 2 / 4;
@ -90,6 +83,7 @@ ul { list-style-position: inside; }
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-diary { .nav-diary {
grid-area: 1 / 4 / 2 / 5; grid-area: 1 / 4 / 2 / 5;
@ -97,6 +91,7 @@ ul { list-style-position: inside; }
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-presskit { .nav-presskit {
grid-area: 1 / 5 / 2 / 6; grid-area: 1 / 5 / 2 / 6;
@ -104,41 +99,35 @@ ul { list-style-position: inside; }
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-link {
/* nav buttons */ position: absolute;
top: 45%;
.button { left: 50%;
background-color: #000000; transform: translate(-50%, -50%)
color: #ce50ce;
font-size: 16px;
border: 2px solid #f7dd8e;
height: 48px;
width: 70px;
text-decoration: none;
display: flex;
flex-direction:column;
justify-content:center;
align-items: center;
} }
.nav-link a {
.button:hover { font-size: 18px;
background-color: #723777; }
color: #ce50ce; .nav-link a:link {
font-size: 16px; color: #66C7F4;
border: 2px solid #f7dd8e; }
height: 48px; .nav-link a:visited {
width: 70px; color: #CB9CF2;
text-decoration: none;
display: flex;
flex-direction:column;
justify-content:center;
align-items: center;
} }
.nav-link a:hover {
color: #F9B3D7;
}
.nav-link a:active {
color: #f463ad;
}
/* Body */
.body-row { .body-row {
grid-area: 3 / 1 / 4 / 4; grid-area: 3 / 1 / 4 / 4;
background-color: #d08d11; background-color: #080410;
} }
.pages { .pages {
@ -148,34 +137,34 @@ ul { list-style-position: inside; }
grid-template-rows: repeat(4, auto); grid-template-rows: repeat(4, auto);
grid-column-gap: 0px; grid-column-gap: 0px;
grid-row-gap: 0px; grid-row-gap: 0px;
background-color: #F0565C; background-color: #080410;
word-wrap: break-word; word-wrap: break-word;
} }
.desc { .desc {
grid-area: 1 / 1 / 2 / 2; grid-area: 1 / 1 / 2 / 2;
background-color: #F45693; background-color:;
} }
.story { .story {
grid-area: 2 / 1 / 3 / 2; grid-area: 2 / 1 / 3 / 2;
background-color: #D67476; background-color:;
} }
.system { .system {
grid-area: 3 / 1 / 4 / 2; grid-area: 3 / 1 / 4 / 2;
background-color: #F0787E; background-color:;
} }
.graphics { .graphics {
grid-area: 4 / 1 / 5 / 2; grid-area: 4 / 1 / 5 / 2;
background-color: #F75155; background-color:;
} }
.footer-row { .footer-row {
grid-area: 4 / 1 / 5 / 4; grid-area: 4 / 1 / 5 / 4;
background-color: green; background-color: #900C3F;
} }
.footer-content { .footer-content {
background-color: pink; background-color: #581845;
padding-top: 5px; padding-top: 5px;
text-align: right; text-align: right;
overflow: hidden; overflow: hidden;

@ -1,27 +1,12 @@
* { * {
padding:0; padding:0;
margin:0; margin:0;
font-family: trebuchet ms; arial; calibri; gill sans; helvetica neue; candara; geneva; verdana; sans-serif;
} }
a { a {
text-decoration: none; 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;
}
.grid { .grid {
display: grid; display: grid;
@ -37,16 +22,20 @@ mark {
flex-direction:column; flex-direction:column;
justify-content:center; justify-content:center;
align-items: center; align-items: center;
background-color: #DAF7A6; background-color: #900C3F;
} }
.blessfrey-logo { grid-area: 1 / 3 / 2 / 6; } .blessfrey-logo {
grid-area: 1 / 3 / 2 / 6;
padding-top: 5px;
color: #FBDAEC;
}
/* navigation pane */ /* navigation pane */
.nav-row { .nav-row {
grid-area: 2 / 1 / 3 / 8; grid-area: 2 / 1 / 3 / 8;
background-color: #FFC300; background-color: #900C3F;
} }
.nav-grid { .nav-grid {
@ -57,7 +46,7 @@ mark {
display: grid; display: grid;
grid-template-columns: auto repeat(4, 70px) auto; grid-template-columns: auto repeat(4, 70px) auto;
grid-template-rows: 90px; grid-template-rows: 90px;
grid-column-gap: 8px; grid-column-gap: 17px;
grid-row-gap: 0px; grid-row-gap: 0px;
align-items: end; align-items: end;
justify-items: center; justify-items: center;
@ -77,6 +66,7 @@ mark {
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-game { .nav-game {
grid-area: 1 / 3 / 2 / 4; grid-area: 1 / 3 / 2 / 4;
@ -84,6 +74,7 @@ mark {
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-diary { .nav-diary {
grid-area: 1 / 4 / 2 / 5; grid-area: 1 / 4 / 2 / 5;
@ -91,6 +82,7 @@ mark {
flex-direction: column; flex-direction: column;
justify-content: flex-end; justify-content: flex-end;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-presskit { .nav-presskit {
grid-area: 1 / 5 / 2 / 6; grid-area: 1 / 5 / 2 / 6;
@ -98,43 +90,35 @@ mark {
flex-direction: column; flex-direction: column;
justify-content: flex-end; justify-content: flex-end;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-link {
/* nav buttons */ position: absolute;
top: 45%;
.button { left: 50%;
background-color: #000000; transform: translate(-50%, -50%)
color: #ce50ce;
font-size: 16px;
border: 2px solid #f7dd8e;
height: 48px;
width: 70px;
text-decoration: none;
display: flex;
flex-direction:column;
justify-content:center;
align-items: center;
} }
.nav-link a {
.button:hover { font-size: 18px;
background-color: #723777; }
color: #ce50ce; .nav-link a:link {
font-size: 16px; color: #66C7F4;
border: 2px solid #f7dd8e; }
height: 48px; .nav-link a:visited {
width: 70px; color: #CB9CF2;
text-decoration: none; }
display: flex; .nav-link a:hover {
flex-direction:column; color: #F9B3D7;
justify-content:center; }
align-items: center; .nav-link a:active {
color: #f463ad;
} }
/* Body */ /* Body */
.body-row { .body-row {
grid-area: 3 / 1 / 4 / 8; grid-area: 3 / 1 / 4 / 8;
background-color: #FF5733; background-color: #080410;
} }
.social { .social {
@ -144,7 +128,7 @@ mark {
.bg { .bg {
grid-area: 3 / 3 / 4 / 6; grid-area: 3 / 3 / 4 / 6;
background-color: #C70039; background-color:;
background-image: url(../img/bg/homeBG.png); background-image: url(../img/bg/homeBG.png);
width: 650px; width: 650px;
height: 457px; height: 457px;
@ -168,6 +152,7 @@ mark {
display: flex; display: flex;
flex-direction:column; flex-direction:column;
background-color: #581845; background-color: #581845;
color: #F9B3D7;
height: 85px; height: 85px;
overflow-y: scroll; overflow-y: scroll;
margin-right: 0px; margin-right: 0px;
@ -180,6 +165,19 @@ mark {
padding-left: 8px; padding-left: 8px;
} }
.news a:link {
color: #F9B3D7;
}
.news a:visited {
color: #F9B3D7;
}
.news a:hover {
color: #f463ad;
}
.news a:active {
color: #f463ad;
}
.headline { .headline {
margin-right: 0px; margin-right: 0px;
margin-left: 0px; margin-left: 0px;
@ -193,6 +191,7 @@ mark {
.footer-content { .footer-content {
background-color: #581845; background-color: #581845;
color: #F9B3D7;
padding-top: 5px; padding-top: 5px;
text-align: right; text-align: right;
overflow: hidden; overflow: hidden;

@ -1,31 +1,19 @@
* { * {
padding:0; padding:0;
margin:0; margin:0;
font-family: trebuchet ms; arial; calibri; gill sans; helvetica neue; candara; geneva; verdana; sans-serif;
} }
a { a {
text-decoration: none; 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; } ul { list-style-position: inside; }
.textbox { .textbox {
margin: 20px; margin: 20px;
padding: 20px;
background-color: #C9C2D6;
color: #080410;
} }
.grid { .grid {
@ -42,16 +30,19 @@ ul { list-style-position: inside; }
flex-direction:column; flex-direction:column;
justify-content:center; justify-content:center;
align-items: center; align-items: center;
background-color: #3B429F; background-color: #900C3F;
} }
.blessfrey-logo { grid-area: 1 / 2 / 2 / 3; } .blessfrey-logo { grid-area: 1 / 2 / 2 / 3;
padding-top: 5px;
color: #FBDAEC;
}
/* navigation pane */ /* navigation pane */
.nav-row { .nav-row {
grid-area: 2 / 1 / 3 / 4; grid-area: 2 / 1 / 3 / 4;
background-color: #AA7DCE; background-color: #900C3F;
} }
.nav-grid { .nav-grid {
@ -62,7 +53,7 @@ ul { list-style-position: inside; }
display: grid; display: grid;
grid-template-columns: auto repeat(4, 70px) auto; grid-template-columns: auto repeat(4, 70px) auto;
grid-template-rows: 90px; grid-template-rows: 90px;
grid-column-gap: 8px; grid-column-gap: 17px;
grid-row-gap: 0px; grid-row-gap: 0px;
align-items: end; align-items: end;
justify-items: center; justify-items: center;
@ -83,6 +74,7 @@ ul { list-style-position: inside; }
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-game { .nav-game {
grid-area: 1 / 3 / 2 / 4; grid-area: 1 / 3 / 2 / 4;
@ -90,6 +82,7 @@ ul { list-style-position: inside; }
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-diary { .nav-diary {
grid-area: 1 / 4 / 2 / 5; grid-area: 1 / 4 / 2 / 5;
@ -97,6 +90,7 @@ ul { list-style-position: inside; }
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-presskit { .nav-presskit {
grid-area: 1 / 5 / 2 / 6; grid-area: 1 / 5 / 2 / 6;
@ -104,41 +98,36 @@ ul { list-style-position: inside; }
flex-direction:column; flex-direction:column;
justify-content:flex-end; justify-content:flex-end;
padding-bottom: 3px; padding-bottom: 3px;
position: relative;
} }
.nav-link {
/* nav buttons */ position: absolute;
top: 45%;
.button { left: 50%;
background-color: #000000; transform: translate(-50%, -50%)
color: #ce50ce; }
font-size: 16px; .nav-link a {
border: 2px solid #f7dd8e; font-size: 18px;
height: 48px;
width: 70px;
text-decoration: none;
display: flex;
flex-direction:column;
justify-content:center;
align-items: center;
} }
.button:hover { .nav-link a:link {
background-color: #723777; color: #66C7F4;
color: #ce50ce; }
font-size: 16px; .nav-link a:visited {
border: 2px solid #f7dd8e; color: #CB9CF2;
height: 48px; }
width: 70px; .nav-link a:hover {
text-decoration: none; color: #F9B3D7;
display: flex;
flex-direction:column;
justify-content:center;
align-items: center;
} }
.nav-link a:active {
color: #f463ad;
}
/* Body */
.body-row { .body-row {
grid-area: 3 / 1 / 4 / 4; grid-area: 3 / 1 / 4 / 4;
background-color: orange; background-color: #080410;
} }
.pages { .pages {
@ -148,56 +137,48 @@ ul { list-style-position: inside; }
grid-template-rows: repeat(9, auto); grid-template-rows: repeat(9, auto);
grid-column-gap: 0px; grid-column-gap: 0px;
grid-row-gap: 0px; grid-row-gap: 0px;
background-color: #F0565C; background-color: #;
word-wrap: break-word; word-wrap: break-word;
} }
.fact { .fact {
grid-area: 1 / 1 / 2 / 2; grid-area: 1 / 1 / 2 / 2;
background-color: #F45693;
} }
.desc { .desc {
grid-area: 2 / 1 / 3 / 2; grid-area: 2 / 1 / 3 / 2;
background-color: #9b0017;
} }
.features { .features {
grid-area: 3 / 1 / 4 / 2; grid-area: 3 / 1 / 4 / 2;
background-color: #f84c09;
} }
.dev { .dev {
grid-area: 4 / 1 / 5 / 2; grid-area: 4 / 1 / 5 / 2;
background-color: #900C3F;
} }
.videos { .videos {
grid-area: 5 / 1 / 6 / 2; grid-area: 5 / 1 / 6 / 2;
background-color: #ff8600;
} }
.graphics { .graphics {
grid-area: 6 / 1 / 7 / 2; grid-area: 6 / 1 / 7 / 2;
background-color: #b61643;
justify-content:center; justify-content:center;
align-items: center; align-items: center;
} }
.contact { .contact {
grid-area: 7 / 1 / 8 / 2; grid-area: 7 / 1 / 8 / 2;
background-color: #4f000b;
} }
.credits { .credits {
grid-area: 8 / 1 / 9 / 2; grid-area: 8 / 1 / 9 / 2;
background-color: #720026;
} }
.permissions { .permissions {
grid-area: 9 / 1 / 10 / 2; grid-area: 9 / 1 / 10 / 2;
background-color: #fc60a8;
} }
.footer-row { .footer-row {
grid-area: 4 / 1 / 5 / 4; grid-area: 4 / 1 / 5 / 4;
background-color: green; background-color: #080410;
} }
.footer-content { .footer-content {
background-color: pink; background-color: #080410;
color: #F9B3D7;
padding-top: 5px; padding-top: 5px;
text-align: right; text-align: right;
overflow: hidden; overflow: hidden;

@ -1,45 +0,0 @@
/* blessfrey css by chimchooree, written in xed */
body {
color: #4f000b;
font-family: lato; calibri; arial; sans-serif;
font-size: 20px;
background-color: #ff7f51;
background-image: url(https://i.imgur.com/Pp71lWt.png);
/*background-image: url(/res/img/medallion.png);*/
background-size: 70px 70px;
background-repeat: repeat;
margin-right: 0px;
margin-left: 0px;
margin-top: 0px;
margin-bottom: 0px;
}
/* nav buttons */
.button {
background-color: #000000;
color: #ce50ce;
font-size: 16px;
border: 2px solid #f7dd8e;
height: 48px;
width: 94px;
text-decoration: none;
display: flex;
flex-direction:column;
justify-content:center;
align-items: center;
}
.button:hover {
background-color: #723777;
color: #ce50ce;
border: 2px solid #f7dd8e;
height: 48px;
width: 94px;
text-decoration: none;
display: flex;
flex-direction:column;
justify-content:center;
align-items: center;
}

@ -1,186 +0,0 @@
* {
padding:0;
margin:0;
}
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; }
.textbox {
margin: 20px;
}
.grid {
height: 100vh;
width: 100vw;
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: #3B429F;
}
.blessfrey-logo { grid-area: 1 / 2 / 2 / 3; }
/* navigation pane */
.nav-row {
grid-area: 2 / 1 / 3 / 4;
background-color: #AA7DCE;
}
.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: 8px;
grid-row-gap: 0px;
align-items: end;
justify-items: center;
}
.nav-bar {
grid-area: 1 / 1 / 2 / 7;
display: flex;
flex-direction:column;
justify-content:flex-end;
align-items: bottom;
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;
align-items: bottom;
padding-bottom: 3px;
}
.nav-game {
grid-area: 1 / 3 / 2 / 4;
display: flex;
flex-direction:column;
justify-content:flex-end;
align-items: bottom;
padding-bottom: 3px;
}
.nav-diary {
grid-area: 1 / 4 / 2 / 5;
display: flex;
flex-direction:column;
justify-content:flex-end;
align-items: bottom;
padding-bottom: 3px;
}
.nav-presskit {
grid-area: 1 / 5 / 2 / 6;
display: flex;
flex-direction:column;
justify-content:flex-end;
align-items: bottom;
padding-bottom: 3px;
}
/* nav buttons */
.button {
background-color: #000000;
color: #ce50ce;
font-size: 16px;
border: 2px solid #f7dd8e;
height: 48px;
width: 70px;
text-decoration: none;
display: flex;
flex-direction:column;
justify-content:center;
align-items: center;
}
.button:hover {
background-color: #723777;
color: #ce50ce;
font-size: 16px;
border: 2px solid #f7dd8e;
height: 48px;
width: 70px;
text-decoration: none;
display: flex;
flex-direction:column;
justify-content:center;
align-items: center;
}
.body-row {
grid-area: 3 / 1 / 4 / 4;
background-color: #d08d11;
}
.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: #F0565C;
word-wrap: break-word;
}
.desc {
grid-area: 1 / 1 / 2 / 2;
background-color: #F45693;
}
.story {
grid-area: 2 / 1 / 3 / 2;
background-color: #D67476;
}
.system {
grid-area: 3 / 1 / 4 / 2;
background-color: #F0787E;
}
.graphics {
grid-area: 4 / 1 / 5 / 2;
background-color: #F75155;
}
.footer-row {
grid-area: 4 / 1 / 5 / 4;
background-color: #EC424A;
text-align: right;
padding-top: 5px;
padding-right: 25px;
}
.footer {
background-color: #060d1a;
}

@ -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<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
btn.rledata = dataptr;
dataptr += MAX_REC_LEN;
btn.rlepos = 0;
btn.currentrun = 0;
btn.datalen = MAX_REC_LEN;
}
}
// write RLE button bit streams
for(int i=0; i<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
if(bForce || (newbuttons&(1<<i)) != (m_buttonstate&(1<<i)) || btn.currentrun==0x7FFF)
{
if(btn.currentrun)
{
int bit = (m_buttonstate>>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<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
if(btn.rledata)
{
bIsRunning = true;
if(!btn.currentrun && btn.rlepos<btn.datalen)
{
unsigned short value = btn.rledata[btn.rlepos++];
btn.currentrun = value&0x7FFF;
m_buttonstate &= ~(1<<i);
m_buttonstate |= ((value>>15)&1)<<i;
--btn.currentrun;
}
else
{
if(btn.currentrun)
{
--btn.currentrun;
}
else if(btn.rlepos==btn.datalen)
{
btn.rledata = NULL;
}
}
}
}
if(bIsRunning)
{
// TODO: this is where you can overwrite the live button state to the prerecorded one
systeminput.buttons = m_buttonstate;
}
}
#endif
}
/******************************************************************************/
#if INPUTREPLAY_CAN_PLAYBACK
bool SimpleInputRec::LoadFile(KSTR szfilename)
{
for(int i=0; i<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
btn.datalen = 0;
btn.rledata = NULL;
btn.rlepos = 0;
btn.currentrun = 0;
}
delete[] m_data;
m_bRecording = false;
if(fcheckexists(szfilename))
{
FILE* f = fopen(szfilename, "wb");
if(f)
{
// WARNING: You'll want to do more error checking, but just to keep it simple...
fseek(f,0,SEEK_END);
unsigned long filelen = ftell(f);
fseek(f,0,SEEK_SET);
m_data = new unsigned char[filelen];
fread(m_data, 1, filelen, f);
fclose(f);
unsigned char* bufptr = m_data;
int numbuttons = bufptr[0] | (bufptr[1]<<8);
bufptr += 2;
if(numbuttons <= INPUT_BUTTONS_TOTAL)
{
for(int i=0; i<numbuttons; ++i)
{
ButtonRec& btn = m_buttons[i];
btn.datalen = bufptr[0] | (bufptr[1]<<8);
bufptr += 2;
}
for(int i=0; i<numbuttons; ++i)
{
ButtonRec& btn = m_buttons[i];
if(btn.datalen)
{
// WARNING: Endian dependent for simplcicity
btn.rledata = (unsigned short*)bufptr;
bufptr += btn.datalen*2;
}
}
}
return true;
}
}
return false;
}
#endif
/******************************************************************************/
#if INPUTREPLAY_CAN_RECORD
void SimpleInputRec::WriteToFile()
{
if(m_data && m_bRecording)
{
Update(true);
FILE* f = fopen("_autorec.rec","wb");
if(f)
{
fputc(INPUT_BUTTONS_TOTAL, f);
fputc(0, f);
for(int i=0; i<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
fputc((unsigned char)btn.rlepos, f);
fputc(btn.rlepos >> 8, f);
}
for(int i=0; i<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
// WARNING: Endian dependent for simplcicity
fwrite(btn.rledata, 2, btn.rlepos, f);
}
fclose(f);
}
}
}
#endif
/******************************************************************************/
#endif // INPUTREPLAY_INCLUDED

@ -0,0 +1,287 @@
/******************************************************************************/
// SIMPLE INPUT RECORD/PLAYBACK
// (c) 2015 Brian Provinciano
//
// You are free to use this code for your own purposes, no strings <code>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<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
btn.rledata = dataptr;
dataptr += MAX_REC_LEN;
btn.rlepos = 0;
btn.currentrun = 0;
btn.datalen = MAX_REC_LEN;
}
}
// write RLE button bit streams
for(int i=0; i<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
if(bForce || (newbuttons&(1<<i)) != (m_buttonstate&(1<<i)) || btn.currentrun==0x7FFF)
{
if(btn.currentrun)
{
int bit = (m_buttonstate>>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<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
if(btn.rledata)
{
bIsRunning = true;
if(!btn.currentrun && btn.rlepos<btn.datalen)
{
unsigned short value = btn.rledata[btn.rlepos++];
btn.currentrun = value&0x7FFF;
m_buttonstate &= ~(1<<i);
m_buttonstate |= ((value>>15)&1)<<i;
--btn.currentrun;
}
else
{
if(btn.currentrun)
{
--btn.currentrun;
}
else if(btn.rlepos==btn.datalen)
{
btn.rledata = NULL;
}
}
}
}
if(bIsRunning)
{
// TODO: this is where you can overwrite the live button state to the prerecorded one
systeminput.buttons = m_buttonstate;
}
}
#endif
}
/******************************************************************************/
#if INPUTREPLAY_CAN_PLAYBACK
bool SimpleInputRec::LoadFile(KSTR szfilename)
{
for(int i=0; i<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
btn.datalen = 0;
btn.rledata = NULL;
btn.rlepos = 0;
btn.currentrun = 0;
}
delete[] m_data;
m_bRecording = false;
if(fcheckexists(szfilename))
{
FILE* f = fopen(szfilename, "wb");
if(f)
{
// WARNING: You'll want to do more error checking, but just to keep it simple...
fseek(f,0,SEEK_END);
unsigned long filelen = ftell(f);
fseek(f,0,SEEK_SET);
m_data = new unsigned char[filelen];
fread(m_data, 1, filelen, f);
fclose(f);
unsigned char* bufptr = m_data;
int numbuttons = bufptr[0] | (bufptr[1]<<8);
bufptr += 2;
if(numbuttons <= INPUT_BUTTONS_TOTAL)
{
for(int i=0; i<numbuttons; ++i)
{
ButtonRec& btn = m_buttons[i];
btn.datalen = bufptr[0] | (bufptr[1]<<8);
bufptr += 2;
}
for(int i=0; i<numbuttons; ++i)
{
ButtonRec& btn = m_buttons[i];
if(btn.datalen)
{
// WARNING: Endian dependent for simplcicity
btn.rledata = (unsigned short*)bufptr;
bufptr += btn.datalen*2;
}
}
}
return true;
}
}
return false;
}
#endif
/******************************************************************************/
#if INPUTREPLAY_CAN_RECORD
void SimpleInputRec::WriteToFile()
{
if(m_data && m_bRecording)
{
Update(true);
FILE* f = fopen("_autorec.rec","wb");
if(f)
{
fputc(INPUT_BUTTONS_TOTAL, f);
fputc(0, f);
for(int i=0; i<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
fputc((unsigned char)btn.rlepos, f);
fputc(btn.rlepos >> 8, f);
}
for(int i=0; i<INPUT_BUTTONS_TOTAL; ++i)
{
ButtonRec& btn = m_buttons[i];
// WARNING: Endian dependent for simplcicity
fwrite(btn.rledata, 2, btn.rlepos, f);
}
fclose(f);
}
}
}
#endif
/******************************************************************************/
#endif // INPUTREPLAY_INCLUDED

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 817 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 KiB

@ -1,11 +1,11 @@
% rebase('frame.tpl') % rebase('frame.tpl')
<!--Content--> <!--Content-->
<div class="contact-box"> <div class="contact-box">
<h1>Contact</h1> <h1>contact</h1>
<h2>General + Business</h2> <h2>general + business</h2>
I would love to hear from you once blessfrey.me is functional and my dev email is set up. Won't be long.<br> I would love to hear from you once blessfrey.me is functional and my dev email is set up. Won't be long.<br>
<br> <br>
You can always reach me on Twitter as <a href="https://twitter.com/lilchimchooree" rel="nofollow">@lilchimchooree</a> through DMs or mentions.<br> You can always reach me through Twitter as <a href="https://twitter.com/lilchimchooree" rel="nofollow">@lilchimchooree</a>.<br>
<br> <br>
Press can snag a copy of my presskit at the <a href="/presskit" rel="nofollow">presskit</a> page. Press can snag a copy of my presskit at the <a href="/presskit" rel="nofollow">presskit</a> page.
<br><br> <br><br>

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

@ -2,12 +2,12 @@
<div class="sidebar"> <div class="sidebar">
<div class="about-box"> <div class="about-box">
<h1>about</h1> <h1>about</h1>
blessfrey is a game.<br> <b>blessfrey</b> is a 2D action RPG developed for PC. Build the best skillbar against the next challenge.<br>
</div> </div>
<div class="twitter-box"> <div class="twitter-box">
<h1>follow</h1> <h1>chat</h1>
<a href="https://twitter.com/lilchimchooree">@lilchimchooree</a><br> Twitter: <a href="https://twitter.com/lilchimchooree">@lilchimchooree</a><br>
<br> <br>
<a href="/contact" rel="nofollow">contact me</a><br> <a href="/contact" rel="nofollow">contact me</a><br>
</div> </div>
@ -17,21 +17,19 @@
<div class="latest-text"> <div class="latest-text">
<ul> <ul>
% for l in latest: % for l in latest:
<li>&#9;<a href={{l[0]}} rel="nofollow">{{!l[1]}}</a></li> <li>&#9;<a href=/{{l[0]}} rel="nofollow">{{!l[1]}}</a></li>
% end % end
</ul> </ul>
<br> <br>
</div> </div>
</div> </div>
<div class="disclosure"> <div class="disclosure">
<h1>disclosure</h1> <h1>disclosure</h1>
blessfrey.me is not using sponsored posts or affiliate links right now. blessfrey.me is not using sponsored posts or affiliate links. <br>
<br>
blessfrey.me does not collect personal information + has no cookies.<br>
<br> <br>
If this changes, sponsored content will be <a href="https://www.ftc.gov/tips-advice/business-center/guidance/ftcs-endorsement-guides-what-people-are-asking" rel="nofollow">properly</a> <a href="https://www.ftc.gov/sites/default/files/attachments/press-releases/ftc-publishes-final-guides-governing-endorsements-testimonials/091005revisedendorsementguides.pdf" rel="nofollow">disclosed</a>, cookies and analytics will comply with the GDPR and CCPA, etc.<br> blessfrey.me does not collect personal information + has no cookies. <br>
<br> <br>
Thank you for following the development of blessfrey.<br> Thank you for following the development of blessfrey. <br>
</div> </div>
</div> </div>

@ -1,5 +1,5 @@
% rebase('frame.tpl') % rebase('frame.tpl')
% import re
<div class="dir-row"> </div> <div class="dir-row"> </div>
<div class="diary-dir"> <div class="diary-dir">
<center> <center>
@ -76,11 +76,14 @@
</div> </div>
<div class="snippet-info"> <div class="snippet-info">
<b>{{!s[2]}} <b>{{!s[2]}}
• <a class="social-link social-twitter" href="http://twitter.com/share?text={{!s[4]}}&url=https://blessfrey.me{{!s[3]}}&via=lilchimchooree" target="_blank">tweet</a> • <a class="social-link social-twitter" href='http://twitter.com/share?text={{s[4]}}&url=https://blessfrey.me{{s[3]}}&via=lilchimchooree' target="_blank">tweet</a>
• <a class="social-link social-fb" href='http://www.facebook.com/share.php?u={{s[3]}}'>facebook</a> • <a class="social-link social-fb" href='http://www.facebook.com/share.php?u={{s[3]}}'>facebook</a>
• <a class="social-link social-email" href="mailto:?body=Hey,+check+out+this+post:+{{!s[1]}}., {{s[3]}}">email</a></b> % 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)
• <a class="social-link social-email" href='mailto:?body={{message}}'>email</a></b>
</div> </div>
<div class="snippet-link"> <div class="snippet-link">
<a href={{s[3]}} rel="nofollow"><b>read more</b></a> <a href={{s[3]}} rel="nofollow"><b>read more</b></a>

@ -9,30 +9,17 @@
% include diary-boxes.tpl % include diary-boxes.tpl
<div class="recommend"> <div class="recommend">
% if len(recommends) > 0:
<div class="more"><h1>more like this...</h1></div> <div class="more"><h1>more like this...</h1></div>
<div class="snip1"> % end
<div class="snippet-title"> <div class="rec-box">
<a href={{recommends[0][2]}} rel="nofollow"><b>{{!recommends[0][0]}}</b></a> % for s in recommends:
</div> <div class="snip">
<div class="snippet-content"> <div class="snippet-title">
{{!recommends[0][1]}} <a href=/{{s[1]}} rel="nofollow"><b>{{!s[0]}}</b></a>
</div> </div>
</div>
<div class="snip2">
<div class="snippet-title">
<a href={{recommends[1][2]}} rel="nofollow"><b>{{!recommends[1][0]}}</b></a>
</div>
<div class="snippet-content">
{{!recommends[1][1]}}
</div>
</div>
<div class="snip3">
<div class="snippet-title">
<a href={{recommends[2][2]}} rel="nofollow"><b>{{!recommends[2][0]}}</b></a>
</div>
<div class="snippet-content">
{{!recommends[2][1]}}
</div> </div>
% end
</div> </div>
</div> </div>

@ -7,42 +7,60 @@
<div class="textbox story"> <div class="textbox story">
<h1>Story</h1><br> <h1>Story</h1><br>
<br> <br>
You play as a transfer student to a Deep South town. <br> The main character suddenly transfers to a rural foreign town at the end of the year.<br>
Her uncle is nowhere to be found, so she's left to her own devices for the summer.<br>
<br> <br>
There's a popular rumor that the local shopping center closes early because it's haunted, evidenced by strange noises and lights. <br>
<br> <br>
Your classmates haze you into spending the night, and you discover that the mall fills with slimes at night, and they bubble up from secret tunnels underneath the stores. <br> Her classmates let her in on the rumor that the local shopping center is haunted at night, with strange lights and noises. <br>
</div> On a dare haunted sleepover, she discovers that the mall fills with slimes at night, bubbling up from secret tunnels underneath the stores. <br>
<div class="textbox system">
<h1>System</h1><br>
<br>
You and your controllable AI companions each have two classes and 8-skill skillbar to manage to take on the various combat and puzzle challenges in the Abyss.<br>
<br>
<h2>Team</h2><br>
<br>
Throughout the game, you will control between zero and five AI companions, whose Second Classes and Skillbars you will be able to customize.<br>
<br>
<h2>Multiclassing</h2><br>
<br>
Blessfrey has a multiclassing system to give the player freedom to express his playstyle. You choose your First Class at the beginning of the game and can unlock Second Classes through gameplay. The First Class is permanent and grants an exclusive bonus effect, such as higher Health or increased item efficacy, and a set of skills. The Second Class can be changed in safe areas to gain access to more skills. For example, a Heavy / Disciple will have plenty of tanking and healing options, while a Heavy / Chemist will have more focus on tanking and debuffing.<br>
<br> <br>
<h2>Skills</h2><br>
<br> <br>
Skills are individual powers gained through gameplay which give specific effects according to their rules, which can be read in the player's Skill Library. Skills generally have a cost (usually Energy), an Activation Time (the time from pressing the skill to applying it), a Cooldown Time (time until skill can be used again), and a target. Skills may have an Initial Effect (effect immediately applied at activation), a main Effect (the effect applied after activation), and an End Effect (an effect applied after a specified time after activation).<br> But there's more than slimes beneath the city. There's a whole secret world down there. <br>
<br> <br>
The skillbar only has 8 slots and can only be edited in safe areas, so you must build strategies + synergies against the areas you plan to explore. All skills must come from your current First or Second Class, duplicate skills are removed, and only one Elite Skill, an especially strong skill, is allowed per bar.<br> </div>
<br> <div class="textbox system">
Stat Points can be pumped into the classes' stats to increase the effectiveness of the skills associated with the given stat. <br> <h1>System</h1><br>
<br> <br>
The only permanent decision is the First Class. Stat Points can be redistributed and skills are never unlearned or replaced. The player is free to explore hundreds of combinations, including builds tailored for a specific level, general builds that can work in any area, or joke builds.<br> In this build-based RPG, you explore the depths of the downtown dungeon with your customizable AI teammates.<br>
<br> <br>
<h2>Explore</h2><br> <h2>Socialize</h2><br>
During the adventure, your conversations with characters that will affect how they view you.<br>
<br>
In conversations, you select dialogue choices that will affect your relationship with characters and influence future events. <br>
<br>
CG illustrations will highlight particular moments in the story.<br>
<br><br>
<h2>Learn</h2><br>
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. <br>
<br> <br>
You gain new skills and unlock more detailed UI information through exploring the world. Meeting new people, reaching new areas, fighting masses of the same enemy type, consuming items, and more all contribute to the player's knowledge base.<br> Each skill has different routes for unlocking, so they will be available regardless of playstyle. <br>
<br> <br>
The Main Character applies her experiences to her combat, unlocking new skills. For instance, suffering from Burning, visiting lava pools, and eating flambé foods all contribute to the Fire track and will unlock skills related to fire resistance, fire projectiles, and so on.<br> Your experiences will also unlock more detailed UI information.<br>
<br> <br>
The Main Character will also be able to apply her experience to the player's UI. As you face more encounters with particular enemies, the UI will display more specific information about them. Over the course of the game, "rainbow sludge monster" will become "Road Oil," non-specific Health bars will become numeric, and "using poison projectile" will become "using Toxic Dart."<br> <br>
<h2>Build</h2><br>
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. <br>
<br>
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.<br>
<br>
Pump your stat points into stats to increase the effectiveness of their associated skills. Gain stat points through story progression and level ups. <br>
<br>
Your second class, stat points, and skillbar can be freely changed in safe areas and are never unlearned or replaced.<br>
<br>
<br>
<h2>Battle</h2><br>
In this action rpg, you and your teammares will battle foes using default weapon attacks and skills from your skillbars. <br>
<br>
Weapons have different attack rates, ranges, and possible damage.<br>
<br>
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. <br>
<br>
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.<br>
<br><br>
</div> </div>
<div class="textbox graphics"> <div class="textbox graphics">
<h1>Graphics</h1> <h1>Graphics</h1>

@ -1,16 +1,14 @@
% rebase('frame.tpl') % rebase('frame.tpl')
% import random % import random
<div class="social"> <div class="social"> </div>
<a href="https://twitter.com/lilchimchooree"><img class="img-social-ribbon" src="static/img/ele/twitter-ribbon.png" alt="link to developer's Twitter" rel="nofollow"></a>
</div>
<div class="bg"> </div> <div class="bg"> </div>
<div class="footer-row"> </div> <div class="footer-row"> </div>
<div class="tweets"> <div class="tweets">
<a class="twitter-timeline" data-width="400" data-height="200" data-theme="dark" rel="nofollow" href="https://twitter.com/lilchimchooree?ref_src=twsrc%5Etfw">Tweets by lilchimchooree</a> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> <a class="twitter-timeline" data-width="400" data-height="200" data-theme="dark" href="https://twitter.com/lilchimchooree" data-chrome="noheader nofooter transparent noborders">Tweets by lilchimchooree</a> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div> </div>
<div class="news"> <div class="news">
<center>. •        . <strong>news</strong> ☆      .. . <br></center> <center>. •        . <strong>news</strong> ☆      .. . <br></center>

@ -1,5 +1,5 @@
<div class="whitespace"> </div> <div class="whitespace"> </div>
<div class="blessfrey-logo"> <div class="blessfrey-logo">
<center>blessfrey.me</center><br> <center><b>blessfrey.me</b></center><br>
</div> </div>

@ -3,23 +3,35 @@
<div class="nav-grid"> <div class="nav-grid">
<div class="nav-bar"></div> <div class="nav-bar"></div>
<div class="nav-index"> <div class="nav-index">
<a href="/" rel="nofollow"> <a href="/">
<div class="button">home</div> <img src="/static/img/btn/skillbtn.png" alt="home" style="width:85px;height:55px;">
</a> </a>
<div class="nav-link">
<a href="/">home</a>
</div>
</div> </div>
<div class="nav-game"> <div class="nav-game">
<a href="/game" rel="nofollow"> <a href="/game">
<div class="button">game</div> <img src="/static/img/btn/skillbtn.png" alt="game" style="width:85px;height:55px;">
</a> </a>
<div class="nav-link">
<a href="/game">game</a>
</div>
</div> </div>
<div class="nav-diary"> <div class="nav-diary">
<a href="/diary" rel="nofollow"> <a href="/diary">
<div class="button">diary</div> <img src="/static/img/btn/skillbtn.png" alt="diary" style="width:85px;height:55px;">
</a> </a>
<div class="nav-link">
<a href="/diary">diary</a>
</div>
</div> </div>
<div class="nav-presskit"> <div class="nav-presskit">
<a href="/presskit" rel="nofollow"> <a href="/presskit">
<div class="button">presskit</div> <img src="/static/img/btn/skillbtn.png" alt="presskit" style="width:85px;height:55px;">
</a> </a>
<div class="nav-link">
<a href="/presskit">presskit</a>
</div>
</div> </div>
</div> </div>

@ -5,7 +5,7 @@
<div class="textbox fact"> <div class="textbox fact">
<h1>Fact Sheet</h1> <h1>Fact Sheet</h1>
<ul> <ul>
<li><b>Description:</b> Build synergies across your skillbar and teammates to survive the local smalltown dungeon.</li> <li><b>Description:</b> Build synergies across your skillbar and teammates to survive the downtown dungeon.</li>
<li><b>Developer:</b> chimchooree, US indie dev</li> <li><b>Developer:</b> chimchooree, US indie dev</li>
<li><b>Genre:</b> Singleplayer Action RPG</li> <li><b>Genre:</b> Singleplayer Action RPG</li>
<li><b>Release Date:</b> Spring 2030</li> <li><b>Release Date:</b> Spring 2030</li>
@ -21,9 +21,9 @@
<div class="textbox desc"> <div class="textbox desc">
<h1>Description</h1> <h1>Description</h1>
<br> <br>
In active development, Blessfrey is the first game by US-based indie game developer chimchooree. <br> Blessfrey is the first game in development by US-based indie game developer chimchooree. <br>
<br> <br>
Blessfrey is a 2D action RPG set in a rural southern town riddled with secret tunnels and dungeons. 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. Bosses, traps, and a secret world await. <br> 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. Bosses, traps, and a secret world await. <br>
<br> <br>
@ -43,12 +43,12 @@ The multiclass and skill system emphasizes player skill, personal expression, an
<div class="textbox dev"> <div class="textbox dev">
<h1>Developer </h1> <h1>Developer </h1>
<br> <br>
chimchooree is learning to code through gamedev, automating the boring stuff, and taking online classes. See some of her code on <a href="https://gitlab.com/chimchooree">GitLab</a> and some of her design process + planning on her <a href="diary.php">blog</a> and on <a href="https://twitter.com/lilchimchooree">Twitter</a>. <br> chimchooree is learning to code through making a dream game, automating the boring stuff, and taking online classes. See some of her code on <a href="https://gitlab.com/chimchooree">GitLab</a> and some of her design process + planning on her <a href="diary.php">blog</a> and on <a href="https://twitter.com/lilchimchooree">Twitter</a>. <br>
<br> <br>
Her most complex projects are blessfrey, a 2D action RPG written in Godot Engine's GDScript and Cat Store, a text-based breeding sim written in Java using IntelliJ. <br> Her most complex projects are blessfrey, a 2D action RPG written in Godot Engine's GDScript and Cat Store, a text-based breeding sim written in Java using IntelliJ. <br>
</div> </div>
<div class="textbox videos"> </div> <!--<div class="textbox videos"> </div>-->
<div class="textbox graphics"> <div class="textbox graphics">
<h1>Graphics</h1> <h1>Graphics</h1>
@ -82,7 +82,7 @@ The multiclass and skill system emphasizes player skill, personal expression, an
<li>Art: chimchooree</li> <li>Art: chimchooree</li>
<li>Design: chimchooree</li> <li>Design: chimchooree</li>
<li>Engine: Godot Engine</li> <li>Engine: Godot Engine</li>
<li><a href="/credits/" rel="nofollow">Full Credits</a></li> <li><a href="/credits" rel="nofollow">Full Credits</a></li>
</ul><br> </ul><br>
</div> </div>

Loading…
Cancel
Save