final/src/Player.java

420 lines
13 KiB
Java
Raw Normal View History

2022-05-31 18:19:23 +01:00
/* Eric Li, ICS4U, Completed 5/29/2022
Paddle class defines behaviours for the left and right player-controlled paddles */
2022-06-03 18:50:13 +01:00
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
2022-05-31 18:19:23 +01:00
import java.awt.*;
import java.awt.event.KeyEvent;
2022-06-09 05:07:44 +01:00
import java.awt.event.MouseEvent;
2022-05-31 18:19:23 +01:00
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
2022-06-03 18:50:13 +01:00
import java.io.IOException;
2022-06-15 16:25:38 +01:00
import java.util.Arrays;
import java.util.LinkedList;
2022-05-31 18:19:23 +01:00
public class Player extends GenericSprite {
public final int SPEED = 5;
2022-06-06 03:18:10 +01:00
public static final int PLAYER_WIDTH = 52;
2022-06-05 22:33:24 +01:00
public static final int PLAYER_HEIGHT = 94;
2022-06-13 18:53:58 +01:00
2022-06-17 18:03:38 +01:00
public static final double reach = 0.89;
2022-06-16 18:32:58 +01:00
public static final int steelReachRange = 4*Tile.length;
public int lastXDirection, lastYDirection, lastFrame;
2022-06-03 18:50:13 +01:00
2022-06-07 19:46:45 +01:00
public static final int walkSpeedCap = 5;
2022-06-06 03:18:10 +01:00
public boolean alive;
private transient final Sound jump = new Sound("sound/jump.wav");
2022-06-09 19:19:23 +01:00
2022-06-12 01:02:41 +01:00
public static int mouseX;
public static int mouseY;
public transient boolean leftMouseDown;
2022-06-12 01:02:41 +01:00
public transient boolean rightMouseDown;
2022-06-12 22:28:27 +01:00
boolean holdingSteel;
2022-06-13 04:55:19 +01:00
boolean canPlaceSteel;
2022-06-12 01:02:41 +01:00
2022-05-31 18:19:23 +01:00
// sA[0] is -x, -y
// sA[1] is x, -y
// sA[2] is -x, y
// sA[3] is x, y
public BufferedImageWrapper[][][] spriteArray;
public Player(int x, int y, BufferedImageWrapper[][][] sprites) throws UnsupportedAudioFileException, LineUnavailableException, IOException {
2022-05-31 18:19:23 +01:00
super(x, y, PLAYER_HEIGHT, PLAYER_WIDTH);
// jump = new Sound("sound/jump.wav");
2022-05-31 18:19:23 +01:00
spriteArray = sprites;
2022-06-06 03:18:10 +01:00
alive = true;
2022-06-08 19:32:31 +01:00
isPlayer = true;
2022-06-09 19:19:23 +01:00
leftMouseDown = false;
2022-06-12 22:28:27 +01:00
holdingSteel = false;
2022-06-13 04:55:19 +01:00
canPlaceSteel = false;
2022-05-31 18:19:23 +01:00
}
// moves paddle when key is pressed
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_D){
2022-06-02 18:21:29 +01:00
rightPressed = true;
}
if(e.getKeyCode() == KeyEvent.VK_A){
2022-06-02 18:21:29 +01:00
leftPressed = true;
}
if(e.getKeyCode() == KeyEvent.VK_W){
2022-06-02 18:21:29 +01:00
upPressed = true;
}
if(e.getKeyCode() == KeyEvent.VK_S){
2022-06-02 18:21:29 +01:00
downPressed = true;
}
2022-05-31 18:19:23 +01:00
}
// stops moving paddle when key is released
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_D){
2022-06-02 18:21:29 +01:00
rightPressed = false;
}
if(e.getKeyCode() == KeyEvent.VK_A){
2022-06-02 18:21:29 +01:00
leftPressed = false;
}
if(e.getKeyCode() == KeyEvent.VK_W){
2022-06-02 18:21:29 +01:00
upPressed = false;
}
if(e.getKeyCode() == KeyEvent.VK_S){
2022-06-02 18:21:29 +01:00
downPressed = false;
}
2022-05-31 18:19:23 +01:00
}
public boolean collide(Tile tile, double x, double y){
if(tile==null){return false;}
2022-06-05 16:53:03 +01:00
if(!tile.collision){
return false;
}
2022-06-07 18:12:48 +01:00
if(x+WIDTH>tile.realX&&x<tile.realX+Tile.length&&y-tile.y<Tile.length&&tile.y-y<HEIGHT){
2022-06-05 16:53:03 +01:00
return true;
}
return false;
}
2022-05-31 18:19:23 +01:00
// calls parent
2022-06-05 16:53:03 +01:00
2022-06-05 22:33:24 +01:00
public boolean canUpdate(double x, double y){
2022-06-05 16:53:03 +01:00
boolean canUpdate = true;
int lowX = Math.max(0, ((GameFrame.game.camera.x+GamePanel.GAME_WIDTH)/Tile.length)-4);
int highX = Math.min(lowX + 8, GameFrame.game.map.length);
int lowY = Math.max(0,(this.y/Tile.length)-6);
int highY = Math.min(lowY + 12, GameFrame.game.map[0].length);
for(int i=lowX; i<highX; i++) {
for (int j = lowY; j < highY; j++) {
if (GameFrame.game.map != null) {
if (collide(GameFrame.game.map[i][j], this.x + x, this.y + y)) {
if (GameFrame.game.map[i][j].isFinish) {
LevelManager.nextLevel();
GameFrame.game.player.reset();
return true;
}
if (GameFrame.game.map[i][j].kills) {
GameFrame.game.player.reset();
2022-06-08 04:59:19 +01:00
return true;
}
canUpdate = false;
break;
}
2022-06-06 16:24:46 +01:00
}
2022-06-05 16:53:03 +01:00
}
}
return canUpdate;
}
2022-06-14 18:34:18 +01:00
// public boolean SteelCollide(GenericSprite g, int x, int y){
// if(x+WIDTH>tile.realX&&x<tile.realX+Tile.length&&y-tile.y<Tile.length&&tile.y-y<HEIGHT){
// return true;
// }
// return false;
// }
public void updatePlaceSteel(int x, int y){
2022-06-16 18:32:58 +01:00
if(this.y<0){
canPlaceSteel = false;
return;
}
2022-06-14 18:34:18 +01:00
canPlaceSteel = true;
boolean adjacent = false;
int realX = x*Tile.length-GameFrame.game.camera.x;
2022-06-15 02:35:05 +01:00
double xDis = (realX - GamePanel.GAME_WIDTH/2+ Tile.length/2) - (this.x+WIDTH/2);
double yDis = (y*Tile.length + Tile.length/2) - (this.y+HEIGHT/2);
double hypo = Math.sqrt(xDis*xDis+yDis*yDis);
2022-06-16 18:32:58 +01:00
int xx = (mouseX + GameFrame.game.camera.x + GamePanel.GAME_WIDTH / 2) / Tile.length;
int yy = (mouseY / Tile.length);
2022-06-15 02:35:05 +01:00
//System.out.println(hypo +" "+xDis + " "+ realX);
2022-06-16 18:32:58 +01:00
for(NonPlayer e: GameFrame.game.enemy){
2022-06-17 18:28:39 +01:00
int TileX = xx*Tile.length;
int TileY = yy*Tile.length;
int ex = (e.x+GamePanel.GAME_WIDTH/2);
//System.out.println((xx*Tile.length)+" "+(yy*Tile.length)+" ");
//System.out.print(" "+ (e.x+GamePanel.GAME_WIDTH/2) + " "+e.y+" ");
if(TileX<=ex+e.WIDTH&&ex<=TileX+Tile.length&&TileY<=e.y+e.HEIGHT&&e.y<=TileY+Tile.length){
canPlaceSteel = false;
return;
}
2022-06-16 18:32:58 +01:00
}
if(Math.abs(xDis)<(WIDTH+Tile.length)/2&&Math.abs(yDis)<(HEIGHT+Tile.length)/2){
canPlaceSteel = false; return;
}
2022-06-14 18:34:18 +01:00
int[][]check = {{1,0},{0,1},{-1,0},{0,-1}};
for(int[]a: check){
try{
if(GameFrame.game.map[x+a[0]][y+a[1]]!=null&&!GameFrame.game.map[x+a[0]][y+a[1]].replaceAble){
2022-06-14 18:34:18 +01:00
adjacent = true;
break;
}
} catch(Exception e){
}
}
if(!adjacent){canPlaceSteel = false; return;}
2022-06-16 18:32:58 +01:00
if(hypo>steelReachRange){canPlaceSteel = false; return;}
2022-06-15 16:25:38 +01:00
if(GameFrame.game.map[x][y]!=null&&!GameFrame.game.map[x][y].replaceAble){canPlaceSteel = false; return;}
2022-06-16 18:32:58 +01:00
if(!canReach(xx,yy)){canPlaceSteel = false; return;};
//System.out.println(realX);
2022-06-14 18:34:18 +01:00
}
2022-06-16 18:32:58 +01:00
2022-06-08 19:32:31 +01:00
public void move() throws IOException {
2022-06-12 01:02:41 +01:00
// mouseX = MouseInfo.getPointerInfo().getLocation().x;
// mouseY = MouseInfo.getPointerInfo().getLocation().y;
int Tilex = (mouseX + GameFrame.game.camera.x + GamePanel.GAME_WIDTH / 2) / Tile.length;
2022-06-14 18:34:18 +01:00
int Tiley = (mouseY / Tile.length);
if(holdingSteel){
updatePlaceSteel(Tilex,Tiley);
}
2022-06-05 22:33:24 +01:00
if(canUpdate(xVelocity, 0)&&canUpdate(0, yVelocity)&&!canUpdate(xVelocity, yVelocity)){
GameFrame.game.camera.x += -Math.signum(xVelocity);
2022-06-05 22:33:24 +01:00
}
2022-06-05 16:53:03 +01:00
if(!canUpdate(xVelocity, 0)){
int updateAmount = 0;
if(xVelocity>0){
while(canUpdate(updateAmount, 0)){
updateAmount++;
}
GameFrame.game.camera.x+=updateAmount-1;
2022-06-05 16:53:03 +01:00
} else if(xVelocity<0){
while(canUpdate(updateAmount, 0)){
updateAmount--;
}
GameFrame.game.camera.x+=updateAmount+1;
2022-06-05 16:53:03 +01:00
}
2022-06-07 19:46:45 +01:00
//xVelocity = 0;
2022-06-05 22:33:24 +01:00
}
if(!canUpdate(0, yVelocity)){
2022-06-05 16:53:03 +01:00
if(yVelocity>0){
while(canUpdate(0,1)){
y+=1;
}
isGrounded = true;
2022-06-05 22:33:24 +01:00
} else if(yVelocity<0){
2022-06-05 16:53:03 +01:00
while(canUpdate(0,-1)){
y-=1;
}
}
yVelocity = 0;
}
if(canUpdate(xVelocity, yVelocity)) {
y = y + (int) yVelocity;
GameFrame.game.camera.x = GameFrame.game.camera.x + (int) xVelocity;
2022-06-07 19:46:45 +01:00
} else if(canUpdate(0,yVelocity)){
y = y + (int) yVelocity;
xVelocity*=0.75;
2022-06-07 19:46:45 +01:00
} else if(canUpdate(xVelocity,0)){
GameFrame.game.camera.x = GameFrame.game.camera.x + (int) xVelocity;
2022-06-05 16:53:03 +01:00
}
2022-06-08 16:23:57 +01:00
if(rightPressed){
if(isGrounded){
2022-06-08 19:32:31 +01:00
addParticle(-1);
2022-06-08 16:23:57 +01:00
}
if(xVelocity<5) {
xVelocity += 1;
}
2022-06-02 18:21:29 +01:00
}
2022-06-08 16:23:57 +01:00
if(leftPressed) {
2022-06-08 19:32:31 +01:00
if(isGrounded){
addParticle(1);
}
2022-06-08 16:23:57 +01:00
if(xVelocity>-5) {
xVelocity -= 1;
}
2022-06-02 18:21:29 +01:00
}
if(upPressed&isGrounded){
2022-06-05 16:53:03 +01:00
y-=1;
isGrounded = false;
if(canUpdate(0,-8)) {
2022-06-16 03:18:19 +01:00
if (jump != null) {
jump.start();
}
2022-06-05 16:53:03 +01:00
}
2022-06-02 18:21:29 +01:00
yVelocity = -10;
}
2022-06-09 05:07:44 +01:00
xVelocity *= 0.93;
2022-06-05 16:53:03 +01:00
if(!isGrounded) {
yVelocity += 0.3;
2022-06-05 22:33:24 +01:00
if(downPressed){
yVelocity+=1;
}
2022-06-05 16:53:03 +01:00
}
2022-06-06 03:18:10 +01:00
if(!alive){
alive = true;
reset();
}
2022-06-02 18:21:29 +01:00
capSpeed();
}
2022-06-06 03:18:10 +01:00
public void reset(){
2022-06-12 19:11:09 +01:00
LevelManager.setLevel(LevelManager.level);
GameFrame.game.camera.x = LevelManager.xSpawn;
2022-06-06 03:18:10 +01:00
y = LevelManager.ySpawn;
2022-06-13 18:53:58 +01:00
holdingSteel = false;
2022-06-06 03:18:10 +01:00
}
2022-06-08 19:32:31 +01:00
2022-06-12 22:28:27 +01:00
public void mousePressed(MouseEvent e) throws SpriteException, IOException {
2022-06-15 16:25:38 +01:00
canReach(1,1);
2022-06-12 01:02:41 +01:00
mouseX = e.getX();
mouseY = e.getY();
2022-06-09 19:19:23 +01:00
if(e.getButton()==MouseEvent.BUTTON1) {
leftMouseDown = true;
}
2022-06-12 22:28:27 +01:00
if(e.getButton()==MouseEvent.BUTTON3) {
int x = (mouseX + GameFrame.game.camera.x + GamePanel.GAME_WIDTH / 2) / Tile.length;
2022-06-12 22:28:27 +01:00
int y = (mouseY / Tile.length);
2022-06-13 04:55:19 +01:00
rightMouseDown = true;
2022-06-16 18:32:58 +01:00
2022-06-13 04:55:19 +01:00
if (!holdingSteel) {
2022-06-16 18:32:58 +01:00
if (GameFrame.game.map[x][y] != null && GameFrame.game.map[x][y].movable) {
double xDis = (this.x + WIDTH / 2) - (GameFrame.game.map[x][y].realX + Tile.length / 2);
double yDis = (this.y + HEIGHT / 2) - (GameFrame.game.map[x][y].y + Tile.length / 2);
double hypo = Math.sqrt(xDis * xDis + yDis * yDis);
if (hypo <steelReachRange) {
2022-06-13 18:53:58 +01:00
holdingSteel = true;
if (GameFrame.game.map[x][y].previousBlock != null) {
GameFrame.game.map[x][y] = GameFrame.game.map[x][y].previousBlock;
2022-06-13 18:53:58 +01:00
} else {
GameFrame.game.map[x][y] = null;
2022-06-13 18:53:58 +01:00
}
}
2022-06-12 22:28:27 +01:00
}
2022-06-16 18:32:58 +01:00
} else if ((GameFrame.game.map[x][y] == null || GameFrame.game.map[x][y].replaceAble) && canPlaceSteel) {
Tile temp = GameFrame.game.map[x][y];
2022-06-16 18:32:58 +01:00
GameFrame.game.map[x][y] = new SingleTile(x * Tile.length - (GamePanel.GAME_WIDTH / 2), y * Tile.length, new BufferedImageWrapper(("img/tiles/boxes/steel.png")));
GameFrame.game.map[x][y].movable = true;
GameFrame.game.map[x][y].previousBlock = temp;
2022-06-13 04:55:19 +01:00
holdingSteel = false;
2022-06-12 22:28:27 +01:00
}
2022-06-16 18:32:58 +01:00
}
2022-06-12 22:28:27 +01:00
}
2022-06-12 23:22:13 +01:00
2022-06-12 01:02:41 +01:00
2022-06-15 16:25:38 +01:00
//TODO
public boolean canReach(int x, int y){
int pX = (int)(((double)GameFrame.game.camera.x + GamePanel.GAME_WIDTH) / Tile.length);
int pY = (int)(((double)this.y+HEIGHT/2)/Tile.length);
//System.out.println(pX+" "+pY);
2022-06-16 18:32:58 +01:00
if(pY<0){
return false;
}
2022-06-15 16:25:38 +01:00
//BFS
int[][]check = {{0,1},{1,0},{-1,0},{0,-1}};
int[][]dis = new int[1000][18];
for(int[]a: dis){
Arrays.fill(a, Integer.MAX_VALUE);
}
boolean[][]vis = new boolean[1000][18];
LinkedList<Integer> xx = new LinkedList<>();
LinkedList<Integer> yy = new LinkedList<>();
2022-06-15 19:54:21 +01:00
xx.add(pX);
yy.add(pY);
2022-06-15 16:25:38 +01:00
dis[pX][pY] = 0;
vis[pX][pY] = true;
2022-06-15 19:54:21 +01:00
while(!xx.isEmpty()){
int tempX = xx.poll();
int tempY = yy.poll();
for(int[]a: check){
try{
int newX = tempX + a[0];
int newY = tempY + a[1];
2022-06-16 18:32:58 +01:00
if(dis[tempX][tempY]+1<(Math.min(6,dis[newX][newY]))) {
2022-06-15 19:54:21 +01:00
dis[newX][newY] = dis[tempX][tempY]+1;
2022-06-16 18:32:58 +01:00
if(GameFrame.game.map[newX][newY]==null||GameFrame.game.map[newX][newY].replaceAble) {
xx.add(newX);
yy.add(newY);
}
2022-06-15 19:54:21 +01:00
}
} catch(Exception e){
}
}
}
2022-06-16 18:32:58 +01:00
if(dis[x][y]<=6){
2022-06-15 19:54:21 +01:00
return true;
}
2022-06-16 18:32:58 +01:00
2022-06-15 16:25:38 +01:00
return false;
}
2022-06-12 01:02:41 +01:00
public void mouseDragged(MouseEvent e) {
mouseX = e.getX();
mouseY = e.getY();
2022-06-09 19:19:23 +01:00
}
2022-06-13 04:55:19 +01:00
public void mouseMoved(MouseEvent e) {
mouseX = e.getX();
mouseY = e.getY();
}
2022-06-09 19:19:23 +01:00
public void mouseReleased(MouseEvent e) {
2022-06-12 01:02:41 +01:00
mouseX = e.getX();
mouseY = e.getY();
2022-06-09 19:19:23 +01:00
if(e.getButton()==MouseEvent.BUTTON1) {
leftMouseDown = false;
if (GameFrame.game.bombs.size() < 3 && LevelManager.bombs>0) {
2022-06-12 19:11:09 +01:00
LevelManager.bombs--;
GameFrame.game.bombs.add(new StickyBomb(GameFrame.game.player.x + GameFrame.game.camera.x + WIDTH/2, GameFrame.game.player.y+HEIGHT/2,
(mouseX - GameFrame.game.player.x) / 20, (mouseY - GameFrame.game.player.y) / 10, GameFrame.game.bomb, GameFrame.game.explosionArray));
2022-06-09 19:19:23 +01:00
}
2022-06-09 18:40:43 +01:00
}
2022-06-12 22:28:27 +01:00
if(e.getButton()==MouseEvent.BUTTON3){
rightMouseDown = false;
}
2022-06-09 05:07:44 +01:00
}
2022-06-08 19:32:31 +01:00
public void addParticle(int x) throws IOException {
if(GlobalState.randInt(1,3)==3) {
GameFrame.game.particles.add(new Particle(this.x + GameFrame.game.camera.x + WIDTH / 2 + GlobalState.randInt(-PLAYER_WIDTH / 2, PLAYER_WIDTH / 2)
2022-06-08 19:32:31 +01:00
, (int) (y + HEIGHT * 0.95), GlobalState.randInt(-2, 2) + x, GlobalState.randInt(-4, 1), GlobalState.randInt(1, 7), "img/particles/GrassParticle.png"));
}
}
2022-05-31 18:19:23 +01:00
public int draw(Graphics g, int frame) {
2022-06-03 22:33:21 +01:00
frame %= spriteArray[0][0].length;
2022-06-14 18:34:18 +01:00
if(rightMouseDown){
2022-06-17 18:03:38 +01:00
g.drawOval((int)(x+WIDTH/2-(reach*steelReachRange)),(int)(y+HEIGHT/2-(reach*steelReachRange)), (int)(reach*steelReachRange*2),(int)(reach*steelReachRange*2));
2022-06-14 18:34:18 +01:00
}
if (!upPressed && !downPressed && !leftPressed && !rightPressed) {
g.drawImage(spriteArray[lastXDirection][lastYDirection][0].image, x-10, y, null);
2022-05-31 18:19:23 +01:00
return 0;
} else {
lastXDirection = (int)(Math.signum(xVelocity) + 1) / 2;
lastYDirection = (int)(Math.signum(yVelocity) + 1) / 2;
lastFrame = frame;
g.drawImage(spriteArray[lastXDirection][lastYDirection][frame].image, x-10, y, null);
2022-05-31 18:19:23 +01:00
return 1;
}
2022-06-12 01:02:41 +01:00
2022-05-31 18:19:23 +01:00
}
2022-06-14 18:34:18 +01:00
//public int BfsDis()
2022-05-31 18:19:23 +01:00
}