Marios kicking each-other and code organization

This commit is contained in:
Kleme
2017-09-14 13:36:42 +02:00
parent c584472bb7
commit 4ee557a0b8
4 changed files with 170 additions and 72 deletions
+25 -29
View File
@@ -17,10 +17,9 @@ import javax.swing.SwingUtilities;
public abstract class Launch { public abstract class Launch {
private static final String VERSION = "1.7.1"; private static final String VERSION = "1.7.2";
private static List<MarioWindow> windows;
private static TrayIcon trayIcon;
private static PopupMenu popup; private static PopupMenu popup;
private static Menu sizeMenu; private static Menu sizeMenu;
private static MenuItem add, split, kill, exit; private static MenuItem add, split, kill, exit;
@@ -29,14 +28,12 @@ public abstract class Launch {
public static void main(String[] args) { public static void main(String[] args) {
windows = new ArrayList<>();
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {
windows.add(new MarioWindow(null, currentFactor, null)); new MarioWindow(null, currentFactor, null);
addTrayIcon(windows.get(0)); addTrayIcon(MarioWindow.getAll().get(0));
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
@@ -50,7 +47,7 @@ public abstract class Launch {
System.exit(0); System.exit(0);
} }
TrayIcon trayIcon = new TrayIcon(Utils.createImage("/icon_"+mwRef.getTilesetName()+".png", "icon")); trayIcon = new TrayIcon(Utils.createImage("/icon_"+mwRef.getTilesetName()+".png", "icon"));
trayIcon.setImageAutoSize(true); trayIcon.setImageAutoSize(true);
popup = new PopupMenu(); popup = new PopupMenu();
@@ -63,10 +60,10 @@ public abstract class Launch {
size.addActionListener(new ActionListener(){ size.addActionListener(new ActionListener(){
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
for(MarioWindow mw:windows) for(MarioWindow mw:MarioWindow.getAll())
mw.setFactor(f); mw.setFactor(f);
currentFactor = f; currentFactor = f;
refreshPopupMenu(); refreshTray();
} }
}); });
sizeMenu.add(size); sizeMenu.add(size);
@@ -77,8 +74,8 @@ public abstract class Launch {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
try { try {
windows.add(new MarioWindow(null, currentFactor, null)); new MarioWindow(null, currentFactor, null);
refreshPopupMenu(); refreshTray();
} catch (IOException e1) { } catch (IOException e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
@@ -90,17 +87,17 @@ public abstract class Launch {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
List<MarioWindow> save = new ArrayList<>(); List<MarioWindow> save = new ArrayList<>();
save.addAll(windows); save.addAll(MarioWindow.getAll());
windows.clear(); MarioWindow.getAll().clear();
currentFactor /= 2; currentFactor /= 2;
for(MarioWindow mw:save){ for(MarioWindow mw:save){
try { try {
MarioWindow child1 = new MarioWindow(mw.getCenter(), currentFactor, mw.getTilesetName()); MarioWindow child1 = new MarioWindow(mw.getCenter(), currentFactor, mw.getTilesetName());
MarioWindow child2 = new MarioWindow(mw.getCenter(), currentFactor, mw.getTilesetName()); MarioWindow child2 = new MarioWindow(mw.getCenter(), currentFactor, mw.getTilesetName());
child1.getAi().run(false); child1.getAi().setInvicible(true);
child2.getAi().run(true); child2.getAi().setInvicible(true);
windows.add(child1); child1.getAi().jump(false);
windows.add(child2); child2.getAi().jump(true);
} catch (IOException e1) { } catch (IOException e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
@@ -108,7 +105,7 @@ public abstract class Launch {
} }
save = null; save = null;
System.gc(); System.gc();
refreshPopupMenu(); refreshTray();
} }
}); });
@@ -117,11 +114,11 @@ public abstract class Launch {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
Random r = new Random(); Random r = new Random();
int index = r.nextInt(windows.size()); int index = r.nextInt(MarioWindow.getAll().size());
windows.get(index).kill(); MarioWindow.getAll().get(index).kill();
windows.remove(index); MarioWindow.getAll().remove(index);
System.gc(); System.gc();
refreshPopupMenu(); refreshTray();
} }
}); });
@@ -133,11 +130,8 @@ public abstract class Launch {
} }
}); });
refreshTray();
refreshPopupMenu();
trayIcon.setPopupMenu(popup); trayIcon.setPopupMenu(popup);
trayIcon.setToolTip("MiniMario ! (version "+VERSION+")\nBy Klemek");
final SystemTray tray = SystemTray.getSystemTray(); final SystemTray tray = SystemTray.getSystemTray();
try { try {
@@ -148,18 +142,20 @@ public abstract class Launch {
} }
} }
private static void refreshPopupMenu(){ private static void refreshTray(){
popup.removeAll(); popup.removeAll();
popup.add(sizeMenu); popup.add(sizeMenu);
popup.add(add); popup.add(add);
if(currentFactor > 1){ if(currentFactor > 1){
popup.add(split); popup.add(split);
} }
if(windows.size()>1){ if(MarioWindow.getAll().size()>1){
exit.setLabel("Kill them all !"); exit.setLabel("Kill them all !");
popup.add(kill); popup.add(kill);
trayIcon.setToolTip(MarioWindow.getAll().size()+" MiniMarios ! (version "+VERSION+")\nBy Klemek");
}else{ }else{
exit.setLabel("Kill it !"); exit.setLabel("Kill it !");
trayIcon.setToolTip("MiniMario ! (version "+VERSION+")\nBy Klemek");
} }
popup.add(exit); popup.add(exit);
} }
+90 -34
View File
@@ -3,7 +3,8 @@ package fr.klemek.minimario;
import java.awt.Point; import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.util.Random; import java.util.ArrayList;
import java.util.List;
public class MarioAI { public class MarioAI {
@@ -47,8 +48,7 @@ public class MarioAI {
private Point2D.Float pos; private Point2D.Float pos;
private boolean left, wait, turn; private boolean left, wait, turn, kicked, invicible;
private static Random rand = new Random();
private final int minx,maxx; private final int minx,maxx;
private int sizex, sizey, speedf; private int sizex, sizey, speedf;
@@ -56,7 +56,7 @@ public class MarioAI {
//constructor //constructor
public MarioAI(int sizex, int sizey, int speedf){ public MarioAI(int sizex, int sizey, int speedf){
this.id = rand.nextInt(); this.id = Utils.nextInt();
this.minx = Utils.getMinX(); this.minx = Utils.getMinX();
this.maxx = Utils.getMaxX(); this.maxx = Utils.getMaxX();
this.sizex = sizex; this.sizex = sizex;
@@ -86,7 +86,10 @@ public class MarioAI {
this.spdy += GRAVITY*speedf; this.spdy += GRAVITY*speedf;
speed.y = spdy; speed.y = spdy;
if(this.spdy>=this.maxspdy){ if(this.spdy>=this.maxspdy){
int randi = rand.nextInt(100); this.kicked = false;
this.invicible = false;
this.spdy = 0;
int randi = Utils.nextInt(100);
if(randi<40){ //0-39 - 40% if(randi<40){ //0-39 - 40%
this.state = State.STILL; this.state = State.STILL;
}else if(randi<70){ //40-69 - 30% }else if(randi<70){ //40-69 - 30%
@@ -104,23 +107,23 @@ public class MarioAI {
if(this.time2<this.time){ if(this.time2<this.time){
if(this.wait){ if(this.wait){
this.wait = false; this.wait = false;
int randi = rand.nextInt(100); int randi = Utils.nextInt(100);
if(randi<70){ //0-69 - 70% if(randi<70){ //0-69 - 70%
this.state = State.WALKING; this.state = State.WALKING;
}else if(randi<90){ //70-89 - 20% }else if(randi<90){ //70-89 - 20%
this.spdy = -rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y-speedf*MIN_JUMP_SPEED_Y; this.spdy = -Utils.nextFloat()*speedf*MAX_JUMP_SPEED_Y-speedf*MIN_JUMP_SPEED_Y;
this.maxspdy = rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y+speedf*MIN_JUMP_SPEED_Y; this.maxspdy = Utils.nextFloat()*speedf*MAX_JUMP_SPEED_Y+speedf*MIN_JUMP_SPEED_Y;
this.state = State.JUMPING; this.state = State.JUMPING;
}else{ //90-99 - 10% }else{ //90-99 - 10%
boolean nextSide = rand.nextBoolean(); boolean nextSide = Utils.nextBoolean();
this.turn = this.left != nextSide; this.turn = this.left != nextSide;
this.left = nextSide; this.left = nextSide;
this.state = State.RUNNING; this.state = State.RUNNING;
} }
}else{ }else{
this.time2 = this.time+rand.nextInt(MAX_STILL_TIME)+MIN_STATE_TIME; this.time2 = this.time+Utils.nextInt(MAX_STILL_TIME)+MIN_STATE_TIME;
this.wait = true; this.wait = true;
int randi = rand.nextInt(100); int randi = Utils.nextInt(100);
if(randi<75){ //0-74 - 75% if(randi<75){ //0-74 - 75%
this.state = State.STILL; this.state = State.STILL;
}else if(randi<85){ //75-84 - 10 % }else if(randi<85){ //75-84 - 10 %
@@ -140,23 +143,23 @@ public class MarioAI {
if(this.time2<this.time){ if(this.time2<this.time){
if(this.wait){ if(this.wait){
this.wait = false; this.wait = false;
int randi = rand.nextInt(100); int randi = Utils.nextInt(100);
if(randi<60){ //0-59 - 60% if(randi<60){ //0-59 - 60%
boolean nextSide = rand.nextBoolean(); boolean nextSide = Utils.nextBoolean();
this.left = nextSide; this.left = nextSide;
this.state = State.STILL; this.state = State.STILL;
}else if(randi<90){ //60-89 - 30% }else if(randi<90){ //60-89 - 30%
boolean nextSide = rand.nextBoolean(); boolean nextSide = Utils.nextBoolean();
this.turn = this.left != nextSide; this.turn = this.left != nextSide;
this.left = nextSide; this.left = nextSide;
this.state = State.RUNNING; this.state = State.RUNNING;
}else{ //90-99 - 10% }else{ //90-99 - 10%
this.spdy = -rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y-speedf*MIN_JUMP_SPEED_Y; this.spdy = -Utils.nextFloat()*speedf*MAX_JUMP_SPEED_Y-speedf*MIN_JUMP_SPEED_Y;
this.maxspdy = rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y+speedf*MIN_JUMP_SPEED_Y; this.maxspdy = Utils.nextFloat()*speedf*MAX_JUMP_SPEED_Y+speedf*MIN_JUMP_SPEED_Y;
this.state = State.JUMPING; this.state = State.JUMPING;
} }
}else{ }else{
this.time2 = this.time+rand.nextInt(MAX_WALKING_TIME)+MIN_STATE_TIME; this.time2 = this.time+Utils.nextInt(MAX_WALKING_TIME)+MIN_STATE_TIME;
this.wait = true; this.wait = true;
} }
} }
@@ -166,30 +169,30 @@ public class MarioAI {
if(this.time2<this.time){ if(this.time2<this.time){
if(this.wait){ if(this.wait){
this.wait = false; this.wait = false;
int randi = rand.nextInt(100); int randi = Utils.nextInt(100);
if(randi<50){ //0-49 - 50% if(randi<50){ //0-49 - 50%
boolean nextSide = rand.nextBoolean(); boolean nextSide = Utils.nextBoolean();
this.turn = this.left != nextSide; this.turn = this.left != nextSide;
this.left = nextSide; this.left = nextSide;
this.state = State.WALKING; this.state = State.WALKING;
}else if(randi<90){ //50-89 - 40% }else if(randi<90){ //50-89 - 40%
this.spdy = -rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y-speedf*MIN_JUMP_SPEED_Y; this.spdy = -Utils.nextFloat()*speedf*MAX_JUMP_SPEED_Y-speedf*MIN_JUMP_SPEED_Y;
this.maxspdy = rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y+speedf*MIN_JUMP_SPEED_Y; this.maxspdy = Utils.nextFloat()*speedf*MAX_JUMP_SPEED_Y+speedf*MIN_JUMP_SPEED_Y;
this.state = State.JUMPING; this.state = State.JUMPING;
}else{ //90-99 - 10% }else{ //90-99 - 10%
this.state = State.STILL; this.state = State.STILL;
} }
}else{ }else{
this.time2 = this.time+rand.nextInt(MAX_RUNNING_TIME)+MIN_STATE_TIME; this.time2 = this.time+Utils.nextInt(MAX_RUNNING_TIME)+MIN_STATE_TIME;
this.wait = true; this.wait = true;
} }
} }
break; break;
case LOOSING: case LOOSING:
if(this.time-this.time2>100){ if(this.time-this.time2>100){
int randi = rand.nextInt(100); int randi = Utils.nextInt(100);
if(randi<80){ //0-79 - 80% if(randi<80){ //0-79 - 80%
this.time2 = this.time+rand.nextInt(MAX_STILL_TIME)+MIN_STATE_TIME; this.time2 = this.time+Utils.nextInt(MAX_STILL_TIME)+MIN_STATE_TIME;
this.wait = true; this.wait = true;
this.state = State.STILL_DUCK; this.state = State.STILL_DUCK;
}else{ //80-99 - 20% }else{ //80-99 - 20%
@@ -208,32 +211,55 @@ public class MarioAI {
this.left = !this.left; this.left = !this.left;
} }
if(this.state != State.JUMPING){
int[] ybounds = Utils.getYBounds((int) pos.x); int[] ybounds = Utils.getYBounds((int) pos.x);
if(pos.y<=ybounds[0]){
if(pos.y<ybounds[0]){ this.spdy = 0;
this.spdy = Math.abs(this.spdy); this.maxspdy = Utils.nextFloat()*speedf*MAX_JUMP_SPEED_Y+speedf*MIN_JUMP_SPEED_Y;
this.maxspdy = rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y+speedf*MIN_JUMP_SPEED_Y;
this.state = State.JUMPING; this.state = State.JUMPING;
}else if(pos.y+sizey>ybounds[1]){ }else if(pos.y+sizey>ybounds[1]){
this.spdy = -rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y-speedf*MIN_JUMP_SPEED_Y; this.spdy = -Utils.nextFloat()*speedf*MAX_JUMP_SPEED_Y-speedf*MIN_JUMP_SPEED_Y;
this.maxspdy = -Math.abs(this.spdy); this.maxspdy = -Math.abs(this.spdy);
this.state = State.JUMPING; this.state = State.JUMPING;
} }
} }
if(this.spdy<=0){
Rectangle bounds = this.getBounds();
for(MarioAI ma:getOthers(this.id)){
if(ma.spdy<=0 && !ma.isInvicible() && bounds.intersects(ma.getBounds())){
ma.fall();
ma.setKicked(true);
}
}
}
}
return new Point((int)this.pos.x, (int)this.pos.y); return new Point((int)this.pos.x, (int)this.pos.y);
} }
public void run(boolean left){ public void jump(boolean left){
this.turn = false; this.turn = false;
this.left = left; this.left = left;
this.time2 = this.time+rand.nextInt(MAX_WALKING_TIME); this.time2 = this.time+Utils.nextInt(MAX_WALKING_TIME);
this.wait = false; this.wait = false;
this.spdy = -rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y-speedf*MIN_JUMP_SPEED_Y; this.spdy = -Utils.nextFloat()*speedf*MAX_JUMP_SPEED_Y-speedf*MIN_JUMP_SPEED_Y;
this.maxspdy = rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y+speedf*MIN_JUMP_SPEED_Y; this.maxspdy = Utils.nextFloat()*speedf*MAX_JUMP_SPEED_Y+speedf*MIN_JUMP_SPEED_Y;
this.state = State.JUMPING; this.state = State.JUMPING;
} }
public void fall(){
int[] ybounds = Utils.getYBounds((int)this.pos.x);
if(this.pos.y-this.sizey<ybounds[1]){
this.turn = false;
this.wait = false;
this.maxspdy = Utils.nextFloat()*speedf*MAX_JUMP_SPEED_Y+speedf*MIN_JUMP_SPEED_Y;
this.spdy = 0;
this.state = State.JUMPING;
}
}
//getter/setter //getter/setter
public void setSize(int sizex, int sizey, int speedf){ public void setSize(int sizex, int sizey, int speedf){
@@ -261,7 +287,7 @@ public class MarioAI {
case RUNNING: case RUNNING:
return this.time%150<75?MARIO_RUNNING_1:MARIO_RUNNING_2; return this.time%150<75?MARIO_RUNNING_1:MARIO_RUNNING_2;
case JUMPING: case JUMPING:
return this.spdy<=MAX_JUMP_SPEED_Y/10f?MARIO_JUMPING:MARIO_FALLING; return this.spdy<=MAX_JUMP_SPEED_Y/10f?MARIO_JUMPING:this.kicked?MARIO_LOOSING:MARIO_FALLING;
case STILL_LOOK_UP: case STILL_LOOK_UP:
return MARIO_LOOK_UP; return MARIO_LOOK_UP;
case STILL_WIN: case STILL_WIN:
@@ -289,4 +315,34 @@ public class MarioAI {
return id; return id;
} }
public float getSpdy() {
return spdy;
}
public boolean isInvicible() {
return invicible;
}
public void setInvicible(boolean invicible) {
this.invicible = invicible;
}
public boolean isKicked() {
return kicked;
}
public void setKicked(boolean kicked) {
this.kicked = kicked;
}
//static functions
public static List<MarioAI> getOthers(int id){
List<MarioAI> list = new ArrayList<MarioAI>();
for(MarioWindow mw:MarioWindow.getAll())
if(mw.getAi().getId() != id)
list.add(mw.getAi());
return list;
}
} }
+16 -3
View File
@@ -9,6 +9,8 @@ import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter; import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random; import java.util.Random;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
@@ -17,7 +19,9 @@ import javax.swing.Timer;
public class MarioWindow extends JWindow implements ActionListener { public class MarioWindow extends JWindow implements ActionListener {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 797825180779341089L;
private static List<MarioWindow> windows = new ArrayList<>();
private static final int REFRESH_MS = 20; private static final int REFRESH_MS = 20;
private static final int TILE_W = 20; private static final int TILE_W = 20;
@@ -38,10 +42,13 @@ public class MarioWindow extends JWindow implements ActionListener {
public MarioWindow(Point start, int factor, String tilesetName) throws IOException { public MarioWindow(Point start, int factor, String tilesetName) throws IOException {
windows.add(this);
this.setBackground(new Color(0, 0, 0, 0)); this.setBackground(new Color(0, 0, 0, 0));
//this.setLocationRelativeTo(null);
if(start == null) if(start == null)
this.setLocationRelativeTo(null); this.setLocation(Utils.randomScreenLocation(TILE_W*factor, TILE_H*factor));
else else
this.setLocation((int)(start.x + TILE_W*factor/2f), (int)( start.y + TILE_H*factor/2f)); this.setLocation((int)(start.x + TILE_W*factor/2f), (int)( start.y + TILE_H*factor/2f));
@@ -63,7 +70,6 @@ public class MarioWindow extends JWindow implements ActionListener {
this.tilesetName = tilesetName; this.tilesetName = tilesetName;
BufferedImage tileset = ImageIO.read(this.getClass().getResource("/"+tilesetName+".png")); BufferedImage tileset = ImageIO.read(this.getClass().getResource("/"+tilesetName+".png"));
this.p = new TilePanel(this, tileset, TILE_W, TILE_H, factor); this.p = new TilePanel(this, tileset, TILE_W, TILE_H, factor);
@@ -114,6 +120,7 @@ public class MarioWindow extends JWindow implements ActionListener {
this.setVisible(false); this.setVisible(false);
} }
//events //events
@Override @Override
@@ -162,4 +169,10 @@ public class MarioWindow extends JWindow implements ActionListener {
this.setVisible(true); this.setVisible(true);
} }
//static functions
public static List<MarioWindow> getAll(){
return windows;
}
} }
+33
View File
@@ -3,9 +3,11 @@ package fr.klemek.minimario;
import java.awt.GraphicsDevice; import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment; import java.awt.GraphicsEnvironment;
import java.awt.Image; import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.net.URL; import java.net.URL;
import java.util.Random;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
@@ -13,6 +15,8 @@ public abstract class Utils {
private static Rectangle[] bounds = new Rectangle[0]; private static Rectangle[] bounds = new Rectangle[0];
protected static Random rand = new Random();
public static Point2D.Float add(Point2D.Float p1, Point2D.Float p2) { public static Point2D.Float add(Point2D.Float p1, Point2D.Float p2) {
return new Point2D.Float(p1.x + p2.x, p1.y + p2.y); return new Point2D.Float(p1.x + p2.x, p1.y + p2.y);
} }
@@ -90,4 +94,33 @@ public abstract class Utils {
return (new ImageIcon(imageURL, description)).getImage(); return (new ImageIcon(imageURL, description)).getImage();
} }
} }
//random
public static int nextInt(int min, int max){
return rand.nextInt(max-min)+min;
}
public static int nextInt(int max){
return rand.nextInt(max);
}
public static int nextInt(){
return rand.nextInt();
}
public static boolean nextBoolean(){
return rand.nextBoolean();
}
public static float nextFloat(){
return rand.nextFloat();
}
public static Point randomScreenLocation(int sizex, int sizey){
int x = nextInt(getMinX(),getMaxX()-sizex);
int[] yb = getYBounds(x);
int y = nextInt(yb[0],yb[1]-sizey);
return new Point(x,y);
}
} }