Well I try to make an object an image, an object that goes into an ArrayList. But I don't know how to do it. I tried several methods but none of them I tried did not work. What do you think should be added? And my object is called Apple.Thanks in advance
public class Gamepanel extends JPanel {
public void tick()
{
if(apples.size()==0)
{
//System.out.println(apples.size());
int xC=r.nextInt(79);
int yC=r.nextInt(79);
apple=new Apple(xC,yC,10);
apples.add(apple);
}
for(int i=0;i<apples.size();i++)
{
if(xC==apples.get(i).getxC()&&yC==apples.get(i).getyC())
{
size++;
score++;
apples.remove(i);
i++;
}
}
}
public void paint(Graphics g)
{
//here I draw the snake and his food
if(State==STATE.GAME)
{
g.clearRect(0, 0, WIDTH, HEIGHT);
g.setColor(Color.BLACK);
g.fillRect(0,0,WIDTH,HEIGHT);
//here i make my map of the game
for(int i=0;i<apples.size();++i)
{
apples.get(i).draw(g);
}
}
public class Apple {
private int xC,yC,width,height;
BufferedImage ap=null;
public Apple(int xC,int yC,int titleSize) {
this.xC=xC;
this.yC=yC;
width=titleSize;
height=titleSize;
}
//here i want to draw a picture for each my objects from ArrayList
public void draw(Graphics g)
{
}
I'm not sure what you're meaning by make an object an image... I don't see any code with the definition for apple...
Have you tried using Textures? You can easily create a Texture[] array containing different textures for use.
Texture[] apples = new Texture[2];
apples[0] = new Texture("apple1.png");
apples[1] = new Texture("apple2.png");
ArrayLists can also be used, but my experience with 2d games is in using libGDx (im guessing your package is graphics2D? with GDx you can...
SpriteBatch batch = new SpriteBatch();
ArrayList<Texture> apples = new ArrayList<Texture>();
//add your textures, then draw using a SpriteBatch
batch.begin();
batch.draw([texture],xpos,ypos); batch.draw(apples.get(i), 150, 500);
batch.end();
Related
I'm working on the old multi-threaded bouncing balls problem in swing. I've got everything set up so far, but I'd like to add an explosion animation when two balls collide. I've got collision detection and I can display text where the collision took place, but I was wondering on the best modular approach to creating a small animation (for example, pixels exploding 360 degrees around the point, fading out over time)
Class structure:
Ball
public class Ball {
private double x,y,dx,dy;
private static final int XSIZE = 15;
private static final int YSIZE = 15;
public Ball(){
// make x,y,dx,dy random
}
public int getX(){//}
public int getY(){//}
public Point position(){
return new Point(x,y);
}
public void move(Rectangle2D bounds){
//do movement (change x,y,dx,dy)
}
public Ellipse2D getShape(){
return new Ellipse
}
public boolean collide(Ball other){
if (this.position().distance(other.position()) < XSIZE)
return true;
return false;
}
}
BallComponent
public class BallComponent extends JPanel {
public ArrayList<Ball> balls = new ArrayList<Ball>();
private ArrayList<Color> colors = new ArrayList<Color>();
private ArrayList<Point> explosions = new ArrayList<Point>();
Random rnd = new Random();
private boolean exploding = false;
public void add(Ball b) {
balls.add(b);
colors.add(new Color(rnd.nextFloat(),rnd.nextFloat(),rnd.nextFloat()));
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for(int i=0; i<balls.size(); i++){
for(int j=0; j<i; j++){
if (balls.get(i).collide(balls.get(j))){
exploding = true;
explosions.add(balls.get(i).position());
balls.remove(i);
colors.remove(i);
balls.remove(j);
colors.remove(j);
return;
}
}
g2.setColor(colors.get(i));
g2.fill(balls.get(i).getShape());
if (exploding){
for (Point p : explosions){
g2.drawString("boom", p.x, p.y);
}
}
}
}
public void reset(){
balls = new ArrayList<Ball>();
colors = new ArrayList<Color>();
explosions = new ArrayList<Point>();
}
}
Thanks in advance
One thing you must do is get program logic out of the painting method, here the paintComponent method. You have collision detection within this method, your removing logical items from collections from within this method, you're even returning out of the method before it has fully done its primary job -- which is drawing all the components.
Instead I suggest that you re-arrange your program more along M-V-C or Model-View-Controller lines where the state of the balls is held by the model classes, the game loop controlled by the controller class, where collision detection is done in the controller using the model's state, and where the GUI classes, the "view" holds no program logic whatsoever and simply displays the state of the model.
What code should I add so that the rectangles painted before continue to exist on the screen when new ones are printed.Here is the code
import javax.sound.midi.*;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class MiniMusicPlayer3
{
private boolean fire = false;
private JFrame frame;
public static void main(String args[])
{
MiniMusicPlayer3 mini = new MiniMusicPlayer3();
mini.go();
}
public void go()
{
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600,600);
frame.setVisible(true);
MyDrawPanel boxes = new MyDrawPanel();
frame.getContentPane().add(boxes);
try
{
Sequencer player =MidiSystem.getSequencer();
player.open();
Sequence seq = new Sequence(Sequence.PPQ,4);
Track track = seq.createTrack();
int arr[] ={127};
player.addControllerEventListener(new MyDrawPanel(),arr);
//add notes to the track
for(int i = 5;i<61;i+=4)
{
track.add(makeEvent(144,1,i,100,i));
track.add(makeEvent(176,1,127,0,i));
track.add(makeEvent(128,1,i,100,(i+2)));
}
player.setSequence(seq);
player.setTempoInBPM(220);
player.start();
}
catch(Exception ex)
{
}
}
public MidiEvent makeEvent(int onOff,int one,int note,int vel,int tick)
{
MidiEvent event = null;
try
{
ShortMessage a = new ShortMessage();
a.setMessage(onOff,one,note,vel);
event = new MidiEvent(a,tick);
}
catch(Exception e)
{
}
finally
{
return event;
}
}
class MyDrawPanel extends JPanel implements ControllerEventListener
{
public void controlChange(ShortMessage message)
{
System.out.println("control change happens");
fire = true;
frame.repaint();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if(fire)
{
Graphics2D g2d = (Graphics2D)g;
int red = (int)(Math.random()*255);
int blue = (int)(Math.random()*255);
int green = (int)(Math.random()*255);
Color color = new Color(red,blue,green);
g2d.setColor(color);
int height = (int)((Math.random()*120)+10);
int width = (int)((Math.random()*120)+10);
int x = (int)((Math.random()*40)+10);
int y = (int)((Math.random()*40)+10);
g2d.fillRect(x, y, width, height);
fire = false;
}
}
}
}
Also why does the code above not let the rectangles persist as opposed to the code below that allows the circles to persist
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Animate
{
private JFrame frame;
private int x=10,y=10;
public static void main(String args[])
{
Animate ballRoll = new Animate();
ballRoll.go();
}
public void go()
{
frame = new JFrame();
frame.setSize(500,500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyRoll ball = new MyRoll();
frame.getContentPane().add(ball);
for(x = 5;x<=350;x++)
{
y=x;
try
{
Thread.sleep(50);
}
catch(Exception e)
{
System.out.println("dsfsd");
}
ball.repaint();
}
}
class MyRoll extends JPanel
{
public void paintComponent(Graphics g)
{
g.setColor(Color.ORANGE);
g.fillOval(x, y, 100, 100);
}
}
}
Replace frame.repaint() with this.repaint() and remove super.paintComponent(g) if you want to persist the previous painting as well but I never suggest you to use this approach. You have to redraw all the objects again in paintComponent().
Please have a look at below sections for detail information about Paint processing in Swing application.
Painting in AWT and Swing
The Paint processing
A Closer Look at the Paint Mechanism
"What code should I add so that the rectangles previously printed persist,instead of getting erased when the new rectangles are painted?"
Create a list of Rectangle2D object (as a class member).
Loop through the list in the paintComponent and paint each rectangle.
When you want to add a new rectangle, well, add a new rectangle to the list and repaint.
If you want different colors (or and other state) for each rectangle, create a wrapper like (See some of the examples below).
"Also why does the code above not let the rectangles persist as opposed to the code below that allows the circles to persist"
No rectangle are not "persisting" per se. What you are seeing are paint artifacts from not calling super.paintComponent which clears the previous paint. You should always call super.paintComponent though, like in your first example. So your best options is to go with the first part of my answer.
See a bunch of examples here and here and here and here and here and here.
The basic premise of all those examples is storing a list of similar object in a list and iterating through the list to paint all the objects. Each object can have its own specific state.
You could also extend your MyDrawPanel class so you keep track of which rectangles to paint plus their colors. So you could add each new rectangle to a list of rectangles and keep track of the rectangle colors using a map. Then you just need to add new rectangles to the list and the new color to the map. Finally, you'll need to loop through the list of rectangles and paint these one by one.
Here is how it could be done:
class MyDrawPanel extends JPanel implements ControllerEventListener
{
// List of all rectangles that needs to be painted
java.util.List<Rectangle> rectangles = new ArrayList<Rectangle>();
// Map over all colors for each rectangle that must be painted
Map<Rectangle, Color> rectangleColors = new HashMap<Rectangle, Color>();
public void controlChange(ShortMessage message)
{
System.out.println("control change happens");
fire = true;
frame.repaint();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if(fire)
{
Graphics2D g2d = (Graphics2D)g;
int red = (int)(Math.random()*255);
int blue = (int)(Math.random()*255);
int green = (int)(Math.random()*255);
Color color = new Color(red,blue,green);
g2d.setColor(color);
int height = (int)((Math.random()*120)+10);
int width = (int)((Math.random()*120)+10);
int x = (int)((Math.random()*40)+10);
int y = (int)((Math.random()*40)+10);
// Create a new rectangle to paint
Rectangle newRect = new Rectangle(x, y, width, height);
// Store the rectangle in the list over rectangles to paint
rectangles.add(newRect);
// Add the color of the rectangle in the map over rectangle colors
rectangleColors.put(newRect, color);
// Paint all the rectangles using their colors one by one
for (Rectangle rect : rectangles) {
// Get the color of the rectangle
Color rectColor = rectangleColors.get(rect);
// Set the rectangle color
g2d.setColor(rectColor);
// Fill the rectangle with the rectangle color
g2d.fill(rect);
}
fire = false;
}
}
}
There are two common approaches:
as has already been mentioned a couple of times, you keep a List of objects to paint and then iterate through the List in the paintComponent(...) method.
draw to a BufferedImage.
Take a look at Custom Painting Approaches which exams both of these approaches and contains working examples of both.
I'm trying to pass a graphics element up the chain. I need to have the ability to draw a number of different die and return the correct one for each instance. I can get this to compile but I don't know if i'm doing this correctly. I want to pass the graphics component to a panel to be displayed.
My shortened paint class
import java.awt.*;
import javax.swing.*;
class DiePaint extends JPanel
{
Graphics g;
public Graphics dieSwitch(int inInt)
{
return die1();
}
private Graphics die1()
{
//reset drawing
repaint();
//draw a die with 1 pip
g.setColor(Color.BLACK);
g.drawRect(0,0,50,50);
g.drawOval(24,24,2,2);
g.fillOval(24,24,2,2);
//return graphic
return g;
}
}
A method in my other class i'm trying to use to call it.
private void setDie()
{
//set die labels
die1P.paint(drawDie.dieSwitch(game.getDie(0)));
}
"I want to pass the graphics component to a panel to be displayed."
No, you don't.
You need to see how to Perform Custom Painting. You're going to need a paintComponent method in your panel
#Override
protected void paintComponent(Graphic s) {
super.paintComponent(g);
// draw here
}
You don't explicitly call paint like you are doing here die1P.paint(drawDie.dieSwitch
If you want to be able to set what is being painted, you can have a Die object that you use to draw. Something like
class Die {
public void draw(Graphics g) {
// draw die here
}
}
Then in your panel class have a setter for the Die object, that will repaint the new Die. You will probably want to have a way to differentiate each die. Pass some arguments to a constructor to do that. Then paint the one die.
public class DiePanel extends JPanel {
private Die die;
public void setDie(Die die) {
this.die = die;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (die != null) {
die.draw(g);
}
}
}
You may also, instead, want to make Die an interface, so you can implement difference Die objects, like DieOne, DieTwo, etc. Something like
public interface Die {
void Draw(Grapchis g);
}
public class DieOne {
#Override
public void draw(Graphics g) {
// draw die one
}
}
When you call setDie(), you can pass a specific Die, like
DieOne dieOne = new DieOne();
...
diePanel.setDie(dieOne);
Yes you can pass the drawn component by using BufferedImage....first you draw the graphic on this BufferedImage then pass this image and then draw this image to the Panel...Here is the code:
import java.awt.*;
import javax.swing.*;
import java.awt.image.*;
class DiePaint extends JPanel
{
int width=500; int height=500; //you can change as requred
BufferedImage buffg=new BufferedImage(width,height , BufferedImage.TYPE_INT_ARGB);
Graphics g;
public BufferedImage dieSwitch(int inInt) //change return type to BufferedImage
{
return die1();
}
private BufferedImage die1() // change return type to BufferedImage
{
g=buffg.getGraphics(); //get Graphics from buffg..
//reset drawing
repaint();
//draw a die with 1 pip
g.setColor(Color.BLACK); //draw all the component on buffg using its Graphics g
g.drawRect(0,0,50,50);
g.drawOval(24,24,2,2);
g.fillOval(24,24,2,2);
//return graphic
return buffg;
}
}
now once you get this "buffg" now you can draw it on any panel.....
JPanel p=new JPanel(){
#Override
public void paint(Graphics g){
g.drawImage(drawDie.dieSwitch(game.getDie(0))); //get & draw Image
}
};
I'm a little stump on getting a jump start on this assignment. Any help is appreciated. I have a class called MapView and it's essentially the window of where the game is going to be drawn on the panel. I currently have it iterating through the other classes/objects under the update method already. What would be the best way to iterate through the objects again to draw the game objects? I'm not sure what to do. I have draw methods under each object class also but trying to figure out how to draw those also and draw it through the iterator.
public class MapView extends JPanel implements IObserver, ActionListener{
JPanel myPanel;
private Timer timer = new Timer(5, this);
int x = 0;
int moveX = 2;
public MapView(){
super.setBorder(BorderFactory.createTitledBorder("Map:"));
myPanel = new JPanel();
}
public void update(IObservable o, Object arg){
GameWorldProxy gwp = (GameWorldProxy) o;
Iterator gameObjects = gwp.getCollection().getIterator();
while(gameObjects.hasNext()){
GameObject gameObj = (GameObject) gameObjects.getNext();
System.out.println(gameObj);
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
timer.start();
}
public void actionPerformed(ActionEvent e){
repaint();
}
}
How do I grab the current objects and iterate through them to draw it correctly on the panel?
I have found this class that draws circles with different colors. The color of each circle is determined according to a specific order of colors which iterates as it comes to the end (having used all colors by one time). I want to modify this on a way that grants me the potential to determine individually the color (on g.setColor) for each circle. In other words, I want to be able to deploy the color as a parameter and to invoke the method from another method in another class.
public class DrawingPane extends JPanel {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Rectangle rect;
for (int i = 0; i < circles.size(); i++) {
rect = circles.elementAt(i);
g.setColor(colors[(i % color_n)]);
g.fillOval(rect.x, rect.y, rect.width, rect.height);
}
}
}
If you find my question stupid I would like to let you know that what worries me is the fact that the method is inherited from JPanel and I am not sure how to override it effectively.
Your DrawingPane seems to have a list of Rectangle named circles (sic). I don't know if Rectangle is one of your classes or the standard java.awt.Rectangle.
If it's one of your class, then simply add a color attribute to this class, and get this attribute from it during your iteration.
If it's the standard java.awt.Rectangle, then introduce a Circle class, containing a Rectangle and a color, and use a list of Circle rather than a list of Rectangle.
I want to be able to deploy the color as a parameter and to invoke the method from another method in another class
Then you need to store the Color and shape as properties of a custom class.
Custom Painting Approaches shows an example of how to do this. I would use the DrawOnComponent example as a starting point. Your code will be much simpler since you don't need to handle dragging. All you need to do is create an addCircle(...) method which will take the size/location/color of the circle as parameters.
Are you looking for this ?
You are free to declare the classes MyCircle and DrawingPane in separate .Java files.
I am sure that this will give answer to " I want to be able to deploy the color as a parameter and to invoke the method from another method in another class."
public class TestingX12 {
public static void main(String args[]) {
new TestingX12();
}
public TestingX12() {
//create list of circles
List<MyCircle> circList = new ArrayList<MyCircle>();
circList.add(new MyCircle(new Rectangle(100, 20, 120, 30), Color.red));
circList.add(new MyCircle(new Rectangle(150, 50, 80, 50), Color.yellow));
circList.add(new MyCircle(new Rectangle(30, 90, 30, 110), Color.blue));
DrawingPane dp = new DrawingPane(circList);
JFrame frame = new JFrame("JToolTip Sample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(dp);
frame.setSize(400, 450);
frame.setVisible(true);
}
class MyCircle {
Rectangle rectangle;
Color color;
public MyCircle(Rectangle r, Color c) {
this.rectangle = r;
this.color = c;
}
}
public class DrawingPane extends JPanel {
List<MyCircle> circles;
public DrawingPane(List<MyCircle> circles) {
this.circles = circles;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Rectangle rect;
for (int i = 0; i < circles.size(); i++) {
rect = circles.get(i).rectangle;
g.setColor(circles.get(i).color);
g.fillOval(rect.x, rect.y, rect.width, rect.height);
System.out.println("Drawing...");
}
}
}
}
I'm not sure what you mean, but if you're trying to set the circle colors from an outside class, then make the array a property of the class with a setter and (if needed) a getter:
public class DrawingPane extends JPanel {
private Color[] colors;
public void setCircles(Color[] colors) {
this.colors = colors;
repaint();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Rectangle rect;
if (colors != null) {
for (int i = 0; i < colors.size(); i++) {
rect = circles.elementAt(i);
g.setColor(colors[(i % color_n)]);
g.fillOval(rect.x, rect.y, rect.width, rect.height);
}
}
}
}