Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

 
Advanced search

1385190 Posts in 66327 Topics- by 58809 Members - Latest Member: foggermachine

November 28, 2020, 06:12:21 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsJOLLY WORLD - Gory physics sandbox game (⨀_⨀)
Pages: [1]
Print
Author Topic: JOLLY WORLD - Gory physics sandbox game (⨀_⨀)  (Read 792 times)
Smerik
Level 1
*



View Profile
« on: October 25, 2020, 11:23:00 PM »

Hi All,

We are proud to present Jolly World! (currently in open Alpha)


Try our open alpha here:https://jollyworld.netlify.app/

For more info on the game + editor itself, we've made this post: https://forums.tigsource.com/index.php?topic=71053.0.

User generated content: (click a level to play it)



If you are interested in technical bits and pieces this thread might be for your!

Platforms:
  • Desktop Web
  • Mobile web
  • Google Play
  • iTunes

Technology:
  • HTML5

Frameworks:
  • Rendering: Pixi 4
  • Physics: Box2D
  • UI: mostly dat.gui
« Last Edit: November 23, 2020, 11:40:15 AM by Smerik » Logged

Smerik
Level 1
*



View Profile
« Reply #1 on: October 25, 2020, 11:57:24 PM »

Undo Button

In this post I'm going to explain how we've solved a simple yet highly underrated feature of any editor, the undo button!.

The very first feedback we received on our game was the fact that it was lacking a "simple" undo button. A vital feature to any editor out there.

But technically it's really not that simple, and I'll explain a bit why. But before that let's go a little bit into the internals of Jolly World.

Jolly World serializes the whole world as an JSON object. Each independent object in the world is serialized through a serializer that turns that object into an array of properties, e.g.:
[6,2347.101869683881,1015.5543600150933,0,"","",2,"#999999","#000",1,null,[{"x":-4992.11140782106,"y":396.085418860877},{"x":-4992.11140782106,"y":-396.085418860877},{"x":4992.11140782106,"y":-396.085418860877},{"x":4992.11140782106,"y":396.085418860877}],null,null,null,null,"Grass.jpg",1,0,0,0].

The order in the JSON is the actual sorting order of the rendering engine, so objects that come first are rendered on a lower layer as new objects.

Whenever you click the screen the engine tries to find the most logical sprite you tried to click in the game and sees if it is attached to any higher level object / group or prefab and makes the full selection. Then when you move the object 10 pixels to the right, an action is fired with the current selection and it executes the desired action of moving the object 10 pixels.

The very first attempt of making an Undo is simply inverting the action and applying it again, this was very simple to make. Just store a list of all the actions executed and simply undoing inverts that action.

However very soon the engine became to complex for this, to give an example:
Let's say you have 10 different objects on 10 different layers, all with many different objects in between them. And you select all those 10 objects and decide to group them. My code executes the action group and combines all the objects on a single layer. Now to undo that we simply have to ungroup them right? Well we lost a lot of information, because we don't know any more on which layers all those objects were placed. Simply ungrouping them won't do, we also have to position them in the right layer. This becomes even more of a nightmare when all the objects also have triggers attached to them with multiple actions that are removed on grouping.

Now we could obviously make the Undo script smarter and also store more info with each type of action. But that approach is not very scalable, because then for every new feature we make we would have to go over all of the undo code and see if everything works as expected.

Can we think of a better way of solving this? The key was in the serialization of the world. We have a very fast serializer and we can build the world from a relatively small JSON object. So now instead of storing each action itself, we store the full world json of the complete world at the current state. We capped the undos to at max 50, this result in a maximum memory consumption of roughly 250MB, which is fine given that this game has a small memory footprint by itself. The added benefit now is that any new feature we build that can be serialized is also automatically "undoable". Initially I also had code in there that diffed the current world json with the previous world json and would just store the delta between them, however I found that with bigger worlds this process would become CPU intensive and was not worth the saved memory consumption.

Anyways I hope you found this interesting, I will think about a next post, if there are requests please do let me know!
Logged

Smerik
Level 1
*



View Profile
« Reply #2 on: October 29, 2020, 12:38:47 AM »

Spikes and Spears

It took me quite a long time to figure out how to do spikes in the game.


Even to the point where I sparred with Jim Bonacci from Happy Wheels to ask him how he did it.


He truly is an amazing person. He has been my motivation to push through these years of working on this game.
Happy Wheels has always been one of my favorite games, and growing up on Newgrounds where I also placed all my games https://erik.newgrounds.com I really looked up to him.

Anyways now back to the technical part, so like shared in the conversation they are done with Prismatic joints.

quoting iforce2d:
Quote
The prismatic joint is probably more commonly known as a slider joint. The two joined bodies have their rotation held fixed relative to each other, and they can only move along a specified axis

That's exactly what we want right? We want the body attached to the spike only move along the axis of the spike.

So in terms of mock code this is what i do:

Code:

 this.contactListener.BeginContact = function (contact) {

    // 1) we get the bodies and figure out which body is the spike
    // 2) we cancel the collision reaction
    // 3) we get the world manifold to find the world collision point
    // 4) we ensure this body is not already connected and has the conditions that allows it to connect (e.g. property softBody or Flesh)
    // 5) we check the contact angle, we only want to attach bodies that enter the spike from the right direction, it should not stick
    //    when the body touches the side of the spike
    // 6) if all conditions are met we push the body in an array to attach the joint in the next frame (can't attach joints during collision step)
}
this.contactListener.EndContact = function (contact) {
    // 1) we check if this body was attached to this spike
    // 2) if so we push it in an array to remove in the next frame
}

And voila!

You can use the maxMotorForce property of a prismatic joint to set the resistance of the body on the spike.

This code is also powering things like arrows and spears:
Logged

Smerik
Level 1
*



View Profile
« Reply #3 on: November 06, 2020, 11:09:37 AM »

Currently working on the functionality similar to the Ninja Rope from worms, wow that was way harder than I expected.



This blog post was most helpful in figuring out how to do it:
http://antonior-software.blogspot.com/2016/12/box2d-ninja-rope.html

Obviously we won't shoot the rope from his head, we will have upgrades that you can place around the world, similar to how it works in Mario.

Here is an example of the hats you can find:


Any idea what the first hat is going to do?
Logged

Smerik
Level 1
*



View Profile
« Reply #4 on: November 07, 2020, 05:55:00 AM »

Managed to style the rope hat completely now:
Logged

Smerik
Level 1
*



View Profile
« Reply #5 on: November 20, 2020, 02:09:30 AM »

I have finally managed to add full Bezier Curve editing in the engine and vertice editing in general.



You trigger this mode by double clicking a graphic or a physics object.

Bezier curves are really fun! One thing was a bit tricky, for adding new vertices you can click the path at any point, but how do you detect clicking on a bezier curve? For that I'm actually using a library called jsBezier. This has a very simple function that can calculate the distance to any bezier.

Having this functionality in there really improves the art created by people in our community.

Check out this amazing level!



Logged

JobLeonard
Level 10
*****



View Profile
« Reply #6 on: November 20, 2020, 04:06:15 AM »

Nice!

Gave the Christmas level a spin - took me a little experimenting to figure out the controls but worked just fine after that Smiley
Logged
Smerik
Level 1
*



View Profile
« Reply #7 on: November 20, 2020, 12:37:32 PM »

Nice!

Gave the Christmas level a spin - took me a little experimenting to figure out the controls but worked just fine after that Smiley

That's actually great feedback, I still have to work on a proper tutorial for the game. That's one of those things that is always pushed back.
Logged

Smerik
Level 1
*



View Profile
« Reply #8 on: November 23, 2020, 11:27:35 AM »

Optimization of Explosions

I took a stab at optimizing explosions. They are already quite optimized by themselves, but when you group A LOT of them next to each other, you create a chain reaction which results in a lot of debris being created. Each barrel creates like 30 physics particles, so when you stack 30 of them together thats 900 physics particles being created in a single frame. I'm going to change how this works and grab particles from a pool that can max hold 200 particles. This way I'm not creating particles (using "new" in javascript or any other language is expensive) but am just swapping in and out existing particles from the pool. This will increase the performance and take a very tiny cut in memory consumption which is way worth it!

Logged

JobLeonard
Level 10
*****



View Profile
« Reply #9 on: November 23, 2020, 02:55:03 PM »

Nice. I'll be on the look-out for improperly cleaned up state Tongue
Logged
Smerik
Level 1
*



View Profile
« Reply #10 on: November 27, 2020, 01:39:37 AM »

Nice. I'll be on the look-out for improperly cleaned up state Tongue

Haha! Yeah i'm constantly on the lookout out for these kind of leaks. It's becoming a bigger nightmare with the complexity of the engine growing.
Logged

vdapps
Level 1
*


Head against wall since 2013


View Profile WWW
« Reply #11 on: November 27, 2020, 05:55:01 AM »

Heh, I gave it a try (web alpha version), and it's lot of fun, with superb physical mechanics. Very nice piece of work, I always admire pure HTML5 games done right (I see it as more complicated to do and to debug comparing to 'conventional' languages).

Also I have to say, I appreciate physics in your game (I'm doing simple 2D physics in my other game RTG) and for me it's quite a challenge (I did only simple box vs box collisions, so veeery basic stuff and I saw it's no easy thing to do it correctly). I see that you are resolving much more complex things like joints, generic geometry vs generic geometry collisions, etc.. and it works nicely, fluently without glitches, this is quite high-level to me. (btw, I was working with Havok before, back when I was in professional game development, I had lot of fun with physics in test levels).
Logged

Smerik
Level 1
*



View Profile
« Reply #12 on: Today at 06:03:16 AM »

Thanks @vdapps. I do have to admit that I'm using a library for all the pure physics calculations. It's a library called Box2D. I have always been fascinated by physics engine. Love also the work from Natural Motion (Endorphin & Euphoria), but Havok managed to bring physics in games to mass market.
Logged

vdapps
Level 1
*


Head against wall since 2013


View Profile WWW
« Reply #13 on: Today at 03:19:36 PM »

Nice to know about this Box2D lib, maybe I'll give it a shot, even if in my RTG project I will use only very simple physics. Let's see. Yeah, I was with Havok around 2005, it was new thing back then, we were awed by what it's doing.

Look at JOLLY WORLD again, are you not inspired by Happy Tree Friends ? Grin
Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic