In this tutorial we will handle collisions. Before that we will add one more object type to our game and that is the boundary. As the boundaries in the game Polar were perpendicular to the axes so the collision check is quite easy.
public class LineObject extends BaseObject{ public static final int HORIZONTAL=1; public static final int VERTICAL=2; public int Direction; public LineObject(float x,float y,int direction){ Position=new Vector2(x,y); Direction=direction; } public void Destroy(){ IsActive=false; } public void Draw(SpriteBatch sp){ } }
Boundary.java
public class Boundary extend LineObject{ public TextureObject texture; public Boundary(TextureRegion region, float x,float y,int dir){ super(x,y,dir); texture=new TextureObject(region,Position); } public void Draw(SpriteBatch sp){ if(IsActive) texture.Draw(sp); } }
CollsiionHandler.java
public static boolean CheckCollision(CircleObject circle,LineObject line){ if(line.Direction==LineObject.HORIZONTAL){ float d=circle.Position.y-line.Position.y; if(Math.abs(d)-circle.Radius<0){ if(d<0) circle.Position.y=line.Position.y-circle.Radius; } }else{ float d=circle.Position.x-line.Position.x; if(Math.abs(d)-circle.Radius<0){ if(d<0) circle.Position.x=line.Position.x-circle.Radius; } } }
This is a really basic overlap check for circle and line. As in our game we have only horizontal/vertical lines so we can just check the distance in x/y axis and if it is less than the radius of circle then the circle overlaps the line. In our game also, the speed of the ball was never such that it would cross the line inside a frame or it would tunnel through the line. Though if you want to check for tunnel you can always extrapolate the position for the next frame using its current velocity and check which side of the line lies the center of circle. If both are on different sides then there is a collision.
Now we have our basic bodies, now we will loop through them in our update method to check if any of them is colliding or not. One method is to check each body with every other body for collision. This is a little inefficient considering the fact that two static bodies would almost never change their position so will never collide during the game. So we will make two arrays in the ObjectManager class which will have references for static and dynamic bodies in the game and update will check for collision between all the dynamic and statics bodies and dynamic and dynamic bodies.
List<BaseObject> staticObjects; List<BaseObject> dynamicObjects; List<BaseObject> removeList; LevelManager levelManager; ObjectManager(){ //... Add staticObjects=new ArrayList<BaseObject>(); dynamicObjects=new ArrayList<BaseObject>(); } public void AddObject(BaseObject obj){ //FOR STATIC if(obj.Mass==0){ staticObjects.add(obj); }else dynamicObjects.add(obj); } public void RemoveObject(int index){ //BEFORE REMOVING From Objects array Object obj=objects[index]; if(obj.Mass==0) staticObjects.remove(obj); else dynamicObjects.remove(obj); } public void Update(dt){ //remove the objects in removeList for(int i=0;i<removeList.size();i++) RemoveObject(removeList.get(i).UniqueID); removeList.clear(); //Update Objects //Collision Check for(int i=0;i<dynamicObjects.size();i++){ BaseObject dObj=dynamicObjects.get(i); for(int j=0;j<staticObjects.size();j++){ BaseObject sObj=staticObjects.get(i); if(sObj.objectType==CIRCLE_OBJECT){ if(CollisionHandler.CheckCollisiob((CircleObject)dObj, (CircleObject)sObj)){ //CHECK FOR THE TYPES if(sObj.Tag.Equals("STAR"){ //If star has to be deleted add it to removelist removeList.add(sObj); levelManager.CurrentStarCount++; } //CHECK FOR MOB AND SO ON } }else{ if(CollisionHandler.CheckCollisiob((CircleObject)dObj, (LineObject)sObj)){ //Do Something } } } } }
This was a simplified way of looking at the collisions. We added one more field to the BaseObject which holds an integer value for type and define those types globally like CIRCLE_OBJECT,LINE_OBJECT etc. On checking for collision we check the type and then typecast accordingly and pass them as arguments in the collision function. As in our game the only dynamic objects are the circle objects, we did not check the type there and static objects can only be boundary or laser(line) or other circle objects (stars, mobs).
On checking the collisions we can remove objects when required and add other effects if needed. We can update the level state variables also. In the main game loop we can check in the update if count of stars has reached the required count to finish the level or if the protagonist’s health is 0 then finish the level etc.
Next Tutorial:
In next tutorial we will handle the different states to decide the end/finishing of the level and also add the Combo Text which appears on successive collects of stars.
Let us know any of your doubts/suggestions; please put them in the comments section and we would try to answer them.
Thank you for the patience.