/* package magball; */ import java.applet.*; import java.awt.*; public class magball3 extends Applet implements Runnable{ Thread mThread = null; private Graphics g; private Rectangle r; public final int NUM_WALLS = 8; public int wStage = 1; private point mouse = new point(100,100); public int diff = 0; public wall[] walls = new wall[NUM_WALLS + 10]; public ball[] balls = new ball[wStage + 10]; private void nextLevel(Graphics g){ diff = diff + (50 - diff) / 5; wStage = wStage + 1; paint(g); } private void display(Graphics g){ for (int h = 1; h <= wStage; h++){ balls[h].accel(mouse); for (int i = 1; i <= NUM_WALLS; i++){ if (walls[i].bounce(balls[h],balls[h].size.x/2)) if (walls[i].win && (balls[h].vel.length() < 1.0)) nextLevel(g); for (int h2 = 1; h2 < wStage; h2++){ /** Ball for kollisjon **/ int h3 = (h + h2 - 1) % wStage + 1; if (balls[h].bounce(balls[h3].pos,(balls[h].size.x + balls[h3].size.x)/2)){ for (int j = 1; j <= NUM_WALLS; j++){ // ny bounce dersom hjørne if (walls[j].bounce(balls[h],balls[h].size.x/2)) if (walls[j].win && (balls[h].vel.length() < 1.0)) nextLevel(g); balls[h].bounce(balls[h3].pos,(balls[h].size.x + balls[h3].size.x)/2); } } } } balls[h].move(g); } } public void paint(Graphics g){ int leftFloor = 0; int leftTilt = 0; int pile = 0; for (int h = 1; h <= wStage; h++){ balls[h] = new ball(g,550 * h / (wStage + 1),80,30 + h * 10,30 + h * 10); } Rectangle r = g.getClipRect(); g.clearRect(r.x, r.y, r.width, r.height); g.setPaintMode(); g.setColor(Color.white); g.fillRect(0,0,550,270); g.setColor(Color.black); if (wStage == 3) leftFloor = 140; if (wStage > 2) leftTilt = 30; if (wStage > 3) pile = 60; if (wStage > 4) pile = 110; walls[1] = new wall(0,0,diff,270 - leftFloor -leftTilt); // down walls[2] = new wall(0,0,200 - diff,leftTilt); // right walls[3] = new wall(0,0,diff,- 130 + leftFloor + pile); // 1/2 up walls[4] = new wall(0,0,50 - diff,0); // 1/8 right walls[5] = new wall(0,0,0,130 - pile); // 1/2 down walls[6] = new wall(0,0,300,-50); // right walls[7] = new wall(0,0,0,- 220 ); // up walls[8] = new wall(0,0,- 550,0); // right walls[9] = new wall(0,0,0,0); walls[4].win = true; if (wStage != 2) walls[2].power = 2.0; if (wStage > 2) walls[6].power = 2.0; if (wStage > 4) walls[7].power = 2.0; for (int i = 1; i <= NUM_WALLS; i++){ walls[i].B.add(walls[i].B,walls[i].A); walls[i + 1].A.assign(walls[i].B); walls[i].init(); g.setColor(Color.red); if (walls[i].power > 1.0) g.setColor(Color.yellow); if (walls[i].win) g.setColor(Color.green); g.drawLine((int) walls[i].A.x,(int) walls[i].A.y ,(int) walls[i].B.x,(int) walls[i].B.y); } } public void start(){ if (mThread == null){ mThread = new Thread(this); mThread.start(); } } public void stop(){ if (mThread != null){ mThread.stop(); mThread = null; } } public void run(){ g = getGraphics(); repaint(); while (true){ try{ display(g); Thread.sleep(50); } catch (InterruptedException e){ stop(); } } } public boolean mouseMove(Event evt, int x, int y){ mouse.init((double) x,(double) y); return true; } } class point { public double x = 0,y = 0; public point(double p_x, double p_y){ x = p_x; y = p_y; } public void init(double p_x, double p_y){ x = p_x; y = p_y; } public void assign(point a){ x = a.x; y = a.y; } public void mult(double a, point b){ x = a * b.x; y = a * b.y; } public void add(point a, point b){ x = a.x + b.x; y = a.y + b.y; } public void sub(point a, point b){ x = a.x - b.x; y = a.y - b.y; } public double square(point a){ return (a.x - this.x)*(a.x - this.x) + (a.y - this.y)*(a.y - this.y); } public double length(){ return Math.sqrt(x*x + y*y); } public void set_length(double a){ mult(a / length(),this); } public void corner(point A){ init(A.x / Math.abs(A.x),A.y / Math.abs(A.y)); } } class ball{ public final int MAX_VEL = 14; public point size = new point(0,0); public point acc = new point(0,0); public point vel = new point(0,0); public point pos = new point(50,50); public point p = new point(50,50); public wall t_wall = new wall(0,0,1,1); public point t_p = new point(0,0); ball(Graphics g, double posx, double posy, double sizex, double sizey ){ pos.init(posx,posy); size.init(sizex,sizey); p.assign(pos); } public void move(Graphics g){ g.setColor(Color.white); display(g,p); g.setColor(Color.black); display(g,pos); } public void display(Graphics g,point A){ g.drawOval((int) (A.x - size.x / 2 + 2) ,(int) (A.y - size.y / 2 + 2) ,(int) size.x -3 ,(int) size.y -3); } public void accel(point mouse){ p.assign(pos); acc.sub(pos,mouse); // finne distanse til mus acc.mult(Math.pow(500/ (pos.square(mouse) + 10),2),acc); acc.y += 0.5; // addere gravitasjon vel.add(vel,acc); // øke hastighet if (vel.length() > MAX_VEL) vel.set_length(MAX_VEL); // sette maks fart pos.add(pos,vel); // Ny posisjon } public boolean bounce(point edge, double radius){ boolean ret = false; t_wall.A.assign(p); t_wall.B.assign(pos); t_wall.init(); t_wall.dist(edge); if (t_wall.length < radius){ double t = Math.sqrt(radius*radius - t_wall.D.y*t_wall.D.y); t = t_wall.D.x - (t / t_wall.length); t_p.mult(t,t_wall.E); t_p.sub(t_wall.A,t_p); // Punktet hvor radius treffer t_p.sub(t_p,edge); t_p.init(t_p.y, - t_p.x); // Parallell med treff-flate t_wall.A.add(edge,t_p); t_wall.B.sub(edge,t_p); t_wall.init(); t_wall.bounce(this, radius); // Sprett på denne! ret = true; } return ret; } } class wall { public point A = new point(0,0); public point B = new point(0,0); public point D = new point(0,0); // returnerer parallelltall og distanse public point E = new point(0,0); // AB public point F = new point(0,0); // __AB public point G = new point(0,0); // temp public double length = 0; private double k1 = 0; private double k2 = 0; public boolean win = false; public double power = 1.0; public wall(double a,double b,double c,double d){ A.init(a,b); B.init(c,d); } public void init(){ E.init(B.x - A.x, B.y - A.y); // vector AB F.init(E.y, - E.x); // vinkelrett vector AB length = E.length(); // lengden av AB k1 = 1/ (E.x * E.x + E.y * E.y); // kalkuleringsforhold k2 = k1 * length; } public void dist(point C){ G.sub(C,A); // AC D.x = (G.y * E.y + G.x * E.x) * k1; D.y = (G.y * E.x - G.x * E.y) * k2; } public boolean bounce(ball b, double radius){ dist(b.pos); boolean ret = false; if (Math.abs(D.y) < radius){ // innenfor distanse if (D.x >= 0 && D.x <= 1.0){ // innenfor start/stop // Sette nytt punkt = pos + (Size - D.y) * __AB / length G.mult((radius * 2 - 2 * Math.abs(D.y))/length,F); b.pos.add(b.pos,G); // sette ny fart snudd rundt innfall/utfallsvinkel G.add(b.vel,A); dist(G); G.mult(2 * D.x, E); b.vel.sub(G,b.vel); b.vel.mult(power,b.vel); brake(b.vel); ret = true; } else { // if radius til et av punktene if (D.x < 0.5) b.bounce(A,radius); // sette ny farts-retning else b.bounce(B,radius); } } return ret; } public void brake(point vel){ G.corner(vel); G.mult(0.2,G); vel.sub(vel,G); } }