I'm trying to recreate a DigDug game in Java for my computer science class.
As I'm just a beginner, I'm only going to have the monsters move up and then back down, instead of chasing the player. I'm having difficulties making the monsters continuously move though. It will go up, but it will not go back down, and it doesn't repeat.
Previously it would just immediately fly off the screen if the player reached the point, or it wouldn't move at all. I have tried a for-loop, a while-loop and a do-while loop. I also tried a delay but it stopped my entire program. The goal is to make all of the monsters move up and down when the player reaches a certain point (340, 270).
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.awt.Font;
import java.awt.event.*;
import javax.swing.Timer;
import java.util.ArrayList;
import java.awt.event.KeyAdapter;
public class DigDug extends Applet implements MouseMotionListener, MouseListener, KeyListener
{
private final Color c_background = new Color(32, 73, 150);
private final Color c_first = new Color(230, 185, 9);
private final Color c_second = new Color(224, 128, 18);
private final Color c_third = new Color(232, 61, 14);
private final Color c_last = new Color(184, 0, 0);
private final Color c_score = new Color(232, 42, 96);
public boolean ifEntered = false;
public boolean isMoving1 = false;
private int count = 0;
private int otherCount = 0;
private Image flower;
private Image diggy;
private Image enemies1;
private Image enemies2;
private Image enemies3;
private Image arrowUp;
private Image arrowDown;
private Image arrowLeft;
private Image arrowRight;
//private ArrayList<Point> enemies = new ArrayList<Point>();
Font myFont = new Font("SansSerif",Font.BOLD, 16);
private Timer timer;
private Point Up;
private int digx = 685;
private int digy = 45;
private int e1x = 76;
private int e1y = 210; //i created a variable that would hold the enemies's values
private int e2x = 465;
private int e2y = 342;
private int e3x = 546;
private int e3y = 127;
private boolean ifW = false;
private boolean ifA = false;
private boolean ifS = false;
private boolean ifD = false;
private boolean yaas = false;
private int arrowX = digx+5;
private int arrowY = digy+5;
private ArrayList<Integer> xpts = new ArrayList<Integer>();
private ArrayList<Integer> ypts = new ArrayList<Integer>();
public void init()
{
diggy = getImage(getDocumentBase(), "Dig_Dug.png");
flower = getImage(getDocumentBase(), "flower.gif");
enemies1 = getImage(getDocumentBase(), "Pooka.png");
enemies2 = getImage(getDocumentBase(), "Fygar.gif");
enemies3 = getImage(getDocumentBase(), "Pooka.png");
arrowUp = getImage(getDocumentBase(), "ArrowUp.png");
arrowDown = getImage(getDocumentBase(), "ArrowDown.png");
arrowRight = getImage(getDocumentBase(), "Arrow-Point-Right.png");
arrowLeft = getImage(getDocumentBase(), "ArrowLeft copy.png");
setBackground(c_background);
setSize(700,500);
addMouseMotionListener(this);
addMouseListener(this);
setFont(myFont);
addKeyListener(this);
Up = new Point(digx, digy);
}
public void paint(Graphics g)
{
score(g);
background(g);
g.setColor(Color.white);
//g.fillRect(player.x, player.y, 10, 10);
if(ifEntered)
{
if(digx > 330)
digx--;
else if(digy < 247)
digy++;
repaint();
}
if(digx == 330 && digy == 247)
{
yaas = true; //checks if the player has reached spot
//(random variable i created
}
if(yaas == true) //this if statement is where i am having the problem
{
//int count = 0;
//int count = 0;
boolean isUp = false;
for(int i = 0; i < count; i++)
{
if(e1y == 210)
{
while(e1y != 120)
{
e1y--;
}
isUp = true;
}
if(e1y == 120 && isUp == true)
{
while(e1y != 210)
{
e1y++;
}
isUp = false;
}
count++;
}
}
g.drawImage(diggy, digx, digy, 20, 20, null);
g.drawImage(flower, 680, 41, 20, 20, null);
g.drawImage(enemies1, e1x, e1y, 20, 20, null);
g.drawImage(enemies2, e2x, e2y, 20, 20, null);
g.drawImage(enemies3, e3x, e3y, 20, 20, null);
if(digy > e1y && digy < (e1y+20) && digx > e1x && digx < (e1x+20) ||e1y == digy || e1x == digx )
{
background(g);
g.setColor(Color.white);
g.drawString("GAME OVER", 294, 260);
// repaint();
}
if(digy > e2y && digy < (e2y+20) && digx > e2x && digx < (e2x+20)||e2y == digy || e2x == digx )
{
background(g);
g.setColor(Color.white);
g.drawString("GAME OVER", 294, 260);
// repaint();
}
if(digy > e3y && digy < (e3y+20) && digx > e3x && digx < (e3x+20) || e3y == digy && e3x == digx)
{
background(g);
g.setColor(Color.white);
g.drawString("GAME OVER", 294, 260);
// repaint();
}
}
public void score(Graphics g)
{
g.setColor(c_score);
g.drawString("1UP", 101, 21);
g.drawString("HIGH SCORE", 271, 21);
g.setColor(Color.white);
g.drawString(" " + count, 118, 35);
g.drawString(" " + count, 317, 35);
}
public void background(Graphics g)
{
g.setColor(c_first);
g.drawRect(0,65, 700, 120);
g.fillRect(0, 65, 700, 120);
g.setColor(c_second);
g.drawRect(0,166, 700, 120);
g.fillRect(0,166, 700, 120);
g.setColor(c_third);
g.drawRect(0, 267, 700, 120);
g.fillRect(0, 267, 700, 120);
g.setColor(c_last);
g.drawRect(0, 388, 700, 120);
g.fillRect(0, 388, 700, 120);
}
First, you will need an understanding of Painting in AWT and Swing and Concurrency in Java. I would also discourage the use of Applet, applets have there own bunch of issues which you probably don't need to deal with right now.
The paint method is not the place to update the state of your UI, the paint method should just paint the current state. You should also not change the state of the UI from within the paint method, this could cause no end of issues
To start with, you need some kind of "game loop", this loop is responsible for updating the state of the game and scheduling the updates to the UI
In the main loop, we maintain a movement "delta", this describes the amount of change that a particular object has and in what direction, in this example, I'm only dealing with enemies1, but you can imagine anything that moves will need it's own as well.
On each cycle of the game loop, we apply the delta to the objects current position, do a bounds check and invert the delta as required...
e1y += moveDelta;
if (e1y >= 210) {
e1y = 209;
moveDelta *= -1;
} else if (e1y <= 120) {
e1y = 121;
moveDelta *= -1;
}
The mainLoop below should probably go in the init or start method, depending on if you can work out how to "pause" the Thread
Thread mainLoop = new Thread(new Runnable() {
#Override
public void run() {
int moveDelta = -1;
gameOver = false;
while (!gameOver) {
if (ifEntered) {
if (digx > 330) {
digx--;
} else if (digy < 247) {
digy++;
}
repaint();
}
// Removed some code here for testing
e1y += moveDelta;
if (e1y >= 210) {
e1y = 209;
moveDelta *= -1;
} else if (e1y <= 120) {
e1y = 121;
moveDelta *= -1;
}
if (digy > e1y && digy < (e1y + 20) && digx > e1x && digx < (e1x + 20) || e1y == digy || e1x == digx) {
gameOver = true;
} else if (digy > e2y && digy < (e2y + 20) && digx > e2x && digx < (e2x + 20) || e2y == digy || e2x == digx) {
gameOver = true;
} else if (digy > e3y && digy < (e3y + 20) && digx > e3x && digx < (e3x + 20) || e3y == digy && e3x == digx) {
gameOver = true;
}
try {
Thread.sleep(40);
} catch (InterruptedException ex) {
}
repaint();
}
}
});
mainLoop.start();
You then need to replace the paint method with code that only paints the current state of the game
#Override
public void paint(Graphics g) {
super.paint(g);
score(g);
background(g);
g.setColor(Color.white);
//g.fillRect(player.x, player.y, 10, 10);
if (gameOver) {
g.setColor(Color.white);
g.drawString("GAME OVER", 294, 260);
} else {
g.drawImage(diggy, digx, digy, 20, 20, null);
g.drawImage(flower, 680, 41, 20, 20, null);
g.drawImage(enemies1, e1x, e1y, 20, 20, null);
g.drawImage(enemies2, e2x, e2y, 20, 20, null);
g.drawImage(enemies3, e3x, e3y, 20, 20, null);
}
}
Now, I'd recommend that you dump Applet in favour of a JPanel (for the core logic) and a JFrame (for displaying) and a Swing Timer instead of the Thread. You get double buffering for free to start with
Related
I am currently working on creating a game with Java and I wanted to create a hover effect. Whenever the mouse is hovering over a rectangle that i created in the Gui i wanted a boolean to be set to true or false. I am not sure what i did wrong. Here is my code:
package com.tutorial.main;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;
import com.tutorial.main.Game.STATE;
public class Shop extends MouseAdapter{
private Game game;
private Handler handler;
private Random r = new Random();
private HUD hud;
private boolean enough_maxhealth = true;
private boolean enough_speed = true;
private boolean enough_frozen = true;
private boolean enough_blast = true;
private boolean health_info = false;
private boolean speed_info = false;
private boolean freeze_info = false;
private boolean blast_info = false;
//static to show other classes what is upgraded, can be implemented so it won't have to in future
public static int[] upgrades = {0,0,3,0};
private static int[] prices = {1,2,1,5};
//way program is built, coin has to be static
public static int COIN = 0;
private int shop_timer = 0;
//check if this is needed
private int timer_frozen_upgrade = 100;
public Shop(Game game, Handler handler, HUD hud){
this.game = game;
this.handler = handler;
this.hud = hud;
}
public void mousePressed(MouseEvent e){
int mx = e.getX();
int my = e.getY();
}
public void mouseReleased(MouseEvent e){
int mx = e.getX();
int my = e.getY();
//Shop buttons
if(game.gameState == STATE.Shop){
//back button
if(mouseOver(mx, my, 210, 350, 200, 64)){
game.gameState = STATE.Game;
return;
}
//health upgrade
if(mouseOver(mx, my, 80, 110, 150, 50)){
// Cost 1 coins for + 10 health
if (COIN >= prices[0]){
//checks if maxed, 3 is the max
if (upgrades[0] < 3){
//updates upgrades
upgrades[0] += 1;
//adds 10 health to players max health
HUD.MAX_HEALTH += 10;
COIN -= prices[0];
}
}else{
//set a message to be shown for 40 ticks
shop_timer = 40;
//signifies that you don't have enough
enough_maxhealth = false;
}
}
//back button
if(mouseOver(mx, my, 230, 380, 200, 64)){
game.gameState = STATE.Game;
}
//speed upgrade
if(mouseOver(mx, my, 80, 200, 150, 50)){
if(COIN >= prices[1]){
if(upgrades[1] < 3){
for(int i = 0; i < handler.object.size(); i++){
GameObject tempObject = handler.object.get(i);
if(tempObject.getId() == ID.Player){
//increases player default Vx and Vy by 108%
tempObject.setVx_Default(tempObject.getVx_Default() * 1.08f);
tempObject.setVy_Default(tempObject.getVy_Default() * 1.08f);
//costs 2 coins
COIN -= prices[1];
upgrades[1] += 1;
}
}
}
}else{
//set a message to be shown for 40 ticks
shop_timer = 40;
enough_speed = false;
}
}
//Freeze enemies
/*
if(mouseOver(mx, mx, Game.WIDTH - 230, 110, 150, 50)){
System.out.println("Pressed buy");
if(COIN >= 2){
if(upgrades[2] < 3){
upgrades[2] += 1;
System.out.println("Bought frozen");
}
}
}*/
//freeze
if(mouseOver(mx, my, Game.WIDTH - 230, 110, 150, 50)){
if(COIN >= prices[2]){
//if(upgrades[2] < 3){
for(int i = 0; i < handler.object.size(); i++){
GameObject tempObject = handler.object.get(i);
if(tempObject.getId() == ID.Player){
//increases player default Vx and Vy by 108%
COIN -= prices[2];
upgrades[2] += 1;
}
//}
}
}else{
//set a message to be shown for 40 ticks
shop_timer = 40;
enough_frozen = false;
}
}
//blast
if(mouseOver(mx, my, Game.WIDTH - 230, 200, 150, 50)){
if(COIN >= prices[3]){
if(upgrades[3] < 2){
for(int i = 0; i < handler.object.size(); i++){
GameObject tempObject = handler.object.get(i);
if(tempObject.getId() == ID.Player){
//increases player default Vx and Vy by 108%
COIN -= prices[3];
upgrades[3] += 1;
}
}
}
}else{
//set a message to be shown for 40 ticks
shop_timer = 40;
enough_blast = false;
}
}
}
}
//returns true or false depends of mouse is over certain cordinates
private boolean mouseOver(int mx, int my, int x, int y, int width, int height){
if(mx > x && mx < x + width){
if (my > y && my < y + height){
return true;
}else return false;
}else return false;
}
//checks if the mouse has entered one of the rectangles
public void mouseEntered(MouseEvent e){
int mx = e.getX();
int my = e.getY();
//Shop buttons
if(game.gameState == STATE.Shop){
//health box
if(mouseOver(mx, my, 80, 110, 150, 50)){
health_info = true;
}else{
health_info = false;
}
//speed box
if(mouseOver(mx, my, 80, 200, 150, 50)){
speed_info = true;
}else{
speed_info = false;
}
//freeze box
if(mouseOver(mx, my, 410, 110, 150, 50)){
freeze_info = true;
}
else freeze_info = false;
//blast box
if(mouseOver(mx, my, 410, 200, 150, 50)){
blast_info = true;
}else{
blast_info = false;
}
}
}
//checks if the mouse has exited one of the rectangles
public void mouseExited(MouseEvent e){
int mx = e.getX();
int my = e.getY();
//Shop buttons
if(game.gameState == STATE.Shop){
//health box
if(mouseOver(mx, my, 80, 110, 150, 50)){
health_info = false;
}else{
health_info = true;
}
//speed box
if(mouseOver(mx, my, 80, 200, 150, 50)){
speed_info = false;
}else{
speed_info = true;
}
//freeze box
if(mx > 110 && mx < 410){
if(my > 50 && my < 150){
freeze_info = false;
System.out.println("exit in");
}
else{
freeze_info = true;
System.out.println("exit left");
}
}
else{
freeze_info = true;
System.out.println("exit left");
}
//blast box
if(mouseOver(mx, my, 410, 200, 150, 50)){
blast_info = false;
}else{
blast_info = true;
}
}
}
public void tick(){
//reduces shop timer that shows message
if(shop_timer >= 0){
shop_timer--;
}
}
public void render(Graphics g){
//try to simplify/optimize
//Shop System
if(game.gameState == STATE.Shop){
//creates fonts for future reference
Font fnt = new Font("arial", 1, 50);
Font fnt2 = new Font("arial", 1, 20);
Font fnt3 = new Font("arial", 1, 17);
Font fnt4 = new Font("arial", 1, 11);
Font fnt5 = new Font("arial", 1, 9);
Font fnt6 = new Font("arial", 1, 40);
g.setColor(Color.black);
g.fillRect(0, 0, Game.WIDTH, Game.HEIGHT);
g.setColor(Color.gray);
g.setFont(fnt);
g.drawString("Shop", 250, 50);
//Displays Health
g.setColor(Color.gray);
g.fillRect(15, 15, 200, 32);
g.setColor(new Color(75, (int) HUD.greenValue, 0));
g.fillRect(15,15, (int) HUD.HEALTH * 2, 32);
g.setColor(Color.white);
g.drawRect(15, 15, 200, 32);
g.setFont(fnt2);
g.setColor(Color.white);
//Health upgrade
g.drawRect(80, 110, 150, 50);
g.drawString("Max Health", 90, 140);
g.setColor(Color.gray);
if(upgrades[0] >= 1){
g.setColor(Color.green);
}
g.fillRect(82, 170, 44, 14);
if(upgrades[0] >= 2){
g.setColor(Color.green);
}else{
g.setColor(Color.gray);
}
g.fillRect(134, 170, 44, 14);
if(upgrades[0] >= 3){
g.setColor(Color.green);
}else{
g.setColor(Color.gray);
}
g.fillRect(186, 170, 44, 14);
//Speed upgrade
g.setColor(Color.white);
g.drawRect(80, 200, 150, 50);
g.setColor(Color.gray);
if(upgrades[1] >= 1){
g.setColor(Color.green);
}
g.fillRect(82, 260, 44, 16);
if(upgrades[1] >= 2){
g.setColor(Color.green);
}else{
g.setColor(Color.gray);
}
g.fillRect(134, 260, 44, 16);
if(upgrades[1] >= 3){
g.setColor(Color.green);
}else{
g.setColor(Color.gray);
}
g.fillRect(186, 260, 44, 16);
g.setColor(Color.white);
g.setFont(fnt3);
g.drawString("Speed Upgrade", 82, 230);
//freeze enemy effect
g.drawRect(Game.WIDTH - 230, 110, 150, 50);
g.setColor(Color.white);
g.setFont(fnt3);
g.drawString("Freze Enemy", Game.WIDTH - 215, 140);
g.setFont(fnt4);
if(freeze_info){
g.drawString("Press 'f' to slow enemies", Game.WIDTH - 230, 173 );
g.drawString("(Can only be used once)", Game.WIDTH - 228, 185);
}
g.setFont(fnt6);
g.setColor(Color.red);
g.drawString("" + upgrades[2], 590, 150);
//blast for some odd ticks
g.setColor(Color.white);
g.drawRect(Game.WIDTH - 230, 200, 150, 50);
//g.setColor(Color.gray);
//g.fillRect(80, 210, 33, 10);
g.setFont(fnt2);
g.drawString("Blast", Game.WIDTH - 190, 230);
g.setFont(fnt4);
g.drawString("Press 'ctrl' for Imunity", Game.WIDTH - 230, 263 );
g.drawString("(Can only be used once)", Game.WIDTH - 228, 278);
g.setFont(fnt6);
g.setColor(Color.red);
g.drawString("" + upgrades[3], 590, 240);
g.setFont(fnt);
//back button
g.setColor(Color.white);
g.drawRect(230, 380, 200, 64);
g.drawString("Back", 260, 430);
if(!enough_maxhealth || !enough_speed || !enough_frozen || !enough_blast){
if(shop_timer > 0){
System.out.println(shop_timer);
g.setFont(fnt2);
g.setColor(Color.white);
if(!enough_maxhealth){
g.drawString("You need " + (prices[0] - COIN) + " coins more", 190, 90);
}else if(!enough_speed){
g.drawString("You need " + (prices[1] - COIN) + " coins more", 190, 90);
}else if(!enough_frozen){
g.drawString("You need " + (prices[2] - COIN) + " coins more", 190, 90);
}else if(!enough_blast){
g.drawString("You need " + (prices[3] - COIN) + " coins more", 190, 90);
}
}else{
enough_maxhealth = true;
enough_speed = true;
enough_frozen = true;
enough_blast = true;
}
}
}
}
}
I tried to change some things with the freeze to see if it would effect the way it worked, but it still isn't properly working. The boolean for freeze is set to true in MouseExit whenever i leave the GUI, but i cannot make it correspond to the rectangle.
The class Rectangle2D has methods for testing collisions with other rectangles and/or a single point.
Tests if the specified coordinates are inside the boundary of the
Shape
contains(double x, double y)
and
Tests if the interior of the Shape entirely contains the specified
rectangular area.
contains(double x, double y, double w, double h)
I'd suggest refactoring your code to use these instead, and write some unit tests if you don't have any to prove it works.
Extend from this class to inherit the functionality for your objects
******************** EDITS ********************
class SomeObjectToRepresent extends Rectangle2D {
#override
public boolean contains(x, y){
boolean b = super.contains(x, y);
// change the state based on b
}
}
Something like the above but not exactly, just trying to point you in the right direction.
As for mouse events I would recommend using the MouseMotionListener
instead and use mouseMoved event and check your components, set their state based on whether the mouse is within bounds of your component by updating a list of components in your application. A component manager can do this or your JFrame can whenever a mouse event is obtained.
It's more brutish to do this but it's very easy to implement and I doubt you'll have many components.
Since every time the mouse moves that list will be updated or at least touched on.
I'm trying to find out where this was but you may need to add your mouse listener twice, one for motion and another for just the original. I know that sounds strange but I vaguely remember this being a problem for me too when events were not firing.
Rectangle2D
Currently I'm studying Computer Science and my teacher want me to make a snake game with array.
I have this code that is exactly same as my friend's but it only grow one body length and won't grow longer and after it eats the food it starts to slow down the speed of moving snake. I'm not sure where I went wrong please help. Thank you.
Here's the code:
public class Main extends JPanel implements KeyListener, ActionListener {
private static final long serialVersionUID = 1L;
static int dir;
static int i;
static int x[] = new int[200]; // Decleare Array of snake on x coordinate
static int y[] = new int[200]; // Decleare Array of snake on y coordinate
static int taillength = 1;
static int sxinc = 20, syinc = 20; // Speed of moving snake
static int fx = 100, fy = 100; // Declare the position of where food at
static int f2x = 300, f2y = 300; // Declare the position of where food2 at
static int fmx = 300, fmy = 100; // Declare the position of where food3 at
static int score = 0; // Create Score Counter
static int width = 745, height = 489; // Declare the size of JPanel
static int nsx, nsy; // The new value of the snake movement
static int csx = 20, csy = 20; // The value to add/minus on the number to
static BufferedImage background = null;
static JFrame f;
static JFrame g;
public Main() {
addKeyListener(this);
}
public void addNotify() {
super.addNotify();
requestFocus();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background, 0, 0, width, height, this);
g.setColor(Color.GREEN);
g.fillRect(fx, fy, 20, 20);
g.setFont(new Font("Times New Roman", Font.BOLD, 15));
g.setColor(Color.GREEN);
g.drawString("GREEN - Add 1 body length, add 1 score", 0, 429);
g.setColor(Color.BLUE);
g.fillRect(f2x, f2y, 20, 20);
g.setFont(new Font("Times New Roman", Font.BOLD, 15));
g.setColor(Color.BLUE);
g.drawString("BLUE - Add 2 body length, add 2 score", 0, 444);
g.setColor(Color.CYAN);
g.fillRect(fmx, fmy, 20, 20);
g.setFont(new Font("Times New Roman", Font.BOLD, 15));
g.setColor(Color.CYAN);
g.drawString("CYAN - Minus 1 body length, add 1 score", 0, 459);
g.setColor(Color.RED);
for (int j = 0; j < x.length && j < taillength; j++) {
g.fillRect(x[j], y[j], 20, 20);
g.setColor(Color.ORANGE);
}
g.fillRect(x[0], y[0], 20, 20);
g.setColor(Color.RED);
g.setFont(new Font("Times New Roman", Font.BOLD, 25));
g.setColor(Color.WHITE);
g.drawString("Score : " + score, 305, 459);
}
public void snakenew() {
for (int i = 0; i < x.length; i++) {
x[i] = 0;
y[i] = 0;
}
}
public static void main(String a[]) {
x[0] = 300;
y[0] = 220;
try { // Import Background
background = ImageIO.read(new File("H:/shutterstock_12730534.jpg"));
} catch (IOException e) {
}
Main p = new Main();
g = new JFrame();
g.add(p);
g.setSize(200, 300);
g.setVisible(true);
g.setResizable(false);
f = new JFrame();
f.add(p);
f.setSize(width, height);
f.setVisible(true);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Timer t = new Timer(60, p);
t.start();
}
public void actionPerformed(ActionEvent e) {
if ((x[0] + 20 > width) || (x[0] < 0) || (y[0] + 40 > height)
|| (y[0] < 0)) { // Game over when hit the wall
JOptionPane.showMessageDialog(null, "You hit the wall!", "Game",
JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
if ((taillength > 1) && (x[i] != x[0]) && (y[i] != y[0])) { // Game over
// when
// touch you
// snake
// body
if ((x[0] == x[i]) & (y[0] == y[i])) {
JOptionPane.showMessageDialog(null, "You ran into yourself!",
"Game", JOptionPane.INFORMATION_MESSAGE);
}
}
if (dir == KeyEvent.VK_UP) {
if (y[0] == y[taillength]) {
y[0] = y[0] - syinc;
}
}
else if (dir == KeyEvent.VK_DOWN) {
if (y[0] == y[taillength]) {
y[0] = y[0] + syinc;
}
}
else if (dir == KeyEvent.VK_LEFT) {
if (x[0] == x[taillength]) {
x[0] = x[0] - sxinc;
}
}
else if (dir == KeyEvent.VK_RIGHT) {
if (x[0] == x[taillength]) {
x[0] = x[0] + sxinc;
}
}
if (dir == KeyEvent.VK_K) {
if ((score > 6) && (taillength > 5)) {
taillength = taillength - 5;
score = score - 7;
}
}
if ((x[0] == fx) && (y[0] == fy)) { // Food Score and random food
fx = (int) (Math.random() * 37) * 20;
fy = (int) (Math.random() * 25) * 20;
taillength++;
score++;
}
if ((x[0] == f2x) && (y[0] == f2y)) {
f2x = (int) (Math.random() * 37) * 20;
f2y = (int) (Math.random() * 25) * 20;
taillength = taillength + 2;
score = score + 2;
}
if ((x[0] == fmx) && (y[0] == fmy)) {
if (taillength > 0) {
fmx = (int) (Math.random() * 37) * 20;
fy = (int) (Math.random() * 25) * 20;
taillength--;
score++;
}
}
for (i = taillength; i > 0; i--) {
x[i] = x[(i - 1)];
y[i] = y[(i - 1)];
}
f.repaint();
}
public void keyPressed(KeyEvent ke) {
dir = ke.getKeyCode();
}
public void keyReleased(KeyEvent arg0) {
}
public void keyTyped(KeyEvent arg0) {
}
}
A few things:
You are using a timer, but the item you are putting in the timer has no run() method... That's not how a timer works (please reference the last point as to why).
You are redrawing the whole screen every single time you tick. Not only is that ridiculous, it is most likely the cause of your aforementioned lag when you grow the body. Fixing this will ensure that you experience little to now lag between growth (although, you will still need to compensate at later growths by changing the speed of the snake; this, will also make the game more difficult as you go on, just like real Snake). This usage of the paint() method, can be attributed to the same reasoning as the last point.
You took someone elses code. Don't use code that doesn't belong to you--it might work, and you're fine, or you might have the same bug as the other guy, and now you've got a great time explaining why you have the copied code of some other student.
In conclusion: if you want to borrow code, never borrow code from someone who is in the same course as you. Finally, look up some examples of Snake games in Java. I'm sure you'll find some people who have experienced similar problems, from whom you might learn. I hope this helps you, and best of luck!
I am trying to make a Platformer game where you can run around and jump off the base of rectangles and off the sides of them.
I am compiling this in Processing 2.2.1. The program does not run. I am also looking for help on how to implement a jump and when to change the character's image.
speed = 0;
int numrects = 9;
Player player1 = new Player();
//Rectangle[] platforms = new Rectangle[16];
public static Rectangle[] platforms = new Rectangle[16];
class Player{
PImage[] images = new PImage[10];
int xMove, yMove, xSpeed, ySpeed, gravity, jumpheight, xSize, ySize;
boolean a = true;
boolean d = true;
boolean w = true;
int x, y;
int numFrames = 7; // The number of animation frames
int frame = 0; // The frame to display
PImage img;
Player (){
xSpeed = 10;
ySpeed = 10;
xSize = 24;
ySize = 51;
x = width/2;
y = height/2;
}
void jump() {
for (int x = 0; x <= jumpheight; x++){
y = y + gravity;
image(images[frame], x, y);
}
for (int x = 0; x <= jumpheight; x++){
y = y - gravity;
image(images[frame], x, y);
}
}
};
class Rectangle{
int x, y, xSize, ySize;
//.fill(127);
Rectangle(){
x = 1;
y = 1;
xSize = 10;
ySize = 10;
}
void build(int newx, int newy, int newxSize, int newySize){
x = newx;
y = newy;
xSize = newxSize;
ySize = newySize;
rect (x, y, xSize, ySize);
}
};
void setup() {
size(1920, 1080);
frameRate(30);
player1.images[0] = loadImage("Staticl.png");
player1.images[3] = loadImage("Staticr.png");
player1.images[1] = loadImage("step1left.png");
player1.images[4] = loadImage("step1right.png");
player1.images[2] = loadImage("step2left.png");
player1.images[5] = loadImage("step2right.png");
//images[3] = loadImage("1.jpg");
//images[7] = loadImage("2.jpg");
player1.xSpeed = 10;
player1.x = 500;
player1.y = 500;
platforms[0].build(0, 837, 1920, 244);
platforms[1].build(0, 765, 294, 23);
platforms[2].build(733, 725, 734, 39);
platforms[3].build(0, 765, 294, 23);
platforms[4].build(0, 765, 294, 23);
platforms[5].build(1306, 569, 161, 195);
platforms[6].build(558, 607, 653, 33);
platforms[7].build(0, 522, 496, 34);
platforms[8].build(477, 360, 173, 37);
platforms[9].build(690, 288, 445, 34);
platforms[10].build(1149, 174, 217, 40);
platforms[11].build(1390, 298, 243, 33);
platforms[12].build(1488, 490, 167, 30);
platforms[13].build(1690, 301, 138, 31);
platforms[14].build(1693, 426, 227, 27);
platforms[15].build(1866, 226, 54, 199);
}
void checkforcollision(){
for (int x = 0; x <= numrects; x++){
if (player1.x + player1.xSize == platforms[x].x && player1.y <= platforms[x].y + platforms[x].ySize && player1.y + player1.ySize >= platforms[x].y){
// right side of box hits left side of platform
player1.d = false;
player1.w = true;
}
else if(player1.x == platforms[x].x + platforms[x].xSize && player1.y <= platforms[x].y + platforms[x].ySize && player1.y + player1.ySize >= platforms[x].y){
// left side of box hits right side of platform
player1.a = false;
player1.w = true;
}
else if(player1.y + player1.ySize == platforms[x].y && player1.x <= platforms[x].x + platforms[x].xSize && player1.x + player1.xSize >= platforms[x].x){
// bottom of player hits top of box
player1.w = false;
}
else if(player1.y == platforms[x].y + platforms[x].ySize && player1.x <= platforms[x].x + platforms[x].xSize && player1.x + player1.xSize >= platforms[x].x){
// top of player hits bottom of box
player1.w = true;
player1.a = true;
player1.d = true;
}
else {
player1.w = false;
player1.a = true;
player1.d = true;
}
}
}
void draw() {
checkforcollision();
if (player1.d == true)
player1.x = player1.x + player1.xSpeed;
image(player1.images[player1.frame], player1.x, player1.y);
if (player1.a == true)
player1.x = player1.x - player1.xSpeed;
image(player1.images[player1.frame], player1.x, player1.y);
if (player1.w == true)
player1.jump();
//image(images[frame], player1.x, player1.y);
}
void keyPressed() {
if ((key == 'a') || (key == 'A')){
player1.a = true;
}
else if ((key == 'd') || (key == 'D')){
player1.d = true;
}
else if ((key == 'w') || (key == 'W')){
player1.w = true;
}
}
void keyReleased() {
if ((key == 'a') || (key == 'A')){
player1.a = false;
}
else if ((key == 'd') || (key == 'D')){
player1.d = false;
}
}
The NullPointerException is because you haven't initialized the Rectangles in the array yet. So this line causes an error:
platforms[0].build(0, 837, 1920, 244);
First, you need to run something like this:
for (int i=0; i<platforms.length; i++) {
platforms[i] = new Rectangle();
}
I am currently making an applet that simulates a Tortoise vs. Hare Race. They each have individual moves, picked at random. My applet works, but it only displays the end of the race in which the Tortoise Wins. I would like it to display the individual moves that the tortoise/hare make, almost like a gif.
heres my code:
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Color;
import java.awt.Font;
public class Project2 extends Applet
{
Image tortoise, hare;
int tortoiseXPos = 180, hareXPos = 180;
final int tortoiseYPos = 50, hareYPos = 400, SQUARE = 20;
int move;
public void init()
{
tortoise = getImage(getDocumentBase(), "tortoise.gif");
hare = getImage(getDocumentBase(), "hare.gif");
}
public void gameControl()
{
//1200 is finish line
while((tortoiseXPos < 1200) || (hareXPos < 1200))
{
move = (int)(Math.random() * 10);
tortoiseMoves(move);
hareMoves(move);
for(int i = 0; i < 10; i++)
{
delay();
}
}
}
public void paint(Graphics field)
{
drawField(field);
drawMove(field);
//Display winner when they get to the finish line
if(tortoiseXPos >= 1200)
{
field.setFont(new Font("Times New Roman", Font.ITALIC, 72));
field.drawString("Tortoise Wins", 650, 240);
}
else if(hareXPos >= 1200)
{
field.setFont(new Font("Times New Roman", Font.ITALIC, 72));
field.drawString("Tortoise Wins!!", 650, 240);
}
}
public void drawField(Graphics field)
{
setBackground(Color.green);
Font f = new Font("Times New Roman", Font.BOLD, 48);
field.setFont(f);
field.drawString("Tortoise", 0, 75);
field.drawString("Hare", 0, 425);
//fill alternating black and white rectangles
field.setColor(Color.black);
int x = 180;
for(int i = 0; i < 25; i++)
{
field.fillRect(x, 50, SQUARE, 50);
field.fillRect(x, 400, SQUARE, 50);
x += (SQUARE * 2);
}
field.setColor(Color.white);
x = 200;
for(int i = 0; i < 25; i++)
{
field.fillRect(x, 50, SQUARE, 50);
field.fillRect(x, 400, SQUARE, 50);
x += (SQUARE * 2);
}
}
public void clearMove(Graphics s)
{
}
public void drawMove(Graphics s)
{
gameControl();
s.drawImage(tortoise, tortoiseXPos, 50, this);
s.drawImage(hare, hareXPos, 400, this);
}
public void tortoiseMoves(int move)
{
//Moves for Tortoise
if(move <= 5)
{
tortoiseXPos += (3 * SQUARE);
}
else if(move <= 8)
{
tortoiseXPos += SQUARE;
}
else if(move <= 10)
{
tortoiseXPos -= (6 * SQUARE);
}
if(tortoiseXPos < 0)
{
tortoiseXPos = 0;
}
if(tortoiseXPos > 1200)
{
tortoiseXPos = 1200;
}
}
public void hareMoves(int move)
{
//Moves for Hare
if(move <= 2)
{
hareXPos += (9 * SQUARE);
}
if(move <= 5)
{
hareXPos += (SQUARE);
}
if(move <= 6)
{
hareXPos -= (SQUARE);
}
if(move <= 8)
{
hareXPos -= (2 * SQUARE);
}
if(move <= 10)
{
hareXPos = hareXPos;
}
if(hareXPos < 0)
{
hareXPos = 0;
}
if(hareXPos > 1200)
{
hareXPos = 1200;
}
}
public void delay()
{
//To see individual moves
for(int i = 0; i <= 90000000; i++)
{}
}
}
If you guys could give me some pointers on what method to use or how I should go about doing this, I'd appreciate it. Thanks
Add two arrays to your class and store each move for each racer. Then, "paint" the points for each racer on the screen as the race is progressing.
I have a set of sprites that I am calling in a Java game, and when I had 3 sprites it worked fine, but when I add a fourth sprite, the repaint method is only called every other time.
Here is my minimal example,
Main class:
public class Maze extends JPanel implements ActionListener{
/**
* #param args
*/
int stage;
int dir;
int x = 32;
int y = 32;
Rectangle r = new Rectangle(x,y,10,10);
Draw D = new Draw();
public static ArrayList<Rectangle> walls = new ArrayList<Rectangle>();
public ArrayList<Image> spritesl = new ArrayList<Image>();
public ArrayList<Image> spritesd = new ArrayList<Image>();
public ArrayList<Image> spritesr = new ArrayList<Image>();
public ArrayList<Image> spritesu = new ArrayList<Image>();
BufferedImage image;
public Maze() throws IOException{
setBackground(Color.black);
setSize(672,672);
Timer timer = new Timer(2000,this);
timer.addActionListener(this);
timer.start();
//add sprites
for(int i = 1; i<5; i += 1){
spritesl.add(image = ImageIO.read(new File("C:/Users/Dave/Desktop/Sprites/left" + i + ".png")));
}
for(int i = 1; i<5; i += 1){
spritesd.add(image = ImageIO.read(new File("C:/Users/Dave/Desktop/Sprites/down" + i + ".png")));
}
for(int i = 1; i<5; i += 1){
spritesr.add(image = ImageIO.read(new File("C:/Users/Dave/Desktop/Sprites/right" + i + ".png")));
}
for(int i = 1; i<5; i += 1){
spritesu.add(image = ImageIO.read(new File("C:/Users/Dave/Desktop/Sprites/up" + i + ".png")));
}
}
public static void main(String[] args) throws IOException {
JFrame frame = new JFrame();
Maze ate = new Maze();
frame.addKeyListener(new Input());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(ate);
frame.setPreferredSize(new Dimension(688, 709));//16, 37
frame.setVisible(true);
frame.pack();
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
//call wall drawer
g.setColor(Color.gray);
D.draw(g);
g.setColor(Color.red);
//set animation
if(dir == 1){
g.drawImage(spritesu.get(stage-1),x,y, this);
}else if(dir == 2){
g.drawImage(spritesr.get(stage-1),x,y, this);
}else if(dir == 3){
g.drawImage(spritesd.get(stage-1),x,y, this);
}else if(dir == 4){
g.drawImage(spritesl.get(stage-1),x,y, this);
}
System.out.println("set");
}
#Override
public void actionPerformed(ActionEvent e) {
boolean up =false;
boolean right =false;
boolean down =false;
boolean left =false;
//next part tests each direction for collisions
if(Input.right){
right = true;
x += 4;
if(x>672-32){
x -= 4;
right = false;
}else{
for(int i = 0; i < walls.size(); i += 1){
if(new Rectangle(x, y, 30, 30).intersects(walls.get(i))){
x -= 4;
right = false;
}
}
}
}
if(Input.left){
left = true;
dir=4;
x-=4;
if(x<0){
x += 4;
left = false;
}else{
for(int i = 0; i < walls.size(); i += 1){
if(new Rectangle(x, y, 32, 32).intersects(walls.get(i))){
x += 4;
left = false;
}
}
}
}
if(Input.down){
down = true;
dir=3;
y+=4;
if(y>672-32){
y -= 4;
down = false;
}else{
for(int i = 0; i < walls.size(); i += 1){
if(new Rectangle(x, y, 32, 32).intersects(walls.get(i))){
y -= 4;
down = false;
}
}
}
}
if(Input.up){
up = true;
dir=1;
y-=4;
if(y<0){
y += 4;
up = false;
}else{
for(int i = 0; i < walls.size(); i += 1){
if(new Rectangle(x, y, 32, 32).intersects(walls.get(i))){
y += 4;
up = false;
}
}
}
}
//sets direction of animation
if(left||down||right||up){
if(left){
dir = 4;
}
if(down){
dir = 3;
}
if(right){
dir = 2;
}
if(up){
dir = 1;
}
stage += 1;
if(stage >= 4 || stage <= 0){
stage = 1;
}
System.out.println(stage);
}
repaint();
}
}
My input tester(probably not necessary, but its needed for the game to run):
public class Input implements KeyListener {
public static boolean left = false;
public static boolean right = false;
public static boolean up = false;
public static boolean down = false;
public static boolean space = false;
//test for keys
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT)
left = true;
if (key == KeyEvent.VK_RIGHT)
right = true;
if (key == KeyEvent.VK_UP)
up = true;
if (key == KeyEvent.VK_DOWN)
down = true;
if (key == KeyEvent.VK_SPACE)
space = true;
}
#Override
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT)
left = false;
if (key == KeyEvent.VK_RIGHT)
right = false;
if (key == KeyEvent.VK_UP)
up = false;
if (key == KeyEvent.VK_DOWN)
down = false;
if (key == KeyEvent.VK_SPACE)
space = false;
}
#Override
public void keyTyped(KeyEvent e) {}
}
and my Draw class:
public class Draw {
public void draw(Graphics g){
//draw everything
Maze.walls.clear();
g.fillRect(0, 0, 672, 32);
g.fillRect(0, 0, 32, 672);
g.fillRect(0, 640, 320, 32);
g.fillRect(352, 640, 320, 32);
g.fillRect(640, 0, 32, 320);
g.fillRect(640, 352, 32, 320);
Maze.walls.add(new Rectangle(0, 0, 672, 32));
Maze.walls.add(new Rectangle(0, 0, 32, 672));
Maze.walls.add(new Rectangle(0, 640, 320, 32));
Maze.walls.add(new Rectangle(352, 640, 320, 32));
Maze.walls.add(new Rectangle(640, 0, 32, 320));
Maze.walls.add(new Rectangle(640, 352, 32, 320));
}
}
now, this works and cycles three stages, but as soon as I change the stage max to 5, it only paints on stages 2 and 4, which are exactly the same. Can anyone tell me what I am doing wrong?
Swing "Timers coalesce events by default." As noted by #HOFE, re-reading your sprite images is likely slowing things down enough to trigger the effect. Instead, read the images into a List<Image> when the program starts.