Giter VIP home page Giter VIP logo

agsbox2d's People

Contributors

ericoporto avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

agsbox2d's Issues

Add built-in keyword where it makes sense

"builtin" means that user cannot create instances of that type in script using new.

Lot's of things in this plug-in are produced by the AgsBox2D factory and itself too needs this keyword added.

Add license notice on top of source files

Just add a reminder of the license used similar to:

/*
 * Copyright (C) <Year>  <Name of Author>
 *
 * This program is free software. You can use and redistribute it
 *  under the terms and conditions of the zlib-license (see LICENCE).
 *
 * SPDX-License-Identifier: Zlib
 */

Add readonly IDs for fixtures and bodies

Need both b2fixture ID as in AGS Script FixtureID and b2body ID as in AGS Script ID - so they would not reflect their wrappers IDs, but the IDs of the Box2D elements they represent and give interface too. Theoretically, it should exist only one wrapper element ( AgsBody, AgsFixture) for one Box2D element (b2Body, b2Fixture), but I need IDs to test if this proceeds.

Some #endif statements could use clarification through comments

Especially when displaying huge chunks of code on tiny monitors #endif statements could
use some sort of comment stating what they end.

The only file that doesn't seem to come directly from Box2D (which apparently doesn't have any comments after #endif statements) that is affected by this issue is agsbox2d.cpp

A basic example taken from agsbox2d.cpp
#if AGS_PLATFORM_OS_WINDOWS

//==============================================================================

// ***** Design time *****

IAGSEditor *editor; // Editor interface

const char *ourScriptHeader =
"  \r\n"
"enum BodyType { \r\n"
"  eBodyStatic=0, \r\n"
"  eBodyKinematic=1, \r\n"
"  eBodyDynamic=2, \r\n"
"}; \r\n"
" \r\n"
"managed struct Body { \r\n"
"  import attribute float fX; \r\n"
"  import attribute float fY; \r\n"
"  import attribute int X; \r\n"
"  import attribute int Y; \r\n"
"  import attribute bool FixedRotation; \r\n"
"  import attribute bool Bullet; \r\n"
"  readonly import attribute bool IsDestroyed; \r\n"
"  import attribute float Angle; \r\n"
"  import attribute float LinearDamping; \r\n"
"  import attribute float AngularDamping; \r\n"
"  import attribute float AngularVelocity; \r\n"
"  import attribute float Inertia; \r\n"
"  readonly import attribute float LinearVelocityX; \r\n"
"  readonly import attribute float LinearVelocityY; \r\n"
"  import void ApplyForce(float fx, float fy); \r\n"
"  import void SetLinearVelocity(float fx, float fy); \r\n"
"  import void ApplyAngularImpulse(float impulse); \r\n"
"  import void ApplyLinearImpulse(float intensity_x, float intensity_y); \r\n"
"  import void ApplyTorque(float torque); \r\n"
"  import bool IsTouching(Body* other); \r\n"
"}; \r\n"
" \r\n"
"managed struct World { \r\n"
"  \r\n"
"  /// Advances one step of the simulation \r\n"
"  import void Step(float dt, int velocityIteractions = 8, int positionIteractions = 3); \r\n"
"}; \r\n"
" \r\n"
"managed struct ShapeCircle; \r\n"
"managed struct ShapeRectangle; \r\n"
" \r\n"
"managed struct Shape { \r\n"
"  \r\n"
"  /// If this shape is a circle, returns the ShapeCircle interface; otherwise null. \r\n"
"  readonly import attribute ShapeCircle* AsCircle;  // $AUTOCOMPLETENOINHERIT$  \r\n"
"  \r\n"
"  /// If this shape is a rectangle, returns the ShapeRectangle interface; otherwise null. \r\n"
"  readonly import attribute ShapeRectangle* AsRectangle;  // $AUTOCOMPLETENOINHERIT$  \r\n"
"}; \r\n"
" \r\n"
"managed struct ShapeCircle extends Shape { \r\n"
"  \r\n"
"}; \r\n"
" \r\n"
"managed struct ShapeRectangle extends Shape { \r\n"
"  \r\n"
"  import attribute float fWidth; \r\n"
"  import attribute float fHeight; \r\n"
"  import attribute int Height; \r\n"
"  import attribute int Width; \r\n"
"  readonly import attribute float PointsfX[]; \r\n"
"  readonly import attribute float PointsfY[]; \r\n"
"  \r\n"
"}; \r\n"
" \r\n"
"managed struct Fixture { \r\n"
"  import attribute float Friction; \r\n"
"  import attribute float Density; \r\n"
"  import attribute float Restitution; \r\n"
"  \r\n"
"}; \r\n"
" \r\n"
"struct AgsBox2D { \r\n"
"  \r\n"
"  /// Set Meter \r\n"
"  import static void SetMeter(float meter); \r\n"
"  \r\n"
"  /// Get Meter \r\n"
"  import static float GetMeter(); \r\n"
"  \r\n"
"  /// Create World \r\n"
"  import static World* CreateWorld(float gravityX, float gravityY); \r\n"
"  \r\n"
"  /// Create Body \r\n"
"  import static Body* CreateBody(World* world,  float x, float y, BodyType bodytype); \r\n"
"  /// Destroy Body \r\n"
"  import static void DestroyBody(World* world, Body* body);  \r\n"
"  \r\n"
"  /// Create Rectangle Shape \r\n"
"  import static Shape* CreateRectangleShape(float w,  float h,  float x=0, float y=0); \r\n"
"  \r\n"
"  /// Create Circle Shape \r\n"
"  import static Shape* CreateCircleShape(float radius,  float x=0, float y=0); \r\n"
"  \r\n"
"  /// Create Fixture \r\n"
"  import static Fixture* CreateFixture(Body* body, Shape* shape, float density=0); \r\n"
"  \r\n"
"}; \r\n";


//------------------------------------------------------------------------------

LPCSTR AGS_GetPluginName()
{
        return ("agsbox2d");
}

//------------------------------------------------------------------------------

int AGS_EditorStartup(IAGSEditor *lpEditor)
{
        // User has checked the plugin to use it in their game

        // If it's an earlier version than what we need, abort.
        if (lpEditor->version < MIN_EDITOR_VERSION)
                return (-1);

        editor = lpEditor;
        editor->RegisterScriptHeader(ourScriptHeader);

        // Return 0 to indicate success
        return (0);
}

//------------------------------------------------------------------------------

void AGS_EditorShutdown()
{
        // User has un-checked the plugin from their game
        editor->UnregisterScriptHeader(ourScriptHeader);
}

//------------------------------------------------------------------------------

void AGS_EditorProperties(HWND parent)                        //*** optional ***
{
        // User has chosen to view the Properties of the plugin
        // We could load up an options dialog or something here instead
/*	MessageBox(parent,
             L"agsfastwfc v1.0 By Calin Leafshade",
             L"About",
         MB_OK | MB_ICONINFORMATION);
 */
}

//------------------------------------------------------------------------------

int AGS_EditorSaveGame(char *buffer, int bufsize)             //*** optional ***
{
        // Called by the editor when the current game is saved to disk.
        // Plugin configuration can be stored in [buffer] (max [bufsize] bytes)
        // Return the amount of bytes written in the buffer
        return (0);
}

//------------------------------------------------------------------------------

void AGS_EditorLoadGame(char *buffer, int bufsize)            //*** optional ***
{
        // Called by the editor when a game is loaded from disk
        // Previous written data can be read from [buffer] (size [bufsize]).
        // Make a copy of the data, the buffer is freed after this function call.
}

//==============================================================================

#endif

Even though, Box2D.h etc. seem to be taken directly (or with some slight modifications) from Box2D I'd consider adding some comments. However, it certainly wouldn't make sense to "fix" a library that's updated frequently (nor would I want to update a 7000 lines file ๐Ÿ‘… ).

Figure out how to adapt contact filters

My first guess is a contact stack that is read only and changes at each time step

I would also like to add some way to filter contacts with a fixture from this stack. And also, some way to pass an array of fixtures to ignore (which the contacts involving them aren't put on the array on first place).

Still, the callbacks approach is more interesting, but I am not sure how well it would work in AGS. Maybe need to branch and test this.

Hack to pass int as floats and vice versa

ags stores everything as ints, so if you just pass float to function, it will be converted to int loosing its float quality.
Like if you pass 1.5 it will become 1

so instead you must cheat to make receiving function think that this is integer.

something like:

union
{
    float f;
    uint32_t ui32;
} hack;

hack.f = 123.456;

CallEngine(hack.ui32);

here union is 4 bytes, and it can be seen as both float and uint32. So you can assign it as float and pass as integer, and all data will stay as it is necessary for float.

internally engine does opposite conversion.

Add isSleeping property

Checking if a fixture/body is asleep may be useful when selecting what I should move/update animation state, in a more complex/larger world.

What's implemented and what isn't from desired Box2D API

AgsBox2D : similar to love.physics

  • AgsBox2D.SetMeter;
  • AgsBox2D.GetMeter;
  • AgsBox2D.CreateWorld;
  • AgsBox2D.CreateBody;
  • AgsBox2D.DestroyBody;
  • AgsBox2D.CreateFixture;
  • AgsBox2D.CreateShapeRectangle;
  • AgsBox2D.CreateShapeCircle;
  • AgsBox2D.GetDistance(fixture1, fixture2);
  • AgsBox2D.CreatePolygonShape
  • AgsBox2D.CreateEdgeShape
  • AgsBox2D.CreateChainShape
  • AgsBox2D.CreateDistanceJoint
  • AgsBox2D.CreateFrictionJoint
  • AgsBox2D.CreateGearJoint
  • AgsBox2D.CreateMotorJoint
  • AgsBox2D.CreateMouseJoint
  • AgsBox2D.CreatePrismaticJoint
  • AgsBox2D.CreatePulleyJoint
  • AgsBox2D.CreateRevoluteJoint
  • AgsBox2D.CreateRopeJoint
  • AgsBox2D.CreateWeldJoint
  • AgsBox2D.CreateWheelJoint

Body : similar to body from love

  • Body.fX
  • Body.fY
  • Body.X
  • Body.Y
  • Body.Angle
  • Body.FixedRotation
  • Body.LinearVelocityX
  • Body.LinearVelocityY
  • Body.LinearDamping
  • Body.ApplyForce(float fx, float fy)
  • Body.SetLinearVelocity(float fx, float fy)
  • Body.ApplyAngularImpulse(float impulse)
  • Body.ApplyLinearImpulse(float fx, float fy)
  • Body.ApplyTorque(float torque)
  • Body.AngularDamping
  • Body.AngularVelocity
  • Body.Inertia
  • Body.Bullet
  • Body.IsTouching(Body* body)

World - similar to world from love

  • World.Step()
  • World.BoundingBoxQuey()
  • World.Raycast()

Shape

  • Shape.AsRectangle
  • Shape.AsCircle

Fixture : similar to fixture from love

  • Fixture.Body
  • Fixture.Shape
  • Fixture.Density
  • Fixture.Friction
  • Fixture.Restitution
  • Fixture.GetBoundingBox

Implement serialization and deserialization

First, objects need to have IDs

To serialize objects they need to store their IDs and the IDs of any objects they point too: Bodies, their world ID; Fixtures, the IDs things the fixtures contains; And so on.

These IDs will be used for deserialization, since we can't store pointers because the memory will be different.

When an object is deserialized, it needs to check if it's own ID is on it's respective table pointer. If it isn't, we instantiate that object with the received parameters from deserialization process. If it's, we instead skip instantiation, and apply the parameters on the already instantiated object.

So when deserializing an object that points to other object, we get the ID of the object it points to (and we know the type of that ID). We check a table that has IDs as keys and the respective pointer as value. If that ID is found, we get the pointer and place in the right place. If that ID is not found, we initialize the object with default parameters anyway and place it on the table with the ID.

Properly disposal of pointers

For now, when the pointer of a Box2D thing goes out of scope, things can break. Specifically, the world should never go out of scope or the things it contains will go kaboom. Instead we need to properly invalidate all the pointers - passing null to previously contained AgsBody objects.

Connect AGS Object to Box2D World

Provide some way to easily get a Room Object manipulated by a world. This is possible now through AGS Script but if some way to easen this can be created it would be useful.

Potentially it would allow specifying a margin with an eInnerMarging specifier of inner margin or eOuterMargin. Not sure yet if outer margin would actually be useful. But it would be useful passing an innermarging, I assume also objects are created as rectangle boxes by default. Maybe adding an option to be a circle too.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.