arkinrev

LD 43

First Submission Anxiety

This is my first submission to any game jam, and it took quite a bit of support from my significant other to push me enough to actually submit a game. I have not completed programming a game since probably high school and had it not been for the YouTube algorithm linking one of Brackeys' videos over a year ago, I may not have found this jam. Thanks to many YouTubers' tutorials and all of the inspiring games I've seen submitted to previous LD jams, I have finally finished a game.

Have a look at Eldritchual LD43CoverImage.png

Eldritchual - First LD RecapDevlog (I really need a longer title for reasons...)

Introduction - My Personal Journey

I'm going to write a proper (and shorter) post-mortem to follow. The best way for me to get there is to try to lay out the whole development process that led me to this point. A short personal background might be in order, but if you want to skip to the technical portion, hop over to the next heading. (This is going to be long)

I first heard about Ludum Dare after watching a lot of Brackeys' videos that the YouTube algorithm had selected for me last year. Although I wasn't writing or producing anything, I subscribed to him and several other YouTubers, watched, followed along, and still, didn't write anything. I bounced around to other YouTubers over the next year, and while I binge watched Blackthornprod, I really liked his LD entry Evolution, so I popped over to the site here to find it when I noticed a jam was coming up in a few weeks.

I hadn't written a complete video game for a long time (few decades) and thought: I wonder if I can do this? Had any of those tutorials stuck? I hadn't touched C++ in a very long time, I mainly have written small supplement apps to my boardgames in PHP, some VB and Javascript to keep a few websites running, figuring out C# can't be that rough. I've recorded music in Audacity. I have the equipment to handle audio. I just recently replaced the stylus that I lost for my Wacom tablet. And since I cut cable, my TV time has been heavily spent on my numerous hobby interests, so I'm fairly sure that I can do everything, stay on task, and complete something.

I started talking about it. I mentioned it a few times around the house and playing some online games, psyching myself up to move forward. I've always had a lot of game ideas that I really was quite fond of, and I've been a somewhat silent armchair-gamedev for quite some time. I talk about it when it comes up, but I don't usually give my feedback on game forums or wherever. In one discussion that was getting a little bit heated about a month ago, I wanted to say "If you know how they should have written the game, then why don't you do it?" I kept that to myself, because I didn't really feel that I had a leg to stand on. If I think I've got good ideas, why don't I just write it myself? Now, this isn't to say that people who don't write anything don't have valid feedback, just that there is a difference between saying what you liked or didn't is a little bit different than saying "you should do it like this." There's a line somewhere in there that there's no time to unpack right now.

As the jam approached I told myself and others: If I have something that resembles a complete game, I'll post it. I had found a safety net. I could always just silently follow along from the sidelines. I didn't have to post.

ss1.png

Jam Recap - The Actual Development Recap

Everything that follows is all about the events that took place as I tried to make and submit Eldritchual If I had kept a journal, this is how it would have gone (to the best of my recollection):

The Weeks Prior

The actual jam preparation started a few weeks ago. I binge watched tutorials. 3D, 2D, particles, physics, different game types, terrain types, transitions, bars, counters, timers, shooting, enemy AI, etc. I didn't know what game I was going to make, so I wanted to be ready. I watched numerous post-mortem videos, and a few very helpful and entertaining ones from Pixel Prophecy that really helped give me an idea for what to expect and for what the process looks like. Most importantly were the planning and decision making aspects.

I signed up on ldjam.com just as the theme voting was finishing. I voted. I can't remember what for. With more tutorials ahead of me I think I reached a point that I needed to clear my head. I tried to have a blank slate when it came to the theme. I didn't want to remember the options, and I didn't want to fall in love with a theme that wasn't utlimately selected. I know I'm new to this, but there are a lot of videos and comments that float across the feed here that mention how bad themes are, or how limiting a theme is. All of that was getting to me. There was a negative cloud forming and I knew that it would be raining on me the entire time if I wasn't ready for it. I came here for the challenge. I wanted to participate because I'm proud of my ideas. I don't know how well I'm going to perform, but I know that I needed the confidence to tackle any theme presented and the willpower to take control of the theme. It's my game, and whatever the theme is, the theme works for me. I put a lot of effort in to get the skills that I have and I want to earn my rating among developers. I had to tell myself that I refuse to lose to the theme. I had to give myself that pep talk and then watch some TV, play some games, and take a lot of deep breaths to relax. The anxiety built up so much that I needed a shower to relax. I sat down at my computer 4 minutes after the theme had been announced.

Friday: 9:04pm - 5:30am

I had a small whiteboard sitting next to me. Across the top I had written two things. Simple. Interesting. Under that was the theme. I started brainstorming various interpretations. What does sacrifice mean? Historical human sacrifice? Ritual sacrifice? Something to do with volcano sacrifice, etc. Then I thought: I'll make a list of who is sacrificing something, a list of why things are sacrificed, and a list of what is usually sacrificed. Looking that over, what was interesting? what was simple? Then I just felt like being a cult leader, getting people converted to your cause, probably developing bonds with them, and chucking them into a pit for your own goals or the greater good was the core concept. Now what kind of cult is this? I wasn't making a "kids" game, but at the same time, I wanted to make something accessible. I decided right away that I didn't want anything too real. I wanted to summon some horrible thing, I just didn't want it to be pushing anyone into an uncomfortable space. Well, I don't really like Lovecraft Mythos, but it fits the bill. Maybe playing around with it would blunt the edges of my disdain for the genre. Unreal and hopefully I can make a genre I don't enjoy approachable to me. I made a quick list of what would cultists do? I drew out little squares. Worship, relax, hide from authorities, some ritual bar showing progress. I was moving the parts on the whiteboard as I thought through the challenges of leading a cult. All the while "Simple" written at the top of the board. What is the player doing? They need to care about their cultists, but they also need to kill them. Why does a player care about their pieces? I thought: they should be doing something for the player. They were making something, or producing something. Your cultists that do the most you should care about the most, so they should be worth more than the ones that don't further your other goals. That's when I came up with the happiness idea. If you keep them happy, they work harder. If they are unhappy, they leave. What do they produce? Faith in the thing you worship, but is there another tradeoff other than just happiness? I thought that the other thing a cult needed to summon a horrible creature would be that they can't get caught. I had my unnamed resources that later turned out to be Faith and Obscurity.

I sketched out little smiley faces that might float over the head of your cultist. There might be a little bar to show the happiness level or progress. I pivoted there and thought "I'll just make that their face." Keep it simple. I didn't need to expose every number for every mechanic. The squares turned in to regions that you would move cultists around in. I had my central mechanic, I loosely had some UI ideas, I was ready to go. It's now 10:30pm and I need two things before I go to bed: a prototype for the core systems and most importantly, the art for the cultists, which would be the central point of interaction in the game.

I spent the next few hours drawing the cultists, splitting them into parts that I could animate, and making sure that their appearance was not inferring anything other than somewhat-whimsical cultist. I was ready to bring them into Unity and start skeletal animation, until I chickened out. I wasn't sure if I could swap my parts around and move the pieces. Instead I made a clumsy prefab that contained all of the cultist parts, fumbled with some slight animation to keep the game active but not busy, and used the Animator and animations to turn the other sprite renderers on and off. The cultist was in the game, and I started on his script at about 12:30 am.

I immediately created the enumeration for happiness, but it would be a while before I used them. First, I needed to be able to drag and drop him. It was at that point that I realized, not a single tutorial I had watched dealt with drag and drop. I had prepared for a lot, and my core mechanic was something I was completely unprepared for. How hard could it be? I scrambled around, implemented something that I had pieced together from old tutorials, and it was working! But... would bug out with two cultists in the game. I tried to fix it, tried to implement states that would allow the cultist to be picked up and put down without triggering whatever the bug was, but I would just not be able to click and drag the other cultist sometimes without clicking on the one that I had just dropped. Back to the Google machine and I found some information on the event based handling. Cobbling the two concepts together and eureka! I could drag my cultists around. On to the next step at 3:00am, where are they in the game?

I made a few simple sprites with box colliders on them, they had a unique color for each zone and I knew that I was going to need a tag for each area, so I created tags for the zones as well. Now, there might be a better way to do this, but I wanted my cultist game position based on where they were standing, so I adopted a ground check idea from several 2D platformer tutorials. I put an empty game object at their feet and in the cultist's script, created a Physics2D overlap circle to find the box I was standing in. I kept the radius very, very small and printed a Debug.Log message indicating the tag of the area that I was standing in. 3:20am, and the core interactions were working. Adrenaline and caffeine kept me moving after that. If I can just make them produce in the zones, I technically have a game.

I knew that I needed a repository for the game state. How far was the ritual progressed? What are the meters at? etc. I made an empty GameObject and created all of the variables that I thought I would need. I also created a GameState enum that would let me determine if the game was running or not. Back in the Update method of my cultists I wanted to make sure that the only time they were doing anything was when the game was in progress. The Update method contained an if statement that all of the InProgress actions would take place. If the game is in progress, produce, make sounds, check happiness, etc. Right now, they just needed to produce faith. I knew that I wanted their happiness to interact with production, and I knew that each zone would have different production rates, and I also knew that I wanted to be able to tweak and balance those items, so everything became a public variable. I started off with SerializedFields, but I didn't know what I was doing with the numbers yet, so I made them public. I also didn't know how often I wanted them to produce, so I created variables to have a cooldown on their production rates. All of the pieces were in place and I was ready. A little bit of tweaking here and there and the script was working. The cultists were filling the faith meter. I quickly duplicated the work and they were filling the other unnamed meter too. It was 4:00am and the game was somewhat running.

I thought that I should sleep, but that feeling quickly passed. I wrote some code to deal with their happiness and tied that to their face change, and although it wasn't updating their happiness yet, I could manually adjust their happiness in the editor and their face would change. I didn't want it changing the face every frame, but that's how it was working at first. I implemented the recruiting progress and suddenly, I was spawning Cultist prefabs when the bar filled. I could remove my cultists from the scene and let the game mechanics spawn them in every time their recruitment hit a certain level.

I had created a canvas for the UI when I was working through the mouse drag events, so I put some sliders on that to represent the different meters, ritual, obscurity, and faith. Quickly linked those to the game controller GameObject and could see the level in game. On the game controller, I didn't know what the range of these meters should be, or how much would be needed of each thing, so I wrote them in a way that would allow me to control the maximum numbers and the meter would still work by having a variable representing the percentage and a variable representing the amount earned. I finished the first day by creating some icons to describe each bar. The hidden/secret concept was rough at this point, and I decided on Obscurity and the moon to represent how hidden they were from the public.

Day 1 behind me. (the story speeds up from here, and thanks for reading this far.)

Saturday: 10:00am - 4:00am

I had a game, and I woke up with some enthusiasm to remove the colored boxes representing the different areas. I took a screenshot of the game and moved that over into GIMP to start drawing the game area. I wanted a shrine, library, town streets to recruit on, and a TV area, with grand plans of swapping between different cultist TV shows. I wanted to have all of the UI in the center, and the areas to transition via shadow from one to the other. Small vignettes of daily cultist life. By noon, it was in the game, and I started to work on scaling it for different screen sizes. That didn't take long to properly scale the background image, but suddenly I was worried about the areas scaling properly and on my whiteboard saw "Simple." I stopped and thought Web game for ease of play, one resolution, you're not really gaining anything from scaling the screen, and if the game area opens up without scaling everything, you're influencing balance. I sized it for my desired resolution and moved on at around 2:30pm.

Back into the game I quickly tied happiness to production and started to influence their happiness based on the things that they did. Once that number was moving, the code that I already had in place changed the face. I knew I didn't want it to actually change every frame, so I checked happiness and then only updated the sprite when there was a difference where happiness was to where it is now after the adjustment. If I changed into a new level, I should change the sprite. One game element remaining at 3:00pm.

I moved on to the sacrifice. The other elements were already in place to handle it, so I combined all of those again as I had for the other bars and 10 minutes later, I was getting progress on my ritual bar and cultists were being sacrificed. Something was missing though. You were fighting the other two bars, and progress was static on the ritual bar. And, other than losing, what was the point of the other bars? I immediately knew that I needed the ritual bar to decay every so often, so I set up the variables and the game controller script to reduce it as part of the Update method, ensuring that I only did so when the Game State was InProgress. On top of that, I now had an idea for the faith bar. The higher that bar is, the less your ritual progress is impacted. Keeping faith high had value. Time for a playtester.

I still didn't have a menu system at this point, but I had a playable game by 5:00pm. I had to manually adjust the game state in the scene editor, but I was able to have my girlfriend sit down at my system and play. It took a little bit, but she won. She offered some feedback, and I sat down to play a real game for once. I had everything rolling when suddenly: Game over. Was there a bug? What was wrong? I checked my debug log and... well... I let my faith meter empty. I lost. I wasn't paying attention to it. This game needed some menu screens.

From 5:30 to about 6:30, I started working on some balance tweaks and the menus. Getting them in place, getting Textmesh pro in place for some crisp text, and most importantly setting up a button to start the game.

I started working on Scriptable Objects for the Tutorial pages and after taking screenshots and writing it all up, it was around 8:30 when I realized just how much time I had spent getting all of that text in place and having the game playtested and tweaked a few times. That's when I encounterd my first real wall. Textmesh Pro namespaces were not loading. I had just scripted the tutorial pages to update the text when you press the button, and the Textmesh pro package wasn't there. It said it was in my project. Visual studio disagreed. It was a frantic few hours of searching when finally I manually copied the required files to where Visual Studio expected them and I was back on track. I compiled and ran the game, the tutorial pages were great, and disaster struck. I tried to start the game and everything sat there. My game object with all of the balance and gameplay variables in it was empty. There were no values in any of the fields. All that careful balance: out the window. I had to remember what the values were. It's almost 11:00pm and I'm frustrated with the Textmesh Pro issue, and I just needed to keep moving. Fill it all in as I go, I have no time for this.

Back on track around midnight. Everything is running again with tutorials and menus and a playable game. I felt like something was missing. Well, two things really. I could never see when a new recruit was coming, so I implemented a bar much like the others. Since it isn't a game winning or losing bar, I kept it small and out of the way. The next important item was to have something to indicate that the cultists just did something. I made placeholder particle systems and spawned particles every time their production triggered. My intent was to update those to unique particles per production item, but in the end, they were all basically the same and I could have just colored them when they were instantiated. Still, I had a few particle system prefabs to work with. When I fired it up again at around 2:30am, everything started to feel right. I knew when things were happening. I had a clear representation of the game state. I had cultists that just vanished when you put them in the pit. Time for a little lighthearted gore.

I created a fresh particle system, made it bloody, made it vary, tried to get it to sort of look like it splattered up and then spread. Got it just juicy enough that the disappearing cultist wouldn't be too much of an issue. I added the effect to the destruction of the cultist by instantiating a particle system with a single burst that deleted itself when it finished. The particle system would be independent of the cultist game object and it would destroy itself without any additional scripting. 3:30am, everything is in place. I have time for a few more playtests and then I made a list of all of the things that I either needed or wanted.

Need: Music. Sound. Those were the biggest two items on the list. Finish the tutorial pages. (I knew I should call it the "Manual" at this point) Win screen. Lose Screen. Restart the game.

Things I want: Image for each loss type, Image for victory, a cool summoning animation for winning, light effects for the candles and other lights in the scene. An animated Vignette image that would display when sacrificing the cultists, a pickup animation when cultists are dragged, a difficulty setting to adjust for different skill levels, a random event system where tentacles would bring buffs that you could click on, penalties, and other events like the arrest of cultists to keep the game a little bit unpredictable.

Sunday: 11:30am - 7:45pm

The final day, I immediately reviewed some movie scoring videos, some music theory videos, and I grabbed Bosca Ceoil and fired it up. I tossed it into Ab minor scale and for a tense sound, did a simple two chord alternating slow rhythm. Abm and maybe Ebm. Next was some sort of percussion, somewhat like a heartbeat, but not too much on the nose. I didn't want to get out of hand. tried a few sounds I liked and gave them a bass drum rhythm that I enjoyed. All very slow. Lastly, sticking with Ab minor scale, I tossed a few notes around, did some variation, and then gave the melody a little intensity at the end. I had considered lengthening the arrangement, and probably should have, but it was now 2:00pm and I still needed sounds.

For the sounds I kept it simple. I made them all with my mouth and manipulated them in Audacity. Apologies for the chewing sound. That was lunch, and it really worked well as a sacrifice sound that was just a little bit juicy. For the cultists, I moved their vocals maybe 5 semitones up in pitch, gave them all reverb and moved along. Most of the sounds were pitched up in this way. For the gore sounds, I pitched down several octaves, tossed in some echo, and threw in some reverb. I did some strange whispers and pitched them up, threw in some echo and then faded every one of the effects out. In unity, I added the sound clips to variables on my cultist, added an AudioSource to them, and then in each of their production methods, I just played the appropriate clip. A happy accident: Since all of the cultist logic is attached to the cultist their cooldowns were not all in sync, so their sounds would fire off at different times. This made the worship sounds really interesting. I tried to keep all of the sounds pretty low key, because I was worried that a screen full of cultists would murder your ears. It sort of worked out I think.

Running out of time, at 3:30pm, I knew that I needed my Game Over and win screens, so I made a new Canvas for win and a new Canvas for losing. When the lose canvas loaded, I would explain why the game ended. The win screen didn't need this since there was only one way to win. When the lose condition on the game controller object fired, it would update the reason for losing text on the game over canvas. The game would switch to the Losing game state and the canvas would change. It was late and I was clunky with the canvas changes. I basically disabled all of their sprite renderers and forced the one I wanted to show to be enabled.

I only had time for one "want to include" and I chose the least disruptive. I created a flashing light that utilized Mathf.PingPong and Mathf.Sin to control the flickering lights. I adjusted the alpha channel on the light sprites and made all of my lit areas flicker just a subtle amount. Each one is just a little bit different. It was now 5:30pm and I was about to chicken out.

Maybe I won't post. My significant other pushed me a little bit more and I did it. Opened all of the accounts I needed and had the game submitted by 7:30. There was a long period of "source code anxiety," not really knowing the cleanest way to do it. And that's sort of it. Eldritchual is a thing now. And, fantastic job getting this far in the read (or skipping to the end and pretending to read).

I just want to close by saying: Have you ever seen something that wasn't really a game and then you decided at some point, that this is pretty much a game that only I am playing?

Well, at some point during the day 2 recap, that became me and this little nagging character limit indicator at the bottom of the text box. It's not that I need to get a high score here, its more that I can't let this little thing beat me. With about 200 more characters to go at this point, there's really no reason to stop. So I'll try to close in just enough characters by thanking everyone that helped along the way, all of the content creators that made tutorials for me to learn from. Fantastic YouTubers like

Eldritchual Post-mortem

Eldritchual was my first game jam entry, and writing a brief post-mortem will be a great opportunity to smooth out the process for future jams. (That's my hope at least.) Hop over here to rate, play, and check out the source code, and after you have a chance to play and review Eldritchual, hop back here and see a few of the lessons learned.

SS3.png

What Went Right?

  • The mechanics and interactions remained simple. One of the driving design notes on the whiteboard next to me was "Simple." It was a reminder to keep the scope small enough to complete and clear enough to be both accessible and approachable.
  • It's complete. I kept saying that "I just won't post if it's not done." I pushed myself to have a complete game, and then I still needed a nudge to post it. Being able to stay on task and check off every one of the features that I decided that I needed to be in the game was a fantastic positive for me. There was a list of "like to have" items on my feature list, but
  • I posted the game. This was surprisingly challenging to post to the Compo. I almost backed out at the last moment, but just posting the game was another positive for me. I needed a push.
  • Tried things I've never done. Unity scriptable objects for the lesson topics in the tutorial, mouse click and drag interactions in Unity, Music in Bosca Ceoil, and of course all of the things that come with the process; hosting a game, participating in a 48-hour game event, and pulled everything together before the deadline.
  • Clearing my mind before the event. I started thinking about the themes as they went through voting and I listened to the positive and negative feedback about them. Ultimately, I needed as much time as possible to clear my thoughts and position myself to tackle the challenge.
  • Subtle 2D lighting. I really enjoy the subtle light flickering effects from all of the objects. There are a few things I would have like to have tried with it. In the end, I think the small amount of light and motion helps keep the game screen alive.

What Went Wrong?

  • Slow start. The majority of the game balance and timing seemed to work, but getting the player interacting with meaningful choices had a 36-second delay, even if you know what you are doing. Difficulty settings and an event system would have addressed this.
  • Tutorial was too long. At first, it was going to be a tutorial. With scriptable objects, I was able to create more content relatively quickly, and I had initially intended to display some "under the hood" information there as well. The tutorial quickly turned into a game manual, which would be fine, but was not represented that way, and the game lacked an introduction as a result. The "Tutorial" should have been rebranded on the menu screens as a "Manual" before the conclusion.
  • No version control. Not only was there no version control, but somehow the main game object had all of its balance values cleared and I didn't have a complete list of them. I was also not prepared to host my source code once I decided to post the game. As a result, there was a needless delay in posting the source code.
  • Coding became bulky and sloppy. Too many features were stacking onto the game objects, and later on, some methods would have cleaned up the code and been easier to maintain. For instance: each method that toggles the display of a menu or UI canvas manually sets the canvas to true or false. As I added more menus and screens, this temporary code kept drawing my attention back with strange canvas interactions. More methods and classes would ultimately have been worth more and would have been able to be used for more features than my inline-procedural hacks.
  • Music quality was low. Had I been prepared, I would have just played and recorded a music track. I thought it would be cleaner to use a tool like Bosca Coeil, but I think I could have had higher quality if I was just ready to perform and record.
  • Eating and sleeping. I didn't eat or sleep like humans usually do. That was somewhat to be expected, but with a little bit of preplanning, this could have been avoided.

What Will I Do Next Time?

  • GitHub. I've uploaded the source code to a GitHub Eldritchual Repo after the event concluded. This is significantly easier to work with and trivial to share the source code. In addition, I've been able to create a development branch to make some small changes to the code that can be reincorporated into the master after I finish the features and balance that I really wanted to include in the game. Until then, the original LD version can still be seen in the master. I was worried that the time crunch of the jam, and Unity, and my limited exposure to Git would be a hindrance. In reality, it would have likely saved me time, and in retrospect, I had enough time to get it started. In addition, I could have used the GitHub project features instead of my trusty whiteboard for my feature based development. Just incorporating the tools available on GitHub, I hope to have a much cleaner and more organized project.
  • Have my instruments and recording equipment ready the night before. I could have and should have had better options for music available.
  • Vacation day on Monday. A 48-hour event takes a lot out of a person. I should have taken the day off on Monday. This may not seem like a lot, but having a chance to relax, spend time reviewing some games, and spend time with family after ignoring them for two days would be a better way for me to handle it.
  • Get to the good stuff. Get the player playing as soon as they launch the game. You have less than 30 seconds to get to the hook without the player feeling the hindrance of that delay. I'm going to aim for a player-driven ramp up that allows a player to ramp up at their own pace.
  • Gimp brush dynamics. I noticed that there were a few brush dynamics that I would have like to have tweaked a little bit. More options for cleaner lines, more options for smoother brushes. I want to have the brush dynamics ready for a variety of styles since I don't know what I will need to create.

So, those were some of the lessons that I've walked away with. I hope there is some insight that can help you, even if it is from a first-timer. What do you think? I'd love to hear what you think I've missed or how you tackled these issues in the comments. Thanks for reading!

LD 44

Specimen Delve - Compo Entry

Cover.png

Intro

A scoundrel specimen collector with two ray guns and some tentacles is about to show a dying planet just how little he cares about your life, while laughing all the way to the intergalactic bank.

Freeze the native lifeforms and then slap a transfer order on them to beam them up to your ship. Avoid the saw bots and their blades, or slap them until they break! Use your heat ray to break through the cavern and make your way to the other specimens to be collected. Slide down the cavern walls with tour action-grip-tentacles, and boost off of them during a slide to climb up faster.

Oh, and I forgot to mention, the planet is about to explode, and your engineer is giving it all that it has. For the small price of some of your extra specimens, he can push it just a little bit longer before they abandon planet. Get moving!

Play

Rate, Leave Comments, and Try Specimen Delve here!

About

I didn't really latch on to the theme, so I interpreted "Your" as "not mine", "Life" as "Lifeforms", and "Currency" as a thing that buys you something "time".

This endeavor was very focused on "Systemic" play. Unfortunately, some of the systems there was no time for. (Killing lifeforms drops pink goo, killing robots explode, tentacle slap knockback, and things like aiming on an angle.) There were a few points that I was really stuck on, and a few areas that I tried to spend too much time polishing.

While it is playable with a keyboard, I used my Steam Controller in Desktop mode, and at the last minute had to swap Esc for ` in the key bindings, since the final web version would leave full screen mode. It only took a single keybind remap for me, but here it is. I'd love to have put an option to remap controls in the game, but there is only so much time!

Have fun!

Lifeforms Detected

The best profits are the most dangerous in the specimin trade. Freeze, mine, and slap your way to payday while you survive as long as you can in this dying planet, beaming your collected specimens back to your ship. Don't waste too much time wandering the caverns, your engineer might take the ship at any moment. Bribe him with the specimens you've collected to stay just a little bit longer in Specimen Delve.Give it a try and rate!

Cover.png

Beam Over to Specimen Delve

Cover.png

Bring your tentacles and ray guns to Specimen Delve, a 2D Platformer set in the caverns of a dying planet. Collect specimens of the alien life, avoid the harvesting Sawbots, and mine your way through the planet. Send as many specimens as you can back to your ship until your engineer decides that it's time to jump the ship a safe distance away, with or without you. Offer delicious lifeforms as bribes to stay just a little bit longer, and try to save enough to make a profit.

Head over to Specimen Delve and comment with your high score!

Patrolling Sawbots

I tried something that I had not done before in Unity for this LD: Raycast2D. You can see the sawbot functioning, and don't forget to play and rate Specimen Delve, here.

What the Sawbots Do

The Sawbots are fairly simple automatons: they patrol back and forth on whatever block they are on, then if they run out of platform to walk on, they turn around. If they bump into something, they turn around. If they see something they can shoot, they stop moving and shoot. That was the general idea, and here's how it went.

Disclaimer: I'm describing what I did, which may or may not be ideal. Experts comment!

The Setup

The Sawbot is a single sprite with an empty GameObject floating out in front of it. To get it moving, I had a few booleans managing what the sawbot was doing, and then a simple translate to move it during FixedUpdate.

``` Vector2 facing; facing = (facingRight) ? transform.right : -transform.right; if (moving) { transform.Translate(facing * speed * Time.deltaTime);

    }

``` There's a small Flip function to rotate the sprite/gameobject as well. The full code is in the PatrolAI.cs script on github. Floating in front of the sprite is an empty GameObject that I aim a ray downward to look for ground ahead of it, and a ray forward to look for targets to shoot. You can see the rays and position below (which will likely be pulled in closer in a later build)

Looking at the Ground

SawbotAIRays.png

And here (but consolidated) are the functions that I used to detect the ground. The LayerMask contains all of the objects that could be ground, while the edgeDetect Transform is the Transform of the empty GameObject that was being used to look ahead at the ground. ``` public Transform edgeDetect;

public LayerMask lm; //looking for ground

    RaycastHit2D hit;
    hit = Physics2D.Raycast(edgeDetect.position, Vector2.down, 1, lm);
    Debug.DrawRay(edgeDetect.position, Vector2.down, Color.red);
    if (hit.collider != null)
    {
        hitGround = true;
        Debug.Log("Robot hit something.");
    }
    else
    {
        Debug.Log("Robot didn't see ground.");
        Flip();
        hitGround = false;
    }

```

Happy Accident Looking Down

This worked well while on a platform, and accidentally worked (sort of) when it walked into a wall, since it detects the wall ahead as ground. As the player froze objects, however, the Sawbot didn't flip. I added a Collision check and when the sawbot hit an object with the "Iceblock" tag, it would turn around.

private void OnCollisionEnter2D(Collision2D collision) { if(collision.gameObject.tag == "Iceblock") { Flip(); //Debug.Log("hit an iceblock"); } }

Unfortunately, after adding additional Sawbot spawning mechanics, I realized that I forgot to update the OnCollisionEnter2D function above, and the below behavior emerged: SawbotCollide.png Two Sawbots would run into each other indefinitely since they neither detected the Sawbot in the collision, or saw the other Sawbot with the ray. My first instinct was: FIX IT! Then, as I watched it happen a few more times, I realized that there was something amusing about these mindless drones running into each other indefinitely, because they were either malfunctioning or poorly programmed to begin with. I started trying to push Sawbots into these positions, and found that I could use their "programming" against them to harvest the level around them.

For me, this was a fun, unplanned, and emergent behavior that I decided to keep. See if you can use this technique against them and get deeper into the caverns in Specimen Delve over here.

My Takeaways

Overall, even though I wandered around the code to make these things function, I was able to get the patrolling, target detection, and shooting all to function with essentially the same technique. Cast our a Ray, determine what it hit, and take action. Having this tool in my back pocket opens up several options for me, and an unexpected number of uses in 2D.

Let me know what you think or what interesting things you may have used RaycastHit2D for. Thank you for reading!

Ludum Dare 46

Random Levels in It Hungers

I thought I'd take a few minutes to quickly describe how I created random levels in It Hungers. This last minute addition to the game was really something that made it a little bit more replayable for me, even though it's a very crude addition.

The Overall Plan

The plan basically consists of a grid of positions within an arena. I would then essentially shuffle a deck of tiles, rotate them, and place them into the arena. These vignettes are each responsible for populating themselves with the prefabs that inhabit them, like enemies or pickup items.

The Grid

It's not much to look at, but the grid is basically several game objects out in the world. grid.png

Pretty uninspiring, right? That's where my VignetteManager comes to the rescue!

The Vignette Manager

The vignette manager's job is to know where all of the game positions are for these tiles. Generates a random "deck" of tiles, shuffles it, and rotates each tile as it places it down into the game. Each tile then populates itself, or in the case of "special" tiles like the player spawn or the larva spawn, it handles them accordingly. This is a little bit clunky, but the shuffling function basically randomly selects an item in a List (array) of available locations. It "draws" that tile from the stack, and places it into a "shuffled" stack. Basically, all it's doing is rearranging the order of the tiles.

``` Transform randomListVignetteTransform() { Transform selectedVignetteTransform;

    int index = Random.Range((int)0,(int)shufflingVignettes.Count); //picks a random array index
    selectedVignetteTransform = shufflingVignettes[index]; 
    shufflingVignettes.RemoveAt(index); // removes that index from the unshuffled version of the list
    shuffledVignettes.Add(selectedVignetteTransform); // adds it to the shuffled version
    return selectedVignetteTransform; // and returns the transform of the empty placeholder game object in the list 
}

```

Then, we randomly rotate in a similar way, and put a random vignette prefab in that location.

``` float randomPrefabRotation() { float randomRot; int randIndex = Random.Range((int)0, rotations.Length); randomRot = rotations[randIndex];

    return randomRot;
}

GameObject randomPrefab()
{
    GameObject randomGO;
    int randIndex = Random.Range((int)0, vignettes.Length);
    randomGO = vignettes[randIndex];

    return randomGO;
}

```

You may have noticed by now, that each of these bits are really doing the same thing: grabbing random items from a list. These random things are basically random obstacles or meshes, that have not been populated yet with any denizens or items in the game.

Filling out the Vignette

The last little bit was putting something in each of these vignette tiles. Basically, I really did the same thing. A random list of "things" in an empty game object. The Start method randomly instantiates an item from that list, and the placeholder game object deletes itself.

``` public class RandomSpawnControl : MonoBehaviour { public GameObject[] enemySpawnerGO; public GameObject mapGOParent; public GameObject spawnParentGO;

// Start is called before the first frame update
void Start()
{
    spawnParentGO = GameObject.FindWithTag("MapGOTagger");

    GameObject goInstantiated;
    GameObject objToSpawn = enemySpawnerGO[Random.Range((int)0, enemySpawnerGO.Length)];
    goInstantiated = Instantiate(objToSpawn, this.transform.position, this.transform.rotation);
    goInstantiated.transform.SetParent(spawnParentGO.transform);

    Destroy(this.gameObject);
}

} ``` These enemySpawnerGO game objects are enemies, items, and spawners. randSpawn.png You can see that I've cheated a little bit, and seeded these elements to favor some things more than others. Once this has all been instantiated, you've got yourself a level!

LD46LDImage.png

Thinking like a Boardgame

I sort of knew what I was getting into with random levels. I've looked at it so many different ways, and ran out of time trying to do it in a previous Ludum Dare. This time, the Ah Ha moment was thinking like it was a board game. These weren't "random levels" they were tiles or cards being drawn from a deck. Pick a random place, draw a random card, place it, and remove the possibility of "drawing" that same location again. I know it's a mess and could use more work. But look at it! It was a 30 minute effort and really made it feel like there is more game there.

The full code can be found buried here: https://github.com/ArkInRev/LD46

You can check out the game here: https://ldjam.com/events/ludum-dare/46/it-hungers

If you stuck it out this far, thanks for reading and I hope it helps someone!

Ludum Dare 49

Ludum Dare 51

It's Looking for You

GettingEaten.png

It Searches in the Darkness

An alien lifeform stalks the corridors of the ship. It listens for the noise you make when you are near it, and it will charge at you ravenously if you're spotted. Fortunately for you, light causes the creature pain. If only you could keep the power on for longer than 10 seconds!

Stalk through the ship, find the missing parts to fix the generator, and avoid the alien in the darkness.

Play 'It Hunts!'

https://ldjam.com/events/ludum-dare/51/it-hunts

Run!

Avoid the Alien

closeCall.gif

Close Call!

Try to avoid the alien while you repair the ship's generator. The power toggles every 10 seconds, so get moving and stay hidden. Play "It Hunts" here: https://ldjam.com/events/ludum-dare/51/it-hunts