I'm trying to make the game "Snake," but I'm getting stuck on the tail. Right
now, I'm just trying to make the first tail block have the same coordinates as the
head. Here's what I have. For the main class:
public class Game extends JPanel implements ActionListener {
Snake p;
RandomDot r;
Trail trail;
Point w;
Image img;
Timer time;
int t=75;
int score = 0;
int count = 0;
int x, y;
boolean lost = false;
public Game(){
p = new Snake();
r = new RandomDot();
trail = new Trail();
w = new Point();
addKeyListener(new AL());
setFocusable(true);
ImageIcon i = new ImageIcon("C:/Matt's stuff/background.png");
img = i.getImage();
time = new Timer(t, this);
time.start();
}
#Override
public void actionPerformed(ActionEvent e)
{
p.move();
p.moveup();
w.points();
trail.getFirstDot();
trail.findCoords();
if (score>=1)
{
trail.getFirstDot();
}
if (lost==true)
{
score++;
r.getRandom();
lost = false;
}
repaint();
checkCollisions();
}
public int score()
{
return score;
}
public boolean getLost()
{
return lost;
}
public void checkCollisions()
{
Rectangle r1 = r.getBounds();
Rectangle r2 = p.getBounds();
if (r1.intersects(r2))
{
lost = true;
}
}
#Override
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(img, 0, 0, null);
g2d.drawImage(p.getImage(), p.getX(), p.getY(), null);
g2d.drawImage(r.getImage2(), r.getX2(), r.getY2(), null);
if (score>=1)
{
g2d.drawImage(trail.getImage(), trail.getX(), trail.getY(), null);
}
System.out.println(score + "00");
}
private class AL extends KeyAdapter{
#Override
public void keyReleased(KeyEvent e)
{
p.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e)
{
p.keyPressed(e);
}
}
}
For the Snake's head's class:
public class Snake {
Integer x = 480, y = 280, dx = 0, dy = 0, h, m;
boolean dead = false;
boolean didmove = false;
Image still;
RandomDot r;
Game g;
Trail t;
public Snake(){
ImageIcon i = new ImageIcon("C:/Matt's Stuff/snake.png");
still = i.getImage();
}
public Rectangle getBounds(){
return new Rectangle(x,y, 10, 10);
}
public void move(){
x = x + dx;
h = x;
didmove = true;
if (x>=990||x<=5){
dead = true;
x = 480;
y = 280;
dx = 0;
dy = 0;
didmove = false;
}
}
public void moveup(){
y = y + dy;
m = y;
didmove = true;
if (y>=590||y<=0){
dead = true;
x = 480;
y = 280;
dx = 0;
dy = 0;
didmove = false;
}
}
public Integer getX(){
return x;
}
public Integer getY(){
return y;
}
public Image getImage(){
return still;
}
public boolean getBoolean(){
return dead;
}
public boolean didmove(){
return didmove;
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT){
if (dead == false){
dx = -10;
dy = 0;
} else {
x = 480;
y = 280;
dx = 0;
dy = 0;
}
}
if (key == KeyEvent.VK_RIGHT){
if (dead == false){
dx = 10;
dy = 0;
} else {
x = 480;
y = 280;
dx = 0;
dy = 0;
}
}
if (key == KeyEvent.VK_UP){
if (dead == false){
dy = -10;
dx = 0;
}else {
x = 480;
y = 280;
dx = 0;
dy = 0;
}
}
if (key == KeyEvent.VK_DOWN){
if (dead == false){
dy = 10;
dx = 0;
}else {
x = 480;
y = 280;
dx = 0;
dy = 0;
}
}
}
public void keyReleased(KeyEvent e){
int key = e.getKeyCode();
}
}
And lastly, the tail:
public class Trail {
Image still;
Integer x = 500, y = 500, dx, dy, dx2, dy2;
Game g;
Snake p;
Point d;
int count=0;
boolean visible = false;
public Trail(){
ImageIcon i = new ImageIcon("C:/Matt's Stuff/Dot.png");
still = i.getImage();
p = new Snake();
d = new Point();
}
public void getFirstDot(){
visible = true;
}
public void findCoords(){
if (visible == true)
{
x = p.getX();
y = p.getY();
}
}
public Integer getX(){
return x;
}
public Integer getY(){
return y;
}
public Image getImage(){
return still;
}
}
Now my problem is this: The p.getX() and p.getY() in the tail class do not work! The tail block just sits there where the snake's head initially started! I don't know what is going on, none of my research seems to help! Please help me out? Why is it that p.getX() and p.getY() will work in the main Game class, but not the Tail's? Thank you in advance!
You're creating a new Snake() inside your Trail constructor, and then referring to that Snake instead of the one the Game knows about. Instead of creating a new Snake, you should pass in a reference to the constructor, so that you call the methods of the object that is actually being updated:
// In the Trail class
public Trail(Snake s) {
p = s;
// other stuff
}
// In the Game class:
trail = new Trail(p);
// ...
Now when you call p.getX() and so on, you'll actually be pointing at the correct Snake, so you should see your position update correctly.
You should pass the reference of existing Snake object to Trail constructor to make it work. For example in Game class your code should be like this:
public Game(){
p = new Snake();
r = new RandomDot();
trail = new Trail(p);//Pass the reference of Snake so that you get all information w.r.t the current Snake in consideration
w = new Point();
addKeyListener(new AL());
setFocusable(true);
ImageIcon i = new ImageIcon("C:/Matt's stuff/background.png");
img = i.getImage();
time = new Timer(t, this);
time.start();
}
And change the Trail constructor as follows:
public Trail(Snake p){
ImageIcon i = new ImageIcon("C:/Matt's Stuff/Dot.png");
still = i.getImage();
this.p = p;
d = new Point();
}
Related
I need help with a project. For this project we have created moving rectangles that "freeze" when clicked on. We are also supposed to make frozen rectangles unfrozen if they collide with another. I have gotten the first step done but I can't seem to get the rectangles to unfreeze if they collide. I apologize if this doesn't make sense. I am new to Java and stack overflow. Here is my class code.
import edu.princeton.cs.introcs.StdDraw;
import java.util.Random;
import java.awt.Color;
public class MovingRectangle {
//canvas = canvasSize;
public int width; //width of rectangle
public int height; //height of rectangle
public double xVelocity; //x velocity
public double yVelocity; //y velocity
public int xPosition; //x starting position
public int yPosition; //y starting position
private boolean isFrozen; //the rectangle is still moving
// private int R, G, B;
Random rng = new Random();
public int R = rng.nextInt(256);
public int G = rng.nextInt(256);
public int B = rng.nextInt(256); //RGB variables
public int canvas;
public Color c;//canvas size
public MovingRectangle(int x, int y, int w, int h, double xv, double yv, int canvasSize) {
xPosition = x;
yPosition = y;
width = w;
height = h;
xVelocity = xv;
yVelocity = yv;
canvas = canvasSize;
isFrozen = false;
c =new Color(R,G,B);
}
//draws rectangle
public void draw() {
// Random rng = new Random();
// R = rng.nextInt(256);
// G = rng.nextInt(256);
// B = rng.nextInt(256);
// c = new Color(R,G,B);
StdDraw.setPenColor(c);
StdDraw.filledRectangle(xPosition, yPosition, width/2, height/2);
}
//pick a new random color
// public void color() {
// Random rng = new Random();
//
// R = rng.nextInt(256);
// G = rng.nextInt(256);
// B = rng.nextInt(256);
// c = new Color(R,G,B);
// }
//updates position every frame
public void move() {
if (isFrozen == false) {
xPosition += xVelocity;
yPosition += yVelocity;
// xPosition += 0;
// yPosition += 0;
//Check for hitting sides of canvas
if (xPosition > canvas) {
xVelocity *= -1;
//color();
}
if( xPosition < 0) {
xVelocity *= -1;
//color();
}
if (yPosition > canvas ) {
yVelocity *= -1;
//color();
}
if(yPosition <= 0) {
yVelocity*=-1;
//color();
}
}
}
public boolean ifColliding(MovingRectangle rectangle) {
int rightedge = rectangle.xPosition + rectangle.width/2;
int leftedge = rectangle.xPosition - rectangle.width/2;
int topedge = rectangle.yPosition + rectangle.height/2;
int bottomedge = rectangle.yPosition - height/2;
int rightedge2 = this.xPosition + this.width/2;
int leftedge2 = this.xPosition - this.width/2;
int topedge2 = this.yPosition + this.height/2;
int bottomedge2 = this.yPosition - this.height/2;
if(leftedge<rightedge2 && leftedge2<rightedge && topedge>bottomedge2 && bottomedge<topedge2) {
return true;
}
else {
return false;
}
}
public void freeze() {
if(StdDraw.mousePressed() && StdDraw.mouseX() <= xPosition+width && StdDraw.mouseX() >= xPosition-width && StdDraw.mouseY() <=yPosition+height &&StdDraw.mouseY() >= yPosition-height) {
xVelocity=0;
yVelocity=0;
c= new Color(100,0,0);
isFrozen= true;
}
}
public boolean isFrozen() {
return isFrozen;
}
public void winState() {
StdDraw.clear();
}
public void setFrozen(boolean val) {
isFrozen = false;
if (isFrozen == false) {
xPosition += xVelocity;
yPosition += yVelocity;
}
}
// public void stop() {
// isMoving = false;
// }
}
And my driver.
import edu.princeton.cs.introcs.StdDraw;
import java.util.Random;
import java.util.Scanner;
import java.awt.Color.*;
import edu.princeton.cs.introcs.StdDraw;
public class RectangleDriver {
public static final int canvas = 500;
public static void main(String[] args) {
//set canvas size
StdDraw.setCanvasSize(canvas,canvas);
StdDraw.setXscale(canvas, 0);
StdDraw.setYscale(0, canvas);
//assign variables
Random rng = new Random();
//make a rectangle
MovingRectangle[] rectangles = new MovingRectangle[5]; //(x, y, w, h, xv, yv, canvas);
for(int i =0;i<rectangles.length;i++) {
int x = rng.nextInt(canvas); //xPosition
int y = rng.nextInt(canvas); //yPosition
int w = rng.nextInt(100)+20; //width
int h = rng.nextInt(100)+20; //height
double xv = rng.nextInt(5)+2; //xVelocity
double yv = rng.nextInt(5)+2; //yVelocity
rectangles[i]= new MovingRectangle(x,y,w,h,xv,yv,canvas);
}
//while isMoving, the rectangles move
while (true) {
StdDraw.clear();
for(int i =0; i<rectangles.length;i++) {
rectangles[i].move();
rectangles[i].draw();
rectangles[i].freeze();
System.out.println(rectangles[i].isFrozen());
//for 0
if(rectangles[i].ifColliding(rectangles[1])){
if(rectangles[0].isFrozen()) {
rectangles[0].setFrozen(false);
}
}
if(rectangles[i].ifColliding(rectangles[2])){
if(rectangles[0].isFrozen()) {
rectangles[0].setFrozen(false);
}
}
if(rectangles[i].ifColliding(rectangles[3])){
if(rectangles[0].isFrozen()) {
rectangles[0].setFrozen(false);
}
}
if(rectangles[i].ifColliding(rectangles[4])){
if(rectangles[0].isFrozen()) {
rectangles[0].setFrozen(false);
}
}
//for 1
if(rectangles[1].ifColliding(rectangles[0])){
if(rectangles[1].isFrozen()) {
rectangles[1].setFrozen(false);
}
}
if(rectangles[1].ifColliding(rectangles[2])){
if(rectangles[1].isFrozen()) {
rectangles[1].setFrozen(false);
}
}
if(rectangles[1].ifColliding(rectangles[3])){
if(rectangles[1].isFrozen()) {
rectangles[1].setFrozen(false);
}
}
if(rectangles[1].ifColliding(rectangles[4])){
if(rectangles[1].isFrozen()) {
rectangles[1].setFrozen(false);
}
}
// for 2
if(rectangles[2].ifColliding(rectangles[0])){
if(rectangles[2].isFrozen()) {
rectangles[2].setFrozen(false);
}
}
if(rectangles[2].ifColliding(rectangles[1])){
if(rectangles[2].isFrozen()) {
rectangles[2].setFrozen(false);
}
}
if(rectangles[2].ifColliding(rectangles[3])){
if(rectangles[2].isFrozen()) {
rectangles[2].setFrozen(false);
}
}
if(rectangles[2].ifColliding(rectangles[4])){
if(rectangles[2].isFrozen()) {
rectangles[2].setFrozen(false);
}
}
//for 3
if(rectangles[3].ifColliding(rectangles[1])){
if(rectangles[3].isFrozen()) {
rectangles[3].setFrozen(false);
}
}
if(rectangles[3].ifColliding(rectangles[2])){
if(rectangles[3].isFrozen()) {
rectangles[3].setFrozen(false);
}
}
if(rectangles[3].ifColliding(rectangles[0])){
if(rectangles[3].isFrozen()) {
rectangles[3].setFrozen(false);
}
}
if(rectangles[3].ifColliding(rectangles[4])){
if(rectangles[3].isFrozen()) {
rectangles[3].setFrozen(false);
}
}
//for 4
if(rectangles[4].ifColliding(rectangles[1])){
if(rectangles[4].isFrozen()) {
rectangles[4].setFrozen(false);
}
}
if(rectangles[4].ifColliding(rectangles[2])){
if(rectangles[4].isFrozen()) {
rectangles[4].setFrozen(false);
}
}
if(rectangles[4].ifColliding(rectangles[3])){
if(rectangles[4].isFrozen()) {
rectangles[4].setFrozen(false);
}
}
if(rectangles[4].ifColliding(rectangles[0])){
if(rectangles[4].isFrozen()) {
rectangles[4].setFrozen(false);
}
}
}
if(rectangles[0].isFrozen()==true && rectangles[1].isFrozen()==true && rectangles[2].isFrozen()==true && rectangles[3].isFrozen()==true && rectangles[4].isFrozen()==true) {
StdDraw.clear();
StdDraw.text(250, 250, "You win!");
}
StdDraw.show(100);
}
}
}
I am making a game with android. The player is a rectangle that has to jump over obstacles. When i jump i decrease the height and the y coordinates. When i run the game the rectangle is jumping but when i try to jump over an obstacle its still hitting it. So i think i forget to change a value but i have no idea what value. Sorry for my bad english and i am a beginner at coding.
This is my Player class:
package com.example.niek.speelveld;
import android.graphics.Canvas;
import android.graphics.Paint;
/**
* Created by Niek on 15-8-2017.
*/
public class Player extends GameObject {
private int score;
private boolean up;
private boolean playing;
private long startTime;
private int h = 0;
private boolean jump;
public Player(int x , int y){
super.x = x;
super.y = y;
width = 100;
height = GamePanel.HEIGHT;
score = 0;
startTime = System.nanoTime();
}
public void setUp(boolean b){up = b;}
public void update(){
long elapsed = (System.nanoTime()-startTime)/1000000;
if(elapsed>100){
score++;
startTime = System.nanoTime();
}
if(up && h == 0){
jump = true;
up = false;
}
if (jump) {
if (h < 120) {
h = h + 7;
height = height - 7;
y = y - 7;
} else {
jump = false;
}
} else {
if (h > 0) {
h = h - 7;
height = height + 7;
y = y + 7;
}
}
}
public void draw(Canvas canvas){
Paint myPaint = new Paint();
myPaint.setStyle(Paint.Style.STROKE);
myPaint.setStrokeWidth(7);
canvas.drawRect(x, y, width + x, height, myPaint );
myPaint.setStrokeWidth(1);
canvas.drawText("HIGHSCORE " + score, GamePanel.WIDTH - 100 , 0+myPaint.getTextSize(), myPaint);
}
public int getScore(){return score;}
public boolean getPlaying(){return playing;}
public void setPlaying(boolean b){playing = b;}
//public void resetScore(){score = 0;}
public boolean getJump() {
return jump;
}
}
And in my Gamepanel class i use these 2 methods. When i call the class obstacle.get(i).update(); its only updating the x value so its moving towards the player.
public void update(){
if(player.getPlaying()) {
bg.update();
player.update();
//Add obstacles with timer
long obstacleElapsed = (System.nanoTime()-obstacleStartTime)/1000000;
if(obstacleElapsed >(2000 - player.getScore()/4)){
obstacles.add(new Obstacle(BitmapFactory.decodeResource(getResources(), R.drawable.rsz_spike1), WIDTH + 10, HEIGHT - 51, 14, 51, player.getScore()));
//reset timer
obstacleStartTime = System.nanoTime();
}
}
//Loop through every obstacle and check collision
for(int i = 0; i<obstacles.size(); i++){
obstacles.get(i).update();
if (collision(obstacles.get(i), player)) {
obstacles.remove(i);
player.setPlaying(false);
Intent intent = new Intent(c, Result.class);
intent.putExtra("SCORE", player.getScore());
c.startActivity(intent);
break;
}
//Remove obstacles that are out of the screen
if (obstacles.get(i).getX() < -100) {
obstacles.remove(i);
break;
}
}
}
public boolean collision(GameObject o, GameObject p){
if(Rect.intersects(o.getRectangle(), p.getRectangle())){
return true;
}
return false;
}
#Override
public void draw(Canvas canvas){
//Get Width and Height from screen
final float scaleFactorX = (float)getWidth()/WIDTH;
final float scaleFactorY = (float)getHeight()/HEIGHT;
if(canvas!=null) {
final int savedState = canvas.save();
canvas.scale(scaleFactorX, scaleFactorY);
bg.draw(canvas);
player.draw(canvas);
//Draw obstacles
for(Obstacle o : obstacles ){
o.draw(canvas);
}
canvas.restoreToCount(savedState);
}
}
And finally the Player and the Obstacle class extends Gameobject where i have the getRectangle method.
public Rect getRectangle(){
return new Rect(x, y, x+width, y+height);
}
I am working on homework for class, and its late because I can't seem to understand the material despite all the research that I am doing. I am a beginner and do not know much in the way of java. Also, this is my first post so please be forgiving when you are reading this.
I am building on source code from my textbook, which I updated recently for past homework, but now I am trying to generate a class that draws multiple squares and moves those objects independently and at different speeds. They will all need to rebound off the walls as well. I followed the instructions and created two arrays that will hold the random x and y values between 1 and 10. However, I struggle with arrays and I am sure that I am not doing it correctly. So, I would love some feedback to see if I have it set up correctly.
I have a the jpanel pulling up and drawing, and as long as there is 1 square it is working fine bouncing off the walls, but things change when I draw more than one. The do not move independently and they also share the same speed. Some even disappear from time to time. This has really thrown me off. I appreciate any help!
In short, I am trying to paint new squares that all travel in different directions and at different speeds. Per the instructions we are suppose create and use a two arrays that handle the x and y values.
Here is what I have so far:
public class DotsPanel extends JPanel
{
private int delay = 15;
private final int SIZE = 7, IMAGE_SIZE = 3; // radius of each dot
private Timer timer;
private int x, y, i;
private ArrayList<Point> pointList;
static int [] xarray = new int [1000];
static int [] yarray = new int [1000];
Random rand = new Random();
//-----------------------------------------------------------------
// Constructor: Sets up this panel to listen for mouse events.
//-----------------------------------------------------------------
public DotsPanel()
{
pointList = new ArrayList<Point>();
int [] xarray = new int [1000];
int [] yarray = new int [1000];
timer = new Timer(delay, new ReboundListener());
addMouseListener (new DotsListener());
addMouseMotionListener (new DotsListener());
setBackground(Color.gray);
setPreferredSize(new Dimension(700, 500));
for(int i = 0; i < xarray.length; i++)
{
xarray[i] = rand.nextInt(7);
yarray[i] = rand.nextInt(7);
}
timer.start();
}
//-----------------------------------------------------------------
// Draws all of the dots stored in the list.
//-----------------------------------------------------------------
public void paintComponent(Graphics page)
{
super.paintComponent(page);
page.setColor(Color.BLUE);
for (Point spot : pointList)
{
page.fillRect(spot.x-SIZE, spot.y-SIZE, 25, 25);
page.drawString("Count: " + pointList.size(), 5, 15);
}
}
//*****************************************************************
// Represents the listener for mouse events.
//*****************************************************************
private class DotsListener implements MouseListener, MouseMotionListener
{
//--------------------------------------------------------------
// Adds the current point to the list of points and redraws
// the panel whenever the mouse button is pressed.
//--------------------------------------------------------------
public void mousePressed(MouseEvent event)
{
pointList.add(event.getPoint());
repaint();
}
public void mouseDragged(MouseEvent event)
{
// initially I had two xarray and yarray in here just like in
// mouseClicked
// but it did not change anything when removed
}
//--------------------------------------------------------------
// Provide empty definitions for unused event methods.
//--------------------------------------------------------------
public void mouseClicked(MouseEvent event)
{
xarray[i] = rand.nextInt(7);
yarray[i] = rand.nextInt(7);
}
public void mouseReleased(MouseEvent event) {}
public void mouseEntered(MouseEvent event) {}
public void mouseExited(MouseEvent event) {}
public void mouseMoved(MouseEvent e) {}
}
private class ReboundListener implements ActionListener
{
//--------------------------------------------------------------
// Updates the position of the image and possibly the direction
// of movement whenever the timer fires an action event.
//--------------------------------------------------------------
public void actionPerformed(ActionEvent event)
{
for (Point spot : pointList)
{
spot.x += xarray[i];
spot.y += yarray[i];
if (spot.x <= 0 || spot.x >= 700)
xarray[i] = xarray[i] * -1;
if (spot.y <= 0 || spot.y >= 500)
yarray[i] = yarray[i] * -1;
repaint();
}
}
}
}
However, I struggle with arrays and I am sure that I am not doing it correctly.
I wouldn't use Arrays.
Instead, have a Ball object manage its own state. Then you can have different color, speed, size etc for each Ball. Then when the Timer fires you just calculate the new position and repaint the Ball.
Here is an example to get you started:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
public class BallAnimation4
{
private static void createAndShowUI()
{
BallPanel panel = new BallPanel();
JFrame frame = new JFrame("BallAnimation4");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( panel );
frame.setSize(800, 600);
frame.setLocationRelativeTo( null );
//frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible( true );
panel.addBalls(5);
panel.startAnimation();
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
class BallPanel extends JPanel implements ActionListener
{
private ArrayList<Ball> balls = new ArrayList<Ball>();
public BallPanel()
{
setLayout( null );
setBackground( Color.BLACK );
}
public void addBalls(int ballCount)
{
Random random = new Random();
for (int i = 0; i < ballCount; i++)
{
Ball ball = new Ball();
ball.setRandomColor(true);
ball.setLocation(random.nextInt(getWidth()), random.nextInt(getHeight()));
ball.setMoveRate(32, 32, 1, 1, true);
// ball.setMoveRate(16, 16, 1, 1, true);
ball.setSize(32, 32);
balls.add( ball );
}
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
for (Ball ball: balls)
{
ball.draw(g);
}
}
public void startAnimation()
{
Timer timer = new Timer(75, this);
timer.start();
}
public void actionPerformed(ActionEvent e)
{
move();
repaint();
}
private void move()
{
for (Ball ball : balls)
{
ball.move(this);
}
}
class Ball
{
public Color color = Color.BLACK;
public int x = 0;
public int y = 0;
public int width = 1;
public int height = 1;
private int moveX = 1;
private int moveY = 1;
private int directionX = 1;
private int directionY = 1;
private int xScale = moveX;
private int yScale = moveY;
private boolean randomMove = false;
private boolean randomColor = false;
private Random myRand = null;
public Ball()
{
myRand = new Random();
setRandomColor(randomColor);
}
public void move(JPanel parent)
{
int iRight = parent.getSize().width;
int iBottom = parent.getSize().height;
x += 5 + (xScale * directionX);
y += 5 + (yScale * directionY);
if (x <= 0)
{
x = 0;
directionX *= (-1);
xScale = randomMove ? myRand.nextInt(moveX) : moveX;
if (randomColor) setRandomColor(randomColor);
}
if (x >= iRight - width)
{
x = iRight - width;
directionX *= (-1);
xScale = randomMove ? myRand.nextInt(moveX) : moveX;
if (randomColor) setRandomColor(randomColor);
}
if (y <= 0)
{
y = 0;
directionY *= (-1);
yScale = randomMove ? myRand.nextInt(moveY) : moveY;
if (randomColor) setRandomColor(randomColor);
}
if (y >= iBottom - height)
{
y = iBottom - height;
directionY *= (-1);
yScale = randomMove ? myRand.nextInt(moveY) : moveY;
if (randomColor) setRandomColor(randomColor);
}
}
public void draw(Graphics g)
{
g.setColor(color);
g.fillOval(x, y, width, height);
}
public void setColor(Color c)
{
color = c;
}
public void setLocation(int x, int y)
{
this.x = x;
this.y = y;
}
public void setMoveRate(int xMove, int yMove, int xDir, int yDir, boolean randMove)
{
this.moveX = xMove;
this.moveY = yMove;
directionX = xDir;
directionY = yDir;
randomMove = randMove;
}
public void setRandomColor(boolean randomColor)
{
this.randomColor = randomColor;
switch (myRand.nextInt(3))
{
case 0: color = Color.BLUE;
break;
case 1: color = Color.GREEN;
break;
case 2: color = Color.RED;
break;
default: color = Color.BLACK;
break;
}
}
public void setSize(int width, int height)
{
this.width = width;
this.height = height;
}
}
}
Since your Arrays only contain the Point you want to paint you don't have any information about the speed each point should be moved at. The best you could do is create a random amount each point should be moved each time its location is changed. This would give erratic movement as each time you move a point the distance would be random.
If you want more constant speed then you would need to create a second Array to contain the distance each point should move every time.
This starts to get messy creating a new Array every time you want a new property to be unique for the object you want to paint. That is why the approach to create a custom Object with multiple properties is easier to manage.
I am almost done with my first little java game for my final project. It is a sidescroller where you have to shoot/avoid asteroids. My last problem is figuring out how to make my array of asteroids collide with the player's lasers. Here's what I have so far, there's an "AWT-EventQueue-0" java.lang.NullPointerException" on line 137, that I can't deal with. Any help is appreciated.
Edit: I added in my other classes, I realize it would be hard to judge the functionality of my code if I didn't show you where it came from.
package ShooterGame;
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.*;
public class Board extends JPanel implements ActionListener
{
Enemy[] baddies = new Enemy[10000];
Player p;
Image img;
int y;
Timer time;
boolean lost = false;
static Font font = new Font("SanSerif", Font.BOLD, 24);
public AudioClip theme, bang, laser;
static ArrayList<Enemy> enemies;
public static int score = 0;
public static int lives = 5;
public Board()
{
p = new Player();
addKeyListener(new ActionListener());
setFocusable(true);
ImageIcon i = new ImageIcon("images/background.png");
img = i.getImage();
time = new Timer(5, this);
time.start();
for(int j = 0; j < baddies.length; j++)
{
Random ran = new Random();
y = ran.nextInt(365)+1;
baddies[j]= new Enemy((100*j + 700), y, "images/asteroid.gif");
}
theme = Applet.newAudioClip(getClass().getResource("theme.mid"));
theme.play();
bang = Applet.newAudioClip(getClass().getResource("bang.wav"));
}
public void actionPerformed(ActionEvent e)
{
checkCollisions();
ArrayList<?> bullets = Player.getBullets();
for(int i = 0; i < bullets.size(); i++)
{
Bullet b = (Bullet)bullets.get(i);
if(b.isVisible() == true)
{
b.move();
}
else
{
bullets.remove(i);
}
}
p.move();
for(int i = 0; i < baddies.length; i++)
{
if(p.x > 400)
{
baddies[i].move(p.getdx());
}
}
repaint();
}
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
if(lost)
{
g2d.drawString("You Lose!", 300, 300);
}
if((p.getX() - 590) % 2400 == 0 || (p.getX() - 590) % 2400 == 1)
{
p.nx = 0;
}
if((p.getX() - 1790) % 2400 == 0 ||(p.getX() - 1790) % 2400 == 1)
{
p.nx2 = 0;
}
g2d.drawImage(img, 685-p.nx2, 0, null);
if(p.getX() >= 590)
{
g2d.drawImage(img, 685-p.nx, 0, null);
}
g2d.drawImage(p.getImage(), p.edge, p.getY(), null);
ArrayList<?> bullets = Player.getBullets();
for(int i = 0; i < bullets.size(); i++)
{
Bullet b = (Bullet)bullets.get(i);
g2d.drawImage(b.getImg(), b.getX(), b.getY(), null);
}
for(int i = 0; i < baddies.length; i++)
{
if(baddies[i].isAlive == true)
{
g2d.drawImage(baddies[i].getImg(), baddies[i].getX(), baddies[i].getY(), null);
}
}
g2d.setColor(Color.white);
g2d.drawString("Score: " + score, 0, 320);
g2d.drawString("Lives: " + lives, 80, 320);
}
public void checkCollisions()
{
Rectangle[] rect = new Rectangle[baddies.length];
for(int i = 0; i < baddies.length; i++)
{
Enemy e = (Enemy)baddies[i];
rect[i] = e.getBounds();
}
ArrayList<?> bullets = Player.getBullets();
for (int i = 0; i < bullets.size(); i++)
{
Bullet b = (Bullet) bullets.get(i);
Rectangle b1 = b.getBounds();
if (rect[i].intersects(b1) && baddies[i].isAlive())
{
score++;
baddies[i].isAlive = false;
baddies[i].isVisible = false;
bang.play();
}
Rectangle h = p.getBounds();
if (h.intersects(rect[i]))
{
if(baddies[i].isAlive() == true)
{
lives--;
if(lives < 0)
{
lost = true;
theme.stop();
System.exit(1);
}
}
}
}
}
private class ActionListener extends KeyAdapter
{
public void keyReleased(KeyEvent e)
{
p.keyReleased(e);
}
public void keyPressed(KeyEvent e)
{
p.keyPressed(e);
}
}
}
Enemy
package ShooterGame;
import java.awt.*;
import javax.swing.ImageIcon;
public class Enemy
{
int x, y;
Image img;
boolean isAlive = true;
boolean isVisible = true;
public Enemy(int startX, int startY, String location)
{
x = startX;
y = startY;
ImageIcon l = new ImageIcon(location);
img = l.getImage();
}
public Rectangle getBounds()
{
return new Rectangle(x, y, 60, 60);
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
public boolean isAlive()
{
return isAlive;
}
public boolean isVisible()
{
return isVisible;
}
public Image getImg()
{
return img;
}
public void move(int dx)
{
x = x - dx;
}
}
Bullet
package ShooterGame;
import java.applet.Applet;
import java.awt.*;
import javax.swing.ImageIcon;
import java.applet.AudioClip;
public class Bullet
{
int x, y;
Image img;
boolean visible;
public Bullet(int startX, int startY)
{
x = startX;
y = startY;
ImageIcon newBullet = new ImageIcon("images/bullet.gif");
img = newBullet.getImage();
visible = true;
}
public Rectangle getBounds()
{
return new Rectangle(x, y, 9, 5);
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
public Image getImg()
{
return img;
}
public boolean isVisible()
{
return visible;
}
public void move()
{
x = x + 2;
if(x > 700)
{
visible = false;
}
}
public void setVisible(boolean isVisible)
{
visible = isVisible;
}
}
Player
package ShooterGame;
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.ImageIcon;
public class Player
{
int x, dx, y, dy, nx2, nx, edge, ceiling;
Image player;
ImageIcon ib = new ImageIcon("images/player1back.gif");
ImageIcon i = new ImageIcon("images/playerstill.gif");
ImageIcon f = new ImageIcon("images/playerforward.gif");
ImageIcon up = new ImageIcon("images/playerup.gif");
ImageIcon down = new ImageIcon("images/playerdown.gif");
public AudioClip laser;
static ArrayList<Bullet> bullets;
public Player()
{laser = Applet.newAudioClip(getClass().getResource("laser.wav"));
player = ib.getImage();
x = 75;
nx = 0;
nx2 = 685;
y = 172;
edge = 150;
ceiling = 0;
bullets = new ArrayList<Bullet>();
}
public static ArrayList<Bullet> getBullets()
{
return bullets;
}
public void fire()
{
Bullet z = new Bullet((edge + 60), (y+17));
bullets.add(z);
}
public Rectangle getBounds()
{
return new Rectangle(edge, y, 43, 39);
}
public void move()
{
y = y + dy;
if(y < ceiling)
{
y = ceiling;
}
if(y > 290)
{
y = 290;
}
if(dx != -1)
{
if(edge + dx <= 151)
{
edge = edge + dx;
}
else
{
x = x + dx;
nx2 = nx2 + dx;
nx = nx + dx;
}
}
else
{
if(edge + dx > 0)
{
edge = edge + dx;
}
}
}
public int getX()
{
return x;
}
public int getdx()
{
return dx;
}
public int getY()
{
return y;
}
public Image getImage()
{
return player;
}
public void keyPressed(KeyEvent e)
{
int key = e.getKeyCode();
if(key == KeyEvent.VK_RIGHT)
{
dx = 2;
player = f.getImage();
}
if(key == KeyEvent.VK_UP)
{
dy = -1;
player = up.getImage();
}
if(key == KeyEvent.VK_DOWN)
{
dy = 1;
player = down.getImage();
}
if(key == KeyEvent.VK_SPACE)
{
fire();
laser.play();
}
}
public void keyReleased(KeyEvent e)
{
int key = e.getKeyCode();
if(key == KeyEvent.VK_RIGHT)
{
dx = 1;
player = ib.getImage();
}
if(key == KeyEvent.VK_UP)
{
dy = 0;
player = ib.getImage();
}
if(key == KeyEvent.VK_DOWN)
{
dy = 0;
player = ib.getImage();
}
}
}
Frame
package ShooterGame;
import javax.swing.*;
public class Frame
{
public AudioClip theme;
public Frame()
{
JFrame frame = new JFrame();
frame.add(new Board());
frame.setTitle("SideShooter");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(700,365);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}
public static void main(String[] args)
{
new Frame();
}
}
Ok, so the problem is the line mentioned in the other answer, but I believe it is that all the enemies may not be initialised before it checks collisions. Because you are making 10000 of them to start with, I think your action performed method may be checking collisions before they have all be created.
One thing to try could be to bring down the amount of enemies you have and see if it still keeps happening, try 100 or 1000, but this still won't fix the issue.
You really want to be change your game to run in it's own loop though, at the moment you are only checking collisions when the player performs an action. so if the player stops moving, no collision detection...
I would suggest that you find a book called 'Killer Game Programming in Java', there are free ebook version, and just read the first 2 chapters about making a game loop. The book is a bit old, but the basics of the loop are very good.
This question here also contains a very simple loop, and some suggestions in the comments about how to make it better.
The error is on the line
rect[i] = e.getBounds();
Are you not initializing the bounds of your Enemy class correctly? Alternatively, the Enemy you pulled out of the array could be null.
I'm new to programming and I have some issues on how to control my animation's speed. And I hope that you can give me some tips for this code.
public class Maze extends Canvas {
Map map;
Mario mario;
private Timer time;
private BufferStrategy strategy;
private int move;
boolean gameRunning = true;
public Maze(){
map = new Map();
mario = new Mario();
JFrame frame = new JFrame();
frame.setTitle("SuperMario2D");
JPanel panel = (JPanel) frame.getContentPane();
panel.setPreferredSize(new Dimension(438, 438));
panel.setLayout(null);
setBounds(0, 0, 454, 476);
panel.add(this);
setIgnoreRepaint(true);
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
addKeyListener(new KeyHandler());
requestFocus();
createBufferStrategy(2);
strategy = getBufferStrategy();
}
public void gameLoop() {
long lastLoopTime = System.currentTimeMillis();
while (gameRunning) {
// work out how long its been since the last update, this
// will be used to calculate how far the entities should
// move this loop
long delta = System.currentTimeMillis() - lastLoopTime;
lastLoopTime = System.currentTimeMillis();
Graphics2D g = (Graphics2D) strategy.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillRect(0,0,800,600);
map.draw(g);
mario.draw(g, move);
g.dispose();
strategy.show();
}
try {
Thread.sleep(10);
} catch (Exception e) {}
}
public class KeyHandler extends KeyAdapter{
public void keyPressed(KeyEvent e){
int keycode = e.getKeyCode();
if(keycode == KeyEvent.VK_UP){
mario.move(0, -1); //if it's not equal this will not execute because Y-1 will equal to w
move = 1;
System.out.println("You press up");
}
if(keycode == KeyEvent.VK_DOWN){
mario.move(0, 1);
move = 2;
System.out.println("You press down");
}
if(keycode == KeyEvent.VK_LEFT){
mario.move(-1, 0);
move = 3;
System.out.println("You press left");
}
if(keycode == KeyEvent.VK_RIGHT){
mario.move(1, 0);
move = 4;
System.out.println("You press right");
}
}
public void keyReleased(KeyEvent e){
int keycode = e.getKeyCode();
if(keycode == KeyEvent.VK_UP){
move = 5;
System.out.println("You released up");
}
if(keycode == KeyEvent.VK_DOWN){
move = 6;
System.out.println("You released down");
}
if(keycode == KeyEvent.VK_LEFT){
move = 7;
System.out.println("You released down");
}
if(keycode == KeyEvent.VK_RIGHT){
move = 8;
System.out.println("You released down");
}
}
public void keyTyped(KeyEvent e){
}
}
public static void main(String[] args){
Maze maze = new Maze();
maze.gameLoop();
}
}
here is the code that loads my animated images
public class Mario {
private int x, y;
private int tileX, tileY; //for collision
//private Image player;
private Image[] playerDown = new Image[3];
private Image[] playerUp = new Image[3];
private Image[] playerLeft = new Image[3];
private Image[] playerRight = new Image[3];
private Image[] playerJumpD = new Image[3];
private Image[] playerJumpU = new Image[3];
private Image[] playerJumpL = new Image[3];
private Image[] playerJumpR = new Image[3];
private int cycle = 0;
private long scene1 = 0;
private long scene2 = 500;
public Mario(){
moveDown();
moveUp();
moveLeft();
moveRight();
/*
//jump
jumpDown();
jumpUp();
jumpLeft();
jumpRight();
*/
tileX = 1;
tileY = 1;
}
public void moveDown(){
playerDown[0] = new ImageIcon("images/marioFW1.png").getImage();
playerDown[1] = new ImageIcon("images/marioFW2.png").getImage();
playerDown[2] = new ImageIcon("images/marioFW3.png").getImage();
}
public void moveUp(){
playerUp[0] = new ImageIcon("images/marioB1.png").getImage();
playerUp[1] = new ImageIcon("images/marioB2.png").getImage();
playerUp[2] = new ImageIcon("images/marioB3.png").getImage();
}
public void moveLeft(){
playerLeft[0] = new ImageIcon("images/marioJW1.png").getImage();
playerLeft[1] = new ImageIcon("images/marioJW2.png").getImage();
playerLeft[2] = new ImageIcon("images/marioJW3.png").getImage();
}
public void moveRight(){
playerRight[0] = new ImageIcon("images/marioR1.png").getImage();
playerRight[1] = new ImageIcon("images/marioR2.png").getImage();
playerRight[2] = new ImageIcon("images/marioR3.png").getImage();
}
/*
//jump
public void jumpDown(){
playerJumpD[0] = new ImageIcon("images/marioFJ1.png").getImage();
playerJumpD[1] = new ImageIcon("images/marioFJ2.png").getImage();
playerJumpD[2] = new ImageIcon("images/marioFJ3.png").getImage();
}
public void jumpUp(){
playerJumpU[0] = new ImageIcon("images/marioBJ1.png").getImage();
playerJumpU[1] = new ImageIcon("images/marioBJ2.png").getImage();
playerJumpU[2] = new ImageIcon("images/marioBJ3.png").getImage();
}
public void jumpLeft(){
playerJumpL[0] = new ImageIcon("images/marioJL1.png").getImage();
playerJumpL[1] = new ImageIcon("images/marioJL2.png").getImage();
playerJumpL[2] = new ImageIcon("images/marioJL3.png").getImage();
}
public void jumpRight(){
playerJumpR[0] = new ImageIcon("images/marioRJ1.png").getImage();
playerJumpR[1] = new ImageIcon("images/marioRJ2.png").getImage();
playerJumpR[2] = new ImageIcon("images/marioRJ3.png").getImage();
}
*/
public void move(int dx, int dy){
// x += dx;
// y += dy;
tileX += dx;
tileY += dy;
}
public Image getMoveDown(){
if(cycle == playerDown.length){
cycle = 0;
}
return playerDown[cycle++];
}
public Image getMoveUp(){
if(cycle == playerUp.length){
cycle = 0;
}
return playerUp[cycle++];
}
public Image getMoveLeft(){
if(cycle == playerLeft.length){
cycle = 0;
}
return playerLeft[cycle++];
}
public Image getMoveRight(){
if(cycle == playerRight.length){
cycle = 0;
}
return playerRight[cycle++];
}
/*
//jump
public Image getJumpD(){
if(cycle == playerJumpR.length){
cycle = 0;
}
return playerJumpR[cycle++];
}
public Image getJumpU(){
if(cycle == playerJumpU.length){
cycle = 0;
}
return playerJumpU[cycle++];
}
public Image getJumpL(){
if(cycle == playerJumpL.length){
cycle = 0;
}
return playerJumpL[cycle++];
}
public Image getJumpR(){
if(cycle == playerJumpR.length){
cycle = 0;
}
return playerJumpR[cycle++];
}
*/
/*
public void checkMove(){
if (System.currentTimeMillis() - scene1 < scene2) {
return;
}
scene1 = System.currentTimeMillis();
}
*/
public int getTileX(){
return tileX;
}
public int getTileY(){
return tileY;
}
public void draw(Graphics g, int move) {
if(move == 0)
g.drawImage(playerDown[1], getTileX(), getTileY(), null );
if(move == 1)
g.drawImage(getMoveUp(), getTileX(), getTileY(), null );
if(move == 2)
g.drawImage(getMoveDown(), getTileX(), getTileY(), null );
if(move == 3)
g.drawImage(getMoveLeft(), getTileX(), getTileY(), null );
if(move == 4)
g.drawImage(getMoveRight(), getTileX(), getTileY(), null );
if(move == 5)
g.drawImage(playerUp[1], getTileX(), getTileY(), null );
if(move == 6)
g.drawImage(playerDown[1], getTileX(), getTileY(), null );
if(move == 7)
g.drawImage(playerLeft[1], getTileX(), getTileY(), null );
if(move == 8)
g.drawImage(playerRight[1], getTileX(), getTileY(), null );
}
}
This is where the map was successfully loaded. I'm not sure how i was able to make i run in accelerated graphics mode.
public class Map {
private Scanner m;
private String[] Map = new String[14]; //how many tiles in the map
private Image tiles, grass2, grass3, grass3b;
private Image wall, sand1;
private Image finish;
public Map(){
tiles = new ImageIcon("images/grass2.png").getImage();
wall = new ImageIcon("images/grass1.png").getImage();
grass2 = new ImageIcon("images/grass2.png").getImage();
grass3 = new ImageIcon("images/grass3.png").getImage();
grass3b = new ImageIcon("images/grass3b.png").getImage();
sand1 = new ImageIcon("images/sand1.png").getImage();
finish = new ImageIcon("images/tile.png").getImage();
openFile();
readFile();
closeFile();
}
public void openFile(){
try{
m = new Scanner(new File("images/Map.txt"));
}catch(Exception e){
System.out.println("Can't open the file: "+e);
}
}
public void readFile(){
while(m.hasNext()){ // read through the file
for(int i = 0; i < 14; i++){
Map[i] = m.next();
}
}
}
public void closeFile(){
m.close();
}
public String getMap(int x, int y){
String index = Map[y].substring(x, x + 1);
return index;
}
public Image getTiles(){
return tiles;
}
public Image getWall(){
return wall;
}
public Image getFinish(){
return finish;
}
public Image getImageGrass2(){
return grass2;
}
public Image getImageGrass3(){
return grass3;
}
public Image getImageGrass3b(){
return grass3b;
}
public Image getImageSand1(){
return sand1;
}
//added
public void draw(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
for(int y = 0; y < 14; y++){
for(int x = 0; x < 14; x++){
/**draw the finish line**/
if(getMap(x, y).equals("f")){
g2.drawImage(getFinish(), x*32,y*32, null);
}
/**-----------------------)*/
if(getMap(x, y).equals("g")){
//the size of the image is X 20 by Y20
g2.drawImage(getTiles(), x*32, y*32, null);
}
if(getMap(x, y).equals("w")){
//the size of the image is X 20 by Y20
g2.drawImage(getWall(), x*32, y*32, null);
}
if(getMap(x, y).equals("d")){
//the size of the image is X 20 by Y20
g2.drawImage(getImageGrass3(), x*32, y*32, null);
}
if(getMap(x, y).equals("b")){
//the size of the image is X 20 by Y20
g2.drawImage(getImageGrass3b(), x*32, y*32, null);
}
if(getMap(x, y).equals("s")){
//the size of the image is X 20 by Y20
g2.drawImage(getImageSand1(), x*32, y*32, null);
}
}
}
}
}