I am a first year programming student. I have coved the basics of precedual programming in c++. I am now fairly new to Java.
Recently i have taken a keen interest into game programming.
my situation:
my situation:
I have a hero class and a rival class. each with thier own members and methods.
how can i make it possible for the hero to interact with the rival, do i do this through the use of interfaces? for example an interface with an undefined attack method
and have both the class implement that interface?
if so
what should the code look like in the attack method of both classes
something likes this
example:
// heros version of implemented method
public int attack()
{
// idealy when hero attacks, the health value will be reduced by 15 of what it is.
rival1.getHealth(- 15)
}
// rival version of implemented method
public int attack()
{
// idealy when rival attacks, the health value will be reduced by 15 of what it is.
hero1.getHealth(- 15)
}
Please help me understanding why we use interefaces and , the anwser to my question
any help or suggestions will be greatly appreciated :) .
I would say you should not use an interface. A better approach would be to use a superclass. With a superclass you can avoid redefining many of the methods that will, presumably, be shared by both the rival and the hero. Here is an example implementation:
Superclass:
public abstract class ExampleFighter {
private String name;
private int health;
private boolean isDead = false;
public ExampleFighter(String name, int health) {
this.name = name;
this.health = health;
}
public void attack(ExampleFighter ef) {
int damage = 0;
//calculate damage dealt
damage = 10;
ef.takeDamage(damage);
}
public void takeDamage(int damage) {
//manipulate the amount of damage taken
if(health - damage <= 0) {
health = 0;
isDead = true;
} else {
health -= damage;
}
}
public boolean isDead() {
return isDead;
}
}
Subclasses:
public class ExampleHero extends ExampleFighter {
int reputation; //the general opinion of the hero
public ExampleHero() {
super("Hero Oreh of Herosville", 100);
reputation = 0;
}
public void improveReputation() {
reputation++;
}
}
public class ExampleRival extends ExampleFighter {
public ExampleRival() {
super("Your greatest rival", 101);
}
}
The side effect of this system is that it requires a fourth class to actually play the game:
public class ExampleGame {
private ExampleHero hero;
private ExampleRival rival;
public static void main(String... args) {
ExampleGame game = new ExampleGame();
game.start();
}
public ExampleGame() {
hero = new ExampleHero();
rival = new ExampleRival();
//what ever other game setup you need to do.
//alternately you could have a load() method
//that takes care of most of this.
}
private void start() {
//make your run loop or query the user for input
//or whatever you need to do. I will create an
//example run loop
boolean running = true;
while(running) {
//this whole block should be moved
//to another method called gameUpdate()
//or something similar but since this
//is a quick example I'll just leave it
//here
hero.attack(rival);
rival.attack(hero);
if(rival.isDead()) {
hero.improveReputation();
System.out.println(“Your rival is dead!");
running = false;
} else if(hero.isDead()) {
System.out.println("you died :(");
running = false;
}
}
}
}
Now this might seem a bit complicated but it illustrates a very important concept: separation of concerns. Separation of concerns involves putting code and making classes that make sense. A player should not know who it’s rival is, player might not even know that enemies exist or what sort of terrain it’s standing on. But a player should know how to manage it's health, it's name, how to take damage, etc. In contrast a Game object would need to know about all the players and enemies so it can tell them to fight and move around on the screen. This is an informal definition of seperation of concerns, for more accurate information read the wikipedia page. In this example I separated the hero and the rival so that, later, you can add more enemies without having to modify your hero code every time. This system also allows you to expand on the game's UI without affecting the player or rival. If you wanted to add a GUI to your game you could add an initialize() method in ExampleGame that setup the GUI. Then in the game loop you could call methods to draw images and graphics onto the GUI. With seperation of concerns you can make the system far more modular and easy to use.
Your second question is: why do we use interfaces? Interfaces are a way of making sure that other classes have a behavior you need them to have, without specifying exactly how they should do it. A classic example of the use of interfaces is the Comparable interface. The Comparable interface has one method that it’s must be implemented: compareTo(). The purpose of this method is to allow a ranking of value objects (think String or File) that cannot use the standard boolean mathematical operations (<, >, ==, etc.) You can think of it as like signing a contract. You (the class implementing the interface) agree to have a certain set of functionality however you make that functionality is up to you. For more information read the java tutorial
I should add a caveat to this answer: Inheritance is not the best option. If you want to know how to do it right you should look up MVC (Model View Controller) and Component Based Design. Even these may not the best choice for what you're doing but they're good starting points.
I think you're going to want to break it up into a Fighter class and a FightController class. Then the Fighter would be assigned to either the hero or the rival in the FightController.
So, it would essentially be something like the following (don't mind the sloppy rudimentary code, I haven't written Java in ~2 years, I just slapped this together and I'm not sure it will compile):
public class Fighter {
private int health;
private boolean isTheHero;
public Fighter(int startHealth, boolean hero) {
health = startHealth;
isTheHero = hero;
}
public void adjustHealth(int change) {
if (change > health) {
return 0;
}
health -= change;
return health;
}
public boolean isHero() {
return is_hero;
}
public boolean wasBeaten() {
return health <= 0;
}
}
public class FightController {
private Fighter hero;
private Fighter rival;
private boolean isHerosTurn;
public FightController() {
hero = new Fighter(startHealth, true);
rival = new Fighter(startHealth, false);
isHerosTurn = true;
}
public void takeATurn() {
int hitValue = 15; //Do something to figure out the hit
remainder = 0;
if (hero.wasBeaten() or rival.wasBeaten()) {
sys.out.println("This match is already over");
} else {
if (isHerosTurn) {
remainder = rival.adjustHealth(hitValue);
if (remainder == 0) {
sys.out.println("The HERO wins!!!");
}
} else {
remainder = hero.adjustHealth(hitValue);
if (remainder == 0) {
sys.out.println("The Rival wins. Boo!");
}
}
isHerosTurn = !isHerosTurn;
}
}
}
Then you can do something like:
controller = new FightController();
controller.takeATurn();
controller.takeATurn();
controller.takeATurn();
controller.takeATurn();
on and on until the game is over.
You need to think in terms of a framework for java gaming.
Here's another post addressing the issue,
Game programming in Java?
Objects interact by sending messages. Look at it this way: when a player attacks, then he sends it's violent message to another players reveiveHit method.
Or, to implement it with a common design pattern: a player could send out attacks and other players observe it's behaviour and determine, if they have been hit.
What you shouldn't do: make one player depend on another one (like in your example). If you want to model a match, then add some sort of manager/referee that does the bookkeeping of attacks and effects.
Please help me understanding why we
use interfaces
Implementing an interface allows a class to become more formal about the behavior it promises to provide also they form a contract between the class and the outside world, and this contract is enforced at build time by the compiler. If your class claims to implement an interface, all methods defined by that interface must appear in its source code before the class will successfully compile.
1 . Why we are implementing interfaces ?
2. Why do we need interfaces in Java?
and , the anwser to my question
Since your code has common attack( ) method in both the classes i.e Rival and Hero, best way would be to declare the method in an interface.
Remember, following is just a code-snippet, not the complete code. You can complete it yourself.
public interface Fight {
public int attack();
}
public class Hero implements Fight {
public int attack() {
rival1.getHealth(-15);
}
}
public class Rival implements Fight {
public int attack() {
hero1.getHealth(-15);
}
}
This is the interface for the character in the game which interact with each other.
public interface Character{ ... }
This is the interface if the character is able to attack or not.
public interface Fightable{
public void attack(Character character);
}
These are the two classes in your game which implements both the interfaces.
public class Hero implements Character, Fightable
{
// heros version of implemented method
public int attack(Character character)
{
// idealy when hero attacks, the health value will be reduced by 15 of what it is.
character.setHealth(-15);
}
}
public class Villon implements Character, Fightable
{
// rival version of implemented method
public int attack(Character character)
{
// idealy when rival attacks, the health value will be reduced by 15 of what it is.
character.setHealth(- 15);
}
}
Related
I studied about SOLID Principle and created a question for me about it.
you suppose that we need a Tea Object in Mug class, now is this better than create a instance from Tea in Mug class or pass from outside through Constructor or setter method.
which on is true?
example:
class Mug {
private Tea tea;
public Mug(){
this.tea = new Tea();
}
public boolean isFull(){
return this.tea.value != 10;
}
}
or
class Mug {
private Tea tea;
public Mug(Tea tea){
this.tea = tea;
}
// public void setTea(Tea tea){
// this.tea = tea;
// }
public boolean isFull(){
return this.team.value != 10;
}
}
use:
public class Test {
static void main(String[] args){
Mug mug = new Mug();
//or
Mug mug = new Mug(new Tea());
}
}
which one is better?
NOTE: Suppose that Mug support only Tea object in our program.
Both of your cases violate SOLID.
Your each concrete implementation (concrete class) should only be dependent upon Abstractions.
in your case Tea is not an abstraction. Mug has tight coupling with Tea. Below is a possible way to code it.
public interface ITea{
//tea related methods which you think should be exposed to outside world. Also all implementation of ITea must support these method (L in SOLID)
}
public class Tea implements ITea{
// Implement the contract methods from ITea
}
public class Mug {
private ITea tea;
// Have constructor or setter to inject concrete implementation. Setter will provide you capability to modify behavioral at run time.
}
EDIT:
1. If we are sure there is only one possible implementation Of tea. Then also interface is better as concrete implementations are hard to mock and hence makes unit testing is difficult.
Avoid using enums for setting type. Enums inject switch cases and in future if a case is added all such switch cases needs to be modified leading to violation of O in SOLID.
If a case is added you have to modify existing code and in case you forget to add a case somewhere it leads to unexpected errors. (It violates OCP. Instead of enums put logic in specific implementation, have common interface and specific implementation). Also if we implement the case specific logic in individual instances of enum then the enum file will become gigantic. Instead if we have specific logic in individual concrete classes implementing common interface makes the user code easy as it can be injected with concrete classes in a polymorphic way.
p.s. this answer is about following the principles and it's not always possible to do so. It's fine to violate the principle but we must know that we are violating it, and have a very good reason to do so.
I would use the second one where possible, injecting a classes dependencies, take this example where the Tea constructor requires more information:
class Mug {
private Tea tea;
public Mug(int temperature) {
this.tea = new Tea(temperature);
}
public boolean isFull() {
return tea.value != 10;
}
}
See how ugly that is that Mug's constructor now needs information only used by Tea's constructor.
But as it stands I would say that neither of your examples violates any SOLID principle.
There is nothing that says you can't create a new object inside another and nothing that says you must create abstractions.
Here would be a real violation in this area:
class Mug { // VIOLATION
private Tea tea;
private Coffee coffee;
public Mug(boolean tea) {
if (tea) {
this.tea = new Tea();
} else {
this.coffee = new Coffee();
}
}
public boolean isFull() {
return tea.value != 10 || coffee.value != 10;
}
}
The class depends upon multiple similar classes. Compare to:
class Mug {
private Liquid liquid;
public Mug(Liquid liquid) {
this.liquid = liquid;
}
public boolean isFull() {
return liquid.getVolume() != 10;
}
}
interface Liquid {
int getVolume();
}
class Tea implements Liquid {
private int volume;
#Override
public int getVolume() {
return volume;
}
}
class Coffee implements Liquid {
private int volume;
#Override
public int getVolume() {
return volume;
}
}
But as you only have one thing that can go in a Mug there is no violation and no need for an abstraction. In general, never write any code that doesn't solve a problem.
And never create an abstraction with a name like ITea. In such a case either the concrete class name is not specific enough, or the abstraction name is not general enough.
In my application I have a 2d array of entities to represent a grid. Each location in the grid can either be empty or occupied by an entity (in this case it's just a person or wall). Right now I use instanceof to check whether an entity is a person or a wall.
I was thinking of giving each entity a method which returns an enum stating their type so i.e. a wall entity would return EntityType.WALL. I was wondering if this is the best idea to remove the use of instanceof or is instanceof suitable in this scenario?
Use Tell, Don't Ask: instead of asking the objects what they are and then reacting on that, tell the object what to do and then walls or people do decide how they do what they need to do.
For example:
Instead of having something like this:
public class Wall {
// ...
}
public class Person {
// ...
}
// later
public class moveTo(Position pos) {
Object whatIsThere = pos.whatIsThere();
if (whatIsThere instanceof Wall) {
System.err.println("You cannot move into a wall");
}
else if (whatIsThere instanceof Person) {
System.err.println("You bump into " + person.getName());
}
// many more else branches...
}
do something like this:
public interface DungeonFeature {
void moveInto();
}
public class Wall implements DungeonFeature {
#Override
public void moveInto() {
System.err.println("You bump into a wall");
}
// ...
}
public class Person implements DungeonFeature {
private String name;
#Override
public void moveInto() {
System.err.println("You bump into " + name);
}
// ...
}
// and later
public void moveTo(Position pos) {
DungeonFeature df = currentPosition();
df.moveTo(pos);
}
This has some advantages.
First, you don't need to adjust a giant if then else tree each time you add a new dungeon feature.
Second, the code in the dungeon features is self-contained, the logic is all in the said object. You can easily test it and move it.
The theoretical solution to removing the instanceof in a refined way is the usage of the Visitor Pattern. How it works is that the object that needs to know whether the other element is a wall or person calls that object with itself as a parameter, and that particular object calls back thus providing information about its type.
Example,
public class Person {
void magic() {
if(grid.getAdjacent() instanceof Person) {
Person otherPerson = (Person)grid.getAdjacent();
doSomethingWith(otherPerson);
} else if(grid.getAdjacent() instanceof Wall) {
Wall wall = (Wall)grid.getAdjacent();
doOtherThingWith(wall);
}
}
}
Can become
public class Person extends Entity {
void magic() {
grid.getAdjacent().visit(this);
}
void onVisit(Wall wall) {
doOtherThingWith(wall);
}
void onVisit(Person person) {
doSomethingWith(person);
}
public void visit(Person person) {
person.onVisit(this);
}
}
public class Wall extends Entity {
public void visit(Person person) {
person.onVisit(this);
}
}
I would let person and wall inherit from a abstract superclass ( e.g. Tile ) which has a method getType() returning an enum or int and implement this method in Wall and Person returning the appropriate
If you follow the other answers here and implement a visitor pattern or use an enum you will not make a mistake.
However, it might also help to think about what exactly it is you want to do with that switching logic (be it instanceof or visitors), because sometimes there is a simpler way to do that.
For example, if all you want to do is check if an entity occupies a grid in a blocking way, then you can just add a method boolean isSolid() to each entity via interface. You can use this with default methods for extra beauty:
public interface GridPhysics {
default boolean isSolid() {
return true;
}
// other grid physics stuff
}
public class Wall implements GridPhysics {
// nothing to do here, it uses the default
}
// in your game logic
public boolean canMoveTo(GridPhysics gridCell) {
return !gridCell.isSolid() && otherChecks();
}
You might also want to have a look at entity component systems (e.g. Artemis), which basically take this idea of "composition over inheritance" to the extreme.
ligi's answer is right on the money. (Whoever downvoted it, I wonder what they were thinking.) As an alternative, consider this:
abstract class Tile
{
public final EntityType type;
protected Tile( EntityType type )
{
this.type = type;
}
}
abstract class Pedestrian extends Tile
{
public Pedestrian()
{
super( EntityType.PEDESTRIAN );
}
}
abstract class Wall extends Tile
{
public Wall()
{
super( EntityType.WALL );
}
}
The rationale behind this is that the "type" of the entity is a permanent characteristic of the entity, so it is suitable to be specified in the constructor and to be realized in a final member field. If it is returned by a virtual method (non-final method in java parlance) then descendants would be free to return one value at one point in time, and another value at another point in time, which would spell havoc.
Oh, and if you really cannot stand the public final member, go ahead and add a getter for it, but my advice would be that never mind the purists, public final members without getters are perfectly fine.
Answers are very good here nothing to say anything about that, but if I were in such situation and if it is allowed than i would have been gone for a 2d int array with possible value 0(for empty by default assignment) and 1,2 for person or wall.
As mentioned on this other question, modern Java compilers are very efficient at operations like instanceof. You should be fine using it.
In fact, one of the other provided answers tested instanceOf and string comparisons, and instanceOf was significantly faster. I recommend you stick with using it.
I'm writing a chess game. My basic design is to have a 2d array (8 x 8) consisting of square objects. Squares have a number of fields: int height, int width, Piece piece (null if empty, some type of Piece object otherwise.
NB: Rook, Knight, Bishop, etc. all extend Piece.
Now, I'm getting a little tripped up on how to figure out what moves are legal for a given piece, given my OOP design. Here's what I'm thinking:
1) User clicks square
2) We determine what piece is on square (if empty, return error message)
3) Generate legal moves for that piece on that square
I'm worried about writing code like:
if (clickedSquare.piece.instanceOf(Rook)) {
return Rook.getLegalDestinationSquares(clickedSquare);
} else if (clickedSquare.piece.instanceOf(Bishop)) {
return Bishop.getLegalDestinationSquares(clickedSquare);
} else if...
Which seems really bad. There must be a way to do this that conforms better to OOP but I'm still learning.
Thanks for the help,
Mariogs
You don't need to create that if statement. Just get the current piece on the field and call some method like (getLegalMoves()) or something.
If field is empty - return empty list of allowed moves.
public abstract class Piece {
public abstract List<Field> getFieldsAllowed(Field field);
}
public class Rook extends Piece {
#Override
public List<Field> getFieldsAllowed(Field field) {
// TODO Auto-generated method stub
return null;
}
}
public class Field {
public Piece getPiece() {
// get current piece
}
}
Something like this. Try to find your own solution. This one is not perfect.
public final class Point {
public final int x, y;
public Point (int x, int y){
this.x = x;
this.y = y;
}
}
public abstract class Piece {
private Point location;
protected Piece (Point initial){
this.location = initial;
}
public Point getLocation(){ return location; }
public Point setLocation(Point location){ this.location = location; }
public abstract List<Point> getLegalMoves ();
}
public final class Rook {
public Rook (Point initial){
super(initial);
}
public List<Point> getLegalMoves (){
// you know the current location, and you know you are a Rook,
// so you have all you need to determine the possible points where
// this Rook can go to
}
}
Then in other code, you can do:
List<Point> legalMoves = clickedSquare.piece.getLegalMoves();
which clearly makes abstraction of what actual piece it is acting upon.
If you do need a static method for other purposes, you can define them in each class such as Rook. Delegate the instance methods to the static methods to avoid code duplication. Like this:
public final class Rook {
// constructor etc.
public List<Point> getLegalMoves (){
return Rook.getLegalMoves (getLocation());
}
public static List<Point> getLegalMoves(Point start){
// you know the location (start), and you know this method is for a Rook,
// so you have all you need to determine the possible end points
}
}
However, if you do not need that static method, don't use and don't even write it (or at least don't expose it in the API of the class). Users of your classes will otherwise start to abuse it end will end up writing code as you provided in your start post - those countless if-elses.
By using this solution, you can add more concrete subclasses (Pawn, King, ...) in the future without touching any existing code (that now acts on Piece), which gives you a maintainability advantage compared to your provided approach.
If Rook, Bishop etc are:
public class Rook extends Piece {
#Override
public String getLegalDestinationSquares() {
// returns all leagal Rook squers
return null;
}
}
and Piece is:
public abstract class Piece {
public abstract String getLegalDestinationSquares();
}
Then you might do it like (in your sample):
return clickedSquare.piece.getLegalDestinationSquares();
Return String is just example, probably you should return Collection of squares.
From OOD there are a few critics.
a field is a field even if no figure is on the field. A null-filed therefore does not exists (LSP)!
a figure do never know what moves he can do, this must be set only by the game rules. Create a new class called Rules. Its the responsibility of the rules to know what moves he can do(SRP). A King (for example) must know if he already did a Castling to decide if he can do a Castling, therefore he must know the previous moves, and this breaks the DIP - ah, here we have another class we miss: ChessNotation.
instanceof is usefull when you inherit things, a Rook can not inherit a field (LSP,DIP).
Let's say I have a board game where players can buy the squares that they land on. I have a method in my abstract base class of Squares called this:
public abstract void applyLandOnAffect(Player player);
Then in my class of BuyableSquares I implement this method shown below:
#Override
public void applyLandOnAffect(Player player){
//Offer them the chance buy the square here.
}
Then if they choose to buy the square I want the object to change from a BuyableSquares() into a BoughtSquare(). The code in the BoughtSquare would handle what happens when another player lands on a bought square. But the issue is how and where I should transform it.
I was thinking this type of code:
this = new BoughtSquare();
But it's not accepted syntax.
How do I approach this?
Thanks
If you are using polymorphism to have different processing of Square instances depending on its type, my suggestion is to use State design pattern.
To introduce it in your application you should:
define a new interface named e.g. SquareState with methods that differ depending on the square type
public interface SquareState {
void applyLandOnAffect(Player player);
}
define all square types which will implement this interface and provide the implementation of the methods from the SquareState interface
public AvailableState implements SquareState {
public void applyLandOnAffect(Player player) { // ..
}
}
public BoughtState implements SquareState {
public void applyLandOnAffect(Player player) { // ..
}
}
introduce a new attribute inside the Square class that will store the current state of the square
public class Square {
private SquareState state;
// ..
}
Once you have done that, changing the state of the Square will be a matter of calling:
this.state = new BoughtSquare();
First of all, you can't assign anything to this.
In order to achieve what you want, why not create a flag in the BuyableSquares class, that indicates whether or not the square is bought.
public class BuyableSquares extends Squares {
private boolean bought = false; // by default
//...
public void markAsBought() {
bought = true;
}
}
Once you instantiate an object, you cannot change its class.
An option would that, as both classes already extend a superclass, use that as the reference to the classes so you can easily replace them. So, you store your board as a set (or list or array) of Square, each of them is a BuyableSquare or a BoughtSquare. When a BuyableSquare must be transformed, you replace it from your structure with the correspondent BoughtSquare (of course, a BoughtSquare constructor that takes the original BuyableSquare as a parameter would be advisable).
I agree with the previous post the the State pattern is best. Setup the Square class with a state variable that you can switch to different states when different events happen to that square. Then, have each state encapsulate the behaviors for what happens when a player lands on the square and it is in a particular state. To change states, just reassign a different instance of SquareState to the state variable. A very simple outline would look like this.
interface SquareState{
void applyLandOnAffect(Player player);
}
public class Square{
private SquareState state = new AvailabelState();
}
public AvailableState implements SquareState{
public void applyLandOnAffect(Player player){
...
}
}
public BoughtState implements SquareState{
public void applyLandOnAffect(Player player){
...
}
}
You should just have one class called Square instead of having separate classes for purchased squares and unpurchased squares. Or you can extend Square if you plan on having other types of squares that are not purchasable. Create a boolean value in your class called purchased that's set to false by default. Then when the square is purchased you can set the value to true.
public class PurchaseableSquare extends Square
{
private boolean purchased;
public Square()
{
this.purchased = false;
}
public void purchaseSquare()
{
this.purchased = true;
}
}
This is one of the examples that justify the rule prefer composition over inheritance.
In your case you have Square subtypes where you define the behavior. The problem is that your object can't change class, so it can't be transformed from BuyableSquare to BoughtSquare. A design based on composition would create a new interface for the square's state. So Square has a SquareState. The different behaviors of bought and not bought squares will be defined in different subtypes of the SquareState interface. So when somebody buys a square you just change its state. Something like:
public class Square {
private SquareState state = new Buyable();
public void buyMe() {
this.state=new Bought();
}
}
I'm writing a game engine in Java for Android games and my engine handles collision detection for different shapes. Each shape is its own class (Square, Circle, etc.), and derives from a common abstract parent Collidable. I have a physics manager class which basically checks if any of the existing objects in the game are colliding with another, and then does the appropriate action when collision is detected. The check for collision is implemented inside each physics shape child class as in the code below.
public abstract class Collidable
{
}
public class Square extends Collidable
{
public boolean Collides(Square) {...}
public boolean Collides(Circle) {...}
public boolean Collides(Triangle) {...}
}
public class Circle extends Collidable
{
public boolean Collides(Square) {...}
public boolean Collides(Circle) {...}
public boolean Collides(Triangle) {...}
}
public class Triangle extends Collidable
{
public boolean Collides(Square) {...}
public boolean Collides(Circle) {...}
public boolean Collides(Triangle) {...}
}
public class PhysicsMgr
{
public boolean Collides(Collidable p1, Collidable p2)
{
return p1.Collides(p2);
// This obviously won't work because there is no Collides
// method in Collidable. I want it to somehow call the child's
// method and pass in p2 as its child type rather than as
// a parent. Or somehow do this:
return (p1.child()).Collides(p2.child());
// I know that obviously nothing like this exists.
}
}
I am aware of "instanceof" and really don't want to check the child type of p1 and p2 versus every single collision shape I have. There must be a better way. I'm looking for either a workaround for my current problem, or preferably a redesign of my current collision detection system to avoid this problem altogether.
Thanks!
you should read about the visitor pattern
For starters, I wouldn't make Collidable an abstract class. Even though there are probably good arguments for it; it just seems to me like this is an "is a" situation where a lot of objects could be collidable.
So, that being said, here is what I would recommend:
// Assuming you're working in 2 dimensions
public class Coordinates {
public Coordinates(float x, float y) {
// etc etc etc
}
}
public interface ICollidable {
// Using unusually long name to illustrate point,
// but feel free to rename.
public int getMaxDistanceFromCenterOfMass(Coordinates unitVector);
public Coordinates getCenterOfMass();
}
And then, for Square, Triangle, and Circle, I would implement the interface.
public class Square implements ICollidable {
#Override
public int getMaxDistanceFromCenterOfMass(Coordinates unitVector) {
// Must declare and initialize
return this.lengthOfSide;
}
#Override
public Coordinates getCenterOfMass() {
return this.centerOfMass;
}
}
public class Circle implements ICollidable {
#Override
public int getMaxDistanceFromCenterOfMass(Coordinates unitVector) {
// Must declare and initialize
return this.radius;
}
#Override
public Coordinates getCenterOfMass() {
return this.centerOfMass;
}
}
public class Triangle implements ICollidable {
#Override
public int getMaxDistanceFromCenterOfMass(Coordinates unitVector) {
// Must declare and initialize
return this.lengthOfSide;
}
#Override
public Coordinates getCenterOfMass() {
return this.centerOfMass;
}
}
Then, in your PhysicsMgr...
public class PhysicsMgr {
public boolean Collides(ICollidable p1, ICollidable p2) {
Coordinates cm1 = p1.getCenterOfMass();
Coordinates cm2 = p2.getCenterOfMass();
int length = Math.sqrt(Math.pow(cm1.x - cm2.x, 2) + Math.pow(cm1.y - cm2.y, 2))
// It is a misnomer to use coordinates as a unit vector, but if I defined a
// UnitVector class, it would be exactly the same with the exception of
// the class name for this situation.
Coordinates unitVector = new Coordinates((cm1.x - cm2.x)/length, (cm1.y - cm2.y)/length);
int collisionDistance1 = p1.getMaxDistanceFromCenterOfMass(unitVector);
int collisionDistance2 = p2.getMaxDistanceFromCenterOfMass(unitVector);
return (length - collisionDistance1 - collisionDistance2) <= 0;
}
}
The one major caveat here is that using the maxDistance from center of mass literally will only give you an approximation for the Square and Triangle. To be exact, you will have to declare some orientation, theta, and calculate the distance from the center of mass of the object to the edge along the unit vector (which will be tricky, but exact).
Another thing that is nice about this is that it allows you to easily add other collidable objects as your engine becomes more sophisticated. This also makes it so that none of the objects have to know about each other.
I was a physics TA for 3 years and it was actually how I got my first exposure to programming. If you're interested in the extra work, here is a reference to the book we used: http://matterandinteractions.org/ It is great for programmers because it teaches physics by using coding examples in python (specifically, vpython http://vpython.org/ ). So this would be a very good reference to have for physics programming.
public boolean Collides(Square) {...}
public boolean Collides(Circle) {...}
public boolean Collides(Triangle) {...}
You are going to need separate implementations for the various combinations of shapes (because there is no common algorithm, I think). So at one point, there will be the need to call instanceof. I am afraid having an abstract method or interface method public boolean Collides(Collidable) is not going to help here, and what you have now cannot be significantly improved upon. This is a textbook case of the limitations of OOP, because these collision detection methods cannot be neatly attached to any of the shape classes, they live somewhere in between, in something like your physics manager.