This week, I made good progress on engine stuff, but I also wiped myself out. Have to take it easy this weekend.

I’m still just staring at a little dude in a prototype walkabout area… Gah. It’ll get better eventually.

Funny… player clones actually kind of work in the engine now. In Hibernator, a bunch of player state information was stored in global variables, which caused total chaos when more than one player actor existed.

Reading up on LÖVE’s GLSL shaders. Hope to eventually have palette swapping and color cycle / ramping support.

 

Getting closer to working slopes. The player is now correctly positioned on a tile which has slope attributes, but there are still glitches when the player crosses vertical tile edges (teleporting one tile up in the air, not locking to the slope when walking downhill, etc.)

It’s important to me that the player’s bottom-center point is used to determine positioning on slopes. This does come with its own problems, since I want to keep using the full width of the player’s bounding box for collisions against solid square tiles, and those two kinds of collision detection can interfere with each other. It’s probably too much to get into here (I love to ramble on about this, maybe in the next Bolero project update), but I can think of a couple of games off-hand that use the bottom corners for slope placement, such that the player kind of juts out into the air, and it just doesn’t feel right. Likewise, I can think of at least one game that uses the bottom-center point for landing jumps on platforms, and it’s the game’s biggest shortcoming. I need both kinds of checks.

There are a few ways that one can implement slopes in a tilemapped environment. For now, I’m making slopes a property of the terrain def, and specifying two numbers in the range of 0.0-1.0, which represent the height of the left and right sides of the tile (0.0 is the top, 1.0 is the bottom.)

A four-tile-wide ramp would look like this:

name  slope_left  slope_right
-----------------------------
4xa1  1.0         0.75
4xa2  0.75        0.5
4xa3  0.5         0.25
4xa4  0.25        0.0
4xb4  0.0         0.25
4xb3  0.25        0.5
4xb2  0.5         0.75
4xb1  0.75        1.0


....  ....  ....  ..##  ##..  ....  ....  ....
....  ....  ..##  ####  ####  ##..  ....  ....
....  ..##  ####  ####  ####  ####  ##..  ....
..##  ####  ####  ####  ####  ####  ####  ##..

4xa1  4xa2  4xa3  4xa4  4xb4  4xb3  4xb2  4xb1

When the player’s bottom-center point is overlapping a tile with slope attributes, linear interpolation is used to get a height value from the left and right slope values, using the player’s center X coordinate (with some additional modulo / divide operations to get it down to a number between 0 and 1) as the input.

I was going to go by pixel count instead of 0-1, but if the tiles have to be resized for whatever reason, I think 0-1 would be less of a headache to convert. Likewise for collision bitmasks.

I’m excited about finally getting slopes working, bugs notwithstanding. I wanted them in Hibernator early on, but got frustrated, and decided it was for the best to push on without them. Hoping to eventually get this all working with in-game actors besides the player.

I want slopes. I want’em bad.

As a step toward this, I got jump-through platforms working. A code typo from earlier prevented terrain attribute lookups from returning any real data, and I had to do some digging to figure out the root cause. I added more debug draw functions to help narrow this down.

On today’s episode of I Can’t Do Basic Math: incorrect bracket placement causes all actor spawnpoints to skew downward the further right they are on the map

(These happy boys should be on the top row)
(i swear i fixed this already how did it come back)

Chipping away at collision detection and platforming state, trying to make these functions work with multiple actor types, and be easy to work with.

These test enemies fall when walking off of solid terrain, something no non-player creature in Hibernator was capable of. I think the closest thing to it was the little crawling spike guys, who would change direction if the ground tapered off in front of them.

Got nothing done today, besides recording the sound of a small desk fan and trying to make it sound vaguely sinister with the vocoder plugin in Audacity

Made a screenshot map of Hibernator that I’ll include when I update the project this weekend. While I didn’t have the foresight to write a function to screencap all of the areas in pristine condition, I did have the benefit of being able to disable the HUD and window border, and toggle player visibility with a temporary shortcut key.

Made some progress on the cell / tile / terrain definition mix-up that I inherited from Hibernator. Following this convention now:

  • cells are the raw integer values taken from map data. On their own, they map to whichever tileset is associated with the map, left-to-right, top-to-bottom. Within Lua and LÖVE, they are one-indexed, and everywhere else (Tiled, GraphicsGale), they are zero-indexed.
  • Tilesets contain a sparse array of tile_defs, which represent additional handling data for a tile, including a string referring to what kind of terrain it’s supposed to be (along with the animation info I threw in earlier).
  • terrain_defs are tables of key-value pairs that describe how higher-level game logic should treat a particular tile, such as whether it’s intended to be an obstacle to the player.

Cells are just integer numbers, tile_defs are per-tileset, and terrain_defs are project-wide.

If you’re curious, here’s the Hibernator terrain mapping. This was annoying but generally livable, since the game only had a single tileset, and I could cross-reference it using the grid snap mode in GraphicsGale. But it was holding things back quite a bit in the current project.

The tile ID values mapped to the following:

1 = default
2 = empty
3 = solid
4 = hazard_passable
5 = hazard_impassable
6 = ladder
7 = water

During development, I used the “1-8?” blocks to keep track of how many jump power-ups were necessary to travel through various routes of the map. The “default” and “empty” terrains being effectively the same but technically different caused some subtle bugs at times.