Simple Collision - non Box2D

Any community contributions to libgdx go here! Some may get included in the core API when permission is granted.

Simple Collision - non Box2D

Postby Bastionpayne » Fri Aug 19, 2011 7:04 pm

These are zips of classes i use in my game, I have a bug, and I'm stuck. It's a logical bug. Since I hacked this simple engine for libgdx, I think I'm missing something after porting to use with Actors and the stage. When on android phone my character jitters up and down. I figure if someone else uses the engine and hacks something real quick they will see hat the logical issue, or maybe it works great and makes me feel good lol.

Anywho, inside ActorClasses.zip there's (extending from Actor), BasicActor - > AnimatedActor -> AdvanceActor, and ActiveGroup ( which is the same as the scene group just adding methods getting the x value of the first actor in group and last actor in group, and a boolean whether the group is active or not active)

Inside the collision.zip, there's CollisionDistributor -> BasicCollisionGroup ->CollisionGroup ->PreciseCollisionGroup->AdvanceCollisionGroup as well as CollisionRect, CollisionObject, CollisionLine and CollisionBounds

An example of extending CollisionGroup from my own code.

Code: Select all
package org.mantragames.shooter.collision;

import org.mantragames.collision.CollisionGroup;
import org.mantragames.collision.CollisionRect;
import org.mantragames.gameobject.BasicActor;
import org.mantragames.shooter.player.Player;

public class PlayerGroundCollision  extends CollisionGroup{

   @Override
    public CollisionRect getCollisionShape1(BasicActor s1) {
        // collision offset, cut 6 pixels at each side
      
        rect1.setBounds(s1.x,s1.y,
                s1.getWidth(), s1.getHeight());
       
         //System.out.println(rect1.toString());
        return rect1;
    }
   
   @Override
   public CollisionRect getCollisionShape2(BasicActor s2){
      
         
      rect2.setBounds(s2.x, s2.y,
                s2.getWidth(), s2.getHeight()-15);
      
      
      return rect2;
      
   }


   

   
   @Override
   public void collided(BasicActor s1, BasicActor s2){
      //System.out.println(s1.name+" PlayerToGround - CollisionRect "+rect1.x+","+rect1.y+"["+rect1.width+":"+rect1.height+"]");
      //System.out.println("aSensor - "+this.aSENSOR+" bSensor - "+this.bSENSOR);
      //this.revertPosition1();
    if(collisionSide == BOTTOM_TOP_COLLISION){
      
      
       if(s1.getVerticalSpeed() < 0){
            s1.setY(rect2.y + rect2.height + 0.01f);
            ((Player) s1).setJumping(false);   
            ((Player) s1).setOnGround(true);
         }
         else{
            if(!((Player) s1).isJumping()){
            s1.setY(rect2.y + rect2.height + 0.01f);
            s1.setVerticalSpeed(0);
            }
         }

         
    }
   
   
      
   
      
         if(collisionSide == LEFT_RIGHT_COLLISION){
            
            //s1.setVerticalSpeed(0);
            //s1.setHorizontalSpeed(0);
            
         }
          if(collisionSide == RIGHT_LEFT_COLLISION){
            
            //s1.setVerticalSpeed(0);
            //s1.setHorizontalSpeed(0);
            
         }
         
      
   /*
      if(collisionSide == LEFT_RIGHT_COLLISION){
         if(GameScreen2.direction == GameScreen2.Direction.right){
            if(!((Player) s1).isOnGround()){
                    if(((Thumbpad)Gdx.input.getInputProcessor()).LEFTdown() || Gdx.input.isKeyPressed(Keys.A) ){
                          s1.addVerticalSpeed(((Player) s1).getElapsedTime(), -0.004f, -0.05f);
                          ((Player) s1).setJumping(false);
                     }
                    
                    if(((Thumbpad)Gdx.input.getInputProcessor()).B1pressed()){
                         s1.setVerticalSpeed(0);
                        // s1.addVerticalSpeed(((Player) s1).getElapsedTime(), 0.004f, 3);
                         s1.moveX(50);
                         s1.moveY(80);
                         ((Player) s1).setJumping(true);
                     }
                    
            }
            
         }else{
            
         }
            
             
      }
      
      
      if(collisionSide == RIGHT_LEFT_COLLISION){
         if(GameScreen2.direction == GameScreen2.Direction.left){
                 if(((Thumbpad)Gdx.input.getInputProcessor()).LEFTdown() || Gdx.input.isKeyPressed(Keys.A) ){
                       s1.addVerticalSpeed(((Player) s1).getElapsedTime(), -0.004f, -0.05f);
                       ((Player) s1).setJumping(false);
                  }
                 
                 if(((Thumbpad)Gdx.input.getInputProcessor()).B1pressed()){
                      s1.setVerticalSpeed(0);
                      s1.addVerticalSpeed(((Player) s1).getElapsedTime(), 0.004f, 3);
                      s1.moveX(-50);
                      s1.moveY(80);
                      ((Player) s1).setJumping(true);
                  }
         }else{
            
            
         }
   
         }
      */
         
   //this.printCollisionSide();
      
      
   }

   @Override
   public void aSensorTriggered(BasicActor s1, BasicActor s2) {
      //System.out.println("aSensorTriggered" +" "+s2.name);
      
      
   }

   @Override
   public void bSensorTriggered(BasicActor s1, BasicActor s2) {
      //System.out.println("bSensorTriggered"+" "+s2.name);
      
   }
   

}





In your Game Screen class or whatever...
Code: Select all
PlayerGroundCollision playerGroundCollision = new PlayerGroundCollision();
playerGroundColllision.setCollisionGroup(PLAYERGROUP,GROUNDGROUP);

public void render(float delta){


playerGroundCollision.checkCollision();
}



Where PLAYERGROUP AND GROUNDGROUP are ActiveGroups objects.

Of course, doing each collision and typing checkCollision(); sucks so CollisionManager takes
care of that... you have to copy and paste this is not in the zips ooops!

Code: Select all
class CollisionManager{
   private Array<CollisionDistributor> collisions;
   public CollisionManager(){
      collisions = new Array<CollisionDistributor>();
      
   }
   
   /**
    * Kind of optimizes collision detection i'll have to do
    * something better though.
    *
    * @param player
    */
   public void checkActivity(BasicActor player) {
      
      for(CollisionDistributor x : collisions ){
         
         if(player.x > x.getGroup2().getEnd()+50 ||
               player.x < x.getGroup2().getStart()-50){
            
            x.setActive(false);
         }
         else{
            x.setActive(true);
         }
         
      }
      
      
   }


   public void addCollisionGroup(ActiveGroup group1, ActiveGroup group2, CollisionDistributor collisionGroup) {
   
      // ensure group1 and group2 is not registered yet
      if (this.getCollisionGroup(group1, group2) != null) {
         System.err.println("WARNING: " + group1.getName() + " <-> "
                 + group2.getName() + " already have a CollisionManager");
         System.err.println("CollisionGroup insertions operation continued");
      }
      

      collisionGroup.setCollisionGroup(group1, group2);
      this.collisions.add(collisionGroup);
   }
   
   /**
    * Returns associated collision group that checking collision of
    * <code>group1</code> and <code>group2</code>, or null if requested
    * collision group can not be found.
    *
    * @param group1 the first group of the collision group to be find
    * @param group2 the second group of the collision group to be find
    * @return CollisionGroup that checks group1 and group2 for collision, or
    *         null if no collision group can be found.
    */
   public CollisionDistributor getCollisionGroup(ActiveGroup group1, ActiveGroup group2) {
      
      for (int i = 0; i < this.collisions.size; i++) {
         if (this.collisions.get(i).getGroup1() == group1
                 && this.collisions.get(i).getGroup2() == group2) {
            return this.collisions.get(i);
         }
      }
      
      return null;
   }
   
   /**
    * Checks the collisions that against <b>ACTIVE</b> groups,
    * if they aren't active no collisions are checked.
    */
   protected void checkCollisions(){
      for (int i = 0; i < this.collisions.size; i++) {
         if (this.collisions.get(i).isActive()) {
            this.collisions.get(i).checkCollision();
         }
      }
   }
   
   
}





use in Game Screen class something like this...

Code: Select all
CollisionManager managedCollisions = new CollisionManager();

managedCollisions.addCollisionGroup(PLAYERGROUP,GROUNDGROUP, new PlayerGroundCollision());
managedCollisions.addCollisionGroup(ENEMYGROUP,GROUNDGROUP,new EnemyGroundCollision()):

public void render(float delta){
managedCollisions.checkCollisions();
}


Use actors and groups for tiles, or you can use CollisionBounds class for tiles which is prefered. Solid tiles use actors and groups.

Also note that the actors use elapsedTime for many methods, you can use Gdx.graphics.getDeltaTime() to do the elapsedTime or create your own SystemTimer and Timer class.


Let me know what you all think, and please do let me know if you have errors cause that will help me to make this better.



ActorClasses.zip
The minimum classes used with collision suite
(10.93 KiB) Downloaded 374 times

collision.zip
Simple Collision suite
(18.21 KiB) Downloaded 366 times
"You can't build a reputation on what you are going to do."- Henry Ford
Bastionpayne
 
Posts: 105
Joined: Wed May 11, 2011 3:49 pm
Location: USA

Return to Libgdx Contributions

Who is online

Users browsing this forum: No registered users and 1 guest