- Päls & Fjäder -

Project Details
  • Project Length: 2 Weeks

  • Team Size: 14 people

  • Engine: Unity

  • Planning: Discord

  • Project Length: 2 Weeks

  • Team Size: 14 people

  • Engine: Unity

  • Planning: Discord

  • Project Length: 2 Weeks

  • Team Size: 14 people

  • Engine: Unity

  • Planning: Discord

  • My Roles: Character Programmer

  • Player 2 Character Controller

  • Water Bullets

  • Xbox Adaptive Controller

  • My Roles: Character Programmer

  • Player 2 Character Controller

  • Water Bullets

  • Xbox Adaptive Controller

  • My Roles: Character Programmer

  • Player 2 Character Controller

  • Water Bullets

  • Xbox Adaptive Controller

Squirrel Character Controller

This was my first project as a programmer at future games, I worked on the character controller for the squirrel.

A requirement for this project was that we use an Xbox adaptive controller meaning that all inputs needed to be performed on just two buttons, my biggest challenge at the time was configuring the inputs since I was new to unity´s input system.

The final controls ended up being left/right buttons rotate the squirrel and to fire the gun you need to press down both buttons.

Show Related Code

using UnityEngine;
using UnityEngine.UIElements;
using UnityEngine.InputSystem;
using FIMSpace.Basics;
using UnityEngine.Android;
using FIMSpace.Generating.Rules;
using UnityEngine.Serialization;
using Unity.Cinemachine;


public class H_SquirrelMovement : MonoBehaviour
{
    [FormerlySerializedAs("TurnRate")] [SerializeField] private float turnRate;
    [FormerlySerializedAs("PSpawnpoint")] [SerializeField] private Transform pSpawnpoint;
    [FormerlySerializedAs("ProjectileInterval")] [SerializeField] private float projectileInterval;
    [FormerlySerializedAs("WaterForce")] [SerializeField] private float waterForce;
    [FormerlySerializedAs("PelicanMovement")] [SerializeField] private Galla_PelicanPlayer pelicanMovement;
    [FormerlySerializedAs("BirdDirectionForce")] [SerializeField] private float birdDirectionForce;
    [FormerlySerializedAs("_animator")] [SerializeField] private Animator animator;
    [SerializeField] private ParticleSystem waterImpactSplash;
    [SerializeField] private float initialTurnRate = 1;
    [SerializeField] private float turnRateIncrement = 1;
    private float _projectileCountDown;
    private float _turnDirection = 0f;
    private CustomInputSystem _inputSystem;
    private bool _buttonDownA = false;
    private bool _buttonDownD = false;
    private float _currentTurnRate;
    private bool canShoot = true;

    [FormerlySerializedAs("Projectile")] public H_WaterBlob projectile;
    private Quaternion _squirrelWorldRotation;

    private PlayerInput _playerInput;
    private InputAction _acButtonAEnter;
    private InputAction _acButtonAExit;
    private InputAction _acButtonBEnter;
    private InputAction _acButtonBExit;

    private void Awake()
    {
        _currentTurnRate = initialTurnRate;
        _squirrelWorldRotation = transform.rotation;
        _playerInput = GetComponent<PlayerInput>();
        _acButtonAEnter = _playerInput.actions["SquirrelButtonAPressed"];
        _acButtonAExit = _playerInput.actions["SquirrelButtonAReleased"];
        _acButtonBEnter = _playerInput.actions["SquirrelButtonBPressed"];
        _acButtonBExit = _playerInput.actions["SquirrelRotateBReleased"];
        animator = GetComponent<Animator>();
    }

    private void Start()
    {
        _inputSystem = new CustomInputSystem();
        _inputSystem.Enable();
        waterForce = waterForce * 100;
    }

    private void Update()
    {
        if (_buttonDownA && _buttonDownD)
        {
            if (canShoot)
            {
                _currentTurnRate = initialTurnRate;
                if (_projectileCountDown <= 0)
                {
                    FireWaterGun();
                    _projectileCountDown = projectileInterval;
                }
                animator.SetBool("IsTurning", false);
                animator.SetBool("IsIdle", false);
                canShoot = false;
            }
        }
        else
        {
            RotateSquirrel();
            canShoot = true;
        }
        
        if (!_buttonDownA && !_buttonDownD && _projectileCountDown > 0)
        {
            animator.SetBool("IsIdle", true);
        }
        
        transform.rotation = _squirrelWorldRotation;
        _projectileCountDown = _projectileCountDown - Time.deltaTime;
    }

    private void RotateSquirrel()
    {
        if (_turnDirection != 0f)
        {
            animator.SetBool("IsTurning", true);
            animator.SetBool("IsIdle", false);
            if (_currentTurnRate < turnRate)
            {
                _currentTurnRate += turnRateIncrement;
            }
        }
        else
        {
            animator.SetBool("IsTurning", false);
            _currentTurnRate = initialTurnRate;
        }
        
        _squirrelWorldRotation *= Quaternion.Euler(Vector3.up * (_turnDirection * _currentTurnRate * Time.deltaTime));
    }

    private void FireWaterGun()
    {
        CinemachineImpulseSource cinemachineImpulseSource = GetComponent<CinemachineImpulseSource>();
        FMODUnity.RuntimeManager.PlayOneShot("event:/BalloonShoot", gameObject.transform.position);

        // Ensure the impulse is generated with the rotation aligned to the GameObject's forward direction
        cinemachineImpulseSource.GenerateImpulseWithVelocity(transform.forward * 0.2f);
        
        animator.SetTrigger("Shoot");
        animator.SetBool("IsIdle", false); // Ensure IsIdle is false when shooting
        
        Vector3 projectileSpawn = pSpawnpoint.position;
        Vector3 pelicanDirection = pelicanMovement.transform.forward;
        Vector3 pelicanSpeedVector = pelicanDirection * birdDirectionForce;

        H_WaterBlob projectile = Instantiate(this.projectile, projectileSpawn, pSpawnpoint.transform.rotation);

        projectile.waterForce = waterForce;
        projectile.spawnPointTransform = transform;
        projectile.pelicanSpeedVector = pelicanSpeedVector;
        projectile.waterImpactParticles = waterImpactSplash;
    }

    //-------------------------------------\/ Input Controls \/-----------------------------------------

    public void ButtonAEnter()
    {
        _buttonDownA = true;
        _turnDirection = -1f;
    }

    public void ButtonAExit()
    {
        if (_buttonDownA && _buttonDownD)
        {
            _buttonDownA = false;
            _turnDirection = 1f;
        }

        else
        {
            _buttonDownA = false;
            _turnDirection = 0f;
        }
    }

    public void ButtonBEnter()
    {
        _buttonDownD = true;
        _turnDirection = 1f;
    }

    public void ButtonBExit()
    {
        if (_buttonDownA && _buttonDownD)
        {
            _buttonDownD = false;
            _turnDirection = -1f;
        }

        else
        {
            _buttonDownD = false;
            _turnDirection = 0f;
        }
    }

    private void OnEnable()
    {
        _acButtonAEnter.performed += _ => ButtonAEnter();
        _acButtonAEnter.canceled += _ => ButtonAExit();
        _acButtonBEnter.performed += _ => ButtonBEnter();
        _acButtonBEnter.canceled += _ => ButtonBExit();
    }

    private void OnDisable()
    {
        _acButtonAEnter.performed -= _ => ButtonAEnter();
        _acButtonAEnter.canceled -= _ => ButtonAExit();
        _acButtonBEnter.performed -= _ => ButtonBEnter();
        _acButtonBEnter.canceled -= _ => ButtonBExit

Show Related Code

using UnityEngine;
using UnityEngine.UIElements;
using UnityEngine.InputSystem;
using FIMSpace.Basics;
using UnityEngine.Android;
using FIMSpace.Generating.Rules;
using UnityEngine.Serialization;
using Unity.Cinemachine;


public class H_SquirrelMovement : MonoBehaviour
{
    [FormerlySerializedAs("TurnRate")] [SerializeField] private float turnRate;
    [FormerlySerializedAs("PSpawnpoint")] [SerializeField] private Transform pSpawnpoint;
    [FormerlySerializedAs("ProjectileInterval")] [SerializeField] private float projectileInterval;
    [FormerlySerializedAs("WaterForce")] [SerializeField] private float waterForce;
    [FormerlySerializedAs("PelicanMovement")] [SerializeField] private Galla_PelicanPlayer pelicanMovement;
    [FormerlySerializedAs("BirdDirectionForce")] [SerializeField] private float birdDirectionForce;
    [FormerlySerializedAs("_animator")] [SerializeField] private Animator animator;
    [SerializeField] private ParticleSystem waterImpactSplash;
    [SerializeField] private float initialTurnRate = 1;
    [SerializeField] private float turnRateIncrement = 1;
    private float _projectileCountDown;
    private float _turnDirection = 0f;
    private CustomInputSystem _inputSystem;
    private bool _buttonDownA = false;
    private bool _buttonDownD = false;
    private float _currentTurnRate;
    private bool canShoot = true;

    [FormerlySerializedAs("Projectile")] public H_WaterBlob projectile;
    private Quaternion _squirrelWorldRotation;

    private PlayerInput _playerInput;
    private InputAction _acButtonAEnter;
    private InputAction _acButtonAExit;
    private InputAction _acButtonBEnter;
    private InputAction _acButtonBExit;

    private void Awake()
    {
        _currentTurnRate = initialTurnRate;
        _squirrelWorldRotation = transform.rotation;
        _playerInput = GetComponent<PlayerInput>();
        _acButtonAEnter = _playerInput.actions["SquirrelButtonAPressed"];
        _acButtonAExit = _playerInput.actions["SquirrelButtonAReleased"];
        _acButtonBEnter = _playerInput.actions["SquirrelButtonBPressed"];
        _acButtonBExit = _playerInput.actions["SquirrelRotateBReleased"];
        animator = GetComponent<Animator>();
    }

    private void Start()
    {
        _inputSystem = new CustomInputSystem();
        _inputSystem.Enable();
        waterForce = waterForce * 100;
    }

    private void Update()
    {
        if (_buttonDownA && _buttonDownD)
        {
            if (canShoot)
            {
                _currentTurnRate = initialTurnRate;
                if (_projectileCountDown <= 0)
                {
                    FireWaterGun();
                    _projectileCountDown = projectileInterval;
                }
                animator.SetBool("IsTurning", false);
                animator.SetBool("IsIdle", false);
                canShoot = false;
            }
        }
        else
        {
            RotateSquirrel();
            canShoot = true;
        }
        
        if (!_buttonDownA && !_buttonDownD && _projectileCountDown > 0)
        {
            animator.SetBool("IsIdle", true);
        }
        
        transform.rotation = _squirrelWorldRotation;
        _projectileCountDown = _projectileCountDown - Time.deltaTime;
    }

    private void RotateSquirrel()
    {
        if (_turnDirection != 0f)
        {
            animator.SetBool("IsTurning", true);
            animator.SetBool("IsIdle", false);
            if (_currentTurnRate < turnRate)
            {
                _currentTurnRate += turnRateIncrement;
            }
        }
        else
        {
            animator.SetBool("IsTurning", false);
            _currentTurnRate = initialTurnRate;
        }
        
        _squirrelWorldRotation *= Quaternion.Euler(Vector3.up * (_turnDirection * _currentTurnRate * Time.deltaTime));
    }

    private void FireWaterGun()
    {
        CinemachineImpulseSource cinemachineImpulseSource = GetComponent<CinemachineImpulseSource>();
        FMODUnity.RuntimeManager.PlayOneShot("event:/BalloonShoot", gameObject.transform.position);

        // Ensure the impulse is generated with the rotation aligned to the GameObject's forward direction
        cinemachineImpulseSource.GenerateImpulseWithVelocity(transform.forward * 0.2f);
        
        animator.SetTrigger("Shoot");
        animator.SetBool("IsIdle", false); // Ensure IsIdle is false when shooting
        
        Vector3 projectileSpawn = pSpawnpoint.position;
        Vector3 pelicanDirection = pelicanMovement.transform.forward;
        Vector3 pelicanSpeedVector = pelicanDirection * birdDirectionForce;

        H_WaterBlob projectile = Instantiate(this.projectile, projectileSpawn, pSpawnpoint.transform.rotation);

        projectile.waterForce = waterForce;
        projectile.spawnPointTransform = transform;
        projectile.pelicanSpeedVector = pelicanSpeedVector;
        projectile.waterImpactParticles = waterImpactSplash;
    }

    //-------------------------------------\/ Input Controls \/-----------------------------------------

    public void ButtonAEnter()
    {
        _buttonDownA = true;
        _turnDirection = -1f;
    }

    public void ButtonAExit()
    {
        if (_buttonDownA && _buttonDownD)
        {
            _buttonDownA = false;
            _turnDirection = 1f;
        }

        else
        {
            _buttonDownA = false;
            _turnDirection = 0f;
        }
    }

    public void ButtonBEnter()
    {
        _buttonDownD = true;
        _turnDirection = 1f;
    }

    public void ButtonBExit()
    {
        if (_buttonDownA && _buttonDownD)
        {
            _buttonDownD = false;
            _turnDirection = -1f;
        }

        else
        {
            _buttonDownD = false;
            _turnDirection = 0f;
        }
    }

    private void OnEnable()
    {
        _acButtonAEnter.performed += _ => ButtonAEnter();
        _acButtonAEnter.canceled += _ => ButtonAExit();
        _acButtonBEnter.performed += _ => ButtonBEnter();
        _acButtonBEnter.canceled += _ => ButtonBExit();
    }

    private void OnDisable()
    {
        _acButtonAEnter.performed -= _ => ButtonAEnter();
        _acButtonAEnter.canceled -= _ => ButtonAExit();
        _acButtonBEnter.performed -= _ => ButtonBEnter();
        _acButtonBEnter.canceled -= _ => ButtonBExit

Show Related Code

using UnityEngine;
using UnityEngine.UIElements;
using UnityEngine.InputSystem;
using FIMSpace.Basics;
using UnityEngine.Android;
using FIMSpace.Generating.Rules;
using UnityEngine.Serialization;
using Unity.Cinemachine;


public class H_SquirrelMovement : MonoBehaviour
{
    [SerializeField] private float turnRate;
    [SerializeField] private Transform pSpawnpoint;
    [SerializeField] private float projectileInterval;
    [SerializeField] private float waterForce;
    [SerializeField] private Galla_PelicanPlayer pelicanMovement;
    [SerializeField] private float birdDirectionForce;
    [SerializeField] private Animator animator;
    [SerializeField] private ParticleSystem waterImpactSplash;
    [SerializeField] private float initialTurnRate = 1;
    [SerializeField] private float turnRateIncrement = 1;
    private float _projectileCountDown;
    private float _turnDirection = 0f;
    private CustomInputSystem _inputSystem;
    private bool _buttonDownA = false;
    private bool _buttonDownD = false;
    private float _currentTurnRate;
    private bool canShoot = true;

    public H_WaterBlob projectile;
    private Quaternion _squirrelWorldRotation;

    private PlayerInput _playerInput;
    private InputAction _acButtonAEnter;
    private InputAction _acButtonAExit;
    private InputAction _acButtonBEnter;
    private InputAction _acButtonBExit;

    private void Awake()
    {
        _currentTurnRate = initialTurnRate;
        _squirrelWorldRotation = transform.rotation;
        _playerInput = GetComponent<PlayerInput>();
        _acButtonAEnter = _playerInput.actions["SquirrelButtonAPressed"];
        _acButtonAExit = _playerInput.actions["SquirrelButtonAReleased"];
        _acButtonBEnter = _playerInput.actions["SquirrelButtonBPressed"];
        _acButtonBExit = _playerInput.actions["SquirrelRotateBReleased"];
        animator = GetComponent<Animator>();
    }

    private void Start()
    {
        _inputSystem = new CustomInputSystem();
        _inputSystem.Enable();
        waterForce = waterForce * 100;
    }

    private void Update()
    {
        if (_buttonDownA && _buttonDownD)
        {
            if (canShoot)
            {
                _currentTurnRate = initialTurnRate;
                if (_projectileCountDown <= 0)
                {
                    FireWaterGun();
                    _projectileCountDown = projectileInterval;
                }
                animator.SetBool("IsTurning", false);
                animator.SetBool("IsIdle", false);
                canShoot = false;
            }
        }
        else
        {
            RotateSquirrel();
            canShoot = true;
        }
        
        if (!_buttonDownA && !_buttonDownD && _projectileCountDown > 0)
        {
            animator.SetBool("IsIdle", true);
        }
        
        transform.rotation = _squirrelWorldRotation;
        _projectileCountDown = _projectileCountDown - Time.deltaTime;
    }

    private void RotateSquirrel()
    {
        if (_turnDirection != 0f)
        {
            animator.SetBool("IsTurning", true);
            animator.SetBool("IsIdle", false);
            if (_currentTurnRate < turnRate)
            {
                _currentTurnRate += turnRateIncrement;
            }
        }
        else
        {
            animator.SetBool("IsTurning", false);
            _currentTurnRate = initialTurnRate;
        }
        
        _squirrelWorldRotation *= Quaternion.Euler(Vector3.up * (_turnDirection * _currentTurnRate * Time.deltaTime));
    }

    private void FireWaterGun()
    {
        CinemachineImpulseSource cinemachineImpulseSource = GetComponent<CinemachineImpulseSource>();
        FMODUnity.RuntimeManager.PlayOneShot("event:/BalloonShoot", gameObject.transform.position);

        // Ensure the impulse is generated with the rotation aligned to the GameObject's forward direction
        cinemachineImpulseSource.GenerateImpulseWithVelocity(transform.forward * 0.2f);
        
        animator.SetTrigger("Shoot");
        animator.SetBool("IsIdle", false); // Ensure IsIdle is false when shooting
        
        Vector3 projectileSpawn = pSpawnpoint.position;
        Vector3 pelicanDirection = pelicanMovement.transform.forward;
        Vector3 pelicanSpeedVector = pelicanDirection * birdDirectionForce;

        H_WaterBlob projectile = Instantiate(this.projectile, projectileSpawn, pSpawnpoint.transform.rotation);

        projectile.waterForce = waterForce;
        projectile.spawnPointTransform = transform;
        projectile.pelicanSpeedVector = pelicanSpeedVector;
        projectile.waterImpactParticles = waterImpactSplash;
    }

    //-------------------------------------\/ Input Controls \/-----------------------------------------

    public void ButtonAEnter()
    {
        _buttonDownA = true;
        _turnDirection = -1f;
    }

    public void ButtonAExit()
    {
        if (_buttonDownA && _buttonDownD)
        {
            _buttonDownA = false;
            _turnDirection = 1f;
        }

        else
        {
            _buttonDownA = false;
            _turnDirection = 0f;
        }
    }

    public void ButtonBEnter()
    {
        _buttonDownD = true;
        _turnDirection = 1f;
    }

    public void ButtonBExit()
    {
        if (_buttonDownA && _buttonDownD)
        {
            _buttonDownD = false;
            _turnDirection = -1f;
        }

        else
        {
            _buttonDownD = false;
            _turnDirection = 0f;
        }
    }

    private void OnEnable()
    {
        _acButtonAEnter.performed += _ => ButtonAEnter();
        _acButtonAEnter.canceled += _ => ButtonAExit();
        _acButtonBEnter.performed += _ => ButtonBEnter();
        _acButtonBEnter.canceled += _ => ButtonBExit();
    }

    private void OnDisable()
    {
        _acButtonAEnter.performed -= _ => ButtonAEnter();
        _acButtonAEnter.canceled -= _ => ButtonAExit();
        _acButtonBEnter.performed -= _ => ButtonBEnter();
        _acButtonBEnter.canceled -= _ => ButtonBExit

Water Bullets

In our game the squirrel player had the objective of shooting water on to burning trees so I had to program the logic for the bullets so that they would interact with the fire system.

At first the bullets only extinguished the trees they collided with, but this caused the game difficulty to become too high so I adjusted it to perform a sphere cast on impact to extinguish all nearby trees as well.

Show Related Code

using FIMSpace.Generating.Rules;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Serialization;

public class H_WaterBlob : MonoBehaviour
{
    Rigidbody _body;
    [FormerlySerializedAs("WaterForce")] public float waterForce;
    [FormerlySerializedAs("PelicanSpeedVector")] public Vector3 pelicanSpeedVector;
    [FormerlySerializedAs("SpawnPointTransform")] public Transform spawnPointTransform;
    public float aoeRadius = 5f;
    public ParticleSystem waterImpactParticles;
    

    private void Start()
    {
        _body = GetComponent<Rigidbody>();
        Vector3 finalBulletVector = (transform.forward * waterForce) + (pelicanSpeedVector);

        _body.AddForce(finalBulletVector);
    }

    private void OnCollisionEnter(Collision collision)
    {
        AoeCheck();
        Instantiate(waterImpactParticles, transform.position, quaternion.identity);
        FMODUnity.RuntimeManager.PlayOneShotAttached("event:/WaterSplash", gameObject);
        Destroy(this.gameObject);
    }

    private void AoeCheck()
    {
        Collider[] hitColliders = Physics.OverlapSphere(this.transform.position, aoeRadius);

        foreach (var hitCollider in hitColliders)
        {
            TreeUnit tree = hitCollider.gameObject.GetComponent<TreeUnit>();
            if (tree != null)
            {
                MeshRenderer treeRenderer = tree.GetComponentInChildren<MeshRenderer>();
                
                ForestManager.Instance.ExtinguishTree(tree

Show Related Code

using FIMSpace.Generating.Rules;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Serialization;

public class H_WaterBlob : MonoBehaviour
{
    Rigidbody _body;
    [FormerlySerializedAs("WaterForce")] public float waterForce;
    [FormerlySerializedAs("PelicanSpeedVector")] public Vector3 pelicanSpeedVector;
    [FormerlySerializedAs("SpawnPointTransform")] public Transform spawnPointTransform;
    public float aoeRadius = 5f;
    public ParticleSystem waterImpactParticles;
    

    private void Start()
    {
        _body = GetComponent<Rigidbody>();
        Vector3 finalBulletVector = (transform.forward * waterForce) + (pelicanSpeedVector);

        _body.AddForce(finalBulletVector);
    }

    private void OnCollisionEnter(Collision collision)
    {
        AoeCheck();
        Instantiate(waterImpactParticles, transform.position, quaternion.identity);
        FMODUnity.RuntimeManager.PlayOneShotAttached("event:/WaterSplash", gameObject);
        Destroy(this.gameObject);
    }

    private void AoeCheck()
    {
        Collider[] hitColliders = Physics.OverlapSphere(this.transform.position, aoeRadius);

        foreach (var hitCollider in hitColliders)
        {
            TreeUnit tree = hitCollider.gameObject.GetComponent<TreeUnit>();
            if (tree != null)
            {
                MeshRenderer treeRenderer = tree.GetComponentInChildren<MeshRenderer>();
                
                ForestManager.Instance.ExtinguishTree(tree

Show Related Code

using FIMSpace.Generating.Rules;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Serialization;

public class H_WaterBlob : MonoBehaviour
{
    Rigidbody _body;
    [FormerlySerializedAs("WaterForce")] public float waterForce;
    [FormerlySerializedAs("PelicanSpeedVector")] public Vector3 pelicanSpeedVector;
    [FormerlySerializedAs("SpawnPointTransform")] public Transform spawnPointTransform;
    public float aoeRadius = 5f;
    public ParticleSystem waterImpactParticles;
    

    private void Start()
    {
        _body = GetComponent<Rigidbody>();
        Vector3 finalBulletVector = (transform.forward * waterForce) + (pelicanSpeedVector);

        _body.AddForce(finalBulletVector);
    }

    private void OnCollisionEnter(Collision collision)
    {
        AoeCheck();
        Instantiate(waterImpactParticles, transform.position, quaternion.identity);
        FMODUnity.RuntimeManager.PlayOneShotAttached("event:/WaterSplash", gameObject);
        Destroy(this.gameObject);
    }

    private void AoeCheck()
    {
        Collider[] hitColliders = Physics.OverlapSphere(this.transform.position, aoeRadius);

        foreach (var hitCollider in hitColliders)
        {
            TreeUnit tree = hitCollider.gameObject.GetComponent<TreeUnit>();
            if (tree != null)
            {
                MeshRenderer treeRenderer = tree.GetComponentInChildren<MeshRenderer>();
                
                ForestManager.Instance.ExtinguishTree(tree

Reflections

This was my first project in my journey to become a game programmer and I feel that it served as a very good starting point to working as a programmer in a team, I learned about Unity's input system and was able to hook up my controller with other programmers systems.

The project it self was quite successful and became quite polished in the end, since we had limitations such as the theme being "Forest", being required to use the Xbox adaptive controller and our target audience being of ages 10-13 the creation process took quite some time but I think it helped us come up with creative solutions to the problems that popped up.

Game Trailer
Smooth Scroll
This will hide itself!

Halldorkari13@gmail.com

0733920759

Contact:

Halldorkari13@gmail.com

0733920759

Contact:

Halldorkari13@gmail.com

0733920759

Contact: