Graphics2D animation, cant understand why paintComponent only draws the shape one time and then stops. I Also can't understand why my timer counter variable isn't incrementing. I've been banging my head against this for over an hour, can anyone nudge me in the right direction?
package Tetris;
import javax.swing.JLabel;
import java.util.ArrayList;
public class Tetri {
private int xCoords= (int)(Math.random()*10);
private int yCoords=0;
private int shapeType;
private int orientation=0;
public Tetri(int shapeT){
shapeType = shapeT;
}
public int getOrient(){
return orientation;
}
public void setOrient(int orient){
orientation = orient;
}
public void setXCoords(int coords){
xCoords = coords;
}
public int getXCoords(){
return xCoords;
}
public void setYCoords(int coords){
yCoords = coords;
}
public int getYCoords(){
return yCoords;
}
public int getShape(){
return shapeType;
}
}
package Tetris;
import javax.swing.JFrame;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JPanel;
import java.awt.Color;
import javax.swing.Timer;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
public class MovingRectangle {
public static void main(String[] args){
new MovingRectangle();
}
public MovingRectangle() {
EventQueue.invokeLater(new Runnable(){
@Override
public void run(){
JFrame frame = new JFrame("Tetris");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(0,1));
frame.add(new TestPane(Color.RED));
frame.setSize(1000,800);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Graphics g0;
private int unit = 50;
private ArrayList<Tetri> shapeList = new ArrayList<Tetri>();
int timercount =1;
public TestPane(Color foreground){
setForeground(foreground);
this.setBackground(Color.BLUE);
Timer timer = new Timer(2000,new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
System.out.println("timercount :"+timercount);
timercount = timercount++;
shapeList.add(new Tetri((int)(Math.random()*2)));
System.out.println("shapeList size : "+shapeList.size());
repaint();
}
});
timer.start();
}
@Override
public void paintComponent(Graphics g){
g0 = g;
super.paintComponent(g);
if(shapeList.size()>0){
Tetri current = shapeList.get(0);
if(current.getShape()==0){
createShape0(current.getXCoords(),current.getYCoords(),current.getOrient());
}
if(current.getShape()==1){
createShape1(current.getXCoords(),current.getYCoords(),current.getOrient());
}
current.setYCoords(current.getYCoords()+50);
}
else{shapeList.add(new Tetri((int)(Math.random()*2)));}
}
public void createShape0(int xc,int yc,int orien){
int yPixel= yc*50;
int xPixel= xc*50;
Graphics2D g2d = (Graphics2D) g0.create();
g2d.setColor(Color.RED);
if(orien==0){
g2d.drawRect(xPixel, yPixel, unit*4, unit);
}
if(orien==1){
g2d.drawRect(xPixel, yPixel, unit, unit*4);
}
}
public void createShape1(int xc,int yc, int orien){
int yPixel= yc*50;
int xPixel= xc*50;
Graphics2D g2d = (Graphics2D) g0.create();
g2d.setColor(Color.GREEN);
if(orien==0){
g2d.drawRect(xPixel, yPixel, unit*3, unit);
g2d.drawRect(xPixel+50, yPixel+50,unit,unit);
}
if(orien==1){
g2d.drawRect(xPixel+50, yPixel-50, unit, unit*3);
g2d.drawRect(xPixel, yPixel,unit,unit);
}
if(orien==2){
g2d.drawRect(xPixel, yPixel, unit*3, unit);
g2d.drawRect(xPixel+50, yPixel-50,unit,unit);
}
if(orien==3){
g2d.drawRect(xPixel+50, yPixel-50, unit, unit*3);
g2d.drawRect(xPixel+100, yPixel,unit,unit);
}
}
}
}
I have a list of things, but lets start with the most obvious.
You "movement" calculations are way off.
int yPixel = yc * 50;
int xPixel = xc * 50;
This is causing your shape to "jump" expectational larger distances...in fact, I can't find any reason for you to "modify" these values at all. Simply making them read as...
int yPixel = yc;
int xPixel = xc;
Got the shape moving just fine...
Code Review
Graphics2D g2d = (Graphics2D) g.create();
) then you are responsible for disposing of it (g2d.dispose()
) when you are done with it. Otherwise you will slowly consume system resources until your application crashes (talking from experience - it's a hard bug to find ;))You seem to be going about the process the hard way. You should create a class for each Shape
, based off the Tetri
that knows how to "draw" itself. That way you would simple pass the graphics context to it in your paint loop and not care. This makes is significantly easier to add new pieces over time.
If you base each of these pieces off a java.awt.Shape
, it becomes significantly easier to transform the shape and rotate them.
Take a look at 2D Graphics, in particular, Working with Geometry