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
Related
I am very new to coding and have a question regarding the code below. (It's a Java program I'm trying to get to work in processing) I'd like it to grow the circle with the count_up, but when one of the circles reaches the max width to go back again (in a way to loop the action) I was trying to make this happen with if...else but I don't know how I should define the if so that it's working.
int count_up = 0;
int count_down = 500;
void setup()
{
size(500, 500);
}
void draw() {
if ( count_up < width/2) {
fill(170, 172, 204, 150);
circle(width/2, height/2, count_up);
count_up += 1;
fill(250, 191, 171, 100);
circle(width/2, height/2, count_down);
count_down -= 2;
}
else {
fill(170, 172, 204, 150);
circle(width/2, height/2, count_up);
count_up -= 1;
fill(250, 191, 171, 100);
circle(width/2, height/2, count_down);
count_down += 2;
}
}
This is what the code is supposed to do but without growing indefinetly:
int count_up = 0;
int count_down = 500;
void setup()
{
size(500, 500);
}
void draw() {
background (233);
fill(170, 172, 204, 150);
circle(width/2, height/2, count_up);
count_up += 1;
fill(250, 191, 171, 100);
circle(width/2, height/2, count_down);
count_down -= 2;
}
I actually got it with this simple trick, to define else as:
} else {
count_up = 0;
count_down = 500;
}
}
I'm creating a car game where it creates a 3D pseudo effect by moving the screen backwards and the car itself just stays still on the map, using the arrow keys. It only takes in one input at a time, meaning you have to let go of an arrow key first. I have some code that I've got to show what I'm aiming for the screen to do as well, as the screen only moves forwards, backwards, left, and right.
Example of what I want the screen to do:
public class Main extends JFrame {
private static final long serialVersionUID = 7722803326073073681L;
private boolean left = false;
private boolean up = false;
private boolean down = false;
private boolean right = false;
public JLabel lbl = new JLabel ("mn");
public Main() {
// Just setting up the window and objects
setSize(400, 400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
lbl.setBounds(100, 100, 20, 20);
add(lbl);
setLocationRelativeTo(null);
// Key listener, will not move the JLabel, just set where to
addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {}
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) left = false;
if (e.getKeyCode() == KeyEvent.VK_RIGHT) right = false;
if (e.getKeyCode() == KeyEvent.VK_UP) up = false;
if (e.getKeyCode() == KeyEvent.VK_DOWN) down = false;
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) left = true;
if (e.getKeyCode() == KeyEvent.VK_RIGHT) right = true;
if (e.getKeyCode() == KeyEvent.VK_UP) up = true;
if (e.getKeyCode() == KeyEvent.VK_DOWN) down = true;
}
});
// This thread will read the 4 variables left/right/up/down at every 30 milliseconds
// It will check the combination of keys (left and up, right and down, just left, just up...)
// And move the label 3 pixels
new Thread(new Runnable() {
#Override
public void run() {
try {
while (true) {
if (left && up) {
lbl.setBounds(lbl.getX() - 10, lbl.getY() - 10, 20, 20);
} else if (left && down) {
lbl.setBounds(lbl.getX() - 10, lbl.getY() + 10, 20, 20);
} else if (right && up) {
lbl.setBounds(lbl.getX() + 10, lbl.getY() - 10, 20, 20);
} else if (right && down) {
lbl.setBounds(lbl.getX() + 10, lbl.getY() + 10, 20, 20);
} else if (left) {
lbl.setBounds(lbl.getX() - 10, lbl.getY(), 20, 20);
} else if (up) {
lbl.setBounds(lbl.getX(), lbl.getY() - 10, 20, 20);
} else if (right) {
lbl.setBounds(lbl.getX() + 10, lbl.getY(), 20, 20);
} else if (down) {
lbl.setBounds(lbl.getX(), lbl.getY() + 10, 20, 20);
}
Thread.sleep(30);
}
} catch (Exception ex) {
ex.printStackTrace();
System.exit(0);
}
}
}).start();
}
public static void main(String[] args) {
new Main();
}
}
However, since the code above only moves the letters, I'm having a lot of difficulty in implementing it in the game as well. This is what I'm currently using to move the screen. (If I were to delete this method, nothing would appear).
What is currently happening:
public class RoadAppMain extends JFrame {
private static final int D_W = 1920; //Window dimension
private static final int D_H = 1280; //Window height
int grassWidth = 1920; //Width of grass
int vanishHeight = 768; // Height of vanishing point
int roadWidth = 900; //Width of the road
int rumbleLen = 800; //Length of each track stripe
double camDist = 0.8; //Camera distance
int N; //Size of each row or line
int playerPosX = 0; //Movement of player left and right
int playerPosY = 0; //Movement of player up and down
List<Line> lines = new ArrayList<RoadAppMain.Line>();
List<Integer> listValues = new ArrayList<Integer>();
DrawPanel drawPanel = new DrawPanel();
public RoadAppMain() {
for (int i = 0; i < 1600; i++) {
Line line = new Line();
line.z = i * rumbleLen;
int curveAngle = (int) (Math.random() * 15 + 1);
if (i > 20 && i < 70) {
line.curve = curveAngle;
}
else if (i > 100 && i < 150) {
line.curve = -curveAngle;
}
else if (i > 180 && i < 230) {
line.curve = curveAngle;
}
else if (i > 260 && i < 310) {
line.curve = -curveAngle;
}
else if (i > 340 && i < 390) {
line.curve = curveAngle;
}
else if (i > 400 && i < 420) {
}
lines.add(line);
}
N = lines.size();
//Handles action events by user
ActionListener listener = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
drawPanel.repaint();
}
};
Timer timer = new Timer(1, listener);
timer.start();
add(drawPanel);
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
//Moves screen using arrow keys - THIS IS THE PART IM TALKING ABOUT
private class DrawPanel extends JPanel {
public DrawPanel() {
String VK_LEFT = "VK_LEFT";
KeyStroke W = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0);
InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW); //necessary
inputMap.put(W, VK_LEFT);
ActionMap actionMap = getActionMap(); //necessary
actionMap.put(VK_LEFT, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
playerPosX -= 200;
drawPanel.repaint();
}
});
String VK_RIGHT = "VK_RIGHT";
KeyStroke WVK_RIGHT = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0);
inputMap.put(WVK_RIGHT, VK_RIGHT);
actionMap.put(VK_RIGHT, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
playerPosX += 200;
drawPanel.repaint();
}
});
String VK_UP = "VK_UP";
KeyStroke WVK_UP = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0);
inputMap.put(WVK_UP, VK_UP);
actionMap.put(VK_UP, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
playerPosY += 200;
drawPanel.repaint();
}
});
String VK_DOWN = "VK_DOWN";
KeyStroke WVK_DOWN = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0);
inputMap.put(WVK_DOWN, VK_DOWN);
actionMap.put(VK_DOWN, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
playerPosY -= 200;
drawPanel.repaint();
}
});
}
//Drawing components feature
protected void paintComponent(Graphics g) {
drawValues(g);
g.setColor(Color.black);
g.fillRect(0, 0, 1920, 395);
}
}
private void drawValues(Graphics g) {
int startPos = playerPosY / rumbleLen;
double x = 0; //Initial X position of screen on road
double dx = 0; //Correlation between the angle of the road and player
double maxY = vanishHeight;
int camH = 1700 + (int) lines.get(startPos).y; //Height of the camera
//Starting position
for (int n = startPos; n < startPos + 300; n++) {
Line l = lines.get(n % N); //Position of line
l.project(playerPosX - (int) x, camH, playerPosY);
x += dx;
dx += l.curve;
if (l.Y > 0 && l.Y < maxY) {
maxY = l.Y;
Color grass = ((n / 2) % 2) == 0 ? new Color(21, 153, 71) : new Color(22, 102, 52); //Color for grass (first is for lighter, second for darker)
Color rumble = ((n / 2) % 2) == 0 ? new Color(255, 255, 255) : new Color(222, 4, 4); // Color for rumble (first is white, second is red)
Color road = new Color(54, 52, 52); // Color of road or asphalt
Color midel = ((n / 2) % 2) == 0 ? new Color(255, 255, 255) : new Color(54, 52, 52); //Color of hashed lines (first for white lines, second for gap)
Color car = new Color(104, 104, 104);
Color tire = new Color(0, 0, 0);
Color stripe = new Color(0, 0, 0);
Color light = new Color(253, 0, 0);
Color hood = new Color(0, 0, 0);
Color frame = new Color(0,0,255);
Line p = null;
if (n == 0) {
p = l;
} else {
p = lines.get((n - 1) % N);
}
draw(g, grass, 0, (int) p.Y, grassWidth, 0, (int) l.Y, grassWidth); //(Graphics g, Color c, int x1, int y1, int w1, int x2, int y2, int w2)
draw(g, rumble, (int) p.X, (int) p.Y, (int) (p.W * 2.03), (int) l.X, (int) l.Y, (int) (l.W * 2.03)); //Affects width of rumble
draw(g, road, (int) p.X, (int) p.Y, (int) (p.W * 1.8), (int) l.X, (int) l.Y, (int) (l.W * 1.8));
draw(g, midel, (int) p.X, (int) p.Y, (int) (p.W * 0.78), (int) l.X, (int) l.Y, (int) (l.W * 0.78)); //ADD HERE
draw(g, road, (int) p.X, (int) p.Y, (int) (p.W * 0.7), (int) l.X, (int) l.Y, (int) (l.W* 0.7)); //To cover the gap in between each midel. Must be after to allow it to colour over it
draw(g, car, 965, 927, 125, 965, 1005, 125);
draw(g, tire, 875, 1005, 35, 875, 1050, 35);
draw(g, tire, 1055, 1005, 35, 1055, 1050, 35);
draw(g, stripe, 1050, 965, 30, 870, 980, 30);
draw(g, stripe, 1050, 950, 30, 870, 965, 30);
draw(g, hood, 965, 880, 90, 965, 927, 125);
draw(g, light, 875, 950, 5, 875, 980, 5);
draw(g, light, 890, 950, 5, 890, 980, 5);
draw(g, light, 905, 950, 5, 905, 980, 5);
draw(g, light, 1025, 950, 5, 1025, 980, 5);
draw(g, light, 1040, 950, 5, 1040, 980, 5);
draw(g, light, 1055, 950, 5, 1055, 980, 5);
draw(g, frame, 965, 874, 86, 965, 880, 90);
draw(g, light, 965, 874, 35, 965, 880, 45);
}
}
}
void draw(Graphics g, Color c, int x1, int y1, int w1, int x2, int y2, int w2) {
Graphics g9d = g;
int[] x9Points = { x1 - w1, x2 - w2, x2 + w2, x1 + w1 };
int[] y9Points = { y1, y2, y2, y1 };
int n9Points = 4;
g9d.setColor(c);
g9d.fillPolygon(x9Points, y9Points, n9Points);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new RoadAppMain();
}
});
}
class Line {
double x, y, z;
double X, Y, W;
double scale, curve;
public Line() {
curve = x = y = z = 0;
}
void project(int camX, int camY, int camZ) {
scale = camDist / (z - camZ);
X = (1 + scale * (x - camX)) * grassWidth / 2;
Y = (1 - scale * (y - camY)) * vanishHeight / 2;
W = scale * roadWidth * grassWidth / 2;
}
}
}
How could I implement that movement into my game as well?
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
I have a problem where my frame shows up as grey, but then after a few seconds it displays the image as my for loop is finishing. I need to make it so that it displays the image correctly once it opens in order to show the loop. Here is my entire code, sorry about the length:
import java.awt.*;
import javax.swing.*;
public class MainFrame extends JFrame{
public void MainFrame() {
setTitle("Game");
setSize(1300, 650);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setBackground(Color.WHITE);
Dice diceObject = new Dice();
add(diceObject);
}
}
import java.awt.*;
import java.util.Random;
import javax.swing.*;
public class Dice extends JPanel {
public static int pause(int n)
{
try {
Thread.sleep(n);
} catch(InterruptedException e) {
}
return n;
}
public void Dice() {
setDoubleBuffered(true);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
int num = 0;
for (int i = 0; i < 7; i++) {
Random generator= new Random();
int number = generator.nextInt(6)+1;
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, height);
g.setColor(Color.BLACK);
g.drawRoundRect(550, 150, 200, 200, 50, 50);
System.out.println("Test");
if (number == 1) { //Roll one
num = 1;
g.setColor(new Color (0, 0, 0));
g.fillOval(640, 240, 20, 20);
pause(100);
} if (number == 2) { //Roll two
num = 2;
g.setColor(new Color (0, 0, 0));
g.fillOval(590, 290, 20, 20);
g.fillOval(690, 190, 20, 20);
pause(100);
} if (number == 3) { //Roll three
num = 3;
g.setColor(new Color (0, 0, 0));
g.fillOval(590, 290, 20, 20);
g.fillOval(640, 240, 20, 20);
g.fillOval(690, 190, 20, 20);
pause(100);
} if (number == 4) { //Roll four
num = 4;
g.setColor(new Color (0, 0, 0));
g.fillOval(590, 290, 20, 20);
g.fillOval(590, 190, 20, 20);
g.fillOval(690, 290, 20, 20);
g.fillOval(690, 190, 20, 20);
pause(100);
} if (number == 5) { //Roll five
num = 5;
g.setColor(new Color (0, 0, 0));
g.fillOval(590, 290, 20, 20);
g.fillOval(590, 190, 20, 20);
g.fillOval(640, 240, 20, 20);
g.fillOval(690, 290, 20, 20);
g.fillOval(690, 190, 20, 20);
pause(100);
} if (number == 6) { //Roll six
num = 6;
g.setColor(new Color (0, 0, 0));
g.fillOval(590, 190, 20, 20);
g.fillOval(590, 240, 20, 20);
g.fillOval(590, 290, 20, 20);
g.fillOval(690, 190, 20, 20);
g.fillOval(690, 240, 20, 20);
g.fillOval(690, 290, 20, 20);
pause(100);
}
}
g.setFont(new Font("TimesRoman", Font.PLAIN, 20));
g.drawString("You rolled a " + num, 590, 100);
pause(1000);
}
}
Thanks in advance.
The first problem is the fact that you are setting the frame visible BEFORE you add anything to it...
Instead, try calling setVisible last
public class MainFrame extends JFrame{
public void MainFrame() {
setTitle("Game");
setSize(1300, 650);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBackground(Color.WHITE);
Dice diceObject = new Dice();
add(diceObject);
setVisible(true);
}
}
You should also avoid extending directly from JFrame as you're not adding any new functionality to the class and need to take into consideration Initial Threads and ensure you are starting the main UI within the context of the Event Dispatching Thread.
The rest of your problems relate to your previous question
Updated with working example
Cause I'm lazy, I've utilised the Graphics 2D API to draw the dots. I did this because many of the dots appear in the same locations for many of the numbers...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DiceRoller {
public static void main(String[] args) {
new DiceRoller();
}
public DiceRoller() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Die());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Die extends JPanel {
private int number = 1;
public Die() {
Timer timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
number = (int) (Math.round((Math.random() * 5) + 1));
repaint();
}
});
timer.setRepeats(true);
timer.setInitialDelay(0);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(220, 220);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth();
int height = getHeight();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, width, height);
g2d.setColor(Color.BLACK);
g2d.drawRoundRect(10, 10, width - 20, height - 20, 50, 50);
List<Shape> dots = new ArrayList<>(6);
if (number == 1 || number == 3 || number == 5) {
int x = (width - 20) / 2;
int y = (height - 20) / 2;
dots.add(new Ellipse2D.Float(x, y, 20, 20));
}
if (number == 2 || number == 3 || number == 4 || number == 5 || number == 6) {
int x = ((width / 2) - 20) / 2;
int y = ((height / 2) - 20) / 2;
dots.add(new Ellipse2D.Float(x, y, 20, 20));
dots.add(new Ellipse2D.Float(x + (width / 2), y + (height / 2), 20, 20));
}
if (number == 4 || number == 5 || number == 6) {
int x = (width / 2) + (((width / 2) - 20) / 2);
int y = ((height / 2) - 20) / 2;
dots.add(new Ellipse2D.Float(x, y, 20, 20));
dots.add(new Ellipse2D.Float(x - (width / 2), y + (height / 2), 20, 20));
}
if (number == 6) {
int x = (((width / 2) - 20) / 2);
int y = (height - 20) / 2;
dots.add(new Ellipse2D.Float(x, y, 20, 20));
dots.add(new Ellipse2D.Float(x + (width / 2), y, 20, 20));
}
for (Shape dot : dots) {
g2d.fill(dot);
}
g2d.dispose();
}
}
}
I'm quite new with Java and at the moment I'm making a super meat boy kinda game but I just can't figure out how to make him jump.
Here is the code I have so far, can anyone please describe me how to make him jump? Thanks.
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Timer;
import java.util.TimerTask;
public class meatboy extends Applet implements KeyListener{
public int x = 10, y = 300, gravity = 3;
public int xs = 380, ys = 230;
double jumptime = 0;
public boolean right, left, up, jump, start, grounded;
public void init(){
setSize(800,400);
setBackground(Color.black);
addKeyListener(this);
/////Movement//////
Timer t = new Timer();
t.schedule(new TimerTask(){public void run(){
if (start == true){
if (right == true){
x = x + 3;
}if (left == true){
x = x - 3;
}if(up == true && grounded == true){
while(jumptime < 50){
y--;
jumptime = jumptime + 0.5;
}
grounded = false;
jumptime = 0;
}
/////GRAVITY//////
y = y + gravity;
///////Collision Dectection/////
if(x > 790){//right of screen stop
x = 10;
}if(x < 10){// left stop
x = 789;
}if(y > 352){
y = y - 3;
grounded = true;
}
////////////End of collision///////////
repaint();
}}},10,10);
///////movement end////////
}
public void paint(Graphics g){
////////CREATES MEATBOY///////////////
if (start == false){
x = 10;
y = 300;
g.setColor(Color.DARK_GRAY);
g.fillRect(0, 0, 800, 400);
g.setColor(Color.white);
g.drawString("MeatBoy 4K", 358, 180);
g.drawString("Press Z to start!!!!", 350, 200);
g.setColor(Color.RED);
g.fillRect(xs, ys, 16, 16);//meatboys body
g.fillRect(xs + 16, ys + 6, 4, 4);//arm
g.fillRect(xs - 4, ys + 6, 4, 4);//arm
g.fillRect(xs, ys + 12, 4, 6);//leg
g.fillRect(xs + 12, ys + 12, 4, 6);//leg
g.setColor(Color.black);
g.fillRect(xs + 2, ys + 2, 5, 5);//eye
g.fillRect(xs + 10, ys + 2, 5, 5);//eye
}
if (start == true){
g.setColor(Color.RED);
g.fillRect(x, y, 16, 16);//meatboys body
g.fillRect(x + 16, y + 6, 4, 4);//arm
g.fillRect(x - 4, y + 6, 4, 4);//arm
g.fillRect(x, y + 12, 4, 6);//leg
g.fillRect(x + 12, y + 12, 4, 6);//leg
g.setColor(Color.black);
g.fillRect(x + 2, y + 2, 5, 5);//eye
g.fillRect(x + 10, y + 2, 5, 5);//eye
///////////END OF MEATBOY//////////////////
////////Creates Floor///////////////////
g.setColor(Color.GRAY);
g.fillRect(0, 370, 800, 30);
}
}
/**
*
*/
private static final long serialVersionUID = 1L;
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_Z){
//right = true;
start = true;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT){
//right = true;
right = true;
}if (e.getKeyCode() == KeyEvent.VK_LEFT){
left = true;
}if (e.getKeyCode() == KeyEvent.VK_UP){
up = true;
}if (e.getKeyCode() == KeyEvent.VK_SPACE){
up = true;
}
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT){
//right = true;
right = false;
}if (e.getKeyCode() == KeyEvent.VK_LEFT){
left = false;
}if (e.getKeyCode() == KeyEvent.VK_UP){
up = false;
}if (e.getKeyCode() == KeyEvent.VK_SPACE){
up = false;
}
}
public void keyTyped(KeyEvent e) {
}
}
When you jump you make a vertical change of 1 (up), however, your gravity makes a vertical change of -3 (down) and if getting too far down you reset the vertical position to ground level.
What you need to do is compensate for gravity when "jumping" and one way of doing it would be to use
while(jumptime < 50){
y -= 1 + gravity;
jumptime = jumptime + 0.5;
}