/****************************/ /* Bouncing Balls V2.0 1997 */ /* for Java API 1.1.3 */ /* Ju Li */ /****************************/ import java.applet.*; import java.awt.*; import java.net.*; import java.util.*; public class bounce_old extends Applet implements Runnable { // image for double-buffering. Image backBuffer,newbackBuffer; // graphics context of double-buffering. Graphics backBufferG,newbackBufferG; // overload interface Runnable's run() Thread animator; Button north,Gravity,Velocity, Restart; Checkbox checkbox; TextField T_Gravity, T_Velocity; Panel south, east; Choice choice; Color Background_Color=Color.white,Border_Color=Color.black; Image girl_img[],gold; double gravity = 300.0; double radius = 6.0; double velocity = 300.0; // in ms, for each frame of animation int delay = 100; // geometry of the animation box int Box_Width=200,Box_Height=200,bx,by; // list of past trajectories for grabbed ball int stacklength=50, ip=-1, ip_omit=5; long last_time[] = new long [stacklength]; double last_x[] = new double [stacklength]; double last_y[] = new double [stacklength]; int girl_x_stacklength=10, girl_x_ip=0; double girl_saved_x[] = new double [girl_x_stacklength]; boolean one_round=false,pause=false,mute=true,first_time=true; boolean up=false,left=false,right=false,dead=false,gamestart=false; int total_ball_no = 3; // total number of balls int ball_no=1; // number of balls in displaying int min_ball=0; // which ball is caught bu mouce String S_ball_no; // parameter get from Choice Ball[] ball= {new Ball(), new Ball(), new Ball()}; int girl_no = 6; // number of images for girl int girl_cur=0, score=0, score_old=1; // index for which girl_img is currently on screen // 0--stand, 1--left, 2--right, 3--down, 4--up, 5--dead. double girl_x,girl_y,gold_x,gold_y,gold_width,gold_height; double girl_width[], girl_height[]; double girl_rep_x[]=new double[5],girl_rep_y[]=new double[5]; double girl_vx=0.,girl_vy=0.,girl_initial_vy=0.,girl_x_increment=1.; // double girl_timescale=100*1E-3,tmp; // peacetime is the time in seconds after start // that girl can move around without jeopardy. double program_start, run_start, peacetime=1., tmp; Font myfont = new Font("TimesRoman",Font.PLAIN,14); Beeper simplebeeper = new Beeper(); public void init() { String arg; int i; // get parameters from applet tag fields arg = getParameter("delay"); if (arg != null) delay = Integer.parseInt(arg); arg = getParameter("Box_Width"); if (arg != null) Box_Width = Integer.parseInt(arg); arg = getParameter("Box_Height"); if (arg != null) Box_Height = Integer.parseInt(arg); arg = getParameter("gravity"); if (arg != null) gravity = (Double.valueOf(arg)).doubleValue(); arg = getParameter("radius"); if (arg != null) radius = (Double.valueOf(arg)).doubleValue(); arg = getParameter("velocity"); if (arg != null) velocity = (Double.valueOf(arg)).doubleValue(); arg = getParameter("peacetime"); if (arg != null) peacetime = (Double.valueOf(arg)).doubleValue(); arg = getParameter("girl_x_increment"); if (arg != null) girl_x_increment=(Double.valueOf(arg)).doubleValue(); arg = getParameter("girl_initial_vy"); if (arg != null) girl_initial_vy=(Double.valueOf(arg)).doubleValue(); setLayout(new BorderLayout()); // North source lists add ("North",north=new Button("Click to see source for this applet")); // South Buttons and TextFields Panel south = new Panel(); add ("South", south); south.setLayout(new FlowLayout()); south.add(Gravity = new Button ("Change g")); south.add(T_Gravity = new TextField (Integer.toString((int)gravity,10), 4)); south.add(Velocity = new Button ("Change v")); south.add(T_Velocity = new TextField (Integer.toString((int)velocity,10), 4)); // East Checkbox Panel east= new Panel(); add ("East", east); east.setLayout(new GridLayout(3,1)); choice = new Choice(); choice.addItem("One"); choice.addItem("Two"); choice.addItem("Three"); east.add(choice); checkbox = new Checkbox("Mute",null,true); east.add(checkbox); east.add(Restart = new Button ("Restart")); // Center animation box bx = bounds().x+(size().width-Box_Width)/3; by = bounds().y+(size().height-Box_Height)/2; for ( i=0; i< total_ball_no; i++) { String fillin_color; ball[i].radius = radius; ball[i].x = ball[i].radius + (Box_Width-2*ball[i].radius)*Math.random(); ball[i].y = ball[i].radius + (Box_Height-2*ball[i].radius)*Math.random(); // Initialize balls tmp = Math.random() * Math.PI * 2.; ball[i].vx = velocity*Math.cos(tmp); ball[i].vy = velocity*Math.sin(tmp); fillin_color = getParameter("Ball_Fillin_Color"); ball[i].Fillin_Color = ball[i].colorFromString(fillin_color,Color.black); ball[i].Fillin_Color = Color.black; } arg = getParameter("Background_Color"); Background_Color = ball[0].colorFromString (arg,Color.white); setBackground(Background_Color); setBackground(Color.white); arg = getParameter("Border_Color"); Border_Color = ball[0].colorFromString (arg,Color.black); Border_Color = Color.black; // Create double buffer with getSize of the animation box backBuffer = createImage(Box_Width+1,Box_Height+1); backBufferG = backBuffer.getGraphics(); //load resource images for gold gold = getImage (getCodeBase(), "Images/mygold_small.xbm"); //load resource images for running girl girl_img = new Image[girl_no]; girl_width = new double[girl_no]; girl_height = new double[girl_no]; for (i=0;i Box_Width-ball[min_ball].radius) ball[min_ball].x =Box_Width-ball[min_ball].radius; if (ball[min_ball].y < ball[min_ball].radius) ball[min_ball].y = ball[min_ball].radius; if (ball[min_ball].y > Box_Height-ball[min_ball].radius) ball[min_ball].y = Box_Height-ball[min_ball].radius; getAppletContext().showStatus (ball[min_ball].x+" "+ball[min_ball].y+" ball grabbed"); repaint(); return true; } return false; } public boolean mouseDrag(Event evt, int x, int y) { if (!dead) { ball[min_ball].x = x - bx; ball[min_ball].y = y - by; if (ball[min_ball].x < ball[min_ball].radius) ball[min_ball].x = ball[min_ball].radius; if (ball[min_ball].x > Box_Width-ball[min_ball].radius) ball[min_ball].x = Box_Width-ball[min_ball].radius; if (ball[min_ball].y < ball[min_ball].radius) ball[min_ball].y = ball[min_ball].radius; if (ball[min_ball].y > Box_Height-ball[min_ball].radius) ball[min_ball].y = Box_Height-ball[min_ball].radius; getAppletContext().showStatus (ball[min_ball].x+" "+ball[min_ball].y+" ball dragged"); // save the dragged trajectory in a stack which goes around: ip ++; if (ip == stacklength) { ip -= stacklength; one_round = true; } last_time[ip] = System.currentTimeMillis(); last_x[ip] = ball[min_ball].x; last_y[ip] = ball[min_ball].y; repaint(); return true; } return false; } public synchronized boolean mouseUp(Event evt, int x, int y) { if(!dead) { // take a segment of the trajectory to estimate the ball velocity int first_ip,last_ip; last_ip=(ip>ip_omit)?(ip-ip_omit):ip; if (one_round) { first_ip = ip + 1 ; if (first_ip == stacklength) first_ip = 0; } else first_ip = 0; // position still like being dragged ball[min_ball].x = x - bx; ball[min_ball].y = y - by; if (ball[min_ball].x < ball[min_ball].radius) ball[min_ball].x = ball[min_ball].radius; if (ball[min_ball].x > Box_Width-ball[min_ball].radius) ball[min_ball].x = Box_Width-ball[min_ball].radius; if (ball[min_ball].y < ball[min_ball].radius) ball[min_ball].y = ball[min_ball].radius; if (ball[min_ball].y > Box_Height-ball[min_ball].radius) ball[min_ball].y = Box_Height-ball[min_ball].radius; // velocity estimate: if (last_ip > first_ip) { long t_del = last_time[last_ip] - last_time[first_ip]; ball[min_ball].vx = (last_x[last_ip]-last_x[first_ip])/(double)t_del*1E+3; ball[min_ball].vy = (last_y[last_ip]-last_y[first_ip])/(double)t_del*1E+3; } // clear the stack ip = -1; one_round = false; print_press_p_to_pause(); pause = false; animator.resume(); return true; } return false; } public boolean handleEvent (Event event) { Double G,V; // let the system first do what it should do super.handleEvent (event); int i; // handle key press switch (event.id) { case Event.KEY_ACTION: case Event.KEY_PRESS: switch(event.key) { case 'p': case 'P': pause = (pause != true); if (pause) { getAppletContext().showStatus("Paused: press p to restart"); animator.suspend(); } else { if (!pause) { print_press_p_to_pause(); animator.resume(); } } return true; case Event.LEFT: case 'J': case 'j': { if (up) return false; girl_cur = 1; left = true; girl_x -= girl_x_increment; if ( girl_x <= 0. ) { girl_x = 0.; //if (!mute) play(getDocumentBase(), getParameter("thump")); } //set_rep_coord(); return true; } case Event.RIGHT: case 'L': case 'l': { if (up) return false; girl_cur = 2; right = true; girl_x += girl_x_increment; if ( girl_x >= Box_Width - girl_width[girl_cur] ) { girl_x = Box_Width - girl_width[girl_cur]; //if (!mute) play(getDocumentBase(), getParameter("thump")); } //set_rep_coord(); return true; } case Event.DOWN: case 'M': case 'm': { if (up) return false; girl_cur = 3; girl_y = Box_Height - girl_height[girl_cur]; //set_rep_coord(); return true; } case Event.UP: case 'K': case 'k': { if (up) return false; girl_cur = 4; up = true; girl_vy = -girl_initial_vy; i = girl_x_ip+1; if (i==girl_x_stacklength) i=0; girl_vx = (girl_saved_x[girl_x_ip]-girl_saved_x[i])/ (girl_x_stacklength*delay*(1E-3))*0.6; //set_rep_coord(); return true; } default:return false; } case Event.KEY_ACTION_RELEASE: { switch(event.key) { case Event.DOWN: { if (up) return false; girl_cur = 0; //set_rep_coord(); return true; } case Event.LEFT: left = false; return true; case Event.RIGHT: right = false; return true; default: return false; } } } // handle Button component if ((event.target instanceof Button) && (event.key==0)) { try { // show .java source of this program: if ((Button)event.target == north) { try { getAppletContext(). showDocument(new URL(getCodeBase(), getParameter("source"))); } catch (MalformedURLException e) { getAppletContext().showStatus("URL doesn't exist"); return false; } return true; } // "Change g" button pushed: else if ((Button)event.target == Gravity) { try { G = Double.valueOf(T_Gravity.getText()); } catch (NumberFormatException e) { getAppletContext().showStatus("Wrong input"); return false; } gravity = G.doubleValue(); return true; } // "Change v" button pushed: else if ((Button)event.target == Velocity) { try { V = Double.valueOf(T_Velocity.getText()); } catch (NumberFormatException e) { getAppletContext().showStatus("Wrong input"); return false; } velocity = V.doubleValue(); for (i=0; i< ball_no; i++) { tmp = Math.sqrt(ball[i].vx*ball[i].vx+ball[i].vy*ball[i].vy); if (tmp != 0.) { ball[i].vx *= velocity / tmp; ball[i].vy *= velocity / tmp; } else { tmp = Math.random() * Math.PI * 2.; ball[i].vx = velocity*Math.cos(tmp); ball[i].vy = velocity*Math.sin(tmp); } } return true; } // if the Restart button pressed, start the game, score=0 else if ((Button)event.target == Restart) { for ( i=0; i< total_ball_no; i++) { // Initialize balls ball[i].radius = radius; ball[i].x = ball[i].radius + (Box_Width-2*ball[i].radius)*Math.random(); ball[i].y = ball[i].radius + (Box_Height-2*ball[i].radius)*Math.random(); tmp = Math.random() * Math.PI * 2.; ball[i].vx = velocity*Math.cos(tmp); ball[i].vy = velocity*Math.sin(tmp); } getAppletContext().showStatus("Game Restarted: press p to pause"); girl_cur = 0; girl_y = Box_Height-girl_height[girl_cur]; // initialize the stack for girl positions. for (i=0;i= xmax) { //if (!mute)play(getDocumentBase(), getParameter("thump")); ball[i].x = 2*xmax - ball[i].x; ball[i].vx = - ball[i].vx; } if (ball[i].y <= ymin) { //if (!mute) play(getDocumentBase(), getParameter("thump")); if (gravity == 0.) { ball[i].y = 2*ymin - ball[i].y; ball[i].vy = - ball[i].vy; } else { y_old = ball[i].y - delay*(1E-3)*(ball[i].vy+vy_old[i])/2.; if (ymin - y_old < 0) { tc = (-vy_old[i]-Math.sqrt(vy_old[i]*vy_old[i]+ 2*gravity*(ymin-y_old)))/gravity; vy_c = vy_old[i] + tc * gravity; ball[i].vy = -vy_c + (delay*(1E-3)-tc) * gravity; } else { tc = 0.; vy_c = 0.; ball[i].vy = 0.; } // ignore all multiple collisions, avoid singularity at vy = 0. if (ball[i].vy < 0.0001) { ball[i].vy = 0.; ball[i].y = ymin; } else ball[i].y = ymin+(-vy_c+ball[i].vy)*(delay*(1E-3)-tc)/2.; //if (vy_c<-2.) //if (!mute) play(getDocumentBase(), getParameter("thump")); } } if (ball[i].y >= ymax) { if (gravity == 0) { ball[i].y = 2*ymax - ball[i].y; ball[i].vy = - ball[i].vy; } else { y_old = ball[i].y-delay*(1E-3)*(ball[i].vy+vy_old[i])/2.; if (ymax-y_old > 0) { tc = (-vy_old[i]+Math.sqrt(vy_old[i]*vy_old[i]+ 2*gravity*(ymax-y_old)))/gravity; vy_c = vy_old[i] + tc * gravity; ball[i].vy = -vy_c + (delay*(1E-3)-tc) * gravity; } else { tc = 0.; vy_c = 0.; ball[i].vy = 0.; } // ignore all multiple collisions, avoid singularity at vy = 0. if (ball[i].vy > -0.0001) { ball[i].vy = 0.; ball[i].y = ymax; } else ball[i].y = ymax + (-vy_c+ball[i].vy)*(delay*(1E-3)-tc)/2.; //if (vy_c>2.) //if (!mute) play(getDocumentBase(), getParameter("thump")); } } repaint(); } // if girl has jumped: if (up) { girl_vy_old = girl_vy; girl_vy += delay*(1E-3)*gravity*2.0; girl_y += delay*(1E-3)*(girl_vy+girl_vy_old)/2.; girl_x += delay*(1E-3)*girl_vx; } if (girl_y < 2) { girl_y = 2.; girl_vy = 0.; } if (girl_y > Box_Height-girl_height[girl_cur]) { girl_cur = 0; girl_y = Box_Height-girl_height[girl_cur]; girl_vy = 0.; //set_rep_coord(); up = false; } if (!gamestart) gamestart = (System.currentTimeMillis()-run_start)/1000.>peacetime; if (girl_x > Box_Width - girl_width[girl_cur]) girl_x = Box_Width - girl_width[girl_cur]; if (girl_x < 2) girl_x = 2.; girl_between_x = ((girl_x>gold_x) && (girl_xgold_x) && (girl_x+girl_width[girl_cur]gold_y) && (girl_ygold_y) && (girl_y+girl_height[girl_cur]girl_x) && (gold_xgirl_x) && (gold_x+gold_widthgirl_y) && (gold_ygirl_y) && (gold_y+gold_height Box_Height-girl_height[girl_cur]) girl_y = Box_Height-girl_height[girl_cur]; dead = true; repaint(); animator.suspend(); } } repaint(); } public void print_press_p_to_pause() { int i; double bit_in_second = 1.; if ((System.currentTimeMillis()-run_start)/1000. < peacetime) { String bits_from_run = "get ready"; // show time as dots ... for (i=1;i<=Math.round((peacetime-(System.currentTimeMillis()-run_start)/1000.) /bit_in_second);i++) bits_from_run = bits_from_run + "."; getAppletContext().showStatus(bits_from_run+" (press p to pause)"); } else getAppletContext().showStatus("press p to pause"); } public String getAppletInfo() { return "Ju Li 1997 "; } String[][] parameterInfo = { {"source","String","java source code URL"}, {"velocity","double","initial velocity of the ball, in screen pixel/second"}, {"gravity","double","gravity acceleration, in screen pixel/second^2"}, {"delay","int","time inteval of animation in millisecond"}, {"radius","double","radius of the ball, in screen pixels"}, {"Box_Width","int","width of the animation box"}, {"Box_Height","int","height of the animation box"}, {"Ball_Fillin_Color","String", "RGB format like FF0000, or red,green,blue,white,black,gray"}, {"Background_Color","String", "RGB format like FF0000, or red,green,blue,white,black,gray"}, {"Border_Color","String", "RGB format like FF0000, or red,green,blue,white,black,gray"}, }; public String[][] getParameterInfo() { return parameterInfo; } }