Unity 2D side-scrolling game (JUNGLE RULES)

Table of contents

< Game Demo >

< Project content >

(1) Project content

< Project Analysis >

(1) Game planning

(2) Game art

(3) Game program

< Project implementation >

(1) Game character (Player)

(2) Enemy

(3) UI interface

(4) Camera

(5) Billboard

(6) Game scene (Scene)

< project source code >​​​​​​​


< Game Demo >

    

    

    

    

Alibaba cloud disk sharinghttps://www.aliyundrive.com/s/tty5y5BumD1Extraction code: ov67

< Project content >

(1) Projectcontent

JUNGLE RULES is a side-scrolling game made with Unity2D. It can mainly achieve the following functions:

1. Character control: A key to run left, D key to run right, Q key to switch attack mode, J key to attack (chopping in knife mode, shooting in gun mode), K key to jump (can be performed Double jump), L key to read the notice board. When a character is hit, his blood will be deducted. When the blood tank is empty, he will die. After death, he will be reborn in the current level. When attacking a mob with a knife, it will produce a blade effect, and when attacking a mob with a gun, it will produce an explosion effect.

2. Simple mob AI: Two types of monsters, one is sword-wielding mobs, and the other is non-sword-wielding mobs. Both types of mobs can achieve the function of random walking within a specified range. When the player enters the mob warning range, the mobs automatically approach the player. Players will lose blood when they encounter mobs. When mobs holding swords get close to the character, they will slash with their swords simultaneously. When a mob is hit, it flashes red and loses blood, and disappears when it dies.

3.UI interface: The main interface displays the game title, the start game (PLAY) button and the exit game (QUIT) button, all of which enable logical interaction. The character’s health bar and bullet count are displayed on the upper left side of the game interface, and will change with the specific values. The game end interface displays an ending message and an exit game button.

4. Construction of levels: The game mainly has two levels, the novice village level and the main level. Build a simple map for the Novice Village level. The main levels are designed in the form of a maze. Players operate on map blocks that they can stand on. If they fall off the map and die, they will be reborn.

5. Other objects and logic:Notice Board – When a character approaches the notice board and presses the L key, the notice content will be displayed. Teleportation Array – Characters automatically enter the next level after entering the teleportation array. Game camera – automatically follows characters, and the camera vibrates when monsters are hit.

< Project Analysis >

(1) Game planning

1.1 Game plot:

Many green monsters with helmets appeared in the forest, threatening people’s survival. For this reason, hunters set out into the forest with swords and guns to defeat the monsters and give people a peaceful life.

1.2 Game levels:

The game is divided into two levels. In order to guide new players to gradually become familiar with the game operations, a simple map is built in the Novice Village level, and one sword-wielding mob and one non-sword-wielding mob are placed to allow players to understand the attack modes of the mobs. The Novice Village level is equipped with a notice board that gives players operation prompt information, and players can read it when needed. After players have adapted to the operation, they can choose to enter the teleportation array to reach the main level.

The main level builds a complex map. With the limited camera perspective, players cannot understand the entire map and can only explore slowly. Place multiple mobs throughout the main level to increase the difficulty of the game. In addition, players will also face the risk of falling out of the map and dying. The design of the map needs to reflect such elements. When the player completes the exploration, peace is brought to the forest. The player enters the end scene through the teleportation array located deep in the level, the end of the game.

1.3 Game balance:

The character’s health value is set to 30, the character’s maximum ammunition load is set to 7, the character’s attack damage is set to 2, the health value of the mobs is set to 10, the damage of non-sword-wielding mobs is set to 1, and the damage of sword-wielding mobs is set to 1. Damage is set to 3. Overall, the game difficulty is relatively simple and does not put too much operational pressure on players. Although the sword-wielding mobs attack more frequently and cause higher damage, they can be defeated without any damage as long as the player attacks with a gun.

(2) Game art

The overall art style of the game is pixel style. The theme of the game is hunters and forests, so green is mostly used in the selection of materials. Different background images are applied to the menu scene, Novice Village scene, main scene, and end scene. Build a map using map tiles and decorate it with farm-themed material packs.

All game materials come from Unity’s official resource store and online trading platform. They are obtained for a fee and there is no infringement of art copyrights.

(3) Game program

3.1 Mainly involved objects and functions.

3.1.1 Game Character (Player)

The attributes of the game character itself are: movement speed, jumping speed, character health, and attack damage.

The five actions of the game character are: standby, running, jumping, falling, and attacking. First, on the display layer, we need to use the Animator component to control character animation to achieve animation switching. Then at the logical level, we need to write relevant functions in the C# script. When the system receives the corresponding input from the keyboard and meets the conditions, it calls the function to execute the relevant logic, and finally realizes the overall visual effect of the action.

As the most important part of the game, game characters interact with various objects in the game. We need to detect the collision between the game and the object, and then trigger the corresponding function. When a character collides with a mob, the character’s injury function is called. When the collision boxes of bullets and swords collide with mobs, the mob’s injury function is called. When the character collides with the portal, the transfer function is called to enter the next scene. When the character collides with the bulletin board, press L to call the function that displays the bulletin information.
3.1.2 Enemy

The attributes of the game mobs themselves are: movement speed, mob health, and mob damage.

The three actions of game monsters are: standby, running, and attacking. Also use the Animator component in the display layer to switch animations. At the logic layer, use C# script to control the Animator component to switch.

There are two different mobs in the game, but the two mobs are similar in the implementation of the common basic logic. We write the abstract base class Enemy, and inherit the sword-wielding mob (EnemySK) and non-wielding mobs on the basis of Enemy. Sword mobs (EnemyNSK). In the base class, three basic logics are implemented: the mob is injured when hit, the character is injured when hit, and the mob is injured and flashes red. Write the mob animation switching logic and random walk in the script of the derived class.

3.1.3 UI interface (Canvas)

The game theme “JUNGLE RULES” is displayed on the main interface, and the guide “Defeat Enemies And Save People!” guides players into the basic game plot. There are two buttons on the main interface. Click the PLAY button to enter the Novice Village scene. Click the QUIT button to exit the program. The game interface can obtain the character’s health and bullet count parameters, and dynamically change the health slot and bullet count slot. The ending interface displays the closing words “Appreciation To Your Bravery” to praise the player’s courage, set an exit button, and click the exit game (QUIT) button to exit the program.

3.1.4 Camera (Main Camera)

The camera always follows the character to display the map screen, ensuring that the character is always in the center and lower position of the screen. At the same time, the camera cannot extend beyond the map boundaries, showing the contents of a blank canvas. When the character jumps out of the map, the camera is restricted to the bounds. The camera also has an Animator component, which can realize camera vibration animation when the monster is hit.

3.1.5 Billboard and Trans

The implementation logic of these two objects is similar and they both use collision bodies. The notice board detects a collision with a character and displays a notice message when L is entered on the keyboard. The notice information disappears automatically after the character leaves. The teleportation array uses the scene management class (SceneManagement) of the Unity engine to jump to the scene.

3.2 Division of scenes

   
The game is mainly divided into four scenes: the main menu scene, the novice village scene, the main level scene, and the end scene, which are played in order.

 < Project implementation >

(1) Game character (Player)

    

//Player Controller(Script)
public class PlayerController : MonoBehaviour
{
public float runSpeed;//Character running speed
public float jumpSpeed;//The character’s first bounce speed
public float doubleJumpSpeed;//The second bounce speed of the character

private Rigidbody2D myRigidbody;//Rigid body component
private Animator myAnim;//animation component
private BoxCollider2D myFeet;//Square collision body component
private bool isGround; //Record whether the foot touches the ground
private bool canDoubleJump;//Determine whether a double jump can be performed

// Start is called before the first frame update
void Start()
{
myRigidbody = GetComponent<Rigidbody2D> ();//Call the rigid body component of the object
myAnim = GetComponent<Animator> ();//Call the object animation component
myFeet = GetComponent<BoxCollider2D> ();//Call the object square collision component
}

    // Update is called once per frame
void Update()
{
    Run();//Realize character running left and right and animation display
    Flip();//Flip the material horizontally when running left and right
    Jump();//Implement character jumping logic
    CheckGrounded();//Detect whether the character is touching the ground
    SwitchAnimation();//Realize animation switching when characters jump
    SwitchMode();//Switch attack mode
}
 
//Player Health(Script)
public class PlayerHealth : MonoBehaviour
{
public int Health;//character health value
private Animator myAnim;//animation component
    // Start is called before the first frame update
    void Start()
    {
        Healthbar.HealthMax = Health;//Set the life bar of the UI interface
        Healthbar.HealthCurrent = Health;//Set the life bar of the UI interface
     myAnim=GameObject.FindGameObjectWithTag("Player").GetComponent<Animator>();
    }//Call Player’s animation component

    // Update is called once per frame
    void Update()
    {
        if (Health <= 0)
        {
            Invoke("Restart", 3f);//Death will respawn after 3 seconds
        }
        if (transform.position.y < -20)// If you fall out of the map, you are dead
        {
            Health = 0;
            Healthbar.HealthCurrent = Health;
        }
    }
    public void DamagePlayer(int damage); //Character injury function, called by mobs
void Restart();//rebirth function
}

PlayerAttack is used to implement the character’s knife attack, and BulletHit is used to implement the character’s gun attack.

//Player Attack(Script)
public class PlayerAttack : MonoBehaviour
{
    public int damage; //Attack damage
    public float time; //attack action duration
    public float startTime; //Attack action start time
    public GameObject SwordPrefab;//Attack effect

    private Animator anim;//animation component
    private PolygonCollider2D collider2D;//Polygon collision component
    private bool CanAttack;//Can attack (the next attack can only be carried out after one attack)

    // Start is called before the first frame update
    void Start()
    { //Call the Player animation component
        anim = GameObject.FindGameObjectWithTag("Player").GetComponent<Animator>();
        collider2D = GetComponent<PolygonCollider2D> ();//Calling the collision body component
        CanAttack = true;
    }

    // Update is called once per frame
    void Update()
    {
        Attack();//Attack implementation function
}
Attack()//Detect input and call coroutine
    IEnumerator StartAttack()//The coroutine waits for a certain period of time to activate the attack collision box
    IEnumerator disableHitBox()//The coroutine waits for a certain period of time to cancel the attack collision box
    void OnTriggerEnter2D(Collider2D other)//Detect collision and call mob injury function
}

//Bullet Hit(Script)
public class BulletHit : MonoBehaviour
{
    private int Bullet = 7;//Set the maximum number of bullets
    private bool canShoot = true;//Mark whether there is a bullet
    public GameObject BulletPrefab;//Bullet prefab
private Animator anim;//animation component
    // Start is called before the first frame update
    void Start()
    {
        Bulletbar.BulletMax = Bullet;//Set the bullet slot of the UI interface
        Bulletbar.BulletCurrent = Bullet;//Set the bullet slot of the UI interface
        anim = GameObject.FindGameObjectWithTag("Player").GetComponent<Animator>();
        //Call the player's animation component
    }
    // Update is called once per frame
    void Update()
    {
        if (Input.GetButtonDown("Attack") && anim.GetBool("Armed"))//Press J while holding a gun
        {
            if (Bullet > 0)//There is a bullet
            {
                anim.SetTrigger("Attack");//Set attack animation
                Instantiate(BulletPrefab, transform.position, transform.rotation);
                //Generate bullets at the muzzle
                Bullet -= 1; //The number of bullets is reduced by 1
            }
        }
        if (Input.GetButtonDown("Loading"))//implement loading
        {
            Bullet = 7;
        }
        Bulletbar.BulletCurrent = Bullet;//Transmit the number of bullets to the UI interface in real time
    }
}

//Bullet(Script)
public class Bullet : MonoBehaviour
{
    public float speed;//bullet flight speed
    public int damage;//bullet damage
    public float destroyDistance; //The longest flight distance of the bullet
    public float time;//produce an explosion effect and disappear after time seconds
    public GameObject ImpactEffect;//Bullet explosion effect

    private Rigidbody2D rb2d;//Rigid body component
    private Vector3 startPos;//Three-dimensional vector records the bullet exit position

    // Start is called before the first frame update
    void Start()
    {
        rb2d = GetComponent<Rigidbody2D> ();//Call the object rigid body component
        rb2d.velocity = transform.right * speed;//Set flight speed
        startPos = transform.position;
    }

    // Update is called once per frame
    void Update()
    {
        float distance = (transform.position - startPos).sqrMagnitude;//Calculate the distance flown
        if (distance > destroyDistance)//Automatically eliminate beyond flight distance
        {
            Destroy(gameObject);
        }
    }
void OnTriggerEnter2D(Collider2D other)//Colliding with a mob and calling the mob injury function 
//Produce bullet explosion effect
}

(2) Enemy

       

   

//Enemy(Script)
public abstract class Enemy : MonoBehaviour
{
    public int Health;//Mob health value
    public int damage;//Mob damage
    public float flashTime;//red flash time
    public float DeathTime; //Death animation playback time
    private SpriteRenderer sr; //Image rendering component
    private Color originalColor;//Initial color
    private PlayerHealth playerHealth;//player health value

    // Start is called before the first frame update
    public void Start()
    {
        playerHealth = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerHealth> ();//Get life
        sr = GetComponent<SpriteRenderer> ();//Call component
        originalColor = sr.color;//Save the initial color
    }

    // Update is called once per frame
    public void Update()
    {
        
    }
    public void TakeDamage(int damage) //Mob damage function
    void FlashColor(float time) //Red flash function of mobs
    void ResetColor()//Reset to original color
    void OnTriggerEnter2D(Collider2D other)//Deduct blood when colliding with a character
}

//Knight(Script)
public class Knight : Enemy
{
    public float speed;//Mobile moving speed
    public float startWaitTime;//Waiting time for mobs
    private float waitTime; //Record the time elapsed to reach a certain point
    private Rigidbody2D myRigidbody;//Rigid body component

    public Transform movePos;//Move position
    public Transform leftPos;//The leftmost end of the patrol range
    public Transform rightPos;//The rightmost end of the patrol range
    private Transform playerTransform;//character position
    private Animator myAnim;
    private BoxCollider2D Bcollider2D;

    // Start is called before the first frame update
    public void Start()
    {
        base.Start();//Call the Start() function of the base class
        waitTime = startWaitTime; //Initialize waiting time
        movePos.position = GetRandomPos();//Initialize the mob’s moving position to a random position
        myAnim = GetComponent<Animator>();
        Bcollider2D = GetComponent<BoxCollider2D>();
        playerTransform = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform> ();//Get the character’s position
    }

    // Update is called once per frame
    public void Update()
    {
        base.Update();//Call the Update() function of the base class
        if (Health > 0)
        {
            Guard();//Perform patrol
        }
        else
        {
            myAnim.SetTrigger("Die");//Call the death animation
            Bcollider2D.enabled = false;//The mob collision body is invalid
            Invoke("KillEnemy", DeathTime);//Destroy the object after the death animation is played
        }
    }
    void KillEnemy()//Destroy the object
    Vector2 GetRandomPos()//Get random position
    void Flip()//Horizontal flipping of the mob image when the mob moves left and right
    void Guard()//Random walk pursuit character implementation function 
}

(3) UI interface

   

//Health bar(Script)
public class Healthbar : MonoBehaviour
{
    public Text HealthText;//The health value displayed on the UI
    public static int HealthCurrent;//Current life
    public static int HealthMax;///Maximum life

    private Image healthbar;//life bar image
    // Start is called before the first frame update
    void Start()
    {
        healthbar = GetComponent<Image> ();//Calling the life bar
        HealthCurrent = HealthMax;
    }

    // Update is called once per frame
    void Update()
    {
        healthbar.fillAmount = (float)HealthCurrent / (float)HealthMax;//Set the health bar filling amount
        HealthText.text = HealthCurrent.ToString() + "/" + HealthMax.ToString();//Set the raw                                    
                                                                                  health
    }
}

//Bullet Bar(Script)
public class Bulletbar : MonoBehaviour
{
    public Text BulletText;//The number of bullets displayed on the UI
    public static int BulletCurrent;//The current number of bullets
    public static int BulletMax;//Maximum number of bullets

    private Image bulletbar;//bullet bar image
    // Start is called before the first frame update
    void Start()
    {
        bulletbar = GetComponent<Image> ();//Call the bullet bar
        //HealthCurrent = HealthMax;
    }

    // Update is called once per frame
    void Update()
    {
        bulletbar.fillAmount = (float)BulletCurrent / (float)BulletMax;//Set the bullet bar filling amount
        BulletText.text = BulletCurrent.ToString() + "/" + BulletMax.ToString();//Set the child 
                                                                                  Bullet value
    }
}

(4) Camera

       

Camera Follow(Script):
public class CameraFollow : MonoBehaviour
{
    public Transform target;//Tracking target (set to Main Camera)
    public float smoothing;//smoothing constant

    public Vector2 minPosition; //Track the lower left corner of the border
    public Vector2 MaxPosition;//Track the upper right corner of the border

    // Start is called before the first frame update
    void Start()
    {
        GameController.camShake = GameObject.FindGameObjectWithTag("CameraShake").GetComponent<CameraShake>();
    }
    void LateUpdate()//triggered later
    {
        if (target != null)
        {
            if (transform.position != target.position)//implement following
            {
                Vector3 targetPos = target.position;
                targetPos.x = Mathf.Clamp(targetPos.x, minPosition.x, MaxPosition.x);
                targetPos.y = Mathf.Clamp(targetPos.y, minPosition.y, MaxPosition.y);
                transform.position = Vector3.Lerp(transform.position, targetPos, smoothing);
            }
        }
    }
    public void SetCamPosLimit(Vector2 minPos, Vector2 maxPos)
    {
        minPosition = minPos;
        MaxPosition = maxPos;
    }
}

(5) Billboard

   

//Sign(Script)
public class Sign : MonoBehaviour
{
    public GameObject dialogbox;//Bulletin Board
    private bool isPlayerInSign;//Mark the collision between the character and the bulletin board
    // Start is called before the first frame update
    void Start()
    {
        dialogbox.SetActive(false);//Set the announcement information to be invisible
    }
    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.L) && isPlayerInSign) 
        {
            dialogbox.SetActive(true);//Set the announcement information to be visible
        }
    }
    void OnTriggerEnter2D(Collider2D other)//Detect collision and assign value to isPlayerInSign
void OnTriggerExit2D(Collider2D other)//Leave the collision body and set the announcement information to be invisible
//isPlayerInSign changes synchronously
}

(6) Game scene (Scene)

< project source code >

JUNGLERULES_Unity project file.rar-Other document resources-Download

Related Posts

Unity uses XML to create a simple login system

How to play videos in Unity

UE4_UE5 making 3DUI-following the camera direction (with project)

Unity[DateTime]- How to add a validity period to the software

[Unity3D-UGUI Application] (4) Using UGUI pop-up window display model and pop-up window model interaction

unity3D terrain editor—Terrain

Unity exports the Android project and creates a new activity to place the privacy agreement

Unity game development: implementation of dialogue system

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*