Merge remote-tracking branch 'origin/master'

# Conflicts:
#	src/GamePanel.java
#	src/Player.java
#	src/Tile.java
master
Chara1236 2022-06-05 12:01:21 -04:00
commit 4d58cece36
7 changed files with 137 additions and 53 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

View File

@ -11,13 +11,9 @@ import java.awt.*;
import java.awt.event.*; import java.awt.event.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Scanner;
import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException; import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.*; import javax.swing.*;
@ -33,13 +29,16 @@ public class GamePanel extends JPanel implements Runnable, KeyListener{
public Graphics graphics; public Graphics graphics;
public Player player; public Player player;
public BackgroundImage background; public BackgroundImage background;
public int frame; public int playerFrame, enemyFrame;
// keeps track of how many ticks has elapsed since last frame change // keeps track of how many ticks has elapsed since last frame change
public int frameCounter = 0; public int playerFrameCounter = 0;
public int enemyFrameCounter = 0;
public BufferedImage[][][] spriteArray = new BufferedImage[2][2][11]; public BufferedImage[][][] playerSpriteArray = new BufferedImage[2][2][11];
public BufferedImage[][][] slimeSpriteArray = new BufferedImage[2][2][3];
public static ArrayList<Tile>map = new ArrayList<Tile>(); public static ArrayList<Tile>map = new ArrayList<Tile>();
public static ArrayList<NonPlayer>enemy = new ArrayList<NonPlayer>();
public static Camera camera; public static Camera camera;
@ -51,19 +50,35 @@ public class GamePanel extends JPanel implements Runnable, KeyListener{
public GamePanel() throws IOException, SpriteException, UnsupportedAudioFileException, LineUnavailableException { public GamePanel() throws IOException, SpriteException, UnsupportedAudioFileException, LineUnavailableException {
camera = new Camera(0); camera = new Camera(0);
background = new BackgroundImage(0, 0, backgroundImage, GAME_WIDTH, GAME_HEIGHT, 10); background = new BackgroundImage(0, 0, backgroundImage, GAME_WIDTH, GAME_HEIGHT, 10);
for (int i = 0; i < 11; i++) { try {
try { // load player sprites from disk here
for (int i = 0; i < 11; i++) {
BufferedImage sprite = getImage(String.format("img/walk/p1_walk%s.png", String.format("%1$2s", i+1).replace(' ', '0'))); BufferedImage sprite = getImage(String.format("img/walk/p1_walk%s.png", String.format("%1$2s", i+1).replace(' ', '0')));
spriteArray[1][0][i] = sprite; playerSpriteArray[1][0][i] = sprite;
spriteArray[1][1][i] = sprite; playerSpriteArray[1][1][i] = sprite;
spriteArray[0][0][i] = flipImageHorizontally(sprite); playerSpriteArray[0][0][i] = flipImageHorizontally(sprite);
spriteArray[0][1][i] = flipImageHorizontally(sprite); playerSpriteArray[0][1][i] = flipImageHorizontally(sprite);
} catch (IOException e) {
e.printStackTrace();
} }
// load slime sprites from disk here
// these variables were not defined above because they are temporary variables
BufferedImage[] temporarySlimeArray = {getImage("img/enemy/slime/slimeWalk1.png"),
getImage("img/enemy/slime/slimeWalk2.png"),
getImage("img/enemy/slime/slimeDead.png")};
BufferedImage[] flippedTemporarySlimeArray = {flipImageHorizontally(getImage("img/enemy/slime/slimeWalk1.png")),
flipImageHorizontally(getImage("img/enemy/slime/slimeWalk2.png")),
flipImageHorizontally(getImage("img/enemy/slime/slimeDead.png"))};
// please note that these sprites are reversed compared to the player sprites
slimeSpriteArray[0][0] = temporarySlimeArray;
slimeSpriteArray[0][1] = temporarySlimeArray;
slimeSpriteArray[1][0] = flippedTemporarySlimeArray;
slimeSpriteArray[1][1] = flippedTemporarySlimeArray;
} catch (IOException e) {
e.printStackTrace();
} }
player = new Player(GAME_WIDTH/2, GAME_HEIGHT/2, 'W', 'A', 'S', 'D', playerSpriteArray); //create a player controlled player, set start location to middle of screenk
enemy.add(new NonPlayer(1200, 100, slimeSpriteArray, 50, 28));
enemy.add(new NonPlayer(0, 100, slimeSpriteArray, 50, 28));
player = new Player(GAME_WIDTH/2, GAME_HEIGHT/2, 'W', 'A', 'S', 'D', spriteArray); //create a player controlled player, set start location to middle of screenk player = new Player(GAME_WIDTH/2, GAME_HEIGHT/2, 'W', 'A', 'S', 'D', spriteArray); //create a player controlled player, set start location to middle of screenk
// the height of 35 is set because it is half of the original tile height (i.e., 70px) // the height of 35 is set because it is half of the original tile height (i.e., 70px)
this.setFocusable(true); //make everything in this class appear on the screen this.setFocusable(true); //make everything in this class appear on the screen
@ -87,19 +102,22 @@ public class GamePanel extends JPanel implements Runnable, KeyListener{
//we are using "double buffering here" - if we draw images directly onto the screen, it takes time and the human eye can actually notice flashes of lag as each pixel on the screen is drawn one at a time. Instead, we are going to draw images OFF the screen, then simply move the image on screen as needed. //we are using "double buffering here" - if we draw images directly onto the screen, it takes time and the human eye can actually notice flashes of lag as each pixel on the screen is drawn one at a time. Instead, we are going to draw images OFF the screen, then simply move the image on screen as needed.
image = createImage(GAME_WIDTH, GAME_HEIGHT); //draw off screen image = createImage(GAME_WIDTH, GAME_HEIGHT); //draw off screen
graphics = image.getGraphics(); graphics = image.getGraphics();
draw(graphics, frame);//update the positions of everything on the screen draw(graphics, playerFrame, enemyFrame);//update the positions of everything on the screen
g.drawImage(image, 0, 0, this); //move the image on the screen g.drawImage(image, 0, 0, this); //move the image on the screen
} }
//call the draw methods in each class to update positions as things move //call the draw methods in each class to update positions as things move
public void draw(Graphics g, int frame){ public void draw(Graphics g, int playerFrame, int enemyFrame){
background.draw(g); background.draw(g);
for(int i=0; i<map.size(); i++){ for(int i=0; i<map.size(); i++){
map.get(i).draw(g); map.get(i).draw(g);
} }
frameCounter += player.draw(g, frame); for (NonPlayer n: enemy) {
// this is a feature; the more enemies there are, the faster the enemies will (appear) to move
enemyFrameCounter += n.draw(g, enemyFrame);
}
playerFrameCounter += player.draw(g, playerFrame);
g.drawString(camera.x+" "+map.get(0).x,100,100); g.drawString(camera.x+" "+map.get(0).x,100,100);
} }
@ -107,12 +125,17 @@ public class GamePanel extends JPanel implements Runnable, KeyListener{
//this method is constantly called from run(). By doing this, movements appear fluid and natural. If we take this out the movements appear sluggish and laggy //this method is constantly called from run(). By doing this, movements appear fluid and natural. If we take this out the movements appear sluggish and laggy
public void move(){ public void move(){
player.move(); player.move();
for (NonPlayer n: enemy) {
n.move();
}
} }
//handles all collision detection and responds accordingly //handles all collision detection and responds accordingly
public void checkCollision() { public void checkCollision() {
player.isGrounded = false; player.isGrounded = false;
for (NonPlayer n : enemy) {
n.isGrounded = false;
}
for (Tile i : map) { for (Tile i : map) {
i.update(); i.update();
} }
@ -121,20 +144,25 @@ public class GamePanel extends JPanel implements Runnable, KeyListener{
player.y = 0; player.y = 0;
} }
if (player.y >= GAME_HEIGHT - Player.PLAYER_HEIGHT) { if (player.y >= GAME_HEIGHT - Player.PLAYER_HEIGHT) {
player.y = GAME_HEIGHT - Player.PLAYER_HEIGHT; player.y = GAME_HEIGHT - Player.PLAYER_HEIGHT;
player.yVelocity = 0; player.yVelocity = 0;
player.isGrounded = true; player.isGrounded = true;
} }
if (player.x <= 0) { if (player.x <= 0) {
player.x = 0; player.x = 0;
} }
if (player.x <= 0) { if (player.x + Player.PLAYER_WIDTH >= GAME_WIDTH) {
player.x = 0; player.x = GAME_WIDTH - Player.PLAYER_WIDTH;
} }
if (player.x + Player.PLAYER_WIDTH >= GAME_WIDTH) {
player.x = GAME_WIDTH - Player.PLAYER_WIDTH; for (NonPlayer n : enemy) {
if (n.y >= GAME_HEIGHT - n.npcHeight) {
n.y = GAME_HEIGHT - n.npcHeight;
n.yVelocity = 0;
n.isGrounded = true;
} }
} }
}
//run() method is what makes the game continue running without end. It calls other methods to move objects, check for collision, and update the screen //run() method is what makes the game continue running without end. It calls other methods to move objects, check for collision, and update the screen
@ -161,10 +189,15 @@ public class GamePanel extends JPanel implements Runnable, KeyListener{
move(); move();
checkCollision(); checkCollision();
repaint(); repaint();
if (frameCounter > 5) { if (playerFrameCounter > 5) {
// increment sprite image to be used and keeps it below 12 // increment sprite image to be used and keeps it below 12
frame = (frame + 1) % 11; playerFrame += 1;
frameCounter -= 5; playerFrameCounter -= 5;
}
if (enemyFrameCounter > 5) {
// increment sprite image to be used and keeps it below 12
enemyFrame += 1;
enemyFrameCounter -= 5;
} }
delta--; delta--;
} }

View File

@ -13,16 +13,19 @@ public class GenericSprite extends Rectangle{
public double xVelocity; public double xVelocity;
public final double SPEED = 20; //movement speed of ball public final double SPEED = 20; //movement speed of ball
public final double speedCap = 5; //Speed cap of ball public final double speedCap = 5; //Speed cap of ball
public int WIDTH = 20; //size of ball public int WIDTH; //size of ball
public int HEIGHT = 20; //size of ball public int HEIGHT; //size of ball
public boolean rightPressed = false; public boolean rightPressed = false;
public boolean leftPressed = false; public boolean leftPressed = false;
public boolean upPressed= false; public boolean upPressed= false;
public boolean downPressed = false; public boolean downPressed = false;
public boolean isGrounded = false; public boolean isGrounded = false;
//constructor creates ball at given location with given dimensions //constructor creates ball at given location with given dimensions
// TODO: reverse order of height and width
public GenericSprite(int x, int y, int height, int width){ public GenericSprite(int x, int y, int height, int width){
super(x, y, height, width);WIDTH = width; HEIGHT = height; super(x, y, width, height);
WIDTH = width;
HEIGHT = height;
} }
//called from GamePanel when any keyboard input is detected //called from GamePanel when any keyboard input is detected
@ -41,12 +44,12 @@ public class GenericSprite extends Rectangle{
//called from GamePanel whenever a mouse click is detected //called from GamePanel whenever a mouse click is detected
//changes the current location of the ball to be wherever the mouse is located on the screen //changes the current location of the ball to be wherever the mouse is located on the screen
public void mousePressed(MouseEvent e){ public void mousePressed(MouseEvent e){
//x = e.getX();
// y = e.getY();
} }
public void move(){ public void move(){
} }
public void capSpeed(){ public void capSpeed(){
@ -61,8 +64,8 @@ public class GenericSprite extends Rectangle{
//called frequently from the GamePanel class //called frequently from the GamePanel class
//draws the current location of the ball to the screen //draws the current location of the ball to the screen
public void draw(Graphics g){ public void draw(Graphics g){
g.setColor(Color.black);
g.fillOval(x, y, WIDTH, HEIGHT);
} }
} }

56
src/NonPlayer.java Normal file
View File

@ -0,0 +1,56 @@
/* Eric Li, ICS4U, Completed 5/29/2022
Paddle class defines behaviours for the left and right player-controlled paddles */
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
public class NonPlayer extends GenericSprite {
public final int SPEED = 3;
// please note that these are not static, in contrast to the player class, as different enemies will have different heights
public int npcWidth;
public int npcHeight;
public int currentXDirection, currentYDirection;
public boolean isDead;
// private final Sound bump;
public BufferedImage[][][] spriteArray;
public NonPlayer(int x, int y, BufferedImage[][][] sprites, int npcWidth, int npcHeight) throws UnsupportedAudioFileException, LineUnavailableException, IOException {
super(x, y, npcHeight, npcWidth);
// bump = new Sound("sound/bump.wav");
spriteArray = sprites;
// TODO: remove
this.npcWidth = npcWidth;
WIDTH = npcWidth;
this.npcHeight = npcHeight;
HEIGHT = npcHeight;
xVelocity = 3;
}
public void move(){
x += (int)xVelocity;
y += (int)yVelocity;
yVelocity+=0.3;
capSpeed();
}
public int draw(Graphics g, int frame) {
if (!isDead) {
// last frame is reserved for death animation
frame %= spriteArray[0][0].length - 1;
currentXDirection = (int)(Math.signum(xVelocity) + 1) / 2;
currentYDirection = (int)(Math.signum(yVelocity) + 1) / 2;
// x-GamePanel.camera.x is used as the camera doesn't follow NPCs
g.drawImage(spriteArray[currentXDirection][currentYDirection][frame], x-GamePanel.camera.x, y, null);
return 1;
} else {
g.drawImage(spriteArray[currentXDirection][currentYDirection][spriteArray[0][0].length-1], x-GamePanel.camera.x, y, null);
return 0;
}
}
}

View File

@ -17,7 +17,7 @@ public class Player extends GenericSprite {
public int lastXDirection, lastYDirection, lastFrame; public int lastXDirection, lastYDirection, lastFrame;
public int upKey, downKey, rightKey, leftKey; public int upKey, downKey, rightKey, leftKey;
private Sound jump; private final Sound jump;
// sA[0] is -x, -y // sA[0] is -x, -y
// sA[1] is x, -y // sA[1] is x, -y
// sA[2] is -x, y // sA[2] is -x, y
@ -152,16 +152,8 @@ public class Player extends GenericSprite {
capSpeed(); capSpeed();
} }
public void capSpeed(){
if(xVelocity>speedCap){
xVelocity = speedCap;
} else if(xVelocity<-1*speedCap) {
xVelocity = -1*speedCap;
}
}
public int draw(Graphics g, int frame) { public int draw(Graphics g, int frame) {
// g.setColor(Color.WHITE); frame %= spriteArray[0][0].length;
if (!upPressed && !downPressed && !leftPressed && !rightPressed) { if (!upPressed && !downPressed && !leftPressed && !rightPressed) {
g.drawImage(spriteArray[lastXDirection][lastYDirection][0], x, y, null); g.drawImage(spriteArray[lastXDirection][lastYDirection][0], x, y, null);
return 0; return 0;