Initial commit

This commit is contained in:
Kleme
2017-06-28 21:28:16 +02:00
parent 611a567f93
commit 9c75add9d6
17 changed files with 645 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="res"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="output" path="bin"/>
</classpath>
+2
View File
@@ -0,0 +1,2 @@
/bin/
/resources/*
+17
View File
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>MiniMario</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
+11
View File
@@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.8
Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

+23
View File
@@ -0,0 +1,23 @@
package fr.klemek.minimario;
import java.io.IOException;
import javax.swing.SwingUtilities;
public class Launch {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
new MarioWindow();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
+258
View File
@@ -0,0 +1,258 @@
package fr.klemek.minimario;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.util.Random;
public class MarioAI {
//times
private static final int MIN_STATE_TIME = 500;
private static final int MAX_STILL_TIME = 10000-MIN_STATE_TIME;
private static final int MAX_WALKING_TIME = 5000-MIN_STATE_TIME;
private static final int MAX_RUNNING_TIME = 3000-MIN_STATE_TIME;
//speeds
private static final float WALK_SPEED = 0.5f;
private static final float RUN_SPEED = 1.5f;
private static final float JUMP_SPEED_X = 0.25f;
private static final float GRAVITY = 0.25f;
private static final float MAX_JUMP_SPEED_Y = 5f;
//tiles
private static final int MARIO_STILL = 0;
private static final int MARIO_WALKING_2 = 1;
private static final int MARIO_JUMPING = 2;
private static final int MARIO_FALLING = 3;
private static final int MARIO_TURNING = 4;
private static final int MARIO_BACK = 5;
private static final int MARIO_DUCK = 6;
private static final int MARIO_WIN = 7;
private static final int MARIO_RUNNING_1 = 8;
private static final int MARIO_RUNNING_2 = 9;
private static final int MARIO_LOOK_UP = 10;
private static final int MARIO_LOOSING = 11;
private enum State{
STILL, STILL_BACK, STILL_WIN, STILL_DUCK, STILL_LOOK_UP, WALKING, RUNNING, JUMPING, LOOSING
}
private State state;
private int time, time2;
private float spdy, maxspdy;
private Point2D.Float pos;
private boolean left, wait, turn;
private Random rand;
private final int minx,maxx;
private int sizex, sizey, speedf;
public MarioAI(int sizex, int sizey, int speedf){
this.minx = Utils.getMinX();
this.maxx = Utils.getMaxX();
this.sizex = sizex;
this.sizey = sizey;
this.speedf = speedf;
this.state = State.STILL;
this.time = 0;
this.pos = new Point2D.Float();
this.rand = new Random();
}
public void setSize(int sizex, int sizey, int speedf){
this.sizex = sizex;
this.sizey = sizey;
this.speedf = speedf;
}
public void setPos(Point newpos){
this.pos = new Point2D.Float(newpos.x, newpos.y);
}
public void moved(Point newpos){
this.pos = new Point2D.Float(newpos.x, newpos.y);
this.state = State.LOOSING;
this.time2 = time;
}
public Point refresh(int refresh){
time += refresh;
Point2D.Float speed = new Point2D.Float();
switch(this.state){
case JUMPING:
speed.x = (this.left?-1f:1f)*speedf*JUMP_SPEED_X;;
this.spdy += GRAVITY*speedf;
speed.y = spdy;
if(this.spdy>=this.maxspdy){
int randi = rand.nextInt(100);
if(randi<40){ //0-39 - 40%
this.state = State.STILL;
}else if(randi<70){ //40-69 - 30%
this.state = State.WALKING;
}else{ //70-99 - 30%
this.state = State.RUNNING;
}
}
break;
case STILL_BACK:
case STILL_LOOK_UP:
case STILL_WIN:
case STILL_DUCK:
case STILL:
if(this.time2<this.time){
if(this.wait){
this.wait = false;
int randi = rand.nextInt(100);
if(randi<70){ //0-69 - 70%
this.state = State.WALKING;
}else if(randi<90){ //70-89 - 20%
this.spdy = -rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y;
this.maxspdy = rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y;
this.state = State.JUMPING;
}else{ //90-99 - 10%
boolean nextSide = rand.nextBoolean();
this.turn = this.left != nextSide;
this.left = nextSide;
this.state = State.RUNNING;
}
}else{
this.time2 = this.time+rand.nextInt(MAX_STILL_TIME)+MIN_STATE_TIME;
this.wait = true;
int randi = rand.nextInt(100);
if(randi<75){ //0-74 - 75%
this.state = State.STILL;
}else if(randi<85){ //75-84 - 10 %
this.state = State.STILL_LOOK_UP;
}else if(randi<95){ //85-94 - 10%
this.state = State.STILL_DUCK;
}else if(randi<99){ //95-99 - 4%
this.state = State.STILL_BACK;
}else{ //99 - 1%
this.state = State.STILL_WIN;
}
}
}
break;
case WALKING:
speed.x = (this.left?-1f:1f)*speedf*WALK_SPEED;
if(this.time2<this.time){
if(this.wait){
this.wait = false;
int randi = rand.nextInt(100);
if(randi<60){ //0-59 - 60%
boolean nextSide = rand.nextBoolean();
this.left = nextSide;
this.state = State.STILL;
}else if(randi<90){ //60-89 - 30%
boolean nextSide = rand.nextBoolean();
this.turn = this.left != nextSide;
this.left = nextSide;
this.state = State.RUNNING;
}else{ //90-99 - 10%
this.spdy = -rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y;
this.maxspdy = rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y;
this.state = State.JUMPING;
}
}else{
this.time2 = this.time+rand.nextInt(MAX_WALKING_TIME)+MIN_STATE_TIME;
this.wait = true;
}
}
break;
case RUNNING:
speed.x = (this.left?-1f:1f)*speedf*RUN_SPEED;;
if(this.time2<this.time){
if(this.wait){
this.wait = false;
int randi = rand.nextInt(100);
if(randi<50){ //0-49 - 50%
boolean nextSide = rand.nextBoolean();
this.turn = this.left != nextSide;
this.left = nextSide;
this.state = State.WALKING;
}else if(randi<90){ //50-89 - 40%
this.spdy = -rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y;
this.maxspdy = rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y;
this.state = State.JUMPING;
}else{ //90-99 - 10%
this.state = State.STILL;
}
}else{
this.time2 = this.time+rand.nextInt(MAX_RUNNING_TIME)+MIN_STATE_TIME;
this.wait = true;
}
}
break;
case LOOSING:
if(this.time-this.time2>100){
this.time2 = this.time+rand.nextInt(MAX_STILL_TIME)+MIN_STATE_TIME;
this.wait = true;
this.state = State.STILL;
}
break;
}
this.pos = Utils.add(this.pos, speed);
if(pos.x<=minx && this.left || pos.x+sizex>=maxx && !this.left){
this.turn = true;
this.left = !this.left;
}
int[] ybounds = Utils.getYBounds((int) pos.x);
if(this.state != State.JUMPING){
if(pos.y<ybounds[0]){
this.spdy = 0f;
this.maxspdy = rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y;
this.state = State.JUMPING;
}else if(pos.y+sizey>ybounds[1]){
this.spdy = -rand.nextFloat()*speedf*MAX_JUMP_SPEED_Y;
this.maxspdy = 0f;
this.state = State.JUMPING;
}
}
return new Point((int)this.pos.x, (int)this.pos.y);
}
public int getTile(){
if(this.turn){
if(this.time%200>=100){
this.turn = false;
}
return MARIO_TURNING;
}else{
switch(this.state){
case LOOSING:
return MARIO_LOOSING;
case WALKING:
return this.time%400<200?MARIO_STILL:MARIO_WALKING_2;
case RUNNING:
return this.time%150<75?MARIO_RUNNING_1:MARIO_RUNNING_2;
case JUMPING:
return this.spdy<=1f?MARIO_JUMPING:MARIO_FALLING;
case STILL_LOOK_UP:
return MARIO_LOOK_UP;
case STILL_WIN:
return MARIO_WIN;
case STILL_BACK:
return MARIO_BACK;
case STILL_DUCK:
return MARIO_DUCK;
case STILL:
default:
return MARIO_STILL;
}
}
}
public boolean isReversed(){
return this.left;
}
}
+168
View File
@@ -0,0 +1,168 @@
package fr.klemek.minimario;
import java.awt.AWTException;
import java.awt.Color;
import java.awt.Menu;
import java.awt.MenuItem;
import java.awt.Point;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JWindow;
import javax.swing.Timer;
public class MarioWindow extends JWindow implements ActionListener {
private static final long serialVersionUID = 1L;
private static final String VERSION = "1.5";
private static final int REFRESH_MS = 20;
private static final int TILE_W = 20;
private static final int TILE_H = 24;
private TilePanel p;
private final Timer refresh;
private int factor = 2;
private MarioAI ai;
private Point initialClick;
public MarioWindow() throws IOException {
this.setBackground(new Color(0, 0, 0, 0));
this.setLocationRelativeTo(null);
this.ai = new MarioAI(TILE_W*factor,TILE_H*factor, factor);
Random r = new Random();
String tileset_name = "mario";
if(r.nextInt(100)>=90){ //90-99 - 10%
tileset_name = "luigi";
}
if(r.nextInt(100)>=99){ //99 - 1%
tileset_name += "_fire";
}
BufferedImage tileset = ImageIO.read(this.getClass().getResource("/"+tileset_name+".png"));
this.p = new TilePanel(this, tileset, TILE_W, TILE_H, factor);
this.p.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
initialClick = e.getPoint();
getComponentAt(initialClick);
}
});
this.p.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
// get location of Window
int thisX = getLocation().x;
int thisY = getLocation().y;
// Determine how much the mouse moved since the initial click
int xMoved = (thisX + e.getX()) - (thisX + initialClick.x);
int yMoved = (thisY + e.getY()) - (thisY + initialClick.y);
// Move window to this position
int X = thisX + xMoved;
int Y = thisY + yMoved;
setLocation(X, Y);
ai.moved(getLocation());
}
});
this.add(this.p);
this.refresh = new Timer(REFRESH_MS, this);
this.pack();
this.setAlwaysOnTop(true);
if (!SystemTray.isSupported()) {
System.out.println("SystemTray is not supported");
return;
}
TrayIcon trayIcon = new TrayIcon(Utils.createImage("/icon_"+tileset_name+".png", "icon"));
trayIcon.setImageAutoSize(true);
final PopupMenu popup = new PopupMenu();
Menu sizeMenu = new Menu("Change size");
popup.add(sizeMenu);
for(int i = 0; i < 5; i++){
final int f = (int)Math.pow(2, i);
MenuItem size = new MenuItem(f+"x");
size.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
setFactor(f);
}
});
sizeMenu.add(size);
}
MenuItem exit = new MenuItem("Kill it !");
exit.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
popup.add(exit);
trayIcon.setPopupMenu(popup);
trayIcon.setToolTip("MiniMario ! (version "+VERSION+")\nBy Klemek");
final SystemTray tray = SystemTray.getSystemTray();
try {
tray.add(trayIcon);
} catch (AWTException e) {
System.out.println("TrayIcon could not be added.");
}
this.setVisible(true);
this.ai.setPos(this.getLocation());
this.refresh.start();
}
private void setFactor(int factor){
this.setVisible(false);
this.factor = factor;
this.ai.setSize(TILE_W*factor,TILE_H*factor, factor);
this.p.setFactor(factor);
this.pack();
this.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(this.refresh)) {
this.setLocation(this.ai.refresh(REFRESH_MS));
this.p.setTile(this.ai.getTile(), this.ai.isReversed());
}
}
}
+66
View File
@@ -0,0 +1,66 @@
package fr.klemek.minimario;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import javax.swing.JWindow;
public class TilePanel extends JPanel {
private static final long serialVersionUID = 1L;
private final int tileWidth, tileHeight, imageWidth, imageHeight, columns, rows;
private int id, factor;
private BufferedImage image;
private boolean reversed = false;
public TilePanel(JWindow parent, BufferedImage image, int tileWidth, int tileHeight, int factor) {
super();
this.tileWidth = tileWidth;
this.tileHeight = tileHeight;
this.image = image;
this.imageWidth = image.getWidth();
this.imageHeight = image.getHeight();
this.columns = this.imageWidth / this.tileWidth;
this.rows = this.imageHeight / this.tileHeight;
System.out.println("Tileset : "+this.columns+"x"+this.rows);
this.setFactor(factor);
this.setBackground(new Color(0, 0, 0, 0));
this.setOpaque(false);
}
public void setFactor(int factor){
this.factor = factor;
Dimension size = new Dimension(tileWidth * factor, tileHeight * factor);
this.setPreferredSize(size);
this.setMinimumSize(size);
this.setMaximumSize(size);
}
@Override
public void paintComponent(Graphics g) {
g.clearRect(0, 0, tileWidth * factor, tileHeight * factor);
if (id >= 0 && id < rows * columns) {
if (reversed) {
g.drawImage(image, 0, 0, tileWidth * factor, tileHeight * factor, (1 + id % columns) * tileWidth,
(id / columns) * tileHeight, (id % columns) * tileWidth, (1 + id / columns) * tileHeight, this);
} else {
g.drawImage(image, 0, 0, tileWidth * factor, tileHeight * factor, (id % columns) * tileWidth,
(id / columns) * tileHeight, (1 + id % columns) * tileWidth, (1 + id / columns) * tileHeight, this);
}
}
g.dispose();
}
public void setTile(int id, boolean reversed) {
this.id = id;
this.reversed = reversed;
this.repaint();
}
}
+93
View File
@@ -0,0 +1,93 @@
package fr.klemek.minimario;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.net.URL;
import javax.swing.ImageIcon;
public abstract class Utils {
private static Rectangle[] bounds = new Rectangle[0];
public static Point2D.Float add(Point2D.Float p1, Point2D.Float p2) {
return new Point2D.Float(p1.x + p2.x, p1.y + p2.y);
}
public static int getMaxX() {
int maxx = 0;
GraphicsDevice[] gds = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
if(bounds.length == 0){
bounds = new Rectangle[gds.length];
}
for (int i = 0; i < gds.length; i++) {
GraphicsDevice gd = gds[i];
bounds[i] = gd.getDefaultConfiguration().getBounds();
if(bounds[i].getMaxX()>maxx){
maxx=(int) bounds[i].getMaxX();
}
}
return maxx;
}
public static int getMinX(){
int minx = 0;
GraphicsDevice[] gds = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
if(bounds.length == 0){
bounds = new Rectangle[gds.length];
}
for (int i = 0; i < gds.length; i++) {
GraphicsDevice gd = gds[i];
bounds[i] = gd.getDefaultConfiguration().getBounds();
if(bounds[i].getMinX()<minx){
minx=(int) bounds[i].getMinX();
}
}
return minx;
}
public static int[] getYBounds(int x){
if(bounds.length == 0){
GraphicsDevice[] gds = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
bounds = new Rectangle[gds.length];
for (int i = 0; i < gds.length; i++) {
GraphicsDevice gd = gds[i];
Utils.bounds[i] = gd.getDefaultConfiguration().getBounds();
}
}
int[] out = null;
for(Rectangle b:bounds){
if(x>=b.getMinX()&&x<=b.getMaxX()){
if(out == null){
out = new int[]{(int)b.getMinY(),(int)b.getMaxY()};
}else{
if(b.getMinY()<out[0])
out[0] = (int) b.getMinY();
if(b.getMaxY()>out[1])
out[1] = (int) b.getMaxY();
}
}
}
if(out == null)
out = new int[]{0,0};
return out;
}
//Obtain the image URL
public static Image createImage(String path, String description) {
URL imageURL = Utils.class.getResource(path);
if (imageURL == null) {
System.err.println("Resource not found: " + path);
return null;
} else {
return (new ImageIcon(imageURL, description)).getImage();
}
}
}