You can view this content for free after you Log In or Sign Up.
Devlog - Automatic Stairs Creation
Following up on the latest feature in the previous blog post; the improved stairs system.
My prototype system for stairs was a relatively simple one - with only 2 main objects (the top & bottom entry points). Instead of treating stairs like a physical object, players would instead enter the "on stairs" state, only allowing them to move diagonally. That is how the original CV games did it, but can't work if we want players to land ON stairs after a jump. So we created a new object [o_stairs_mid] and placed one at each tile of the entire staircase.
The problem with this solution is that it requires I hand place every single step for every single staircase in every single room. It is extremely prone to user error, and if I wanted to move any of the staircases, I'd have to move EVERY single step. That's annoying.
So I've decided to automate the process, though this was a bit tricky.
My initial plan was to have [o_stairs_mid] duplicate on creation until it meets [o_stairs_top], but GameMaker wouldn't allow this because it could result in an infinite loop...
So I came up with another solution; involving measuring the desired length of each staircase to automatically create the amount of steps needed between both entry points. ---
Outline of Behavior
But this was still tricky... [o_stairs_bottom] needs to find the EXACT [o_stairs_top] I wanted. Using a collision_line to detect the top entry could still choose incorrect instances, such as:
Instances at the same X coordinate as my desired instance (like right next to it).
Instances above my desired Instance, but still along the collision line.
So here's what I'm ultimately doing: send out a collision line, save a list of every single entry the line touches, then filter out any instances that have a different direction (image_xscale), then loop through that list of entries, and select the closest instance.
Once I've found the closest instance, I measure the distance between the two entries in tiles, then [o_stairs_bottom] will create [o_stairs_mid] along the line until they meet [o_stairs_top]. Now, I only need to hand-place the entries and the engine will handle the rest on its own.
Automatic Stair Generation!
---
Get Equipped with the power to lie dormant for 8 years.
Oh, and I've added a slide ability.
This is a feature I've planned to include since the early prototype, but its inclusion was never essential, so I never spent time to include it. When the player starts sliding, they get a sudden burst of speed, and they decelerate over time.
I thought about making it identical to Mega Man's slide, but worried it would be too fast that too many people would prefer it over walking. That slide also would make it easier to die too...
I still need to create original art for it.
---
I hope everything works as intended. I have a nearly complete basic movement system, assuming I don't do extra stuff like wall jumps or back flips.
I'm noticing an issue with sprite warping (presumably due to sub pixel movement) and my old smooth camera system doesn't fix it (but it still works perfectly in my prototype even after it has been converted into the latest version of Gamemaker). So I might need to create a new camera system or find out why it's happening.
You can view this content for free after you Log In or Sign Up.
Devlog - Improved Stairs & Collision
I have done more work on the Beaumontvania Engine.
But first, to reiterate a previous point:
In Castlevania, players can jump through ceilings from underneath, but will be blocked from jumping into a block's side. I accomplished & discussed this in my last blog post.
While this behavior is perfectly fine, I did want to introduce some of the additional quirks seen in the Bloodstained: Curse of the Moon games (which also recreate classic CV). There are two features in particular that I wanted:
The ability to jump when there are blocks directly above you. In CV (and my engine), the player is unable to execute a jump if there is a block above their head when grounded.
The ability to jump through ceilings and land on top of them.
Although the player's jump is too low to naturally jump through ceilings, I want the engine to at least be capable of supporting this feature in the case of a double jump, for example.
However... There is an obstacle! The player's feet is constantly checking for collisions. If the player attempts to jump through a solid, the feet will detect [o_solid] and interrupt their jump - causing the player to immediately bounce back down.
I solved this by modifying the foot collision -- basically: if players are inside of a solid during a jump, then consider their character as NOT grounded, and do not interrupt their jump.
Behold! Unlimited Power! The ability to jump through ceilings.
---
This has caused bugs, however.
One issue is that players can fall through floors because portions of their body are technically inside of [o_solid] even when they should be grounded. I have fixed this (I hope).
Here's one such solution:
If players are jumping and within a solid... And their feet detects [o_solid] below, but the feet themselves are NOT inside of a solid, then treat the player as grounded. Otherwise, we can treat them as not grounded.
I hope they're fixed, anyway. But let me show you those bugs anyway, just for fun.
Bug. Player's knee is inside wall, so player's Feet Detection was never re-enabled.Bug. Player's back is inside wall, so Feet Detection was never re-enabled.Unrelated Bug. The body thought this area was a legal space to stand.
---
I have also implemented stairs (and much more efficiently than before). There might be one thing about the older code that is slightly better, but the newer code is faster, requires less lines of code, and requires less individual objects per staircase by default.
But I've also added a new feature - the ability to jump onto stairs.
This feature was not present in the original CV trilogy, but was seen various titles, such as CV: Bloodlines, Super Castlevania IV, Rondo of Blood, and even Bloodstained: Curse of the Moon.
This feature does make stairs a bit more complicated, and was the primary reason I never had it in the Prototype. Its inclusion also means that staircases now require additional objects... In fact, one additional object for every 16 pixels (or tile).
In the prototype, stairs were comprised of two tangible objects - a top & bottom entry point. The rest of the stairs did not exist; players were instead put into a unique state where they can only move diagonally until they exit via one of the entry points.
But to accommodate the ability to land ON stairs, every step needs an object to detect.
I hope there are no bugs present, but I would not be surprised if there were. I don't know if there's any real demand for it, but players can also lock their movement while holding A too. Player can Jump onto stairs, drop off stairs, and lock position.
I can use basic math to determine the correct coordinates for players to land.
If [o_stairs_mid] is drawn from its bottom-left corner (0, 0) and players run across the stairs in a perfect diagonal line, then coordinates for the top-right corner are (16, 16). If players land on the stairs on its 8th horizontal pixel, then their feet should also be on the 8th vertical pixel. But this is very tricky when dealing with gravity pulling players down in sub-pixels very quickly.
So: I find the difference between [o_player.x] and [o_stairs_mid.x] (origin: 0,0) to determine how far long the player is along the horizontal axis (let's say they're 12 pixels deep). I then take 12 and add it to the stairs vertical axis, ensuring a perfect 1:1 ratio.
So, when players enter the stairs while falling, I then FORCE them to those coordinates. This can sometimes result in an abrupt jittery animation though.
---
Oh, and players now have the ability to drop off stairs.
Although this feature was not in very many games, they were present in SC4 & RoB -- which are probably the two most iconic "classic-style" games in the franchise for many fans. That said, I was uncertain about its inclusion because:
It makes stairs less risky than they already were (due to Elayne's speed) since players can now instantly exit staircases on command.
Players may accidentally drop off stairs and die.
The Curse of the Moon games never included the ability to drop off of stairs despite allowing players to jump onto them. I can only assume the reason for this choice was because it was better for the game design & balance... So might it be a mistake for me to include it? I am also less inclined to give players methods to rush through or ignore tangible gameplay mechanics.
But it's good that my engine is, at the very least, capable of supporting these features now.
You can view this content for free after you Log In or Sign Up.
Devlog - New Elaynevania Collision System
Surprise! A gamedev update? In the year of our brell, 2026?!
I have recently started to recreate my Beaumont-vania engine in the hopes of making a better version from scratch. So I thought I would share my recent developments - and more openly.
---
Screenshots from Bloodstained: Curse of the Moon 2, which uses a recreation of Castlevania's mechanics.
In the classic Castlevania games, players interact with the world in a rather unique way:
Players will ignore collision with blocks (or o_solid) above their heads, allowing their jump arc to continue without interruption. But when jumping into [o_solid] from its side, the players will instead be prevented from moving horizontally, blocked by the wall ahead of them.
These behaviors can also occur simultaneously: players may overlap ceiling tiles while also being blocked by walls at the same time. This can be a little tricky to replicate. If our method to detect collisions is a simple rectangle that covers the player's body using place_meeting, then players would likely hit their heads on the ceiling, like in most games.
So the solution used in my prototype is similar to Castlevania's (and many other NES games): using a set of collision_points instead, all placed across the player's body to detect [o_solid].
However, different player states (move, jump, etc.) all required using different collision points, forcing me to keep track of 6+ points across different blocks code just to detect [o_solid].
Old Code - Macros for Collision Points (very messy)
Each state used their own collision points, and the airborne states all had their own variations of repeated code, introducing several opportunities for inconsistency & bugs... My logic also suffered from a few "magic numbers" and even resulted in players getting stuck on blocks.
This collision system was a constant problem across the game's development.
---
However, I recently designed a new system in a fresh project; even using a rectangle with place_meeting to check for collisions despite my earlier statement.
This requires some clever problem solving - inspired by Programancer's method for TASQ.
Instead of checking for collisions with:
place_meeting(x, y, o_solid)
I am using:
place_meeting(x, y_offset, o_solid)
Instead of detecting collisions at the player's Y coordinate, we're checking a dynamic position that changes using a customlocal variable [y_offset]. This basically lets us trick the code into thinking the player is not PHYSICALLY inside of the block, allowing uninterrupted jump arcs.
So, when checking to see if players can move horizontally:
If the player is OUTSIDE of [o_solid], check for blocks AT the player's height.
If the player is INSIDE of [o_solid], check for blocks BELOW that [o_solid]'s bottom edge.
As a result, since [y_offset] is being lowered below the active ceiling, players can still bump into walls on the side, as those walls are ALSO below the active ceiling - achieving our goal of recreating Castlevania's environmental collision.
Although not accurate to the written code, this is basically what is happening.
---
I have also created a script for generic jump movement to use in all relevant airborne states, so that I can re-use it without having to write it more than once. If any changes are made to it, then it will be reflected in ALL of the player states that call this script automatically.
Moving forward, I plan to use this strategy more often -- creating "building blocks" of logic to re-use across multiple scripts & objects instead of hard-coding similar behavior every time.
Helper Script: Handles horizontal movement, for use during all airborne states (Jump, Fall, Jump Whip, etc.)
Player Jump State Script: Calls the Helper Script, but does not handle any horizontal movement itself.
My new logic is still work-in-progress, but has proven fairly successful so far. The new logic is cleaner and doesn't have many of the "wall clipping" problems my last system did. I found a notable bug in the Helper Script's second condition, but it otherwise works fine. Still, I do need to fix that, so the shown code does not reflect the final product. I want to make sure this behavior is perfect before adding any other player actions.
It may be worthwhile to create a game focused on platforming without complex mechanics, so that it would be much easier to test & receive patron feedback without other mechanics getting in the way.
---
This game development blog post is different from previous posts because it focuses solely on logic and code, which I imagine limits the overall entertainment value for most viewers -- but it is interesting, and an important part of the development process.
I'd also like to be less rigid with my devlogs by not requiring it to always highlight new art or features, so diversifying is nice. Whether that's showcasing a linear progression of the game engine, general game design concepts, or even experimenting with other game ideas...
Ability to support your Creator by pledging – one-time or recurring.
Means to reaching out to the Creator directly via Instant Messenger.
Subscribe
WE USE COOKIES
SubscribeStar and its trusted third parties collect browsing information as specified in the Privacy Policy and use cookies or similar technologies for analysis and technical purposes and, with your consent, for functionality, experience, and measurement as specified in the Cookies Policy.