Pedu -Physics EDUcation- by YUKI ozawa This sample is processing demo for physics education. / import fisica.*; import guicomponents.*; /* configs */ boolean IS_FULLSCREEN = false; int FPS = 30; /* draw area size */ int WND_WIDTH = 800; int WND_HEIGHT = 800; /**/ enum PhyObject_t { PHYOBJECT_NONE, PHYOBJECT_CIRCLE, PHYOBJECT_BOX, }; /* */ final static int PHYOBJECT_NONE = 0; final static int PHYOBJECT_CIRCLE = 1; final static int PHYOBJECT_BOX = 2; final static int PHYOBJECT_TRIANGLE = 3; int curPhyObject = PHYOBJECT_NONE; /* initialize all */ void setup() { /* dont set drawarea from variable. applet export cant work. */ size(800,800); /**/ smooth(); frameRate( FPS ); addMouseWheelListener(new java.awt.event.MouseWheelListener() { public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) { mouseWheel(evt.getWheelRotation()); } } ); gui_init(); phy_init(); } void mouseWheel(int delta) { phy_rotobj( mouseX, mouseY, delta ); } void draw() { app_render(); fill(0); text( "FPS:"+frameRate, WND_WIDTH-70, WND_HEIGHT-8 ); } /**/ void app_render() { background(255); phy_update(); phy_draw( true ); renderMocObject_(); } /**/ void renderMocObject_() { if( !isStartSizing ) { return ; } switch( curPhyObject ) { case PHYOBJECT_NONE: break; case PHYOBJECT_CIRCLE: { float cx = (endPoint.x + startPoint.x)/2; float cy = (endPoint.y + startPoint.y)/2; float dx = (endPoint.x - startPoint.x); float dy = (endPoint.y - startPoint.y); float r = sqrt( dx*dx+dy*dy ); noFill(); stroke(204, 102, 0); ellipse(cx, cy, r, r); } break; case PHYOBJECT_BOX: { float sx = startPoint.x; float sy = startPoint.y; float w = (endPoint.x - startPoint.x); float h = (endPoint.y - startPoint.y); noFill(); stroke(204, 102, 0); rect(sx,sy,w,h); } break; case PHYOBJECT_TRIANGLE: { float sx = startPoint.x; float sy = startPoint.y; float w = (endPoint.x - startPoint.x); float h = (endPoint.y - startPoint.y); noFill(); stroke(204, 102, 0); triangle(sx, sy, sx, sy+h, sx+w, sy+h ); } break; default: print("UnKownObjectType\n"); break; } } /* change to creating circle mode */ void OnChangeCreateShape_Circle() { curPhyObject = PHYOBJECT_CIRCLE; phy_draggable( false ); print("Change to Circle mode\n"); } /* change to creating box mode */ void OnChangeCreateShape_Box() { curPhyObject = PHYOBJECT_BOX; phy_draggable( false ); print("Change to Box mode\n"); } /* change to creating triangle mode */ void OnChangeCreateShape_Triangle() { curPhyObject = PHYOBJECT_TRIANGLE; phy_draggable( false ); print("Change to Triangle mode \n"); } PVector startPoint = new PVector(); PVector endPoint = new PVector(); boolean isStartSizing = false; /**/ void mousePressed() { /* on press right button. */ if (mouseEvent.getButton()==MouseEvent.BUTTON3) { phy_deleteobj(mouseX, mouseY); } else { statrtCreateObjOnmousePressed_(); if( phy_ishitobj(mouseX, mouseY ) ) { phy_draggable( true ); } else { phy_draggable( false ); } phy_switchStaticAt( mouseX, mouseY ); } } void statrtCreateObjOnmousePressed_() { if( gui_isOverGUI( mouseX, mouseY ) || phy_ishitobj(mouseX, mouseY ) ) { return; } isStartSizing = true; startPoint.x = mouseX; startPoint.y = mouseY; } /**/ void mouseDragged() { if( !isStartSizing ) { return ; } /**/ int x = (int)startPoint.x - (int)mouseX; int y = (int)startPoint.y - (int)mouseY; endPoint.x = startPoint.x-x; endPoint.y = startPoint.y-y; } /**/ int powerof2nize_( int v ) { boolean isMinus = false; if( v < 0.0f ) { isMinus = true; v = -v; } for( int i=2;i<20;++i) { int p1 = (int)Math.pow( 2, i ); int p2 = (int)Math.pow( 2, i+1 ); if( p1 < v && v < p2 ) { if( isMinus ) { return -p1; } else { return p1; } } } return 4; } /**/ void mouseReleased() { if( !isStartSizing ) { return ; } isStartSizing = false; switch( curPhyObject ) { case PHYOBJECT_NONE: /* do nothing. */ break; case PHYOBJECT_CIRCLE: { int cx = (int)(endPoint.x + startPoint.x)/2; int cy = (int)(endPoint.y + startPoint.y)/2; float dx = (endPoint.x - startPoint.x); float dy = (endPoint.y - startPoint.y); float r = sqrt( dx*dx+dy*dy ); /* if radius is less than 10pix, dont create that. */ if(r > 10.0f) { phy_addcircle(cx, cy, r ); } } break; case PHYOBJECT_BOX: { int sx = (int)startPoint.x; int sy = (int)startPoint.y; int w = (int)(endPoint.x - startPoint.x); int h = (int)(endPoint.y - startPoint.y); if(w<0) { w = -w; sx = sx - w; } if(h<0) { h = -h; sy = sy - h; } /* if size is less than 10pix, dont create that. */ if( w>10.0f && h > 10.0f ) { phy_addbox(sx, sy, w, h, 0.0f ); } } break; case PHYOBJECT_TRIANGLE: { int sx = (int)startPoint.x; int sy = (int)startPoint.y; int w = (int)(endPoint.x - startPoint.x); int h = (int)(endPoint.y - startPoint.y); /* if size is less than 10pix, dont create that. */ if( abs(w)>10.0f && abs(h) > 10.0f ) { phy_addtriangle(sx, sy, w, h, 0.0f ); } } break; default: print("UnKownObjectType\n"); break; } } //---------------------------------------------------------------------------------------------------------- // Physics //---------------------------------------------------------------------------------------------------------- float frequency = 5; float damping = 1; float puenteY; FBody[] steps = new FBody[20]; FWorld world; PImage g_arrowImage; int boxWidth = WND_WIDTH /(steps.length) - 2; void phy_init() { Fisica.init(this); world = new FWorld(0,0,WND_WIDTH,WND_HEIGHT); world.setEdges(); world.remove(world.top); /* load arrow image. */ g_arrowImage = loadImage("arrow.png"); } void phy_draggable( boolean isDraggable ) { world.setGrabbable( isDraggable ); } /**/ void phy_update() { /* step(dt,ite) stability is not good. so call default step() several times */ /* int iteratoNum = 2; world.step( 2.0f/frameRate, iteratoNum ); / for( int i=0;i<6;++i) { world.step(); } } void phy_draw( boolean isShowBodiesInfo ) { world.draw(); if( isShowBodiesInfo ) { renderVelocityArrow_(); } } /* */ void renderVelocityArrow_() { /* TODO diviede otherfunc */ ArrayList bodies = world.getBodies(); for( Object obj: bodies ) { FBody body = (FBody)obj; float vx = body.getVelocityX(); float vy = body.getVelocityY(); float x = body.getX(); float y = body.getY(); float rot = atan2( vy, vx ); float bodyScale = min( sqrt( vy*vy+ vy*vy )*0.01f-0.2f, 0.5f ); float bodyAlpha = bodyScale; if( bodyScale < 0.0 ) { continue; } /* show arrow at body */ pushMatrix(); translate( x, y ); rotate( rot + PI/2.0f ); scale( bodyScale ); translate( -g_arrowImage.width/2, -g_arrowImage.height ); image( g_arrowImage, 0, 0 ); popMatrix(); } } /* Add circle body */ void phy_addcircle( float x, float y, float radius ) { FCircle bola = new FCircle(radius); bola.setPosition(x, y); bola.setDensity(0.2); bola.setFill(120, 120, 190); bola.setNoStroke(); world.add(bola); } /* Add box body */ void phy_addbox( float x, float y, float width, float height, float rot ) { x += width/2; y += height/2; FBox newBox = new FBox(width,height); newBox.setPosition(x, y); newBox.setRotation( rot ); newBox.setDensity(0.2); newBox.setFill(180, 120, 190); newBox.setNoStroke(); world.add(newBox); } /* Add triangle body */ void phy_addtriangle( float x, float y, float width, float height, float rot ) { FPoly newPoly = new FPoly(); float w3 = width/3; float h3 = height/3; x += w3; y += h3*2; newPoly.vertex(-w3, -h3*2 ); newPoly.vertex(-w3, +h3 ); newPoly.vertex(+w3*2, +h3 ); newPoly.setPosition(x, y); newPoly.setRotation( rot ); newPoly.setDensity(0.2); newPoly.setFill(120, 180, 120); newPoly.setNoStroke(); world.add( newPoly ); } /* switch dynamic object to static, and vice versa. */ void phy_switchStaticAt( int aMouseX, int aMouseY ) { FBody body = world.getBody( aMouseX, aMouseY ); if( body != null ) { if( !body.isStatic() ) { body.setStaticBody( true ); body.setStatic( true ); } else { float x = body.getX(); float y = body.getY(); if( body instanceof FBox ) { FBox box = (FBox)body; float width = box.getWidth(); float height = box.getHeight(); float rot = box.getRotation(); world.remove( body ); phy_addbox( x-width/2, y-height/2, width, height, rot ); } else if( body instanceof FCircle ) { FCircle circle = (FCircle)body; float radius = circle.getSize(); world.remove( body ); phy_addcircle( x, y, radius ); } else if( body instanceof FPoly ) { /* FPoly cant tell the vertex info. FPoly doesnt have that feature for some reason. :( */ /* So simply delete this obj */ world.remove( body ); } } } } /* rotate obj on target point */ void phy_rotobj( int x, int y, int mouseDelta ) { FBody body = world.getBody( x, y ); if( body != null && body.isStatic() ) { float rot = body.getRotation(); rot += mouseDelta * PI/36.0f; body.setRotation( rot ); } } /* object hit test */ boolean phy_ishitobj(int x, int y ) { return ( world.getBody(x, y) != null ); } /* delete object */ void phy_deleteobj( int x, int y ) { FBody body = world.getBody( x, y ); if( body != null ) { world.remove(body); } } /* clear all bodies in world */ void phy_clearAllObj() { /* clear all object */ world.clear(); /* set the wall. */ world.setEdges(0,0,WND_WIDTH,WND_HEIGHT); world.remove(world.top); } //---------------------------------------------------------------------------------------------------------- // GUI //---------------------------------------------------------------------------------------------------------- GButton btnCreateBox; GButton btnCreateCircle; GButton btnCreateTriangle; GButton btnClock; GButton btnClear; void gui_init() { G4P.setColorScheme(this, GCScheme.BLUE_SCHEME); G4P.setFont(this, "Verdana", 12); G4P.setMouseOverEnabled(true); createCreatePanel(); } void createCreatePanel() { int baseX = WND_WIDTH-65; int baseY = WND_HEIGHT-330; /* box button */ btnCreateBox = new GButton(this,"_box.png",3, baseX,baseY,50,30); btnCreateBox.tag = "CreateBox"; /* circle button */ btnCreateCircle = new GButton(this,"_circle.png",3, baseX,baseY+65*1,50,30); btnCreateCircle.tag = "CreateCircle"; /* triangle button */ btnCreateTriangle = new GButton(this,"_triangle.png",3, baseX,baseY+65*2,50,30); btnCreateTriangle.tag = "CreateTriangle"; /* clock button */ btnClock = new GButton(this,"_clock.png",3, baseX,baseY+65*3,50,30); btnClock.tag = "clock"; /* clear button
Source code: pedu
Built with Processing