3d ball not bouncing on palette

23 views Asked by At

This is a pong-like game but in 3d, so there is wide ground, two player palettes and a ball which start from the center going through the player1 palette.

I'm trying to make the ball bounce in the opposite direction when it collide with the palette, but instead, it reaches the palette and then go away only for a very little space and slowly.

GameScreen.java:

import static app.my3dgame.Constants.*;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.Net;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.VertexAttributes;
import com.badlogic.gdx.graphics.g3d.Environment;
import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.graphics.g3d.ModelBatch;
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
import com.badlogic.gdx.graphics.g3d.utils.CameraInputController;
import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.bullet.Bullet;
import com.badlogic.gdx.physics.bullet.collision.Collision;
import com.badlogic.gdx.physics.bullet.collision.ContactListener;
import com.badlogic.gdx.physics.bullet.collision.btBoxShape;
import com.badlogic.gdx.physics.bullet.collision.btBroadphaseInterface;
import com.badlogic.gdx.physics.bullet.collision.btCapsuleShape;
import com.badlogic.gdx.physics.bullet.collision.btCollisionConfiguration;
import com.badlogic.gdx.physics.bullet.collision.btCollisionDispatcher;
import com.badlogic.gdx.physics.bullet.collision.btCollisionObject;
import com.badlogic.gdx.physics.bullet.collision.btConeShape;
import com.badlogic.gdx.physics.bullet.collision.btCylinderShape;
import com.badlogic.gdx.physics.bullet.collision.btDbvtBroadphase;
import com.badlogic.gdx.physics.bullet.collision.btDefaultCollisionConfiguration;
import com.badlogic.gdx.physics.bullet.collision.btDispatcher;
import com.badlogic.gdx.physics.bullet.collision.btSphereShape;
import com.badlogic.gdx.physics.bullet.dynamics.btConstraintSolver;
import com.badlogic.gdx.physics.bullet.dynamics.btDiscreteDynamicsWorld;
import com.badlogic.gdx.physics.bullet.dynamics.btDynamicsWorld;
import com.badlogic.gdx.physics.bullet.dynamics.btSequentialImpulseConstraintSolver;
import com.badlogic.gdx.physics.bullet.linearmath.btMotionState;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Dialog;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ArrayMap;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.ScreenViewport;

import app.my3dgame.BulletDebugDrawer;
import app.my3dgame.GameObject;
import app.my3dgame.MyGame;
public class GameScreen implements Screen, InputProcessor {
    MyGame game;
    
    PerspectiveCamera cam;
    CameraInputController camController;
    ModelBatch modelBatch;
    Environment environment;
    Model model;
    Array<GameObject> instances;
    ArrayMap<String, GameObject.Constructor> constructors;
    float spawnTimer;

    btCollisionConfiguration collisionConfig;
    btDispatcher dispatcher;
    MyContactListener contactListener;
    btBroadphaseInterface broadphase;
    btDynamicsWorld dynamicsWorld;
    btConstraintSolver constraintSolver;

    GameObject objectPaletta;
    GameObject objectPallina;
    GameObject objectPalettaAvversario;
    GameObject objectBall;

    float angle, speed = 90f;

    BulletDebugDrawer bulletDebugDrawer;

    public GameScreen(final MyGame game, boolean _partitaControIlComputer) {

        this.game = game;

        Bullet.init();
    }

    
    private void init() {
        modelBatch = new ModelBatch();
        environment = new Environment();
        
        environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f)); 
        environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f)); 

        cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

        
        cam.position.set(0f, 40f, 0f); 
        cam.lookAt(0, 0, 0); 
        
        cam.position.set(G1_VIEW_POSITION.x, G1_VIEW_POSITION.y, G1_VIEW_POSITION.z); 
        cam.lookAt(G1_VIEW_LOOK_AT.x, G1_VIEW_LOOK_AT.y, G1_VIEW_LOOK_AT.z); 

        cam.near = 1f;
        cam.far = 300f; 
        cam.update();

        camController = new CameraInputController(cam);
        
        
        initModels();

        bulletDebugDrawer = new BulletDebugDrawer(modelBatch, cam);
    }
    private void initModels() {
        ModelBuilder mb = new ModelBuilder();
        mb.begin();
        mb.node().id = "ground";
        mb.part("ground", GL20.GL_TRIANGLES, VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.RED))).box(5f, 1f, 5f);
        mb.node().id = "sphere";
        mb.part("sphere", GL20.GL_TRIANGLES, VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.GREEN))).sphere(1f, 1f, 1f, 10, 10);
        mb.node().id = "box";
        mb.part("box", GL20.GL_TRIANGLES, VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.BLUE))).box(1f, 1f, 1f);
        mb.node().id = "cone";
        mb.part("cone", GL20.GL_TRIANGLES, VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.YELLOW))).cone(1f, 2f, 1f, 10);
        mb.node().id = "capsule";
        mb.part("capsule", GL20.GL_TRIANGLES, VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.CYAN))).capsule(0.5f, 2f, 10);
        mb.node().id = "cylinder";
        mb.part("cylinder", GL20.GL_TRIANGLES, VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.MAGENTA))).cylinder(1f, 2f, 1f, 10);

        mb.node().id = "playingfield";
        mb.part("playingfield", GL20.GL_TRIANGLES, VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.RED))).box(PLAYING_FIELD_WIDTH, PLAYING_FIELD_HEIGHT, PLAYING_FIELD_DEPT);
        mb.node().id = "paletta";
        mb.part("paletta", GL20.GL_TRIANGLES, VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.CYAN)))
            .capsule(0.5f, 5f, 10);

        model = mb.end();
    }

    @Override
    public void show() {

        init(); 

        constructors = new ArrayMap<String, GameObject.Constructor>(String.class, GameObject.Constructor.class);
        constructors.put("ground", new GameObject.Constructor(model, "ground", new btBoxShape(new Vector3(2.5f, 0.5f, 2.5f)), 0f));
        constructors.put("sphere", new GameObject.Constructor(model, "sphere", new btSphereShape(0.5f), 1f));
        constructors.put("box", new GameObject.Constructor(model, "box", new btBoxShape(new Vector3(0.5f, 0.5f, 0.5f)), 1f));
        constructors.put("cone", new GameObject.Constructor(model, "cone", new btConeShape(0.5f, 2f), 1f));
        constructors.put("capsule", new GameObject.Constructor(model, "capsule", new btCapsuleShape(.5f, 1f), 1f));
        constructors.put("cylinder", new GameObject.Constructor(model, "cylinder", new btCylinderShape(new Vector3(.5f, 1f, .5f)), 1f));

        constructors.put("playingfield", new GameObject.Constructor(model, "playingfield", new btBoxShape(new Vector3(PLAYING_FIELD_WIDTH/2, PLAYING_FIELD_HEIGHT/2, PLAYING_FIELD_DEPT/2)), 0f));
        constructors.put("paletta", new GameObject.Constructor(model, "paletta", new btBoxShape(new Vector3(0.5f, 0.5f, 0.5f)), 1f));

        constructors.put("ball", new GameObject.Constructor(model, "sphere", new btSphereShape(0.5f), 3f));

        collisionConfig = new btDefaultCollisionConfiguration();
        dispatcher = new btCollisionDispatcher(collisionConfig);
        broadphase = new btDbvtBroadphase();
        constraintSolver = new btSequentialImpulseConstraintSolver();
        dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, constraintSolver, collisionConfig);
        dynamicsWorld.setGravity(new Vector3(0, -10f, 0));
        contactListener = new MyContactListener();

        instances = new Array<GameObject>();
        
        createPlayingField();
        createG1Palette();
        createBall();
        moveBall();
        createG2Palette();
    }

    void createPlayingField() {
        GameObject object = constructors.get("playingfield").construct("playingfield");
        object.body.setCollisionFlags(object.body.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_KINEMATIC_OBJECT);
        object.transform.trn(PLAYING_FIELD_POSITION.x, PLAYING_FIELD_POSITION.y, PLAYING_FIELD_POSITION.z); 
        object.body.setUserValue(instances.size);
        instances.add(object);
        dynamicsWorld.addRigidBody(object.body);
        object.body.setContactCallbackFlag(GROUND_FLAG);
        object.body.setContactCallbackFilter(0);
        object.body.setActivationState(Collision.DISABLE_DEACTIVATION);
    }

    void createG1Palette() {
        objectPaletta = constructors.get("paletta").construct("paletta");
        objectPaletta.body.setCollisionFlags(objectPaletta.body.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_KINEMATIC_OBJECT);
        objectPaletta.body.setMassProps(10.0f, new Vector3(1, 1, 1));
        objectPaletta.transform.rotate(0, 0, 1, 90); 
        objectPaletta.transform.trn(G1_PALETTE_POSITION.x, G1_PALETTE_POSITION.y, G1_PALETTE_POSITION.z);
        objectPaletta.body.setUserValue(instances.size);
        instances.add(objectPaletta);
        dynamicsWorld.addRigidBody(objectPaletta.body);
        objectPaletta.body.setContactCallbackFlag(GROUND_FLAG);
        objectPaletta.body.setContactCallbackFilter(0);
        objectPaletta.body.setActivationState(Collision.DISABLE_DEACTIVATION);
    }
    void createBall() {
        
        objectBall = constructors.get("ball").construct("ball");
        
        objectBall.transform.setFromEulerAngles(MathUtils.random(360f), MathUtils.random(360f), MathUtils.random(360f));
        objectBall.transform.trn(BALL_POSITION.x, BALL_POSITION.y, BALL_POSITION.z);
        objectBall.body.proceedToTransform(objectBall.transform);
        objectBall.body.setRestitution(100.0f);
        objectBall.body.setFriction(0.0f);
        objectBall.body.setMassProps(1.0f, new Vector3(1, 1, 1));
        objectBall.body.setDamping(0.0f, 0.0f); 
        objectBall.body.setWorldTransform(objectBall.transform);
        objectBall.body.setCollisionFlags(objectBall.body.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
        objectBall.body.setUserValue(instances.size);
        instances.add(objectBall);
        
        objectBall.body.setContactCallbackFlag(OBJECT_FLAG);
        objectBall.body.setContactCallbackFilter(GROUND_FLAG);
        dynamicsWorld.addRigidBody(objectBall.body);
    }
    void moveBall() {
        objectBall.body.applyCentralImpulse(new Vector3(0, 0, 50));
    }
    void createG2Palette() {
        objectPalettaAvversario = constructors.get("paletta").construct("paletta");
        objectPalettaAvversario.body.setCollisionFlags(objectPalettaAvversario.body.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_KINEMATIC_OBJECT);
        objectPalettaAvversario.transform.rotate(0, 0, 1, 90); 
        objectPalettaAvversario.transform.trn(G2_PALETTE_POSITION.x, G2_PALETTE_POSITION.y, G2_PALETTE_POSITION.z); 
        objectPalettaAvversario.body.setUserValue(instances.size);
        instances.add(objectPalettaAvversario);
        dynamicsWorld.addRigidBody(objectPalettaAvversario.body);
        objectPalettaAvversario.body.setContactCallbackFlag(GROUND_FLAG);
        objectPalettaAvversario.body.setContactCallbackFilter(0);
        objectPalettaAvversario.body.setActivationState(Collision.DISABLE_DEACTIVATION);
    }
    public void spawn () {
        GameObject obj = constructors.values[1 + MathUtils.random(constructors.size - 2)].construct("random obj");
        obj.transform.setFromEulerAngles(MathUtils.random(360f), MathUtils.random(360f), MathUtils.random(360f)); 
        obj.transform.trn(MathUtils.random(-2.5f, 2.5f), 9f, MathUtils.random(-2.5f, 2.5f)); 
        obj.body.proceedToTransform(obj.transform);
        obj.body.setCollisionFlags(obj.body.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
        obj.body.setUserValue(instances.size); 
        instances.add(obj);
        dynamicsWorld.addRigidBody(obj.body);
        obj.body.setContactCallbackFlag(OBJECT_FLAG);
        obj.body.setContactCallbackFilter(GROUND_FLAG);
    }

    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(0.3f, 0.3f, 0.3f, 1.f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);


        final float myDelta = Math.min(1f / 30f, Gdx.graphics.getDeltaTime());
        
        dynamicsWorld.stepSimulation(myDelta, 5, 1f / 60f);

        camController.update();
        
        modelBatch.begin(cam);
        modelBatch.render(instances, environment);
        modelBatch.end();
    }
    
    @Override
    public void resize(int width, int height) {

        stageTuttoSchermo.getViewport().update(width, height, true);

        camStage.position.set(0, 0, 10);
        camStage.lookAt(0, 0, 0);

        camStage.update();

        stage.getViewport().update(width, height, true);
    }


    class MyContactListener extends ContactListener {
        @Override
        public boolean onContactAdded (int userValue0, int partId0, int index0, boolean match0, int userValue1, int partId1, int index1, boolean match1) {
            GameObject gameObject0 = instances.get(userValue0);
            GameObject gameObject1 = instances.get(userValue1);

            ((ColorAttribute) gameObject0.materials.get(0).get(ColorAttribute.Diffuse)).color.set(Color.WHITE);
            
            ((ColorAttribute) gameObject1.materials.get(0).get(ColorAttribute.Diffuse)).color.set(Color.WHITE);
            

            if((gameObject0.name.equals("paletta") && gameObject1.name.equals("ball")) || (gameObject1.name.equals("paletta") && gameObject0.name.equals("ball"))) {
                (gameObject0.name.equals("paletta") ? gameObject0 : gameObject1).body.setLinearVelocity(new Vector3(0, 20f, 0f));
            }

            return true;
        }
    }

    
    public static class MyMotionState extends btMotionState {
        public Matrix4 transform;

        @Override
        public void getWorldTransform (Matrix4 worldTrans) {
            worldTrans.set(transform);
        }

        @Override
        public void setWorldTransform (Matrix4 worldTrans) {
            transform.set(worldTrans);
        }
    }
}

GameObject.java:

import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.graphics.g3d.ModelInstance;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.bullet.collision.btCollisionShape;
import com.badlogic.gdx.physics.bullet.dynamics.btRigidBody;
import com.badlogic.gdx.utils.Disposable;

import app.my3dgame.screens.GameScreen;

public class GameObject extends ModelInstance implements Disposable {
    public final btRigidBody body;
    public final GameScreen.MyMotionState motionState;
    public final String name;

    public GameObject (Model model, String node, btRigidBody.btRigidBodyConstructionInfo constructionInfo, String name) {
        super(model, node);
        motionState = new GameScreen.MyMotionState();
        motionState.transform = transform;
        body = new btRigidBody(constructionInfo);
        body.setMotionState(motionState);
        this.name = name;
    }

    @Override
    public void dispose () {
        body.dispose();
        motionState.dispose();
    }

    public static class Constructor implements Disposable {
        public final Model model;
        public final String node;
        public final btCollisionShape shape;
        public final btRigidBody.btRigidBodyConstructionInfo constructionInfo;
        private static Vector3 localInertia = new Vector3();

        public Constructor (Model model, String node, btCollisionShape shape, float mass) {
            this.model = model;
            this.node = node;
            this.shape = shape;
            if (mass > 0f)
                shape.calculateLocalInertia(mass, localInertia);
            else
                localInertia.set(0, 0, 0);
            this.constructionInfo = new btRigidBody.btRigidBodyConstructionInfo(mass, null, shape, localInertia);
        }

        public GameObject construct (String name) {
            return new GameObject(model, node, constructionInfo, name);
        }

        @Override
        public void dispose () {
            shape.dispose();
            constructionInfo.dispose();
        }
    }
}

Constants.java:

import com.badlogic.gdx.math.Vector3;

public class Constants {
    public final static float MINIMUM_VIEWPORT_SIZE = 10f;
    public final static float MINIMUM_VIEWPORT_SIZE_PIXEL = 800f;

    public final static short GROUND_FLAG = 1 << 8;


    public final static short OBJECT_FLAG = 1 << 9;

    public final static short ALL_FLAG = -1;

    public final static float PLAYING_FIELD_WIDTH = 50f;
    public final static float PLAYING_FIELD_HEIGHT = 1f;
    public final static float PLAYING_FIELD_DEPT = 80f;
    public final static Vector3 PLAYING_FIELD_POSITION = new Vector3(0, 0, 0);

    public final static Vector3 G1_VIEW_POSITION = new Vector3(0, 30, 45);
    public final static Vector3 G1_VIEW_LOOK_AT = new Vector3(0, 0, PLAYING_FIELD_DEPT/4f);

    public final static Vector3 G1_PALETTE_POSITION = new Vector3(0, PLAYING_FIELD_HEIGHT, (PLAYING_FIELD_DEPT/2-5));
    public final static Vector3 G2_PALETTE_POSITION = new Vector3(0, PLAYING_FIELD_HEIGHT, -(PLAYING_FIELD_DEPT/2-5));

    public final static Vector3 BALL_POSITION = new Vector3(0, PLAYING_FIELD_HEIGHT, 0);
}

Do you have any suggestion to make it works?

Thanks

0

There are 0 answers