ozkriff's devlog https%3A//ozkriff.games Zola en Sat, 21 Sep 2019 00:00:00 +0000 Zemeroth v0.6: Renown, Upgrades, Sprite Frames & Flips, Effect Icons, and Videos Sat, 21 Sep 2019 00:00:00 +0000 https%3A//ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/ https%3A//ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/ <!-- markdownlint-disable MD013 --> <!-- cspell:ignore reddit playtests indiedb tigsource nerfed Grammarly youtube --> <!-- cspell:ignore indistinctly zscene KDEnlive ezgif Kubuntu Knockback --> <p>Hi, folks! I'm happy to announce <strong>Zemeroth v0.6</strong>. Main features of this release are: renown and fighter upgrades, possessions, sprite frames and flips, and status effect icons.</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/title-screenshot.png" alt="Title image showing new fighter types, icons, explosions, etc" /></p> <p><a href="https://github.com/ozkriff/zemeroth">Zemeroth</a> is my hobby turn-based hexagonal tactics game written in <a href="https://rust-lang.org">Rust</a>. You can <a href="https://github.com/ozkriff/zemeroth/releases/tag/v0.6.0">download precompiled v0.6 binaries</a> for Windows, Linux, and macOS or <strong><a href="https://ozkriff.itch.io/zemeroth">play the online version on itch.io</a></strong> (should work on mobile browsers too).</p> <hr /> <p>After 0.5 release, I've experimented a little bit with <a href="https://users.rust-lang.org/t/zemeroth-a-2d-turn-based-strategy-game/28311/5">smaller forum updates</a> and <a href="https://youtu.be/EDoxb7vbqgg">short complimentary videos</a>, but I've expectedly failed to make them regularly. Actually, I only managed to publish one such update: drafts for second and third updates were never finished. So, I decided to cancel my attempts at making weeklies and squashed all the &quot;weekly&quot; text drafts together into this larger announcement post.</p> <p>Video drafts were also squashed into <strong><a href="https://www.youtube.com/watch?v=6tZByt4LBlU">a video version of this post</a></strong>, check it out:</p> <p><a href="https://www.youtube.com/watch?v=6tZByt4LBlU"><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/youtube-devlog-screenshot.png" alt="YouTube vide preview" /></a></p> <p>So, what does this release add to the game?</p> <h2 id="renown-and-fighter-upgrades">Renown and Fighter Upgrades</h2> <p>The biggest additions of this release are the renown system and fighter upgrades.</p> <p>&quot;Renown&quot; is the currency of the campaign mode that the player receives by winning battles and spends on recruiting and upgrading their fighters between battles. The term is obviously borrowed from <a href="https://bannersaga.gamepedia.com/Renown">Banner Saga</a>.</p> <p>Updated campaign menu looks like this:</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/campaign-menu.png" alt="a screenshot of campaign menu" /></p> <p>Now it shows not only the last battle casualties and their current fighters but also their current renown and a list of possible actions with their costs (in renown).</p> <p>The player is now free to choose more then one action if they have enough renown.</p> <p>One upgrade option is chosen randomly for up to two upgradable fighters in the player's group.</p> <p>If the player doesn't like provided upgrade options, they can skip straight to the next battle (that will be a little bit harder) and use their renown later.</p> <p>Recruit candidates (and the amount of received renown after a battle) are still encoded in the <code>award</code> section of campaign's nodes (this is likely to become a little bit more random too in future versions). A sample from <a href="https://github.com/ozkriff/zemeroth_assets/blob/e3886c064/campaign_01.ron">assets/campaign_0.ron</a>:</p> <pre style="background-color:#2b303b;"> <span style="color:#c0c5ce;">initial_agents: [&quot;swordsman&quot;, &quot;spearman&quot;], nodes: [ // . . . ( scenario: ( objects: [ (owner: None, typename: &quot;boulder&quot;, line: None, count: 1), (owner: Some((1)), typename: &quot;imp&quot;, line: Some(Front), count: 3), (owner: Some((1)), typename: &quot;imp_bomber&quot;, line: Some(Middle), count: 2), ], ), award: ( recruits: [&quot;spearman&quot;, &quot;alchemist&quot;], renown: 18, ), ), // . . . </span></pre> <p>(<em>Note to myself: Employ an &quot;<a href="https://github.com/ron-rs/ron/blob/master/docs/extensions.md#implicit_some">implicit_some</a>&quot; RON extension.</em>)</p> <p>Fighter costs and upgrade options are described in a <a href="https://github.com/ozkriff/zemeroth_assets/blob/e3886c064/agent_campaign_info.ron">assets/agent_campaign_info.ron</a> config, that looks like this:</p> <pre style="background-color:#2b303b;"> <span style="color:#c0c5ce;">{ &quot;swordsman&quot;: ( cost: 10, upgrades: [&quot;heavy_swordsman&quot;, &quot;elite_swordsman&quot;], ), &quot;elite_swordsman&quot;: (cost: 15), &quot;heavy_swordsman&quot;: (cost: 14), &quot;spearman&quot;: ( cost: 11, upgrades: [&quot;heavy_spearman&quot;, &quot;elite_spearman&quot;], ), &quot;elite_spearman&quot;: (cost: 15), // . . . </span></pre> <p>Recruitment cost consists of a basic type cost plus a group size penalty (the player's fighters count). The penalty is added because the intended size of the group is four to six fighters.</p> <p>The upgrade cost is just a difference between original and upgraded type costs.</p> <p>Now the campaign has some level of strategy: the player should think if it's better to recruit a new fighter or upgrade the existing ones. The player should never have enough renown to buy everything they want.</p> <hr /> <p>As for the new fighter types, most of the current upgrades can be split into two &quot;kinds&quot;:</p> <ul> <li> <p>&quot;Elite&quot; fighters are generally faster, have more abilities and can use them more often. They feel overpowered at this iteration and most likely will be nerfed in next releases.</p> </li> <li> <p>&quot;Heavy&quot; fighters are the opposite: they move slower (two move points instead of three), have fewer attack points, but deal more damage and have more health points.</p> <p>Later I will convert some of their extended health points into armor points, but this doesn't work atm, because there're no enemies, except for Imp Summoners, that can do anything with an armored fighter.</p> </li> </ul> <p>Basic fighter types were nerfed: fewer strength points, accuracy, abilities, etc, but are still useful.</p> <p>The idea is that the player should have fighters from all three kinds in their group: slow heavies are supposed to be used as devastating &quot;iron fist&quot;, quick and agile elites are used for vanguard and flanks, and basic fighters are used to fight weak enemies or finish off wounded ones.</p> <p>Here are current &quot;upgrade trees&quot; (they have only one level for now, but I'm planning to add more nodes in future versions):</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/upgrade-trees.png" alt="upgrade trees" /></p> <ul> <li><strong>spearman</strong> - still has 3 health points, &quot;Jump&quot; ability, and two-tile attack range, but lost one reaction attack, one accuracy, and one dodge point. Only useful for defense. <ul> <li><strong>elite spearman</strong> - has 4 health, one more accuracy and dodge points, and, most importantly, has an additional attack. The latter allows using him as the first fighter in a series of attacks, because he can move closer to enemies and instantly attack one of them from a safe distance, giving the initiative to the player.</li> <li><strong>heavy spearman</strong> - moves slowly, can't jump at all but has 5 health and deals 2 damage (that's a lot, considering his two-tile attack range). Still only useful for defense, but is very effective.</li> </ul> </li> <li><strong>swordsman</strong> - has 3 health points (lost one), lost one accuracy and doesn't have &quot;Dash&quot; and &quot;Rage&quot; abilities anymore (only &quot;Jump&quot;). <ul> <li><strong>elite swordsman</strong> - has the stats of an old swordsman: 4 health, more accurate and all three abilities: &quot;Jump&quot;, &quot;Dash&quot;, and &quot;Rage&quot;.</li> <li><strong>heavy swordsman</strong> - slow and has no abilities at all but has 6 health, increased accuracy and greater attack damage (3).</li> </ul> </li> <li><strong>hammerman</strong> - has 4 health points and low accuracy. Lost &quot;Heavy Strike&quot; passive ability, but still have &quot;Club&quot; and &quot;Knockback&quot; abilities. <ul> <li><strong>heavy hammerman</strong> - slow, lost one attack point, but deals up to 5 damage, breaks up to 3 armor, has 6 health, a &quot;Heavy Strike&quot; passive ability and both &quot;Club&quot; and &quot;Knockback&quot; abilities. Can slay even a fully fresh imp summoner in a few strikes.</li> </ul> </li> <li><strong>alchemist</strong> - is a special type, because he can't attack directly. He lost all bombs except for the Push Bomb. Also, the cooldown of the &quot;Heal&quot; ability was increased. <ul> <li><strong>healer</strong> - heals more points with a 2 turns cooldown and can throw only Poison Bomb. Also, can do double moves in one turn for cases when the wounded fighter is on the other side of the map.</li> <li><strong>firer</strong> - can't heal anyone, but can do mass destruction by throwing exploding and fire bombs.</li> </ul> </li> </ul> <p>(<em>See <a href="https://github.com/ozkriff/zemeroth_assets/blob/master/objects.ron">objects.ron</a> for exact details.</em>)</p> <p>As you can see, sometimes the upgraded versions lose some of their abilities. These upgrades are more like a specialization, not just an improvement: the fighter focuses on a smaller set of skills.</p> <p>I also try to make fighter's stats match their visuals so the situation described in this <a href="https://itch.io/post/660275">itch.io review</a> won't repeat:</p> <blockquote> <p>... the most mobile unit in the game is the only one wearing heavy armor. Perhaps it'd be more fitting for the Hammerman to be in plate.</p> </blockquote> <h2 id="agent-s-info-screen">Agent's Info Screen</h2> <p>A basic fighter info screen was added:</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/agent-info-screen.png" alt="agent info screen" /></p> <p>It's opened by clicking on a small <code>[i]</code> button on the right from a fighter's type in the campaign menu:</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/agent-info-button.png" alt="&quot;i&quot; button in the campaign menu" /></p> <p>This screen allows the player to look up stats and abilities before recruiting or upgrading a fighter.</p> <h2 id="possession">Possession</h2> <p>Another gameplay change is possessions: imp summoners can now possess imps to give them more action points for a few turns.</p> <p>The &quot;Possessed&quot; status is visualized with a yellow lightning status icon (read more about the status icons in the &quot;Status Effect Icons&quot; section below).</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/possession-demo-1.gif" alt="Possession demo 1: spearman is killed by a possessed imp" /></p> <p>On the beginning of their turn, possessed imp gets three additional Joker points (reminder: Jokers can be used as attack or move points and aren't removed when the agent receives damage).</p> <p>Possessed imps can run through the whole map, make a lot of attacks, and they won't stop on your reaction attacks until they're dead. So the player must look closely for potentially possessed imps and be ready to reposition fighters to form a lethal defense line:</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/possession-demo-2.gif" alt="Possession demo 1: possessed imp is killed with reaction attacks" /></p> <p>The idea is that the player should never be in a situation like when two possessed imps run towards a lonely and badly positioned fighter.</p> <p><em>Note</em>: &quot;Possession&quot; looks like to be a bad name for one demon forcing a lesser demon to be more performing, so this ability and effect will likely be renamed in future versions.</p> <h2 id="visual-improvements">Visual Improvements</h2> <p>There're many small visual improvements in this release.</p> <h3 id="current-tile-highlighting">Current Tile Highlighting</h3> <p>First, a tile under the cursor is highlighted now when using a mouse (it was requested by many playtesters). It makes no sense do this with touch inputs because the user will just constantly see the latest tile they touched, so the feature only works when input event's delta movement isn't zero.</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/tile-highlighting.gif" alt="demo of the tile highlighting" /></p> <p>^ <em>Switching between mouse input and touch emulation in the web version</em></p> <h3 id="sprites-flipping">Sprites Flipping</h3> <p>Next, agent sprites <a href="https://github.com/ozkriff/zemeroth/pull/473">are now flipped horizontally</a> to match their action's direction. Weapon flashes are also now flipped when needed.</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/scene-with-flipped-agents.png" alt="scene with flipped agents" /></p> <p>^ <em>A screenshot with both imps and humans faced left and right</em></p> <p>I've wanted to add this for a long time because previously humans were facing strictly to the right (imps - to the left) and sometimes they were attacking each other backward.</p> <p>To implement this <code>enum Facing { Left, Right }</code>, a <code>Sprite::set_facing</code> method, and a corresponding <code>action::SetFacing</code> scene action <a href="https://github.com/ozkriff/zemeroth/pull/473">were added</a> to the <code>zscene</code> library.</p> <p>The implementation of <code>Sprite:set_facing</code> is a little hacky atm. I was hoping to implement this method using only ggez's <a href="https://docs.rs/ggez/0.5.1/ggez/graphics/struct.DrawParam.html">ggez::DrawParams</a>' <code>scale</code> and <code>offset</code> fields, but because of <a href="https://github.com/ggez/ggez/issues/439">this bug</a>, it doesn't really work with custom screen coordinates that I'm using. So the method was implemented on <code>zscene::Sprite</code>'s abstraction level using external offset.</p> <h3 id="dodge-animations">Dodge Animations</h3> <p>It's hard to actually miss while attacking a static target with a melee weapon in real life. Most of the misses are caused by the targets dodging moves. So, simple target dodge animations when an attack misses <a href="https://github.com/ozkriff/zemeroth/pull/471">were added to the game</a> to display this.</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/dodge-demo.gif" alt="Dodge animation demo" /></p> <p>^ <em>Dodge animations demo</em></p> <h3 id="move-interruption-message">Move Interruption Message</h3> <p>If any tile of a movement path is inside the attack range of an enemy agent with attack points, a reaction attack is triggered. If this attack succeeds the movement is interrupted.</p> <p>A move point (or a joker) is spent even if the agent hasn't actually moved anywhere: the starting tile is also considered a part of the path. This prevents agents from exiting a melee too easily (&quot;Jump&quot; and &quot;Dash&quot; abilities exist to counter this).</p> <p>I like this mechanic, but sometimes it wasn't clear to playtesters what just happened: they clicked on a tile, but were attacked and can't move anymore.</p> <p>A helper message is <a href="https://github.com/ozkriff/zemeroth/pull/472">now shown</a> when an agent's move is interrupted.</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/move-interrupted-msg-demo.gif" alt="Demo of the movement interruption message" /></p> <p>^ <em>A demo of a heavy swordsman's failed attempt to move away from an imp</em></p> <h3 id="frames">Frames</h3> <p>From the beginning of the project I decided that I don't want to implement real smooth animations for agents: I don't like how 2D skeletal animations look in general and per frame animations are too hard to make. Quoting from <a href="https://ozkriff.github.io/2017-08-17--devlog/index.html#zemeroth">the initial vision</a>:</p> <blockquote> <p>* Simple vector 2d graphics with just 3-5 sprites per unit;</p> </blockquote> <p>So the plan was to have a few situational sprites (&quot;attacking&quot;, &quot;taking damage&quot;, etc) per unit and use simple procedural animation to make the image more alive. It's a compromise between having real animations and only having totally static pieces.</p> <p>Some procedural animations (like <a href="https://ozkriff.games/2018-03-03--devlog/index.html#simple-walking-animation">&quot;bumpy&quot; walk</a> or <a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/index.html#visual-improvements">blood splatters and dust</a>) were implemented in previous versions of the game, but all agents still used only one sprite.</p> <p>With this release, agents finally <a href="https://github.com/ozkriff/zemeroth/pull/476">get special sprite frames for (some) abilities</a>!</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/frames-demo.gif" alt="frames demo" /></p> <p>^ <em>A demo of special ability frames (&quot;Rage&quot;, &quot;Heal&quot;, and &quot;Summon&quot;)</em></p> <p>For now, special frames are used only for the visualization of abilities. I've tried adding &quot;attack frames&quot;, but they conflicted too much with weapon flashes and I decided that the game looks better without these frames.</p> <p>Though, it's likely that spearman will get special directional attack frames <a href="https://github.com/ozkriff/zemeroth/issues/477">in the next versions</a> because he can attack enemies two tiles away from him and it looks weird with a completely static sprite sometimes because the spear is too far away from its target.</p> <hr /> <p>Sprite sets are configured now with a <a href="https://github.com/ozkriff/zemeroth_assets/blob/56b620664/sprites.ron">sprites.ron</a> config that looks like this:</p> <pre style="background-color:#2b303b;"> <span style="color:#c0c5ce;">{ // ... &quot;alchemist&quot;: ( paths: { &quot;&quot;: &quot;/alchemist.png&quot;, &quot;throw&quot;: &quot;/alchemist_throw.png&quot;, &quot;heal&quot;: &quot;/alchemist_heal.png&quot;, }, offset_x: 0.05, offset_y: 0.1, shadow_size_coefficient: 1.0, ), &quot;imp_summoner&quot;: ( paths: { &quot;&quot;: &quot;/imp_summoner.png&quot;, &quot;summon&quot;: &quot;/imp_summoner_summon.png&quot;, }, offset_x: 0.0, offset_y: 0.15, shadow_size_coefficient: 1.3, ), // ... } </span></pre> <p>The <code>&quot;&quot;</code> (empty string) frame is considered the default frame.</p> <p>As the event visualizers don't know anything about specific agent types, the code usually checks if the sprite has some event-specific frame and only then adds an action node that will switch the sprite to that frame during its execution:</p> <pre style="background-color:#2b303b;"> <span style="color:#b48ead;">let</span><span style="color:#c0c5ce;"> frame = &quot;</span><span style="color:#a3be8c;">jump</span><span style="color:#c0c5ce;">&quot;; </span><span style="color:#b48ead;">if</span><span style="color:#c0c5ce;"> sprite_object.</span><span style="color:#96b5b4;">has_frame</span><span style="color:#c0c5ce;">(frame) { actions.</span><span style="color:#96b5b4;">push</span><span style="color:#c0c5ce;">(action::SetFrame::new(&amp;sprite_object, frame).</span><span style="color:#96b5b4;">boxed</span><span style="color:#c0c5ce;">()); } </span></pre> <p>Frames are stored inside the <code>zscene::Sprite</code> struct like this:</p> <pre style="background-color:#2b303b;"> <span style="color:#c0c5ce;">drawable: Option&lt;Box&lt;dyn Drawable&gt;&gt;, drawables: HashMap&lt;String, Option&lt;Box&lt;dyn Drawable&gt;&gt;&gt;, current_frame_name: String, </span></pre> <p>I didn't want to index a HashMap with a string for every sprite on every frame, so the current frame lives in a special field <code>drawable</code> and everything is stored as options to simplify frame swapping.</p> <h3 id="explosion-ground-marks">Explosion Ground Marks</h3> <p>To make the battlefield look more interesting decorative explosion ground marks were added:</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/explosion-ground-mark-demo.gif" alt="explosion ground marks demo" /></p> <p>Same as blood, they're slowly disappearing into transparency in three turns to avoid making the battlefield too noisy and unreadable.</p> <p>It looks boring when there're many similar big explosion mark sprites on the battlefield, so in future versions there should be something like 3-5 randomly chosen versions of this sprite (<a href="https://github.com/ozkriff/zemeroth/issues/531">#531</a>).</p> <h3 id="status-effect-icons">Status Effect Icons</h3> <p>Icons for lasting effects were <a href="https://github.com/ozkriff/zemeroth/pull/511">added</a> so the player can quickly see a more detailed game state info:</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/status-effect-icons.png" alt="status effect icons demo" /></p> <p>There're three lasting effects atm:</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/status-effect-icons-images.png" alt="image files" /></p> <p>If there's more than one lasting effect applied to one agent, icons are stacked vertically:</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/status-effect-icons-stacked.png" alt="stacked icons demo" /></p> <p>The icons are twice the size of brief info dots because they're more detailed.</p> <h2 id="external-contributions">External Contributions</h2> <p>There were a few PRs from external contributors:</p> <ul> <li>by <a href="github.com/debris">@debris</a>: <ul> <li><a href="https://github.com/ozkriff/zemeroth/pull/485">&quot;Bump ggez to version 0.5.0-rc.2&quot;</a>;</li> <li><a href="https://github.com/ozkriff/zemeroth/pull/490">&quot;Highlight buttons on mouse over&quot;</a>;</li> <li><a href="https://github.com/ozkriff/zemeroth/pull/486">&quot;Load sprites from sprites.ron file&quot;</a>;</li> </ul> </li> <li>by <a href="github.com/ltfschoen">@ltfschoen</a>: <ul> <li><a href="https://github.com/ozkriff/zemeroth/pull/491">&quot;docs: Fix logic of insert within zcomponents&quot;</a>;</li> <li><a href="https://github.com/ozkriff/zemeroth/pull/488">&quot;Update readme with instructions to add missing dependencies&quot;</a>.</li> </ul> </li> </ul> <p>Thanks, folks!</p> <h2 id="other-changes">Other Changes</h2> <ul> <li>AIs of the Summoner and Bomber imps <a href="https://github.com/ozkriff/zemeroth/pull/508">were tweaked</a> to keep shorter distances because chasing summoners through the whole map with slow heavy fighters is just boring.</li> <li>The &quot;Explosion Bomb&quot; ability was balanced: explosions <a href="https://github.com/ozkriff/zemeroth/pull/505">now destroy armor</a>. This was done to balance this ability with a &quot;Fire Bomb&quot;.</li> <li>The &quot;Club&quot; ability <a href="https://github.com/ozkriff/zemeroth/pull/514">was balanced</a>: its duration was educed and the &quot;Fly Off&quot; effect was removed. This was done to better differentiate it with the &quot;Knockback&quot; ability.</li> <li>A mostly empty rustfmt.toml file <a href="https://github.com/ozkriff/zemeroth/pull/495">was added</a> to the repo (<a href="https://github.com/ozkriff/zemeroth/issues/492">to explicitly document the desired formatting</a>).</li> <li>I added <a href="https://github.com/ozkriff/zemeroth/blob/8586ef2ac/README.md#inspiration">a new &quot;Inspiration&quot; section</a> to the README with a list of games that inspire(d) Zemeroth.</li> </ul> <h2 id="text-logo">Text Logo</h2> <p>The game now has a (temporary?) text logo:</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/text-logo.png" alt="Text logo" /></p> <p>The image was manually re-drawn (in a low-poly style similar to game's angular sprites) from a text written in the <a href="https://www.dafont.com/old-london.font">&quot;Old London&quot;</a> font.</p> <p>Not sure if it really fits the game - surprisingly many people say that it looks like something related to Death Metal and not just a generic medieval font - but it'll do for now.</p> <h2 id="spreading-the-word">Spreading the Word</h2> <p>I've got the <a href="https://ozkriff.games">ozkriff.games</a> domain and <a href="https://help.github.com/en/articles/using-a-custom-domain-with-github-pages">moved my devlog to it</a>. This is my first domain and the buying process turned out to be not nearly as scary as I was expecting.</p> <p>I revived my Patreon page: <a href="https://patreon.com/ozkriff">patreon.com/ozkriff</a>.</p> <p>I also created new social pages (in addition to <a href="https://twitter.com/ozkriff">twitter</a>):</p> <ul> <li><a href="https://fb.com/ozkriff.games">fb.com/ozkriff.games</a></li> <li><a href="https://vk.com/ozkriff.games">vk.com/ozkriff.games</a> (ru)</li> </ul> <p>... and a bunch forum threads and database pages (in addition to <a href="https://ozkriff.itch.io/zemeroth">itch.io</a>):</p> <ul> <li><a href="https://forums.tigsource.com/index.php?topic=67464.0">tigsource</a></li> <li><a href="https://indiedb.com/games/zemeroth">indiedb</a></li> <li><a href="https://users.rust-lang.org/t/zemeroth-a-2d-turn-based-strategy-game/28311">users.rust-lang.org</a></li> <li><a href="https://gamejolt.com/games/zemeroth/414937">gamejolt</a></li> <li><a href="https://gamedev.ru/projects/forum/?id=244345">gamedev.ru</a> (ru)</li> </ul> <p>The initial plan was to post weekly updates to Patreon, forums, and catalog pages but as that experiment was canceled (see the preface) I most likely will just post links to new version announces there. Let's hope that this will motivate me to make smaller releases more often. :)</p> <h2 id="about-devlog-videos">About Devlog Videos</h2> <p>As written in the preface, new devlog posts will be complimented with their video versions for folks who prefer consuming information in a more dynamic audio-visual form. I don't have any experience with making of such videos (I've been only making GIFs and short gameplay videos) so I'm learning this stuff as I go along. I see it as a part of game development, so it makes sense to add a few notes about my current routine to the devlog.</p> <p>Ideally, I'd like to do record a live demo without a strict script, but speaking to the camera when you're not used to it is quite stressful and additionally I'm not quite comfortable with English. I've tried a few times to record the whole video &quot;live&quot; in one piece and it totally failed for me.</p> <p>So, I prepare a script (by adapting a text post a little bit) and read it out (usually, one section at a time). I don't have any external mic and just use a simple headset for now (as clearly can be seen from the video). I use <strong><a href="https://audacityteam.org">Audacity</a></strong> to do the recording and to <a href="https://manual.audacityteam.org/man/noise_reduction.html">filter out most noticeable background noises</a>.</p> <p>Then, I record short intro and outro clips using my phone's (its camera isn't perfect, but still much better than my laptop's webcam) to personalize the voiceover a little bit.</p> <p>GIFs from the post can't be reused for the visualization because they're too small, so I go through the script and use <strong><a href="https://en.wikipedia.org/wiki/SimpleScreenRecorder">SimpleScreenRecorder</a></strong> to record a lot of screen clips.</p> <p>I'm using Kubuntu as my main OS, so the natural choice for a video editor is <strong><a href="https://kdenlive.org">Kdenlive</a></strong>. Its UI feels a little bit clunky, but docs are fine and it seems to do all the basic stuff that I need: cut/match the video clips to the voiceover and add some background music.</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/kdenlive.png" alt="Kdenlive screenshot" /></p> <p>Finally, I prepare and add subtitles. There're at least three reasons to do this: accessibility, my terrible English pronunciation, and translation (to Russian). Again, KDE software seems to do the job fine: I just add the script to <strong><a href="https://store.kde.org/p/1126783">KDE Subtitle Composer</a></strong> line by line and tweak the timings a little bit.</p> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/subtitles-creation.png" alt="How KDE Subtitle Composer looks" /></p> <p>And that's it, the video is done and can be uploaded to <a href="https://youtube.com/user/ozkriff619/videos">YouTube</a>.</p> <p>I'm not completely happy with the quality of the 0.6 announcement video, but I guess it's only a question of practice.</p> <hr /> <p><img src="https://ozkriff.games/2019-09-21--devlog-zemeroth-v0-6/final-sequence.gif" alt="just silly final gif" /></p> <p>That's all for today, thanks for reading!</p> <p><a href="https://github.com/ozkriff/zemeroth/blob/master/README.md#roadmap">Here's Zemeroth's roadmap</a>, if you want to know on what I'm going to work next.</p> <p>If you're interested in Zemeroth project you can follow <strong><a href="https://twitter.com/ozkriff">@ozkriff on Twitter</a></strong> for fresh news or subscribe to my <strong><a href="https://youtube.com/user/ozkriff619/videos">YouTube channel</a></strong>. Also, if you're interested in Rust game development in general, you may want to check <strong><a href="https://twitter.com/rust_gamedev">@rust_gamedev on Twitter</a></strong>.</p> <p><strong>Discussions of this post</strong>: <a href="https://www.reddit.com/r/rust/comments/d7avev/zemeroth_v06_renown_upgrades_sprite_frames">/r/rust</a>, <a href="https://mobile.twitter.com/ozkriff/status/1175413716495622144">twitter</a>.</p> Zemeroth v0.5: ggez, WASM, itch.io, visuals, AI, campaign, tests Mon, 13 May 2019 00:00:00 +0000 https%3A//ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/ https%3A//ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/ <!-- markdownlint-disable MD013 --> <!-- cspell:ignore Berserker Muton kiegel Yururu ldjam devs itchio PNGs --> <p>Hi, folks! I'm happy to announce <strong>Zemeroth v0.5</strong>. Main features of this release are: migration to ggez, web version, itch.io page, campaign mode, AI improvements, visual updates, and tests.</p> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2019-04-29--title-demo.gif" alt="demo fight" /></p> <p><a href="https://github.com/ozkriff/zemeroth">Zemeroth</a> is a turn-based hexagonal tactical game written in Rust. You can <a href="https://github.com/ozkriff/zemeroth/releases/tag/v0.5.0">download precompiled v0.5 binaries</a> for Windows, Linux, and macOS. Also, now you can <strong><a href="https://ozkriff.itch.io/zemeroth">play an online version</a></strong> (<em>read more about it in the &quot;WebAssembly version&quot; section below</em>).</p> <blockquote> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2019-04-27--github-commits.png" alt="GitHub commits graph" /></p> </blockquote> <p>The last release happened about a year ago. Since then the development mostly happened in irregular bursts, sometimes it even was completely stalled for weeks. But a year is a big period of time anyway, so there're still lots of changes.</p> <p>Lots of text ahead, feel free to skip sections that you're not interested in particularly. Here's a table of contents:</p> <ul> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#migration-to-the-ggez-game-engine">Migration to the <code>ggez</code> Game Engine</a></li> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#webassembly-version">WebAssembly Version</a></li> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#itchio">itch.io</a></li> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#visual-improvements">Visual Improvements</a></li> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#campaign-mode">Campaign Mode</a></li> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#hit-chances">Hit Chances</a></li> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#armor">Armor</a></li> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#ai-updates">AI Updates</a></li> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#bombs-and-commutative-effects">Bombs and Commutative Effects</a></li> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#other-game-rules-changes">Other Game Rules Changes</a></li> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#gameplay-video">Gameplay Video</a></li> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#svg-atlas">SVG Atlas</a></li> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#assets-hash">Assets Hash</a></li> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#tests">Tests</a></li> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#other-technical-changes">Other Technical Changes</a></li> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#indikator">Indikator</a></li> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#migrated-this-devlog-to-zola">Migrated This Devlog to Zola</a></li> <li><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/#roadmap">Roadmap</a></li> </ul> <h2 id="migration-to-the-ggez-game-engine">Migration to the <code>ggez</code> Game Engine</h2> <p>An experiment with maintaining my own engine (even a simple and minimalistic 2D one) turned out to be too exhausting in practice: you have to fight a constant stream of reports about small corner case issues and deal with platform-specific tweaks and hacks (stuff <a href="https://github.com/ggez/ggez/issues/587">like this</a>, for example). It can consume surprisingly large amounts of time. But what's more important for a hobby project, it also sucks too much fun out of the development process.</p> <p>And what made it worse in my case is that <a href="https://docs.rs/hate">Häte2d</a> intentionally wasn't a general-purpose game engine (to reduce the scope of work), so it was sad to know that all this work won't be reused by anyone. But converting Häte into a real general-purpose engine wasn't an option either, because it wouldn't have left any time for Zemeroth's development.</p> <p>So I've surrendered and decided to give away some control over low-level parts of Zemeroth: <a href="https://github.com/ozkriff/zemeroth/pull/247">Häte2d was discontinued</a> and replaced by <a href="https://github.com/ggez/ggez">ggez</a>, the most mature and actively developed Rust 2d game engine at that time.</p> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/ggez-logo-maroon-full.svg" alt="ggez's logo" /></p> <p><code>häte</code> had some built-in basic <a href="https://docs.rs/hate/0.1.0/hate/scene/">scene management</a> and <a href="https://docs.rs/hate/0.1.0/hate/gui/">GUI</a> systems, but ggez is minimalistic by design and has none of this. So, two helper crates were extracted from Häte2d and rebuilt on top of ggez:</p> <ul> <li><a href="https://github.com/ozkriff/zemeroth/tree/721ad06a6/ggwp-zscene">ggwp-zscene</a> is a simple scene/declarative animation manager that provides: <ul> <li>Sprites with shared data;</li> <li>Scene and Actions to manipulate sprites;</li> <li>Simple layers;</li> </ul> </li> <li><a href="https://github.com/ozkriff/zemeroth/tree/721ad06a6/ggwp-zgui">ggwp-zgui</a> is a tiny and opinionated UI library: <ul> <li>Provides only simple labels, buttons and layouts;</li> <li>Handles only basic click event;</li> <li>No custom styles, only the basic one.</li> </ul> </li> </ul> <p>Since Icefoxen <a href="https://github.com/ggez/ggez/issues/373">asked not to use <code>ggez-</code> prefix</a>, I used <code>ggwp-</code> (&quot;good game, well played!&quot;) to denote that the crate belongs to ggez's ecosystem, but is not official.</p> <p>These helper crates are still tied to Zemeroth, not sure how helpful these libraries can be for a project that is not Zemeroth-like. But maybe someone will manage to extract some benefit from them.</p> <p>These crates are still immature and aren't published on crates.io yet, while the <code>rancor</code> component library was renamed to <code>zcomponents</code> and <a href="https://crates.io/crates/zcomponents">is published</a>.</p> <hr /> <p>Initially, I migrated to ggez v0.4 that was SDL2-based. But as soon as the first release candidate of <a href="https://github.com/rust-windowing/winit">winit</a>-based ggez v0.5 became available I attempted to migrate to it. I've filed <a href="https://github.com/ggez/ggez/issues?q=is%3Aissue+author%3Aozkriff+created%3A%3E2019-01-01">a bunch of mostly text-related issues in the process</a> and tried to fix the most critical ones for Zemeroth: <a href="https://github.com/ggez/ggez/pull/559">&quot;Remove the generic argument from Drawable::draw&quot;</a>, <a href="https://github.com/ggez/ggez/pull/567">&quot;Drawable::dimensions()&quot;</a> (big one!) and <a href="https://github.com/ggez/ggez/pull/593">&quot;Fix Text::dimensions height&quot;</a>. These PRs took some time, but then I relatively easy <a href="https://github.com/ozkriff/zemeroth/pull/426">ported Zemeroth to ggez v0.5.0-rc.0</a>.</p> <p>ggez v0.5 isn't released yet, so at the moment Zemeroth uses ggez <code>0.5.0-rc.1</code>. It's stable enough for me.</p> <hr /> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2019-05-03--na.png" alt="nalgebra logo" /></p> <p>Before the migration, I was using <a href="https://github.com/rustgd/cgmath">cgmath</a>, because it's a simple and straightforward library. But ggez's &quot;native&quot; math library is nalgebra and even though ggez v0.5 uses <code>mint</code> types for all its public API, I still migrated to nalgebra, because of <a href="https://users.rust-lang.org/t/cgmath-looking-for-new-maintainers/20406">this</a>.</p> <hr /> <p>One downside of the migration to ggez is that debug builds are much slower now because more code is pure Rust. Something like 3-5 FPS on my notebook. But it's ok, I don't need debug builds often, I prefer debugging through logs anyway. And when I really need a debug build to track down something extremely strange, I can use cargo's yet unstable feature <a href="https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-overrides">&quot;profile-overrides&quot;</a>.</p> <pre style="background-color:#2b303b;"> <span style="color:#bf616a;">cargo-features </span><span style="color:#c0c5ce;">= [&quot;</span><span style="color:#a3be8c;">profile-overrides</span><span style="color:#c0c5ce;">&quot;] [profile.dev.overrides.&quot;</span><span style="color:#a3be8c;">*</span><span style="color:#c0c5ce;">&quot;] </span><span style="color:#bf616a;">opt-level </span><span style="color:#c0c5ce;">= </span><span style="color:#d08770;">2 </span></pre> <p>Another serious downside of the engine switch, <a href="https://github.com/ggez/ggez/issues/70">though temporary (?)</a>, is that there's no native Android version of the game for now. But who really needs a native port when you have...</p> <h2 id="webassembly-version">WebAssembly Version</h2> <p>After ggez v0.5-rc.0 was published, Icefoxen has posted <a href="https://wiki.alopex.li/TheStateOfGGEZ2019">&quot;The State Of GGEZ 2019&quot;</a>, where among other things he wrote that a web port is unlikely to happen soon because a lot of issues in dependencies need to be fixed first. It could be relatively easy to write a specialized web backend for ggez, but ggez's philosophy is against having multiple backends.</p> <p>And that's where <a href="https://twitter.com/notfl3">Fedor @not-fl3</a> suddenly comes in with his <a href="https://github.com/not-fl3/good-web-game">good-web-game</a> WASM/WebGL game engine. He had been experimenting with 2d web prototypes (<a href="https://twitter.com/notfl3/status/1079499336243965952">like this one</a>) for some time and used a custom 2d web engine for this. The API of this engine was heavily inspired by ggez so he managed to write a partly ggez-compatible wrapper in a weekend.</p> <p>Colors are slightly off and text rendering is a little bit different, but otherwise, it works nicely and smoothly, providing the same experience:</p> <p><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2019-01-29--web-port-vs-native.jpg"><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2019-01-29--web-port-vs-native.jpg" alt="web version vs native" /></a></p> <p>Zemeroth uses good-web-game for its web version as a quick-n-dirty immediate solution until a proper WASM support arrives to GGEZ (there're no plans of making good-web-game some kind of official GGEZ backend or anything like this). The currently implemented subset of ggez's API is quite limited and while it may be used for other games, it will probably require a lot of work to do.</p> <hr /> <p>You can't use crate renaming in <code>Cargo.toml</code> to reuse a name on different platforms,</p> <pre style="background-color:#2b303b;"> <span style="color:#65737e;"># Cargo.toml with these dependencies wouldn&#39;t build: </span><span style="color:#c0c5ce;">[target.&#39;</span><span style="color:#a3be8c;">cfg(not(target_arch = &quot;wasm32&quot;))</span><span style="color:#c0c5ce;">&#39;.dependencies] </span><span style="color:#bf616a;">ggez </span><span style="color:#c0c5ce;">= &quot;</span><span style="color:#a3be8c;">0.5.0-rc.1</span><span style="color:#c0c5ce;">&quot; [target.&#39;</span><span style="color:#a3be8c;">cfg(target_arch = &quot;wasm32&quot;)</span><span style="color:#c0c5ce;">&#39;.dependencies] </span><span style="color:#bf616a;">ggez </span><span style="color:#c0c5ce;">= { </span><span style="color:#bf616a;">git </span><span style="color:#c0c5ce;">= &quot;</span><span style="color:#a3be8c;">https://github.com/not-fl3/good-web-game</span><span style="color:#c0c5ce;">&quot;, </span><span style="color:#bf616a;">package </span><span style="color:#c0c5ce;">= &quot;</span><span style="color:#a3be8c;">good-web-game</span><span style="color:#c0c5ce;">&quot; } </span></pre> <p>So the crate substitution hack is done in <code>main.rs</code> using <code>extern crate</code> items in <code>main.rs</code>:</p> <pre style="background-color:#2b303b;"> <span style="color:#c0c5ce;">#[</span><span style="color:#bf616a;">cfg</span><span style="color:#c0c5ce;">(</span><span style="color:#bf616a;">not</span><span style="color:#c0c5ce;">(target_arch = &quot;</span><span style="color:#a3be8c;">wasm32</span><span style="color:#c0c5ce;">&quot;))] </span><span style="color:#b48ead;">extern crate</span><span style="color:#c0c5ce;"> ggez; #[</span><span style="color:#bf616a;">cfg</span><span style="color:#c0c5ce;">(target_arch = &quot;</span><span style="color:#a3be8c;">wasm32</span><span style="color:#c0c5ce;">&quot;)] </span><span style="color:#b48ead;">extern crate</span><span style="color:#c0c5ce;"> good_web_game as ggez; </span></pre> <p>99.9% of code stays the same, but I had to use a separate main, because good-web-game has a different initialization API:</p> <pre style="background-color:#2b303b;"> <span style="color:#c0c5ce;">#[</span><span style="color:#bf616a;">cfg</span><span style="color:#c0c5ce;">(target_arch = &quot;</span><span style="color:#a3be8c;">wasm32</span><span style="color:#c0c5ce;">&quot;)] </span><span style="color:#b48ead;">fn </span><span style="color:#8fa1b3;">main</span><span style="color:#c0c5ce;">() -&gt; GameResult { ggez::start( conf::Conf { cache: conf::Cache::Index, loading: conf::Loading::Embedded, ..Default::default() }, |</span><span style="color:#b48ead;">mut </span><span style="color:#bf616a;">context</span><span style="color:#c0c5ce;">| { </span><span style="color:#b48ead;">let</span><span style="color:#c0c5ce;"> state = MainState::new(&amp;</span><span style="color:#b48ead;">mut</span><span style="color:#c0c5ce;"> context).</span><span style="color:#96b5b4;">unwrap</span><span style="color:#c0c5ce;">(); event::run(context, state) }, ) } </span></pre> <p>Finally, a short helper script <code>utils/wasm/build.sh</code> was added:</p> <pre style="background-color:#2b303b;"> <span style="color:#65737e;">#!/bin/sh </span><span style="color:#bf616a;">cp -r</span><span style="color:#c0c5ce;"> assets static </span><span style="color:#bf616a;">cp</span><span style="color:#c0c5ce;"> utils/wasm/index.html static </span><span style="color:#bf616a;">ls</span><span style="color:#c0c5ce;"> static &gt; static/index.txt </span><span style="color:#bf616a;">cargo</span><span style="color:#c0c5ce;"> web build </span></pre> <ul> <li><a href="https://github.com/koute/cargo-web">cargo-web</a> only packs a <code>static</code> directory (it's hardcoded), so the script copies the game's assets there;</li> <li>the <code>index.html</code> template page is also copied there;</li> <li>all assets should be listed in <code>index.txt</code> for good-web-game to be able to load them, so this file is created;</li> </ul> <p>You can find a minimal example of good-web-game <a href="https://github.com/not-fl3/good-web-game/tree/9b362da6d/examples/simple">here</a>.</p> <h2 id="itch-io">itch.io</h2> <p>The web version needs to be hosted somewhere. <a href="https://itch.io/">itch.io</a> is a nice place for this:</p> <p><strong><a href="https://ozkriff.itch.io/zemeroth">ozkriff.itch.io/zemeroth</a></strong></p> <p>it has a nice and simple UI (for both developers and consumers), it's extremely <a href="https://itch.io/docs/creators/html5">easy to upload a web game there</a> and it's a relatively known store for indie games that can provide some exposure by itself.</p> <p><a href="https://ozkriff.itch.io"><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2019-05-02--itch-ozkriff.png" alt="screenshot of the itch.io page" /></a></p> <p>(<em><a href="https://ozkriff.itch.io/zoc">Zone of Control also got an itch.io page</a></em>)</p> <hr /> <p>Note an &quot;Enter fullscreen&quot; button in the bottom right corner of the game area:</p> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2019-04-26-wasm-fullscreen-button.png" alt="&quot;enter fullscreen&quot; button" /></p> <hr /> <p>As I've said in the ggez section above, the web version of the game seems to work fine on most mobile devices:</p> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2019-05-04--android-wasm.jpg" alt="web version on android device" /></p> <hr /> <p>With a playable version only a click away I received a lot of fresh feedback: a lot of people that previously were only following the development now actually tried to play the game.</p> <p>The most important things people want to see improved are:</p> <ul> <li>Improve the GUI: Replace text buttons with icons, show some tooltips, etc;</li> <li>Add a tutorial or at least a short guide;</li> <li>Randomness is too frustrating: missed attacks should result in some little positive effect, like pushing enemies back or reducing their stamina;</li> <li>The game lacks ranged attack units, like archers or knife throwers.</li> </ul> <p>@Yururu even wrote <a href="https://itch.io/post/660275">a giant comment</a> on the itch page! It's inspiring when a stranger from the internet breaks through the crude primitive interface, figures out game mechanics on a quite deep level, and writes a detailed review of their experience and thoughts.</p> <hr /> <p>I've created <a href="https://www.reddit.com/r/rust/comments/arm9dr/a_list_of_itchio_games_written_in_rust">an itch.io list of Rust games</a>. When I find a Rust game on itch.io I add it there.</p> <p>Also, I've sent a request to itch.io folks to add Rust as an instrument, so now a more official list is available: <a href="https://itch.io/games/made-with-rust">itch.io/games/made-with-rust</a> (you can edit a game's instruments here: &quot;edit game&quot; -&gt; &quot;metadata&quot; -&gt; &quot;engines &amp; tools&quot;). Looks like my original list will be deprecated with time but it's still useful for now because only authors of the games can add an instrument to the metadata.</p> <h2 id="visual-improvements">Visual Improvements</h2> <p><a href="https://twitter.com/ozkriff/status/975827153056075776">The initial draft</a> of the new sprites looked like this:</p> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/agents-inkscape-mockup.jpeg" alt="New style mockup" /></p> <p>Tiles are flattened now. It's less a schematic top-down view as it was before. &quot;Camera&quot; is moved to the side so the tiles and agents are shown using the same projection.</p> <p>There're many gradients in the mockup image above. Later I decided to get rid of all the gradients and curvy lines and stick with &quot;pseudo lowpoly&quot; style.</p> <p>Floating Eye and Insecto-snake agent types from the mockup haven't made it to the master yet.</p> <hr /> <p>All objects now have a shadow. It makes the image a little bit more tangible. Walk and especially throw animations feel better now.</p> <p>Initially, shadow was an ellipse with gradient. Later it was replaced by two semi-transparent hexagons for style consistency.</p> <hr /> <p><a href="https://github.com/ozkriff/zemeroth/pull/401">Added blood splatters and weapon flashes</a> to make attacks more dramatic:</p> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2018-12-22--blood-splatters-and-weapon-flashes-demo-2.gif" alt="blood drops and weapon flashes demo" /></p> <p>The number of drops depends on the attack's damage. Blood slowly disappears into transparency in three turns, otherwise, the battlefield would become a complete and unreadable mess.</p> <p>Every agent now has <code>WeaponType</code>: &quot;smash&quot;, &quot;slash&quot;, &quot;pierce&quot;, and &quot;claw&quot;. For now, they are just visual information. They affect only what sprite is used during the attack animation.</p> <p>Same as agent sprites, weapon flash sprites are not yet mirrored horizontally. That is most noticeable with curvy smash sprite.</p> <p>Also, spearman's &quot;pierce&quot; weapon sprite is horizontal and it looks weird during vertical attacks. Either multiple sprites are needed or it should be rotated.</p> <hr /> <p><a href="https://github.com/ozkriff/zemeroth/pull/390">Added a Dust effect</a> (for jumps and throws):</p> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2019-05-12--dust-clouds.gif" alt="dust demo" /></p> <p>It is created by a simple function that just emits a bunch of half-transparent sprites and attaches position and color change actions to them. Sprites' size, velocity, and transparency are a little bit randomized.</p> <h2 id="campaign-mode">Campaign Mode</h2> <p>A basic campaign mode was added. It's just a linear sequence of battles with predefined scenarios. After each battle, your survived fighters are carried over to the next battle. If you lose a battle - the campaign is over for you. If you win a battle, you're shown a transition screen with a list of your dead fighters, your current squad, and possible recruits:</p> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2018-11-15--first-iteration-of-a-campaign-mode.png" alt="Campaign screen example" /></p> <p>The campaign is defined by a <a href="https://github.com/ron-rs/ron">RON</a> config file with this structure:</p> <pre style="background-color:#2b303b;"> <span style="color:#c0c5ce;">initial_agents: [&quot;swordsman&quot;, &quot;alchemist&quot;], nodes: [ ( scenario: ( map_radius: (4), rocky_tiles_count: 8, objects: [ (owner: Some((1)), typename: &quot;imp&quot;, line: Front, count: 3), (owner: Some((1)), typename: &quot;imp_bomber&quot;, line: Middle, count: 2), ], ), award: ( recruits: [&quot;hammerman&quot;, &quot;alchemist&quot;], ), ), ( scenario: ( rocky_tiles_count: 10, objects: [ (owner: None, typename: &quot;boulder&quot;, line: Any, count: 3), (owner: None, typename: &quot;spike_trap&quot;, line: Any, count: 3), (owner: Some((1)), typename: &quot;imp&quot;, line: Front, count: 4), (owner: Some((1)), typename: &quot;imp_toxic&quot;, line: Middle, count: 2), (owner: Some((1)), typename: &quot;imp_bomber&quot;, line: Back, count: 1), (owner: Some((1)), typename: &quot;imp_summoner&quot;, line: Back, count: 2), ], ), award: ( recruits: [&quot;swordsman&quot;, &quot;spearman&quot;, &quot;hammerman&quot;], ), ), ] </span></pre> <p>Here's some real campaign scenario: <a href="https://github.com/ozkriff/zemeroth_assets/blob/acd9fe9ef/campaign_01.ron">campaign_01.ron</a></p> <p>There's a known bug that you can exit from a battle that is not going well at any moment to start again. This will be forbidden - permadeath is the only way :) .</p> <h2 id="hit-chances">Hit Chances</h2> <p>In the previous version of Zemeroth the hit chance was always 50%. Now, <code>attack_accuracy</code> and <code>dodge</code> stats were added to the <code>Agent</code> component to <a href="https://github.com/ozkriff/zemeroth/pull/370">implement a basic hit chances math</a>.</p> <p>When you select an agent that can attack (has an attack point and enemies in range) a hit chance is shown over all available targets:</p> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2018-05-12--hit-chances-1.png" alt="Hit chances screenshot" /></p> <p>During the attack animation, a hit chance is shown near the attacker with a smaller font.</p> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2019-05-12--attack-hit-chances.gif" alt="Hit chance during the attack animation" /></p> <p>This was added in order for the player to see how dangerous enemy attacks are.</p> <hr /> <p>Also, wounded agents now become less accurate. Each lost strength point results in -10% hit chance penalty (up to -30%).</p> <p>Missing strength points (wounds) are shown by almost transparent green dots:</p> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2018-10-04--transparent-dots.png" alt="demo of transparent strength points" /></p> <p>This gameplay change has two game balance consequences:</p> <ul> <li>Now it's more important to wound enemies, finishing them off is a lower priority most of the time. Sometimes wounded enemies even can be helpful to the player, because they are not a real threat to player's fighters, but can block the path for other enemies;</li> <li>Alchemist's &quot;heal&quot; ability became important because your agents are less useful when wounded too.</li> </ul> <p>Also, attacks with strength &gt; 1 have additional hit chances - with reduced damage (each attack strength point gives 10% hit chance improvement). This emulates the situation when an attacker barely touches their target but still manages to make some damage to it.</p> <h2 id="armor">Armor</h2> <p>A basic armor system was implemented. Armor points are shown above the agent in one line with strength points using the yellow dots. Each armor point deflects one damage point on each attack. Some weapons can break armor (the <code>attack_break</code> parameter). Fire and poison ignore armor.</p> <p>Here's a little demo:</p> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2018-09-16--old-armor-demo.gif" alt="old armor demo" /></p> <ul> <li>an imp can't break armor so he can't deal any damage to the heavy swordsman;</li> <li>toxic imp can't deal any direct damage but he poisons the swordsman ignoring the armor;</li> <li>insecto-snake destroys the armor with a powerful attack.</li> </ul> <p>In the current version of the game only imp summoners have armor, so be careful with them.</p> <h2 id="ai-updates">AI Updates</h2> <ul> <li> <p>Now, <a href="https://github.com/ozkriff/zemeroth/pull/306">enemies always act in order of remoteness from a player's fighters</a>. This way melee imps don't trip over each other too much.</p> </li> <li> <p>AI learned to avoid walking into spikes, fire and poison clouds.</p> </li> <li> <p>AI now moves closer to its targets even if there's no direct path to them (<a href="https://youtu.be/09ODLL_Nu8w">full demo video</a>):</p> <p><a href="https://youtu.be/09ODLL_Nu8w"><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2018-06-04--ai-pathfinding-demo.gif" alt="new pathfinding demo" /></a></p> </li> <li> <p>Non-melee imps (bombers and summoners) are now <a href="https://github.com/ozkriff/zemeroth/pull/298">trying to keep distance from the player's fighters in range</a>. They need to avoid melee fights but still be able to throw bombs at a player's fighters or summon new imps near the frontline.</p> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2018-07-02--ai-distance.gif" alt="ai distance demo" /></p> <p>Summoner has a slightly greater min/max range than bomber.</p> </li> </ul> <p>During the debugging of the above-mentioned features, I also wrote <a href="https://github.com/ozkriff/zemeroth/blob/721ad06a6/src/core/map.rs#L152-L169">a simple helper function <code>dump_map</code></a> that takes a closure and dumps required map data as a <code>char</code> in the above GIF, pic 1 shows objects (<code>A</code> - an agent, <code>O</code> - a non-agent object) and pic 2 shows available positions (<code>X</code>).</p> <h2 id="bombs-and-commutative-effects">Bombs and Commutative Effects</h2> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2018-06-04--bombs-issue.png" alt="Illustration with multiple bombs" /></p> <p>^ In the previous version of Zemeroth, each of these bombs would have exploded at the beginning of the next turn in order of their creation. But this order is hard to remember and it's not clear from the picture at all.</p> <p>The order is very important as the explosions push back objects - if the first explosion is on the left, an agent will be damaged by the right bomb too.</p> <p>Pushback is not the only possible effect suffering from this. Other possible examples of <a href="https://en.wikipedia.org/wiki/Commutative_property">non-commutative effects</a>: teleportation, armor-breaking acid, immunity to damage, etc. Anything where changing the order of application can change the final state.</p> <p>I see two possible ways to solve this:</p> <ol> <li><a href="https://store.steampowered.com/app/590380/Into_the_Breach">&quot;Into the Breach&quot;</a>-like approach with explicit numbers;</li> <li>Forbid non-commutative delayed effects.</li> </ol> <p>ItB's approach means just adding this order information explicit in the game's interface. It looks like this:</p> <p><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2018-06-22-into-the-breach.png"><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2018-06-22-into-the-breach-mini.png" alt="Into the breach screenshot" /></a></p> <p>Technically it's possible, but I don't think that it fits for Zemeroth because it's an extremely noisy interface feature, but it's not really a core mechanic.</p> <p>So, <a href="https://github.com/ozkriff/zemeroth/pull/296">I've taken the latter way</a>: the &quot;Bomb&quot; ability was split into two abilities: instant &quot;BombPush&quot; and delayed &quot;BombDamage&quot;.</p> <p>The plan is to have three groups of objects with effects:</p> <ul> <li>Objects with immediate effects - can have non-commutative effects;</li> <li>General objects with timed effects - only commutative effects allowed;</li> <li>Special rare timed objects - can do whatever they want, but only allowed as unique boss abilities, work in their own special phase.</li> </ul> <h2 id="other-game-rules-changes">Other Game Rules Changes</h2> <ul> <li> <p>Spike traps were added. They're almost like fire tiles, but permanent.</p> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2019-05-12--spikes.png" alt="spike trap" /></p> </li> <li> <p><a href="https://github.com/ozkriff/zemeroth/pull/351">Updated</a> &quot;Poison&quot; passive ability: it can’t, by itself, kill an agent anymore. “Poisoned” status is removed when a target’s strength is reduced to 1. This should make battles a little bit less frustrating and more dramatic.</p> </li> <li> <p>Updated the &quot;Summon&quot; ability:</p> <p><a href="https://github.com/ozkriff/zemeroth/pull/413">Each agent is now treated individually</a>. The new code treats each summoned agent individually thus preventing summoning weird packs of same imp types.</p> <p><a href="https://github.com/ozkriff/zemeroth/pull/349">Each use of the &quot;Summon&quot; ability now creates one more imp</a>. It forces the player to play more aggressively.</p> <p>Changed the summoning algorithm to <a href="https://twitter.com/ozkriff/status/1040321852495863808">prefer imp types that are under-presented on the map</a>, not just random ones. Seems to work fine now - even with increased summon rate imp types are balanced in count: <a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2018-09-14--fixed-summoning.png"><em>pic</em></a>.</p> </li> <li> <p><a href="https://github.com/ozkriff/zemeroth/pull/360">Randomly-placed agents are not created point-blank to their enemies anymore</a>.</p> </li> <li> <p>Also, <a href="https://github.com/ozkriff/zemeroth/pull/369">randomly-placed objects are now created on different <code>Line</code>s</a>. This prevents Imp Summoners from being created only a tile away from enemies and thus not having any chances to survive. Or Imp Bombers being instantly tied with a melee fight.</p> <p>A line is defined in the scenario files:</p> <pre style="background-color:#2b303b;"> <span style="color:#c0c5ce;">(owner: Some((1)), typename: &quot;imp&quot;, line: Front, count: 4), </span></pre> <p>There're four possible values:</p> <pre style="background-color:#2b303b;"> <span style="color:#b48ead;">pub enum </span><span style="color:#c0c5ce;">Line { Any, Front, Middle, Back } </span></pre></li> </ul> <h2 id="gameplay-video">Gameplay Video</h2> <p>So, putting these gameplay changes together:</p> <p><a href="https://youtu.be/zUVwAFSrh3c"><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2019-05-12--playtest-youtube-preview.png" alt="youtube video" /></a></p> <p>This is a piece of a campaign mode playtest: battles 3, 4, and 5.</p> <h2 id="svg-atlas">SVG Atlas</h2> <p>Back to more technical updates.</p> <p>As git is bad at storing non-text files and it's practically impossible to use <a href="https://git-lfs.github.com">Git LFS</a> with a free GitHub plan (because of <a href="https://help.github.com/en/articles/about-storage-and-bandwidth-usage">the bandwidth limitations</a>), it looks like a good idea to keep text source files, assets source files, and built assets in separate repositories to make &quot;optimization history editing&quot; (removing old commits) easier.</p> <p><a href="https://github.com/ozkriff/zemeroth">The main repo</a> and <a href="https://github.com/ozkriff/zemeroth_assets">the assets repo</a> already existed, but I wasn't storing assets source files in any VCS.</p> <p>So, during v0.5 development, I've created another repo for assets sources: <a href="https://github.com/ozkriff/zemeroth_assets_src">ozkriff/zemeroth_assets_src</a>. The two key files of this repo are: <a href="https://github.com/ozkriff/zemeroth_assets_src/blob/1f1813eff/atlas.svg">atlas.svg</a> and <a href="https://github.com/ozkriff/zemeroth_assets_src/blob/1f1813eff/export.py">export.py</a>.</p> <p>The atlas contains all sprites in one file. Each sprite is stored as a named group. As the game isn't that much art heavy, using one file for all visual assets looks fitting, because of it:</p> <ul> <li>simplifies sharing parts of sprites and mockups creation;</li> <li>avoids complications of linking/embedding multiple SVG files together (you need to manually edit XML do to this properly as far as I know).</li> </ul> <p>The export script is quite simple, it just calls Inkscape using its CLI interface and tells what named group needs to be exported to PNGs. It boils down to:</p> <pre style="background-color:#2b303b;"> <span style="color:#b48ead;">for </span><span style="color:#96b5b4;">id </span><span style="color:#b48ead;">in </span><span style="color:#c0c5ce;">[&#39;</span><span style="color:#a3be8c;">imp</span><span style="color:#c0c5ce;">&#39;, &#39;</span><span style="color:#a3be8c;">imp_toxic</span><span style="color:#c0c5ce;">&#39;, &#39;</span><span style="color:#a3be8c;">grass</span><span style="color:#c0c5ce;">&#39;, </span><span style="color:#d08770;">...</span><span style="color:#c0c5ce;">]: subprocess.</span><span style="color:#bf616a;">run</span><span style="color:#c0c5ce;">([ &#39;</span><span style="color:#a3be8c;">inkscape</span><span style="color:#c0c5ce;">&#39;, input_file_name, </span><span style="color:#b48ead;">f</span><span style="color:#c0c5ce;">&#39;</span><span style="color:#a3be8c;">--export-id=</span><span style="color:#c0c5ce;">{</span><span style="color:#96b5b4;">id</span><span style="color:#c0c5ce;">}&#39;, </span><span style="color:#b48ead;">f</span><span style="color:#c0c5ce;">&#39;</span><span style="color:#a3be8c;">--export-png=</span><span style="color:#c0c5ce;">{out_dir_name}</span><span style="color:#a3be8c;">/</span><span style="color:#c0c5ce;">{</span><span style="color:#96b5b4;">id</span><span style="color:#c0c5ce;">}</span><span style="color:#a3be8c;">.png</span><span style="color:#c0c5ce;">&#39;, ], </span><span style="color:#bf616a;">check</span><span style="color:#c0c5ce;">=</span><span style="color:#d08770;">True</span><span style="color:#c0c5ce;">) </span></pre> <p>There's also a hack to avoid specifying exact sprite PNG sizes as raw numbers in the export script: each named group contains an invisible square (a rectangle for terrain tiles). It can be temporary made slightly visible for debugging purposes:</p> <p><a href="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2018-07-16--svg-atlas-test.png"><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2018-07-16--svg-atlas-test.png" alt="sprites in the debug mode" /></a></p> <h2 id="assets-hash">Assets Hash</h2> <p>Another technical assets-related update is that a md5 hash check was added. This should help to detect when someone who is building from source forgets to update the assets.</p> <p>A small <a href="https://github.com/ozkriff/zemeroth_assets/blob/acd9fe9ef/checksum.py">checksum.py</a> python script is used to calculate the hash of all non-hidden files in the repo. <a href="https://github.com/ozkriff/zemeroth_assets/blob/acd9fe9ef/travis.yml">CI uses it to check</a> that the committed hashsum really corresponds to the committed assets.</p> <p>The expected hash is <a href="https://github.com/ozkriff/zemeroth/blob/721ad06a6src/main.rs#L92">hardcoded directly into main.rs</a>. If the game is run with a wrong version of assets, now you get a clear error message about that:</p> <pre style="background-color:#2b303b;"> <span style="color:#c0c5ce;">Bad assets checksum abcdeabcdeabcdeabcdeabcdeabcdeab (expected 18e7de361e74471aeaec3f209ef63c3e) </span></pre><h2 id="tests">Tests</h2> <p>One of the benefits of making a turn-based game is that you can relatively easy separate the logic from the visuals and cover the former with tests.</p> <p><a href="https://github.com/ozkriff/zemeroth/pull/439">A few test scenarios were added</a>.</p> <p>They are completely deterministic. Randomness is mitigated with special agent types with unrealistic stats (for example, <code>accuracy = 999</code> or <code>strength = 1</code>), that allows them to always pass required tests (for example, always hits or always dies on the first hit), and an additional <code>no_random</code> flag in the game state, that causes a panic if agent's stats during the &quot;dice roll&quot; may result in non-determined results (basically, it checks that the coefficients are large or low enough to shut off any dice value fluctuations).</p> <p>&quot;Exact objects&quot; were added to the scenarios. Test scenarios mustn't contain any randomly-placed objects, otherwise the <code>no_random</code> debug flag will cause a panic.</p> <p>Basic test looks like this:</p> <pre style="background-color:#2b303b;"> <span style="color:#c0c5ce;">#[</span><span style="color:#bf616a;">test</span><span style="color:#c0c5ce;">] </span><span style="color:#b48ead;">fn </span><span style="color:#8fa1b3;">basic_move</span><span style="color:#c0c5ce;">() { </span><span style="color:#b48ead;">let</span><span style="color:#c0c5ce;"> prototypes = </span><span style="color:#96b5b4;">prototypes</span><span style="color:#c0c5ce;">(&amp;[ (&quot;</span><span style="color:#a3be8c;">mover</span><span style="color:#c0c5ce;">&quot;, [</span><span style="color:#96b5b4;">component_agent_move_basic</span><span style="color:#c0c5ce;">()].</span><span style="color:#96b5b4;">to_vec</span><span style="color:#c0c5ce;">()), (&quot;</span><span style="color:#a3be8c;">dull</span><span style="color:#c0c5ce;">&quot;, [</span><span style="color:#96b5b4;">component_agent_dull</span><span style="color:#c0c5ce;">()].</span><span style="color:#96b5b4;">to_vec</span><span style="color:#c0c5ce;">()), ]); </span><span style="color:#b48ead;">let</span><span style="color:#c0c5ce;"> scenario = scenario::default() .</span><span style="color:#96b5b4;">object</span><span style="color:#c0c5ce;">(</span><span style="color:#d08770;">P0</span><span style="color:#c0c5ce;">, &quot;</span><span style="color:#a3be8c;">mover</span><span style="color:#c0c5ce;">&quot;, PosHex { q: </span><span style="color:#d08770;">0</span><span style="color:#c0c5ce;">, r: </span><span style="color:#d08770;">0 </span><span style="color:#c0c5ce;">}) .</span><span style="color:#96b5b4;">object</span><span style="color:#c0c5ce;">(</span><span style="color:#d08770;">P1</span><span style="color:#c0c5ce;">, &quot;</span><span style="color:#a3be8c;">dull</span><span style="color:#c0c5ce;">&quot;, PosHex { q: </span><span style="color:#d08770;">0</span><span style="color:#c0c5ce;">, r: </span><span style="color:#d08770;">2 </span><span style="color:#c0c5ce;">}); </span><span style="color:#b48ead;">let mut</span><span style="color:#c0c5ce;"> state = </span><span style="color:#96b5b4;">debug_state</span><span style="color:#c0c5ce;">(prototypes, scenario); </span><span style="color:#b48ead;">let</span><span style="color:#c0c5ce;"> path = Path::new(vec![ PosHex { q: </span><span style="color:#d08770;">0</span><span style="color:#c0c5ce;">, r: </span><span style="color:#d08770;">0 </span><span style="color:#c0c5ce;">}, PosHex { q: </span><span style="color:#d08770;">0</span><span style="color:#c0c5ce;">, r: </span><span style="color:#d08770;">1 </span><span style="color:#c0c5ce;">}, ]); </span><span style="color:#96b5b4;">exec_and_check</span><span style="color:#c0c5ce;">( &amp;</span><span style="color:#b48ead;">mut</span><span style="color:#c0c5ce;"> state, command::MoveTo { id: ObjId(</span><span style="color:#d08770;">0</span><span style="color:#c0c5ce;">), path: path.</span><span style="color:#96b5b4;">clone</span><span style="color:#c0c5ce;">(), }, &amp;[Event { active_event: event::MoveTo { id: ObjId(</span><span style="color:#d08770;">0</span><span style="color:#c0c5ce;">), path, cost: Moves(</span><span style="color:#d08770;">1</span><span style="color:#c0c5ce;">), } .</span><span style="color:#96b5b4;">into</span><span style="color:#c0c5ce;">(), </span><span style="color:#65737e;">// small formatting issue, see a note below </span><span style="color:#c0c5ce;"> actor_ids: vec![ObjId(</span><span style="color:#d08770;">0</span><span style="color:#c0c5ce;">)], instant_effects: Vec::new(), timed_effects: Vec::new(), scheduled_abilities: Vec::new(), }], ); } </span></pre> <p>(<em>I didn't use the builder pattern for event construction, even though most of the time two or three its fields are empty vectors, because I've faced some <a href="https://github.com/rust-lang/rustfmt/issues/3157#issuecomment-472718887">method chains formatting issues</a></em>)</p> <p>Test scenario consists of a list of commands and a list of expected events. Occasionally, it can check some parts of the state.</p> <p>A prototypes list and a scenario are created from scratch (though, with some helper functions) for each test. It takes more lines of code than reusing a small set of multi-cases scenarios, but the idea is that this way the amount of objects and components in each test is minimized. This way it's easier to diagnose the bug and makes tests less likely to break on unrelated game logic change.</p> <p>A &quot;dull&quot; enemy agent is required only for the scenario not to end instantly. Because the win condition is when no enemy agents are alive.</p> <hr /> <p><a href="https://github.com/colin-kiegel/rust-pretty-assertions">colin-kiegel/rust-pretty-assertions</a> is a super-useful crate when you need to debug failing assert comparisons of big hierarchical objects (some of which may be many screens long in my case).</p> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2019-03-20--color-assert.png" alt="a colored assert error" /></p> <p>One peculiarity is that I had to replace all <code>HashMap&lt;ObjId, Vec&lt;Foo&gt;&gt;</code> in events with <code>Vec&lt;(ObjId, Vec&lt;Foo&gt;)&gt;</code> to preserve the order. Otherwise pretty-assertion has been exploding.</p> <h2 id="other-technical-changes">Other Technical Changes</h2> <ul> <li><a href="https://github.com/ozkriff/zemeroth/pull/394">Moved all crates to Rust 2018</a>;</li> <li><a href="https://github.com/ozkriff/zemeroth/pull/226">Added a note about 'help-wanted' issues</a>;</li> <li>Used <code>derive_more::From</code> for enums and errors;</li> <li><a href="https://github.com/ozkriff/zemeroth/pull/229">Migrated to <code>std::time::Duration</code></a> and added <code>time_s</code> shortcut/helper function;</li> <li><a href="https://github.com/ozkriff/zemeroth/pull/365">Removed</a> some data duplication from <a href="https://github.com/ozkriff/zemeroth_assets/blob/69e6fb34c/objects.ron">the <code>.ron</code> config with objects descriptions</a> using serde`s default annotations and helper init functions;</li> <li><a href="https://github.com/ozkriff/zemeroth/pull/220">Added a <code>windows_subsystem</code> attribute</a> to hide cmd window on Windows;</li> <li><a href="https://github.com/ozkriff/zemeroth/pull/233">Fixed panic when a boulder is pushed into fire/spikes</a>;</li> <li><a href="https://github.com/ozkriff/zemeroth/pull/431">Mergeed all 'line_height' consts and functions</a>;</li> <li><a href="https://github.com/ozkriff/zemeroth/pull/365">Removed data duplication from <code>objects.ron</code></a>.</li> </ul> <h2 id="indikator">Indikator</h2> <p><a href="https://twitter.com/ozkriff/status/1058359693503070208">Gave a presentation about Zemeroth</a> at 8th Indie-StandUp at <a href="http://indierocket.ru">Indikator</a>. It went pretty good, local indie devs seemed to like the project, especially considering that it's opensource and uses an interesting tech. At least one of the devs has visited <a href="https://www.meetup.com/spbrust">our local rustlang meetup</a> afterward. 🦀</p> <p><img src="https://ozkriff.games/2019-05-13--devlog-zemeroth-v0-5/2018-11-03--indikator.jpg" alt="me presenting Zemeroth at Indikator" /></p> <hr /> <p>It's unrelated, but <a href="https://www.redblobgames.com/grids/hexagons/implementation.html">Zemeroth was mentioned on Amit's page about hex math</a>.</p> <h2 id="migrated-this-devlog-to-zola">Migrated This Devlog to Zola</h2> <p>During the preparation for this Zemeroth release, I've <a href="https://ozkriff.github.io/2017-12-01--devlog/index.html#restructuredtext-markdown">finally</a> switched the static site generator behind this devlog from Python-based <a href="https://getpelican.com">Pelican</a> to Rustlang-based <a href="http://getzola.org">Zola</a>.</p> <p><a href="https://twitter.com/ozkriff/status/1119212330246656002">Here's a twitter thread</a> with some migration notes.</p> <p>TLDR is that I've mostly automatically converted all RestructuredText post sources into Markdown, replaced <a href="http://disqus.com">Disqus comments</a> with direct links to reddit/twitter/etc, set up redirects from old URLs.</p> <h2 id="roadmap">Roadmap</h2> <p>What's next? Some things I <em>hope</em> to implement for v0.6 release are:</p> <ul> <li><a href="https://github.com/ozkriff/zemeroth/issues/276">Replace the text buttons with icons</a>;</li> <li><a href="https://github.com/ozkriff/zemeroth/issues/214">Reduce text overlapping</a>;</li> <li><a href="https://github.com/ozkriff/zemeroth/issues/221">Add sound effects and music</a>;</li> <li><a href="https://github.com/ozkriff/zemeroth/issues/399">Add fighters upgrade trees</a>;</li> </ul> <p>You can find a slightly more detailed roadmap <a href="https://github.com/ozkriff/zemeroth#roadmap">in the project's README</a>.</p> <hr /> <p>That's all for today, thanks for reading!</p> <p>If you're interested in this project you can follow <a href="https://twitter.com/ozkriff">@ozkriff on Twitter</a> for more news.</p> <p>Also, if you're interested in Rust game development in general, you may want to check <a href="http://twitter.com/rust_gamedev">@rust_gamedev</a> twitter account that I've started recently.</p> <p><strong>Discussions of this post</strong>: <a href="https://www.reddit.com/r/rust/comments/bo5w0q/zemeroth_v05_ggez_wasm_itchio_visuals_ai_campaign/">/r/rust</a>, <a href="https://twitter.com/ozkriff/status/1127977478746669056">twitter</a>.</p> Zemeroth v0.4: Abilities, Lasting Effects and New Unit Types Sat, 03 Mar 2018 00:00:00 +0000 https%3A//ozkriff.games/2018-03-03--devlog/ https%3A//ozkriff.games/2018-03-03--devlog/ <p>Hi, comrades! I'm happy to announce Zemeroth v0.4.</p> <p><a href="https://github.com/ozkriff/zemeroth">Zemeroth</a> is a turn-based hexagonal tactical game written in Rust.</p> <p>You can <strong>download precompiled binaries</strong> for Windows, Linux, macOS and android here: <a href="https://github.com/ozkriff/zemeroth/releases/tag/v0.4.0">releases/tag/v0.4.0</a></p> <p>This release adds <a href="https://github.com/Aaronepower/tokei">~2k lines of code</a> - a lot of new features! And it's hard to describe all the stuff only with words and static images so this time I'll try to use more GIFs (btw, <a href="https://github.com/phw/peek">Peek</a> is a cool app for fast gif recording). I hope that they won't cause too much problems for the readers.</p> <p><em>NOTE:</em> Most of the GIFs were recorded on a map of 7 tiles wide, but the actual map is 11. See youtube video in the middle of the article for some real gameplay.</p> <h2 id="simple-walking-animation">Simple walking animation</h2> <p>The first and simplest change is simple walking animations. Compare:</p> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03-move-pre.gif" alt="no animation" /> <img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03-move-now.gif" alt="new arc animation" /></p> <p>That's just a small visual improvement but it makes the game more lively.</p> <h2 id="gameplay-updates">Gameplay Updates</h2> <h3 id="wounds-reduce-attacks-by-one">Wounds reduce attacks by one</h3> <p>New rule: every successful attack now reduces target's attack by 1. It's small but important change because it increases the value of initiative and is relied upon by many abilities.</p> <h3 id="strong-attacks">Strong Attacks</h3> <p>In the previous version all attacks were dealing 1 damage. Now, <strong>Swordsman</strong> and <strong>Hammerman</strong> (see below) deal 2 damage points per hit.</p> <h3 id="abilities">Abilities</h3> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03--abilities-buttons-swordsman.png" alt="buttons: abilities" /></p> <p>Abilities is the main feature of this release. They come in two flavours: <strong>active</strong> and <strong>passive</strong>:</p> <ul> <li> <p>Each active ability activation requires either <strong>Attack</strong> (red) or <strong>Joker</strong> (purple) point and can trigger enemy's reaction attack.</p> <p>Most abilities have cooldowns of 2 or 3 turns long.</p> </li> <li> <p>Passive abilities don't require any action points and are activated automatically: during attacks or at the begining of the turn, for example.</p> </li> </ul> <p>Particular abilities are explained in unit sections below.</p> <h3 id="new-unit-toxic-imp">New Unit: Toxic Imp</h3> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03-imp-poison.gif" alt="toxic imp demo" /></p> <p>Let's start with something simple. This enemy is similar to basic Imp, but does no direct damage and has <strong>Poison Attack</strong> passive ability.</p> <p>Poisoned unit receives one would at the begining of each turn. Note that poison also takes away one attack from the victim, weaking it even more. Poison reduces attacks of poisoned unit by one.</p> <p>Toxic Imp also has no reaction attacks as he's dangerous enough without them.</p> <h3 id="new-unit-imp-bomber">New Unit: Imp-Bomber</h3> <p>Poison is cool, but it doesn't really changes the game much. One obvious problem of v0.3 was <a href="http://keithburgun.net/turtling">turtling</a> - no movement, boring. Reaction attacks encourage defensive playstyle.</p> <p>So a new unit was added: <strong>Imp-Bomber</strong>.</p> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03--imp-bomb-attack.gif" alt="imp-bomber in action" /></p> <p>^ He has an active ability <strong>Bomb</strong> and a very simple AI that tries to use it, if it's available, and then acts as a normal Imp. Bombs with delayed detonation is a classic way to help with this.</p> <p>Bomb explodes on the next turn and damages everyone around, knocking them back for one tile.</p> <p>NOTE: As Imps are stupid they can be easily damaged by their bombs. Use it.</p> <p>This enemy doesn't allow you to stay in a good position without movement. But you still can sometimes move back and forth, so...</p> <h3 id="new-unit-imp-summoner">New Unit: Imp-Summoner</h3> <p>...Soo, meet <strong>Imp-Summoner</strong>! This unit summons so many imps so the only way to stay alive is to rush and attack him while summoned imps are still weak. Summoners are your main targets.</p> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03--ability-summon.gif" alt="'summon' ability" /></p> <p>^ <strong>Summon</strong> ability creates three imps of a random type.</p> <p><em>NOTE: Actually, the plan is to make each <strong>summon</strong> activation even more powerful: call 3-4-5-6 imps, to increase the pressure over time.</em></p> <p>Summoner is slow - сan either move one tile or attack/cast during his turn - but he has a lot of strength (health) points and has <strong>Heavy Impact</strong> and <strong>Regeneration</strong> passive abilities:</p> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03--summoner-regeneration-hit.gif" alt="Regeneration + Heavy Impact" /></p> <p>^ <strong>Regeneration</strong> restores one strength point in the begining of every turn. <strong>Heavy Impact</strong> throws opponents one tile away on every hit (<strong>FlyOff</strong> effect).</p> <h3 id="new-unit-alchemist">New Unit: Alchemist</h3> <p>Let's move to player's new units: meet the first one - <strong>Alchemist</strong>. He's a support unit and has <strong>no direct attacks</strong>, but has a bunch of useful abilities.</p> <p>Basic <strong>Bomb</strong> ability works the same way as it does for Imp-Bomber. <strong>Fire bomb</strong> and <strong>poison bomb</strong> are a little bit more interesting:</p> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03-fire-bomb.gif" alt="fire bomb demo" /></p> <p>^ <strong>Fire</strong> object just deals one damage point each turn to anyone standing in the same tile or to anyone walking through it.</p> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03-poison-bomb.gif" alt="poison bomb demo" /></p> <p>^ <strong>Poison cloud</strong> object acts similar to fire, but it casts <strong>Poisoned</strong> effects on agents. This effects deals one point of damage each turn and lasts for two turns.</p> <p>Both fire and poison cloud objects disappear after two rounds. Note that damage from fire and poison also removes attacks from target - this can protect your alchemist in tough situations.</p> <p>Alchemist has one more useful ability: <strong>Heal</strong> can restore two strength points and remove any lasting effects:</p> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03-heal.gif" alt="&quot;Heal&quot; ability demo" /></p> <h3 id="new-unit-hammerman">New Unit: Hammerman</h3> <p>Slow but powerful unit. His attack deals 2 damage points and he has <strong>HeavyImpact</strong> passive ability (same as Summoner, see above).</p> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03--hammerman-club-hit.gif" alt="&quot;Club&quot; + move + attack combo" /></p> <p>^ <strong>Club</strong> ability causes <strong>Stun</strong> lasting effect and <strong>FlyOff</strong>.</p> <p><strong>Stun</strong> lasting effect removes all attacks/moves/jokers from the target for one round.</p> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03-club-knockback.gif" alt="&quot;Knockback&quot; a boulder + &quot;Club&quot; a bomb demo" /></p> <p>^ These abilities can be used to move bombs and boulders too. You can push enemy into fire, poison or bomb. Or you can push some other your figher out of danger if needed.</p> <h3 id="updated-swordsman">Updated Swordsman</h3> <p><strong>Swordsman</strong> also got a few updates. His main attack now also deals two points of damage.</p> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03--rage.gif" alt="&quot;Rage&quot; ability demo" /></p> <p>^ <strong>Rage</strong> ability gives a lot of attacks but has a long cooldown, so you need to choose carefully when to use it.</p> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03--swordsman-jump.gif" alt="Jump ability" /></p> <p>^ <strong>Jump</strong> ability - think about Diablo's Barbarian (future versions of the ability may get stunning effect ;) ).</p> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03-dash-away.gif" alt="&quot;Dash&quot; escape demo" /></p> <p>^ <strong>Dash</strong> ability allows you to move one tile without triggering reaction attacks. Allows you to start the attack or to escape from the enemies.</p> <p>It may be hard to escape from a bad position witout <strong>Dash</strong> or <strong>Jump</strong> ability:</p> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03-no-dash-escape-attempt.gif" alt="Can't escape with simple move demo" /></p> <p><strong>Dash</strong> can be combined with <strong>Rage</strong> and <strong>Jump</strong> abilities to perform a series of attacks and return back to safety:</p> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03--swordsman-combo.gif" alt="Rage, Dash &amp; Jump combo" /></p> <h3 id="updated-spearman">Updated Spearman</h3> <p>Also got a <strong>Jump</strong> ability, but of a different flavour: three tiles distance and three turns cooldown. So it's mostly useful for escaping:</p> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03--spearman-jump-away.gif" alt="jump away" /></p> <h2 id="gameplay-video">Gameplay Video</h2> <p>So, putting this all together:</p> <p><a href="https://www.youtube.com/watch?v=DpDyVFpoDSQ"><img src="https://ozkriff.games/2018-03-03--devlog/gameplay-vide-preview.png" alt="gameplay" /></a></p> <p>It starts reminding something like a real game, isn't it? :) Though a lot of work is still need to be done.</p> <h2 id="implementation-note-ron-v0-2">Implementation note: RON v0.2</h2> <p><a href="https://github.com/ron-rs/ron/releases/tag/v0.2">RON v0.2</a> added <code>unwrap_newtypes</code> extension that seriously simplified my config files by getting rid of a lot of braces:</p> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03--ron-diff.gif" alt="RON diff" /></p> <p>Thanks, @Torkleyy!</p> <hr /> <p><img src="https://ozkriff.games/2018-03-03--devlog/2018-03-03-phone.gif" alt="Zemeroth on android device" /></p> <p>That's all for today, I have to go play <a href="http://store.steampowered.com/app/590380/Into_the_Breach">Into the Breach</a>! :)</p> <p><strong>Discussions</strong>: <a href="https://www.reddit.com/r/rust/comments/81s7va/zemeroth_v04_abilities_lasting_effects_and_new">/r/rust</a>, <a href="https://twitter.com/ozkriff/status/970017320637747200">twitter</a>.</p> Zemeroth v0.0.3: Jokers, Rancor, Blood and more Fri, 01 Dec 2017 00:00:00 +0000 https%3A//ozkriff.games/2017-12-01--devlog/ https%3A//ozkriff.games/2017-12-01--devlog/ <p>Hi, comrades! Welcome to the second issue of Zemeroth's devlog.</p> <p><a href="https://github.com/ozkriff/zemeroth">Zemeroth</a> is a turn-based hexagonal tactical game written in Rust.</p> <p>It slowly grows into a middle-sized project: <a href="https://github.com/ozkriff/zemeroth">Zemeroth</a> has <a href="https://github.com/Aaronepower/tokei">4.3k LoCs</a> and 82🌟 now. Though I still can't find enough free time to work on it on daily basis and I have to take weeks-long breaks sometimes.</p> <p>So, the progress is quite slow 🐌 but still, I've managed to do some amount of useful stuff during last three months. Here's a short video of how the game looks right now:</p> <div class="youtube"><iframe frameborder="0" allowfullscreen src="https://www.youtube.com/embed/XrC4eCqspUo?rel=0&showinfo=0"></iframe></div> <p>Ok, let's talk about what exactly have I done for the project during this autumn.</p> <h2 id="pre-built-binaries"><a href="https://github.com/ozkriff/zemeroth/issues/56">Pre-built binaries</a></h2> <p>The most important change for anyone who wants to try out Zemeroth and don't want to compile it from the source is auto-deployed pre-built binaries.</p> <p><strong>You can download them here:</strong> <strong><a href="https://github.com/ozkriff/zemeroth/releases">zemeroth/releases</a></strong></p> <p>They are compiled and deployed to Github's releases by CI servers (Travis, Appveyor and CircleCI) on every tag.</p> <p><a href="https://github.com/ozkriff/zemeroth/releases/tag/v0.0.3">The latest release at the time of writing is <code>v0.0.3</code></a>:</p> <p><a href="https://github.com/ozkriff/zemeroth/releases/tag/v0.0.3"><img src="https://ozkriff.games/2017-12-01--devlog/v-0-0-3-release-page.png" alt="v.0.0.3 release page" /></a></p> <p>Linux/Windows and OSX versions are not that interesting - they are built exactly like <a href="https://github.com/ozkriff/zoc/issues/242">it was done for ZoC</a>.</p> <p>Deploying Android <code>apk</code>s is a more interesting story.</p> <p>I've stolen basic apk-building script for CircleCI from <a href="https://github.com/tomaka">@tomaka</a> (thanks again!) - <a href="https://github.com/tomaka/glutin/pull/919">https://github.com/tomaka/glutin/pull/919</a> - and it worked straight out of the box.</p> <p>Deploying <code>apk</code>s is harder: circle-ci doesn't provide a built-in convenient way of deploying to Github, so you have to wield some curl/github_api magic.</p> <p><a href="https://github.com/ozkriff/zemeroth/blob/efc36eb08/.circleci/upload_apk_to_github_releases.sh">All the magic is packed in .circleci/upload_apk_to_github_releases.sh script</a> (which is based on <a href="https://gist.github.com/stefanbuck/ce788fee19ab6eb0b4447a85fc99f447">this gist</a>).</p> <p>Also, some <a href="https://github.com/ozkriff/zemeroth/blob/efc36eb08/.circleci/config.yml#L20-L33">strange branch magic is required</a> if you don't want to run both <code>build</code> and <code>deploy</code> targets on <em>every</em> commit.</p> <hr /> <p>Btw, old badges were not that clear of what do they mean:</p> <p><img src="https://ozkriff.games/2017-12-01--devlog/old-badges.png" alt="build: passing, build: passing, passed - wtf?" /></p> <p>Most programmers know that travis's badge usually means Linux/OSX builds and appveyor is for Windows builds. But what does the third one?</p> <p>To fix this <a href="https://github.com/ozkriff/zemeroth/pull/158/commits/1f0fc2b75">I've added custom labels to the badges through shields.io</a>:</p> <pre style="background-color:#2b303b;"> <span style="color:#c0c5ce;">https://img.shields.io/travis/ozkriff/zemeroth/master.svg?label=Linux|OSX https://img.shields.io/appveyor/ci/ozkriff/zemeroth.svg?label=Windows https://img.shields.io/circleci/project/github/ozkriff/zemeroth/master.svg?label=Android </span></pre> <p>Looks a little bit better now:</p> <p><img src="https://ozkriff.games/2017-12-01--devlog/new-badges.png" alt="uniform new badges" /></p> <hr /> <p><em>And there're two yet-to-be-solved issues:</em></p> <ul> <li><em><a href="https://github.com/ozkriff/zemeroth/issues/136"><code>apk</code>s are built in the debug mode</a></em></li> <li><em><a href="https://github.com/ozkriff/zemeroth/issues/161">Deploy precompiled versions of the latest commit to a special release</a></em></li> </ul> <h2 id="decorations-grass-and-blood-pools">Decorations: Grass and Blood Pools</h2> <p>The <a href="https://github.com/ozkriff/zemeroth/issues/73"><strong>Grass</strong></a> is just a randomly-placed decoration, but <a href="https://github.com/ozkriff/zemeroth/issues/42"><strong>Blood Pools</strong></a> are also an additional indicator of a successful attack:</p> <p><img src="https://ozkriff.games/2017-12-01--devlog/grass.png" alt="two tiles of grass" /> <img src="https://ozkriff.games/2017-12-01--devlog/bool-of-blood.png" alt="pool of blood" /></p> <h2 id="jokers-and-strength">Jokers and Strength</h2> <p>Now, some actual gameplay changes!</p> <p>To make Zemeroth a little bit more tactical <a href="https://github.com/ozkriff/zemeroth/issues/59"><strong>Jokers were added</strong></a>. They can be used either as Attacks or Moves.</p> <p>In the previous version, units were dying from a single hit. That doesn't work well with reaction attacks as they were dying too quickly: fighters should have some kind of basic hit points.</p> <p><a href="https://github.com/ozkriff/zemeroth/issues/63">So <strong>Strength</strong> was added.</a></p> <p>This name is stolen from <a href="http://store.steampowered.com/app/237990/The_Banner_Saga">Banner Saga</a>: as I'm going to use this property also as a basic attack modifier. Right now every successful attack deals a damage of one strength but later a much more fine-grained battle math will be implemented.</p> <h2 id="dots">Dots</h2> <p>To show the most important dynamic information about units on the map <a href="https://github.com/ozkriff/zemeroth/issues/95"><strong>&quot;Dots&quot;</strong> were added</a>.</p> <p><img src="https://ozkriff.games/2017-12-01--devlog/info-dots.png" alt="thee agents with different stats showed by color dots" /></p> <p>The current legend is:</p> <ul> <li>&quot;Strength&quot; - green;</li> <li>&quot;Attacks&quot; - red;</li> <li>&quot;Moves&quot; - blue;</li> <li>&quot;Jokers&quot; - purple.</li> </ul> <hr /> <p><a href="https://github.com/LPGhatguy">@LPGhatguy</a> <a href="https://twitter.com/LPGhatguy/status/902800456082001920">pointed me out on twitter</a> to a problem with colors:</p> <blockquote> <p>With the amount of red/green in the game so far, you should try it with a Deuteranopia filter!</p> </blockquote> <p>I've googled a simulator: <a href="https://www.etre.com/tools/colourblindsimulator">etre.com/tools/colourblindsimulator</a>. Here's an example of its output:</p> <p><img src="https://ozkriff.games/2017-12-01--devlog/color-issue.png" alt="Example of output. Dots are hard to read now" /></p> <p>And, yeah, that doesn't look readable at all. <a href="https://github.com/ozkriff/zemeroth/issues/98">It's clear that I should change the colors and shapes</a> in the near future.</p> <p><em>Btw, <a href="http://gameaccessibilityguidelines.com">http://gameaccessibilityguidelines.com</a> is a very interesting resource. I've never thought about a lot of issues raised and explained there.</em></p> <h2 id="info-panel-with-selected-unit-s-stats"><a href="https://github.com/ozkriff/zemeroth/pull/92">Info panel with selected unit's stats</a></h2> <p>Dots can show only a small portion of the dynamic information about units. Other less important dynamic or static information goes into the side panel.</p> <p><img src="https://ozkriff.games/2017-12-01--devlog/info-panel.png" alt="info panel showing imp's stats using text" /></p> <p>Btw, <a href="https://github.com/ozkriff/zemeroth/pull/100">now you can select enemy units</a> to see their move range and stats in the info panel.</p> <p><em>NOTE: additionally, a deselection of any unit on the second click was added.</em></p> <h2 id="spearman"><a href="https://github.com/ozkriff/zemeroth/issues/65">Spearman</a></h2> <p><img src="https://ozkriff.games/2017-12-01--devlog/spearman.png" alt="closeup of a spearman" /></p> <p>Another important gameplay change is an addition of third fighter type: &quot;Spearman&quot;.</p> <p>He has an attack radius of two tiles and can control with reaction attacks a big area of 18 tiles around him.</p> <p><img src="https://ozkriff.games/2017-12-01--devlog/spearman-controls-territory.png" alt="spearman can attack distant enemies" /></p> <p>On the picture above the spearman has only one Joker point: this is not an attack unit, he's almost useless during his own turn.</p> <p>But if spearman hasn't used its Joker during his own turn, he has <em>four</em> reaction attacks during enemy's turn:</p> <p><img src="https://ozkriff.games/2017-12-01--devlog/spearman-many-reaction-attacks.png" alt="example of a spearman with 4 reactive attacks" /></p> <p>And that's a lot considering that reaction attacks can interrupt enemy's movement.</p> <p>Also, this unit has only three Strength points to accent his defence role.</p> <h2 id="rancor-a-stupid-component-system"><a href="https://github.com/ozkriff/zemeroth/issues/141">Rancör</a> - a Stupid Component System</h2> <p>Previously, Zemeroth's units were represented by a single struct holding all the stuff as its fields. Not a very adaptable solutions and it was impossible to create a non-unit type of objects.</p> <p>It's the end of 2017 so the solution to this problem is obviously <em>components</em>.</p> <p>With a component system, I should be able to implement: <a href="https://github.com/ozkriff/zemeroth/issues/142">Boulders</a>, <a href="https://github.com/ozkriff/zemeroth/issues/69">Bombs</a>, Fire, <a href="https://github.com/ozkriff/zemeroth/issues/154">Poison stuff</a>, <a href="https://github.com/ozkriff/zemeroth/issues/108">Corpses</a>, etc.</p> <p>I don't think Zemeroth needs a full-featured ECS solution (like <a href="https://github.com/slide-rs/specs">specs</a>) as the game is turn-based. A bunch of <code>HashMap&lt;ObjId, ComponentType&gt;</code> will do the work fine.</p> <p>So.. I've reinvented another ~~<a href="https://www.reddit.com/r/rust/comments/6zdvza/my_experience_participating_in_highload_cup_re/dmulhzj">bicycle 🚲</a>~~ square wheel! \o/</p> <p><a href="https://github.com/ozkriff/zemeroth/issues/141">Meet <strong>Rancör</strong> - a simple macro-based component system</a>. I'm not calling this an ECS because it has no systems, it's just a storage.</p> <p>Nothing fancy, you just declare some usual structs for components and create a hidden <code>HashMap</code>-based monster-struct using a friendly macro:</p> <pre style="background-color:#2b303b;"> <span style="color:#c0c5ce;">rancor_storage!(Parts&lt;ObjId&gt;: { strength: component::Strength, pos: component::Pos, meta: component::Meta, belongs_to: component::BelongsTo, agent: component::Agent, }); </span></pre> <p>And then use individual fields:</p> <pre style="background-color:#2b303b;"> <span style="color:#c0c5ce;">parts.agent.</span><span style="color:#96b5b4;">insert</span><span style="color:#c0c5ce;">(id, agent); ... </span><span style="color:#b48ead;">let</span><span style="color:#c0c5ce;"> agent = </span><span style="color:#bf616a;">self</span><span style="color:#c0c5ce;">.state.</span><span style="color:#96b5b4;">parts</span><span style="color:#c0c5ce;">().agent.</span><span style="color:#96b5b4;">get</span><span style="color:#c0c5ce;">(id); </span><span style="color:#b48ead;">if</span><span style="color:#c0c5ce;"> agent.moves == Moves(</span><span style="color:#d08770;">0</span><span style="color:#c0c5ce;">) &amp;&amp; agent.jokers == Jokers(</span><span style="color:#d08770;">0</span><span style="color:#c0c5ce;">) { ... } ... parts.agent.</span><span style="color:#96b5b4;">remove</span><span style="color:#c0c5ce;">(id); </span></pre> <p>Or call <code>parts.remove(id);</code> to completely wipe-out the entity.</p> <hr /> <p>Rancor seems to work fine, but I see two issues:</p> <ul> <li>Too many braces in RON file with prototypes</li> <li><a href="(https://github.com/ozkriff/zemeroth/issues/105#issuecomment-335439037)">Duplication of data between initial values and their base values</a></li> </ul> <p>As I do not expect anyone to use it, this carte lives in the Zemeroth's repo.</p> <p><em>Btw, see <a href="https://gridbugs.org/programming-languages-make-terrible-game-engines">https://gridbugs.org/programming-languages-make-terrible-game-engines</a> and <a href="https://gridbugs.org/modifying-entity-component-system-for-turn-based-games">https://gridbugs.org/modifying-entity-component-system-for-turn-based-games</a> articles about component systems and turn-based games in Rust.</em></p> <h2 id="toml-ron"><a href="https://github.com/ozkriff/zemeroth/pull/67">TOML -&gt; RON</a></h2> <p>Rust community kinda loves TOML, but I'm not a fan of this format. TOML is not <em>that</em> bad, but I find its tables too strange for anything but simple configs.</p> <p>And I've decided to try to use <strong><a href="https://github.com/ron-rs/ron">RON</a></strong> format for Zemeroth.</p> <p><em>(<a href="https://github.com/ron-rs/ron">RON's readme</a> has a pretty good list of reasons of why you may not want to use other formats)</em></p> <p>Thanks to <a href="https://github.com/kvark">@kvark</a> for starting this project originally and thanks to <a href="https://github.com/torkleyy">@torkleyy</a> for resurrecting the project <a href="https://github.com/amethyst/amethyst/pull/269">for Amethyst's needs</a>.</p> <h2 id="boulders-and-rocks">Boulders and Rocks</h2> <p>To make tactics a little bit more interesting and to prototype non-agent objects using Rancör I've <a href="https://github.com/ozkriff/zemeroth/issues/142">added some tile-blocking <strong>Boulders</strong></a>. This is a first non-agent object type in the game.</p> <p>It's a little bit strange that I have different terrain types support for a long time, but not actually using them in the game at all. <a href="https://github.com/ozkriff/zemeroth/pull/164">Meet randomly-placed tiles of <strong>TileType::Rocks</strong> type</a>. You can move through these tiles, but it requires 3 move points and not 1.</p> <p><img src="https://ozkriff.games/2017-12-01--devlog/rocks.png" alt="a map with some boulders and rock tiles" /></p> <p>Rock tiles and boulders work together with blood and grass to make the battlefield look a little bit less boring.</p> <p><em>(Yes, I know that it'll be better to use a different texture for Rocks tiles, not just a darker color)</em></p> <h2 id="logging-log-env-logger"><a href="https://github.com/ozkriff/zemeroth/issues/83">Logging: <code>log</code> &amp; <code>env_logger</code></a></h2> <p>I'm tired of adding a special-cased <code>println</code>s to debug something small and removing them before the commit.</p> <p>As I don't have much experience with slog, I decided to replace <code>println</code>s with a classic <a href="https://docs.rs/env_logger">env_logger</a>. It seems to work, for now, the source code is filled with all kinds of <code>info!</code> and <code>debug!</code> calls. :)</p> <h2 id="hate-examples">Häte: <a href="https://github.com/ozkriff/zemeroth/pull/131">Examples</a></h2> <p>Some news about <a href="https://ozkriff.github.io/2017-08-17--devlog.html#hate2d">my silly game engine</a>.</p> <p>It's important to decouple Häte from Zemeroth. First, Häte was extracted to a separate crate inside the repo. The next step is to separate example/test screens.</p> <p>These screens do nothing game-specific so they belong to the engine.</p> <p>There was a bunch of tasks needed to be solved before extracting the examples:</p> <ul> <li> <p><a href="https://github.com/ozkriff/zemeroth/issues/129">Baked GLSL shaders into Häte's source</a>. They are supposed to be dead-simple &amp; tightly coupled with the engine - what's the point of having them in user's assets dir?</p> </li> <li> <p><a href="https://github.com/ozkriff/zemeroth/issues/130">Baked a default font into Häte's source</a>. I've used the smallest font from this article: <a href="http://oxfordshireweb.com/smallest-file-size-google-web-fonts">http://oxfordshireweb.com/smallest-file-size-google-web-fonts</a>. <code>Karla-Regular.ttf</code> is 17kib only.</p> </li> <li> <p><a href="https://github.com/ozkriff/zemeroth/issues/138"><code>Settings::default</code></a>. Simplified the examples.</p> </li> <li> <p><a href="https://github.com/ozkriff/zemeroth/issues/32">Check assets dir from every <code>fs::load</code> call</a>.</p> </li> </ul> <h2 id="hate-cache-text-textures">Häte: <a href="https://github.com/ozkriff/zemeroth/issues/96">Cache Text Textures</a></h2> <p><a href="https://github.com/ozkriff/zoc">ZoC</a> was almost unusable in debug builds: <a href="https://github.com/ozkriff/zoc/issues/264">it may take more than 10 seconds to start a game on some machines</a> and now I'm trying to keep Zemeroth's debug builds fast enough.</p> <p>One of the common problems is that <a href="https://github.com/redox-os/rusttype">Rusttype</a> is very slow in debug builds, especially on Android. As a text in Häte is rendered by creating a separate texture for every string the simplest solution was to cache these textures.</p> <p>Caching is a little bit sloppy solution, but we have no other choice until <a href="https://github.com/rust-lang/cargo/issues/1359">https://github.com/rust-lang/cargo/issues/1359</a> is implemented.</p> <p><em><strong>NOTE</strong>: Btw, there's a <a href="https://github.com/rust-lang/cargo/issues/1359#issuecomment-329653216">cool hack</a> from <a href="https://github.com/matklad">@matklad</a>, but you have to compile an outdated cargo from his dev-branch.</em></p> <h2 id="game-development-in-rust">&quot;Game Development in Rust&quot;</h2> <p><img src="https://ozkriff.games/2017-12-01--devlog/spb-meetup.jpg" alt="me presenting a talk about zoc and zemeroth on spb meetup" /></p> <p>There was <a href="https://meetup.com/Rust-%D0%B2-%D0%9F%D0%B8%D1%82%D0%B5%D1%80%D0%B5/events/242219775">a local meetup</a> in Saint-Petersburg this September where</p> <ul> <li><a href="https://github.com/not-fl3">@not-fl3</a> talked about his experience as a <a href="https://twitter.com/BringerShar">SHAR</a>'s developer</li> <li><a href="https://github.com/vitvakatu">@vitvakatu</a> talked about <a href="https://github.com/three-rs/three">three-rs</a></li> <li>and I talked about the history of <a href="https://github.com/ozkriff/zoc">ZoC</a> and <a href="https://github.com/ozkriff/zemeroth">Zemeroth</a>.</li> </ul> <p>Everything is in Russian, but here are the links anyway, just in case:</p> <ul> <li><a href="https://www.youtube.com/watch?v=BCsPcsmRhOM">full video</a></li> <li><a href="https://docs.google.com/presentation/d/19-Vc2VOpmB2r42u5arMVdKXfOPzozNjY5drjhbyIw3E">my slides</a></li> </ul> <p><img src="https://ozkriff.games/2017-12-01--devlog/slides-overview.png" alt="overview of the slides" /></p> <p>Thanks to <a href="https://intellij-rust.github.io">JetBrains</a> for hosting the event!</p> <h2 id="short-range-plans">Short-Range Plans</h2> <h3 id="restructuredtext-markdown">RestructuredText -&gt; Markdown</h3> <p>For a long time, I was trying to avoid the use of MD.</p> <p>Mostly <a href="https://eli.thegreenplace.net/2017/restructuredtext-vs-markdown-for-technical-documentation">because MD has no built-in support for extensions and is MD is forever tied to HTML</a>.</p> <p>I was mostly hoping for RST to become popular enough. There was a chance, <a href="https://internals.rust-lang.org/t/rustdoc-restructuredtext-vs-markdown/356">but doc team decided to stay with MD</a> and now Rust community doesn't care about RST at all. :(</p> <p><a href="http://commonmark.org">CommonMark</a> solves the standardization problem to some degree. Though, it's still glued to HTML and is not easily extensible.</p> <p>Anyway, I'm not going to use these documents anywhere except in the web browser, so... <a href="https://github.com/ozkriff/zemeroth/issues/157">I'm going to migrate this blog to some rust blog generator</a> from Pelican. This post is written in MD already.</p> <h3 id="abilities-and-lasting-effects">Abilities and Lasting Effects</h3> <p>A skirmish game is unimaginable without <a href="https://github.com/ozkriff/zemeroth/issues/110">special abilities</a> and some interesting <a href="https://github.com/ozkriff/zemeroth/issues/102">instant</a> and <a href="https://github.com/ozkriff/zemeroth/issues/154">lasting effects</a> of the actions.</p> <p>So, here are some previews of what I'm working right now:</p> <ul> <li><a href="https://youtu.be/Egfyd4VX2YU">https://youtu.be/Egfyd4VX2YU</a> - jump &amp; <a href="https://github.com/ozkriff/zemeroth/issues/102">knockback</a></li> <li><a href="https://youtu.be/TilgaGspTJk">https://youtu.be/TilgaGspTJk</a> - <a href="https://github.com/ozkriff/zemeroth/issues/69">self-explode</a></li> <li><a href="https://youtu.be/Yg38yeno3sE">https://youtu.be/Yg38yeno3sE</a> - <a href="https://github.com/ozkriff/zemeroth/issues/154">poison</a></li> </ul> <hr /> <p><em>Whew! That was the longest piece of text in English that I've ever written O.o.</em></p> <p>That's all for today! :)</p> <p><strong>Discussions</strong>: <a href="https://www.reddit.com/r/rust/comments/7gy3wx/zemeroths_devlog_2_jokers_rancor_blood_and_more/">/r/rust</a>, <a href="https://twitter.com/ozkriff/status/936708540168884224">twitter</a>.</p> ZoC is dead. Long life Zemeroth. Thu, 17 Aug 2017 00:00:00 +0000 https%3A//ozkriff.games/2017-08-17--devlog/ https%3A//ozkriff.games/2017-08-17--devlog/ <p>Soo, yeah, <a href="https://github.com/ozkriff/zoc">Zone of Control</a> project is officially discontinued. Sorry, friends.</p> <p><img src="https://ozkriff.games/2017-08-17--devlog/zed.png" alt="scene from Pulp Fiction" /></p> <p>^ &quot;ZoC's dead, baby. ZoC's dead.&quot;</p> <p>Why have I killed it? The primary reason is classic: I've overestimated my resources/skills and got totally overwhelmed by the scope:</p> <ul> <li> <p>I can't see the finish line and have no idea what exactly I can feature-cut. Strategic mode? Sane UI? Networking? Skeletal animations? Particles? Ships? Aircrafts? Tens of unit types? Oh-oh, I don't believe that ZoC could be really cool without any of these (and some others) features.</p> <p>This situation totally drained all my motivation to continue the project.</p> </li> <li> <p>Slot system (multiple units per tile with fixed positions) is a strange beast.</p> <ol> <li> <p>No idea how to make some friendly user interface: two panels (for friends and enemies) solution is ugly, context menus are not cool either.</p> </li> <li> <p>Slots create problems with visual scale: infantry models are just too small, especially on phone’s screen.</p> </li> </ol> </li> <li> <p><a href="https://ozkriff.games/2017-08-17--devlog/first-person.png">Maybe I should make an FPS? No, that's stupid.</a> Ahem, just joking.</p> </li> </ul> <p>Another reason is that my views on what's important for strategic games have changed in the last several years. Now I prefer <a href="http://keithburgun.net/videogames-are-broken-toys">smaller</a> <a href="http://keithburgun.net/the-default-number-of-players-is-one">single-player</a> games with strong accent on <a href="http://keithburgun.net/minimalism-vs-elegance">emergent complexity</a>.</p> <hr /> <p>So, some farewell screenshots:</p> <p><a href="https://ozkriff.games/2017-08-17--devlog/zoc-screenshot-1.png"><img src="https://ozkriff.games/2017-08-17--devlog/zoc-screenshot-1-preview.png" alt="ZoC gameplay screenshot 1" /></a> <a href="https://ozkriff.games/2017-08-17--devlog/zoc-screenshot-2.png"><img src="https://ozkriff.games/2017-08-17--devlog/zoc-screenshot-2-preview.png" alt="ZoC gameplay screenshot 2" /></a> <a href="https://ozkriff.games/2017-08-17--devlog/zoc-screenshot-3.png"><img src="https://ozkriff.games/2017-08-17--devlog/zoc-screenshot-3-preview.png" alt="blob shadows" /></a></p> <p>...And that it.</p> <p>Goodbye, my old friend Zone of Control.</p> <h1 id="zemeroth">Zemeroth</h1> <p>There’s one great article: <a href="http://makegames.tumblr.com/post/1136623767/finishing-a-game">&quot;Finishing a Game&quot;</a>. I have re-read it a dozen times in the last few years. In the context of ZoC’s fail the most important part of that article is:</p> <blockquote> <p>Rule 14: IF YOU DO QUIT, SCALE DOWN, NOT UP</p> <p>Okay, sometimes it is time to call it quits. Maybe there’s just no way you’ll ever finish, and what you have is too big a mess to cut anything out. Maybe the rest of your team has quit already. My hope in writing this list is to help people avoid this possibility, but hey, maybe you’re just coming off of such a project. And sometimes... shit just happens.</p> <p>If there’s no salvaging it, at least make sure that you scale down your next project. It’s easy to set your sights higher and higher, even as your projects become less and less finished. “My SKILLS are improving! I’m learning from my failure,” is a common excuse. But I think this is why it’s important to treat finishing as a skill, too.</p> </blockquote> <p>Sounds reasonable to me. So I need a new much less ambitious project which still shares some of the ZoC’s core values.</p> <p>I’ve spent May and June - in the heavy existential crisis - ahem, resting and thinking about what can I make.</p> <p>Here’s what I came up with:</p> <ul> <li>Random-based skirmish-level digital tabletop game;</li> <li>Single player only;</li> <li>3-6 fighters under player’s control;</li> <li>Short game session (under an hour) and small unscrollable maps;</li> <li>Simple vector 2d graphics with just 3-5 sprites per unit;</li> <li>Reaction attacks and action’s interruption;</li> <li>Highly dynamic (lots of small unit moves as a side effect of other events);</li> <li>Intentionally stupid and predictable AI;</li> </ul> <p>Something in between of <a href="http://store.steampowered.com/app/237990/The_Banner_Saga">Banner Saga</a>, <a href="https://play.google.com/store/apps/details?id=com.magmafortress.hoplite">Hoplite</a>, <a href="http://store.steampowered.com/app/459680/Auro_A_MonsterBumping_Adventure/">Auro</a> and <a href="http://store.steampowered.com/app/230070/The_Age_of_Decadence/">Age of Decadence</a>.</p> <p>Initial svg mockup (based on <a href="https://ozkriff.games/2017-08-17--devlog/zoc-2d-experiments.png">my old experiments with 2d ZoC</a>):</p> <p><img src="https://ozkriff.games/2017-08-17--devlog/zemeroth-inkscape-mockup.png" alt="inscape mockup" /></p> <hr /> <p>Ok, that was just the plan. What's actually done already?</p> <p>Here's the code: <a href="https://github.com/ozkriff/zemeroth">https://github.com/ozkriff/zemeroth</a></p> <p>Right now Zemeroth looks ~ like this:</p> <p><img src="https://ozkriff.games/2017-08-17--devlog/zemeroth-old-screenshot.png" alt="old Zemeroth's screenshot" /></p> <p>Recent &quot;gameplay&quot; video:</p> <div class="youtube"><iframe frameborder="0" allowfullscreen src="https://www.youtube.com/embed/MVt_UOnmdKI?rel=0&showinfo=0"></iframe></div> <p>What’s implemented:</p> <ul> <li>The cornerstone of the game: reaction attacks and movement interruptions;</li> <li>Basic infantry unit type;</li> <li>Hitpoints;</li> <li>Basic AI: move closer and attack;</li> <li>Some basic UI with text/image buttons and grouping.</li> </ul> <p>Android is supported from the beginning of the development (as I’m reusing ZoC’s codebase):</p> <p><img src="https://ozkriff.games/2017-08-17--devlog/zemeroth-android.png" alt="zemeroth on android photo" /></p> <p>Zemeroth’s architecture is mostly taken from ZoC (minus the networking and multiple game states):</p> <p><img src="https://ozkriff.games/2017-08-17--devlog/data-loop.jpg" alt="data loop" /></p> <p>Scene action system is based on cocos’s one and something I did in dead ZoC’s dev branch:</p> <p><img src="https://ozkriff.games/2017-08-17--devlog/scene-actions.png" alt="example of scene actions" /></p> <p>(<a href="https://docs.rs/piston2d-sprite/0.36.0/sprite/enum.Animation.html">btw, piston has something similar</a>)</p> <h1 id="hate2d">Häte2d</h1> <p>About reusing ZoC’s codebase...</p> <p>I’m a fool who don’t learn anything and totally ignored the third rule from finishing-a-game article:</p> <blockquote> <p>3. DON’T ROLL YOUR OWN TECH IF YOU DON’T HAVE TO</p> </blockquote> <p>Say hello to yet another Rust 2d engine: <a href="https://docs.rs/hate">Häte2d</a> :-D</p> <p>The name is a silly reference to <a href="https://love2d.org">LÖVE2D framework</a> (just in case).</p> <p>NOTE: Häte isn’t a general-purpose game engine (at least right now) and it’s not my goal. Just a simple 2d engine for Zemeroth’s needs.</p> <p>Why haven't I used ggez.rs?</p> <p>Quote from reddit:</p> <blockquote> <p>@pwgen-n1024: have you seen <a href="https://www.reddit.com/r/rust/comments/6mg02o/ggez_a_rust_library_to_create_good_games_easily/">this</a>? its a löve2d clone in rust, it might allow you to save some work.</p> <p>@ozkriff: Granted, I'm well aware of ggez! :-)</p> <p>I'm too lazy to read the docs! NIH syndrome!111 :-D</p> <p>Ahem... It's a cool engine and I recommend it whenever anybody asks me about 2d game engines, but I don't think that ggez's core values match my needs in Zemeroth project:</p> <ul> <li>Ggez tries to mirror Löve as closely as possible but I don't believe that what's good for highly dynamic Lua is equally good for Rust.</li> <li>It seems to me that ggez targets beginners and fast prototype-like projects but I'm going to invest a lot of time into this project.</li> <li>I want the engine to be much more opinionated about UI, scene, etc.</li> <li>Right now ggez uses SDL2 (and it's not easy to replace it with glutin) but I really want to use cargo-apk.</li> </ul> </blockquote> <p>Maybe I was wrong and using geez would be a good idea, <a href="https://www.reddit.com/r/rust/comments/6nri26//dkbqtiu/">see Icefoxen’s answer</a>. But so far working on Häte was fun and we’ll see what happens later.</p> <hr /> <p>That’s all for today :)</p> <p>In case you're wondering, here's full Imgur-devlog which I'm trying to keep updated: <a href="http://imgur.com/a/SMVqO">http://imgur.com/a/SMVqO</a></p> <p><strong>Discussions</strong>: <a href="https://www.reddit.com/r/rust/comments/6uar27/zoc_is_dead_long_life_zemeroth">/r/rust</a>, <a href="https://twitter.com/ozkriff/status/898207059862319104">twitter</a>.</p> This Month in ZoC - 2017.01.24 Tue, 24 Jan 2017 00:00:00 +0000 https%3A//ozkriff.games/2017-01-24--devlog/ https%3A//ozkriff.games/2017-01-24--devlog/ <p>(Repost from <a href="https://users.rust-lang.org/t/this-month-in-zone-of-control/6993">https://users.rust-lang.org/t/this-month-in-zone-of-control/6993</a>)</p> <p>Hi, everyone! :)</p> <p>It has been four months since the first post, sorry. I'm struggling to find enough time for the project plus I was busy with <a href="https://github.com/tomaka/glutin/issues/813">porting glutin to winit</a> for about a month around October.</p> <h1 id="helicopters">Helicopters</h1> <p><a href="https://github.com/ozkriff/zoc/issues/111">https://github.com/ozkriff/zoc/issues/111</a></p> <p><img src="https://ozkriff.games/2017-01-24--devlog/helicopters.png" alt="helicopters" /></p> <ul> <li> <p>Helicopters can fly above any terrain or ground units, but can't capture sectors</p> </li> <li> <p>Most units can't attack helicopters - WeaponType got <code>max_air_distance: Option&lt;i32&gt;;</code> field</p> </li> <li> <p>Helicopters can be seen by enemies even in non-visible tiles</p> </li> <li> <p>Helicopters have a different field of view rules - their FoV have no 'obstacle shadows':</p> <p><img src="https://ozkriff.games/2017-01-24--devlog/air-vs-ground-fov.png" alt="comparison of land and air field of views" /></p> </li> </ul> <p>IDLE animation:</p> <div class="youtube"><iframe frameborder="0" allowfullscreen src="https://www.youtube.com/embed/wj8ldf7sBRc?color=white&rel=0&showinfo=0" ></iframe></div> <p>It's not easy for ground units to catch up with a helicopter :) :</p> <div class="youtube"><iframe frameborder="0" allowfullscreen src="https://www.youtube.com/embed/u5yNCP_1G4M?color=white&rel=0&showinfo=0" ></iframe></div> <p>Haven't got around to implement <a href="https://github.com/ozkriff/zoc/issues/226">AA-guns</a> and <a href="https://github.com/ozkriff/zoc/issues/226">Manpads</a> yet so the main AA-defence for now is just jeep's machinegun.</p> <h1 id="reinforcements">Reinforcements</h1> <p><a href="https://github.com/ozkriff/zoc/issues/208">https://github.com/ozkriff/zoc/issues/208</a></p> <p>Players have no starting forces now - everything is bought in reinforcement sectors for reinforcement points.</p> <p>The upper-left corner displays the amount of reinforcement points that current player has and their per-turn increment:</p> <p><img src="https://ozkriff.games/2017-01-24--devlog/reinforcements.png" alt="Reinforcements" /></p> <p>Reinforcement sectors are marked by two circles in player's color:</p> <p><img src="https://ozkriff.games/2017-01-24--devlog/circle-marks.png" alt="Circle marks" /></p> <p>There's an additional &quot;reinforcements&quot; item in the context menu: when clicked it opens a list of available units:</p> <p><img src="https://ozkriff.games/2017-01-24--devlog/main-context-menu.png" alt="Main context menu" /></p> <p>This opens a list of available units:</p> <p><img src="https://ozkriff.games/2017-01-24--devlog/context-sum-menu.png" alt="Context sub-menu" /></p> <p>There must be enough reinforcement points and enough room for the unit. Units have no move or attack points at their first turn.</p> <p>And, by the way, AI has been taught to buy units too.</p> <h1 id="map-selection">Map selection</h1> <p><a href="https://github.com/ozkriff/zoc/issues/213">https://github.com/ozkriff/zoc/issues/213</a></p> <p>After the implementation of reinforcements it became possible to add map selection.</p> <p>You can change map by clicking on the current map's name in the main menu screen:</p> <p><img src="https://ozkriff.games/2017-01-24--devlog/main-menu.png" alt="Main menu" /></p> <p>It was mostly needed for testing/debugging purposes so most of the maps look like this for now:</p> <p><img src="https://ozkriff.games/2017-01-24--devlog/debug-map.png" alt="Debugging map" /></p> <p>Tests however are in early prototype phase and are not in the repo yet. Right now they use special maps but I intend to implement some ASCII-DSL like the following:</p> <pre style="background-color:#2b303b;"> <span style="color:#c0c5ce;">let map = &quot; ... ... ... ... ... ... ... ... ... ... t.. r.. t.. t.. r.. ..B r.A r.. r.. ..C ... t.. ... ... &quot;; </span></pre> <p>where 't' is a 'trees', 'r' is a road and 'ABC' are positions.</p> <p>Tests work by sending hardcoded commands and waiting for specified events in response. I can't test anything that depends on RNG (attacks mostly) but the movements, FoW, etc are more or less testable. It can't help with errors in visualizer but it makes it easier for me to refactor the Core.</p> <h1 id="auto-deploy-to-github-releases">Auto-deploy to github releases</h1> <p><a href="https://github.com/ozkriff/zoc/pull/246">https://github.com/ozkriff/zoc/pull/246</a></p> <p><a href="https://github.com/Gordon-F">@Gordon-F</a> has implemented auto-deploy of releases for travis and appveyor.</p> <p>Now you can download windows, linux and osx builds for tagged releases here from the <a href="https://github.com/ozkriff/zoc/releases">github releases page</a>.</p> <p>Android is totally different story with all its SDKs/NDKs and is still built and uploaded manually.</p> <h1 id="wreckages">Wreckages</h1> <p><a href="https://github.com/ozkriff/zoc/issues/247">https://github.com/ozkriff/zoc/issues/247</a></p> <p>Now destroyed vehicles leave wreckages.</p> <p><img src="https://ozkriff.games/2017-01-24--devlog/wreckages.png" alt="Wreckages" /></p> <p>They only obstruct movement for now. Later they'll be used by infantry as protective covering.</p> <p>When particle system will be implemented wreckages will emit smoke and fire.</p> <h1 id="towing">Towing</h1> <p><a href="https://github.com/ozkriff/zoc/issues/161">https://github.com/ozkriff/zoc/issues/161</a></p> <p>There're two new items in context menu: &quot;attach&quot; and &quot;detach&quot;.</p> <p>You can't chain attachments or attach WholeTile-sized units.</p> <p>Towing system is mostly important for quick reposition of field guns but it can also help with clearing roads from wrecked vehicles. The latter reason will become more important when partial damage for vehicles gets implemented.</p> <div class="youtube"><iframe frameborder="0" allowfullscreen src="https://www.youtube.com/embed/WEBmAvGUMGU?color=white&rel=0&showinfo=0" ></iframe></div> <h1 id="smoothly-fading-to-alpha-fog-of-war">Smoothly fading to alpha Fog of War</h1> <p><a href="https://github.com/ozkriff/zoc/issues/210">https://github.com/ozkriff/zoc/issues/210</a></p> <div class="youtube"><iframe frameborder="0" allowfullscreen src="https://www.youtube.com/embed/eNwlOO_tTqs?color=white&rel=0&showinfo=0" ></iframe></div> <p>Opening FoW is a very common action so it deserves to be a little more pretty :)</p> <p>It was easy though I had to rework the FoW rendering code to make it use a lot of independently colored scene nodes instead of a single big mesh.</p> <h1 id="fixed-an-old-error-with-units-moving-into-invisible-enemies">Fixed an old error with units moving into invisible enemies</h1> <p><a href="https://github.com/ozkriff/zoc/issues/106">https://github.com/ozkriff/zoc/issues/106</a></p> <p>This change caused some refactorings in the codebase:</p> <ul> <li>Added a new event type: Reveal, similar to ShowUnit but generated by Core itself and not by the filtering system</li> <li>Merge all <code>*State</code> structs and <code>GameState</code> trait into one universal State struct - <a href="https://github.com/ozkriff/zoc/issues/255">#255</a></li> <li>Added a proper FoW layer for air units</li> </ul> <h1 id="other-changes">Other changes</h1> <ul> <li> <p><a href="https://github.com/ozkriff/zoc/issues/159">The short-term roadmap was translated into English and updated</a></p> </li> <li> <p><a href="https://github.com/ozkriff/zoc/issues/205">AI was taught to capture sectors</a></p> <p>AI is still in poor state and crashes once in a while. I need to implement replays to reproduce and fix these errors. It's either AI sometimes issues orders to units that are already dead or there are bugs in the event filtering system.</p> </li> <li> <p><a href="https://github.com/ozkriff/zoc/issues/197">Android memory alignment errors are finally gone</a>, thanks to @not-fl3, @tomaka, @brendanzab and @mhintz.</p> <p><a href="https://github.com/ozkriff/zoc/issues/248">Though android port is still not very stable</a>.</p> </li> <li> <p><a href="https://github.com/ozkriff/zoc/issues/214">Fixed bridge slots count</a>. Now bridges are real strategic points which can be controlled or blocked easily.</p> </li> <li> <p><a href="https://github.com/ozkriff/zoc/issues/220">Do not reduce unit morale if the attack was harmless</a></p> </li> <li> <p>Added &quot;zoom in/out&quot; buttons:</p> <p><img src="https://ozkriff.games/2017-01-24--devlog/zoom-buttons.png" alt="zoom in-out buttons" /></p> <p>because it's simpler than handling multi-touch gestures on android :)</p> </li> </ul> <h1 id="gameplay-screenshots">Gameplay screenshots</h1> <p><img src="https://ozkriff.games/2017-01-24--devlog/gameplay-screenshot-1.png" alt="gameplay screenshot 1" /></p> <p><img src="https://ozkriff.games/2017-01-24--devlog/gameplay-screenshot-2.png" alt="gameplay screenshot 2" /></p> <p><a href="https://twitter.com/ozkriff">@ozkriff on Twitter</a></p> This Month in ZoC - 2016.08.22 Mon, 22 Aug 2016 00:00:00 +0000 https%3A//ozkriff.games/2016-08-22--devlog/ https%3A//ozkriff.games/2016-08-22--devlog/ <p>(Repost from <a href="https://users.rust-lang.org/t/this-month-in-zone-of-control/6993">https://users.rust-lang.org/t/this-month-in-zone-of-control/6993</a>)</p> <p>Hi, comrades! Welcome to the first issue of ZoC's monthly report!</p> <hr /> <p><a href="https://github.com/ozkriff/zoc">ZoC</a> is a turn-based hexagonal strategy game written in Rust.</p> <p>Core game features are:</p> <ul> <li>advanced fog of war</li> <li>slot system (multiple units per tile)</li> <li>reaction fire (xcom-like)</li> <li>morale and suppression</li> </ul> <h1 id="gfx-and-rusttype">GFX and rusttype</h1> <p><a href="https://github.com/ozkriff/zoc/tree/c8b11f4/src/zgl/src">Zgl</a>/<a href="https://github.com/ozkriff/stb-tt-rs">stb_truetype</a> were finally replaced with <a href="https://github.com/gfx-rs/gfx">GFX</a> and <a href="https://github.com/dylanede/rusttype">rusttype</a>, YAY :-D !!1 - <a href="https://github.com/ozkriff/zoc/issues/183">#183</a></p> <h1 id="android">Android</h1> <p>ZoC is now build with <a href="https://github.com/tomaka/android-rs-glue">cargo-apk</a>.</p> <p>There are still some problems with android version though: <a href="https://github.com/ozkriff/zoc/issues/197">https://github.com/ozkriff/zoc/issues/197</a> :(</p> <h1 id="roads">Roads</h1> <p><a href="https://github.com/ozkriff/zoc/issues/152">https://github.com/ozkriff/zoc/issues/152</a></p> <p><img src="https://ozkriff.games/2016-08-22--devlog/simple-road.png" alt="Simple road" /></p> <h1 id="sectors-victory-points-and-game-results-screen">Sectors, victory points and game results screen</h1> <p><a href="https://github.com/ozkriff/zoc/issues/124">https://github.com/ozkriff/zoc/issues/124</a></p> <div class="youtube"><iframe frameborder="0" src="https://www.youtube.com/embed/hI6YmZeuZ3s" ></iframe></div> <p><img src="https://ozkriff.games/2016-08-22--devlog/sectors.png" alt="Sectors" /></p> <h1 id="basic-smoke-screens">Basic smoke screens</h1> <p><a href="https://github.com/ozkriff/zoc/issues/160">https://github.com/ozkriff/zoc/issues/160</a></p> <p><img src="https://ozkriff.games/2016-08-22--devlog/smoke.png" alt="Smoke" /></p> <p><img src="https://ozkriff.games/2016-08-22--devlog/somke-on-water.png" alt="Smoke screen in action" /></p> <div class="youtube"><iframe frameborder="0" allowfullscreen src="https://www.youtube.com/embed/WJHkuWwAb7A?color=white&rel=0&showinfo=0"></iframe></div> <h1 id="water-tiles">Water tiles</h1> <p><a href="https://github.com/ozkriff/zoc/issues/204">https://github.com/ozkriff/zoc/issues/204</a></p> <p><img src="https://ozkriff.games/2016-08-22--devlog/water-tiles.png" alt="Water" /></p> <h1 id="gui-updates">GUI updates</h1> <ul> <li>Replaced unit ids with unit type names</li> <li>Added hit chances</li> <li>Added basic unit info to the upper-left corner of the screen</li> </ul> <p><img src="https://ozkriff.games/2016-08-22--devlog/unit-types.png" alt="unit types" /></p> <p><img src="https://ozkriff.games/2016-08-22--devlog/hit-chances.png" alt="hit chances" /></p> <p><img src="https://ozkriff.games/2016-08-22--devlog/basic-unit-info.png" alt="basic unit info" /></p> <h1 id="fixed-switching-between-normal-and-wireframe-mode-for-buildings">Fixed switching between normal and wireframe mode for buildings</h1> <p><a href="https://github.com/ozkriff/zoc/issues/182">https://github.com/ozkriff/zoc/issues/182</a></p> <p><img src="https://ozkriff.games/2016-08-22--devlog/combined-wireframe-and-normal-buildings.png" alt="combined wireframe and normal buildings" /></p> <h1 id="other-notable-changes">Other notable changes</h1> <ul> <li><a href="https://github.com/ozkriff/zoc/issues/191">Fixed armored units reaction to light reactive fire</a></li> <li><a href="https://github.com/ozkriff/zoc/issues/211">Improved error message about missing assets</a></li> <li><a href="https://github.com/ozkriff/zoc/commit/ac2c7c6">Made MapText fading to alpha smoothly</a></li> <li><a href="https://github.com/ozkriff/zoc/commit/1ee698">Fixed annoying vehicle-in-building pathfinder bug</a></li> <li><a href="https://github.com/ozkriff/zoc/commit/fde38">Added personal independent camera for each human player</a></li> <li><a href="https://github.com/ozkriff/zoc/issues/196">Fixed AI hangup</a></li> </ul> <h1 id="bonus-1-zoc-on-android">Bonus 1: ZoC on android</h1> <p><img src="https://ozkriff.games/2016-08-22--devlog/zoc-on-andoid.jpg" alt="photo" /></p> <h1 id="bonus-2-memoir44-mockup-of-smoke-demo-map">Bonus 2: memoir44-mockup of smoke demo map</h1> <p><img src="https://ozkriff.games/2016-08-22--devlog/memoir44.jpg" alt="photo" /></p> <hr /> <p>Weekly links: <a href="https://users.rust-lang.org/t/whats-everyone-working-on-this-week-31-2016/6747/2">1</a>, <a href="https://www.reddit.com/r/rust/comments/4wob4b/whats_everyone_working_on_this_week_322016/d68pxx4">2</a>, <a href="https://www.reddit.com/r/rust/comments/4xrycf/whats_everyone_working_on_this_week_332016/d6i0d1a">3</a>, <a href="https://www.reddit.com/r/rust/comments/4yzx43/whats_everyone_working_on_this_week_342016/d6rp869">4</a>.</p> <p><a href="https://github.com/ozkriff/zoc">https://github.com/ozkriff/zoc</a>, <a href="https://twitter.com/ozkriff">@ozkriff on Twitter</a></p> Градообразующие объекты Tue, 23 Feb 2016 00:00:00 +0000 https%3A//ozkriff.games/2016-02-23--devlog/ https%3A//ozkriff.games/2016-02-23--devlog/ <p>Показал нескольким знакомым макет, послушал комментарии. Один из повторяющихся - города не выглядят городами, слишком абстрактные, больше похожи на хаотично раскиданные детские кубики.</p> <p>Я об этом не задумывался, моему замыленному взгляду город и так хорошо виден. Даже наоборот, пытался здания раскидать и повернуть как попало, что бы меньше чувствовалась жесткая гексагональная сетка со слотами.</p> <p>По задумке, города (и деревеньки) должны занимать не больше восьми-десяти клеток в радиусе и действительно быть довольно абстрактными - иначе странно будет выглядеть соотношение размеров зданий и техники/человечков. И кое-какая хаотичность в любом случае должна быть, скучные города с улицами ровно под 90 градусов я делать совсем не хочется.</p> <p>Но в то же время города должны выглядеть как цельный многоклеточный объект. Выход вижу в каком-то алгоритме прокладки не влияющих на логику городских улиц и автоматическом визуальном повороте зданий не абы как, а параллельно с улицами.</p> <p>Что бы не запутаться, ввожу разделение: &quot;дорога&quot; - значима для игровой логики и идет строго от центра одной клетки к центру другой, а &quot;улица&quot; - это бутафорское нечто в городских клетках.</p> <p>Около большого здания, наверное, стоит выравнивать мелкие здания относительно него, а не окружающих улиц. Типа, архитектурный ансамбль :) .</p> <p>Если посмотреть на тот же атлас дорог страны, то там от столицы тянутся федеральные трассы, пронизывающие города насквозь:</p> <p><img src="https://ozkriff.games/2016-02-23--devlog/viborg-map.png" alt="карта Выборга с отмеченными главными дорогами" /></p> <p>Вот желтое тут - &quot;дороги&quot;, а белое/серое - &quot;улицы&quot; и дома. Наверное, надо разрешить особую дорогу по городу прокладывать. На этих клетках нельзя дома строить будет, но через нее будут проходить обычные улицы и такая дорога не будет разрывать целостность города.</p> <p>Хммм, еще надо будет научить отряды внутри города двигаться по улицам (визуально, не логически).</p> <p>Надо будет не забыть добавить еще железные дороги - один в один как обычные дороги, только позволят поезду заезжать на клетку. И тропинки в лесу: лес с деревьями, между центрами клеток нарисована небольшая дорога с особой текстурой - по такому лесу техника сможет ехать, но медленно и с плохим обзором.</p> <hr /> <p>Но это так, мысли все. &quot;Реально&quot; в макете не успел все попробовать.</p> <p>Добавил улицы и декоративные заборчики с садами у пары зданий.</p> <p>Здания к улицам повернул &quot;фасадами&quot;.</p> <p>Заводу трубу прилепил, так чуть понятнее что это завод :) .</p> <p><img src="https://ozkriff.games/2016-02-23--devlog/draft-streets-1.png" alt="Макет улиц" /></p> <p><img src="https://ozkriff.games/2016-02-23--devlog/draft-streets-2.png" alt="Макет улиц с другого ракурса" /></p> <p>В таком виде улицы слишком бросаются в глаза для &quot;чисто декоративного&quot; элемента. Возможно, потому что макет довольно беден на детали? В игре можно будет их &quot;запылить&quot; землей по краям, думаю.</p> <p>Еще вопрос, как такое автоматически генерировать можно? Тут-то сетка вручную сделана и довольно хитрожопая:</p> <p><img src="https://ozkriff.games/2016-02-23--devlog/wireframe.png" alt="Сетка макета городских улиц" /></p> <p>Сделал болванку трехклеточного корабля, у этого придется немного поколдавать с путенажодением, что бы он плавно поворачивал и только по широким рекам мог проплывать.</p> <p><img src="https://ozkriff.games/2016-02-23--devlog/updated-draft.png" alt="Рендер макета с вышеописанными изменениями" /></p> <hr /> <p>Чуууточку удалось поковырять код между рисовашками и размышлениями.</p> <p>В рамках подготовки к введению системы слотов удалил костыль с константами номеров узлов сцены (<a href="https://github.com/ozkriff/zoc/issues/154">#154</a>).</p> <p>Долго пытался понять, как мой код ломает погрузку пехоты в грузовик. Потом понял, что оно и раньше не работало. Отлично! :)</p> <p>Потыкал асимметричность тумана войны (<a href="https://github.com/ozkriff/zoc/issues/149">#149</a>), не там все совсем не просто и времени много займет, отложил пока что. Как и отложил задачи о украшении типов-оберток (<a href="https://github.com/ozkriff/zoc/issues/120">#120</a>, <a href="https://github.com/ozkriff/zoc/issues/147">#147</a>), потому что прямой пользы для прототипа от них не так много.</p> <hr /> <p><a href="https://github.com/rust-lang/rust/pull/31123">rust-lang/rust#31123</a> - ураа, проверка сборок под андроидом, лед тронулся! Значит, скоро ситуация со сборкой под андроид должна в лучшую сторону измениться.</p> <hr /> <p>Заглянул тут в <a href="http://store.steampowered.com/app/365560">обзоры</a> Battle of the Bulge в стиме. Я просто в ужасе от того, сколько отрицательных обзоров в &quot;самых полезных&quot;. Какого черта, человеки?! Игра же отличная, просто она отличается от большинства компьютерных стратегий. Идите в ремейки Панзер Дженералс играть, быдлота от мира варгеймов, не портите оценку маленькому шедевру :( .</p> <hr /> <p>Итак, я опять фактически потратил пару дней на макет и размышления. Пора уже заняться реализацией слотов в коде.</p> <hr /> <p>Обсуждение <a href="https://disqus.com/home/discussion/ozkriffgithubio/15e36903ac664d709185e519372aeea4">на Disqus</a>.</p> Чертов макет! Sun, 14 Feb 2016 00:00:00 +0000 https%3A//ozkriff.games/2016-02-14--devlog/ https%3A//ozkriff.games/2016-02-14--devlog/ <p>Ладно, X-Com меня начал потихоньку отпускать и большую часть хотелок по макету получилось набросать.</p> <p>Автоматчик:</p> <p><img src="https://ozkriff.games/2016-02-14--devlog/submachine-gunner.png" alt="автоматчик" /></p> <p>Довольно легко визуально отличить от обычных стрелков должно быть, но на всякий еще сгорбленными их поставил.</p> <p>Закинул в джип еще одного пассажира и подкрутил позы старых:</p> <p><img src="https://ozkriff.games/2016-02-14--devlog/draft-jeep-1.png" alt="пассажиры в джипе" /></p> <p>На средний танк прилепил еще одного танкодесантника сбоку:</p> <p><img src="https://ozkriff.games/2016-02-14--devlog/tankodesant.png" alt="вальяжно-боковой танкодесантник" /></p> <p>С виду, трех еще можно на танк посадить - как раз отряд и будет.</p> <hr /> <p>Так, что тут еще на общем снимке виднеется? Огнеметчик, снайпер, пулеметный рассчет, простенькая средняя закрытая САУ на основе среднего танка. Обновил полевую пушку и ее прицепление к грузовику.</p> <p><img src="https://ozkriff.games/2016-02-14--devlog/big-draft.png" alt="более свежий общий снимок" /></p> <p>На планшете смотрится прилично, солдат всех различить можно.</p> <hr /> <p>Все, считаю &quot;неделю блендера&quot; законченной - толку от дальнейшей проработки макета уже не много, а рисовать я уже устал. Может еще какие-то вещи буду подпиливать в нем, но уже не так целенаправленно.</p> <p>Настало время писать код! Прриступаю к реализации трехслотовой системы! :-D</p> Пришельцы воруют мое время Wed, 10 Feb 2016 00:00:00 +0000 https%3A//ozkriff.games/2016-02-10--devlog/ https%3A//ozkriff.games/2016-02-10--devlog/ <p>Мой план &quot;усилием воли закончить макет за выходные&quot; с грохотом провалился.</p> <p><img src="https://ozkriff.games/2016-02-10--devlog/xcom-sectoid.jpg" alt="Сектоид контроллирует землянина" /></p> <p>(Да, картинка из xcom1, но мне лень искать с новым сектоидом)</p> <p>Внезапно для меня объявился X-COM 2. И внезапно же запустился на моей железяке, хотя все на оптимизации ругаются. Fps, правда, не на высоте совсем.</p> <p>Что могу сказать об игре после пары дней знакомства?</p> <p>Пока в основном положительные эмоции, даже переделанный облик врагов особо не раздражает.</p> <p>Круто, что практически убрали миссии без таймера - хотя люди в половине обзоров и ругаются на таймер, но мне играть стало на порядок интереснее. Тем более, что с новой темой &quot;мы террористы - прибежали, все раздолбали и свалили, пока силы правопорядка не очухались&quot; отлично сочетается.</p> <p>Одна из главных вещей, за которые ругали xcom:eu -что враги ходят по карте группами, которые надо аккуратно уничтожать по одной, и двигаться надо странным образом, что бы случайно не активировать следующую группу. Это же и правда глупо и скучновато было. А теперь у игрока уже не выйдет отсидеться на месте больше двух ходов если ты на месте больше трех-четырех ходов торчишь, то, скорее всего, вообще к цели не успеешь.</p> <p>Я пока вижу один недостаток этого подхода - не та атмосфера, что была в первой части. Тогда солдаты аккуратно прочесывали карту, как, по мнению людей, в реальности охота на прищельцев и происходила бы, а не рвались со всех ног через всю карту. Ну и ладно, меня новая атмосфера вполне устраивает)</p> <p>Немного раздражали несколько нелепые мечи у солдат, но к этому быстро привыкаешь.</p> <p>Еще радует, что гранаты опять можно кидать только по клеткам. Как же много было в прошлой части раздражающих моментов, когда нужно было терпеливо двигать мышку пикель-туда-пиксель-сюда, что бы зацепить всех возможных врагов. Там еще и возможность гранат отскакивать накладывалась на это безобразие. Бррр!</p> <p>В обзорах игру за большое количество ошибок ругают, но у меня всего парочка была. Один из новобранцев был без тела - голова летала сама по себе, пришлось ему костюм поменять туда-сюда в настройках. И один раз планшет, на котором отображается интерфейс взлома, солдат вставил внутрь стены, за которой он прятался, и камера показывала стену. Больше ничего не припоминаю.</p> <p>Вроде мелочь, но мне почему-то очень понравилось - анимации ранений на послемиссионном экране. Как-то компенсирует то, что во время самого тактического боя последствий от ранений почти нет. Плюс, оправдание &quot;они не замечают ранений, потому что адреналин&quot; сразу как-то правдоподобней выглядит - вот же они после боя с ног валятся.</p> <p>Видел отзывы &quot;рандом говно, у меня подряд четыре снайпера промазали при вероятности 80%&quot;. Вот возьми и запиши результаты всех случайностей в игре - уверен, что получится чего-то очень близкое к честному, так что не надо ныть.</p> <p>Еще в отзывах часто мелькает: &quot;солдаты промахиваются в упор, это тупо&quot;. Ну хз, с моим-то обширным опытом промахиваться в упор в Red Orchestra и всяких шутанах, у меня точно нет желания ругать бедных солдат за подобное :) .</p> <p>Из косяков могу еще отметить пикейщиков. Это враги, которые не умеют стрелять, зато быстро бегают и хорошо бьют оглушающими дубинками. Такой появиляется в поле зрения и на следующих ход уже будет атаковать кого-то из твоих солдат. И если твой солдат не будет вырублен первым ударом (а в первую треть игры такое часто случается), то он его сильно ослабит попаданием, что упростит взятие этого солдата под контроль сектоидами. После первой трети игры появляются варианты: снайпера натравить, поставить на его пути своего рукопашника с &quot;автоатакой&quot; по всему пробегающему рядом, взять пикейщика под контроль своими пси-оперативниками, заминировать подходы. После середины игры он обогащает игровой опыт однозначно. Но вначале игры появление этого врага означает, что возможные адекватные варианты поведения игрока сильно суживаются и это вредит игре. Вначале игры выход один - валить этих гадов всем отрядом из всего оружия, как только увидел. Ну или я играть не умею, тоже может быть)))</p> <p>Еще жалко, что за мехов пока играть нельзя, как в xcom:ew. Жду дополнений.</p> <p>Про xcom:eu было много отзывов про оказуаливание, даже сам поначалу не хотел играть, судил по видео с ютуба. Это уже потом, когда меня уговорили попробовать все-таки я понял, что летсплйщики и играли на простом уровне сложности, и там были только ранние этапы игры и действовали они прямолинейно. От того убого и выглядело. Сейчас считаю, что авторы очень даже круто балансируют между хардкорной и казуальной игрой.</p> <p>И да, как всегда считаю, что проходить надо в режиме &quot;железный человек&quot;, без всяких сохранений/загрузок))</p> <p><img src="https://ozkriff.games/2016-02-10--devlog/xcom2-failed-misson-1.jpg" alt="xcom2: неудачная миссия" /></p> <p><img src="https://ozkriff.games/2016-02-10--devlog/xcom2-failed-misson-2.jpg" alt="xcom2: еще более неудачная миссия" /></p> <hr /> <p>Так, ладно, кое-что я все-таки смог заставить себя наклепать.</p> <p>Немного подпиленный легкий танк, самоходка на его основе и болванка джипа:</p> <p><img src="https://ozkriff.games/2016-02-10--devlog/draft-jeep-tank-spg.png" alt="Джип, танк и самоходка" /></p> <p>Новая сетка для солдата, даже кое-какой скелет в него вставил:</p> <p><img src="https://ozkriff.games/2016-02-10--devlog/draft-human-skeleton.png" alt="Болванка человечка" /></p> <p>Долго пытался ему размер подобрать, что бы он в технику влезал, но и виден был. Пока вот на этом остановился.</p> <p>Выдал ему винтовку:</p> <p><img src="https://ozkriff.games/2016-02-10--devlog/rifleman.png" alt="Человечек с винтовкой" /></p> <p>Не удержался и немного деталей джипу добавил (теперь он смотрится слишком детальным, когда рядом с грузовиком стоит) и пассажиров в нем рассадил пейзажно:</p> <p><img src="https://ozkriff.games/2016-02-10--devlog/jeep-with-passengers.png" alt="Джип с пассажирами" /></p> <p>Любой пулеметчик смотрится круче, если может ножку закинуть на что угодно :) .</p> <p>Средний танк с танкодесантником:</p> <p><img src="https://ozkriff.games/2016-02-10--devlog/tankodesant.png" alt="Средний танк с танкодесантником" /></p> <p>Бронетранспортеров на всех не хватит, кому-то придется так к полю боя добираться. Заодно танк целей будет.</p> <hr /> <p>Последнее время в реддите стали мелькать библиотеки шрифтовые, приятно. Раньше думал <a href="https://github.com/PistonDevelopers/truetype">truetype</a> потыкать для замены своих костылей вокруг сишного <a href="https://github.com/nothings/stb/blob/master/stb_truetype.h">stb_truetype</a>, теперь вот еще появился <a href="https://www.reddit.com/r/rust/comments/44btaz/introducing_rusttype_a_pure_rust_alternative_to">RustType</a>. Выглядит вполне прилично (<a href="https://github.com/dylanede/rusttype/blob/6aa3bfa/examples/simple.rs">пример</a>). Хорошо, когда есть из чего выбирать.</p> <hr /> <p>Что же, в связи с xcom-катастрофой переношу цель &quot;закончить с макетом&quot; на конец уже этой недели. Попробую проявиться характер и хоть немного оторвать себя от истребления пришельцев.</p> Первая половина Недели Блендера Fri, 05 Feb 2016 00:00:00 +0000 https%3A//ozkriff.games/2016-02-05--devlog/ https%3A//ozkriff.games/2016-02-05--devlog/ <p>После пары просьб, решил таки <a href="https://github.com/ozkriff/ozkriff.github.io-src/commit/aec640">добавить</a> записям желтушные заголовки. Так их и правда немного проще отличать.</p> <hr /> <p>Набросал <a href="https://github.com/ozkriff/zoc/issues/159">мегазадачу</a> по расширенному прототипу тактического режима. Надеюсь, это немного поможет не разбрасываться на всякие левые дела и просто делать пункт за пунктом.</p> <p>Хотелось бы все это сделать к апрелю, за два месяца. Хе-хе, :-D ну посмотрим, как оно выйдет. Никогда и нигде в сроки не укладывался толком, особенно с таким размытым ТЗ.</p> <hr /> <p>Двери-окна вот зданиям добавил, немного приятнее стало выглядеть, накалякал легкий простенький танк.</p> <p>Деревья кое какие сделал, вместо ворованных. Они не то что бы прям ворованные, но под cc-by-sa, а мне хочется прям свободные-свободные модели в составе игры иметь (<a href="https://github.com/ozkriff/zoc/issues/24">#24</a>).</p> <p><img src="https://ozkriff.games/2016-02-05--devlog/new-scene.png" alt="снимок экрана с новой сценой" /></p> <p>Пробую накидать джип, с ним уже явно становятся видны нестыковки в текущих размерах людей и техники. Что-то надо менять.</p> <p><img src="https://ozkriff.games/2016-02-05--devlog/relative-sizes.png" alt="сравнительные размеры человеков и техники" /></p> <p>Изначально я хотел, что бы в один слот влезало нечто масштаба Т-35 или маус (последние два снизу, ~10 метров).</p> <p>Все-таки предполагалось, что целую клетку будут занимать только огромные здания, заводы там всякие, а техника, если на всю клетку, то тоже должна бы быть сопоставимой с заводом в размерах, мегатанки всякие.</p> <p>Но, как из картинки видно, если придерживаться более-менее реального размера человечков, то они становятся совсем крошечными, если камеру прямо в землю не утыкать.</p> <p>А я такое уже видел в Кодексе Войны и играть в такое очень и очень сложно:</p> <p><img src="https://ozkriff.games/2016-02-05--devlog/fantasy-wars-sizes.jpg" alt="мелкие человечки из Кодекса Войны" /></p> <p>Но просто так взять и увеличить людей я не могу, потому что в игре должны быть джипы, полевые пушки и т.п., где тоже используются модели человечков и, например, джип с увеличенными людьми смотрится как-то так:</p> <p><img src="https://ozkriff.games/2016-02-05--devlog/big-man-small-car.jpg" alt="мужик в детской машинке" /></p> <p>Хмм, вот я, после некоторого размышления, думаю что делать по этому поводу:</p> <p>Придется убирать требование &quot;в слот влезает техника размера т-35/мауса (10м)&quot;, так что в слот максимум помещается техника до 6.5м в длину (без учета всяких торчащих пушек, черт с ними). Увеличиваю людей, допустим, в полтора раза от реальных и увеличиваю технику в обратной пропорции к ее размеру. Т.е. мотоцикл/полевое орудие/джип я увеличиваю ровно как и людей, мелкие танки я увеличиваю уже на меньший процент, средние увеличиваю совсем на чуть чуть, большие танки остаются как есть. А всякие маусы уже в слоты не влезают и занимают сразу целую клетку и черт уж с тем, что они размером с завод будут - еще немножко условностей БОГУ УСЛОВНОСТЕЙ!!^W^W, кхм, в угоду визуальному удобству :).</p> <hr /> <p>Я там в прошлой записи упоминал, что здания с людьми внутри должны будут отображаться разрезанными/сеткой. Пока себе представляю как-то так:</p> <p><img src="https://ozkriff.games/2016-02-05--devlog/wireframe-buildings.png" alt="снимок экрана с сеточными зданиями" /></p> <p>Вопрос, конечно, как это в OpenGL все отображать =. .obj, который пока у меня используется, не умеет хранить просто ребра, ему нужны грани. Менять формат пока не сильно хочется, надо сосредоточиться на прототипе. Есть вариант, в самом блендере, в виде временного хака, какими-нибудь модификаторами сделать вместо набора ребер набор тонких граней.</p> <hr /> <p>Понял, что в блендере как-то жутко глючит выделение объектов. Погуглил, попробовал всякое, в итоге помогло переключение режима выделения с обычного на &quot;Occlusion Query Based Selection&quot;. Странно это все, неприятные мелочи)</p> <hr /> <p>Вышла <a href="https://www.reddit.com/r/gamedev/comments/433hqc">четвертая статья</a> от чувака с космической 6DOF игрой, про распределение времени. Эх, там, судя по всему, о случае когда у тебя нет основной работы и ты просто целыми днями делаешь игру - как не свихнуться от такого и чего-то в итоге все-таки сделать. Не сильно мне совету оттуда подходят) Да и вообще, слабо себе представляю, если честно, как можно решиться уйти с постоянной работы в трушные индюшатники и только этим и жить, брр.</p> <p>Залип тут на гифки в <a href="https://habrahabr.ru/post/276255">хаброзаписи о визуализации потоков в Go</a>, обожаю такие картинки))</p> <p>В /r/rust промелькнул приятный <a href="https://www.reddit.com/r/rust/comments/435572/blog_the_operator_and_try_vs_do/">пост про &quot;try/catch/? vs монады&quot;</a> со срачем в комментариях. Клево, что не все согласились с RFC try/catch/? обсуждения еще идут. Все-таки очень уж частное это решение, в отличие от нормальных монад. Да, с монадами нельзя так просто использовать return, break, continue и т.п. - ну и ладно, пускай функциональщина будет предпочтительней императившины, я совсем не против. В языке и так сильный уклон в эту сторону уже есть.</p> <p>Внезапно <a href="https://github.com/blog/2100-github-pages-now-faster-and-simpler-with-jekyll-3-0">узнал</a>, что блогогенератор Jekyll можно вообще локально не разворачивать, а github pages сами могут из .md исходников .html выплевывать. Как-то совсем мимо моих ушей прошло) Ну да ладно, не буду сломя голову переводить днявку на джекил, уже успел к пеликану более-менее привыкнуть. Да и reStructuredText тут изначально поддерживается, мне он больше по душе.</p> <hr /> <p>Итак, по плану, на этой неделе надо закончить с набросками моделей. Надо бы за выходные несколько видов техники еще допилить, определиться с относительными размерами и, самое сложное, человечка со скелетом и позами с оружием запилить. Ух, ну постараюсь :) .</p> <hr /> <p>Обсуждение <a href="https://disqus.com/home/discussion/ozkriffgithubio/caa3eb6e4d3745878e944d65988df5db">на Disqus</a>.</p> Выходные, размеры, Тарантино и ненависть к людишкам Sun, 31 Jan 2016 00:00:00 +0000 https%3A//ozkriff.games/2016-01-31--devlog/ https%3A//ozkriff.games/2016-01-31--devlog/ <p>Итак, выходные прошли. Толком ничего не сделал, но надо хоть чего-то сюда написать, раз уж опять взялся журнал вести. Так что вот, на :) :</p> <hr /> <p>Переложил журнал из гиста в воскрешенный ozkriff.github.io и столкнулся со сложностями с disqus.</p> <p>Сначала оно вообще не хотело загружаться, <a href="https://github.com/ozkriff/ozkriff.github.io-src/commit/a410487">поправил</a> :) .</p> <p>Потом оно завело для http и https отдельные потоки комментариев, гм =\ .</p> <p>Почитал всякое (типа <a href="https://github.com/barryclark/jekyll-now/issues/165">вот этого</a> или <a href="https://coderabbi.github.io/posts/force-https-with-github-pages">этого</a>). По итогам <a href="https://github.com/ozkriff/ozkriff.github.io-src/commit/183bee">вклячил</a> js-хак с перенаправлением с http на https (хотя при особом желании все равно можно зайти на http).</p> <p>Несколько комментариев к прошлой записи перекинул на https версию. Немного потупил с вытаскиванием CSV из disqus и его правкой - интерфейс у админки disqus не слишком интуитивен. Но само перемещение комментариев прошло просто.</p> <p>Вроде, все более-менее работает, останавливаюсь пока на этом с журналом.</p> <hr /> <p>Поэкспериментировал с геометрией людей, но пристойного ничего пока не вышло. Подумываю сделать их мультяшными. Все-таки игра пошаговая, с клетками - в ней много условностей, а мультяшные персонажи с таким гармоничней смотрятся, тоже ведь визуальные условности.</p> <p>Думал, что ноги надо укоротить и туловище сделать длинным, что бы напоминало человечков с бумажных рисунков. Но в 3D выглядит стремно и совершенно непонятно, как таких уродцев сажать в технику. Похоже, останусь с более-менее обычной человеческой геометрией)</p> <p>Листаю всякие <a href="http://wiki.polycount.com/wiki/Limb_Topology">http://wiki.polycount.com/wiki/Limb_Topology</a> . Ох, все это немного слишком сложно для меня) Да и не то что бы очень надо пока что, все-таки у меня тут пока что довольно набросочные модельки, я даже не пытаюсь какие-то детали изобразить.</p> <hr /> <p><img src="https://ozkriff.games/2016-01-31--devlog/proportions.jpg" alt="схема пропорций" /></p> <p>Одновременно с прикидыванием геометрии людей медитирую над сравнительными размерами техники (человеки же в нее влезать как-то должны). Отталкиваться все-таки буду от техники второй мировой и около того, не смотря на то, что хочу в итоге дизельпанк/постап. Да и такая основа даже более-менее укладывается в <a href="https://ru.wikipedia.org/wiki/%D0%94%D0%B8%D0%B7%D0%B5%D0%BB%D1%8C%D0%BF%D0%B0%D0%BD%D0%BA#.D0.A0.D0.B0.D0.B7.D0.B2.D0.B8.D1.82.D0.B8.D0.B5_.D0.B6.D0.B0.D0.BD.D1.80.D0.B0">Поздний Дизельпанк</a>.</p> <p>Прикольно, кстати, я думал что бронемашины серии БА больше, как и танки Т-70. Хотя и то, и другое - не так уж далеко от грузовиков-автомобилей ушло (в Т-70 две силовых установки от грузовиков обычных, если не ошибаюсь), так что не удивительно.</p> <p>Все со схемы выше должно влезать в слот клетки, даже пятибашенный т35 и маус должны более-менее запихиваться.</p> <p>Вот тут, с блицкриговскими модельками, даже нагляднее размеры чувствуются (хотя не факт, что они тут такие же точные, все-таки Блицкриг не симулятор):</p> <p><img src="https://ozkriff.games/2016-01-31--devlog/blitzjrieg.png" alt="картинка из блицкрига с кучей техники" /></p> <hr /> <p>StopGame выложили <a href="http://www.youtube.com/watch?v=EqwhkOXtrEA">вторую часть Истории Fallout</a> - очень даже приятный обзор первой части. Приятно было за ужином посмотреть, прям ностальгичненько так) Каких-то вещей даже не знал, все-таки я больше во вторую играл в школе.</p> <hr /> <p>Сходил на Омерзительную Восьмерку. Как по мне, отличное кино, старый добрый Тарантина вернулся - Бешеные Псы в антураже старой америки. Но подозреваю, что копать на тему исторической достоверности бессмысленно, гм).</p> <p>Фильм, в общем, отличный, а вот зрителей хотелось поубивать. Что бы так же, с литрами кровищи и кишками на креслах. Давненько в кино уже не были, пол года, наверное. Отвык уже :(</p> <p>Слева уселись две ТП, которые вообще непонятно зачем пошли и весь фильм или откровенно скучали, уткнувшись в телефоны, или болтали о папиках, или взвизгивали &quot;ой боженьки, он что в лицо ее ударил?! женщинуу?!&quot;, &quot;ой, этой у нее мозги на волосах что-ли? фуу, вот больные!&quot;, &quot;ой, негра кровью стошнило что ли?&quot; и т.п. А на титрах громко иронично зааплодировали -&quot;ураа, наконец-то, лучший момент в фильме, зачем только пошли?&quot;. Я вот тоже не знаю зачем они пошли.</p> <p>Спереди сидели какие-то мелкие дурочки, которые громко ржали при каждом &quot;нигер&quot; или еще чем подобным, что по моим представлениям должно вызвать максимум ухмылку. И сидели вконтактике с огромного лопатофона с такой яркостью, что меня аж слепило иногда.</p> <p>Справа сидели два милых гопаря, один из которых все время терял нить &quot;тягомотины&quot; и хотел свалить с сеанса, а другой уговаривал своего дружка остаться и громко, даже не претендуя на шепот, пересказывал сценарий и выдавал свои наивные прогнозы по поводу развития сюжета.</p> <p>В общем, временами было сложно абстрагироваться, такое сильно мешает смотреть атмосферный фильм. Вот бы в кинотеатрах были охранники, которые за превышение громкости выводят из зала, эх.</p> <hr /> <p>Обсуждение <a href="https://disqus.com/home/discussion/ozkriffgithubio/93dfd5b00d8749faad18de13504e6bbc">на Disqus</a>.</p> Несколько моделек и вечная смерть Fri, 29 Jan 2016 00:00:00 +0000 https%3A//ozkriff.games/2016-01-29--devlog/ https%3A//ozkriff.games/2016-01-29--devlog/ <p>Defuz предложил, пока я веду журнал в гисте, пинговать о записях в <a href="https://gitter.im/ozkriff/zoc">https://gitter.im/ozkriff/zoc</a>, что был способ оставлять коменты и узнавать об обновлениях.</p> <hr /> <p>Немного поправил геометрию <a href="https://www.google.ru/search?q=mammoth+tank&amp;tbm=isch">мамонт танка</a>:</p> <p><img src="https://ozkriff.games/2016-01-29--devlog/draft-mammoth-tank.png" alt="Набросок мамонт-танка" /></p> <p>Но сильно возиться с ним не хочется - мне просто нужен какой-то огромный юнит на всю клетку, чтобы не забыть про них совсем)</p> <hr /> <p>С вертолетом тоже пока заканчиваю вот на такой стадии:</p> <p><img src="https://ozkriff.games/2016-01-29--devlog/draft-helicopter.png" alt="Болванка вертолета" /></p> <p>Кстати, на заднем плане, за вертолетом, обрезанные здания виднеются. Примерно так, если что, подумываю рисовать здания в которых кто-то есть.</p> <p>В режиме рендера каркас не рисуется, вообще палки сверху еще должны быть:</p> <p><img src="https://ozkriff.games/2016-01-29--devlog/draft-building.png" alt="Каркасные здания" /></p> <p>(на вписаную и описаную окружности внимание обращать не надо, это просто вспомогательные конструкции для размещения зданий в макете :) )</p> <p>Может еще контуры окон-дверей потом добавлю.</p> <p>В Battle Academy здания с людьми внутри рисуются полупрозрачными, но на деле (для меня, конечно) это очень криво выглядит и ничего не понятно =\ :</p> <p><img src="https://ozkriff.games/2016-01-29--devlog/ba2-buildings.png" alt="Здания в BA2" /></p> <hr /> <p>О, внезапное (эти тоже все обещают &quot;начать вести бложик более постоянно&quot;, хех) обновление в тихом и уютном бложике разработчиков моей любимой Unity of Command:</p> <p><a href="http://unityofcommand.net/blog/2016/01/28/dev-diary-3-are-you-experienced">http://unityofcommand.net/blog/2016/01/28/dev-diary-3-are-you-experienced</a></p> <p>Тут говорится о том, что во второй части игры войска надо будет беречь, потому что они будут переходить из сценария в сценарий. Ну и о тонкостях накопления ими опыта рассказывается.</p> <p>Вот, вроде, это клево и логично, что тебя принуждают не разбрасываться армией просто так. Но что-то в первой части UoC было приятно освобождающее в том, что ты мог пожертвовать чем угодно, лишь бы выполнить боевые задачи в срок. Да и в относительно недавно пройденной мной Battle Academy 2 так же. Эх, теперь, наверное, надо будет над каждым отрядом трястись =\ .</p> <p>В более масштабном Кодексе Войны или даже Битве за Веснот меня необходимость побеждать без потерь сильно раздражала. Тоже интересно, конечно, но там надо было выигрывать почти всегда без потери единого отряда, разве что совсем уж мелочью дешевой жертвовать.</p> <p>С одной стороны, это как-то не слишком реалистично, как по мне, в жизни так не бывает).</p> <p>С другой, это создает прямую связь между сценариями: хорошо играешь -потом побеждать тоже проще, плохо играешь - дальше только сложнее будет. Это занятная метаигра, но не без неприятных нюансов: ты заранее не знаешь, какой процент потерь допустим, так что если есть возможность переиграть сценарий, то лично я обычно переигрываю до тех пор, пока не пройду практически без потерь, а то мало ли что в следующих сценариях меня ждет? Это несколько вытягивает удовольствие из игры. Даже виноватым себя чувствовал, если начинал новый сценарий без идеального прохождения прошлого.</p> <p>Лично моим любимым решением этой сложности является перманентная смерть (когда сохранение только одно и только автоматическое), как в новом X-COM, например. У тебя просто нет возможности переигрывать сценарии, так что из-за этого совесть не мучает и просто стараешься аккуратно играть, лишний раз не подставляя ценных ветеранов под риск.</p> <p>Ладно, посмотрим как тут сделают, может пермадез будет, может условия выигрыша в сцерании будут оговаривать какой-то допустимый процент потерь, или в каждом новом сценарии будут выдавать большое количество &quot;казеных&quot; отрядов, или еще что такое :) .</p> <hr /> <p>Обсуждение <a href="https://disqus.com/home/discussion/ozkriffgithubio/0a30d487068244d88426fd724b62fca1">на Disqus</a>.</p> Очередной перезапуск Thu, 28 Jan 2016 00:00:00 +0000 https%3A//ozkriff.games/2016-01-28--devlog/ https%3A//ozkriff.games/2016-01-28--devlog/ <p>Моя последняя попытка вести нормальный журнал <a href="https://github.com/ozkriff/ozkriff.github.io-src/blob/master/content/2015-11-30--devlog-live-again.rst">провалилась</a> :) .</p> <p>Времени жрет дикое количество. Не умею я, как некоторые люди могут, за пол часа накатать красивую страницу текста :( . После того поста вел каждодневные записи в файлике, что я по проекту делаю, что бы потом из них пост слепить. Через месяц, под новый год таки попробовал - просидел три вечера за этим занятием, задолбался и решил что обойдусь без блога)</p> <p>Так что попробую теперь вести хоть какой-то журнал, в виде маленьких слабо-организованных записей. Как я себе в файлик писал, вот так же - каждый день, если хоть чего-то делал про Зоку, писать что делал, как прошло и какие у меня мысли вообще возникают. Авось кому-нибудь да и будет интересно полистать. Ну и мне потом, наверное, забавно перечитать когда-нибудь будет и вспомнить, какой я был дурной)</p> <p>Собственно, это первая запись :) . Хотя думаю, добавлю пару записей задним числом из недавних разговоров - про тот же план работ.</p> <p>Для начала пускай это дело просто в gist'е живет - каждый день новый файлик. Лениво с полноценным блогом для такого заморачиваться.</p> <hr /> <p>Заготовка вертолета, гм:</p> <p><img src="https://ozkriff.games/2016-01-28--devlog/draft_helicoper.png" alt="Заготовка вертолета" /></p> <hr /> <p>В фоне потихоньку вожусь с удалением констант с индексами из кода сцены (<a href="https://github.com/ozkriff/zoc/issues/154">#154</a>). Сами константы удалил, теперь все получается динамически, но при движении отрядов или переходе хода оно падает. Надо искать, что я там напутал)</p> Мастерплан и мотивация Wed, 27 Jan 2016 00:00:00 +0000 https%3A//ozkriff.games/2016-01-27--devlog/ https%3A//ozkriff.games/2016-01-27--devlog/ <p>Знакомый скинул ссылку на вполне себе интересную <a href="https://www.reddit.com/r/gamedev/comments/426148">серию статей в реддите</a>.</p> <p>Хм, ну базовый цикл у меня близок к цивилизации - &quot;Select unit, move unit, combat/gather, repeat.&quot; у меня тоже ты &quot;выбираешь отряд, двигаешь/атакуешь/используешь навык, заново&quot;.</p> <p>прототип - я большую часть механики беру из игры Battle Academy, так что она уже служит начальным прототипом) Плюс, я вот сейчас &quot;отыгрываю&quot; игру в блендере на макете игры. Туман войны так не симулируешь, а вот базовую логику сражений - вполне. Так-то у меня само приложение сейчас и в ближайшее время, как по нему и видно, на стадии прототипа -практически никакого интерфейса, эффектов, анимацией и т.п только игровая логика, всплывающие текстовые надписи и бааазовая визуализация.</p> <p>как оно сейчас есть оно мне нравилось более-менее, но при попытке сделать карту побольше я понял, что города выглядят страшно криво и бесят меня вот и задумался над переделкой механики - в итоге увеличил клетки</p> <p>Те же технические моменты, типа перехода на glium, я на потом откладываю. Собственно, главное что бы оно на андроиде работало и я мог проверять игру на планшете - в первую очередь для тыкалок же делается.</p> <p>И да, все это - тактический режим, поверх которого должен быть еще стратегический с глобальной картой. Но с стратегическим я пока решил не запариваться сильно, потому что тактический должен быть цельной игрой сам по себе.</p> <p>Стратегический в итоге должен как-то так выглядеть:</p> <p><img src="https://ozkriff.games/2016-01-27--devlog/wargame-strategic-mode-example.jpg" alt="Образец для стратегического режима" /></p> <p>и определять контекст для тактических сражений.</p> <hr /> <p>перехожу ко второй статье)</p> <p>вчера утром знакомому уже писал свой план на ближайший месяц-два</p> <p>сделать в блендере модельки-прототипы базовых видов солдат-техники, затем изменить код игры, что бы оно поддерживало три слота, вклячить в игру здания и дороги, затем вклячить новые виды юнитов с базовой математикой боя для них и добавить условия победы в режиме хотсит. Что бы в итоге в это можно было играть полноценно.</p> <p>Предполагается, что это все где-то на месяц. Хочу сосредоточиться на получении чего-то играбельного, пускай и технически убогого и вообще схематического.</p> <p>Когда это сделаю, тогда в планах сначала переход на glium, затем сетевая игра.</p> <p>А дальше план уже более размытый: добавить редактор карт, загрузки-сохранения, кое-какие спецэффекты довести тактический режим до вида &quot;не очень стыдно показать обычному знакомому, который играет в игры, но в их производстве вообще ничего не понимает&quot; и потом начать работать над стратегическим режимом.</p> <p>Точное время на задачи я даже не буду пытаться прикинуть, все равно долго выйдет. Думаю категориями &quot;вот до такой стадии было бы неплохо добраться через два месяца, это еще через месяц-другой&quot;.</p> <p>&quot;Are you disciplined enough to stay 100% productive over that amount of time?&quot; -гм, 100% буду время от времени забрасывать к чертям проект на неделю-другую как на новый год) а то так с ума сойдешь) но даже в такие перерывы я где-то в фоне все равно продолжаю думать на зоком, так что уверен, что сам проект не брошу.</p> <p>Да, наверное стоит создать суперзадачу на гитхабе &quot;Закончить прототип тактического режима&quot; с более-менее детальным списком дел в масштабе день-неделя. Постепенное проставление галочек и правда должно мотивировать, я люблю такие штуки))</p> <hr /> <p>Перехожу к третьей части, про мотивацию - важная штука)</p> <p>у меня один из способов мотивировать себя - написание всего этого дела на ржавчине) все-таки интересный язык сам по себе. клево с ним разбираться, но и времени на это уходит сильно больше, чем если бы я просто на плюсах написал то же самое, даже свой простенький графический движок. Но мне так не хочется еще и в свободное время пачкать руки в плюсах))</p> <p>Хм, у меня, наверное, два больших источника вдохновения - это стратегические игры, типа Unity of Command, Battle of the Bulge, В Тылу Врага, Close Combat, Uniwar и т.п. Когда дело ну вообще никак не идет, то я хотя бы на вечер забиваю на zoc совсем и сажусь как следует в чего-нибудь стратегическое поиграть. В процессе почти всегда появляются мысли вроде &quot;черт, сюда бы такую-то возможность добавить, вот было бы круто&quot;)</p> <p>И еще схемки - или нарисованные на бумаге</p> <p><img src="https://ozkriff.games/2016-01-27--devlog/2d-zoc-abstract-cities.jpg" alt="Набросок 2д варианта с абстрактными городами" /></p> <p><img src="https://ozkriff.games/2016-01-27--devlog/2d-zoc-draft-one-tile-buildings.png" alt="Набросок 2д варианта с конкретными одноклеточными зданиями" /></p> <p>в таком духе, я их мноооого рисую когда думаю)</p> <p>или макеты в блендере, как вот который сейчас делаю потихоньку</p> <p><img src="https://ozkriff.games/2016-01-27--devlog/blender_mockup.png" alt="Блендерный макет" /></p> <p>Смотришь на это дело и сразу представляешь, как было бы клево, если бы оно могло &quot;ожить&quot;. Что бы вон та артиллерия могла дать залп дымовыми перед вражеским городом, эта пехота забраться в броневики и ломануться навстречу, а вон те танки в это время при поддержке вертолетов зашли в бок и подавили бы с расстояния часть сил врага и блаблабла))</p> Форы Tue, 26 Jan 2016 00:00:00 +0000 https%3A//ozkriff.games/2016-01-26--devlog/ https%3A//ozkriff.games/2016-01-26--devlog/ <p>Недавно тут наткнулся на <a href="http://www.progamer.ru/dev/handicaps.htm">статью про гандикапы</a>.</p> <p>Может для сетевого режима ЗК замена обычных рейтингов на уменьшающиеся при победах гандикапы (форы) и не такая глупая идея. Все-таки вполне себе способ повысить интерес при игре с сильно отличающимся по уровню игры противником.</p> <p>Например, банально давать меньше стартовых очков. Тогда и рейтинг можно упразднить, вместо него использовать размер гандикапа). Типа, когда начинаешь играть, твой рейтинггандикап - 200%. Т.е. у тебя, допустим, 200% стартовых очков, а у топовых игроков будет рейтинггандикап в 60% или типа того. Правда тупо менять количество стартовых очков - слишком дуболомное решение, надо чего-то более хитрое придумать.</p> <p>Для игры со знакомыми можно просто договориться и не тратить все очки или еще какое условие поставить, но это как-то &quot;не круто&quot;. Пробовал много раз так делать со знакомыми, но, обычно, весело не было. Появляется какое-то чувство кустарности, которое меня порядочно нервирует. Еще вручную за договоренностями бывает сложно следить. Точно помню пару раз, как я &quot;ой, так у меня же полторы тыщи очков, чего я туплю? Вооот, тут покупаю крейсер и он всех выносит, бббабах! ..ой, черт&quot;. Ну и интересный домашний гандикап еще надо придумать, что бы игра не поломалась как система.</p> <p>Надо посмотреть, как это дело в более традиционном спорте используется. В Go вон вообще всякой хитроты <a href="https://ru.wikipedia.org/wiki/%D0%A4%D0%BE%D1%80%D0%B0#.D0.A4.D0.BE.D1.80.D0.B0_.D0.B2_.D0.B3.D0.BE">понапридумывали</a>.</p> <p>Подумал-подумал и пока решил, что если и планировать такое, то только в виде параллельного обычному рейтинговому топа, в порядке эксперимента, а то слишком уж тут много тонкостей у этого подхода.</p> <p>Но это так, мысли про далекое будущее все :) .</p> Сложности с crates.io и конфиги из открытого космоса Mon, 25 Jan 2016 00:00:00 +0000 https%3A//ozkriff.games/2016-01-25--devlog/ https%3A//ozkriff.games/2016-01-25--devlog/ <p>Сунулся наконец-то выложить zoc на crates.io. А, оказывается, даже если пакеты лежат в одном репозитории, их надо выкладывать на crates.io отдельно.</p> <p>Посмотрел gfx - они тоже каждый пакет, оказывается, отдельно выкладывают :( . Эх, совсем не хочется загаживать crates.io своими бессмысленными пакетами, они явно никому не пригодятся.</p> <p>Можно бы на модули разбить, а не пакеты, но так инкрементальная сборка будет опять занимать минуту и сложности с привязками к OpenGL возникают.</p> <p>Нафиг тогда выкладывание на crates.io, пока на glium не перейду. Мне не так сильно этот crates.io и нужен, просто немного неприятно, что про твой код забывают при проверке всяких поломок при обновлениях библиотек. Ну да ничего, пару месяцев уж потерплю.</p> <hr /> <p>Возился в связи с этим с Cargo.toml и Cargo.lock. Хоспади, ну все-таки как мне не нравится этот TOML. =(</p> <p>Он в некоторых случаях и правда неплохо справляется, но при работе с ним все время чувство костылей есть. Как-то у него фокус на частности, а не на нормальное обобщенное решение. В целом ничего формат, особенно для простых конфигов, но вот синтаксис таблиц меня ужасает.</p> Перезапуск журнала Mon, 30 Nov 2015 00:00:00 +0000 https%3A//ozkriff.games/2015-11-30--devlog-live-again/ https%3A//ozkriff.games/2015-11-30--devlog-live-again/ <p>Насмотрелся я тут на журналы <a href="http://reangdblog.blogspot.com">reangd</a>, <a href="http://www.gridsagegames.com/blog">cogmind</a>, <a href="https://eao197.blogspot.ru">eao197</a> и всякие другие, решил что тоже чего-нибудь хочу писать. С последней моей попытки прошло около полутора лет)</p> <p>Итак, на момент написания прошлой заметки я работал над Миром Кораблей в <a href="https://wargaming.com/ru/about/our-locations/saint-petersburg">питерском wargaming.net</a>. Собственно, я успел уйти оттуда, поработать над казуалками в <a href="http://zillionwhales.ru">Zillion Whales</a>, оттуда тоже уйти и осесть в <a href="http://protei.ru">Протее</a>. Так что сейчас я ковыряю ip-телефонию и все игры теперь только в свободное время, зато не надо каждый день &quot;любоваться&quot; на ужасы фритуплея)</p> <p>Я больше не студент, совсем - наконец-то закончил заочку в политехе, ура-ура! :-D Темой диплома как раз и был этот проект, даже <a href="https://ozkriff.games/2015-11-30--devlog-live-again/lesnikov_a_a_slides_2015.pdf">презентация</a> вот завалялась. Хотя ничего особо крутого, как мне изначально хотелось, на деле не вышло. Ключевым моментом диплома являлся ИИ. Я там подробно расписал какие они бывают и какие виды подходят для каких игр. А вот реализовать полноценный не успел - сдавался вариант, который только формально можно было назвать &quot;практичным ИИ&quot; (извиняюсь, но лучшего перевода для &quot;utility-based AI&quot; не нашел. &quot;ИИ, основанный на теории полезности&quot; как-то длинновато). Он примерял к текущему состоянию игры захардкоженные шаблоны на основе позиций и типов отрядов, оценивал коэффециент их полезности, и втупую применял их. На специально подготовленных ситуациях выглядело не так и плохо, но это отмазочный вариант, конечно. И с очень стремным кодом, так что в git'е сейчас так и лежит базовый &quot;ИИ&quot; - подъехать в на расстояние выстрела и стрелять :-| . Но общий обыт был интересным)</p> <p>Сама ржавчина, конечно, за это время сильно выросла, с 0.10 аж до 1.4. Вместо извращений по установке зависимостей или возни с git submodules, появился cargo. По достижении 1.0 появилась обратная совместимость. Хотя конкретно от этого я и не в полном восторге, руки у авторов языка теперь &quot;полусвязаны&quot;, но переписываний и правда стало меньше, только когда библиотеки чего-то ломают. Да и с этим Cargo.lock очень помогает. Хотя, я уже месяца полтора его не обновлял - ух и сложный же следующий <code>cargo update</code> у меня будет.</p> <hr /> <p>За полтора года я успел переиграть много во что повлияевшего на мое видение пошаговых стратегий, например:</p> <ul> <li> <p>малоизвестная <a href="https://store.steampowered.com/app/306640">Battle Academy 2</a> из которой я решил фактически передрать ядро механики для тактического режима :) - взаимодействие видов войск, быстрое/осторожное передвижение, хитрая видимость, реакционный огонь, боевой дух/подавление и т.п.;</p> </li> <li> <p>чуть более известная <a href="https://store.steampowered.com/app/218090">Unity of Command</a> повлияла на мое видение стратегического режима - хитрая система линий снабжения, механика окружений и т.п.;</p> </li> <li> <p>мобильная <a href="https://play.google.com/store/apps/details?id=android.uniwar">Uniwar</a> - классная система параллельных сетевых игр, а сама по себе игровая механика напоминает, что шестигранникам минимализм никогда не помешает;</p> </li> <li> <p>серия Wargame, а именно <a href="https://store.steampowered.com/app/222750">W:AB</a> и <a href="https://store.steampowered.com/app/251060">W:RD</a> - одна из немногих стратегий в реальном времени, в которую я с удовольствием поиграл за долгое время. Интересна своим балансом между реализмом/&quot;веселостью&quot; и взаимодействием между разными видами войск.</p> </li> </ul> <p>Много думал про пошаговые игры без клеток, все-таки у клеток много недостатков/особенностей. Даже немного экспериментировал - сделал простенькое путенахождение по вручную размеченной навигационной сетке:</p> <p><img src="https://ozkriff.games/2015-11-30--devlog-live-again/2015-07-30--manual-navmesh-simple-pathfinding.png" alt="Пример простого путенахождения на вручную размеченной сетке" /></p> <p>Путь проложен по центрам треугольников, для оптимизации потом хотел прикрутить <a href="http://digestingduck.blogspot.ru/2010/03/simple-stupid-funnel-algorithm.html">funnel algorithm</a>, но до этого этапа не дошло. Если что, шестигранники тут уже ничего не значат, просто на основе работающего прилжожения экспериментировал. Затем, написал простенький &quot;наращиватель&quot; препятствий, который в зависимости от величины угла добавлял разное количество вспомогательных отрезков:</p> <p><img src="https://ozkriff.games/2015-11-30--devlog-live-again/2015-08-02--obstacle-grow.png" alt="Пример нарощенного препятствия" /></p> <p>Предполагалось, что все юниты будут поделены на несколько групп по размерам и для каждой группы будет поддерживаться своя сетка. Непосредственно преобразованием массива таких &quot;жирных&quot; препятствий в сетку должен был заниматься триангулятор. Мне большего всего приглянулся плюсовый <a href="https://code.google.com/p/poly2tri">poly2tri</a>:</p> <p><img src="https://ozkriff.games/2015-11-30--devlog-live-again/2015-08-11--triangulation-cpp-demo.png" alt="Всякие стандартные примеры из poly2tri" /></p> <p>Даже пытался портировать его на ржавчину, но там очень стремная работа с памятью, очень хреново укладывается в модель ржавчины. Пробовал переделать плюсовую версию на работу с массивами и индексами, но потом решил что очень уж много на эксперимент уходит времени, энтузиазм про бесклеточные игры прошел, так что я совсем забросил попытку.</p> <p>Ну да ладно, темы вдохновляющих игр, разных видов клеток и непрерывного пространства достойны отдельных заметок, а эта запись и так большой получается.</p> <hr /> <p>Теперь, наконец-то, что касается самого проекта.</p> <p>Прежде всего, он переименован из Марoдера в Зону Контроля (Zone of Control). Сокращенно - ЗК/ZoC. Гитхабовское хранилище переехало в <a href="https://github.com/ozkriff/zoc">https://github.com/ozkriff/zoc</a>.</p> <p>Внешний вид с момента сдачи диплома изменился слабо и выглядит все это безобразие сейчас как-то так:</p> <div class="youtube"><iframe frameborder="0" allowfullscreen src="https://www.youtube.com/embed/srJAfngSwxk?color=white&rel=0&showinfo=0" ></iframe></div> <p>Собственно, да, я портировал это на android, хотя под линуксом и виндой тоже должно работать. Спасибо Skligus'y за его <a href="https://github.com/skligys/rusty-cardboard">rusty-cardboard</a>, очень помогло поначалу, и Tomaka за его <a href="https://github.com/tomaka/glutin">glutin</a> и <a href="https://github.com/tomaka/android-rs-glue">android-rs-glue</a>. К сожалению, для сборки под андроид требуется ночная сборка rustc, потому что в android-rs-glue используются какие-то нестабильные штуки. Хотя надо перепроверить, может уже и стабильного компилятора хватит - ржавчина так быстро развивается :).</p> <p>Кстати, да, переписал с glfw-rs на <a href="https://github.com/tomaka/glutin">glutin</a> - чем больше кода на ржавчине, тем прощe, особенно при сборке на разных платформах. Еще хотел со своих <a href="https://github.com/ozkriff/zoc/tree/47e8f0/src/zgl/src">костылей вокруг OpenGL</a> перейти на <a href="https://github.com/tomaka/glium">glium</a>, но пока не осилил.</p> <p>Переделал с выделения через цветовой буфер на чистую математику - пересечение луча из курсора с плоскостью карты, бла бла блап. Уж очень много от времени отрисоки кадра оно сжирало, да и с шейдерами так меньше хлопот.</p> <p>Но это все про техническую часть. Что касается самой игры, то:</p> <ul> <li>два захардкоженых режима на одной карте с одним набором войск - против тупого ИИ или хотсит на двух игроков;</li> <li>от одного до пяти членов отряда в клетке -отказался от идеи иметь несколько отрядов в слотах одной клетки, потому что так и не придумал, как это все нормально отображать и как этим управлять. Хотя, при введении зданий и летающих отрядов, наверное, придется тут усложнить ситуацию;</li> <li>до двух активных очков атаки для стрельбы по прямому приказу игрока;</li> <li>одно пассивное очко атаки для реакционного огня в чужой ход (как в x-com) + неиспользованные в свой ход активные очки атаки становятся пассивными;</li> <li>вероятность поражения с (пока что) захардкожеными вероятностями попадания в зависимости от типа атакующего, защищающегося и местности;</li> <li>кривоватый туман войны, который впоследствии, видимо, будут переведен на менее дискретный алгоритм;</li> <li>заготовка системы боевого духа и подавления - каждый ход восстанавливается 10 очков морали, за каждую атаку снимается по 10, если мораль падает ниже половины - отряд не может стрелять;</li> <li>разная стоимость движения по местности для разных отрядов;</li> <li>два режима передвижения - быстрый и осторожный, который стоит в два раза дороже, зато не накладывает штрафы на точность при стрельбе и при попадании под огонь отряд не лишается оставшихся очков движения;</li> <li>тестовый грузовик для транспортировки пехоты;</li> <li>механика видимости из BA2 с двумя радиусами - &quot;нормальная&quot; и &quot;отличная&quot; видимость. Последняя позволяет увидеть скрытые юниты (например, пехоту в лесу);</li> <li>атаки из засад, если атакующий изначально невидим, с бонусом к атаке и шансом не раскрыть свою позицию;</li> <li>приказ &quot;не стрелять&quot; для отключения реакционного огня при организации хитрых засад или для разведчиков;</li> <li>пока что только четыре вида отрядов: <ul> <li>пехота - четыре человека, одна клетка отличной видимости, умеют тихориться в лесу;</li> <li>разведчики - как пехота, только всего 2 человека, зато видят и бегают немного быстрее;</li> <li>танк - громко стреляет и толсто бронирован, зато у него вообще нет отличной видимости (попробуй что через щели в броне рассмотреть) - без пехотного прикрытия рядом с лесом ему ездить не стоит;</li> <li>грузовик - не умеет стрелять, очень хрупкий и подслеповатый, зато быстрее всех остальных отрядов и может перевозить пехоту;</li> </ul> </li> </ul> <p>Ну, вот как-то так. Разработка, как видно, сильно <a href="http://mysweetwhomp.fr/private/119228173847/tumblr_noimn4cVks1u4yjir">затянулась</a> - - я-то хотел такое уже через пару месяцев иметь, ха! То ли мне просто лень, то ли времени и правда мало получается выделять, черт его знает. Уже мнооого раз полностью терял весь энтузиазм и забрасывал игру на пару месяев, даже пытался чего-то другое делать. Но потом возвращался, что бы все-таки надо довести до ума эту чертову ЗК :) . Да и вышеупомянутые игры сильно помогали с вдохновением)</p> <p>Вот, собственно, вся первая запись. Вряд ли я буду теперь пытаться делать недельные отчеты, скорее буду писать более мелкие заметки по настроению - регулярность вытягивает из любого дела весь интерес. Ну и писать тут буду, наверное, не только по делу - смотрите теги :) .</p> Разработка Мародера - 2014.05.18 Sun, 18 May 2014 00:00:00 +0000 https%3A//ozkriff.games/2014-05-18--devlog-marauder-012/ https%3A//ozkriff.games/2014-05-18--devlog-marauder-012/ <p>Почти дорисовал базового человечка, так лениво :) .</p> <p>Разработчики Ржавчины мутят чего-то страшное. Хотят убрать <code>mut</code>, иммутабельность. Бррр!</p> Разработка Мародера - 2014.05.11 Mon, 12 May 2014 00:00:00 +0000 https%3A//ozkriff.games/2014-05-12--devlog-marauder-011/ https%3A//ozkriff.games/2014-05-12--devlog-marauder-011/ <p>Тревис все так и сломан.</p> <p>Потратил кучу времени, пока искал <code>![macro_export]</code> и тупил вокруг))</p> <p>Запил <code>MeshId</code> структурку, наконец-то.</p> <p>С горем пополам допилил error_context, выложил как отдельную библиотеку на гитхабе и использовал в мародере. И после отзывов переписал ее к чертям))</p> <p>Сделал кое-какие кнопки. Криво, но работает. Тестовая кнопка - &quot;конец хода&quot;.</p> <p>Перевел свои библиотечки и библиотеки bjz на rustc от rust-lang.org</p> Разработка Мародера - 2014.05.04 Mon, 05 May 2014 00:00:00 +0000 https%3A//ozkriff.games/2014-05-05--devlog-marauder-010/ https%3A//ozkriff.games/2014-05-05--devlog-marauder-010/ <p>Трэвис сломался и все никак не чинится. Все протухло :( .</p> <p>Почти добил <code>ErrorContext</code>. Перенес на <code>local_data</code>.</p> <p>Заменил все <code>type = ...</code>, которые можно, на структуры.</p> Разработка Мародера - 2014.04.27 Mon, 28 Apr 2014 00:00:00 +0000 https%3A//ozkriff.games/2014-04-28--devlog-marauder-009/ https%3A//ozkriff.games/2014-04-28--devlog-marauder-009/ <p>Меня поплющило пару дней на тему перехода с 3д моделей на 2д маркеры.</p> <p>Заменил везде <code>&amp;str</code> на <code>Path</code>, так правильней (ссылка на битсквидблог).</p> <p>Заменил структурки <code>struct(MInt)</code> на <code>struct(id: MInt}</code>.</p> <p>Шейдеры с 1.5 на 1.2, что бы можно было запускаться на OpenGL 2.1 без проблем.</p> <p>Перенес исходники в <code>src</code> директорию, а всякое для работы в <code>bin</code> директорию. Добавил в Makefile команду <code>run</code>, которая переходит в <code>bin</code> и запускает игру.</p> <p>Поправил систему слотов.</p> <p>Убрал <code>MBool</code> в пользу обычного <code>bool</code>. В этом был смысл для Си, но тут-то уже все есть.</p> <p>Почти доделал <code>ErrorContext</code>, скоро попробую его внедрить.</p> Разработка Мародера - 2014.04.20 Mon, 21 Apr 2014 00:00:00 +0000 https%3A//ozkriff.games/2014-04-21--devlog-marauder-008/ https%3A//ozkriff.games/2014-04-21--devlog-marauder-008/ <p>Отпуск кончился. Хочется умереть :) .</p> <p>Забыл написать. На прошлой неделе появился первый отчет об ошибке, ура ура! Правда я хз что с ним делать :( .</p> <p>Наткнулся на серию классных постов об обработке ошибок в блоге битсквида.</p> <p>Сделал кое какое отображение 2д и 3д текста.</p> <p>Решил возвращать текст в экранных координатах, а для отображения в 3д сцене его плющить матрицами как надо.</p> <p>Для поиска всех gl вызовов и вывода только их названий:</p> <pre style="background-color:#2b303b;"> <span style="color:#c0c5ce;">grep -oh &#39;gl::\w*(&#39; visualizer/* | sort | uniq </span></pre> <p>Добавил макрос (фу) <code>verify!</code>, позаимствованный из kiss3d, для проверки <code>gl::GetError</code> после каждого OpenGL вызова. Нашлась парочка ошибок. Надеюсь, это поможет запустить мародера на os x, а то неудобно. что отчет об ошибке столько времени уже висит.</p> <p>Сделал отображаемый пробел и поддержку нескольких строчек в текстовом кэше для font_stash.</p> <p>Камера в начале боя теперь не где-то с краю, а в центре карты.</p> Разработка Мародера - 2014.04.13 Mon, 14 Apr 2014 00:00:00 +0000 https%3A//ozkriff.games/2014-04-14--devlog-marauder-007/ https%3A//ozkriff.games/2014-04-14--devlog-marauder-007/ <p>На этой неделе у меня был отпуск, о даа.</p> <p>Наконец-то немного разобрался с pelican и начал приводить в порядок и выкладывать эти недельные отчеты на ozkriff.github.io, а то до этого они у меня только в gist`е лежали.</p> <p>По самому мародеру почти ничего не сделал, только выложил на гитхаб очень-очень базовую версию stb-tt-rs и кое-какой код интеграции в мародер. Но по факту текста в игре пока так и нет.</p> Разработка Мародера - 2014.04.07 Tue, 08 Apr 2014 00:00:00 +0000 https%3A//ozkriff.games/2014-04-08--devlog-marauder-006/ https%3A//ozkriff.games/2014-04-08--devlog-marauder-006/ <p>Аналогично с прошлой - ничего, только смотрю, что б Мародер собирался.</p> <p>Ну и вышел Rust 0.10, ура-ура! Хотя для меня это мало что меняет, все равно использую ночные сборки :) .</p> Разработка Мародера - 2014.03.30 Mon, 31 Mar 2014 00:00:00 +0000 https%3A//ozkriff.games/2014-03-31--devlog-marauder-005/ https%3A//ozkriff.games/2014-03-31--devlog-marauder-005/ <p>За эту неделю ничего не сделал, только слежу, что бы мародер собирался ночными сборками компилятора Ржавчины.</p> Разработка Мародера - 2014.03.23 Mon, 24 Mar 2014 00:00:00 +0000 https%3A//ozkriff.games/2014-03-24--devlog-marauder-004/ https%3A//ozkriff.games/2014-03-24--devlog-marauder-004/ <p>Сходил на Manowar, о да, нужно больше пафоса. Только теперь вообще ничего не слышу :) .</p> <p>Мучал glfw-rs, cgmath-rs и самого мародера, что бы они собирались с последней версией компилятора. Сложно было :)</p> <p>Брендан хочет, что бы cgmath-rs был исправлен не таким грубым хаком. Там могут быть косяки с NaN и +/-Inf. Но я туплю как сделать правильно. :(</p> <p>Мой грандиозный страйк помер :(, черт:</p> <p><img src="https://ozkriff.games/2014-03-24--devlog-marauder-004/2014-03-20--github-streak-fail.png" alt="github-streak-fail" /></p> <p>Капельку поковырял текст. Решил, что не буду использовать cmr/hgl-rs, страшно мне. Лучше все-таки чего-то свое сделаю.</p> <p>Шрифты, шрифты:</p> <p><img src="https://ozkriff.games/2014-03-24--devlog-marauder-004/2014-03-20--font-cli.png" alt="font-cli" /></p> <p>Сделал выделение отдельных отрядов в клетке:</p> <p><img src="https://ozkriff.games/2014-03-24--devlog-marauder-004/2014-03-20--color-picking-1.gif" alt="color-picking-01" /></p> <p><img src="https://ozkriff.games/2014-03-24--devlog-marauder-004/2014-03-20--color-picking-2.png" alt="color-picking-02" /></p> <p><img src="https://ozkriff.games/2014-03-24--devlog-marauder-004/2014-03-20--color-picking-3.gif" alt="color-picking-03" /></p> Разработка Мародера - 2014.03.16 Mon, 17 Mar 2014 00:00:00 +0000 https%3A//ozkriff.games/2014-03-17--devlog-marauder-003/ https%3A//ozkriff.games/2014-03-17--devlog-marauder-003/ <p>Ну что ж. За эту неделю я почти ничего не сделал, времени на Мародера было не так уж много.</p> <p>Зато сходил на концерт Апокалиптики :) .</p> <p><img src="https://ozkriff.games/2014-03-17--devlog-marauder-003/2015-11-23--apocalyptica.jpg" alt="apocalyptica-pic" /></p> <p>Сделал простенькое и кривенькое перетаскивание карты средней кнопкой мыши. Надо будет еще допиливать.</p> <p>Вернулся к ковырянию шрифтов из kiss3d. Решил переписать font-stash на Rust. Пока сделал только базовые привязки к stb_truetype.</p> <p>Все свободное время в субботу-воскресение протупил с попытками обновить cgmath-rs под ночную сборку Ржавчины: изменения с <code>min\max</code> для чисел с плавающей точкой.</p> <p>Пробовал городить страшные вещи с макросами, но пока так и не разобрался.</p> <p>Еще потыкал qapitrace и узнал, что <code>gl::GetError</code> надо вызывать после каждого gl-вызова.</p> <p><img src="https://ozkriff.games/2014-03-17--devlog-marauder-003/2015-11-23--qapitrace.jpg" alt="qapitrace-pic" /></p> Разработка Мародера - 2014.03.10 Tue, 11 Mar 2014 00:00:00 +0000 https%3A//ozkriff.games/2014-03-11--devlog-marauder-002/ https%3A//ozkriff.games/2014-03-11--devlog-marauder-002/ <p>Ну, этот понедельник я считаю последним днем недели. Не может у меня неделя с выходного начинаться, это неправильно как-то.</p> <ul> <li>Теперь передаю информацию о изменениях размера окна в камеру, теперь изображение не сжимается по высоте или ширине при изменении размеров окна.</li> <li>С горем пополам доделал и закомитил базовую версию поддержки нескольких отрядов в одной клетке. Правда, пока что выделить или атаковать можно только первого из них (того, что с индексом 0) и выделение вынесено на кнопку <code>S</code>.</li> <li>Задумался о системе слотов в клетке визуализатора.</li> <li>Еще наткнулся на блог разработки Cogmind - <a href="http://www.gridsagegames.com/blog">http://www.gridsagegames.com/blog</a>. Выглядит офигенно, но ссылки на альфа версию или чего-то подобное я нигде не нашел, жалко.</li> <li>Реализовал простенькую обертку над конфигурационными файлами.</li> <li>Изменилась система сборки glfw-rs - вбил костыли в make_deps.sh.</li> <li>Cmr сказал, что <code>c_str</code> - плохая штука. Заменил на <code>with_c_str(||{...})</code></li> <li>анимации движения теперь не зависят от времени отрисовки кадра.</li> <li>И добавил поворот отряда в сторону движения.</li> <li>Исправил поворот камеры - теперь скорость вращения камеры не зависиот от размера экрана: что бы повернуть камеру на 360 градусов по горизонтали нужно двигать мышкой от левой границы окна до правой, не завсимо от размера окна.</li> <li>Добавил класс MoveHelper, отвечающий за передвижение от точки до точки со скоростью, не зависящей от количества кадров в секунду, и использовал его во всех визуализаторах событий.</li> <li>Удалил из визуализаторов событий методы <code>start</code> - пускай все в new делается.</li> <li>Добавил к анимации события атаки летящий снаряд. Ну как снаряд, хрень какую-то :)</li> <li>Теперь отряды принадлежат к какому-то из игроков, над отрядами теперь висят страшненькие флажки.</li> <li>На последок запек ambient occlusion вместо, кхм, &quot;текстуры&quot; &quot;танка&quot;. Теперь намного лучше, как по мне.</li> </ul> <h1 id="byzanz">Byzanz</h1> <p>Гуглил про выкладывание видео в бложик, наткнулся на упоминания byzanz. Офигенно, теперь загажу все посты анимированными гифками! :)</p> <p><a href="https://github.com/GNOME/byzanz">https://github.com/GNOME/byzanz</a></p> <h1 id="github-streak">Github streak</h1> <p>И да, github streak в 61 день, еее!</p> <p><img src="https://ozkriff.games/2014-03-11--devlog-marauder-002/2014-03-09--github-streak.png" alt="github-streak-pic" /></p> <h1 id="80-simvolov-khvatit-kazhdomu">80 символов хватит каждому!</h1> <p>Узнал про <code>wc -L \*.rs</code> для поиска самой длинной строчки в куче файлов, прикольно.</p> <pre style="background-color:#2b303b;"> <span style="color:#c0c5ce;">$ find src/core -name &quot;*.rs&quot; | xargs wc -L | sort -h 59 src/core/src/game_state.rs 59 src/core/src/player.rs 59 src/core/src/unit.rs 65 src/core/src/geom.rs 71 src/core/src/map.rs 72 src/core/src/partial_state.rs 76 src/core/src/pathfinder.rs 78 src/core/src/ai.rs 80 src/core/src/db.rs 80 src/core/src/fov.rs 83 src/core/src/dir.rs 84 src/core/src/fow.rs 91 src/core/src/internal_state.rs 93 src/core/src/filter.rs 121 src/core/src/lib.rs 121 итого </span></pre> Разработка Мародера - 2014.03.02 Mon, 03 Mar 2014 00:00:00 +0000 https%3A//ozkriff.games/2014-03-03--devlog-marauder-001/ https%3A//ozkriff.games/2014-03-03--devlog-marauder-001/ <p>Так, что я сделал за эту неделю? Вообще, намного меньше, чем собирался :( .</p> <ul> <li> <p>Ну, во первых, решил делать вот эти самые еженедельные записи.</p> </li> <li> <p>Портировал из старых прототипов базовое путенахождение, причем оно происходит не на сервере, а на клиенте, основываясь на знаниях клиента о мире. Т.е., если на пол пути окажется скрытый юнит, то путь через его клетку все равно будет проложен, а уже при симуляции команды на сервере случится сюрприз в виде засады.</p> <p>Раньше:</p> <p><img src="https://ozkriff.games/2014-03-03--devlog-marauder-001/2014-03-10--no-pathfinding.gif" alt="pathfinding-pic-1" /></p> <p>Теперь:</p> <p><img src="https://ozkriff.games/2014-03-03--devlog-marauder-001/2014-03-10--basic-pathfinding.gif" alt="pathfinding-pic-2" /></p> <p>Да, пока отряд никак не поворачивается при движении :( .</p> </li> <li> <p>Немного привел в порядок <code>gl_helpers</code>, вынес из него типы <code>Texture</code>, <code>Vao</code>, <code>Vbo</code> и <code>Shader</code>. Ну и спрятал вызовы привязок gl внутри этих классов.</p> </li> <li> <p>Разделил все исходники на директории <code>core</code> и <code>visualizer</code>. Позже, наверное, сделаю их отдельными единицами компиляции. К первому отходит весь код, который не требует визуализации, т.е. сама суть игры, а визуализатор занимается полученеи ввода от пользователя и показом картинки.</p> </li> <li> <p>Постарался сделать так, что бы после вызова конструктора объекта он уже сразу был готов к использованию, а не ждал вызова <code>init</code>-подобного метода в неопределенном состоянии.</p> </li> <li> <p>Добавил в интерфейс визуализаторов событий метод <code>start</code> для, очевидно, начала визуализации события.</p> </li> </ul> Разработка Мародера - 2014.02.23 Fri, 28 Feb 2014 00:00:00 +0000 https%3A//ozkriff.games/2014-02-28--devlog-marauder-000/ https%3A//ozkriff.games/2014-02-28--devlog-marauder-000/ <p>Тому, что есть на данный момент до игры еще очень далеко. Пока что, по шкале от &quot;демо OpenGL приложение с вращающимся полигоном&quot; до &quot;X-COM, HoMM, Кодекс Войны и др. большие пошаговые игры, которые пришли сходу мне в голову&quot; Мародер находится на минимальном отдалении от левого края.</p> <p>На проект я потратил полтора месяца по часу-другому в день. Большую часть времени я изучал и игрался с Ржавчиной (которая язык программирования) и изучивал-вспоминал основы OpenGL.</p> <p>Есть стремная тестовая модель (вроде как танка), слепленная в блендере за пару минут и покрашенная там же, что бы проверить, как натягиваются текстуры:</p> <p><img src="https://ozkriff.games/2014-02-28--devlog-marauder-000/2014-02-23--ugly-tank.png" alt="ugly-tank-pic" /></p> <p>Других видов отрядов нет.</p> <p>Текстурки - png. Модельки - .obj (самый простой формат, что я знаю).</p> <p>Есть карта из одинаковых шестиугольников серого цвета. В каждой клетке может находиться один отряд.</p> <p>Работает простенькое выделение мышкой (color picking).</p> <p>По кнопке <code>U</code> (_u_nit) в клетке, на которую указывает мышка, появляется новый отряд. Появляется при помощи простенькой анимации - поднимается из-под земли. Такие вот зомби-танки.</p> <p>Отряды можно выделять кликом по клетке, но визуально это никак не отображается.</p> <p>Выделенному отряду можно отдать приказ двигаться, кликнув по пустой клетке, но путенахождение не реализовано, так что он просто полетит по прямой к нужной клетке.</p> <p>Выделенному отряду можно дать команду атаковать, наведя мышку на другой отряд и нажав клавишу <code>A</code> (_a_ttack). Очков здоровия, брони, точности и т.д. нет, атакованный отряд просто сразу умирает. Анимация смерти является противоположностью анимации появления - отряд уходит под землю. Очков действий у отрядов нет, атаковать они могут любое количество раз.</p> <p>По нажатию кнопки <code>T</code> (end _t_urn) ход переходит к следующему игроку (хот сит) и ему показываются результаты действий противников. Отряды не принадлежат к какому-либо игроку и каждый игрок может отдавать приказы любому отряду.</p> <p>Строчек кода на все ушло ~3800.</p> <p>Собирается под линуксом на ночной сборке компилятора Ржавчины. Настроена автосборка на travis-ci.org и я стараюсь не давать коду отстать от ночной сборки компилятора больше, чем на день.</p> <p>Исходники хранятся на гитхабе <a href="https://github.com/ozkriff/marauder">https://github.com/ozkriff/marauder</a>, для текстур и моделей отдельный репозиторий - <a href="https://github.com/ozkriff/marauder-data">https://github.com/ozkriff/marauder-data</a>.</p> <p>Вооооот, так что делать мне еще очень и очень и очень много. :)</p>