Lost – js13k 2017 (Update #2)

There’s about one week left for js13k 2017. As usual the jam has sequestered my mind, draining my processing power, thinking about it all day long how to push it further.

Here’s the story from last update, reconstructed from twitter + the git log. It’s been a fun journey so far.

August 19 – Added background stones using Voronoi. Keeping up with the goal of not using pixel art, got the idea from a shower curtain. May need some additional details to make them look like rocks without using textures.

Screen Shot 2017-09-02 at 11.25.29 AM
Walking around alien caverns

August 22 – Infinitely spawning maps, generated on the fly. This was tricky but needed in order to not be completely irresponsible with memory. One of my goals was to create a huge spawning world within the 13k limit, that of course was going to involve procedural generation (but I intend to keep the world fixed by seeding the pRNG properly). For this I’m dividing the map in 4 quadrants, and based on where the player is I clean the opposite sector and generate the closer ones.

August 23 – Implemented a CA module for Voronoi diagrams and used it on terrain and background to smooth them out. I used the output of the Voronoi library and post processed it adding the neighbor sectors. The CA module I made allow simple rules as in “For a cell of given type X, if there are (more/less) than N cells of type Y around, change its type to Z, P% of times”.

Also added a jetpack for easier exploration. I still didn’t have a clue on the theme of the game, was thinking it was may be going to be a space explorer ala Samus Aran.

August 27 – Added complete zoom support for the camera object (still thinking if it’ll be used in game, for now just using it for debugging purposes). All positions and dimensions are scaled based on the zoom factor, and then repositioned based on the camera position (which right now keeps synced with player, but may change that in the future)

August 29 – Worked hard trying to add support for smoothly walking on the slopes. I almost got it but there were some edge cases where the player would become stuck, or go through the slope and into the rock.

The way it worked was by tracing a line between the player’s hitbox center and an imaginary point below representing the gravity drag. Then I checked for the intersection of the polygon sides vs it to see what side was colliding with the player. Previously, I calculated the slope of all sides of the polygons. Then when the player was walking against the polygon, I changed his y position too, based on the slope.

One of the issues was faced was that when walking between stones the player may sometimes hit the wrong polygon side (one inside the rocks) .

August 30 – Figured out the issues with slopes were going to eat up all my time and I wouldn’t ship without them working perfectly. So decided to change theme to underwater caverns.

Tweaked the physics to allow the player to “float” (weaker gravity) as well as removing jumping since you can thrust upwards anytime now.  Initially made a “radial” movement schema where you could rotate and then thrust forward, but then decided to simplify it so you just move in the direction you press the key to. Also changed collisions so you’ll be stopped completely when colliding with anything (removed slope calculations), but they were still a bit buggy at this point.

Screen Shot 2017-09-02 at 11.31.59 AM
Floating in the caverns

August 31 – Up until now, the player had just been a colored squared so I decided to jump into changing it to what it was going to be in the final game. I considered several options from the beginning but since I was not going to use pixel art, adding humanoid characters with animation would have been quite painful, taking a lot of time and I wasn’t confident the end result would look good since I lack the skills. So, give that I had switched the theme to underwater, I decided to use a rigid body (a vehicle).

Did some research on deep exploration vehicles (Bathyscaphes) and in the end settled for a fantasy bathysphere. Also went ahead and added some “bubble” particles, generated from the sphere’s fans depending on the direction the vehicle was moving. Then as a last touch added a simple emulated head light, using a semitransparent white triangle.

September 1 – Started by doing some needed upgrades into the boilerplate project, mainly replacing using the uglify module with uglify-es in order to be able to use ES6 features in the source code.

Then I finally got into fixing the collisions, so right now I’m checking the intersection between the four sides of the player’s “future” hitbox vs the nearest stones, and calling it a collision in case there’s any intersection. I’m also keeping the case of projecting a line from the hitbox center to the future center and checking for intersections, to prevent cases of high y acceleration by gravity. It works pretty well now.

Did some cleanup using jshint and upgraded some parts to ES6 syntax, just for easier maintenance in the future and for the code to look better too 🙂

I got my hands into a more serious high level world layout generation, I designed the fixed world map which is composed by different sections, each section has a given type (which defines the parameters for the sector generator to build the map) as well as expected connections with neighbor sectors.

After the Voronoi diagram has been generated, the generator marks some of the sectors as special types: Unbreakable stones at the borders of the sector, and fixed open spaces representing the connections with its neighbors, these represent the constraints of the sector in order for it to fit the overall map, the CA rules don’t affect them.

I defined the parameters for some of the sector types: The Gate, Caverns, Open Areas, Farmlands and the Darkness Abyss (In which you can only see your headlight)

darkness
The Darkness Abyss

Then I added The Gate and the orbs needed to open it. In order to win the game you have to explore the depths, find the fours orbs and come back to open it, without getting lost in the process.

I also resized the viewport to 800×600 (was 400×400), and modified the physics a bit by generating a bit of “lift” with the vertical movement (akin to the sphere having some kind of “fins”, I guess)

lost
The Gate

Coming up

In order of relevance seeking to make a fun game

  • Enemies
  • Powerups
  • Parallax effect for background
  • Vegetation in the foreground
  • Enhance sector connection
  • Temple generator
  • City Ruins generator
  • Volcanic Ridge generator

 

Lost in the Underworld – Day 1, js13kgames

Alright, I decided to participate for the first time on js13kgames!

The plan is to create a cavern exploration game with a huge world and multiple paths on it, where the player has to find treasures and powerups. I also hope this series of blog posts is more informative and useful than usual.

The idea is to do terrain generation on the fly using Voronoi diagrams and Cellular Automata, also I won’t use pixel art but instead vector graphics (at least for the terrain).

After checking some of the options in the tools page, I decided to use Florent Cailhol’s JS13k Boilerplate. It is probably the simpler starter project there… it has some game loop logic, seedable RNG and gulp scripts for packing and minifying. It also comes with a sample simple implementation for physics.

I started adding keyboard support so you could jump and move around.

const pressed = {};

module.exports = {
	init: function(){
		window.onkeydown = function(e) {pressed[e.keyCode] = true};
		window.onkeyup = function(e) {pressed[e.keyCode] = false};
	},
	isDown: function(keyCode){
		return pressed[keyCode];
	}
}

Also did some foundations of the “physics” system based on the original, since the terrain will be irregular, what I’m doing for the collisions is checking if the future position of the player will be located inside one of the polygons. I used the “inside” function from James Halliday Point in Polygon repo, an implementation of the PNPOLY algorithm. There’s still a lot of potential optimizations to be done.

stones.forEach(function(s){
  if (e.dx != 0){
    if (e.dx > 0){
      if (inside([tx+e.w,ty+e.h/2], s.vs)){
        hCollision = true;
      }
    } else if (e.dx > 0){
      if (inside([tx,ty+e.h/2], s.vs)){
        hCollision = true;
      }
    }
  }
  if (inside([tx+e.w/2,ty+e.h], s.vs)){
    vCollision = true;
  }
}

Had to add a special case for high acceleration caused by gravity, which would make the player go though thing barriers because the updated position would just go through it. For this one I’m checking if the line traced from the current position to the future position intersects the polygon, based on a stack overflow response by Dan Fox.

if (e.dy > 100){
  //Prevent falling through thin borders at high acc
  if (polygonIntersects({
    a: {x: e.x+e.w/2, y: e.y+e.h},
    b: {x: tx+e.w/2, y: ty+e.h}},
    s.vs
  )){
   vCollision = true;
  }
}

Added simple camera support, centered on the player, for this I have a camera object whose position I affect along with the player’s. Then I substract that position from the world position of all objects when it’s time to draw them, to translate them to viewport coordinates.

js13k-2

Then I added super simple Voronoi map gen using Raymond Hill’s JavaScript Voronoi, it adds quite a bit of weight to the package but works pretty nice. I may have to slim it down for the final dist.

js13k-3.1

For now, I’m just randomly picking Voronoi cells, next up will use CA for the caverns to look less random.

var voronoi = new Voronoi();
var bbox = {xl: -300, xr: 1450, yt: 0, yb: 3550};
var sites = [];
for (var i = 0; i < 450; i++){
  sites.push({
    x: rand.range(bbox.xl, bbox.xr),
    y: rand.range(bbox.yt, bbox.yb)
  })
}
var diagram = voronoi.compute(sites, bbox);
const stones = [];
diagram.cells.forEach(function(cell){
  if (rand.bool())
    return;
  let vs = [];
  cell.halfedges.forEach(function (halfedge){
    vs.push([halfedge.getStartpoint().x, halfedge.getStartpoint().y]);
  });
  stones.push({vs: vs});
});

Navigating around the map made evident that my physics system still needs a lot of work. I will post it here once it’s more polished so it can be useful for someone.

I found out the core of the RNG module of the boilerplate isn’t working, so made it use Math.random instead for now. It also seems the current gulp tasks don’t work well with some ES6 syntax, I’ll take care of that later.

Current package size is: 7.13 KB

Javascript motion picture experiment, part 2

I wasn’t very happy with the result for my first take on the motion picture so I decided to revisit them. I did the following:

  • Remove the precision timing requirements by just calculating the film speed, position it correctly and have the shutter be triggered when the frame is passing through it.
  • Fix the shutter so that it’s not open/closed 50% of the time, instead it opens for 10 milliseconds and closes back, regardless of the desired frame rate.

 

Much better! if frame rate is high enough this looks pretty fluid, but may be too dark! (Note that the 1FPS example is skipping some frames, that’s an artifact of the animated GIF)

To compensate for the short shutter speed I added a white mask to simulate stronger lighting, then I increase the contrast of the film to make it look sharper under the increased lighting.

This also added a natural vignette effect to the movie. The final change I did was simulating a bit of imprecision on the shutter, making it randomly open a bit too late for some frames.

It actually looks much better when running directly (and at higher frame rates), things are happening just too quickly for the GIFs to get all important frames. I’ll clean up and push it to github soon for the curious, for the moment you can check it out online HERE.

I think I achieved what I was aiming for first, however for a real application it may be too tiring for the eyes… may be a hybrid approach (faking part of the visual effects) would be more appealing.

JavaScript motion picture experiment

While developing Curse of Wallachia, I was assaulted with a great curiosity: Would it be possible to emulate the way traditional film movies work using javascript?

The idea was pretty simple: Emulating the “film strip” as individual frames moving quickly (very quickly) on the screen, and then having an overlay area act as a shutter, synchronized with the film strip so that it showed a single frame at a time.

I decided to stream my adventure, which involved a lot of exploring the different options. You can check it out here and here

The goal was to make it so that the movie played at lower FPS than the actual game was running. I ended up doing the following calculations:

Given:

  • SHUTTER_HEIGHT in Pixels.
  • TARGET_FRAME_RATE in Frames per second

Then:

  • MILLIS_PER_FRAME = 1000 / FRAME_RATE
  • SHUTTER_SPEED = 1000 / TARGET_FRAME_RATE
    • in Milliseconds per shutter cycle
    • Each shutter cycle consists on it being opaque and then transparent for the same amount of time.
  • FILM_SPEED_MILLIS = SHUTTER_HEIGHT / SHUTTER_SPEED
    • in Pixels per millis
    • How quick should the film move so that a single frame is shown for each shutter cycle.
  • FILM_SPEED = FILM_SPEED_MILLIS * MILLIS_PER_FRAME
    • Converted to pixels per frame.
    • All sprites in the film strip move this distance on every frame.

Here are my observation after the first try:

  • It’s very hard to time the sprites correctly to move at this high speed and sync their position with the shutter. This is caused in part by the varying real frame rate and the high precision required for the timing.
  • Even if this was possible, having the shutter block the image 50% of the time reduces its brightness a lot (if I’m correct, they fixed this using stronger reflectors historically).
  • Ultimately, I missed the fact that the persistence of vision effect wouldn’t be achievable at low frame rate speeds so in order for this to work I’d have to work with higher frame rates, complicating the emulation even more.

I decided to give up this idea. I realize I may be doing something wrong so if someone wants to take on the challenge (or elaborate on why it’s not feasible) please post in the comments!

Later on I thought on alternatives to achieve my goal, I figured the only way to go was is faking both the Phi phenomenon and the Persistence of Vision effect as follows:

  • Keep the motion of the “film strip” using the same previous calculations.
  • Remove the shutter altogether, instead put a “still frame” sprite on top of the film strip. (This simulates the persistence of vision effect)
  • As the sprites from the film strip come close to a the “still frame” sprite, “burn” the sprite image into it. Since the film strip is moving quickly, this will simulate the phi phenomenon at lower speed (giving it the desired “retro” feel).

Here are the results:

 

I’m pretty happy with these results, admittedly I could have cheated and just put a blurb of pics as the film strip, since they are barely noticeable when over 8FPS… but this was fun and I think it feels more authentic 🙂

Finally, I made the still frame move around a bit when captured to simulate a bit of “jankiness” and imprecision.

cinema-janki

If you have followed the development of Curse of Wallachia, you may have an idea what I’m going to use this for.

Using RiotControl on Project Picker

I’ve updated Project Picker to use riotControl to handle all actions, including moving all model management to store objects. If you are using riot in your FE, this may be useful.

pp

In order to test using multiple stores, I added a pretty useless “history” functionality which keeps track of the projects chosen by the picker.

Here’s how it works, there are three different kinds of actions:

  • User actions
    • Triggered by a user doing an action on the tag. (for example, clicking a button)
    • Handled inside the tags (riotControl not involved)
  • Command actions:
    • Triggered by a user action handler after gathering all required info from the tag.
    • Handled by the stores to execute actions.
  • Result actions:
    • Triggered by a command action handler after an action has been executed.
    • Handled by the tags (and stores to a lesser extent) to update their model.

Check the source code or see it live.

New slashie.net website, now powered by ReactJS

The website for my project collection (http://slashie.net) is now powered by ReactJS. I had to learn how to use it so I figured it was a good idea to update it.

The previous implementation was powered by mustachejs, which was used with nodejs to generate a static html file. I still like that approach, however it didn’t allow by itself for interaction with the data.

Although appearance is very similar, this new version:

  • Allows filtering by project status (and may allow other filters in the future). This also means the groupings by project status are gone now (they made navigation a bit confusing too). This was done using React’s state handling.
  • Has projects sorted descending by project year
  • Adds tags for all the projects with a color code

With this, I’m now officially a Level 1 ReactJS developer. If you are curious or would like to do something similar, you can check out the project repo here.

ROGUElike ONE

A roguelike based in the ROGUE ONE Star Wars story

Play online now!

rogueone2

How to play?

Your mission is to infiltrate Scarif, find the blueprints of the Death Star and beam them to the Rebellion mothership hovering over the planet.

rogueone3

Press Enter plus a direction to fire your ranged weapon, press space bar to access your inventory and use items, or pick up items, or use stairs when you find them.

rogueone1

Every two levels you’ll get to select a new skill for your character, these are triggered just by moving around (for example, cornering an enemy against a wall or jumping on a wall to evade them)

rogueon4

Backstory

Rogue one was pretty cool, so I decided to mod Rodney and transform it into a new game.

It was not a straightforward conversion tho… Rodney has no ranged combat, which is essential to the Star Wars universe, so I had to implement it. Needless to say it was no easy task since the game was design to have all action happen sequentially (i.e. the outcomes of all enemies actions happened immediately).

I also removed the “light source” mechanics (which are a pretty big thing in Rodney) since they didn’t make much sense on this new universe.

The online features of Rodney (basically a “community” level where people could move around and chat) were also disabled since the websockets server for Rodney is disabled, I couldn’t invest time into that and I’m not sure it even adds something to the game.

I’m thinking on making a graphics version, since Rodney already supports graphics, but I’m trying to get some help from a pixel artist. Please contact me if you are interested.

Ananias Roguelike 1.78 released. Bigger rooms, more animations, keyboard commands and more!

Another awesome update is available! This one was delayed a bit by issues with my main dev macbook laptop, which decided to stop working properly and I haven’t been able to fix completely even after using all the spells I know. At least I now have a legit excuse for not releasing the iOS version 🙂

I also did an initial full pixel-art version of the new trailer, since my macbook is no longer operational (I’m not even sure the current work on the trailer is safe), that will take a little bit more.I intend again for this version to be the final way feature wise for the release on iOS and Steam. But that doesn’t mean much… I have had the same intent for about a year.Check the full changes log below!

entrance
The entrance to the Temple of Ananias
test
Bigger rooms
password2
Resetting password via email

User Experience

  • Animation for player!
  • Add dungeon entrance
  • Make monsters and player shake when hit
  • Replace integrity with description for weapons and armor
  • Allow moving by tapping any floor tile
  • Allow switching weapons using Tab
  • Allow throwing items with keyboard (“T”)
  • Allow switching targets (Tab) and confirming (Enter) or cancelling actions(Esc) with keyboard.
  • Reduce 1 minute of dungeon silence

Online

  • Allow recovering password via email

Gameplay

  • Implement two handed weapons (Can’t wear shield at the same time)
  • Add two handed bonus for some weapons. (Staffs, spears, etc)
  • Increase size of rooms
  • Generate rocks and reagents as a separate item group (more reagents to play with)
  • Multiple types of room per level
  • Remove “No spells used” Conduct when using a scroll
  • Remove “Could use carbine” “skill”
  • Make altars and wells not block ranged attacks

Fixes

  • Always hit with melee wands if wand expert
  • Invisible invisible player sprite
  • Enemy attack check for required min range
  • Tweaks on 2.5D walls generation.
  • Add new monster images on manual
  • Fix issue with boots ground sprites

Enhanced process for hybrid apps

Some months ago I wrote about the pain that it was to create a new build, I’d like to update that with my current setup which is much better tho not still super optimal.

I have reduced the manual steps prone to failure as well as the bandwidth cost. The release and announcement part is still manual tho, so I still don’t to release for all platforms and forget to announce thru all channels.

The cocoon.io parts have been removed in favor of a pure Cordova/Crosswalk approach, which have made possible lots of automatisation.

Still, what takes more time is the manual process to be done for each different storefront via its own web interface. Each one requires different info, and all uploads have to be started and monitored manually. It’s pretty uncommon for a store to supply a command line tool.

This is the current process executed for each new release of Ananias:

Packaging

  • Mark the new version in the source code (client and server)
  • Execute the packaging script for each platform, it does the following:
    • Generate a new JS bundle using browserify
    • Generate the player’s manual
    • Copy the required assets based on the platform
    • Do platform specific things like using cordova/crosswalk, nw.js, signing and zipaligning APKs, etc.
    • These are currently shell scripts, no fancy gulp or grunt for now
  • Rename and zip the executable packages for Windows, Mac and Linux (Should add this to the script)
  • Execute the cordova build for iOS
  • Build changes log from git commit messages

Distribution

  • Upload new build to web (ananiasgame.com/play) (About 15MB) (Only Standard edition)
  • Deploy new server version and restart (About 1MB) (including executing migration database scripts)
  • Upload to itch.io via web interface (About 200MB )
  • Sign in to google play developers console
  • Summarize change log for Google Play
  • Upload both x86 and arm APKs (About 100 MB)
  • Upload both APKs to Amazon via web interface (About 100MB)
  • Upload to indiegamestand via web interface (About 200MB)
  • Upload to gamejolt via web interface (About 200MB) (Only Standard Edition)
  • Upload to IndieDB via web interface (About 200MB) (Only Standard Edition)
  • Open xcarchive in xcode organizer
  • Submit package to App Store
  • Wait for processing
  • Go to iTunes Connect
  • Go to Testflight / External Testing
  • Select new build to test
  • Wait for beta review
  • Go back to Testflight / External Testing
  • Set the new build as active.

The process should be executed twice, once for the Standard Edition and then again for the Fellowship edition.

The dream of having a single web endpoint, and have all the clients deal with the updating is still far from happening.