Jump to content
  • Advertisement

Search the Community

Showing results for tags 'Box2D'.

The search index is currently processing. Current results may not be complete.


More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Categories

  • Audio
    • Music and Sound FX
  • Business
    • Business and Law
    • Career Development
    • Production and Management
  • Game Design
    • Game Design and Theory
    • Writing for Games
    • UX for Games
  • Industry
    • Interviews
    • Event Coverage
  • Programming
    • Artificial Intelligence
    • General and Gameplay Programming
    • Graphics and GPU Programming
    • Engines and Middleware
    • Math and Physics
    • Networking and Multiplayer
  • Visual Arts
  • Archive

Categories

  • Audio
  • Visual Arts
  • Programming
  • Writing

Categories

  • Game Dev Loadout
  • Game Dev Unchained

Categories

  • Game Developers Conference
    • GDC 2017
    • GDC 2018
  • Power-Up Digital Games Conference
    • PDGC I: Words of Wisdom
    • PDGC II: The Devs Strike Back
    • PDGC III: Syntax Error

Forums

  • Audio
    • Music and Sound FX
  • Business
    • Games Career Development
    • Production and Management
    • Games Business and Law
  • Game Design
    • Game Design and Theory
    • Writing for Games
  • Programming
    • Artificial Intelligence
    • Engines and Middleware
    • General and Gameplay Programming
    • Graphics and GPU Programming
    • Math and Physics
    • Networking and Multiplayer
  • Visual Arts
    • 2D and 3D Art
    • Art Critique and Feedback
  • Community
    • GameDev Challenges
    • GDNet+ Member Forum
    • GDNet Lounge
    • GDNet Comments, Suggestions, and Ideas
    • Coding Horrors
    • Your Announcements
    • Hobby Project Classifieds
    • Indie Showcase
    • Article Writing
  • Affiliates
    • NeHe Productions
    • AngelCode
  • Topical
    • Virtual and Augmented Reality
    • News
  • Workshops
    • C# Workshop
    • CPP Workshop
    • Freehand Drawing Workshop
    • Hands-On Interactive Game Development
    • SICP Workshop
    • XNA 4.0 Workshop
  • Archive
    • Topical
    • Affiliates
    • Contests
    • Technical
  • GameDev Challenges's Topics
  • For Beginners's Forum
  • Unreal Engine Users's Unreal Engine Group Forum
  • Unity Developers's Forum
  • Unity Developers's Asset Share

Calendars

  • Community Calendar
  • Games Industry Events
  • Game Jams
  • GameDev Challenges's Schedule

Blogs

There are no results to display.

There are no results to display.

Product Groups

  • Advertisements
  • GameDev Gear

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


About Me


Website


Role


Twitter


Github


Twitch


Steam

Found 16 results

  1. olivermarsh

    Box2d overview

    Hi, I was wanting to read the box2d source, but wanted to get a broad overview first. I'll just say what I understand so far: Box2d has discrete & continuous collision detection. We first integrate our shapes velocity, and using a 'conservative advancement algorithm, we advance the shapes & find toi. It then uses gjk & barycentric coordinates to find the closest point on the shapes. If theyre overlapping we use epa or sat (and dont get a contact point? Or run gjk again?) It then builds an incremental manifold (i probably have this wrong) adding a point each frame. Then once all collision points have been collected for the frame, they go through the collision solver that takes each collision, & adds an impulse to the shape to bring the relative velocity <= 0. We go through the list of contacts several times (the iterative rigid body solver), to stabilise the simulation. I'm not sure what it uses for discrete collisions? What things I don't understand is 1. When do we know we don't need a collision point anymore? When the collision points are moving away? 2. How do we know a contact point is unique with gjk/barycentric coords? Or do we just add them and wait till they get pulled off the list? 3. If the toi is less than one & we want to use the rest up, do we run the whole collision routine again for a max say 4 times, to use it up, and where does this fit into the iterative solver? I kind of just want to get an overview of how a physics engine fits together and the parts or algorithms we need. Its just for a hobby engine, and with understanding as a priority. Any help would be great, and sorry if the question is a bit over simplified.
  2. I am developing a simply 2d physics engine and I' ve read the source code of box2d and matter.js. I found some insteresting thing on finding contact point: Box2d use indicent edge, reference edge and clip to determine a contact point. It's very complex method and hard to understand. However, matter.js use a very simply method to do the same thing. just find the vertex that contained by opposite polygon with hill-climbing: var verticesB = SAT._findSupports(bodyA, bodyB, collision.normal), supports = []; // find the supports from bodyB that are inside bodyA if (Vertices.contains(bodyA.vertices, verticesB[0])) supports.push(verticesB[0]); if (Vertices.contains(bodyA.vertices, verticesB[1])) supports.push(verticesB[1]); // find the supports from bodyA that are inside bodyB if (supports.length < 2) { var verticesA = SAT._findSupports(bodyB, bodyA, Vector.neg(collision.normal)); if (Vertices.contains(bodyB.vertices, verticesA[0])) supports.push(verticesA[0]); if (supports.length < 2 && Vertices.contains(bodyB.vertices, verticesA[1])) supports.push(verticesA[1]); } and it works well in demo. My question is: why does box2d use such complex method? It's clear that matter.js's method is better. Or there are some potential shortcomings in matter.js's method?
  3. I'm currently implementing a 2D physics engine, then i stuck in collision resolution. So i did a search in google, and i found this passage, It explains how to use impulse to separate two objects. But after that, i found another another passage, this article is very complicated, but they seem talking the same thing ——— how to implementing the collision resolution. So now, what i confuse is why are there two completely different approaches of collision resolution? What's the difference between them? Which approaches is right? I am not a native english speakers, so i hope you can understand what i wrote. Thanks.
  4. Original Post: Limitless Curiosity Out of various phases of the physics engine. Constraint Resolution was the hardest for me to understand personally. I need to read a lot of different papers and articles to fully understand how constraint resolution works. So I decided to write this article to help me understand it more easily in the future if, for example, I forget how this works. This article will tackle this problem by giving an example then make a general formula out of it. So let us delve into a pretty common scenario when two of our rigid bodies collide and penetrate each other as depicted below. From the scenario above we can formulate: We don't want our rigid bodies to intersect each other, thus we construct a constraint where the penetration depth must be more than zero. \(C: d>=0\) This is an inequality constraint, we can transform it to a more simple equality constraint by only solving it if two bodies are penetrating each other. If two rigid bodies don't collide with each other, we don't need any constraint resolution. So: if d>=0, do nothing else if d < 0 solve C: d = 0 Now we can solve this equation by calculating \( \Delta \vec{p1},\Delta \vec{p2},\Delta \vec{r1}\),and \( \Delta \vec{r2}\) that cause the constraint above satisfied. This method is called the position-based method. This will satisfy the above constraint immediately in the current frame and might cause a jittery effect. A much more modern and preferable method that is used in Box2d, Chipmunk, Bullet and my physics engine is called the impulse-based method. In this method, we derive a velocity constraint equation from the position constraint equation above. We are working in 2D so angular velocity and the cross result of two vectors are scalars. Next, we need to find \(\Delta V\) or impulse to satisfy the velocity constraint. This \(\Delta V\) is caused by a force. We call this force 'constraint force'. Constraint force only exerts a force on the direction of illegal movement in our case the penetration normal. We don't want this force to do any work, contribute or restrict any motion of legal direction. \(\lambda\) is a scalar, called Lagrangian multiplier. To understand why constraint force working on \(J^{T}\) direction (remember J is a 12 by 1 matrix, so \(J^{T}\) is a 1 by 12 matrix or a 12-dimensional vector), try to remember the equation for a three-dimensional plane. Now we can draw similarity between equation(1) and equation(2), where \(\vec{n}^{T}\) is similar to J and \(\vec{v}\) is similar to V. So we can interpret equation(1) as a 12 dimensional plane, we can conclude that \(J^{T}\) as the normal of this plane. If a point is outside a plane, the shortest distance from this point to the surface is the normal direction. After we calculate the Lagrangian multiplier, we have a way to get back the impulse from equation(3). Then, we can apply this impulse to each rigid body. Baumgarte Stabilization Note that solving the velocity constraint doesn't mean that we satisfy the position constraint. When we solve the velocity constraint, there is already a violation in the position constraint. We call this violation position drift. What we achieve is stopping the two bodies from penetrating deeper (The penetration depth will stop growing). It might be fine for a slow-moving object as the position drift is not noticeable, but it will be a problem as the object moving faster. The animation below demonstrates what happens when we solve the velocity constraint. [caption id="attachment_38" align="alignnone" width="800"] So instead of purely solving the velocity constraint, we add a bias term to fix any violation that happens in position constraint. So what is the value of the bias? As mentioned before we need this bias to fix positional drift. So we want this bias to be in proportion to penetration depth. This method is called Baumgarte Stabilization and \(\beta\) is a baumgarte term. The right value for this term might differ for different scenarios. We need to tweak this value between 0 and 1 to find the right value that makes our simulation stable. Sequential Impulse If our world consists only of two rigid bodies and one contact constraint. Then the above method will work decently. But in most games, there are more than two rigid bodies. One body can collide and penetrate with two or more bodies. We need to satisfy all the contact constraint simultaneously. For a real-time application, solving all these constraints simultaneously is not feasible. Erin Catto proposes a practical solution, called sequential impulse. The idea here is similar to Project Gauss-Seidel. We calculate \(\lambda\) and \(\Delta V\) for each constraint one by one, from constraint one to constraint n(n = number of constraint). After we finish iterating through the constraints and calculate \(\Delta V\), we repeat the process from constraint one to constraint n until the specified number of iteration. This algorithm will converge to the actual solution.The more we repeat the process, the more accurate the result will be. In Box2d, Erin Catto set ten as the default for the number of iteration. Another thing to notice is that while we satisfy one constraint we might unintentionally satisfy another constraint. Say for example that we have two different contact constraint on the same rigid body. When we solve \(\dot{C1}\), we might incidentally make \(\dot{d2} >= 0\). Remember that equation(5), is a formula for \(\dot{C}: \dot{d} = 0\) not \(\dot{C}: \dot{d} >= 0\). So we don't need to apply it to \(\dot{C2}\) anymore. We can detect this by looking at the sign of \(\lambda\). If the sign of \(\lambda\) is negative, that means the constraint is already satisfied. If we use this negative lambda as an impulse, it means we pull it closer instead of pushing it apart. It is fine for individual \(\lambda\) to be negative. But, we need to make sure the accumulation of \(\lambda\) is not negative. In each iteration, we add the current lambda to normalImpulseSum. Then we clamp the normalImpulseSum between 0 and positive infinity. The actual Lagrangian multiplier that we will use to calculate the impulse is the difference between the new normalImpulseSum and the previous normalImpulseSum Restitution Okay, now we have successfully resolve contact penetration in our physics engine. But what about simulating objects that bounce when a collision happens. The property to bounce when a collision happens is called restitution. The coefficient of restitution denoted \(C_{r}\), is the ratio of the parting speed after the collision and the closing speed before the collision. The coefficient of restitution only affects the velocity along the normal direction. So we need to do the dot operation with the normal vector. Notice that in this specific case the \(V_{initial}\) is similar to JV. If we look back at our constraint above, we set \(\dot{d}\) to zero because we assume that the object does not bounce back(\(C_{r}=0\)).So, if \(C_{r} != 0\), instead of 0, we can modify our constraint so the desired velocity is \(V_{final}\). We can merge our old bias term with the restitution term to get a new bias value. // init constraint // Calculate J(M^-1)(J^T). This term is constant so we can calculate this first for (int i = 0; i < constraint->numContactPoint; i++) { ftContactPointConstraint *pointConstraint = &constraint->pointConstraint; pointConstraint->r1 = manifold->contactPoints.r1 - (bodyA->transform.center + bodyA->centerOfMass); pointConstraint->r2 = manifold->contactPoints.r2 - (bodyB->transform.center + bodyB->centerOfMass); real kNormal = bodyA->inverseMass + bodyB->inverseMass; // Calculate r X normal real rnA = pointConstraint->r1.cross(constraint->normal); real rnB = pointConstraint->r2.cross(constraint->normal); // Calculate J(M^-1)(J^T). kNormal += (bodyA->inverseMoment * rnA * rnA + bodyB->inverseMoment * rnB * rnB); // Save inverse of J(M^-1)(J^T). pointConstraint->normalMass = 1 / kNormal; pointConstraint->positionBias = m_option.baumgarteCoef * manifold->penetrationDepth; ftVector2 vA = bodyA->velocity; ftVector2 vB = bodyB->velocity; real wA = bodyA->angularVelocity; real wB = bodyB->angularVelocity; ftVector2 dv = (vB + pointConstraint->r2.invCross(wB) - vA - pointConstraint->r1.invCross(wA)); //Calculate JV real jnV = dv.dot(constraint->normal pointConstraint->restitutionBias = -restitution * (jnV + m_option.restitutionSlop); } // solve constraint while (numIteration > 0) { for (int i = 0; i < m_constraintGroup.nConstraint; ++i) { ftContactConstraint *constraint = &(m_constraintGroup.constraints); int32 bodyIDA = constraint->bodyIDA; int32 bodyIDB = constraint->bodyIDB; ftVector2 normal = constraint->normal; ftVector2 tangent = normal.tangent(); for (int j = 0; j < constraint->numContactPoint; ++j) { ftContactPointConstraint *pointConstraint = &(constraint->pointConstraint[j]); ftVector2 vA = m_constraintGroup.velocities[bodyIDA]; ftVector2 vB = m_constraintGroup.velocities[bodyIDB]; real wA = m_constraintGroup.angularVelocities[bodyIDA]; real wB = m_constraintGroup.angularVelocities[bodyIDB]; //Calculate JV. (jnV = JV, dv = derivative of d, JV = derivative(d) dot normal)) ftVector2 dv = (vB + pointConstraint->r2.invCross(wB) - vA - pointConstraint->r1.invCross(wA)); real jnV = dv.dot(normal); //Calculate Lambda ( lambda real nLambda = (-jnV + pointConstraint->positionBias / dt + pointConstraint->restitutionBias) * pointConstraint->normalMass; // Add lambda to normalImpulse and clamp real oldAccumI = pointConstraint->nIAcc; pointConstraint->nIAcc += nLambda; if (pointConstraint->nIAcc < 0) { pointConstraint->nIAcc = 0; } // Find real lambda real I = pointConstraint->nIAcc - oldAccumI; // Calculate linear impulse ftVector2 nLinearI = normal * I; // Calculate angular impulse real rnA = pointConstraint->r1.cross(normal); real rnB = pointConstraint->r2.cross(normal); real nAngularIA = rnA * I; real nAngularIB = rnB * I; // Apply linear impulse m_constraintGroup.velocities[bodyIDA] -= constraint->invMassA * nLinearI; m_constraintGroup.velocities[bodyIDB] += constraint->invMassB * nLinearI; // Apply angular impulse m_constraintGroup.angularVelocities[bodyIDA] -= constraint->invMomentA * nAngularIA; m_constraintGroup.angularVelocities[bodyIDB] += constraint->invMomentB * nAngularIB; } } --numIteration; } General Step to Solve Constraint In this article, we have learned how to solve contact penetration by defining it as a constraint and solve it. But this framework is not only used to solve contact penetration. We can do many more cool things with constraints like for example implementing hinge joint, pulley, spring, etc. So this is the step-by-step of constraint resolution: Define the constraint in the form \(\dot{C}: JV + b = 0\). V is always \(\begin{bmatrix} \vec{v1} \\ w1 \\ \vec{v2} \\ w2\end{bmatrix}\) for every constraint. So we need to find J or the Jacobian Matrix for that specific constraint. Decide the number of iteration for the sequential impulse. Next find the Lagrangian multiplier by inserting velocity, mass, and the Jacobian Matrix into this equation: Do step 3 for each constraint, and repeat the process as much as the number of iteration. Clamp the Lagrangian multiplier if needed. This marks the end of this article. Feel free to ask if something is still unclear. And please inform me if there are inaccuracies in my article. Thank you for reading. NB: Box2d use sequential impulse, but does not use baumgarte stabilization anymore. It uses full NGS to resolve the position drift. Chipmunk still use baumgarte stabilization. References Allen Chou's post on Constraint Resolution A Unified Framework for Rigid Body Dynamics An Introduction to Physically Based Modeling: Constrained Dynamics Erin Catto's Box2d and presentation on constraint resolution Falton Debug Visualizer 18_01_2018 22_40_12.mp4 equation.svg
  5. This is a technical article about how I implemented the fluid in my game “Invasion of the Liquid Snatchers!” which was my entry for the fifth annual "Week of Awesome " game development competition here at GameDev.net. One of the biggest compliments I’ve received about the game is when people think the fluid simulation is some kind of soft-body physics or a true fluid simulation. But it isn’t! The simulation is achieved using Box2D doing regular hard-body collisions using lots of little (non-rotating) circle-shaped bodies. The illusion of soft-body particles is achieved in the rendering. The Rendering Process Each particle is drawn using a texture of a white circle that is opaque in the center but fades to fully transparent at the circumference: These are drawn to a RGBA8888 off-screen texture (using a ‘framebuffer’ in OpenGL parlance) and I ‘tint’ to the intended color of the particle (tinting is something that LibGDX can do out-of-the-box with its default shader). It is crucial to draw each ball larger than it is represented in Box2D. Physically speaking these balls will not overlap (because it’s a hard-body simulation after all!) yet in the rendering, we do need these balls to overlap and blend together. The blending is non-trivial as there are a few requirements we have to take into account: - The RGB color channels should blend together when particles of different colors overlap. -- … but we don’t want colors to saturate towards white. -- … and we don’t want them to darken when we blend with the initially black background color. - The alpha channel should accumulate additively to indicate the ‘strength’ of the liquid at each pixel. All of that can be achieved in GLES2.0 using this blending technique: glClearColor(0, 0, 0, 0); glBlendFuncSeparate(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA, GL_ONE, GL_ONE); Putting all that together gets us a texture of lots of blurry colored balls: Next up, is to contribute this to the main backbuffer as a full-screen quad using a custom shader. The shader treats the alpha channel of the texture as a ‘potential field’, the higher the value the stronger the field is at that fragment. The shader compares the strength of the field to a threshold: Where this field strength is strong enough then we will snap the alpha to 1.0 to manifest some liquid. Where the field strength is too weak then we will snap the alpha to 0.0 (or we could just discard the fragment) to avoid drawing anything. For the final game I went a little further and also included a small window around that threshold to smoothly blend between 0 and 1 in the alpha channel, this softens and effectively anti-aliases the fluid boundary. Here’s the shader: varying vec2 v_texCoords; uniform sampler2D u_texture; // field values above this are 'inside' the fluid, otherwise we are 'outside'. const float threshold = 0.6; // +/- this window around the threshold for a smooth transition around the boundary. const float window = 0.1; void main() { vec4 col = texture2D(u_texture, v_texCoords); float fieldStrength = col.a; col.a = smoothstep(threshold - window, threshold + window, fieldStrength); gl_FragColor = col; } This gives us a solid edge boundary where pixels are either lit or not lit by the fluid. Here is the result after we apply the shader: Things are looking a lot more liquid-like now! The way this works is that when particles come within close proximity of each other their potential fields start to add up; once the field strength is high enough the shader will start lighting up pixels between the two particles. This gives us the ‘globbing together’ effect which really makes it look like a fluid. Since the fluid is comprised of thousands of rounded shapes it tends to leave gaps against the straight-edged tilemap. So the full-screen quad is, in fact, scaled-up to be just a little bit larger than the screen and is draw behind the main scene elements. This helps to ensure that the liquid really fills up any corners and crevices. Here is the final result: And that’s all there is for the basic technique behind it! Extra Niceties I do a few other subtle tricks which help to make the fluids feel more believable… Each particle has an age and a current speed. I weight these together into a ‘froth-factor’ value between 0 and 1 that is used to lighten the color of a particle. This means that younger or faster-moving particles are whiter than older or stationary parts of the fluid. The idea is to allow us to see particles mixing into a larger body of fluid. The stationary ‘wells’ where fluid collects are always a slightly darker shade compared to the fluid particles. This guarantees that we can see the particles ‘mixing’ when they drop into the wells. Magma particles are all different shades of dark red selected randomly at spawn time. This started out as a bug where magma and oil particles were being accidentally mixed together but it looked so cool that I decided to make it happen deliberately! When I remove a particle from the simulation it doesn’t just pop out of existence, instead, I fade it away. This gets further disguised by the ‘potential field’ shader which makes it look like the fluid drains or shrinks away more naturally. So, on the whole, the fading is not directly observable. Performance Optimisations As mentioned in my post-mortem of the game I had to dedicate some time to make the simulation CPU and Memory performant: The ‘wells’ that receive the fluid are really just colored rectangles that “fill up”. They are not simulated. It means I can remove particles from the simulation once they are captured by the wells and just increment the fill-level of the well. If particles slow down below a threshold then they are turned into non-moving static bodies. Statics are not exactly very fluid-like but they perform much better in Box2D than thousands of dynamic bodies because they don’t respond to forces. I also trigger their decay at that point too, so they don’t hang around in this state for long enough for the player to notice. All particles will eventually decay. I set a max lifetime of 20-seconds. This is also to prevent the player from just flooding the level and cheating their way through the game. To keep Java’s Garbage Collector from stalling the gameplay I had to avoid doing memory allocations per-particle where possible. Mainly this is for things like allocating temporary Vector2 objects or Color objects. So I factored these out into singular long-lived instances and just (re)set their state per-particle. Note: This article was originally published on the author's blog, and is reproduced here with the author's kind permission.
  6. A Really Useful Box2D Editor You're a game developer. Your next project will have Box2D-powered physics, and it'll be awesome. So you wrestle with installers, build systems, possibly with compiling the library itself, and then get a rectangle moving around on-screen. Now what? If your game is non-trivial, you could have dozens of different types of objects. You're not going to have a good time describing them in code, as you'd have to recompile every time your designer (which could be you) blows his/her nose. You could come up with your own loader, but then you'd have to come up with your own file format, too, and that's time not spent actually making your game! Enter R.U.B.E., the Really Useful Box2D Editor. R.U.B.E. is a level designer for virtually any game that uses the Box2D physics engine. You can use it to visually create a wide variety of collision shapes, place them on-screen, and edit their properties. R.U.B.E. also boasts a comprehensive scripting system, support for nearly all Box2D constructs, and extensive customizability. The Setup I use R.U.B.E. on Ubuntu 14.04 and a reasonably beefy 2011-era Samsung laptop. R.U.B.E. is available for Windows, Mac, and Linux. The Mac version, however, does not officially support 64-bit computers; it might or might not work. Likewise for any Linux distribution other than Ubuntu. When in doubt, see if the trial version works. I'm using R.U.B.E. to develop a top-down shooter written in Java and libGDX. The Editor The user interface for a program like this should aim to minimize the barrier between the designer's ideas and his/her implementation. Fortunately, R.U.B.E.'s editor does a decent enough job of that. The controls for the editor itself are a bit clunky, relying on keyboard shortcuts to perform basic geometric transformations (e.g. pressing S to scale an object, as opposed to just grabbing a handle like in Unity or Inkscape). A bit annoying, but you'll get used to it. Other features, like the ability to position the menus freely, or the ability to copy objects to other programs as plain text, or even to run the Box2D engine to see how objects move in the world, are very much welcome. I don't think you'll be wrestling with the program too much. The Scripting My limited experience with RubeScript, the built-in scripting engine derived from AngelScript, was a pleasant one. The language itself is nothing spectacular, preferring simplicity for programmers and non-programmers alike over flashy features. Better documentation for the built-in types (strings, arrays, etc.) and code completion would've been nice, at least. What really makes RubeScript stand out is its thorough functionality. Almost all of the built-in editor actions--adding or deleting bodies and joints, smoothing or removing vertices--are actually implemented in RubeScript, and can be viewed in R.U.B.E.'s installation. If the developer himself can write the meat of R.U.B.E. in its own scripting system, I'm sure you can get something out of it, too. Tools like this are why game designers benefit from some programming skills. The Competition Minimal. Most available alternatives lack some of R.U.B.E.'s most defining features. These other editors are only designed for creating simple game objects (such as PhysicsEditor, which doesn't support joints), or lack adequate import/export facilities (e.g. BoxCAD, whose output requires ActionScript 3.0 to be used). Other more generic solutions such as Tiled or even Inkscape might suit your needs if you can write a loader to convert their output to Box2D worlds. I don't feel that most of these other alternatives fill the need for a 2D physics world editor, though for very small games you may disagree. The Surrounding Ecosystem I have nothing but good things to say here. The official documentation for R.U.B.E. is excellent. Even if you ignore the built-in manual (which is very detailed and contains plenty of images), there's a wealth of resources available on the official website, including sample projects and video tutorials. But perhaps best of all, Chris Campbell (the developer) actually gives a damn about you. He reads the forum and any e-mail he gets. It's easy to report bugs or offer feedback from within R.U.B.E. itself. I can send a hastily-written bug report or feature request through through R.U.B.E. and continue working before my concentration wavers. You'll actually get a response from Chris within a reasonable time frame, and he'll make sure you get the best out of R.U.B.E. you possibly can. He's helped me numerous times with reporting bugs, feature requests, and even general Box2D questions. The main problem with R.U.B.E., as I see it, is that your game's technologies will be limited to whatever has a R.U.B.E. loader and a Box2D port available. This issue isn't exclusive to R.U.B.E.--it's inherent in any technology that's not as mainstream as, say, PNGs or WAVs. While R.U.B.E. does have loaders available for many popular game frameworks and programming languages, if none of them suit your needs you'll either have to reconsider your toolkit or write your own loader. The Bottom Line A designer alone may not have much use for R.U.B.E., because odds are if he/she is using a prefab game engine like Game Maker or Unity he/she'll be using its respective built-in editor. But for programmers or designers working with programmers, R.U.B.E. is a solid investment. R.U.B.E. is flexible enough to play well with any custom game engine, yet simple enough to make entertaining game worlds with ease. I wholeheartedly recommend taking the $30 plunge.
  7. So, in the previous post I said the main problem about duplicating a box2d world. The worlds differ. Why would you want to duplicate a box2d world? There are several reasons: To replay a cool sequence. To predict the future. To go back in time. To save the current game. To send the current world to another player. How do you solve this? There is a very simple way of going around the box2d issue. Instead of trying to make a copy of the original world, and hope for the best, you make two copies, and then destroy the original. So instead of running the original world and save the copy... You make two copies, run one and save the second one. That way, the second copy will be identical to the first one. So the solution is: everytime you want to save the current world, you are actually destroying it and making two copies. The players will continue to play on copy number #1 (they will not realise the change) and you store copy number 2, in case you ever need to get back to that instant. This is a very simple solution that can be applied to almost every case. My game turned out to be one of those special cases that required dipping into the source code. I'll talk about it in the next post. If you want to know more about my game and why I had to dance around box2d cloning issues: Posable Heroes now has a steam store page.
  8. This week was full work on the AI, which was lacking a bit, to say the least. It is a simple state machine that changes based on the distance to the character (far? jump, close? punch/kick) and its own physical state (falling? stucked? idling? close to edge?). Eventually I managed to make sequence I'm quite proud of: Several silly situations came out of it before I reached that stage: The AI trying hard to punch, only to fall to their death. Finally! It manages to punch me. It's not really hard to terminate the threat. Sometimes it even terminates itself... is the most convoluted way. When your fighting your bro, and a brofist is mandatory. The AI is not prepared to fight flying robots. Ok, that was a decent punch. So it does not get too cocky. If you are interested in Posable Heroes, you can wishlist it on steam.
  9. desdemian

    A new hud

    Lately I've been working on updating the hud. The game is quite colorful (once you press play) so I thought adding a cardboard only hud to make the distinction. Use to look like this: Now it looks like this: Top left is supposed to be the briefing about the current level. Working on localizing those texts. More about posable heroes: Steam Store Page
  10. lawnjelly

    Evaluating Box2D

    I've been using my own internal physics so far for my jungle game, but had been meaning to try out Box2D as I had heard good things. Whether to use third party middleware for physics comes down to a few pros and cons for me: Middleware Mostly written already Tested Written by specialists May require customization to work well for game May have assumptions that don't work with game Internal Deceptively quick to get *something* working, but a lot of special cases to deal with Programming / testing / research time consuming Can be easily tailored to the game In comparison to quite a bit of middleware I've tried, I found Box2D very easy to compile, and then to slot into the game. I was able to have it effectively swapped in and out with a simple #define. Implementation It only took me yesterday to get much of the functionality working, which must be a record for me with middleware. First I added trees and buildings as static fixtures when the map was loaded, circles for trees and boxes for building sections. Then as dynamic actors are added (animals / floating boxes etc) they are added as circles and boxes. Each tick (I use fixed tick rate) I can apply an impulse to the Box2D actors, then read back their positions after stepping the physics. Only the on screen actors are simulated each tick. This was easy to slot in, as my physics basically does the same. Actor Facing What does slightly complicate things is when I try to rotate the actors to face the direction they are travelling. This is quite simple with a circular actor, but with long box shaped actors (especially crocodiles and elephants) they can get 'trapped' trying to rotate between obstacles, and there can be jitter as the actor tries to rotate but the physics blocks it. This is an ongoing problem I am attempting to solve, with e.g. temporal smoothing or perhaps some AI rather than relying on physics. Response Overall I found Box2D worked great for collision detection, but handling the response in the actors may take a bit of fiddling. When a Box2D actor encounters a tree for example, he bounces or slides around it without penetrating. However in my internal engine, I am able to apply a force to push the actor away from the tree in proportion to how close it is to the centre. Although this is not 'realistic' in terms of physics, it gives a better feel to movement, and helps prevent actors getting stuck between obstacles. On the other hand Box2D looks great for the boats, and they have collision points / responses calculated far better than my own. Of course the other snag is that Box2D is 2D, and my game is 3D, having flying objects roofs etc. I am confident I can add in a third dimension, but at this point I am deciding whether it will be worth it, and whether it will be better to stay with the internal physics (except maybe for boats?), and spend the time instead refining the internal physics. Performance I did also incidentally do some crude performance timings, from memory Box2D was taking around 50-500 microseconds for a tick, versus about 10-30 microseconds for internal. This difference was to be expected as the internal is simpler. This was on my PC, the target is low power mobile phone so this will obviously be longer, I haven't timed on mobile, but I'd estimate 5-10x the time, so could possibly cause a dropped frame, although I don't foresee it being as major a bottleneck as rendering.
  11. Refining the tutorial was probably one of the hardest part of the "later development". Everything was in place, but how to teach the player how to play the game was still a struggle. The first time somebody tried my game, he was 15 minutes on level 1 and he couldnt even solved it. So this was a major issue. The game evolved from a "this is a full level, here are the controls, good luck", to "this is a much limited level, lets try the first feature first and will see how we go". The things that helped me: 1. Limiting number of limbs. On the original first level, you controlled all 4 limbs + head of the character. That was brutal for a first timer. Understanding how physic works on the character is not easy. So I changed that to only 1 limb, and the character starts tied up to a chair. You have to limit the degrees of freedom that you offer the players. 2. Explaining the movie, the poses, and how do they work. Although the concept of a timeline is easy to understand now that everybody browses youtube, keyframes and poses needed to be explained. I tried explaining the bare minimum because I don't want to overwhelm the player on the first level. Explaining that a pose is what make the difference in the movie. 3. Slowing down the player Although it may seem weird, sometimes you have to slow down the player so they dont hurt themselves. At first, just standing on some point in the timeline and moving the character would create a pose. Very fast, very simple. Except that it lead to players creating poses everywhere, anywhere. Not realising where they are standing, and not giving importance to the appropiate time. I had to slow them down, asking them to create the pose manually. This simple creation with a button made the player pay attention where the pose was, and at what time was the movement happening. 4. Teaching by doing, not just showing. This is quite straight forward, but players learn a lot more by doing the actions than just reading about them. In this case I showed an animated example of what the player was suppose to do, and waited for the player to do it themselves. 5. Gameplay before story. I'm pretty sure some writers may hate me, but I was willing to destroy the story if that meant a smooth gameplay/learning curve. One of my biggest fights with players was gravity. It was not easy to teach someone to move and jump, beacause... well... most people don't realise "how" they walk, they just walk. And when they have to pass that expertise to a dummy character, they struggle becuase in their mind is just automatic. It's like tryin to teach a kid to tie their shoes. You just do it, and you would have to analise step by step just to make it work. Original first level. Gravity can be a bitch. In my case, the fact that gravity was such a hussle to overcome, I couldn't add it in the first levels where players were just getting the grip of the game. So I moved my story to space, and then to the moon, were gravity is lower. After several level then the player lands on earth and the gravity challenge appears. Does it make 100% sense as a story now? No. I tried to fit the changes in to the story, but the realism of the story is a little stretched out now. I'm not gonna win any writing prize for it. But I haven't received any of the complaints and struggles I use to see from new players. After refining the tutorial several times, I haven't received a single complain about no understanding the game. Some people still don't like it, that acceptable, but at least now everyone gets to evaluate the game other than "too confusing". I hope my mistakes help you out a bit in your tutorial. Cheers. If you want to know more about the game: Posable Heroes on Steam
  12. behc

    Proof of Concept

    Greetings everyone! I finally managed to put together complete system that will be used as a backbone of my new game. The game itself is supposed to be a mix of Kerbal Space Program and Space Engineers in 2d, maybe with some added influences from other games. I'll get back to this later, when gameplay is more fleshed out. Right now what the game needs is: orbital physics of planetary system, large deformable terrains with rigid body simulation and transitions between those two. tl;dr; There is a video. Orbital physics This part was relatively easy. I choose simulated n-body system over fixed orbits with patched conic approximation. It's simple to write and supports all phenomena like Lagrange points. My system uses Verlet integration with fixed time step (64s) for planets and adaptive time step for small entities (artificial satellites, asteroids). The only drawback here is that plotting trajectories requires to know positions of all planets ahead of time, so it's best to evaluate whole system many steps to the future and just playback current position from history. (You can see these in video when debug drawing is enabled) Planetary physics I modeled planet's surface as linear space located around planet radius, with wrapping around when traveling sideways. Since I want my planets big (not real live big, not even KSP big, but still), each one is split into spaces that span around 4km. Those spaces are all linear and centered around origin. Rigid bodies can move from one to another, can have joints across spaces, but will never collide or interact in any way. Of course the problem is when some body wants to leave one space and enter another. We could simply teleport whole rigid body, but it would miss some collisions. My solution is to clone whole body at new location and link them with teleport joint. It's similar to fixed joint, but maintains relative offset. (don't forget to split mass in half between two bodies) In order for this to work, you need two bounding rectangles: tight and fat. When tight intersects space boundary clone body (2). Destroy cloned body only if fat stops intersecting boundary (4). For all this to work I made some changes to Box2D library, you can find my fork on github. Stitching it together Moving from planet surface space to orbital space is using simple teleportation with conversion from local space coordinates to global orbital one. I sill have some quirks to iron out, but hey, you can fly to the moon!