up to date with server
@ -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,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>
|
<br>
|
||||||
Work on it later.<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>
|
||||||
|
@ -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 <ul> 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 <ul> 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 <ul> 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,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
|
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 817 B |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 144 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 73 KiB |
After Width: | Height: | Size: 141 KiB |
After Width: | Height: | Size: 486 KiB |
@ -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>
|
@ -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>
|
||||||
|