swing - creating many objects with collision properties. JAVA -
i have simple program 3 rectangles: 1 can move push of arrow keys, , 2 moving , forth on own.
when 'player' rectangle , top red collide, player driven rectangle gets put (0,0). when try collide player rectangle bottom red rectangle, not have collision properties , have no idea why.
what missing?
import java.awt.*;//needed graphics import javax.swing.*;//needed jframe window import java.awt.event.actionevent; import java.awt.event.actionlistener; import java.awt.event.keyevent; import java.awt.event.keylistener; public class javaapplication23 extends jframe implements keylistener, actionlistener { public static int x = 0; public static int y = 0; public static int x2 = 100; public static int y2 = 100; public javaapplication23() {//constructor jpanel add(new jp()); }//close jpanel contructor public static void main(string[] args) { javaapplication23 w = new javaapplication23(); w.settitle("mike awesome"); w.setsize(toolkit.getdefaulttoolkit().getscreensize()); w.setdefaultcloseoperation(jframe.exit_on_close); w.setvisible(true); w.addkeylistener(w); } public class jp extends jpanel {//start jpanel class public jp() { container c = getcontentpane(); c.setbackground(color.white);//backgraund color can changed } public void paint(graphics g) {//opens paint method super.paint(g); player(g, x, y); g.setcolor(color.red); enemylevel1(g, x2, y2); rectangle enemyblocks = new rectangle(x2, y2, 25, 25); rectangle player = new rectangle(x, y, 25, 25); enemyblocks.contains(x2, y2); player.contains(x, y); if (player.getbounds().intersects(enemyblocks.getbounds())) { x = 0; y = 0; } pause(1); repaint(); }//close paint method }//close jpanel class public static void pause(int time) { try //opens exception handling statement { thread.sleep(time); } catch (interruptedexception e) { } //captures exception } public void actionperformed(actionevent e) { } public void keytyped(keyevent e) { } public void keyreleased(keyevent e) { } public void keypressed(keyevent e) { if (e.getkeycode() == e.vk_right) { x += 20;//global variable controlling right movement repaint(); } if (e.getkeycode() == e.vk_left) { x -= 20;//global variable controlling left movement repaint(); } if (e.getkeycode() == e.vk_up) { y -= 20;//global variable controlling movement repaint(); } if (e.getkeycode() == e.vk_down) { y += 20;//global variable controlling down movement repaint(); } } public void player(graphics g, int x, int y) { g.fillrect(x, y, 30, 30); } public void enemylevel1(graphics g, int x, int y) { g.fillrect(x2, y2, 25, 25); g.fillrect(x2, y2 + 100, 25, 25); if (x2 < 200 && y2 == 100) { x2 += 1; } if (x2 == 200 && y2 >= 100) { y2 += 1; } if (x2 <= 200 && y2 >= 101) { x2 -= 1; } if (x2 == 100 && y2 <= 101) { y2 -= 1; } pause(10); repaint(); } }
start having @ working geometry, allow reduce of code complexity.
basically, enemy rectangle
, graphics2d
can paint these without of issue. need create instance can update it's position based on needs
public class enemy extends rectangle { private int xdelta; public enemy(int x, int y) { super(x, y, 20, 20); if (x == 0) { xdelta = 1; } else { xdelta = -1; } } public void update(rectangle bounds) { x += xdelta; if (x < bounds.x) { x = bounds.x; xdelta *= -1; } else if (x > bounds.x + bounds.width - width) { x = bounds.x + bounds.width - width; xdelta *= -1; } } }
so, creates single unit of work, isolated else , carries it's own logic it. makes updating it, painting , working simpler.
next, need create list
of these
public class bounce extends jpanel implements keylistener, actionlistener { private list<enemy> enemies; //... public bounce() { enemies = new arraylist<>(5); int y = 100; (int index = 0; index < 5; index++) { int x = (index % 2 == 0) ? 0 : 200; enemy enemy = new enemy(x, y); enemies.add(enemy); y += 60; }
this creates list
of enemy
s distributed evenly within container.
now, need paint them....
@override protected void paintcomponent(graphics g) {//opens paint method super.paintcomponent(g); graphics2d g2d = (graphics2d)g.create(); g2d.setcolor(color.red); (enemy enemy : enemies) { g2d.fill(enemy); } }//close paint method
nb: general convention suggests should override paintcomponent
when want perform custom painting
but don't move, kind of sucks. need way to, on regular bases, update position of enemies...
first, create simple method can call update enemies, remember, capable of updating themselves, need tell them when
public void updatestate() { rectangle bounds = new rectangle(20, 20, 200, 200); (enemy enemy : enemies) { enemy.update(bounds); } }
remember, enemy
self contained, knows how update based on constraints have provided.
and now, need call method on regular bases...
javax.swing.timer timer = new javax.swing.timer(40, new actionlistener() { @override public void actionperformed(actionevent e) { updatestate(); repaint(); } }); timer.start();
okay, schedule callback every 40 milliseconds allow call updatestate
method , repaint
component. neat because won't block event dispatching thread (making our program it's hung) notifies within context of edt, making safe update ui within - win/win :)
take @ concurrency in swing , how use swing timers more details.
okay, doesn't solve collision...
the player rectangle
, why not use same concept have enemies...
public class bounce extends jpanel implements keylistener, actionlistener { private list<enemy> enemies; private rectangle player; //... public bounce() { player = new rectangle(0, 0, 30, 30); enemies = new arraylist<>(5); //... } @override protected void paintcomponent(graphics g) {//opens paint method super.paintcomponent(g); graphics2d g2d = (graphics2d) g.create(); drawplayer(g2d); g2d.setcolor(color.red); (enemy enemy : enemies) { g2d.fill(enemy); if (player.intersects(enemy)) { player.x = 0; player.y = 0; } } }//close paint method public void drawplayer(graphics2d g) { g.fill(player); }
which ends like...
this allows add/remove enemies want , change way in enemies move, , easily
an "awesome" test code...
import java.awt.color; import java.awt.dimension; import java.awt.eventqueue; import java.awt.graphics; import java.awt.graphics2d; import java.awt.rectangle; import java.awt.event.actionevent; import java.awt.event.actionlistener; import java.awt.event.keyevent; import java.awt.event.keylistener; import java.awt.event.mouseadapter; import java.awt.event.mouseevent; 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 bounce extends jpanel implements keylistener, actionlistener { private list<enemy> enemies; private rectangle player; public static void main(string[] args) { eventqueue.invokelater(new runnable() { @override public void run() { try { uimanager.setlookandfeel(uimanager.getsystemlookandfeelclassname()); } catch (classnotfoundexception | instantiationexception | illegalaccessexception | unsupportedlookandfeelexception ex) { ex.printstacktrace(); } jframe frame = new jframe("testing"); frame.setdefaultcloseoperation(jframe.exit_on_close); frame.add(new bounce()); frame.pack(); frame.setlocationrelativeto(null); frame.setvisible(true); } }); } public bounce() { player = new rectangle(0, 0, 30, 30); enemies = new arraylist<>(5); int y = 100; (int index = 0; index < 5; index++) { int x = (index % 2 == 0) ? 0 : 200; enemy enemy = new enemy(x, y); enemies.add(enemy); y += 60; } setbackground(color.white);//backgraund color can changed timer timer = new timer(40, new actionlistener() { @override public void actionperformed(actionevent e) { updatestate(); repaint(); } }); timer.start(); setfocusable(true); requestfocusinwindow(); addmouselistener(new mouseadapter() { @override public void mouseclicked(mouseevent e) { requestfocusinwindow(); } }); addkeylistener(this); } @override public dimension getpreferredsize() { return new dimension(240, 400); } @override protected void paintcomponent(graphics g) {//opens paint method super.paintcomponent(g); graphics2d g2d = (graphics2d) g.create(); drawplayer(g2d); g2d.setcolor(color.red); (enemy enemy : enemies) { g2d.fill(enemy); if (player.intersects(enemy)) { player.x = 0; player.y = 0; } } }//close paint method public void actionperformed(actionevent e) { } public void keytyped(keyevent e) { } public void keyreleased(keyevent e) { } public void keypressed(keyevent e) { if (e.getkeycode() == e.vk_right) { player.x += 20;//global variable controlling right movement } if (e.getkeycode() == e.vk_left) { player.x -= 20;//global variable controlling left movement } if (e.getkeycode() == e.vk_up) { player.y -= 20;//global variable controlling movement } if (e.getkeycode() == e.vk_down) { player.y += 20;//global variable controlling down movement } } public void drawplayer(graphics2d g) { g.fill(player); } public void updatestate() { rectangle bounds = new rectangle(20, 20, 200, 200); (enemy enemy : enemies) { enemy.update(bounds); } } public class enemy extends rectangle { private int xdelta; public enemy(int x, int y) { super(x, y, 20, 20); if (x == 0) { xdelta = 1; } else { xdelta = -1; } } public void update(rectangle bounds) { x += xdelta; if (x < bounds.x) { x = bounds.x; xdelta *= -1; } else if (x > bounds.x + bounds.width - width) { x = bounds.x + bounds.width - width; xdelta *= -1; } } } }
Comments
Post a Comment