Java help: make image move across the screen - java

I've been having trouble with this for quite a while now
I am trying to make a space shooter but to no avail, I'm trying to make the bullet move across the screen like in space invaders etc
when the player presses the space bar a bullet should appear where the player's X position is and move right across the screen.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class game extends JFrame{
boolean run = true;
boolean fired = false;
Image player;
Image bullet;
int playerX = 100;
int playerY = 200;
int bulletX;
int bulletY;
public game(){
//Load Images:
ImageIcon playerI = new ImageIcon("C:/Users/Dan/workspace/shooterProject/bin/shooterProject/ship.png");
player = playerI.getImage();
ImageIcon bulletI = new ImageIcon("C:/Users/Dan/workspace/shooterProject/bin/shooterProject/bullet.png");
bullet = bulletI.getImage();
//Set up game
addKeyListener(new AL());
addMouseListener(new Mouse());
init();
}
private Image dbImage;
private Graphics dbg;
public static void main(String[] args) {
new game();
}
//When the program runs, thins are initialised here
public void init(){
windowManager();
}
public void paintComponent(Graphics g){
if(run == true){
g.drawImage(player, playerX, playerY, this);
}
if(fired == true){
g.drawImage(bullet, bulletX, bulletY, this);
}
repaint();
}
public void paint(Graphics g){
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g.drawImage(dbImage,0,0,this);
}
public void bullet(){
bulletX = playerX;
bulletY = playerY;
while(fired == true){
bulletX = bulletX + 10;
if(bulletX == 800){
bullet = null;
fired = false;
}
}
}
public void windowManager(){
JFrame f = new JFrame();
setTitle("Engine");
setVisible(true);
setResizable(false);
setSize(800,400);
setBackground(Color.BLACK);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public class AL extends KeyAdapter{
public void keyPressed(KeyEvent e){
int keyCode = e.getKeyCode();
if((keyCode == KeyEvent.VK_UP) && (run == true) && (playerY - 20 > 0)){
playerY = playerY - 10;
}else if((keyCode == KeyEvent.VK_DOWN) && (run == true) && (playerY + 20 < 400)){
playerY = playerY + 10;
}
if((keyCode == KeyEvent.VK_SPACE) && (fired == false)){
fired = true;
if(fired == true){
bullet();
}
}
}
public void keyReleased(KeyEvent e){
}
}
public class Mouse extends MouseAdapter {
public void mousePressed(MouseEvent e) {
double x = e.getX();
double y = e.getY();
}
}
}
HOWEVER
When I run the code without the while loop the bullet appears at the player's X position
but
When the while loop is there when the player presses the X button nothing happens, the bullet doesnt even appear!
would anybody be able to assist me in how i can make the bullet appear and move across the screen?
thanks

This is because you are not drawing the bullet until it's out of range, you should not use the while loop this way, you probably need to google for 'Game Loop' but until you do here is a snipet that may help, Note that very bad but should work:
public void paintComponent(Graphics g){
if(run == true){
g.drawImage(player, playerX, playerY, this);
if(fired == true) {
bulletX = bulletX + 10;
if(bulletX > 800 || bulletX < 0){
fired = false;
}
g.drawImage(bullet, bulletX, bulletY, this);
}
repaint();
}
}
public void bullet(){
bulletX = playerX;
bulletY = playerY;
}
one final note, move this code in the paint methode dbImage = createImage(getWidth(), getHeight()) to the constructor or the init() because you are creating a new image every frame.

Related

Java: Pacman collision detection with wall

I have been trying my best to work out collision detection between Pacman and the walls, however my implementation doesn't seem to work as correctly
Does collision detection work at all? Yes
Does it behave correctly? No
How is it currently behaving? When you hit a wall it stops Pacman
from moving which is okay, however any new key presses to move only changes
the images axis (up, right, down or left depending on key press),
it will not move the Pacman beyond its current location after hitting the wall.
Any assistance would be greatly appreciated. thanks in advance
GamePanel.java
package pacman;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements Runnable{
private Thread animator;
private boolean isRunning;
private Map map = new Map();
public GamePanel(){
this.setBackground(Color.BLACK);
this.setDoubleBuffered(true);
addKeyListener(new TAdapter());
setFocusable(true);
}
#Override
public void run() {
isRunning = true;
System.out.println("Is running? "+isRunning);
long startTime, timeDiff, sleepTime;
startTime = System.currentTimeMillis();
while(isRunning){
repaint();
gameUpdate();
timeDiff = System.currentTimeMillis() - startTime;
sleepTime = 5 - timeDiff;
try{
Thread.sleep(sleepTime);
}
catch(InterruptedException ex){
System.exit(0);
}
startTime = System.currentTimeMillis();
}
// gameOver(); not implemented yet, will focus on this when I have some basic animation and the game loop working to satisfaction.
}
#Override
public void addNotify(){
super.addNotify();
startGame();
}
public void startGame(){
if(animator == null || !isRunning){
animator = new Thread(this);
animator.start();
}
} //end of StartGame method
public void gameUpdate(){
map.getPlayer().move();
checkCollision();
} //implementation of ingame updates such as pacman getting killed.
public void checkCollision(){ //this is where I officially set collision up
for(int i = 0; i < map.tiles.length; i++){
for(int j = 0; j < map.tiles.length; j++){
if(map.tiles[i][j] != null){
if(map.getPlayer().getPlayerBox().intersects(map.tiles[i][j].getR())){
map.getPlayer().setColliding(true);
System.out.println("OWW"+map.tiles[i][j].getR().getLocation());
}
}
}
}
}
public void paintComponent(Graphics g){
Graphics2D g2d = (Graphics2D) g;
super.paintComponent(g);
if(isRunning){
drawDot(g2d);
drawPlayer(g2d);
map.drawMap(g2d);
}
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
public void drawDot(Graphics2D g){
g.setColor(Color.GREEN);
for(int x= 0; x < 400; x++){
for(int y = 0; y < 400; y++){
g.drawRect(x * 20, y * 20, 1, 1);
}
}
}
public void drawPlayer(Graphics2D g){
g.drawImage(map.getPlayer().getImage(), map.getPlayer().getX(),map.getPlayer().getY(), this);
}
private class TAdapter extends KeyAdapter{
#Override
public void keyPressed(KeyEvent e) {
map.getPlayer().keyPressed(e);
}
#Override
public void keyReleased(KeyEvent e) {
map.getPlayer().keyReleased(e);
}
}
}
Player.java
package pacman;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
public class Player extends Commons{
private int dx, dy;
private int speed = 1;
private static int playerWidth = 52; //these figures seem off, but that is because the image is not designed correctly or the pacman image is not obeying the logic of not going passed the frame size.
private static int playerHeight = 82;
private Rectangle playerBox;
private Image playerImg = new ImageIcon(Player.class.getResource("Pacman.png")).getImage();
private Image playerImgUp = new ImageIcon(Player.class.getResource("PacmanUp.png")).getImage();
private Image playerImgLeft = new ImageIcon(Player.class.getResource("PacmanLeft.png")).getImage();
private Image playerImgDown = new ImageIcon(Player.class.getResource("PacmanDown.png")).getImage();
private boolean isColliding = false;
public Player(){
this.setX(320);
this.setY(280);
playerBox = new Rectangle(this.getX(), this.getY(),40,40);
}
public void setSpeed(int sp){
speed = sp;
}
public Image getImage(){
if(dy == 1){
return playerImgDown;
}
else if(dy == -1){
return playerImgUp;
}
else if(dx == -1){
return playerImgLeft;
}
else
return playerImg;
}//Responsible for displaying pacman image based on direction of pacman's movement.
void move(){
int x = this.getX();
int y = this.getY();
/*
* This is the part where I am trying to implement some degree of logic to stop it from moving
*/
if(isColliding == false){
this.setX(x += dx);
playerBox.setLocation(x, y);
this.setY(y += dy);
}else if(isColliding == true){
this.setColliding(false);
this.setX(this.getX());
this.setY(this.getY());
}
if (this.getX() <= 1) {
this.setX(1);
}
if (this.getX() >= 400 - playerWidth) {
this.setX(400 - playerWidth);
}
if (this.getY() <= 2) {
this.setY(2);
}
if (this.getY() >= 400 - playerHeight ) {
this.setY(400 - playerHeight);
}
}//Most simplist form of collision detection, stops pacman from leaving the JFrame
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT ){
dx = -speed;
dy = 0;
}
if(key == KeyEvent.VK_RIGHT){
dx = speed;
dy = 0;
}
if(key == KeyEvent.VK_UP){
dx = 0;
dy = -speed;
}
if(key == KeyEvent.VK_DOWN){
dx = 0;
dy = speed;
}
if(key == KeyEvent.VK_ESCAPE){
System.exit(0);
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT){
dy = 0;
}
if(key == KeyEvent.VK_RIGHT){
dy = 0;
}
if(key == KeyEvent.VK_UP){
dx = 0;
}
if(key == KeyEvent.VK_DOWN){
dx = 0;
}
}//end of key release
public Rectangle getPlayerBox() {
return playerBox;
}
public void setPlayerBox(Rectangle playerBox) {
this.playerBox = playerBox;
}
public boolean isColliding() {
return isColliding;
}
public void setColliding(boolean isColliding) {
this.isColliding = isColliding;
}
}// end of class
It looks like what happens is the player enters a tile which causes collision and isColliding is set to true.
The next iteration of the game update calls movement code which checks the player's isColliding boolean. That condition is true and no movement occurs. Next, collision is checked and we haven't moved out of the tile causing the collision so we are stuck in this tile.
I suggest when collision happens to move the player just out of the colliding tile.
We know which direction the player is moving so we can use the inverse direction (multiply dx and dy by -1) to move the player out of the colliding tile.

JFrame.dispose(); isn't doing anything

I've tried every solution I could find here and on forums but I cannot close the wind JFrame no matter what I do and I have no idea why. I need to dispose of the JFrame and launch a different one by creating a WarioWareGUI object.
Right now, the best I seem to be able to do is stop the ball from moving and just leave the old JFrame in the background, but that's not quite good enough. I need the wind JFrame to close
I've tried infinitely disposing, I've tried setting the JFrame as public static and initializing it as an object of BallGame so that I can dispose from anywhere. I've tried simply disposing it immediately after creating it. Nothing seems to get rid of it.
I even tried just setting the ball speed to 0 and making the frame invisible but wind.setVisible(false); doesn't do anything either.
package GameProject;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.Timer;
import javax.swing.WindowConstants;
public final class BallGame extends JComponent implements ActionListener, MouseMotionListener, KeyListener {
private int ballx = 150;
private int bally = 30;
private int paddlex = 0;
private static int ballySpeed = 7;
private static int ballxSpeed = 5;
private int score = 0;
private int round = 1;
private int bounces = 0;
private static int delay = 20;
public static boolean gameOver = false;
public static boolean gameOverFlag = false;
public boolean started;
public static void main(int round) {
//only true the first time the game is run
if ((gameOver == false) && (gameOverFlag == false)) {
gameMake(round);
}
//only true after the game has resulted in a loss
if ((gameOver == true) && (gameOverFlag==true)) {
gameOver = false;
//gameMake(round);
WarioWareGUI gui = new WarioWareGUI();
}
//only true after the game has resulted in a loss and
//returned to main menu
if ((gameOver == false) && (gameOverFlag==true)) {
}
}
public static void gameMake(int round) {
JFrame wind = new JFrame("RedBall/GamePinfo");
BallGame g = new BallGame();
wind.add(g);
wind.pack();
wind.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
wind.setLocationRelativeTo(null);
wind.setVisible(true);
wind.addMouseMotionListener(g);
wind.dispose();
//speed up the timer each round
Timer tt = new Timer(delay, g);
tt.start();
}
public void newball(int ballx, int bally, int ballxspeed, int ballyspeed) {
ballx = 150;
bally = 30;
ballxspeed = 5;
ballyspeed = 7;
JOptionPane.showMessageDialog(null, "new ball !");
return;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 600);
}
#Override
protected void paintComponent(Graphics g) {
//draw the sky
g.setColor(Color.cyan);
g.fillRect(0, 0, 800, 600);
g.setColor(Color.GREEN);
g.fillRect(0, 550, 800, 100);
//draw the paddel
g.setColor(Color.black);
g.fillRect(paddlex, 500, 100, 20);
//draw the ball
g.setColor(Color.RED);
g.fillOval(ballx, bally, 30, 30);
g.setColor(Color.white);
g.setFont(new Font("Arial", 8, 50));
g.drawString(String.valueOf(score), 30, 80);
}
#Override
public void actionPerformed(ActionEvent e) {
//Manages ball movement
ballx = ballx + ballxSpeed;
bally = bally + ballySpeed;
if (gameOverFlag) {
round = 1;
BallGame.main(round);
}
else if (gameOver) {
gameOverFlag = true;
//displays the dialog box indicating victory
JOptionPane.showMessageDialog(this, "You lost on round"
+ round + "!");
ballx = 150;
bally = 30;
}
else if (bounces==10) {
//reset score
bounces = 0;
round++;
JOptionPane.showMessageDialog(this,"You Win! You move on to"
+ " round " + round + "!");
}
// Sets ball speed upward if it hits the paddle
else if (ballx >= paddlex && ballx <= paddlex + 100 && bally >= 475) {
ballySpeed = -7 - (round*2);
//monitors the number of times the ball is successfully hit
score++;
bounces++;
}
// Handles loss condition
else if (bally >= 500 ) {
gameOver = true;
}
// Sets ball movement down if it hits the ceiling
else if (bally <= 0) {
ballySpeed = 7 + (round*2);
}
// Sets ball
else if (ballx >= 775) {
ballxSpeed = -5 - (round*2);
}
// Window left
else if (ballx <= 0) {
ballxSpeed = 5 + (round*2);
}
//**********************************************************************
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
//places paddle in middle of mouse
paddlex = e.getX() - 50;
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
}
I expect calling wind.dispose to shut down the GUI but it won't, no matter where I put it or how I declare the JFrame. I can't just make it invisible either.
The code right now is just where it was when I gave up, I'm not trying to just dispose of it right away of course, but once I can get it to just dispose once successfully, hopefully I can get it to do that at the right time.

My bullet is not being fired when i press the space bar

i'm teaching myself to program in java, and i have decided to make an space invader game. i got my ship moving in any direction, but i have a problem with my bullet being fired. now i know that my y-coordinate of the bullet are being updated every time my ship moves, but it is not firing. I need someone to help me get it to fire if possible. any help is welcome.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Panel extends JPanel implements KeyListener, ActionListener{
private int x;
private int y;
private int dx;
private int dy;
int bx;
int by;
Rectangle bullet;
Timer timer;
private Image image;
public Panel() {
timer = new Timer(30, this);
setBackground(Color.black);
addKeyListener(this);
setFocusable(true);
timer.start();
x=130;
y=430;
bx=xPost()+55;
by=yPost();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
ImageIcon ii= new ImageIcon("C:\\Users\\TriZam\\workspace\\LearningSprite\\ship.png");
image=ii.getImage();
g.drawImage(image, x, y, this);
doDrawing(g);
}
public void move(){
// thhis method will be placed inside the interferance ActionPerformed in order to move the ship and bullet
x += dx;
y += dy;
bx += dx;
by += dy;
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
dx = -3;
if (x<=-25){
dx=0;
}
}
if (key == KeyEvent.VK_RIGHT) {
dx = 3;
if (x>=380 ){
dx=0;
}
}
if (key == KeyEvent.VK_UP) {
dy = -3;
if (y<=0 ){
dy=0;
}
}
if (key == KeyEvent.VK_DOWN) {
dy = 3;
if (y>=430 ){
dy=0;
}
}
if(key ==KeyEvent.VK_SPACE){
// bullet shooting and as you can see the y coordinate updates but bullet not moving.
bullet.y--;
System.out.println(bullet.y--);
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
dx = 0;
}
if (key == KeyEvent.VK_RIGHT) {
dx = 0;
}
if (key == KeyEvent.VK_UP) {
dy = 0;
}
if (key == KeyEvent.VK_DOWN) {
dy = 0;
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void actionPerformed(ActionEvent arg0) {
move();
repaint();
}
int yPost(){
return y;
}
int xPost(){
return x;
}
void doDrawing(Graphics g) {
bullet = new Rectangle(bx, by, 10, 10);
g.setColor(Color.white);
g.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
}
}
This is the main class
import javax.swing.JFrame;
public class MainClass extends JFrame {
private int FrameWidth;
private int FrameHeigh;
private Panel panel;
public MainClass(int width, int height ) {
panel= new Panel();
this.FrameWidth=width;
this.FrameHeigh=height;
setSize(FrameWidth,FrameHeigh);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(panel);
setVisible(true);
}
public static void main(String[] args) {
MainClass m= new MainClass(500, 600);
}
}
create the bullet once ; not inside paint and drawing - inside the constructor;
move this out of
void doDrawing(Graphics g) {
--> remove this from here and into the constructor --> bullet = new Rectangle(bx, by, 10, 10);
also when you update the location of the bullet dont use bx, by and separate variables; just do
bullet.x=....new location
bullet.y=....new location
Inside your key pressed space event, you should create an instance of a bullet. As of right now, you have a member variable Bullet; however it is null since it's never been initialized. That being said, you'll also want to move your bullet--this should be done in your move function.
I see that you have a bx, by, which I'm assuming is suppose to be the bullet's x and y position. However, the rectangle's coordinates never update. Instead of incrementing bx and by, update the rectangle (You'll also want to repaint the rectangle).

Is it possible in javax.swing to user two painters in one frame?

I'm recreating the classic snake game. I've already finished coding the snake. What I have to do now is code the walls (that are supposed to be located at the edges of the frame).
As the painter of the snake "repaints" every 30 miliseconds, I thought it would not be really efficient to let this painter draw the walls as well, as the walls stay on the same place during the whole game so it isn't really necessary to redraw the walls every 30 miliseconds.
Thus, I was wondering whether it was possible to have two painters in my game, one that repaints the snake every 30 miliseconds, and one that paints only once (it paints the walls at the beginning of the game)? How should I do that?
These are the most important parts of the code related to the question (full code can be found below this):
//this is in the main class
public Snake(){
painter = new Painter(this);
this.add(painter, BorderLayout.CENTER);
this.setSize(500, 500);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.addKeyListener(this);
this.requestFocusInWindow();
timer = new Timer(30, this);
startGame();
}
public void startGame(){
snakeList = new LinkedList<Point>();
snakeList.addFirst(new Point(10, 10));
snakeSegments(3);
setFood(30, 30);
movementX = 0;
movementY = 0;
timer.start(); //timer triggers gameUpdate();
}
public void gameUpdate(){
snakeMove(movementX, movementY);
snakeInstructor();
snakeEat();
snakeCollision();
painter.repaint();
}
-
// this is in the painter class
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, 500, 500);
paintSnake(g);
paintFood(g);
}
This is the full code:
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.JFrame;
import javax.swing.Timer;
public class Snake extends JFrame implements KeyListener, ActionListener{
Painter painter;
LinkedList<Point> snakeList;
Timer timer;
Point foodLocation;
int direction;
int snakeSize;
int movementX, movementY;
public static void main(String[] arg){
new Snake();
}
public Snake(){
painter = new Painter(this);
this.add(painter, BorderLayout.CENTER);
this.setSize(500, 500);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.addKeyListener(this);
this.requestFocusInWindow();
timer = new Timer(30, this);
startGame();
}
public void startGame(){
snakeList = new LinkedList<Point>();
snakeList.addFirst(new Point(10, 10));
snakeSegments(3);
setFood(30, 30);
movementX = 0;
movementY = 0;
timer.start();
}
public void gameUpdate(){
snakeMove(movementX, movementY);
snakeInstructor();
snakeEat();
snakeCollision();
painter.repaint();
}
public void snakeCollision(){
for(int i = 4; i < getSnakeSize(); i++){
if(getFirst().equals(snakeList.get(i))){
gameOver();
}
}
}
public void gameOver(){
timer.stop();
}
public void snakeEat(){
if(getFirst().equals(getFood())){
newFood();
setSnakeSize();
snakeSegments(4);
}
}
public void snakeSegments(int i){
snakeSize = i;
while(snakeSize > 0){
snakeList.addLast(new Point(getLast()));
snakeSize--;
}
}
public void snakeInstructor(){
int currentDirection = getDirection();
if (currentDirection == 1){
snakeMove(-1, 0);
} else if (currentDirection == 2){
snakeMove(1, 0);
} else if (currentDirection == 3){
snakeMove(0, -1);
} else if (currentDirection == 4){
snakeMove(0, 1);
}
}
public void snakeMove(int directionX, int directionY){
snakeList.getFirst().x = snakeList.getFirst().x + directionX;
snakeList.getFirst().y = snakeList.getFirst().y + directionY;
for(int i = getSnakeSize()-1; i >=1; i--) {
snakeList.get(i).setLocation(snakeList.get(i-1));
}
}
public void newFood(){
Random generator = new Random();
int x = generator.nextInt(49);
int y = generator.nextInt(47);
setFood(x, y);
}
public void setFood(int x, int y){
foodLocation = new Point(x, y);
}
public Point getFood(){
return foodLocation;
}
public void setDirection(int newDirection){
direction = newDirection;
}
public int getDirection (){
return direction;
}
Point getFirst(){
return snakeList.getFirst();
}
Point getLast(){
return snakeList.getLast();
}
Point get(int i){
return snakeList.get(i);
}
public void addFirst(Point p){
snakeList.addFirst(p);
}
public void addLast(Point p){
snakeList.addLast(p);
}
public int getSnakeSize(){
return snakeList.size();
}
public void setSnakeSize(){
snakeSize = getSnakeSize() + 1;
}
#Override
public void actionPerformed(ActionEvent event) {
gameUpdate();
}
#Override public void keyReleased(KeyEvent e){ }
#Override public void keyTyped(KeyEvent e){ }
#Override public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if((key == KeyEvent.VK_LEFT) && direction != 2){
setDirection(1);
} else if ((key == KeyEvent.VK_RIGHT) && direction != 1){
setDirection(2);
} else if ((key == KeyEvent.VK_UP) && direction != 4){
setDirection(3);
} else if ((key == KeyEvent.VK_DOWN) && direction != 3){
setDirection(4);
} else if (key == KeyEvent.VK_SPACE){
startGame();
}
}
}
-
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
public class Painter extends JPanel{
Snake snake;
public Painter(Snake snake){
this.snake = snake;
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, 500, 500);
paintSnake(g);
paintFood(g);
}
public void paintSnake(Graphics g){
for(int i = 0; i < snake.getSnakeSize(); i++){
g.setColor(Color.WHITE);
Point p = snake.snakeList.get(i);
g.fillRect(p.x*10, p.y*10, 10, 10);
}
}
public void paintFood(Graphics g){
Point p = snake.getFood();
g.setColor(Color.RED);
g.fillRect(p.x*10, p.y*10, 10, 10);
}
}
Yes and no...
You could make the Painter transparent and overlay the snake on top of the walls, but the call to g.fillRect(0, 0, 500, 500); would make that redundant, as it fills the entire component with the current color...
Seen as the paintComponent method for both painters would be called every time you want to update the UI, it's also kind of pointless.
A better solution would be to render the map to BufferedImage and paint it inside the painter before painting the snake.

Collision detection in mouseMoved method

I am creating a game in java. In it, you control a square that follows your mouse. I want to implement collision detection for the square so that it stops slightly within the JFrame and not at the edge. This is very easy when doing this with the arrow keys, but I can't figure it out with the mouseMoved method. Here is the code where the mouseMoved method is:
public void mouseMoved(MouseEvent e){
repaint();
if(e.getX() <= 0)
playerX = 0;
if(e.getX() >= 300)
playerX = 500;
if(e.getY() <= 0)
playerY = 0;
if(e.getY() >= 300)
playerY = 500;
else
playerX = e.getX()-25;
playerY = e.getY()-25;
repaint();
}
Here's the code where the square is created:
public void paintComponent(Graphics g) {
Rectangle player = new Rectangle(playerX, playerY, 50, 50);
g.setColor(Color.blue);
g.fillRect(player.x, player.y, player.width, player.height);
repaint();
}
I don't think you'll need this, but just in case, here's all the code for the GamePanel class, which serves as the panel for my JFrame in the Main class. If you need the Main class let me know but I doubt you will:
package main;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements Runnable{
//Global variables
//Double buffering
private Image dbImage;
private Graphics dbg;
//JPanel variables
static final int GWIDTH = 500, GHEIGHT = 500;
static final Dimension gameDim = new Dimension(GWIDTH, GHEIGHT);
//Game variable
private Thread game;
private volatile boolean running = false;
public boolean mouseClicked = false;
//Character variables
int playerX = 150, playerY = 150;
public class Mouse extends MouseAdapter{
public void mousePressed(MouseEvent e){
mouseClicked = true;
}
public void mouseReleased(MouseEvent e){
mouseClicked = false;
}
public void mouseMoved(MouseEvent e){
repaint();
if(e.getX() <= 0)
playerX = 0;
if(e.getX() >= 300)
playerX = 500;
if(e.getY() <= 0)
playerY = 0;
if(e.getY() >= 300)
playerY = 500;
else
playerX = e.getX()-25;
playerY = e.getY()-25;
repaint();
}
}
public GamePanel(){
addMouseMotionListener(new Mouse());
setPreferredSize(gameDim);
setBackground(Color.BLUE);
setFocusable(true);
requestFocus(true);
}
public void run(){
while(running){
}
}
public void addNotify(){
super.addNotify();
startGame();
}
private void startGame(){
if(game == null || !running){
game = new Thread(this);
game.start();
running = true;
}
}
public void stopGame(){
if(running){
running = false;
}
//Paint method
}
public void paint(Graphics g){
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g.drawImage(dbImage, 0, 0, this);
}
public void paintComponent(Graphics g) {
Rectangle player = new Rectangle(playerX, playerY, 50, 50);
g.setColor(Color.blue);
g.fillRect(player.x, player.y, player.width, player.height);
repaint();
}
private void log(String s){
System.out.println(s);
}
}
Thank you for your help. Please let me know if you need anything.
Your movement code is a bit off. You set the x position only if the Y is not out of bounds and always replace the Y value. Can I suggest full blocks in future - they help avoiding problems like this.
playerX = e.getX()-25;
playerY = e.getY()-25;
if(e.getX() <= 0){
playerX = 0;
}
else if(e.getX() >= 300){
playerX = 500;
}
if(e.getY() <= 0){
playerY = 0;
}
else if(e.getY() >= 300){
playerY = 500;
}
This sets the position first and then corrects it if the player is out of the bounds.

Categories