Making Da○Saba○ Bar (No. 2)

I hope we didn't keep you waiting too long this time.
This is Matsuyama-san from the System Development Department.

We are now bringing you the second installment of "Creating a Da○saba○bar," which began abruptly from the last issue

Click here for the first issue↓

Making Da○Saba○bar (first issue)

In the first issue, we displayed the player, enemies, and field, and implemented the ability to move the player

I think the appeal of "Da○saba○ber" is the exhilaration of defeating large numbers of zombies with a wide variety of weapons, so I plan to implement weapons in the second issue

Weapon type

However, it would take too much time and effort to implement all of the numerous weapon types, so for now I'll narrow it down to about three types

① Shotgun (default weapon)
② Brick
③ Guardian

Around here

As usual, I searched for images that could be used as resources from Undead Survivor and used them

① I found the exact shotgun.
② I don't have any bricks. I have all the farming tools, so I'll throw a plow.
③ I don't have any disc-shaped guardians. I'll swing a sickle around.

Shotgun

Identify the requirements

① Fires in the direction of the player (direction of travel)
② The number of bullets fired increases depending on the level
③ The firing interval shortens depending on the level
④ The range increases depending on the level
⑤ If a zombie is nearby, it will fire at the zombie (auto aim)
⑥ The bullet flies in the direction of ① for a set period of time and disappears
⑦ If it hits a zombie, it will not penetrate

It was surprisingly common

① to ⑤ are the process leading up to firing (Weapon_1),
⑥ to ⑦ are the bullet process (Bullet).

So we will separate each into a class.
Weapon_1 generates a Bullet, and the Bullet that is fired moves and disappears on its own.

Basically, you get the player's direction from the Player class and determine the base ray.
Then, you can rotate the ray by ±n degrees based on the starting point (player coordinates) depending on the number of bullets, and you can scatter bullets in a fan shape.

These parameters are provided for control purposes

// Bullet firing interval (3 levels) private readonly float[] interval = { 1.5f, 1.25f, 1.0f }; // Bullet range (3 levels) private readonly float[] range = { 4.0f, 6.0f, 8.0f }; // Number of simultaneous shots (3 levels) private readonly int[] simultaneous = { 1, 3, 5 }; // Firing angle (5 directions: depends on the number of simultaneous) private readonly float[] angle = { 0, 10, -10, 20, -20 };

For ⑤,
the EnemyController class searches for nearby zombies.
If one is found, the vector between the player's coordinates and the zombie's coordinates becomes the ray of fire.
The bullets are scattered in the same way as above.

After firing the bullet, the Bullet class will move autonomously. If
it moves and hits a zombie, a collision will be detected, and by deleting its own object, it will prevent the bullet from penetrating.
If it does not hit, it will still delete itself after a certain period of time.

And so the shotgun is completed.
Here are the finished products:
Level 1

, Level 2

, Level 3

Brick (plow)

① Throw it upwards.
② Fall in an arc at a certain height.
③ Delete it when it reaches the bottom (off-screen).
④ It will penetrate even if it hits a zombie (up to three)
. ⑤ Increase the number of throws depending on the level. (Throw with a time lag.)

The class will be configured in the same way as the shotgun.
Weapon_2 will generate a plow. The plow itself will then fly in a parabolic trajectory.
The enemy's position is not particularly important.

The biggest problem is the formula for drawing a parabola.
After a bit of searching, I found a great site.
I want to shoot an arrow in a parabolic trajectory (ignoring 2D gravity)
. It's perfect. Thanks to Hatena Blog.
This formula calculates the coordinates on a Bézier curve specified by the start point (p0), vertex (p1), and end point (p2). I
'll also create a coroutine by adding a process to rotate the direction of the arrow by 180° near the vertex.

///<summary> /// Draw a parabola ///</summary> ///<param name="p0"> starting point</param> ///<param name="p1"> Vertex (relative coordinates)</param> ///<param name="p2"> End point (relative coordinates)</param> ///<returns> Coroutines</returns> IEnumerator Throw (Vector3 p0, Vector3 p1, Vector3 p2) { float distance = Vector3.Distance(Vector3.zero, p2); float speed = 0.3f; float t = 0f; while (t <= 1 && isAlive) { float Vx = 2 * (1f - t) * t * p1.x + Mathf.Pow (t, 2) * p2.x + p0.x; float Vy = 2 * (1f - t) * t * p1.y + Mathf.Pow (t, 2) * p2.y + p0.y; transform.position = new Vector3 (Vx, Vy, 0); t += 1 / distance / speed * Time.deltaTime; // Rotate gradually by 180 degrees while t is between 0.4 and 0.6 if (t > 0.4f && t < 0.6f) { float angle = Mathf.Lerp(0, courseGoal[course], (t - 0.4f) / 0.2f); transform.rotation = Quaternion.Euler(0, 0, angle); } yield return null; } Destroy (this.gameObject); }

* p1 and p2 needed to be relative coordinate values, so this has been corrected (March 22, 2024)

All you need to do is specify p0 to p2 when generating the Plow.
By adding random numbers to the height of the vertices and the width from the start point to the end point to create some variation, it will look more realistic.
The finished product is shown below:
Level 1

Level 2

Level 3

Guardian (Scythe)

The one that spins around the player

① Rotates around the player
② The number increases as the level increases
③ Does not disappear even when hitting a zombie (pierces)

Yes, it has the fewest requirements

The construction is the same. Create a Sickle class with Weapon_3.
Simply place them at equal intervals depending on the number you want to place and rotate them at the same speed.
For circular motion, you can calculate the coordinates (offset values) using trigonometric functions.
After that, they will follow the player, so all you need to do is add the player's coordinates.

With these definitions in place,

// Radius public const float Radius = 4.0f; // Rotation speed (per second) private const float RotateSpeed ​​= 270f; // Spin speed (per second) private const float SpinSpeed ​​= 1080f; // Angle (angle for determining position) private float rotateAngle = 0.0f; // Angle (rotation) private float spinAngle = 0.0f;

The rest is handled by the framework

void Update() { // Increase angle (revolution) rotateAngle -= RotateSpeed ​​* Time.deltaTime; // Increase angle (rotation) spinAngle -= SpinSpeed ​​* Time.deltaTime; // Convert angle (revolution) to radians float rad = rotateAngle * Mathf.Deg2Rad; // Convert angle (rotation) to radians float spinRad = spinAngle * Mathf.Deg2Rad; // Update position Vector2 pos = player.Position; transform.position = new Vector3( pos.x + Radius * Mathf.Cos(rad), pos.y + Radius * Mathf.Sin(rad), 0.0f ); // Update rotation transform.rotation = Quaternion.Euler(0.0f, 0.0f, spinAngle);

While doing the circular motion, rotate the sickle itself.
The finished product is below:
Level 1

Level 2

Level 3

Debugging UI

Create a debug UI to check the operation

・Levels 1 to 3 can be set for all weapons.
・Weapon 1 is level 1 by default.
・Weapons 2 and 3 are not yet acquired.

You can quickly create it by adding legacy buttons, etc

That's all for this month

That's all for today.
Thanks to the websites I used as reference, I think I was able to implement it fairly quickly.
It's fun to create something with Unity, even if it's just a mini-game.

By the way, this is what it looks like in full attack mode

Next time

- Zombie ecology
- Collecting experience points and leveling up weapons

I hope to be able to implement something like this

As usual, the entire project is available on GitHub.
I hope it will be helpful.
BeBe Survivor

Well, that's all for now.

If you found this article helpful , please give it a like!
7
Loading...
7 votes, average: 1.00 / 17
547
X facebook Hatena Bookmark pocket

The person who wrote this article

About the author

Kensho Matsuyama

For a long time, he worked at a game development company, working in programs and project management.
Joined Beyond Co., Ltd. in 2019.
He works in the Yokohama office. He is mainly responsible for project management of server-side development work.
(Sometimes programming) His hobbies are cycling (road racer) and watching horse races.