====== Physics, Collisions ====== ---- ===== Basic Physics: Preliminaries ===== * What kinds of games need physics? What games have physics that you know of? * Angry Birds, Tower/World of Goo, Crayon Physics, platformers * Assume fixed discrete simulation (constant time step). * Approximation (This isn't climate modeling or rocket science or something.) * "If You Can Get Away With it, Fake it" (From [[http://www.gamasutra.com/view/feature/130848/how_to_prototype_a_game_in_under_7_.php?page=2|"How to Prototype a Game in Under 7 Days"]]) * Working with a 2D coordinate system. * If you need a formula (e.g., that involves forces or mass), look it up. * Keep it as simple as possible. * Use the metric system (e.g., m, m/s) ===== Position and Velocity ===== * Question: Where is the object at time t? * Velocity - "The rate of change of position along a straight line with respect to time" * Speed and velocity are not the same; velocity is a vector quantity (has direction) while speed is a scalar quantity. * Given variables: object_x, object_y, speed, angle * Calculation of an object's next x and y coordinates (in your game loop): * scale_x = cos(angle) * scale_y = sin(angle) * velocity_x = (speed * scale_x) * velocity_y = (speed * scale_y) * object_x = object_x + velocity_x * object_y = object_y + velocity_y ===== Acceleration ===== * Acceleration - "The rate of change of velocity with respect to time" * When an object moves along at a certain velocity, an amount of acceleration is __continuously__ added to the velocity. * Given variables: object_x, object_y, speed, acceleration, angle * Calculation of an object's next x and y coordinates (in your game loop): * scale_x = cos(angle) * scale_y = sin(angle) * __speed = speed + acceleration__ * velocity_x = (speed * scale_x) * velocity_y = (speed * scale_y) * object_x = object_x + velocity_x * object_y = object_y + velocity_y ===== Gravity ===== * acceleration that only acts downward in the game window * Earth's gravity constant = 9.81 meters per second squared * In a game world, the gravity constant will be different, depending on the frame rate. * Given variables: object_x, object_y * Calculation of an object's next x and y coordinates (in your game loop; assuming that the object is moving): * velocity_y = velocity_y - gravity (gravity is a drag on vertical velocity) * object_y = object_y + velocity_y (if the object has not hit the ground yet) * object_x = object_x + velocity_x * Where gravity computation might be useful * a character jumping in a sidescroller (a "platformer"), games that involve firing projectiles ---- ====== Collisions ====== ===== Collision detection ===== ==== Bounding box method ==== * Problem: often have irregularly shaped objects (thus wasted space). * However, empirically, less space will be wasted using the bounding box method over bounding sphere method. === Collision test, two methods: === * 1. if (object.x >= box.min_x && object.x < = box.max_x && object.y >= box.min_y && object.y < = box.max_y) then collision occurred * Use same approach for mouse choosing in game menus. * In your ''mouseClicked()'' or equivalent method, check to see if the object was picked via x-y coordinates. * 2. Use shapes in Graphics or Graphics2D and see if two intersect. Example: public boolean collidesWith (Entity other) { if (other instanceof RectEntity) { Rectangle him = new Rectangle(); me.setBounds((int) x, (int) y, sprite.getWidth(), sprite.getHeight()); him.setBounds((int) other.x, (int) other.y, other.sprite.getWidth(), other.sprite.getHeight()); return me.intersects(him); } else if (other instanceof CircleEntity) { Ellipse2D him = new Ellipse2D.Double(); me.setBounds((int) x, (int) y, sprite.getWidth(), sprite.getHeight()); him.setFrame((int) other.x, (int) other.y, other.sprite.getWidth(), other.sprite.getHeight()); return him.intersects(me); } else if (other instanceof TriangleEntity) { boolean collided = false; Point2D p1 = ((TriangleEntity)other).p1; Point2D p2 = ((TriangleEntity)other).p2; Point2D p3 = ((TriangleEntity)other).p3; collided = me.intersectsLine(p1.getX(), p1.getY(), p2.getX(), p2.getY()) || me.intersectsLine(p2.getX(), p2.getY(), p3.getX(), p3.getY()) || me.intersectsLine(p3.getX(), p3.getY(), p1.getX(), p1.getY()); return collided; } else { System.out.println("Other Entity's shape is ambiguous!"); return false; } } ===== Collision response ===== * Different objects respond differently to collisions * Some collisions will resemble that of balls on a billiards table (elastic collision). * Angle of incidence - The angle between the ball movement vector and the plane of the billiards rail that it strikes when the ball moving in a straight line collides with it. {{ https://upload.wikimedia.org/wikipedia/commons/thumb/3/30/Angle_of_incidence.svg/200px-Angle_of_incidence.svg.png|(angle of incidence)}} * Remember, when the ball hits the rail, it will bounce away from the rail at the same angle that it strikes the rail. (assumes no spin on ball) * In other words, the angle of reflection = angle of incidence * Calculation (adapted from [[http://rockhopper.monmouth.edu/~jchung/cs498gd/fa15/labs/animation/gamesprite/GameSprite.java|GameSprite.java]]): if ((ballPoint.x + ballSpeed.x) <= plane.x) { ballSpeed.x = (ballSpeed.x * -1); } if ((ballPoint.x + ballSpeed.x) >= (plane.width)) { ballSpeed.x = (ballSpeed.x * -1); } if ((ballPoint.y + ballSpeed.y) <= plane.y) { ballSpeed.y = (ballSpeed.y * -1); } if ((ballPoint.y + ballSpeed.y) >= (plane.height)) { ballSpeed.y = (ballSpeed.y * -1); } ---- ===== Java 2D Gravity and Collision Examples: ===== * Gravity and collision example: CannonFireTest * Gravity example: Lander * Collision example: Pong * Get all 3 Eclipse projects at https://cssegit.monmouth.edu:2443/jchung/JavaPhysicsCollisionExamples.git ----