How to randomly generate tiles in java code - java

I have question about random generation of sprite sheet tiles in java. Whenever I try to use a for loop the random generation changes every millisecond or faster. I am very confused and have no idea where to start from here. If anyone can come up with some easy code for a begginer to grasp the concept of random generation!
Here is the code I am working with for generating a flat map /
public class Map {
Random random = new Random();
public static int mapxDirection;
public static int mapx = 1;
public static int bgSpeed = 20;
public static int grass = 16;
public static int dirt = 0;
public static int stone = 1;
public static int waterup = 2;
public static int waterside = 18;
public static int glass = 17;
public static int chicken = 32;
public static int steak = 33;
public static int mapSpeed = 3;
public static BufferedImage[] sprites;
public void renderMap(Graphics g) {
final int width = 32;
final int height = 32;
final int rows = 16;
final int cols = 16;
sprites = new BufferedImage[rows * cols];
BufferedImage spritesheet = null;
try {
spritesheet = ImageIO.read(new File("res/SpriteSheet.png"));
} catch (IOException e) {
e.printStackTrace();
}
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
sprites[(i * cols) + j] = spritesheet.getSubimage(i * width, j
* height, width, height);
}
}
for (int i = 0; i < 2000; i += 32) {
g.drawImage(sprites[grass], Map.mapx + i, 259, null);
}
for (int i = 0; i < 2000; i += 32) {
for (int j = 291; j <= 508; j += 32) {
g.drawImage(sprites[dirt], Map.mapx + i, j, null);
}
}
for (int i = 0; i < 2000; i += 32) {
for (int j = 508; j <= 540; j += 32) {
g.drawImage(sprites[stone], Map.mapx + i, j - 3, null);
}
}
}
}

There are multiple ways this can be done, it also depends on what type on random generation you want to achieve for example, do you what to completely randomize every tile or do you what to load random chunks. The popular game Minecraft uses the method of random chuck generation.
If your new to game programming, i recommend checking out RealTutsGML Game Programming Tutorials. He teaches you a easy and good way of loading in sprite sheets and also teaches you how to load in and create a level in paint. All though he is making a platformer, you can easily convert the same method into a top down game.
Here is how i would go about creating a random generation map. First i would create a abstract class called GameObject. Every object you make will extend this class.
public abstract class GameObject {
protected float x, y;
protected ObjectId id;
protected float velX= 0, velY = 0;
protected boolean falling = true;
protected boolean jumping = false;
public GameObject(float x, float y, ObjectId id) {
this.x = x;
this.y = y;
this.id = id;
}
public abstract void tick(LinkedList<GameObject> object);
public abstract void render(Graphics g);
public abstract Rectangle getBounds();
public float getX() { return x; }
public float getY() { return y; }
public float getVelX() { return velX; }
public float getVelY() { return velY; }
public boolean isFalling() { return falling; }
public boolean isJumping() { return jumping; }
public void setX(float x) { this.x = x; }
public void setY(float y) { this.y = y; }
public void setVelX(float velX) { this.velX = velX; }
public void setVelY(float velY) { this.velY = velY; }
public void setFalling(boolean falling) { this.falling = falling; }
public void setJumping(boolean jumping) { this.jumping = jumping; }
public ObjectId getId() { return id; }
}
For example if i want to make a object called Block, i would create a class called Block and extends GameObject like this.
public class Block extends GameObject {
private boolean animate = true;
Texture tex = Game.getInstance();
private int type;
public Block(float x, float y, int type, ObjectId id) {
super(x, y, id);
this.type = type;
}
public void tick(LinkedList<GameObject> object) {
bAnimate.runAnimation();
}
public void render(Graphics g) {
if (type == 0) g.drawImage(tex.red_block[0], (int)x, (int)y, null); // Red Block
if (type == 1) g.drawImage(tex.green_block[0], (int)x, (int)y, null); // Blue Block
if (type == 2) g.drawImage(tex.blue_block[0], (int)x, (int)y, null); // Green Block
if (type == 3) g.drawImage(tex.yellow_block[0], (int)x, (int)y, null); // Yellow Block
if (type == 4) g.drawImage(tex.orange_block[0], (int)x, (int)y, null); // Orange Block
if (type == 5) g.drawImage(tex.pink_block[0], (int)x, (int)y, null); // Pink Block
}
public Rectangle getBounds() {
return new Rectangle((int)x, (int)y, 32, 32);
}
}
I then create a LinkedList like this. An also create 2 methods for adding and removing objects for the list.
protected LinkedList<GameObject> object = new LinkedList<GameObject>();
public void addObject(GameObject object) {
this.object.add(object);
}
public void remove(GameObject object) {
this.object.remove(object);
}
I would then simply add objects to the list like this.
addObject(new Block(x * 32, y * 32, random.nextInt(6), ObjectId.Block));
Sense this post is getting kinda big i will leave the rest to you, if you like i can see you the source code of the project i am using. This is also the same method that "RealTutsGML" uses in his tutorials.
I see that you and using Map.mapx instead of that just write the variable mapx no need for the Map. Also your data should always be private or protected. I also recommend making a variable that holds your map size like this.
private static int mapSize = 2000;
It is just so that if you want to change the map size you don't have to replace more than one number.
I hope this helps you out.
Here is a list of java programming books.

Related

How to implement MouseMotionListener in Java Swing for list of objects to follow mouse?

My question is how can i implement the MouseMotionListener for list of objects can follow my mouse? I guess, I couldn't get the idea so far. I tried to do that my second part of the worm will follow the head. So it will become like a train. But in first second seems like Ok but all objects suddenly converge to a point.
Basically my code is above;
My Worm.class is like that;
public class Worm {
Random rd = new Random();
int xWorm;
int yWorm;
int Speed = 100;
int size = 10; // default
Worm()
{
xWorm = rd.nextInt(250);
yWorm = rd.nextInt(250);
}
Worm(int xNew, int yNew){
xWorm = xNew;
yWorm = yNew;
}
public int getxWorm() {
return xWorm;
}
public void setxWorm(int xWorm) {
this.xWorm = xWorm;
}
public int getyWorm() {
return yWorm;
}
public void setyWorm(int yWorm) {
this.yWorm = yWorm;
}
public int getSpeed() {
return Speed;
}
public void setSpeed(int speed) {
Speed = speed;
}
public void move (int dx, int dy) {
xWorm+=dx;
yWorm+=dy;
}
public void setPosition(int x,int y) {
this.xWorm = x;
this.yWorm = y;
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Ellipse2D Ellipse= new Ellipse2D.Double(xWorm,yWorm,10,10);
g2.setColor(Color.GREEN);
g2.draw(Ellipse);
g2.fill(Ellipse);
// g.fillOval(this.xWorm, this.yWorm, 30, 30);
}
public boolean iscollision(Food f) {
Rectangle2D RectangleforFood = new Rectangle2D.Double(f.xFood,f.yFood,5,5);
Rectangle2D RectangleforWormHead = new Rectangle2D.Double(this.xWorm,this.yWorm,10,10);
if (RectangleforWormHead.intersects(RectangleforFood)) {
return true;
}
else {
return false;
}
}
}
and my Panel.class the tracker function like that ;
public void createlongworm() {
for(int i = 0; i < 100 ; i++) {
wormBody.add(new Worm(wormBody.get(i).xWorm+10,wormBody.get(i).yWorm));
}}
public void tracker(ArrayList <Worm> TracktheWorm) {
for(int i = 0; i < TracktheWorm.size()-1 ; i++) {
TracktheWorm.get(i+1).xWorm = TracktheWorm.get(i).xWorm;
TracktheWorm.get(i+1).yWorm = TracktheWorm.get(i).yWorm;
}
repaint();
}

BackGround in my JPanel, how can I resolve this?

Well my problem is that I'm making the stars move with a thread, they move verticaly and it works good but i do a random X for the star and sometimes it intersecs other stars like this :
This is my code for the JPanel:
class Backgroundmoving
public class Backgroundmoving extends JPanel {
ArrayList<starmoving> star;
public Backgroundmoving() {
this.setSize(650, 501);
star = new ArrayList<>();
for (int i = 0; i < 20; i++)
this.addStar();
}
public void addStar() {
int x, y;
x = (int) (Math.random() * 625);
y = (int) (Math.random() * 476);
starmoving e = new starmoving(x, y);
star.add(e);
Thread t = new Thread(e);
t.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
public void draw(Graphics g) {
g.drawImage(new ImageIcon("background.png").getImage(), 0, 0, 650, 501, null);
for (int i = 0; i < star.size(); i++) {
star.get(i).draw(g);
}
repaint();
}
public static void main(String[] args) {
// TODO code application logic here
JFrame gui = new JFrame();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setSize(650, 510);
gui.setResizable(false);
gui.add(new Backgroundmoving());
gui.setVisible(true);
}
}
class starmoving
public class starmoving implements Runnable {
int x;
int y;
int yVel;
public starmoving(int x, int y) {
this.x = x;
this.y = y;
yVel = 1;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
private void move() {
y += yVel;
if (y > 476) {
y = 0;
x = (int) (Math.random() * 625);
}
}
private boolean isOffScreen() {
if (y <= 476)
return false;
return true;
}
public void draw(Graphics g) {
g.drawImage(new ImageIcon("star.png").getImage(), x, y, 12, 12, null);
}
#Override
public void run() {
while (true) {
move();
try {
Thread.sleep(7);
} catch (InterruptedException ex) {
System.out.println(ex.getMessage());
}
}
}
}
i don't want stars intersecting, was thinking in a if before the random X but how can i know if other star is in that X ?
You have an ArrayList that contains all your "StarMoving" objects. So you need to iterate through that list to make sure that none of the object intersect.
On top of that you have other problems.
Use proper Java class names. Java classes SHOULD start with an upper case character. (ie. "starmoving" is wrong)
Don't use multiple Threads for the animation. You current code starts 20 Threads. You should have a single Thread and then iterate through your ArrayList to move all the stars.
Don't read the image in the draw() method. Currently you code is reading the image every 7ms. This is not very efficient. The image should be read once and then stored as a property of your class.

Checkerboard not drawing correct amount of checkers

I am trying to develop a checkerboard given a template of classes and some code for school. I got the board to appear but the right amount of checkers are not being drawn. There are supposed to be 7 red and 9 black checkers but each time I run the program a different amount of each is drawn.
import java.applet.Applet;
import java.awt.*;
import java.util.Random;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class Checkers extends JApplet
{
private final int MAX_SIZE = 8;
private final int APP_WIDTH = 400;
private final int APP_HEIGHT = 400;
private final int MAXSIZE = 8;
Square[][] sq;
public void paint(Graphics page)
{
setBackground(Color.white);
fillBoard(page); // draws the method that will draw the checkers
placeCheckers(page, 7, Color.red); //method to place the red checkers
placeCheckers(page, 9, Color.black); //method to draw black checkers
CheckJumps(page); //check if checkers can jump
setSize (APP_WIDTH,APP_HEIGHT);
}
public void fillBoard(Graphics page)
{
sq = new Square[8][8];
int x,y;
Color rb;
for (int row = 0; row < MAXSIZE; row++)
for (int col = 0; col < MAXSIZE; col++)
{
x = row * (APP_WIDTH/MAXSIZE);
y = col * (APP_HEIGHT/MAXSIZE);
if ( (row % 2) == (col % 2) )
rb = Color.red;
else
rb = Color.black;
sq[row][col] = new Square (x, y, rb);
}
for (int row = 0; row < 8; row++)
for (int col = 0; col < 8; col++)
sq[row][col].draw(page);
}
public void placeCheckers (Graphics page, int num_checkers, Color ncolor)
{
int count, row, col;
int x, y;
Circle c;
Random rand = new Random();
for (count = 0; count < num_checkers; count++)
{
do
{
row = rand.nextInt(8);
col = rand.nextInt(8);
} while (sq[row][col].getOccupy() || ncolor == sq[row][col].getColor());
x = row * (APP_WIDTH/MAXSIZE);
y = col * (APP_HEIGHT/MAXSIZE);
c = new Circle (x, y, 50, ncolor);
c.draw(page);
sq[row][col].setOccupy(true);
}
}
class Square
{
private int x, y = 0;
private Color c;
private boolean occupied;
public Square (int x, int y, Color c)
{
this.x = x;
this.y = y;
this.c = c;
}
public void setX (int x)
{
x = this.x;
}
public int getX ()
{
return x;
}
public void setY (int y)
{
y= this.y;
}
public int getY ()
{
return y;
}
public void setColor (Color c)
{
c = this.c;
}
public Color getColor ()
{
return c;
}
public void setOccupy (boolean occupied)
{
occupied = this.occupied;
}
public boolean getOccupy ()
{
return occupied;
}
public String toString()
{
return ("X coordinate: " + x + "\nY coordinate:" + y + "\nSquare color: " + c);
}
public void draw (Graphics page)
{
page.setColor(c);
page.fillRect(x, y, 50, 50);
}
}
class Circle
{
private int x,y;
private int diameter;
private Color c;
public Circle (int x, int y, int diameter, Color c)
{
this.x = x;
this.y = y;
this.diameter = diameter;
this.c = c;
}
public void setX (int x)
{
x = this.x;
}
public int getX ()
{
return x;
}
public void setY (int y)
{
y= this.y;
}
public int getY ()
{
return y;
}
public void setColor (Color c)
{
c = this.c;
}
public Color getColor ()
{
return c;
}
public void setDiameter (int x)
{
diameter = x;
}
public void draw (Graphics page)
{
page.setColor(c);
page.fillOval(x, y, diameter, diameter);
}
}
If, you have followed some of the advice from your previous question you may have avoided this issue.
As near as I can tell, your problem is you're not calling super.paint, which is responsible for (amongst a lot of other things) preparing the Graphics context for painting. It does this, by clearing what ever was painted on it previously.
Instead of overriding paint of JApplet, which will cause flicker when the applet is updated, you should start with something like a JPanel and override it's paintComponent method. JPanel is double buffered, which will prevent any flicker from occuring. Don't forget to call super.paintComponent.
You shouldn't be calling fillBorder every time paint is called, this is wasteful on a number of levels, instead, you should only call it when you need to. With a little bit more clever design, you could actually get away with calling it from the constructor, but I don't have the time to re-code your entire program.
The size the applet is defined by the HTML page which contains it, not the applet itself, relying on magic numbers (like APP_WIDTH and APP_HEIGHT) is a bad idea. You should, instead, rely on known values, like getWidth and getHeight. This of course assumes you'd like to be able to resize the playable area and avoid possible issues with people deploying your applet with the wrong size ;)
While, I'm guessing that placeCheckers is a test method, you should know, paint can be called any number of times for any number of reasons, many of which you don't control, this means that the checkers will be randomized each time paint is called.
Instead, you should consider creating a virtual board which contains the information about the state of the game and update this as required. You would then simply use the painting process to reflect this model.
An example of how I might "start"...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JApplet;
import javax.swing.JPanel;
public class Checkers extends JApplet {
#Override
public void init() {
add(new Board());
}
public class Board extends JPanel {
private final int APP_WIDTH = 400;
private final int APP_HEIGHT = 400;
private final int MAXSIZE = 8;
Square[][] sq;
#Override
public void invalidate() {
fillBoard();
super.invalidate();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
sq[row][col].draw(g);
}
}
setBackground(Color.white);
placeCheckers(g, 7, Color.red); //method to place the red checkers
placeCheckers(g, 9, Color.black); //method to draw black checkers
}
#Override
public Dimension getPreferredSize() {
return new Dimension(APP_WIDTH, APP_HEIGHT);
}
public void fillBoard() {
sq = new Square[8][8];
int x, y;
Color rb;
int gridSize = Math.min(getWidth(), getHeight());
int size = gridSize / MAXSIZE;
for (int row = 0; row < MAXSIZE; row++) {
for (int col = 0; col < MAXSIZE; col++) {
x = row * (gridSize / MAXSIZE);
y = col * (gridSize / MAXSIZE);
if ((row % 2) == (col % 2)) {
rb = Color.red;
} else {
rb = Color.black;
}
sq[row][col] = new Square(x, y, rb, size);
}
}
}
public void placeCheckers(Graphics page, int num_checkers, Color ncolor) {
int count, row, col;
int x, y;
Circle c;
int gridSize = Math.min(getWidth(), getHeight());
int size = gridSize / MAXSIZE;
Random rand = new Random();
for (count = 0; count < num_checkers; count++) {
do {
row = rand.nextInt(8);
col = rand.nextInt(8);
} while (sq[row][col].getOccupy() || ncolor == sq[row][col].getColor());
x = row * (gridSize / MAXSIZE);
y = col * (gridSize / MAXSIZE);
c = new Circle(x, y, size, ncolor);
c.draw(page);
sq[row][col].setOccupy(true);
}
}
}
class Square {
private int x, y = 0;
private Color c;
private boolean occupied;
private int size;
public Square(int x, int y, Color c, int size) {
this.x = x;
this.y = y;
this.c = c;
this.size = size;
}
public void setX(int x) {
x = this.x;
}
public int getX() {
return x;
}
public void setY(int y) {
y = this.y;
}
public int getY() {
return y;
}
public void setColor(Color c) {
c = this.c;
}
public Color getColor() {
return c;
}
public void setOccupy(boolean occupied) {
occupied = this.occupied;
}
public boolean getOccupy() {
return occupied;
}
public String toString() {
return ("X coordinate: " + x + "\nY coordinate:" + y + "\nSquare color: " + c);
}
public void draw(Graphics page) {
page.setColor(c);
page.fillRect(x, y, size, size);
}
}
class Circle {
private int x, y;
private int diameter;
private Color c;
public Circle(int x, int y, int diameter, Color c) {
this.x = x;
this.y = y;
this.diameter = diameter;
this.c = c;
}
public void setX(int x) {
x = this.x;
}
public int getX() {
return x;
}
public void setY(int y) {
y = this.y;
}
public int getY() {
return y;
}
public void setColor(Color c) {
c = this.c;
}
public Color getColor() {
return c;
}
public void setDiameter(int x) {
diameter = x;
}
public void draw(Graphics page) {
page.setColor(c);
page.fillOval(x, y, diameter, diameter);
}
}
}
Updated
This ones had me scratching me head for a while. Basically, after some additional checking I discovered that the checkers where being allowed to occupy space that was suppose to be already taken. After bashing me head against the do-while loop, I check the setOccupy method and found...
public void setOccupy(boolean occupied) {
occupied = this.occupied;
}
You're assiging the Square's occupied state back to the value you are passing, which has no effect on anything
Instead, it should look more like...
public void setOccupy(boolean occupied) {
this.occupied = occupied;
}
You may also like to have a read through Why CS teachers should stop teaching Java applets

why wont my program paintComponent() if I set an ImageIcon and Image?

I've tried to find similar questions, but I think I have a unique situation here.
I am programming a game in java, my main class creates a frame which adds a component class which is an extension of JPanel. Basically, I draw these ovals and they move around and do different things, and I want to implement a method inside of one my classes which will use an image instead of an oval. However, anytime I try to create and image from a file, the program will not run the overridden "paintComponent(Graphics g)" method.
My main:
package mikeengine;
import javax.swing.JFrame;
public class MikeEngine {
static final int fx = 1300;
static final int fy = 800;
static final int px = 1292;
static final int py = 767;
static interactivePanel levelPanel;
public static void pause() {
try {
Thread.sleep(10); // wait 10ms
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("MEngine");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(fx, fy);
frame.setResizable(false);
frame.setVisible(true);
levelPanel = new interactivePanel();
addship();
frame.getContentPane().add(levelPanel);
levelPanel.requestFocusInWindow();
while (true) {
pause();
levelPanel.move();
levelPanel.repaint();
}
}
static void addship() {
PlayerShip ship = new PlayerShip(100, 25, 25, px, 0, py, 0);
ship.setGraphic("C:/Users/asdf/Documents/NetBeansProjects/mikeEngine/src/mikeengine/res/right-arrow.jpg");
levelPanel.addObject(ship);
for (int i = 0; i < 5; i++) {
PlayerShip ship2 = new PlayerShip((int) (Math.random() * 1000) + 100, (int) (Math.random() * 1000) + 100, 25, px, px / 2, py, 0);
ship2.setMovement((int) (Math.random() * 10) / 5, (int) (Math.random() * 10) / 2);
levelPanel.addObject(ship2);
}
}
}
now, if I comment out the line:
ship.setGraphic("C:/Users/asdf/Documents/NetBeansProjects/mikeEngine/src/mikeengine/res/right-arrow.jpg");
everything renders perfectly.
I don't even paint the image that is going to be created. The image variable is just part of a class and it is currently just being created and doing nothing, so I don't understand how it affects the paintcomponentMethod(), if the paintComponent() isn't even told to try to paint the image ever.
The "PlayerShip" class extends the abstract "OnScreenObject" class (you really shouldn't need to see the code for PlayerShip, it only overrides one irrelevant method).
OnScreenObject looks like so:
package mikeengine;
import java.awt.Color;
import java.awt.Image;
import javax.swing.ImageIcon;
public abstract class OnScreenObject {
private ImageIcon graphic;
Image g;
protected int xmin;
protected int ymin;
protected int xsize;
protected int ysize;
protected int rise;
protected int run;
protected int containerYMax;
protected int containerYMin;
protected int containerXMax;
protected int containerXMin;
protected boolean visible;
protected boolean allowedOffscreen;
protected boolean isSelected;
protected Color color;
OnScreenObject(int x, int y, int sizeX, int sizeY, int cxMax, int cxMin, int cyMax, int cyMin) {
xmin = x;
ymin = y;
xsize = sizeX;
ysize = sizeY;
containerXMax = cxMax;
containerXMin = cxMin;
containerYMax = cyMax;
containerYMin = cyMin;
//
rise = 0;
run = 0;
visible = true;
allowedOffscreen = false;
isSelected = false;
}
public int getXMin() {
return xmin;
}
public int getYMin() {
return ymin;
}
public int getXMax() {
return xmin + xsize;
}
public int getYMax() {
return ymin + ysize;
}
public int getXSize() {
return xsize;
}
public int getYSize() {
return ysize;
}
public Color getColor() {
return color;
}
public boolean getAllowedOffscreen() {
return allowedOffscreen;
}
public boolean getVisible() {
return visible;
}
public int getRun() {
return run;
}
public ImageIcon getGraphic() {
return graphic;
}
public boolean isWithin(int x, int y) {
return x >= xmin && x <= getXMax() && y >= ymin && y <= getYMax();
}
public void setXMin(int x) {
xmin = x;
}
public void setYMin(int y) {
ymin = y;
}
public void setXSize(int x) {
xsize = x;
}
public void setYSize(int y) {
ysize = y;
}
public void setGraphic(String setto) {
try{
graphic = new ImageIcon("setto");
g=graphic.getImage();
System.out.println("tried");
} catch(Exception e){
System.out.println("caught:" + e);
}
}
public void setAllowedOffscreen(boolean allowed) {
allowedOffscreen = allowed;
}
public void setMovement(int riseM, int runM) {
rise = riseM * -1;//rise means to go up, and negative will move it up
run = runM;
}
public void nudge(boolean horizontal, int amount) {
if (horizontal) {
run += amount;
} else {
rise += amount;
}
}
public void setVisible(boolean vis) {
visible = vis;
}
public void setColor(Color c) {
color = c;
}
public boolean checkCollide(OnScreenObject other) {
if (other.getYMax() < getYMin()) { //if other object is above this
return false;
}
if (other.getYMin() > getYMax()) {//if other object is below this
return false;
}
if (other.getXMax() < getXMin()) {//if other is to the left
return false;
}
if (other.getXMin() > getXMax()) {//if other is to the right
return false;
}
return true;
}
public void move() {
if (!allowedOffscreen) {
checkEdge();
}
xmin += run;
ymin += rise;
}
protected abstract void checkEdge();
}
The interactivePanel class is the one that extends JPanel:
package mikeengine;
import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.JPanel;
public class interactivePanel extends JPanel {
ArrayList<OnScreenObject> objects;
IClick myClick;
Ipress myType;
PlayerShip currentShip;
interactivePanel() {
objects = new ArrayList<>();
myClick = new IClick();
myType = new Ipress();
this.addMouseListener(myClick);
this.addKeyListener(myType);
}
#Override
public void paintComponent(Graphics g) {
System.out.println("painting");
paintBackground(g);
paintObjects(g);
checkClick();
checkPress();
}
public void move() {
System.out.println("here2");
checkDeadShip();//also sets current ship
moveObjects();//also removes invisible
checkCollisions();
} // end method move
private void checkClick() {
if (!myClick.getClicked()) {
return;
}
for (int i = 0; i < objects.size(); i++) {
OnScreenObject current = objects.get(i);
if (current.isWithin(myClick.getX(), myClick.getY())) {
System.out.println("CLICKED");
}
}
}
private void paintBackground(Graphics g) {
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
}
private void paintObjects(Graphics g) {
for (int i = 0; i < objects.size(); i++) {
OnScreenObject current = objects.get(i);
g.setColor(current.getColor());
g.fillOval(current.getXMin(), current.getYMin(), current.getXSize(), current.getYSize());
}
}
public void addObject(OnScreenObject toAdd) {
objects.add(toAdd);
}
private void checkPress() {
if (myType.getDown()) {
objects.get(0).nudge(false, 3);
}
if (myType.getUp()) {
objects.get(0).nudge(false, -3);
}
if (myType.getLeft()) {
objects.get(0).nudge(true, -3);
}
if (myType.getRight()) {
objects.get(0).nudge(true, 3);
}
if (myType.getSpace()) {
fire();
}
}
private void fire() {
OnScreenObject shotBullet = new Bullet(currentShip.getXMax(), ((currentShip.getYMax() - currentShip.getYMin()) / 2) + currentShip.getYMin(), 5, getWidth(), 0, getHeight(), 0);
int shipBonus = 0;
if (currentShip.getRun() > 0) {
shipBonus = currentShip.getRun();
}
shotBullet.setMovement(0, shipBonus + 5);
addObject(shotBullet);
}
private void checkCollisions() {
for (int i = 0; i < objects.size() - 1; i++) {
for (int j = 0; j < objects.size(); j++) {
if (j != i) {
OnScreenObject current = objects.get(i);
OnScreenObject next = objects.get(j);
if (current.checkCollide(next)) {
objects.remove(i);
if (i < j) {
objects.remove(j - 1);
} else {
objects.remove(j);
}
}
}
}
}
}
private void checkDeadShip() {
if (objects.size() > 0) {
try {
currentShip = (PlayerShip) objects.get(0);
} catch (Exception e) {
System.out.println("GAME OVER!");
}
}
}
private void moveObjects() {
for (int i = 0; i < objects.size(); i++) {
OnScreenObject current = objects.get(i);
current.move();
if (!current.getVisible()) {
objects.remove(i);
}
}
}
}
if I do not have that line commented out, the
System.out.println("painting"); inside of my public void paintComponent(Graphics g) is never run, which is why I assume that paintComponent isn't running.
(I cant post images since I don't have 10 rep, but its just a JFrame with the beige empty panel look when it is not commented out).
EDIT:
In your setGraphic() method, replace the line
graphic = new ImageIcon("setto");
with this:
graphic = new ImageIcon(this.getClass()
.getResource(setto));

Images disappear when coordinates are updated, JPanel

Bah. I figured out the bug. Of course it was absurdly simple. The overridden update under MovingPanelItem needs to be written as follows:
#Override
public void update( int x, int y )
{
xCoord = xCoord + getxStep();
yCoord = yCoord + getyStep();
}
FULL DISCLOSURE: This is homework.
The PROBLEM:
Upon each Key listener event the screen should be updated and the moving objects should move. Currently, while the objects show up initially, if I press the prescribed key they disappear.
Also, all of the PanelItem's are stored in an ArrayList ( in another class ). All of the objects which are not subclasses of MovingPanelItem remain on the screen upon the KeyEvent.
I know I've left a lot to the imagination so if more detail is needed please let me know.
The superclass:
public class PanelItem
{
private Image img;
protected int xCoord;
protected int yCoord;
protected int width;
protected int height;
//constructor
public SceneItem( String path, int x, int y, int w int h )
{
xCoord = x;
yCoord = y;
setImage( path, w, h );
}
public void SetImage( String path, int w, int h )
{
width = w;
height = h;
img = ImageIO.read(new File(path));
}
//to be Overriden
public void update( int width, int height )
{
}
}
The Subclass:
public class MovingPanelItem extends PanelItem
{
private int xStep, yStep;
// x & y correspond to the coordinate plane
// w & h correspond to image width and height
// xs & ys correspond to unique randomized 'steps' in the for the x and y values
public MovingSceneItem(String path, int x, int y, int w, int h, int xs, int ys)
{
super( path, x, y, w, h);
setxStep(xs);
setyStep(ys);
update( x, y );
}
#Override
public void update( int x, int y )
{
this.xCoord = x + getxStep();
this.yCoord = y + getyStep();
}
}
(In response to Eels)
The panel/window itself is contained within the following class:
public class Panel extends JPanel {
protected ArrayList<PanelItem> panelItems;
private JLabel statusLabel;
private long randomSeed;
private Random random;
public Panel(JLabel sl) {
panelItems = new ArrayList<PanelItem>();
statusLabel = sl;
random = new Random();
randomSeed = 100;
}
private void addPanel() {
addPanelItems(10, "Mouse");
}
private void addPanelItems(int num, String type) {
Dimension dim = getSize();
dim.setSize(dim.getWidth() - 30, dim.getHeight() - 30);
synchronized (panelItems) {
for (int i = 0; i < num; i++) {
int x = random.nextInt(dim.width);
int y = random.nextInt(dim.height);
if (type.equals("Person")) {
int xs = random.nextInt(21) - 10;
int ys = random.nextInt(21) - 10;
panelItems.add(new Mouse(x, y, xs, ys));
}
}
repaint();
}
// causes every item to get updated.
public void updatePanel() {
Dimension dim = getSize();
synchronized (panelItems) {
for (PanelItem pi : panelItems) {
pi.update(dim.width, dim.height);
}
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
synchronized (panelItems) {
for (PanelItem pi : panelItems) {
pi.draw(g);
}
}
}
}
KeyListener class within the test class:
private class MyKeyListener extends KeyAdapter
{
#Override public void keyTyped(KeyEvent e)
{
if(e.getKeyChar() == 'f') {
panel.updatePanel();
panel.repaint();
}
// other key events include reseting the panel &
// creating a new panel, both of which are working.
}
}
Within the above code the only code I'm allowed to change ( & the only code I've written ) is the subclass MovingPanel item.

Categories