Ludum Dare 55 April 13–16, 2024

If you like tower defense games, try Demon's Tower!

Demon's Tower is a game where you have to defend your tower against enemies! Use your cards to summon special abilities to survive longer. Reaching wave 50 allows you to go to a higher tier.

*Link: https://ldjam.com/events/ludum-dare/55/demons-tower

Unfortunately, I haven’t collected enough ratings for the game. A rating and a feedback from you would be greatly appreciated!

2024-04-22 (1).png


2024-04-22 (3).png

Into the Oven !!!

You are a small demon chef! Your job is to make pizza with your choice of toppings, each with their own special effect, and summon these pizzas in combat against hoards of Kobolds to unlock more toppings.

Have fun :D :pizza:

*Link: https://ldjam.com/events/ludum-dare/55/into-the-oven

sc2.pngsc4.png

Woooooooooooooooooo~! Streaming your LD games!

Come toss the games into twitch chat, it'll probably be a quiet stream one otherwise! All are welcome to add their games, just hang around the stream til I'm ready.

Woooooooo! https://www.twitch.tv/justcamh

Guess who is back!!

I couldn't believe it when I saw this...

Brackeys.png

I don't use Godot, but, if I was going to use a flexible, easy to use, FOSS engine that is on the rise and has the support of many great folks, Godot would be it!!

Brackeys is for many of us our introduction into Game Development and he has been, and continues to be the Gold Standard for Game Dev Tutorials. I look forward to his always insightful and instructive videos.

https://youtu.be/EYt6uDr-PHQ?si=6U0GyknTm91c78p4

A Card Crafting Experience!

Check out our game Kalomancy! An auto-battler card game where you can craft your own cards, see what synergies you can make, spam small tokens, wipe boards or buff other cards to the high heavens.

Link: https://ldjam.com/events/ludum-dare/55/kalomancer

CardCreator.png BoardStateUpdatedMana.png

The Making of Bergs

making of logo.png

This is a behind the scenes for the making of our Ludum Dare entry - 'bergs'.

You can checkout the LD page here
https://ldjam.com/events/ludum-dare/55/bergs

Ideas

The first couple of hours were spent brainstorming ideas. We came up with quite a few but eventually landed on the idea of making a 2D puzzle platformer where the player could summon a new character and use the previous character to help them complete the levels in some way. We expanded on this idea a little bit and decided that the characters should spawn with shape and size variations which would also effect how fast they could move and how high they could jump.

Implementation

As the person with the most GDScript (Godot's programming language) experience, I did the majority of the implementation and programming. I wanted to get all the main features added to the game in the first day so that my teammate could start creating levels as soon as possible. On the first day I spent around ~10 hours working on the project. Most of that time was spent creating the core features however some of it was spent on art and a bit polish. Over the next 2 days I spent around another ~6 hours fixing bugs, tweaking a couple of things, and adding polish and game juice (to distract from the lack of any type of graphics lol). There's probably more to say here but I'm writing this a week later so I've forgotten. (I also have no clue how to properly write these things lol).

Level Design

The level design was done by my teammate, CaineTinyArms. I think he did a great job in designing the levels in a way that teach the player the core mechanics of our game without directly telling them.

Here's what Caine had to say about it: I spent a couple hours brainstorming level ideas, many of the early ideas had to be scrapped because I didn't account for berg falling from the sky when they're summoned. The main issue encountered when developing levels was the player could cheese pretty much all of them by just berg-stacking, which is where the no-berg-zone came in. Overall, I think the levels turned out well, considering it's my first forte into level design. (also shout out toast for carrying the team <3)

Sound

The awesome music track was create by my friend, Iiro. I think he did a great job with it and props to him for always being up for creating tracks for my projects. He also did most of the sound effects for the game - including the "BERG" summon sound.

Art

I'm not an artist so I kept things super simple. The bergs are basically just squares with arms, the levels are made from a square only tileset, and the background is made up from spinning squares. This isn't relevant to the art but the game's resolution is also square (it's 160x160 if you're interested). If you couldn't already tell, I quite like squares. All things considered, I think the game turned out looking ok.

Other

The bergs were original called 'guys' (in the project file they still are) but we changed it to 'berg' once we released they kinda looked berg-y.

End

Thanks to everyone who has played the game and left feedback. We haven't replied to many comments as there's quite a few but we have read every single one and taken notes on the feedback everyone has given :).

If you haven't played bergs yet you can check it out here.
https://ldjam.com/events/ludum-dare/55/bergs

We composed the music during the LDJAM

We composed using the precious Roland JDXI synth 5 songs in our game. I let you enjoy the game over screen music.

https://youtu.be/RxkJUpo_-vM

ps : game link is https://ldjam.com/events/ludum-dare/55/demon-lord-revenge

Share your games!

Hiya! I'll be playing some more games this evening and I thought it might be fun seeing if people will respond on here. Feel free to share your game in the comments and I'll try to play them this evening :)

If you also need some more games to play, maybe check this post in a while and join me on my journey of playing some games :)

In the meantime I'll start with our game https://ldjam.com/events/ludum-dare/55/burdemon. If you have time I would love some feedback but don't feel pressured to rate it.

Have a nice day y'all!

Screenshot 2024-04-22 152426.png

Looking for a 2-player game to play with your buddy ?

We got you covered ! :twomenholding_hands:

maintitle.png

Our game TechnoMonk RITUAL has a local 2 player versus mode !

Rocking alone is fine, but rocking together is much better !!

combat-ezgif.com-loop-count.gif

It also has a single player campaign if nobody wants to be beaten by your mad skills... :boom:

wolodance.gif

We're a few ratings shy of the 20 required, so have a go at TechnoMonk RITUAL !

Have you got the time to pay back the fine?

bailout_cover.png

Play a skateboarder who has been summoned to make an appearance at court before noon and pay a fine for the crime of skateboarding. Except you don’t have any money and noon is only 2 minutes away! Skateboard around the city gathering as much loose change as you can find and make it to the courthouse in time. Just don’t get caught skating by the cops!

ldjam55_2.gif

Probably the longest Brainstorming we've done

Sometimes you got not enough ideas, and sometimes you got way too many of them, but none of them since to convince the rest of the team.

After picking our game idea, we realized that we all had different takes on what it was, and started propotyping, deliberating and playtesting with paper cards and drawings for almost 12h straight.

After 12h, we had even more ideas.

In the end we just picked randomly between all our projects and we're actually pretty happy with the outcome ! makingof.png

cards.gif

Have you found our secret room?

For those of you who played our game Sir Lancelittle: who has found the secret room in the game? It contains our lovely NPC Frogkeeper, and he has a special present for you (actually two, if you also count the card reward).

frogkeeper.png

If you haven't found him yet, and had difficulty getting to the boss in our game, Frogkeeper will definitely help you with a full health boost. He's off the beaten path, so keep track of your route through the minimap!

Here's a gameplay video of Metal Harvest!

Hi there, since we put so much effort into the sound of the game this time, I figured showing a little video would make more sense than posting pictures!

https://youtu.be/l6F-VZmsgi8

Try Metal Harvest here!

cover.png

Legend says we are still playing LD games

Road to 100 games continues. Submissions are still open.

We are playing submissions, our favorite games, and games of people who played our game.

Come join us and chill with us :popcorn:

:arrow_right: https://www.twitch.tv/tobugis

3Z3UieUP_400x400.jpg

VCDG dev-log

Virtual Church Of The Digital Goddess is my entry for this 55th LudumDare session. When I discovered the chosen theme (Summoning) I was in an uncomfortable situation. By religious conviction I cannot play with black magical art, evil spirits and all things more or less similar. I have immediately understood that a big amount of entries could play with sorcery - and LD members did. I respect this choice, but I tried to create something different without evil invocation, black sabbath, devil, etc. This is the first time in my indie dev life that I encountered this constraint. So I struggled with a new challenge. Let's go! I decided to create (another) puzzle game - my favorite games' genre, but adding a new way. I asked myself - is there a way to create a game only with a mathematical core, no rigidbody, no collider, etc? So VCDG is an experimentation into solid math processes. Maybe for this reason, the cubes and their movements seem so smooth, perfectly aligned on edges. To do that I use this code :

``` // smooth rotation IEnumerator Tumble(GameObject thisOne, Vector3 direction, Vector3 endPosition, Quaternion endRotation, Vector3 pivot, Vector3 rotAxis, float rotSpeed, bool ret) { float t = 0.0f;

if (loader.GetComponent<Loader>()._move != null && loader != null)
{
    if (Time.timeScale > 1.5f)
        _loader.playSound(_loader._move, this.transform, true, 0.21f, 0.41f, _loader._move.length, false);
    else
        _loader.playSound(_loader._move, this.transform, true, 0.31f, UnityEngine.Random.Range(0.71f, 0.92f), _loader._move.length, false);
}
// rotate player cube
while (t < tumblingDuration)
{
    isTumbling = true; // unreachable
    t += Time.deltaTime;
    // tip to avoid tiny glitch
    if (Mathf.Abs(t - tumblingDuration) < tumblingDuration / 30)
        t += 1.0f; // out of the loop right now

    thisOne.transform.RotateAround(pivot, rotAxis, rotSpeed * Time.deltaTime);
    yield return Timing.WaitForOneFrame;
}
// clean position and rotation
thisOne.transform.position = endPosition;
thisOne.transform.rotation = endRotation;
// store new position so as to check forbidden face
storedPos = endPosition - shift;
// don't store the return movement in back in time mode!!!
if (!ret)
    addNewMov(direction, thisOne);
// check if the last movement is available
checkState(thisOne, direction);
// done
isTumbling = false;

} ```

Also there are a lot of constraints in the game, especially about colors and position/rotation. This part was really complicated - and I struggled hard against some non-understandable bugs. Finally I have this code which seems to me relevant and clever :

``` // check new position and rotation private void checkState(GameObject thisOne, Vector3 direction) { // 1° check if a new step is available if (!loader.GetComponent().giveMeNumber(loader.GetComponent().pattern, listMov.Count)) { computeMove(-direction, thisOne, true, true); // play a sound if (loader.noMoreStep != null && loader != null) loader.playSound(loader.noMoreStep, this.transform, true, 0.4f, 0.95f, _loader.noMoreStep.length, false); // get out of there return; } // 2° check cube face if (listPos.Contains(thisOne.transform.position + new Vector3(1, 0, 0)) || listPos.Contains(thisOne.transform.position - new Vector3(1, 0, 0)) || listPos.Contains(thisOne.transform.position + new Vector3(0, 0, 1)) || listPos.Contains(thisOne.transform.position - new Vector3(0, 0, 1))) { foreach (GameObject g in cc) { // excludes cube player which are not in our radius if (g != thisOne && Vector3.Distance(g.transform.position, thisOne.transform.position) < 1.1f) { var d = (thisOne.transform.position - g.transform.position).normalized; // check if cube touching have the same color on their face var isXA = Mathf.Abs(Vector3.Dot(d, thisOne.transform.right)) > 0.999f; var isYA = Mathf.Abs(Vector3.Dot(d, thisOne.transform.up)) > 0.999f; var isZ_A = Mathf.Abs(Vector3.Dot(d, thisOne.transform.forward)) > 0.999f;

            var isX_B = Mathf.Abs(Vector3.Dot(d, g.transform.right)) > 0.999f;
            var isY_B = Mathf.Abs(Vector3.Dot(d, g.transform.up)) > 0.999f;
            var isZ_B = Mathf.Abs(Vector3.Dot(d, g.transform.forward)) > 0.999f;

            bool sameColor = isX_A == isX_B && isY_A == isY_B && isZ_A == isZ_B;
            // this movement is finally forbidden
            if (!sameColor)
            {
                computeMove(-direction, thisOne, true, true); // back step
                // get out of there
                return;
            }
        }
    }
}
// 3° check colored tiles
if ((Mathf.RoundToInt(thisOne.transform.eulerAngles.x) == 0 && Mathf.RoundToInt(thisOne.transform.eulerAngles.z) == 180) ||
         (Mathf.RoundToInt(thisOne.transform.eulerAngles.x) == 0 && Mathf.RoundToInt(thisOne.transform.eulerAngles.z) == 0))
{   // red tile on ground
    if (greenTilesPos.Contains(storedPos) || blueTilesPos.Contains(storedPos) || greenGoal.Contains(storedPos) || blueGoal.Contains(storedPos))
        computeMove(-direction, thisOne, true, true);
    else if (listBlank.Contains(storedPos))
        blankTileProcess(1, storedPos);
    else if (redGoal.Contains(storedPos))
        levelSolved(thisOne);
    // get out of there
    return;
}
else if ((Mathf.RoundToInt(thisOne.transform.eulerAngles.x) == 0 && Mathf.RoundToInt(thisOne.transform.eulerAngles.z) == 270) ||
         (Mathf.RoundToInt(thisOne.transform.eulerAngles.x) == 0 && Mathf.RoundToInt(thisOne.transform.eulerAngles.z) == 90))
{   // green tile on ground
    if (redTilesPos.Contains(storedPos) || blueTilesPos.Contains(storedPos) || redGoal.Contains(storedPos) || blueGoal.Contains(storedPos))
        computeMove(-direction, thisOne, true, true);
    else if (listBlank.Contains(storedPos))         
        blankTileProcess(2, storedPos);
    else if (greenGoal.Contains(storedPos))
        levelSolved(thisOne);
    // get out of there
    return;
}
else if ((Mathf.RoundToInt(thisOne.transform.eulerAngles.x) == 270 && Mathf.RoundToInt(thisOne.transform.eulerAngles.z) == 0) ||
         (Mathf.RoundToInt(thisOne.transform.eulerAngles.x) == 90 && Mathf.RoundToInt(thisOne.transform.eulerAngles.z) == 0))
{   // blue tile on ground
    if (redTilesPos.Contains(storedPos) || greenTilesPos.Contains(storedPos) || redGoal.Contains(storedPos) || greenGoal.Contains(storedPos))
        computeMove(-direction, thisOne, true, true);
    else if (listBlank.Contains(storedPos))
        blankTileProcess(3, storedPos);
    else if (blueGoal.Contains(storedPos))
        levelSolved(thisOne);
    // get out of there
    return;
}

} // transform blank tile void blankTileProcess(int color, Vector3 vPos) { int i = listBlank.IndexOf(vPos); // UnityEngine.Debug.Log(listBlank.IndexOf(vPos) + " -> " + vPos); // colored blank tile with a new color if (Time.timeScale < 1.5f) { if (stampBlank[i] == 0) { // is this tile blank? stampBlank[i] = listMov.Count; obj.GetComponent().blankTiles.transform.GetChild(i).GetComponent().sharedMaterial = obj.GetComponent().materials[color]; // play a sound if (loader.GetComponent().paint != null && loader != null) loader.playSound(loader.paint, this.transform, true, 0.5f, 0.9f, _loader.paint.length, false); // ... or you can use item selection instead of an integer if (color == 1) redTilesPos.Add(vPos); else if (color == 2) greenTilesPos.Add(vPos); else if (color == 3) blueTilesPos.Add(vPos); else return; } } } ```

To get an inverted clockwise system, allowing the player to come back in time, I used a movement list according to the object and its direction. So the number of steps which are available is computed according to the List.Count integer. We got something like that :

``` // all movement have been saved so as to allow back in time void backInTime() { while (listMov.Last().artefact != cc[index]) splitCube();

if (listBlank.Contains(cc[index].transform.position - shift))
{
    int i = listBlank.IndexOf(cc[index].transform.position - shift);
    // disable a blank tile which has been colored before
    if (stampBlank[i] == listMov.Count)
    {
        obj.GetComponent<LevelConstructor>().blankTiles.transform.GetChild(i).GetComponent<Renderer>().sharedMaterial = obj.GetComponent<LevelConstructor>()._materials[7];
        stampBlank[i] = 0;
        // new blank status
        redTilesPos.Remove(cc[index].transform.position - shift);
        greenTilesPos.Remove(cc[index].transform.position - shift);
        blueTilesPos.Remove(cc[index].transform.position - shift);
    }
}
// invert movement
computeMove(-listMov.Last().movement, listMov.Last().artefact, false, true);
deleteLast();

} ```

My favorite feature is the rounded blank tile which the player paints when a cube walks on it. This is not an easy feature because of one point - you can back in time. So its status must change too. So I implemented a tag on them in order to "clean up" tiles when retrograded cube passes again on a previous tile which has been colored. This tag is just an integer - the step when the tile has been colored. Take a look at the end of the first script - the blankTileProcess() function. In the previous script, you got the code which compute the state of the tile during the right moment.

Some parts of these codes could be improved. As an a single example, I use Time.timeScale like a tag - and I don't like it. There are too many GetComponent occurences in these scripts - and it's not the best way to get a hand on an object. So I have many to do :wink:
For the FX I used some shaders and this project is my first one using the Unity URP system. I tested this option, but I guess that a legacy system could be "enough". I am developing more levels in order to release a full game with 50 levels. I have only one scene for them, and when you see a black screen, it's just a short time to erase the previous level, creating the next... Also I am proud of my level selection system. before I created a button for each level. Now I have only one script to generate how many buttons are required. This script is really useful. Then I share it with you.

``` using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI;

public class DisplayButtons : MonoBehaviour { public Transform button; public int buttonOnX = 10; public int buttonOnY = 5;

Vector3 nextPos = Vector3.zero;
public int spacingX = 80;
public int spacingY = 80;

Vector3 shift;
int id = 0;

void Start()
{
    displayThem();
}

public void displayThem()
{
    nextPos.y = 0;
    id = 0;
    shift = new Vector3(((buttonOnX * spacingX)/2) - (spacingX/2), (-(spacingY * buttonOnY)/2) - (spacingY/2), 0);

    for (int i = 0; i < buttonOnY; i++)
    {
        nextPos.y -= spacingY;
        nextPos.x = 0;

        for (int j = 0; j < buttonOnX; j++)
        {
            id++;
            RectTransform myButton = Instantiate(button as RectTransform);

            myButton.GetComponentInChildren<Text>().text = (id).ToString();
            myButton.GetComponentInChildren<Text>().fontSize = 40;
            myButton.GetComponentInChildren<Text>().color = new Color(0.2f, 0.22f, 0.5f, 0.9f);
            myButton.GetComponentInChildren<Image>().color = new Color(0.7f, 0.5f, 0.8f, 0.9f);
            myButton.SetParent(transform, false);
            myButton.localPosition = nextPos - shift;

            nextPos.x += spacingX;
            int level = PlayerPrefs.GetInt("Level", 1);

            if (id > level && !Application.isEditor)
            {
                myButton.GetComponentInChildren<Button>().interactable = false; // disables button for scene that isn't available
                myButton.GetComponentInChildren<Text>().color = new Color(0.2f, 0.22f, 0.5f, 0.45f);
            }
        }    
    }
}

} ```

I exposed some parts of my project, just sharing with you some keys. I guess that it could be improved - and with more time, I will do it. If you want to test the result, the game is available on Itch.io for free. Play, leave a comment - and this way, I can find your own project which I wanna play. Thank you for your support everyone. I wish you the best ++

https://ldjam.com/events/ludum-dare/55/virtual-church-of-the-digital-goddess

VCDG.jpeg

Thank you so much to everyone who played my entry so far!

Just wanted to say thank you for everyone who played my game. Worked out being a miracle it ended up being submitted at all considering the timing compared to my father's fall an hour later, if I had taken longer I wouldn't have had a chance to submit at all, so that is the entire reason it ended up being way smaller than I initially envisioned with no later updates.

My father has been back from hospital for a week now and he has a head injury that will likely take him 1 month to completely recover from plus other damage.

This was also the first gamejam using the Godot game engine I completed so it was a huge learning experience for me.

Comments like this make me truly appreciate making games: Screenshot 2024-04-22 at 14-43-32 Bone Train - For Ludum Dare 55 ldjam.com Ludum Dare game jam.png

Thank you for all the support and I'm gonna try and play some more of your games now that things are a bit more stable at home.

Just gonna share the entry link to make it easier to find: https://ldjam.com/events/ludum-dare/55/bone-train-for-ludum-dare-55

Mobile games

Hey, friends. If anyone made a mobile game, drop me a link! Have some time to kill...

Thanks for the great jam, everyone!

Had so much fun, first LD with Godot. We spent roughly half our time making secret interactions/secret good ending which no one has been crafty enough to discover yet. :smiley:

If you're a fellow Godot dev, let me know, I love checking out other entries, especially Godot games!

Here's ours, if you have time to check it out, thank you!

No tea time for Slime:

https://ldjam.com/events/ludum-dare/55/no-tea-time-for-slimes

Screenshot 2024-04-22 at 12.21.04 PM.png

63032 (1).png

I fixed the web version of my game

I just fixed the web build, so I made an itch.io page. I only updated code related to the web version to make it work properly (I fixed the graphical bug and added sound, it was only available to the native version up to now, I’m not sure if it’s ok, but say it if it’s not and I’ll remove it), so the native version stays the same, so it should be fair because:

Certain Bug Fixes are allowed. You can’t add new features, but if something broke or didn’t work correctly as you were finishing up, you can fix this after the deadline. You are asked to highlight the changes you make in your submission (a short change log). You probably wont get a 2nd chance with some players, but at least it wont be a problem for future players.

The download stays the same.

I'm planning to upload a time-lapse soon!

Enjoy playing it at https://mibi88.itch.io/the-seven-crystals!

You can see the changes on the GitHub repository!