thevinter

Ludum Dare 46

I want to continue development, what do you think?

I spent the last days thinking about my game, and about the fact that I like the ambient and the mood very much.

We wanted to make a story driven game with similar aesthetics and core mechanics, where you are a flame that has to save a world without a sun and that fell into darkness. What do you think?

ApplicationFrameHostem2020-04-22/em20-48-33.png

How unfortunate events lead to great things:

When we started the development of Solar we wanted to make a game where the player had to keep a fire alive, we weren't sure if we wanted it to be a torch or a bonfire but that was the basic idea (apparently pretty popular)

In the end we settled on doing a roguelike dungeon crawler when the torch dims out over time, the main character was supposed to be a humanoid figure or something similar.

Then, due to unfortunate events, we had to redo all the art 10 hours before the deadline, with an also unfinished game, and I was the one in charge of doing it.

Well, I never did any pixel art and I'm bad at animating stuff so my goal was to find something easy to animate and pretty basic. And then the idea struck me:

Why don't we make the character itself a flame?

I think that made the game a lot better and a lot less generic than a simple "dude in a dungeon", so I'm really glad that happened.

I guess the lesson here is don't let yourself be dragged down by problems in the project, especially in a competition like this when you have a short time to finish your stuff. Try to embrace them and go with the flow, they might lead you to something great ;)

cp5SncvWi2.gif

If you want to play my game you can find it here: https://ldjam.com/events/ludum-dare/46/solar

How To Properly Refactor Your Code (Mostly in Unity)

Hello, I'm currently in the process of reworking my code from the ground up since I want to develop a full version of my game. In this post I'd like to talk about the "proper" ways of mantaining and refactoring your code. (Proper is in quotes since there's actually no proper way of doing it, some ways are just more manageable than others).

First of all you can find the JAM code here: https://bit.ly/3d5z4sP (Carefull, it's a mess!)

What I did wrong

The main problem of that code is the fact that it was really heavily scene dependant. You can see this mostly in the Player script where I have this mess: void Start() { if(!tutorial) StartCoroutine(FadeImage(true)); r = GetComponent<Renderer>(); anim = GetComponent<PlayerAnimator>(); controller = GetComponent<Controller2D>(); shoot = GetComponent<PlayerShoot>(); torch = GetComponent<PlayerTorch>(); if(!tutorial) shake = GameObject.FindGameObjectWithTag("Shake").GetComponent<CameraShake>(); }

I had to add a boolean just for the tutorial level and find all of the special cases where the components were not required. This is clearly an example of bad architecture.

Then I tried but failed to use the Chain Of Command pattern as you can see here:

chromeem2020-04-28/em10-37-02.png

The Player class has some delegations but that code is a mess. It also doesn't follow the Single Responsibility Principle, that class does too many things.

Another mistake is that my code was too sparse

``` public class PlayerAnimator : MonoBehaviour { private Animator anim; private Player p; // Start is called before the first frame update void Start() { p = GameObject.FindGameObjectWithTag("Player").GetComponent(); anim = GetComponent(); }

private void Update()
{
    anim.SetBool("isResting", p.isResting);
}

} ```

This was my animator but as you can see it does almost nothing, the rest of the animation logic is scattered around various scripts (mostly Animation Behaviours)

And lastly my coupling was terrible.

``` public class MainMenuScript : MonoBehaviour { GameObject p; public AudioClip boop; public AudioClip woosh; public Button startButton; public TextMeshProUGUI tutorial;

public void Sound()
{
    AudioManager.Instance.Play(boop, transform, .1f);
}
public void StartGame()
{
    Camera.main.GetComponent<CameraFollow>().player = p.transform;

    p.GetComponentInChildren<Light>().intensity = 2;
    p.GetComponentInChildren<Light>().range = 20;
    StartCoroutine(fadeButton(startButton, false, .2f));
    AudioManager.Instance.Play(woosh, transform, .1f, 2.5f);
    StartCoroutine(ShowTutorial("Use WASD to move"));
}

} ```

For example my Main Menu had to know about the player, the buttons, the text, the sounds etc. That meant that if only one of those things broke, everything else (probaby) did as well

What I did well

Luckily this not being my first jam I had some experience with this sort of things so I managed to do some good stuff.

First of all everything was (at least in the beginning) neatly organized

org.png Separate folders for Art, Scripts, SFX etc... This might seem a small improvement but it really makes a difference when you have to find stuff

And the second thing that really helped me was the use of interfaces. For example I defined one single IInteractable interface

public interface IInteractable { string Name { get; set; } void Interact(Player p); }

And implemented it to every object the player could've interacted with. For example:

``` using UnityEngine;

public class WeaponPickup : MonoBehaviour, IInteractable { public string Name { get => itemName; set => throw new System.NotImplementedException(); } public GameObject weapon; public string itemName = "Magical Bullet"; public void Interact(Player p) { p.AddWeapon(weapon); Destroy(GetComponent()); Destroy(GetComponent()); Destroy(this.gameObject, 1f); AudioManager.Instance.Play(pickUp, transform, .05f); } } ``` (Ignore the destroy mess! This happens when you don't decouple classes! :P)

And the Player a really simple interact logic

``` void OnTriggerEnter2D(Collider2D collision) { if (collision.gameObject.CompareTag("Usable")) { obj = collision.gameObject.GetComponent(); itemTextBox.GetComponent().text = obj.Name; itemTextBox.SetActive(true); canInteract = true; } }

private void OnTriggerExit2D(Collider2D collision) { if (collision.gameObject.CompareTag("Usable")) { itemTextBox.SetActive(false); obj = null; canInteract = false; } }

void Interact() { if(Input.GetKeyDown(KeyCode.E) && canInteract){ obj.Interact(this); } } ``` (They can be simplified even further!)

What Am I doing now?

I've spent the last 4 days rewriting my old code with zero progress, this is because I wanted to turn it into an easily expandable code with the same functionalities. What I did (and am still doing) was:

  • Reducing coupling between classes
  • Implementing Events for most of the functionalities: This correlates with the first point, if I have a class that sends an event and another one that listens to it the two classes are essentialy independant!
  • Separating the Audio and Animation logic from the base classes: I'm doing this using events as well
  • Splitting the Player class into smaller Components (this applies to Unity but other programs as well, check the Single Responsibility Principle!)
  • Using Scriptable Objects to add a layer of abstraction between Classes: this also reduces coupling. Let's say my Player class writes to a HealthScriptObj and my HealthUI reads from it. The two classes are now decoupled but the functionality is the same!

If you came this far, thanks for reading, hope you learned something useful! If you want to check my game you can find it here: Solar

We decided to keep developing Solar

This is the first concept art. What do you think?

IMGem20200429/em163924_921.jpg

You can play the jam version here: https://ldjam.com/events/ludum-dare/46/solar

Streaming your games!

I finally repaired my pc so I'm once again playing your games! Come and say hi :)

https://twitch.tv/thevinter

Hosting a Unity Masterclass (Mostly for 2D)

I'll be talking about how to start with Unity3D, what are its strengths and show some basic code. I'll also talk about good design patterns about the SOLID Principles and about how to avoid writing code that looks like a mess after a week.

https://www.twitch.tv/thevinter

Come if you're interested! Questions are welcome :)

Ludum Dare 47

A Small Preview

This time I totally overscoped lmao

xgUSb70.png

Memorial

It might be a bit rough around the edges but I managed to finish this year's entry as well.

In the distant future there’s a machine that allows you to revive your memories. But sometimes people get stuck in them. It’s not easy to get out, and if you aren’t free in 72 hours then your brain dies.

You take the role of T, a Diver specialized in bringing out people from said loops. Will you be able to?

This is my first time trying to work with 2D art and animations that are not pixel art and it shows. Hopefully nothing too gamebreaking!

drawing.png

(This image might not be representative of the final product :stuckouttongue:)

Streaming Your Games

I know it's kinda late but I'm doing one last session of games streaming. Come into the stream, submit your games and let's have some fun :)

https://twitch.tv/thevinter

You can also check out my game (i still need 7 ratings!): https://ldjam.com/events/ludum-dare/47/memorial

Please help us reach 20 ratings!

We need only 3 more! So it would be great if you tried and rated Memorial!

https://ldjam.com/events/ludum-dare/47/memorial

Ludum Dare 48

Working biography generator

I spent the last 2 hours working on the most useless thing I've ever done but it's fun (and easily expandable). This generates a random biography for every crew member on the ship!

OFuqoK4.png

An intro gif

This gif will supposedly play as soon as someone boots up the game. I should probably add some more frames to it but drawing is hard when you're not an artist :P

whale.gif

I implemented a multiplayer radio system (and it doesn't work on WebGL)

In my game you control a submarine and there is a tool that allows players to send messages to random connected users. A python server runs on a Linux machine and sends all of the messages to me using a telegram bot so I can review them.

tkAuMKT (1).png

A useless feature, but I had fun implementing it. Too bad it doesn't work on WebGL (or at least the game doesn't load and I think this is the culprit. Anyone had similar issues before?)

In the meantime, if you have Windows, you can check my game here!

P2XraNR.png

Art Dump

This is some art I made while I was supposed to be working on the game (this stuff was actually put into it so at least it's not wasted time :P)

photoem2021-04-24/em19-02-20.jpg

photoem2021-04-24/em19-06-24.jpg

photoem2021-04-24/em19-08-50.jpg

photoem2021-04-24/em19-51-21.jpg

photoem2021-04-24/em19-43-18.jpg

photoem2021-04-24/em18-48-29.jpg

You can check out the game here (it's nothing like the drawings :eyes:) :https://ldjam.com/events/ludum-dare/48/reship

Come and send messages!

My game has a multiplayer message functionality, you can open it and send something to another random player. Please help me with populating it with messages :)

P2XraNR.png

Link to the game: https://ldjam.com/events/ludum-dare/48/reship

Only One Rating Left for 20!

Sadly I didn´t have much time this Ludum Dare to play other games, but it still would be awesome if I could get 20 ratings to be rated!

Would you be so kind?

3ed69.png