import java.awt.*; /* *---------------------------------------------------------------------- * * Player.java */ /** This class controls the players. */ /* *---------------------------------------------------------------------- */ public class Player extends Moving { /** How many bullets each player has. Currently set to 6, and will always be. */ public static final int magSize = 6; private Bullet bullets[] = new Bullet[magSize]; private int ammo = magSize; /* * Vertical offset to where the bullets start. */ private int gunY; private int sizeX, sizeY; /* * Rectangle that determines where the player has his feet. * Used to prevent the player to walk over obstacles. */ private Rectangle walk; /* * Rectangle that determines the area the player is sensitive * to bullets. */ private Rectangle hit; /* * Offsets the walk/hit rectangle and coord is translated * with when the player turns around. */ private int turnWalk, turnHit, turn; private Image frames[]; private int framePointer; private int dx, dy; // Player speed. private boolean faceRight; /* * Every scene first two obstacles are ammo boxes, * so the obstacle with index playerId is this * player ammo box. */ private int playerId; /** * Used to be able to give the other player points * when hit by a bullet and to find out which player died. */ public int otherPlayer; /* * Only animate the player when this gets zero. */ private int anim_counter = 0; /* * Animate player every animRate update. */ private int animRate; /* *---------------------------------------------------------------------- * * Player */ /** @param f Player frames. @param props Contains a lot of different values that initialises the player. See the Player.java and Gunfighter.java for more details. @param fr Determines if the player starts facing right or not. Also used to determine which player the player is. */ /* *---------------------------------------------------------------------- * */ public Player(Image f[], int props[], boolean fr) { coord = new Point(props[0], props[1]); frames = f; framePointer = props[2]; for (int n = 0; n < magSize; n++) { bullets[n] = new Bullet(); } faceRight = fr; if (faceRight) { playerId = 0; otherPlayer = 1; } else { playerId = 1; otherPlayer = 0; } hit = new Rectangle(coord.x + props[3], coord.y + props[4], props[5], props[6]); turnHit = props[7]; walk = new Rectangle(coord.x + props[8], coord.y + props[9], props[10], props[11]); turnWalk = props[12]; turn = props[13]; sizeX = props[14]; sizeY = props[15]; gunY = props[16]; animRate = props[17]; } /* *---------------------------------------------------------------------- * * die */ /** This method is called when the player been hit by a bullet. Makes the player scream. Updates the score too. */ /* *---------------------------------------------------------------------- * */ public void die() { for (int n = 0; n < 4; n++) { // Silence other sound effects. Gunfighter.sfx[n].stop(); } Gunfighter.sfx[4].play(); // Scream. Gunfighter.kills[otherPlayer]++; // Update score. Gunfighter.latestPoint = otherPlayer; Gunfighter.gameState = 4; // New duel. } /* *---------------------------------------------------------------------- * * draw */ /** Draws the player. Uncomment the commented lines if you would like to see how the walk and hit rectangles work. */ /* *---------------------------------------------------------------------- * */ public void draw(Graphics g) { g.drawImage(frames[framePointer], coord.x, coord.y, null); // g.drawRect(hit.x, hit.y, hit.width, hit.height); // g.drawRect(walk.x, walk.y, walk.width, walk.height); } /* *---------------------------------------------------------------------- * * drawBullets */ /** Draws the players moving bullets. */ /* *---------------------------------------------------------------------- * */ public void drawBullets(Graphics g) { for (int n = 0; n < magSize; n++) { if (!bullets[n].dead) { bullets[n].draw(g); } } } /* *---------------------------------------------------------------------- * * getAmmo */ /** @return How many bullets the player has left. @see Gunfighter#drawStatus */ /* *---------------------------------------------------------------------- * */ public int getAmmo() { return ammo; } /* *---------------------------------------------------------------------- * * getHit */ /** @return The rectangle where it's fatal to get a bullet. */ /* *---------------------------------------------------------------------- * */ public Rectangle getHit() { return hit; } /* *---------------------------------------------------------------------- * * shoot */ /** Fire the gun. But only if we have ammo and we're able. */ /* *---------------------------------------------------------------------- * */ public void shoot() { if (ammo > 0) { int shot = ableToShoot(); if (shot < magSize) { Gunfighter.sfx[0].play(); ammo--; if (faceRight) { bullets[shot].fire(coord.x + sizeX, coord.y + gunY, 6); } else { bullets[shot].fire(coord.x, coord.y + gunY, -6); } } else { Gunfighter.sfx[2].play(); } } else { Gunfighter.sfx[2].play(); } } /* *---------------------------------------------------------------------- * * update */ /** Updates the player and his bullets. */ /* *---------------------------------------------------------------------- * */ public void update() { if (!collide(2 * dx, 2 * dy)) { coord.translate(dx, dy); walk.translate(dx, dy); hit.translate(dx, dy); } if (anim_counter == 0) { animate(); anim_counter = animRate; } else { anim_counter--; } for (int n = 0; n < magSize; n++) { if (!bullets[n].dead) { bullets[n].update(); } } } /* *---------------------------------------------------------------------- * * userInput */ /** Acts on user input if the player doesn't collide with something. */ /* *---------------------------------------------------------------------- * */ public void userInput(int key, boolean key_pressed) { if (key_pressed && !collide(2 * dx, 2 * dy)) { switch(key) { case 1: // Go up. dy = -2; break; case 2: // Go right. if (!faceRight) { // Turn around if we need and can. if (!collide(turnWalk, 0)) { faceRight = true; walk.translate(turnWalk, 0); hit.translate(turnHit, 0); coord.translate(turn, 0); framePointer = 0; dx = 2; } } else { dx = 2; } break; case 3: // Go down. dy = 2; break; case 4: // Go left. if (faceRight) { // Turn around if we need and can. if (!collide(-turnWalk, 0)) { faceRight = false; walk.translate(-turnWalk, 0); hit.translate(-turnHit, 0); coord.translate(-turn, 0); framePointer = 3; dx =-2; } } else { dx = -2; } break; case 5: // Try to shoot. shoot(); break; default: break; } } else { // Key released. switch(key) { case 1: dy = 0; // Stop walking up. break; case 2: dx = 0; // Stop walking right. break; case 3: dy = 0; // Stop walking down. break; case 4: dx = 0; // Stop walking left. break; default: break; } } } /* *---------------------------------------------------------------------- * * ableToShoot * * Checks if the player is able to shoot. * Return the index of first available bullet. * *---------------------------------------------------------------------- * */ private int ableToShoot() { /* * Check if we stand in a valid position to prevent * shooting across the vertical borders without giving * the other player a chance to see the bullet coming. */ if (ammo > 0 && ((faceRight && coord.x < Gunfighter.screenWidth - 110 - sizeX) || (!faceRight && coord.x > 110))) { for (int n = 0; n < magSize; n++) { if (bullets[n].dead) { return n; } } } return magSize; // Not able to shoot } /* *---------------------------------------------------------------------- * * animate * * Animates the player. * Frame 0-2 when facing right and 5-3 facing left. * *---------------------------------------------------------------------- */ private void animate() { if (faceRight) { if (dx > 0 || dy != 0 ) { if (++framePointer > 2) { framePointer=0; } } } else { if (dx < 0 || dy != 0) { if (--framePointer < 3) { framePointer=5; } } } } /* *---------------------------------------------------------------------- * * collide * * Checks if the player can move in desired direction. * *---------------------------------------------------------------------- * */ private boolean collide(int x, int y) { int i=0; int j=0; boolean collision = false; Rectangle helpRect = new Rectangle(walk.x, walk.y, walk.width, walk.height); helpRect.translate(x,y); /* * Check against the screen borders. */ if ((helpRect.x < 0) || ((hit.y + dy)< 0) || ((helpRect.x + helpRect.width) > Gunfighter.screenWidth) || ((helpRect.y + helpRect.height) > Gunfighter.screenHeight - 40) ) { collision = true; } /* * Check for collision with the other player. */ else if (helpRect.intersects(Gunfighter.actor[otherPlayer].walk)) { collision = true; } else { /* * Check the obstacles. */ while (!collision && (i < Gunfighter.obstacles.length)) { Polygon poly = Gunfighter.obstacles[i].getPolygon(); /* * Check if close to an obstacle */ if (helpRect.intersects(poly.getBoundingBox())) { /* * Yes, check if some of the * new walk rectangles corners are inside the * obstacles polygon... */ if ( poly.inside(helpRect.x, helpRect.y) || poly.inside(helpRect.x, helpRect.y + helpRect.height) || poly.inside(helpRect.x + helpRect.width, helpRect.y)|| poly.inside(helpRect.x + helpRect.width, helpRect.y + helpRect.height) ) { collision = true; } /* * ...or if one the obstacles points are inside * the new walk rectangle. */ else while(!collision && (j < poly.npoints)) { if (helpRect.inside(poly.xpoints[j], poly.ypoints[j])) { collision = true; } j++; } } i++; j=0; } if ((i - 1) == playerId) { // Bumped into our ammo box. reload(); } } return collision; } /* *---------------------------------------------------------------------- * * reload * * Reloads the gun, but only wheen needed. * *---------------------------------------------------------------------- * */ private void reload() { if (ammo != magSize) { Gunfighter.sfx[3].play(); ammo = magSize; } } }