Home Creators Posts Import Register Favorites Logout

Content

Enemy Behavior: Sine Wave

If you recall, I'm building enemy behaviors as separate, external functions that I can simply call inside an enemy, instead of hard-coding specific behavior for every individual enemy.

The classic Medusa Head flight pattern is now implemented. The arrangement is a bit more complicated than my old engine, but is technically easier to apply to enemies now. It also has functionality to scroll with the camera vertically.

So, for our Bat enemy, I can say: Run Horizontal Movement Behavior, then Run Sine Wave Movement Behavior. That's all that is needed for this enemy to perform its basic actions.

Another benefit of this system is that I can easily update the sine-wave pattern mid-flight. CV3 has a Flying Skeleton enemy that moves in a sine-wave pattern that increases in speed & length as it gets closer to the player, so this should allow me to do something similar.

Score -> Gold

The old demo features a bare-bones score system; collecting money & killing enemies raises the score and eventually results in a 1-UP. However, it was never balanced properly, and thus would almost never result in an extra life.

I've changed this into a proper currency system. Now, when players collect money, they are collecting an actual currency that can technically be spent in shops. I'm apprehensive about having to balance an economy -- but this may be more interesting.

As of current, it also behaves similarly to the currency in Dark Souls / Zelda 2. When players die, they'll drop 50% of their Gold. Players can recollect half of that if they manage to reach the spot of their death. So if you had 100G, you'll drop 50G, but can reclaim 25G.

Modifiers

I've begun implementing "Game Rule Modifiers" that can be toggled on / off. This allows me to test different interpretations of a mechanic, but some may also be accessed by players to modify the experience eventually.

One example of a modifier is: Cheap Sub-Weapons

The default cost for sub-weapon use depends on the item itself. For example, the dagger costs 1 WP but the axe costs 3 WP - the idea is that stronger weapons are more expensive to use. This follows the philosophy of modern Vania-likes.

The alternate cost (accessed via modifier) is closer to that of CV1; sub-weapons now cost much less to use. As a result, the dagger and axe both cost 1 WP.

Experiment: Rondo Backflips

Although it's currently only intended for developer use, I've added a Rondo-style backflip. At any point between the START of a jump and the point of DESCENT, pressing [ JUMP ] causes the player to jump AWAY from the direction they are facing. This can function as a tiny double jump that requires a bit of work or even "undo" a jump -- but a player needs to act fast, since they lose the opportunity to backflip the second gravity starts to pull them down.

I don't know if it's sticking around. It's not a very simple & clean maneuver and it will affect the balance of levels, and I don't have much experience with Rondo. But I'm willing to experiment.

Food Pouch

Another feature has been added -- Food Pouch, inspired by the Sub Tank in Megaman X. It serves as a tool to make the game a little easier.

Typically, acquiring food will heal players up to max HP -- and any excess food will be wasted. With the Food Pouch, any excess healing or food will now be stored as portable rations, which can be used at any point via the player's inventory. The pouch can hold 10 HP, which is approx. the entire length of Elayne's starting HP bar.

Small Changes:

Players now drop all sub-weapons on death (resets to dagger).

Players now lose all ammo on death.

Firebomb sub-weapon added. Its flame lasts 2 seconds and deals a possible max damage of 18. The values in the old demo is 14 max damage over 1 sec.

Concerns:

Let's talk about how enemies currently take damage.

The player's weapons create a hitbox that follow it. When enemies contact that hitbox, they take its assigned damage, then enter an invincibility state. That invincibility will last 15 frames (20 in old demo). This prevents enemies from taking constant damage -- otherwise an enemy that SHOULD take 4 hits will die in 1 hit.

But if I want to create a weapon like Bloodtained: CotM's Magic Charm (Holy Water), which does damage over time, we run into some issues -- let's look at some numbers...

The Firebomb in the old demo lasts 1 second and deals 2 damage on contact. When the bomb hits the ground, it creates a flame that does 4 damage. In the old demo (20 iframes), this will mean enemies would take a max of 14 damage altogether.

CotM2's Magic Charm lasts 2 seconds and deals 2 damage on contact. When the Charm hits the ground, it creates a flame that does 3 ticks of 4 damage per tick, so enemies would take a max of 14 damage altogether -- the same exact max damage.

... But if I make my Firebomb last 2 seconds, enemies will take MORE than 14 damage. This is because damage isn't delivered over ticks, but rather when the enemy's iframes run out. Thus, the flame now deals more total damage; a possible max of 18 (2 damage every 15 frames).

I don't want the flame to do less than 2 damage per hit in order to maintain 14 max damage, as that might feel too weak if the enemy only touches it for a brief second. But a damage value above 2 might feel TOO strong with the new iframes and Firebomb length.

That means I may need to re-evaluate my damage calculation in the future. Perhaps instead of giving enemies 15 iframes whenever they take damage, I may need to make it so that different weapon attacks will determine different iframes. For instance, the whip may give 15 frames of invincibility, but the firebomb gives 40 (40 goes into 120 frames three times -- three ticks). As a result, the firebomb will be able to deliver 14 max damage again -- but that will require quite a bit of rewriting.

Recent development has been slow.

Don't forget to eat & sleep.

Files

Comments

Ethan Moreno

Recent development may have been slow, but man... So much good stuff was added into this new build! I especially love seeing the Rondo Backflip, Food Pouch and even the Sine Wave being added into this awesome build of yours! I look forward to reading another devlog in the future (and maybe even getting to play another demo of yours)! Also, Elayne doing her backflip makes think of Sonic's Spin Jump or Samus' Double Jump in her Varia Suit. X3c

John Harris

Is there a reason to make the backflip unavailable once a jump starts descending? It's more useful as an emergency reaction if it can be done at any time, and it doesn't seem like it's so overpowered if it can be.

Brellom

A handful of reasons: 1. This is exactly how it works in Rondo (though their jump is floatier). 2. It would be OP, actually. It's hard to demonstrate without a visual, but imagine a room that wants you to travel to the right, down some stairs, then back to the left so you end up below where you started. You could drop off a ledge, then backflip, and skip the entire room. 3. If I don't constantly account for it in the level design, players could end up out of bounds and die or be unable to continue because I never put a solid block or a teleporter in a niche spot that players weren't expected in. 4. It also makes the controls messier, which is the opposite of what I want. Not only do I want a sense of action commitment and a smooth jump arc, I also want the controls to be as simple and clean as they can possibly be, which is ultimately for the benefit of the player big-picture wise. It already is a little messier to control, so that's why it's just an experiment for now.

Madam Launch

what if each hitbox kept a log of what it hit, and each target was re-hit after a delay specified within the hitbox? FIRE: damage = 2 delay = .25s targets = [ [enemy1, 0.0s], [enemy2, 0.1s], [enemy3, 0.01s], [enemy4, 0.2s], ... ] each tick, the hitboxes would subtract the frame delta from each target's delay timer. once the timer reaches 0, the target is damaged again. of course, the damage is only re-applied if the target is still overlapping with the hitbox. the process would be: 1.) compile a list of all targets colliding with hitbox. 2.) decrement all target delays. 3.) if colliding targets are not currently listed in the hitbox, damage target and add them to list with the specified delay. 4.) if colliding targets ARE currently listed, only damage them if their timer is at/below 0, then reset the timer. 5.) if a listed target's timer is <0, and they are not currently colliding with the hitbox, remove them from the list. simple as. allows for combo attacks on enemies while keeping everything sane. :) since there aren't actually a lot of non-physical hitbox collisions per tick, the computational cost should be minimial.

Brellom

Seems like a decent solution, though I generally want to keep all of the damage code inside the enemy itself for simplicity's sake. I SEEM to have managed it by just giving the weapon hitbox an iframe variable that the enemy reads when it takes damage, which it then uses to update its own iframe timer.