Manual: BulletHell (Bullet Hell) Sample Project

In this tutorial, we will explain the structure and mechanics of BulletHellSample, a sample game featuring a bullet hell system.

◆ Game Overview

This is a game where you defeat a boss that fires bullet patterns with 500 HP using shots and bombs. Since this is a sample, the game ends once the boss is defeated. Move with arrow keys, shoot with the Z key, and use bombs with the X key. We have implemented common bullet hell mechanics such as “grazing” and “bullet cancellation via bombs.”

Game Scene Structure

The game consists solely of the scene test_scene.tscn, with no scene transitions.

Object Structure

Player Ship

player.tscn is the scene for the player ship. As child nodes, it includes GrazeObject.tscn (to implement grazing) and player_hit_checker.tscn (for hit detection).

Enemy Ship

enemy.tscn is the scene for the enemy ship. As a child node, it includes damage_checker.tscn (for hit detection).

Implementation of Each Feature

Enemy Bullet Patterns

The enemy bullet patterns are implemented simply by firing patterns at fixed intervals.

  1. The first pattern is accelerating omnidirectional bullets.
  2. The second pattern is a shotgun-style shot combined with movement.
  3. The third pattern is splitting bullets aimed at the player from the stage edges.
  4. The fourth pattern is a flower-like pattern combining omnidirectional bursts.
  5. The fifth pattern uses directional-changing bullets to draw simple shapes.

Since bullet patterns require repeated playback of sound effects (SE), we implement this by triggering AudioStreamPlayer sounds via an AnimationPlayer node. Although this approach is used due to the lack of appropriate sound sources, ideally, each bullet pattern should have its own dedicated sound source and trigger playback accordingly.

*Currently, the bullet pattern system lacks a mechanism to stop patterns. Even after defeating the enemy, any patterns already in the generation process will continue. We plan to fix this in an update by adding a bullet pattern stopping mechanism. For now, you can avoid this issue by avoiding repeat processing and instead dividing states to implement repetition.

Player’s Normal Shot Patterns

This is implemented by simultaneously firing four types of bullet patterns within a single state. Currently, rapid-fire types cannot specify firing directions, so we simulate direction by firing toward very distant global coordinates.
*We plan to update this soon to allow directional firing.

Grazing Processing

Grazing is implemented by placing GrazeObject.tscn as a child node, which has a larger hitbox than the player’s hitbox. When this object collides with a bullet, it emits grazing particles and adds to the score.

Damage Processing

Both the player and enemy use separate child objects for damage processing. There are two main reasons for this:

  1. To prevent ongoing states from being interrupted by damage.
  2. To clearly separate hit detection for “grazing” and “damage.”
    *In ACTION GAME MAKER, the “HitArea2D” collision detection checks all HitArea nodes under the root node, including child nodes. While this issue can also be avoided by generating objects as child objects rather than child nodes, we chose this approach to make it easier to visually verify the precise position of hitboxes.

Bullet Pattern Layer Structure

The player is on layer 1, enemies on layer 2, and grazing detection on layer 3.
Enemy bullet patterns are on layers 1 and 3.
Player bullet patterns are on layer 2.

Bomb Implementation

Bombs are implemented not as bullet patterns but as regular projectiles.
bomb.tscn is the scene for bombs. They are set to cover the entire screen with a hitbox, destroying any bullet patterns they collide with and converting them into score items with a 10% probability. Additionally, bombs are set to deal damage to the enemy itself.

*Converting bullets into score items involves object creation, which is a heavy process. Setting the conversion rate to 100% or similar values may cause performance drops. We are currently considering solutions for this issue.

Score Items

To reduce the processing load of object creation, score items are implemented using GDScript.
The scene is score_test.tscn. They move toward the player and disappear at a certain distance, increasing or decreasing a specified variable.
You can customize values via the Score node’s inspector.

PickUpRadius: Collision detection distance
PullSpeed: Speed
Group: Target group to approach
Project Variable: Name of the project variable to modify
Variable Add: Value to add

1 Like