Sloth Quest Free Demo: http://www.lumatap.com/sqdemo/index.html
lumatap
Creator of
Recent community posts
We have recently made our game demo available on our website: Sloth Quest Web Demo
Please try it out and let us know what you think. Any comments would be appreciated!
Cutscenes
We're trying to make a somewhat silly game that's a bit unexpected, so throwing the player into a strange, unexplained situation seems completely appropriate, but we're also aiming for a smooth gaming experience. To polish it up we're adding some cutscenes to tell the backstory.
I'm using the Timeline in Unity to layout the cutscene. Like a typical video editor, the timeline lets you take various animations and organize them into a continuous movie experience. Here is the timeline for the introduction cutscene:
It's pretty simple. The rows in the table are separate tracks that roughly correspond to different objects in the world. The top track is the camera, then three tracks for the sloth related items and three more for the chimp (our antagonist). The whole scene takes only 43 seconds, but took a couple of days to plan, build art and choreograph.
Spider Web Trampolines
We had this idea for bouncy spider webs but it seemed too uncontrollable to be of any use as a mechanic. But spider webs are sticky, so we got the idea that you could grab onto them as they are bouncing. But if you let go of a web that's just bouncing up and down, you will only fly up or down. So, we made these webs go around in a circle. Now when you let go, you go flying in the direction you were heading when you released. For added control, the circular motion of the web scales as it makes each circuit. It starts with small circles and gets bigger and bigger, then repeats. If you let go on the biggest circle, you can really propel the sloth across the scene!
Please share your experiences with managing email addresses you collected. We are getting ready to make our game demo available and hope to collect some email addresses. I am wondering what is the best way to management these addresses without too much overhead. Any information shared will be much appreciated.
True. We intend to combine these strategies. We figured flyers with just game title and links to website won't produce much incentive to go find out more about our game unless we offer a demo. We could also draw in more people to try our game on some location if we offered free something (ie finish all three levels within time limit and you get a five dollar gift card?). Of course, I haven't actually tried any of this yet. First things first, get the demo ready. It'll be after the holiday season before I start calling some stores. I have no idea if people are open to this sort of suggestion. I'll try to post something when I get some result. :)
Just yesterday, we were brainstorming about how to recruit for beta testing as well as advertising for the game. Such as:
1. make flyers about the game and post it to local colleges and universities
2. ask stores around us if they would allow us to setup a station where people can just come and play test for a day. Have signup sheets ready, of course
3. setup a web demo with link to a form
Nothing new, of course, but it hadn't occurred to me to try these things until recently. We are hoping to get a demo out soon :)
Thought we'd share one of our dev blogs posted on our website (www.lumatap.com):
Dev blog for October 2019
Crustacean Creation
There is so much to do to make a game, it astounds me how many get finished. Apart from making the actual game (art, game objects, scenes, code) there is website stuff, trying to build an audience on social media, legal business stuff, interfacing with all the game stores (Google Play, Apple, Steam) and daily stuff like managing the version control system and making backups. We're several months into our development and, while we're definitely past the halfway point, there's still a bunch to do. Just making an incidental character takes a lot of steps. As an example, I thought I would walk through how we're doing it.
Meet the crab. When we were designing the underwater levels (oh yes, there are underwater levels) we decided on a few major mechanics and then added a few minor things until it seemed well rounded. The crab is a minor character whose job is to generally annoy the sloth and add some charm to the water scene. He started out as just a crude sketch. I knew I wanted a fiddler crab. They have one big claw that they use to intimidate each other, and generally look a bit silly waving it about.
To begin I did an image search for fiddler crabs, got a page full of results on one monitor, and opened up Blender (a 3D modeling program) on the other. All our models in Sloth Quest are made of various planes in layers that are viewed flat in 2D. The layers are to separate body parts and define which ones are in front or behind others. The crab body is in one plane and his legs are in another behind the body. Each plane is a connected mesh of triangles that form the solid parts that later get painted.
I wanted the crab to be able to walk around on the bottom and to jump up and grab the sloth when he was near and overhead. This required a couple of animations, and animations require bones. Bones get attached to the mesh (or vice versa) and make it deform by dragging the mesh when the bone moves. The armature of bones for the crab was actually more complicated than you might imagine. Crabs have ten legs, but I left a few off to keep them more visually distinct: I only made six. Each leg got two bones to form the upper and lower limb parts. The big claw got a third limb bone to allow it to reach up and a fourth to open and close the claw. The body got one bone and I gave each eye stalk a bone, though I ended up not animating them. All these bones are organized in a hierarchy under the body bone, which in turn is a child of the root bone, a special bone that will move the entire character as it walks.
Before animating, I took a few extra steps and formed IK (inverse kinematics) chains with each limb. In brief, the IK chain lets you position the tip of the limb (the hand or foot) and the other limb bones are automatically repositioned to match. This saves a tremendous amount of time during animation. In the end, the crab legs have nineteen bones, but to animate I only have to position eight (which is still a lot). I made four animations for the crab: standing idle (like he's breathing), reaching up, jumping up and walking. The walk cycle is the most complicated as I needed to coordinate the movement of four legs. The dope sheet image shows each keyframe as a white diamond. The frame numbers representing time are along the bottom scale. I positioned a limb on each keyframe and the animation system interpolates the movement between the positions.
There's a couple other steps involved before getting the crab into the Unity game engine. I had to break the mesh up logically and "unwrap" the resulting pieces into a square. This square is called a UV map (UV refers to the X and Y axes of the square). The UV map defines the areas that will be painted to produce an image (texture) and how it relates to the model's mesh geometry. When making a UV map you generally want to fill the whole square with the mesh parts, leaving as little empty space as possible. Empty space is just wasted memory and bloats the project. It's not very critical a detail, but I kinda like tinkering with the pieces to find an efficient arrangement, like doing a jigsaw puzzle.
So after you create the mesh, build the armature, attach the mesh, animate the armature and make a UV map, you can now export the file. There's a few quirky things you need to figure out to get an acceptable result, but after doing it hundreds of times you get used to it. The resulting FBX file is imported into Unity where it can become an object in the game. But wait, every object has colors, right? We still need to paint it.
We use 3d-Coat to paint our models. It's a complete modelling / retopo / painting system that lets you paint using PBR (physically based rendering) materials in real time and it's fast and sleek. It's not without it's quirks, but it really makes painting fun and satisfying. To paint the crab I imported the FBX into 3d-Coat and set up a UV map of 256 x 256 pixels. You can paint in logical layers just like in Photoshop and later shift them up and down or change their properties in a non-destructive way. I used a couple of layers for different parts of the crab for convenience. After painting, I exported the color texture map (just a square picture really) as a PNG file. Our game is 2d and doesn't use any fancy lighting effects (like normal maps, roughness maps, metallic maps) so I only needed the one color map in this case.
Back in Unity I imported the color map and created a material for the crab. The material marries the color map with the shader (the micro-program that draw the pixels). Next, I created an animator controller for the crab. This defines and controls the different states the crab can assume. I created a state for each animation and a couple extra for when the crab is grabbed onto the sloth and to allow walking left (the walking right animation is played backwards). To finish, I added a variable parameters to trigger the different states and created transitions between the states that would occur when the various parameters changed.
I opened a test scene and dropped the crab model in it. I applied the crab material to the model in the scene and also added the animator controller. To allow the crab to interact with forces and other objects in the physics engine I added both a rigid body and a circle collider. At this point, the crab is visible in the scene and can potentially animate, but that's about it.
To make the crab a character, he needs behavior in the form of C# code. I created an empty script file and began to write some code. It starts out declaring some variables I'll need.
enum CrabState { Idle, WalkRight, WalkLeft, Attack, GrabbedSloth, Release } CrabState CurState; int WalkParamId; int ReachUpParamId; int GrabJumpParamId; int GrabbedOnParamId; Animator Anim; Rigidbody2D BodyRB; Transform BodyTr; Transform ClawTr; bool OnGround; RaycastHit2D[] GroundTestResults; float GroundCheckTimer; bool Jump; bool PushOffSloth; float WaterTimer; float ActionTime; float StateTimer; AudioSource AudioSrc;
Now for some action. The first thing was to find the various parts of the crab that would be manipulated: the animator controller, it's parameters, the crab rigid body, etc. The Unity engine will call the Awake() function exactly once when this object is being created.
void Awake() { Anim = GetComponent<Animator>(); WalkParamId = Animator.StringToHash("walk"); ReachUpParamId = Animator.StringToHash("reach_up"); GrabJumpParamId = Animator.StringToHash("grab_jump"); GrabbedOnParamId = Animator.StringToHash("grabbed_on"); BodyRB = GetComponent<Rigidbody2D>(); BodyTr = transform; ClawTr = transform.Find("Armature/root/body/arm1.L/arm2.L/arm3.L/claw.L"); GroundTestResults = new RaycastHit2D[4]; AudioSrc = GetComponent<AudioSource>(); }
I created a SetState() function to mirror the various states the animator state machine has. They mostly set up the animator, except for the state GrabbedSloth. To grab the sloth with the crab I create physics joint that binds the two rigid bodies together. In this case, a hinge type joint is used so the crab can flob about while hanging on.
void SetState(CrabState st) { CurState = st; StateTimer = 0; switch(st) { case CrabState.Idle: Anim.SetFloat(WalkParamId, 0); Anim.SetBool(ReachUpParamId, false); Anim.SetBool(GrabbedOnParamId, false); Anim.applyRootMotion = true; ActionTime = 1f + Random.value * 2f; break; case CrabState.WalkRight: Anim.SetFloat(WalkParamId, 0.2f); Anim.SetBool(ReachUpParamId, false); Anim.applyRootMotion = true; ActionTime = 0.3f + Random.value; break; case CrabState.WalkLeft: Anim.SetFloat(WalkParamId, -0.2f); Anim.SetBool(ReachUpParamId, false); Anim.applyRootMotion = true; ActionTime = 0.3f + Random.value; break; case CrabState.Attack: Anim.SetFloat(WalkParamId, 0); Anim.SetBool(ReachUpParamId, true); Anim.applyRootMotion = false; break; case CrabState.GrabbedSloth: // Create joint to attach crab HingeJoint2D joint = gameObject.AddComponent<HingeJoint2D>(); joint.autoConfigureConnectedAnchor = false; Transform slothTr = Sloth.GetInstance().GetBodyTransform(); joint.connectedBody = slothTr.GetComponent<Rigidbody2D>(); // Adjust to point near leg-body joint joint.connectedAnchor = new Vector2(0.15f, 0.05f + Random.value * 0.1f); joint.anchor = BodyTr.InverseTransformPoint(ClawTr.position); Anim.SetFloat(WalkParamId, 0); Anim.SetBool(GrabbedOnParamId, true); AudioSrc.clip = SoundFxCollision.GetInstance().GetClip(SoundFxCollision.SoundMaterial.Stick, SoundFxCollision.SoundMaterial.Flesh); AudioSrc.Play(); break; } }
The Update() function gets called every drawing frame, hopefully 60 or more times a second. Here's where some important decisions get made. While the crab is idle, he just waits a bit, then, if he's on the ground, I pick a random direction and start walking. But if the sloth is near he will try to attack.
void Update() { StateTimer += Time.deltaTime; switch(CurState) { case CrabState.Idle: if (StateTimer > ActionTime && OnGround) { float dir = Random.value - 0.5f; if (dir < 0) SetState(CrabState.WalkLeft); else SetState(CrabState.WalkRight); } else if (IsSlothNear()) SetState(CrabState.Attack); break;
While the crab is walking, he's still looking for the sloth to attack. After a short walk, he stands idle again.
case CrabState.WalkLeft: case CrabState.WalkRight: if (StateTimer > ActionTime) SetState(CrabState.Idle); else if (IsSlothNear()) SetState(CrabState.Attack); break;
To attack, I trigger the attack animation. I added an event to the animation so that when the crab should leave the ground, it calls a function that turns the Jump variable to true. More on this later.
case CrabState.Attack: if (!IsSlothNear()) SetState(CrabState.Idle); else if (OnGround) Anim.SetTrigger(GrabJumpParamId); break;
While the crab is grabbed onto the sloth I have to manually move the joint around so it lines up with the big claw. In general, the animation system and the physics system don't play well together. When you have an object driven by both of them, the animation system typically out-bullies the physics. After holding on for 12 seconds, the crab will let go. To prevent instant re-grabbing I have the crab push away from the sloth.
case CrabState.GrabbedSloth: if (StateTimer > 12f) { Sloth sloth = Sloth.GetInstance(); if (!sloth.IsDead()) { HingeJoint2D joint = GetComponent<HingeJoint2D>(); if (joint != null) Destroy(joint); PushOffSloth = true; } SetState(CrabState.Release); } else { // Maintain joint at crab claw as anim transitions to rest pose HingeJoint2D joint = GetComponent<HingeJoint2D>(); joint.anchor = BodyTr.InverseTransformPoint(ClawTr.position); } break;
After releasing the sloth, and after a short delay, the crab returns to idle.
case CrabState.Release: if (StateTimer > 0.5f) SetState(CrabState.Idle); break; } }
The FixedUpdate() function gets called every physics tick, which should be at a fixed interval, usually 60 hertz. It's the place to move physics objects (rigid bodies). At the start, I check if the Jump variable was set (from the jump animation event) and if so, I apply an upward force to the crab. This is a one-time force, so I reset Jump to false until the next time he jumps.
void FixedUpdate() { if (Jump) { Jump = false; BodyRB.bodyType = RigidbodyType2D.Dynamic; BodyRB.AddForce(new Vector2(0, 2f), ForceMode2D.Impulse); }
Similar to Jump there's a variable to push away. Here I calculate a vector away from the sloth and give a gentle boost in that direction.
if (PushOffSloth) { PushOffSloth = false; Vector2 dir = BodyTr.position - Sloth.GetInstance().GetBodyTransform().position; dir = dir.normalized * 0.5f; BodyRB.AddForce(dir, ForceMode2D.Impulse); }
In the rest of the function I handle some environmental control. To keep the crab legs down I apply a small torque to rotate his body if it's tilted too much. Every half second I probe downwards from his body to see if there's a ground object present (ground objects are found in the wall layer). If there's no ground I prevent him from walking. Thirdly, I check if there was a collision with a water object lately, if not, I'll apply full gravity. Normally, when underwater, the gravity force built into the rigid body is weakened.
// Maintain horizontal posture float zrot = BodyRB.rotation; if (zrot < -2f) BodyRB.AddTorque(0.2f, ForceMode2D.Force); else if (zrot > 2f) BodyRB.AddTorque(-0.2f, ForceMode2D.Force); // Check for ground GroundCheckTimer -= Time.fixedDeltaTime; if (GroundCheckTimer <= 0) { GroundCheckTimer = 0.5f; int cnt = Physics2D.RaycastNonAlloc(BodyTr.position, Vector2.down, GroundTestResults, 0.1f, 1 << GameRoot.LayerWall); OnGround = cnt > 0; // Stop walk if not on ground if (!OnGround && (CurState == CrabState.WalkLeft || CurState == CrabState.WalkRight)) SetState(CrabState.Idle); } WaterTimer -= Time.fixedDeltaTime; // Left water? if (WaterTimer <= 0) { // Body no longer buoyant BodyRB.gravityScale = 1f; } }
This function checks if the sloth is attackable. The crab will attack if the sloth enters a rectangular region that is above the crab.
bool IsSlothNear() { Sloth sloth = Sloth.GetInstance(); if (sloth.IsDead()) return false; Vector3 slothPos = sloth.GetBodyTransform().position; Vector3 pos = BodyTr.position; // Sloth above crab? if (slothPos.y > pos.y + 0.1f) { if (Mathf.Abs(slothPos.x - pos.x) <= 0.4f) return true; } return false; }
This function gets called from another tiny script that handles collisions with the crab claw. Collision handler code gets called from the physics engine when object colliders overlap.
public void SlothHitCrab() { if (CurState == CrabState.Attack) SetState(CrabState.GrabbedSloth); }
This is the collision handler for the crab body. Here I'm only interested if the crab is still colliding with some water object. If so, I set a timer that, if expired, indicates the crab has been out of the water long enough to take some action (as you can see above in FixedUpdate()). While underwater, the crab experiences only a weak gravity.
void OnTriggerStay2D(Collider2D coll) { // In water? if (coll.gameObject.layer == GameRoot.LayerWater) { // Reset water timer WaterTimer = 1f; // Body sinks slowly BodyRB.gravityScale = 0.3f; } }
Lastly is that little callback from the jump animation--here is the handler it calls.
// Animation event void JumpEvent() { Jump = true; }
While I certainly left out a few details, that sums up the efforts to get the crab character in the game. Of course, the finished crabs must still be placed into the scenes. After that, you get something like this:
So true and yet so hard to follow. We seem to fall into that "rabbit hole syndrome" all the time. Before we even realize to cut it short a week or two passes by and the project stalls. That's why we started to set up schedules with milestones that are fairly short term. If we have a date set for a feature we seem to be able to keep our focus better. For example, instead of diving into the full rpg game, which we wanted to develop next, we decided to make a mini prequel to test out our ideas as well as the functionalities.
I have a part-time job but my husband and I are trying to make game development our mainstream work. We found it complements our skills well. However, we only recently found a comfortable role for each other that not only works but we both enjoy. We also learned from releasing our first game ,Sarah in the Sky, that setting achievable short term goals is vital to us. Yes, we are just starting out but we are optimistic.
Well, our 44 views in 3 weeks sounds like we are in trouble. :) We are new to the market with a relatively simple and casual game, so we have the same type of questions. Nevertheless, here's something we noticed. We launched our game on Itch.io a week before we launched on Steam. We are also trying out the major social networks as suggested, but we are also new to these social networking as well so that's time consuming and awkward. As it stands now, we have virtually no responses from Itch.io but some on Steam. We've made some sales on Steam but none except to friends and family on Itch.io. Apparently releasing on multiple publishers is a good advice.
Thanks for the reply. I'll check out offworld site some more though my first impression was doubtful. Just spotted this article from https://kotaku.com/hidden-object-games-are-mindless-fluff-and-thats-why-i-177414... Our game seem to fit in better as hidden-object game and it's good to see a site like kotaku mentioning this genre.
Hi, all. My husband and I just joined itch.io to publish our first game, Sarah in the Sky. It's a simple maze game. We chose the simple format so I could learn the process as well as complete the project in timely manner. I wrote the stories and designed the levels while my husband did the rest. We really enjoyed the experience, so we want to continue developing games. In fact, we want to make a rpg next and have been brain storming a lot. Cheers, to all the hard working game developers out there!
https://lumatap.itch.io/sarah-in-the-sky
Sarah in the Sky is a laid back casual game of exploration and discovery. Check it out and let us know what you think!