package sig.engine; import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; import java.awt.image.ColorModel; import java.awt.image.MemoryImageSource; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.awt.GraphicsEnvironment; import java.awt.GraphicsConfiguration; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.event.MouseInputListener; import java.awt.event.KeyListener; import java.awt.Graphics2D; import java.awt.RenderingHints; import sig.JavaProjectTemplate; public class Panel extends JPanel implements Runnable,KeyListener { JFrame window; static JavaProjectTemplate gameInstance; public int pixel[]; final int CIRCLE_PRECISION=32; final int OUTLINE_COL=Color.BRIGHT_WHITE.getColor(); private Thread thread; private Image imageBuffer; private MemoryImageSource mImageProducer; private ColorModel cm; int scanLine=0; int nextScanLine=0; double x_offset=0; double y_offset=0; int frameCount=0; long lastSecond=0; boolean resizing=false; long lastUpdate=System.nanoTime(); final long TARGET_FRAMETIME = 8333333l; public double nanaX = 0; public double nanaY = 0; public int button = 0; private MouseScrollValue scrollWheel=null; public static final int UPDATE_LOOP_FRAMERATE = 244; public static final long UPDATE_LOOP_NANOTIME = (long)((1d/UPDATE_LOOP_FRAMERATE)*1000000000l); public static final double UPDATE_MULT = 1d / UPDATE_LOOP_FRAMERATE; public static RenderingHints RENDERHINTS = new RenderingHints(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF); static long lastReportedTime = System.currentTimeMillis(); public static long TIME = 0; public static long scaleTime; public static Panel p; public static JFrame f; public static void InitializeEngine(JavaProjectTemplate instance){ System.setProperty("sun.java2d.transaccel", "True"); System.setProperty("sun.java2d.d3d", "True"); System.setProperty("sun.java2d.ddforcevram", "True"); System.setProperty("sun.java2d.xrender", "True"); gameInstance=instance; RENDERHINTS.put(RenderingHints.KEY_COLOR_RENDERING,RenderingHints.VALUE_COLOR_RENDER_SPEED); RENDERHINTS.put(RenderingHints.KEY_DITHERING,RenderingHints.VALUE_DITHER_DISABLE); RENDERHINTS.put(RenderingHints.KEY_FRACTIONALMETRICS,RenderingHints.VALUE_FRACTIONALMETRICS_OFF); RENDERHINTS.put(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_SPEED); f = new JFrame(JavaProjectTemplate.PROGRAM_NAME); f.setResizable(false); f.setSize(JavaProjectTemplate.WINDOW_WIDTH,JavaProjectTemplate.WINDOW_HEIGHT); p = new Panel(f); JavaProjectTemplate.game=p; p.init(); f.add(p); f.addKeyListener(p); f.setLocation((int) ((Toolkit.getDefaultToolkit().getScreenSize().getWidth() - f.getWidth()) / 2), (int) ((Toolkit.getDefaultToolkit().getScreenSize().getHeight() - f.getHeight()) / 2)); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setVisible(true); p.render(); long lastGameTime = System.nanoTime(); long dt = 0; while (true) { dt += System.nanoTime() - lastGameTime; lastGameTime = System.nanoTime(); while (dt >= UPDATE_LOOP_NANOTIME) { gameInstance.updateGame(UPDATE_LOOP_NANOTIME/1000000000d); Mouse.pressMap.clear(); Mouse.releaseMap.clear(); Key.KEYS_PRESS.clear(); Key.KEYS_RELEASE.clear(); dt -= UPDATE_LOOP_NANOTIME; TIME += UPDATE_LOOP_NANOTIME; } gameUpdateLoopStabilizer(dt); //This is hackish. Removing this slows down the game by about 30%. The timer runs slower. ??? } } private static void gameUpdateLoopStabilizer(long dt) { if (dt < UPDATE_LOOP_NANOTIME) { lastReportedTime = System.currentTimeMillis(); } else { if (System.currentTimeMillis() - lastReportedTime > 5000) { System.out.println("WARNING! Game is lagging behind! Frames Behind: " + (dt / UPDATE_LOOP_NANOTIME)); lastReportedTime = System.currentTimeMillis(); } } try { Thread.sleep(4); } catch (InterruptedException e) { e.printStackTrace(); } } public Panel(JFrame f) { super(true); this.window=f; thread = new Thread(this, "MyPanel Thread"); this.addMouseListener(new MouseInputListener(){ @Override public void mouseClicked(MouseEvent e) { } @Override public void mousePressed(MouseEvent e) { Mouse.clickMap.put(e.getButton(),true); Mouse.pressMap.put(e.getButton(),true); } @Override public void mouseReleased(MouseEvent e) { Mouse.clickMap.put(e.getButton(),false); Mouse.releaseMap.put(e.getButton(),true); } @Override public void mouseEntered(MouseEvent e) { } @Override public void mouseExited(MouseEvent e) { } @Override public void mouseDragged(MouseEvent e) { } @Override public void mouseMoved(MouseEvent e) { } }); this.addMouseMotionListener(new MouseMotionListener(){ @Override public void mouseDragged(MouseEvent e) { Mouse.x=e.getX(); Mouse.y=e.getY(); Mouse.mousePosition.set(e.getX(),e.getY()); } @Override public void mouseMoved(MouseEvent e) { Mouse.x=e.getX(); Mouse.y=e.getY(); Mouse.mousePosition.set(e.getX(),e.getY()); } }); this.addMouseWheelListener(new MouseWheelListener(){ //-1 is UP, 1 is DOWN @Override public void mouseWheelMoved(MouseWheelEvent e) { scrollWheel=MouseScrollValue.getValue(e.getWheelRotation()); } }); } /** * Get Best Color model available for current screen. * @return color model */ protected static ColorModel getCompatibleColorModel(){ GraphicsConfiguration gfx_config = GraphicsEnvironment. getLocalGraphicsEnvironment().getDefaultScreenDevice(). getDefaultConfiguration(); return gfx_config.getColorModel(); } /** * Call it after been visible and after resizes. */ public void init(){ cm = getCompatibleColorModel(); int screenSize = JavaProjectTemplate.WINDOW_WIDTH * JavaProjectTemplate.WINDOW_HEIGHT; if(pixel == null || pixel.length < screenSize){ pixel = new int[screenSize]; } mImageProducer = new MemoryImageSource(JavaProjectTemplate.WINDOW_WIDTH, JavaProjectTemplate.WINDOW_HEIGHT, cm, pixel,0, JavaProjectTemplate.WINDOW_WIDTH); mImageProducer.setAnimated(true); mImageProducer.setFullBufferUpdates(true); imageBuffer = Toolkit.getDefaultToolkit().createImage(mImageProducer); if(thread.isInterrupted() || !thread.isAlive()){ thread.start(); } } @Override public void paintComponent(Graphics g) { //super.paintComponent(g); // perform draws on pixels long startTime = System.currentTimeMillis(); g.drawImage(this.imageBuffer,0,0,JavaProjectTemplate.WINDOW_WIDTH,JavaProjectTemplate.WINDOW_HEIGHT,0,0,JavaProjectTemplate.WINDOW_WIDTH,JavaProjectTemplate.WINDOW_HEIGHT,this); scaleTime=System.currentTimeMillis()-startTime; } /** * Overrides ImageObserver.imageUpdate. * Always return true, assuming that imageBuffer is ready to go when called */ @Override public boolean imageUpdate(Image image, int a, int b, int c, int d, int e) { return true; } /** * Do your draws in here !! * pixel is your canvas! */ public /* abstract */ void render(){ gameInstance.drawGame(); } public void FillCircle(double center_x,double center_y,double r,Color col) { int counter=0; List> points = new ArrayList>(); for (double theta=0;theta((int)(Math.round(Math.sin(theta)*r+center_x)),(int)(Math.round(Math.cos(theta)*r+center_y)))); } FillPolygon(0,0,col,points); } public void FillOval(double center_x,double center_y,double w,double h,Color col) { int counter=0; List> points = new ArrayList>(); double r = Math.max(w,h); double ratio = Math.min(w,h)/r; for (double theta=0;theta newP = new Point((int)(Math.round(Math.sin(theta)*r)),(int)(Math.round(Math.cos(theta)*r))); if (w>points) { Edge[] edges = new Edge[points.size()]; List edges_sorted = new ArrayList(); for (int i=0;i=edges[i].min_y) { edges_sorted.add(j,edges[i]); inserted=true; break; } } if (!inserted) { edges_sorted.add(edges[i]); } } } } //System.out.println(edges_sorted); List active_edges = new ArrayList(); scanLine = edges_sorted.get(0).min_y-1; nextScanLine = scanLine+1; do { for (int i=0;i=active_edges.size()-1) break; Edge e1 = active_edges.get(i); Edge e2 = active_edges.get(i+1); //System.out.println("Drawing from "+((int)Math.round(e1.x_of_min_y))+" to "+e2.x_of_min_y+" on line "+scanLine); for (int x=(int)Math.round(e1.x_of_min_y);x<=e2.x_of_min_y;x++) { if (x<0||x>JavaProjectTemplate.WINDOW_WIDTH) continue; int index = (scanLine+(int)y_offset)*getWidth()+x+(int)x_offset; if (index=0) { Draw(index,col.getColor()); } } } List new_active_edges = new ArrayList(); for (int i=0;ie.x_of_min_y) { new_active_edges.add(j,e); inserted=true; break; } } if (!inserted) { new_active_edges.add(e); } } active_edges=new_active_edges; GetNextScanLineEdges(edges_sorted, active_edges); } while (active_edges.size()>0); } private void GetNextScanLineEdges(List edges_sorted, List active_edges) { if (scanLine==nextScanLine) { for (int i=0;iscanLine) { nextScanLine=e.min_y; break; } } } } public void Draw(int x, int y, Color col) { if (x<0||y<0||x>=JavaProjectTemplate.WINDOW_WIDTH||y>=JavaProjectTemplate.WINDOW_HEIGHT) return; Draw(y*JavaProjectTemplate.WINDOW_WIDTH+x,col.getColor()); } void Draw(int index, int col) { if (((col>>>24)&0xff)==0) return; if (((col>>>24)&0xff)!=255) { pixel[index]=ColorLerpNoAlpha(new Color(pixel[index]),new Color(col),((col>>>24)&0xff)/255f).getColor(); } else { pixel[index]=col; } } @Override public void run() { while (true) { // request a JPanel re-drawing render(); mImageProducer.newPixels(); if (f!=null) { Graphics2D g2 = (Graphics2D)f.getGraphics(); if (g2!=null) { g2.setRenderingHints(RENDERHINTS); try { repaint(); } finally { g2.dispose(); } } } updateFPSCounter(); //System.out.println("Repaint "+frameCount++); waitForNextFrame(); } } private void waitForNextFrame() { long newTime = System.nanoTime(); if (newTime-lastUpdate=1000) { window.setTitle(JavaProjectTemplate.PROGRAM_NAME+" - FPS: "+(frameCount)); frameCount=0; lastSecond=System.currentTimeMillis(); } frameCount++; } @Override public void keyTyped(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) { if (!Key.isHeld(e.getKeyCode())) { Key.setKeyHeld(e.getKeyCode(), true); Key.KEYS_PRESS.put(e.getKeyCode(),true); } //System.out.println("Key List: "+KEYS); } @Override public void keyReleased(KeyEvent e) { Key.setKeyHeld(e.getKeyCode(), false); Key.KEYS_RELEASE.put(e.getKeyCode(),true); //System.out.println("Key List: "+KEYS); } public void Draw_Text(double x, double y, java.lang.String s, Font f){ Draw_Text(x,y,new String(s),f); } public void Draw_Text_Ext(double x, double y, java.lang.String s, Font f, Color col){ Draw_Text_Ext(x,y,new String(s),f,col); } private void Draw_Text(double x, double y, String s, Font f) { Draw_Text_Ext(x,y,s,f,Color.BLACK); } private void Draw_Text_Ext(double x, double y, String s, Font f, Color col) { java.lang.String finalS = s.toString(); int charCount=0; int yOffset=0; int xOffset=0; Color currentCol = col; for (int i=0;i=0) { x=x1;y=y1;xe=x2-1; } else { x=x2-1;y=y2-1;xe=x1; } while (x0&&dy>0)) { y=y+1; } else { y=y-1; } px=px+2*(dy1-dx1); } Draw(y*JavaProjectTemplate.WINDOW_WIDTH+x,col.getColor()); } } else { if (dy>=0) { x=x1;y=y1;ye=y2-1; } else { x=x2-1;y=y2-1;ye=y1; } Draw(y*JavaProjectTemplate.WINDOW_WIDTH+x,col.getColor()); while (y0&&dy>0)) { x=x+1; } else { x=x-1; } py=py+2*(dx1-dy1); } Draw(y*JavaProjectTemplate.WINDOW_WIDTH+x,col.getColor()); } } } public void Fill_Rect(double x,double y,double w,double h,Color col) { for (int xx=0;xx=0&&y+yy>=0&&x+xx=JavaProjectTemplate.WINDOW_WIDTH||Y-yOffset+y>=JavaProjectTemplate.WINDOW_HEIGHT) { continue; } else { int index = ((vertical? sprite.getHeight()-(Y-(int)yOffset): (Y-(int)yOffset)) +(int)y)*JavaProjectTemplate.WINDOW_WIDTH+ (horizontal? sprite.getWidth()-(X-(int)xOffset): (X-(int)xOffset)) +(int)x; if (((sprite.getImg().getRGB(X,Y)>>>24)&0xFF)==0||index<0||index>=pixel.length) { continue; } else { if (col==Color.WHITE) { Draw(index,sprite.getImg().getRGB(X,Y)); } else { Color img = new Color(sprite.getImg().getRGB(X,Y)); Draw(index,new Color( (int)Math.min(255.0f,Math.max(0,(float)img.r * col.r / 255.0f)), (int)Math.min(255.0f,Math.max(0,(float)img.g * col.g / 255.0f)), (int)Math.min(255.0f,Math.max(0,(float)img.b * col.b / 255.0f)), (int)Math.min(255.0f,Math.max(0,(float)img.a * col.a / 255.0f))).getColor() ); } } } } } } public void Draw_Rect(double x,double y, double w, double h, Color col) { Draw_Line((int)x, (int)y, (int)x+(int)w, (int)y, col); Draw_Line((int)x+(int)w, (int)y, (int)x+(int)w, (int)y+(int)h, col); Draw_Line((int)x+(int)w, (int)y+(int)h, (int)x, (int)y+(int)h, col); Draw_Line((int)x, (int)y+(int)h, (int)x, (int)y, col); } public void Draw_Triangle(double x1, double y1, double x2, double y2, double x3, double y3, Color col) { Draw_Line((int)x1, (int)y1, (int)x2, (int)y2, col); Draw_Line((int)x2, (int)y2, (int)x3, (int)y3, col); Draw_Line((int)x3, (int)y3, (int)x1, (int)y1, col); } private void drawline(int sx,int ex,int ny,Color col){ for (int i = sx; i <= ex; i++) Draw(i, ny, col); } public void Fill_Triangle(double x1, double y1, double x2, double y2, double x3, double y3, Color col){ int t1x, t2x, y, minx, maxx, t1xp, t2xp; boolean changed1 = false; boolean changed2 = false; int signx1, signx2, dx1, dy1, dx2, dy2; int e1, e2; // Sort vertices int temp; if (y1 > y2) {temp=(int)y1;y1=y2;y2=temp;temp=(int)x1;x1=x2;x2=temp;} if (y1 > y3) {temp=(int)y1;y1=y3;y3=temp;temp=(int)x1;x1=x3;x3=temp;} if (y2 > y3) {temp=(int)y2;y2=y3;y3=temp;temp=(int)x2;x2=x3;x3=temp;} t1x = t2x = (int)x1; y = (int)y1; // Starting points dx1 = (int)(x2 - x1); if (dx1 < 0) { dx1 = -dx1; signx1 = -1; } else signx1 = 1; dy1 = (int)(y2 - y1); dx2 = (int)(x3 - x1); if (dx2 < 0) { dx2 = -dx2; signx2 = -1; } else signx2 = 1; dy2 = (int)(y3 - y1); if (dy1 > dx1) {temp=dx1;dx1=dy1;dy1=temp;changed1 = true; } if (dy2 > dx2) {temp=dx2;dx2=dy2;dy2=temp;changed2 = true; } e2 = (int)(dx2 >> 1); // Flat top, just process the second half boolean firstHalfDone=false; if (y1 == y2) firstHalfDone=true; if (!firstHalfDone) { e1 = (int)(dx1 >> 1); for (int i = 0; i < dx1;) { t1xp = 0; t2xp = 0; if (t1x < t2x) { minx = t1x; maxx = t2x; } else { minx = t2x; maxx = t1x; } // process first line until y value is about to change next0: while (i < dx1) { i++; e1 += dy1; while (e1 >= dx1) { e1 -= dx1; if (changed1) t1xp = signx1;//t1x += signx1; else { break next0; } } if (changed1) break; else t1x += signx1; } // Move line next1: // process second line until y value is about to change while (true) { e2 += dy2; while (e2 >= dx2) { e2 -= dx2; if (changed2) t2xp = signx2;//t2x += signx2; else { break next1; } } if (changed2) break; else t2x += signx2; } if (minx > t1x) minx = t1x; if (minx > t2x) minx = t2x; if (maxx < t1x) maxx = t1x; if (maxx < t2x) maxx = t2x; drawline(minx, maxx, y, col); // Draw line from min to max points found on the y // Now increase y if (!changed1) t1x += signx1; t1x += t1xp; if (!changed2) t2x += signx2; t2x += t2xp; y += 1; if (y == y2) break; } } // Second half dx1 = (int)(x3 - x2); if (dx1 < 0) { dx1 = -dx1; signx1 = -1; } else signx1 = 1; dy1 = (int)(y3 - y2); t1x = (int)x2; if (dy1 > dx1) { // swap values temp=dy1;dx1=dy1;dy1=temp; changed1 = true; } else changed1 = false; e1 = (int)(dx1 >> 1); for (int i = 0; i <= dx1; i++) { t1xp = 0; t2xp = 0; if (t1x < t2x) { minx = t1x; maxx = t2x; } else { minx = t2x; maxx = t1x; } // process first line until y value is about to change next3: while (i < dx1) { e1 += dy1; while (e1 >= dx1) { e1 -= dx1; if (changed1) { t1xp = signx1; break; }//t1x += signx1; else break next3; } if (changed1) break; else t1x += signx1; if (i < dx1) i++; } next4: // process second line until y value is about to change while (t2x != x3) { e2 += dy2; while (e2 >= dx2) { e2 -= dx2; if (changed2) t2xp = signx2; else break next4; } if (changed2) break; else t2x += signx2; } if (minx > t1x) minx = t1x; if (minx > t2x) minx = t2x; if (maxx < t1x) maxx = t1x; if (maxx < t2x) maxx = t2x; drawline(minx, maxx, y,col); if (!changed1) t1x += signx1; t1x += t1xp; if (!changed2) t2x += signx2; t2x += t2xp; y += 1; if (y > y3) return; } } public void FillTexturedTriangle(List>vPoints,List>vTex,ListvColour,Sprite sprTex){ try { vColour=new ArrayList(vColour); Point p1 = vPoints.get(0).clone(); Point p2 = vPoints.get(1).clone(); Point p3 = vPoints.get(2).clone(); Double tempP; Color tempC; if (p2.y < p1.y){tempP=(double)p1.y;p1.y=p2.y;p2.y=tempP;tempP=(double)p1.x;p1.x=p2.x;p2.x=tempP;tempP=vTex.get(0).x;vTex.get(0).x=vTex.get(1).x;vTex.get(1).x=tempP;vTex.get(0).y=vTex.get(1).y;vTex.get(1).y=tempP;tempC=vColour.get(0);vColour.set(0,vColour.get(1));vColour.set(1,tempC);} if (p3.y < p1.y){tempP=(double)p1.y;p1.y=p3.y;p3.y=tempP;tempP=(double)p1.x;p1.x=p3.x;p3.x=tempP;tempP=vTex.get(0).x;vTex.get(0).x=vTex.get(2).x;vTex.get(2).x=tempP;vTex.get(0).y=vTex.get(2).y;vTex.get(2).y=tempP;tempC=vColour.get(0);vColour.set(0,vColour.get(2));vColour.set(2,tempC);} if (p3.y < p2.y){tempP=(double)p2.y;p2.y=p3.y;p3.y=tempP;tempP=(double)p2.x;p2.x=p3.x;p3.x=tempP;tempP=vTex.get(1).x;vTex.get(1).x=vTex.get(2).x;vTex.get(2).x=tempP;vTex.get(1).y=vTex.get(2).y;vTex.get(2).y=tempP;tempC=vColour.get(1);vColour.set(1,vColour.get(2));vColour.set(2,tempC);} Point dPos1 = new Point((int)(p2.x-p1.x),(int)(p2.y-p1.y)); Point dTex1 = new Point((int)(vTex.get(1).x-vTex.get(0).x),(int)(vTex.get(1).y-vTex.get(0).y)); int dcr1 = vColour.get(1).r - vColour.get(0).r; int dcg1 = vColour.get(1).g - vColour.get(0).g; int dcb1 = vColour.get(1).b - vColour.get(0).b; int dca1 = vColour.get(1).a - vColour.get(0).a; Point dPos2 = new Point((int)(p3.x-p1.x),(int)(p3.y-p1.y)); Point dTex2 = new Point((int)(vTex.get(2).x-vTex.get(0).x),(int)(vTex.get(2).y-vTex.get(0).y)); int dcr2 = vColour.get(2).r - vColour.get(0).r; int dcg2 = vColour.get(2).g - vColour.get(0).g; int dcb2 = vColour.get(2).b - vColour.get(0).b; int dca2 = vColour.get(2).a - vColour.get(0).a; float dax_step = 0, dbx_step = 0, dcr1_step = 0, dcr2_step = 0, dcg1_step = 0, dcg2_step = 0, dcb1_step = 0, dcb2_step = 0, dca1_step = 0, dca2_step = 0; Point vTex1Step=null, vTex2Step=null; if (dPos1.y!=0) { dax_step = dPos1.x / (float)Math.abs(dPos1.y); vTex1Step = new Point(dTex1.x / (float)Math.abs(dPos1.y),dTex1.y / (float)Math.abs(dPos1.y)); dcr1_step = dcr1 / (float)Math.abs(dPos1.y); dcg1_step = dcg1 / (float)Math.abs(dPos1.y); dcb1_step = dcb1 / (float)Math.abs(dPos1.y); dca1_step = dca1 / (float)Math.abs(dPos1.y); } if (dPos2.y!=0) { dbx_step = dPos2.x / (float)Math.abs(dPos2.y); vTex2Step = new Point(dTex2.x / (float)Math.abs(dPos2.y),dTex2.y / (float)Math.abs(dPos2.y)); dcr2_step = dcr2 / (float)Math.abs(dPos2.y); dcg2_step = dcg2 / (float)Math.abs(dPos2.y); dcb2_step = dcb2 / (float)Math.abs(dPos2.y); dca2_step = dca2 / (float)Math.abs(dPos2.y); } Point vStart; Point vEnd; int vStartIdx; for (int pass = 0; pass < 2; pass++) { if (pass == 0) { vStart = p1; vEnd = p2; vStartIdx = 0; } else { dPos1 = new Point((int)(p3.x-p2.x),(int)(p3.y-p2.y)); dTex1 = new Point((int)(vTex.get(2).x-vTex.get(1).x),(int)(vTex.get(2).y-vTex.get(1).y)); dcr1 = vColour.get(2).r - vColour.get(1).r; dcg1 = vColour.get(2).g - vColour.get(1).g; dcb1 = vColour.get(2).b - vColour.get(1).b; dca1 = vColour.get(2).a - vColour.get(1).a; dcr1_step = 0; dcg1_step = 0; dcb1_step = 0; dca1_step = 0; if (dPos2.y!=0) dbx_step = dPos2.x / (float)Math.abs(dPos2.y); if (dPos1.y!=0) { dax_step = dPos1.x / (float)Math.abs(dPos1.y); vTex1Step = new Point(dTex1.x/(float)Math.abs(dPos1.y),dTex1.y/(float)Math.abs(dPos1.y)); dcr1_step = dcr1 / (float)Math.abs(dPos1.y); dcg1_step = dcg1 / (float)Math.abs(dPos1.y); dcb1_step = dcb1 / (float)Math.abs(dPos1.y); dca1_step = dca1 / (float)Math.abs(dPos1.y); } vStart = p2; vEnd = p3; vStartIdx = 1; } if (dPos1.y!=0) { for (int i = (int)Math.floor(vStart.y); i <= vEnd.y; i++) { int ax = (int)(vStart.x + (float)(i - vStart.y) * dax_step); int bx = (int)(p1.x + (float)(i - p1.y) * dbx_step); Point tex_s = new Point((float)(vTex.get(vStartIdx).x + (float)(i - vStart.y) * vTex1Step.x),(float)(vTex.get(vStartIdx).y + (float)(i - vStart.y) * vTex1Step.y)); Point tex_e = new Point((float)(vTex.get(0).x + (float)(i - p1.y) * vTex2Step.x),(float)(vTex.get(0).y + (float)(i - p1.y) * vTex2Step.y)); Color col_s= new Color(vColour.get(vStartIdx).r + (int)((float)(i - vStart.y) * dcr1_step), vColour.get(vStartIdx).g + (int)((float)(i - vStart.y) * dcg1_step), vColour.get(vStartIdx).b + (int)((float)(i - vStart.y) * dcb1_step), vColour.get(vStartIdx).a + (int)((float)(i - vStart.y) * dca1_step)); Color col_e= new Color(vColour.get(0).r + (int)((float)(i - p1.y) * dcr2_step), vColour.get(0).g + (int)((float)(i - p1.y) * dcg2_step), vColour.get(0).b + (int)((float)(i - p1.y) * dcb2_step), vColour.get(0).a + (int)((float)(i - p1.y) * dca2_step)); int temp; Point tempF; if (ax > bx) {temp=ax;ax=bx;bx=temp;tempF=tex_s.clone();tex_s=tex_e.clone();tex_e=tempF;tempC=col_s.clone();col_s=col_e.clone();col_e=tempC;} float tstep = 1.0f / ((float)(bx - ax)); float t = 0.0f; for (int j = ax; j < bx; j++) { Color pixel = ColorLerp(col_s, col_e, t); if (sprTex != null) { Point lerpComponents = new Point( tex_s.x*(1.0f-t)+tex_e.x*t, tex_s.y*(1.0f-t)+tex_e.y*t ); Color c=new Color(sprTex.getImg().getRGB((int)Math.min(lerpComponents.x*sprTex.width,sprTex.width-1),(int)Math.min(lerpComponents.y*sprTex.height,sprTex.height-1))); pixel.r = (int)Math.min(255.0f,Math.max(0,(float)pixel.r * c.r / 255.0f)); pixel.g = (int)Math.min(255.0f,Math.max(0,(float)pixel.g * c.g / 255.0f)); pixel.b = (int)Math.min(255.0f,Math.max(0,(float)pixel.b * c.b / 255.0f)); pixel.a = (int)Math.min(255.0f,Math.max(0,(float)pixel.a * c.a / 255.0f)); } Draw(j, i, pixel); t += tstep; } } } } } catch (CloneNotSupportedException e) {} } public void Draw_Circle(int x, int y, int radius, Color col) { Draw_Circle(x,y,radius,col,(byte)0xFF); } //The mask indicates which pie slices to draw, each bit of the mask represents 1/8th of a pie slice. By default all pie slices are drawn. public void Draw_Circle(int x, int y, int radius, Color col, byte mask) { if (radius < 0 || x < -radius || y < -radius || x - JavaProjectTemplate.WINDOW_WIDTH > radius || y - JavaProjectTemplate.WINDOW_HEIGHT > radius) return; if (radius > 0) { int x0 = 0; int y0 = radius; int d = 3 - 2 * radius; while (y0 >= x0) // only formulate 1/8 of circle { // Draw even octants if ((mask & 0x01)!=0) Draw(x + x0, y - y0, col);// Q6 - upper right right if ((mask & 0x04)!=0) Draw(x + y0, y + x0, col);// Q4 - lower lower right if ((mask & 0x10)!=0) Draw(x - x0, y + y0, col);// Q2 - lower left left if ((mask & 0x40)!=0) Draw(x - y0, y - x0, col);// Q0 - upper upper left if (x0 != 0 && x0 != y0) { if ((mask & 0x02)!=0) Draw(x + y0, y - x0, col);// Q7 - upper upper right if ((mask & 0x08)!=0) Draw(x + x0, y + y0, col);// Q5 - lower right right if ((mask & 0x20)!=0) Draw(x - y0, y + x0, col);// Q3 - lower lower left if ((mask & 0x80)!=0) Draw(x - x0, y - y0, col);// Q1 - upper left left } if (d < 0) d += 4 * x0++ + 6; else d += 4 * (x0++ - y0--) + 10; } } else Draw(x, y, col); } public void Fill_Circle(int x, int y, int radius, Color col) { if (radius < 0 || x < -radius || y < -radius || x - JavaProjectTemplate.WINDOW_WIDTH > radius || y - JavaProjectTemplate.WINDOW_HEIGHT > radius) return; if (radius > 0) { int x0 = 0; int y0 = radius; int d = 3 - 2 * radius; while (y0 >= x0) { drawline(x - y0, x + y0, y - x0, col); if (x0 > 0) drawline(x - y0, x + y0, y + x0, col); if (d < 0) d += 4 * x0++ + 6; else { if (x0 != y0) { drawline(x - x0, x + x0, y - y0, col); drawline(x - x0, x + x0, y + y0, col); } d += 4 * (x0++ - y0--) + 10; } } } else Draw(x, y, col); } public void FillTexturedPolygon(List>vPoints,List>vTex,ListvColour,Sprite sprTex,PolygonStructure structure) { try { if (vPoints.size() < 3 || vTex.size() < 3 || vColour.size() < 3) return; if (structure == PolygonStructure.LIST) { for (int tri = 0; tri < vPoints.size() / 3; tri++) { List> vP = new ArrayList>(List.of(vPoints.get(tri * 3 + 0), vPoints.get(tri * 3 + 1), vPoints.get(tri * 3 + 2))); List> vT = new ArrayList>(List.of(vTex.get(tri * 3 + 0), vTex.get(tri * 3 + 1), vTex.get(tri * 3 + 2))); List vC = new ArrayList(List.of(vColour.get(tri * 3 + 0), vColour.get(tri * 3 + 1), vColour.get(tri * 3 + 2))); FillTexturedTriangle(vP, vT, vC, sprTex); } return; } if (structure == PolygonStructure.STRIP) { for (int tri = 2; tri < vPoints.size(); tri++) { List> vP = new ArrayList>(List.of(vPoints.get(tri - 2), vPoints.get(tri - 1), vPoints.get(tri))); List> vT = new ArrayList>(List.of(vTex.get(tri - 2), vTex.get(tri - 1), vTex.get(tri))); List vC = new ArrayList(List.of(vColour.get(tri - 2), vColour.get(tri - 1), vColour.get(tri))); FillTexturedTriangle(vP, vT, vC, sprTex); } return; } if (structure == PolygonStructure.FAN) { for (int tri = 2; tri < vPoints.size(); tri++) { List> vP; vP = new ArrayList>(List.of(vPoints.get(0).clone(), vPoints.get(tri - 1).clone(), vPoints.get(tri).clone())); List> vT = new ArrayList>(List.of(vTex.get(0).clone(), vTex.get(tri - 1).clone(), vTex.get(tri).clone())); List vC = new ArrayList(List.of(vColour.get(0).clone(), vColour.get(tri - 1).clone(), vColour.get(tri).clone())); FillTexturedTriangle(vP, vT, vC, sprTex); } return; } } catch (CloneNotSupportedException e) {} } Color ColorLerp(Color c1, Color c2, float t) { return new Color((int)((c2.r * t) + c1.r * (1.0f - t)),(int)((c2.g * t) + c1.g * (1.0f - t)),(int)((c2.b * t) + c1.b * (1.0f - t)),(int)((c2.a * t) + c1.a * (1.0f - t))); } Color ColorLerpNoAlpha(Color c1, Color c2, float t) { return new Color((int)((c2.r * t) + c1.r * (1.0f - t)),(int)((c2.g * t) + c1.g * (1.0f - t)),(int)((c2.b * t) + c1.b * (1.0f - t))); } public void Clear(Color col){ for (int y=0;y