Devlog 3: Game Demo!


Welcome to the third week! Short intro this time around, we'll adopt last week's structure as it was well received. Lots to talk about today so let's get into it straight away!

Art

Laurens

Hey hey!
From the artists side we got some new thingies to proclaim, we have found a (relatively) cohesives style! Shape language, color schemes, screen filters, etc, are now all working together to create a retro, PS1 esque feel, but put into a modern jacket. This has been the result of the artbible and shader tests. (Examples below)

We can't really show the entire art bible at the moment, but we will be able to give more detailed updates and examples soon since we will be hitting production next week! Enviroments and shader work from Mathis and characters and props from Me, 

That's it for this short art section, onto the expansive (And impressive) work from our programmers!

Demo

Dylan

Following last week's progress, we aimed to deliver a playable demo this week. To recap, last week we introduced:

Core Mechanics:

  • Jumping
  • Dashing
  • Shooting
  • Knockback & Self-Knockback
  • Arena Knockout
  • Level Reset

Prototyped Features:

  • Wall Jumping
  • Picking Up & Throwing Weapons

Planned Additions:

  • Fighting with Fists
  • Spawning Weapons
  • Testing Different Arena Scales

What Did We Do?

A lot was completed this week:

  • Fixed multiple bugs from last week
  • Improved dash logic
  • Player differentiation for better clarity
  • Arena Knockout now based on a timer
    • Offscreen indicators for better tracking
  • Prototyped different map scales
  • Adjusted bullet behavior
  • Implemented Game Loop, Point System, and Round System
    • Chaos Card Selection system added
    • Created a Winner Screen
  • Improved jump mechanics
  • Added punching combat
  • Weapon spawning, pickup, and throwing

Bug Fixes & Improvements

Following last week's work, a couple of issues needed to be adressed before pressing on. Let's tackle them in order:

  • Controller Support Issue: Controllers weren’t working properly on Steam.
  • Prototyping Changes Not Saving: Level resets would erase changes.
  • Dashing on the Wrong Axis: Left/right dashing was assigned to the XY Plane instead of the XZ Plane.
  • Ragdoll Colliders Sticking Around: Invisible colliders blocked movement.
  • Camera Issues: Player 0's death would cause the camera to change position.
  • Dash Improvements: Now limited to allow dashing only after landing.

These fixes smoothed out gameplay, making playtesting faster and more reliable. With all of that out of the way, let's tackle the new additions.

Player Differentiation

For the prototype, a simple nametag was added to each player. While this helps with identification, it isn't an ideal solution. The names are too similar, requiring a brief search to locate your character. In the future, player differentiation will be improved with distinct outlines and textures, allowing for instant recognition at a glance!

Arena knockout

The arena knockout system was completely reworked. Previously, a sphere collider was used to detect when players strayed too far, instantly eliminating them. However, this method was both problematic and not quite what we wanted.

Instead, the detection system was changed to a rectangle-shaped zone that properly fits the play space

This allows for more precise detection, ensuring that players who step outside the play area (the Dead Zone) have a brief timer-based window to return. If the timer runs out while they’re in the Dead Zone, the player is eliminated. 

To enhance clarity, an on-screen indicator was added to track the player and visually represent the time remaining. After some quick math and testing, the initial prototype result was as follow:


 Later iterations refined it further, ensuring that the indicator updates properly and disappears once the player is eliminated.

Map Scaling

The initial play space was too small, so an option was added to adjust the camera distance for playtesting.



We settled on this:


After experimenting, we settled on a balanced distance. Large enough to give players space to move, but not so big that fights became a game of tag.

Improved bullets

Bullet behavior was refined to feel more natural:

  • Faster speed
  • Less affected by gravity
  • Smaller overall
  • Destroyed on impact

However, this tweak inspired a new weapon idea, the Bounce Gun! Instead of disappearing on impact, its bullets ricochet off surfaces, creating chaotic battlefield dynamics. The changes will be refelcted in later section with other gifs! With the visual aspect done, we can finally tackle having a playable game!

Game loop

Now for the big one, the core game loop. The goal was to create constant action with no downtime, aligning with our target experience.

The loop, originally designed by Sam and refined further by myself, follows this structure:


  1. Game starts
  2. Play a round
  3. Check if it's the final round
    • No? → Choose a Chaos Factor → Start the next round
    • Yes? → Podium → Timer → Restart New Game from Round 1

To keep things exciting, players can even fight each other during the podium phase!

UI & Systems

The Menu!

Basic Point System
Choas Card Selection

Chaos Factors! Yes indeed, Sam is in charge of a gameplay mockup so stay tuned!

And finally, after a few rounds… a winner is declared! After some quick mockups, the prototype podium was born


completing the full gameplay cycle.

From start to finish, players are always in the action, fighting to the death until a winner emerges. But with the foundation set, it was time to add more mechanics...

Jumping

Previously, we discussed implementing custom jump mechanics, but due to time constraints, we opted to tweak Unreal Engine’s default movement component instead. By adjusting key variables, we achieved a jump that felt snappy yet slightly floaty, while still allowing airborne control.

It’s not perfect, but it works for now, so let’s move on to enhanced violence!

Punching

Melee combat is a core mechanic, after all, this is a brawler, not a shooter. To make melee combat feel natural:

  • Punching works on a full 360-degree axis
  • Players can move while attacking

With that, unarmed combat was born!

But punching while holding a weapon doesn't feel right, does it?. Naturally, the next step was throwing weapons. However, before we could throw weapons, we needed a way to pick them up, and to pick them up, we first had to spawn them...

Spawing weapons

Ahhh there we go, weapons now rain down onto the battlefield, as if hurled by an unseen overseer eager to escalate the chaos. While the timing of weapon spawns still needs fine-tuning to feel less predictable, the core system is in place.


Weapon pick up

With weapons now littering the stage, players need a way to grab and wield them. What good is a battleground full of weapons if no one can use them?


Perfect!

Now, with a simple pickup mechanic, players can seamlessly transition from punching to gunfire the moment they grab a weapon! So let's add the ability to throw them!

Weapon throw

Right now, throwing only discards the weapon, but we’re working on:

  • A more advanced throwing system where weapons act as projectiles
  • A system where thrown weapons deal damage and apply knockback
  • A proper ammo system, giving players a reason to throw weapons when they run out

With this, every discarded weapon could become a deadly projectile leading to even more chaotic and dynamic combat.

Overview

This week, we aimed to deliver a playable demo of the game! Most core mechanics made it in, with only minor adjustments and missing features left to be implemented.

Rather than repeating what’s already been covered, here’s what’s still left to complete the game:

  • Weapon throwing and pickup still need relative velocity logic, as well as damage and knockback.
  • Weapons lack an ammo system, making them overpowered in their current state.
  • Wall sliding didn’t make it into the demo, though it may be added later as an extra mechanic.

Closing Thoughts

We promised a demo, and we delivered! While far from perfect, it proves that our core gameplay is fun and with more time and effort, it can be fun!

If you’d like to try it for yourself, a link to the demo is attached to this post!

This week also marked the finalization of our design decisions. With the team having a clear vision of the game, we can now move into full production starting next week.

What’s Coming Next Week?

Next week, we’ll be presenting our demo to our supervisors. If they see its potential, we’ll transition into productio, starting from scratch to develop the game properly with all systems in place.

That means our artists will finally get to shine, bringing the game’s visual identity to life!

That wraps up this week’s devlog! If you’re here for more technical details, stick around below. Otherwise see you next week!



More Technical!

Just like last week, let’s take a deeper dive into our systems and mechanics—what worked, what didn’t, and what we learned.

Disclaimer (Same as Last Week):

In the following sections, you’ll also find code snippets to illustrate my thought process and workflow. However, please keep in mind that most of this code is purely for prototyping purposes and is by no means good code.

On top of that, a lot of this code was AI-generated to speed up the prototyping process. I want to highlight this because the code doesn’t follow many of the rules and guidelines outlined in our Tech Document, including one of our most important rules:

NO AI CODE IN PRODUCTION

This is strictly for prototyping, so with that disclaimer out of the way, let’s jump in!

Bug Fixes

Not much to say here, writing quick and dirty code (especially AI-generated code) comes with bugs and unexpected behavior. Still, we managed to fix most of them to keep development moving.

One notable bug involved player colliders staying in the world after ragdolling. Since player characters use separate physics bodies for ragdolling, the collider remains active even after the player is knocked out.

At first, I disabled the collider when a player entered ragdoll mode. Simple, right? Well… no. Disabling the collider meant that the collider would fall through the map. While that might seem fine but inefficient at first, Unreal Engine has something called KillZ.

What is KillZ?

KillZ is Unreal Engine’s death plane, anything that drops below the specified Z value is automatically destroyed. That meant if the collider fell through the map, the player would be deleted entirely.

Lowering the KillZ value I hear you say? Unfortunately it wouldn’t fix the issue, just delay it until the player fell further. Instead of disabling it entirely, I moved the collider below the map, out of the way, but still existing.

This fixed the issue of the collider being in the way! And so I used a similar method to handle the player’s mesh falling out of the map, ensuring it gets teleported somewhere safe instead of being outright deleted. To avoid the player 0 being destroyed and messing with the camera.

Player Differentiation

For assigning player nametags, I opted to handle it through the game mode. Since the game mode creates players and controllers in a consistent order, I added a short delay to ensure all players existed before looping through them and assigning names in order. This works for now, but relying on Unreal’s consistency in assigning controllers and creating players in the same order isn’t ideal.

For production, my plan is to shift this responsibility to the controller itself, allowing it to assign a name to the player it possesses instead. This approach would make the system more reliable and independent of any potential inconsistencies in Unreal’s player creation process.

Arena knockout

As mentioned earlier, the arena system was completely reworked. Last week, I talked about how the OnDeath function was being triggered when reloading the level, this issue is now resolved with the new system.

The new approach uses overlap events to start and stop a timer:

  • When a player enters the DeadZone, a timer starts.
  • If the timer runs out while they’re still in the DeadZone, OnDeath is triggered.
  • The timer duration is adjustable in real-time, making it easy to tweak during playtesting.


This method is much simpler than the previous system and eliminates the major issues we ran into before.

On-Screen Player Indicator

 To help track off-screen players, I implemented an on-screen indicator. The logic for this was entirely done in Blueprints, and the indicator itself is a simple widget containing an arrow. Each player gets their own indicator when the game starts.

This implementation was heavily inspired by a video from Verter Construction, but I simplified certain steps based on our needs. It's also important to note that all of it was done in the tick function but it can all be moved to an event based sytem, saving on precious frames. Here’s a breakdown of how it works:

  1. Getting the Viewport & Scaling

    • First, I retrieve the viewport size and scale.
    • I also define minimum and maximum clamping values to keep the indicator within screen bounds.
    • This step could be done with viewport events and is not really necessary in our case as we don't have the option of resizing the viewport yet.
  2. Checking If the Player is Off-Screen

    • I use ProjectWorldToScreen to convert the player’s world position into screen space.
    • Extra checks are done with the min and max clamps ensuring precise detection of the player offscreen.
    • The position of the widget is then set in screen space based on the player's position.
  3. Clamping the Widget to the Screen Edge

    • The indicator is positioned at the closest point to the player within the visible screen space using the clamps.
    • This ensures the widget always stays on-screen.
  4. Angle Calculation for Arrow Direction

    • The video now uses complex 3D projection to find the angle of the indicator.
    • In the video, Verter Construction creates a point in the middle of screen space and traces a line towards the object being tracked using an offset. Those are the White and Green Circles. The Orange line represent the line in 3D Space from the center of the viewport to the target. Next we need to project that line onto screen space (blue line) and clamping its maximum value to the viewport (cyan rectangle) that is how we get the purple sphere, the position of the indicator with a given angle.
    • In our case it's much simpler. Our player is already stuck in 2D space. It is a simple matter of moving the center of the screen to the same plane as the player and our projection is done!
    • Using basic trigonometry, I extract the angle and apply it to rotate the arrow indicator in the correct direction.
  5. Visual Scaling Based on Timer

    • The size of the indicator changes dynamically based on how much time remains before the player is eliminated.
    • At full time, the indicator is at 100% scale, and as time runs out, it shrinks to 0%.

This streamlined method provides a precise and reliable off-screen indicator without unnecessary complexity.

Other Notes

There isn’t much to add regarding map scaling, bullet adjustments, game loop, or jumping. Jumping was simply fine-tuned using Unreal’s built-in variables. While it’s not exactly what we want yet, it’s close enough for the demo.

With that, let’s move on to Punching!

Punching

We already had an existing attack system, all we needed was to add functionality for unarmed combat. This was done using a simple boolean state to check whether the player had a weapon or not.

For the actual punching mechanics, we used a mix of Blueprints and C++.

We started by assigning a sphere collider to the player’s hand and binding an overlap function to it.

  • When the player attacks, we broadcast an event and set the sphere collision to OverlapAll.
  • At the same time, we disable the ability to attack to prevent spam.
  • In the overlap detection, we check if we hit another actor and apply damage and knockback.
  • After that, we disable collision to prevent the attack from dealing damage every frame.

The next step was handling the broadcasted event in Blueprints.

  • A custom event is assigned to the broadcasted signal.
  • When the punch animation plays, it waits for completion before calling ResetPunch().
  • ResetPunch() (handled in C++) unlocks the ability to attack again.

While a "Do Once" node is included, it’s technically redundant—the event cannot be triggered again before ResetPunch() runs. But having a safeguard in place doesn’t hurt.

And with all that we have Punching! But there’s another potential approach that might be more efficient: tracing the animation using animation events. However, for now, our current method works perfectly.

One notable advantage of our setup is that, because the animation montage plays before pitch adjustments, we can blend the punch animation dynamically, allowing attacks on a full 360-degree axis.

Final Notes

For now, I’ll skip talking about the weapon pickup and throw mechanics since they’re still in a basic state and not fully implemented. Right now, they simply attach and detach weapons to the player while toggling collision and physics.

Final Words

That wraps up this week’s devlog!

I Hope you enjoyed this deep dive. If you have any questions, comments, or better ideas, let us know!

See you next week!

Files

BrawlstormDemo-v1.0.rar 346 MB
39 days ago

Get [Group26]Brawlstorm

Leave a comment

Log in with itch.io to leave a comment.