March 13th, 2023 JavaFX App

I created the following to draw a moving car on JavaFX

Free Starter Classes below MIT License

package application;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.Logger;

import javafx.scene.image.Image;
import util.GraphicsUtil;

public class RenderEngine implements Runnable {
	public static Logger logger = Logger.getLogger(RenderEngine.class.getName());
	
	private ConcurrentLinkedQueue<Image> concurrentImageQueue;
	
	public RenderEngine(ConcurrentLinkedQueue<Image> concurrentImageQueue) {
		this.concurrentImageQueue = concurrentImageQueue;
	}
	
	@Override
	public void run() {
		renderFrameLoop();
	}
	
	public void renderFrameLoop() {
		while (true) {
			BufferedImage bufferedImage = renderFrame();
			Image image = GraphicsUtil.convertBufferedImageToImage(bufferedImage);			
			concurrentImageQueue.add(image);
			// logger.info("Frame rendered");
			
			try {
				Thread.sleep(15);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}		
	}
	
	private int carOffset=0;
	
	public BufferedImage renderFrame() {
		BufferedImage bufferedImage = new BufferedImage(1000, 1000, BufferedImage.TYPE_INT_RGB);
		Graphics2D g2D = bufferedImage.createGraphics();
		
		g2D.setColor(Color.BLACK);
		g2D.fillRect(0, 0, 1000, 1000);
		
		g2D.setColor(Color.GREEN); // Draw Green Ground Height 400 to 1000
		g2D.fillRect(0, 400, 1000, 1000);
		
		g2D.setColor(Color.BLUE); // Draw Blue Sky Height 0 to 400
		g2D.fillRect(0, 0, 1000, 400);
		
		drawCar(g2D);
		
		return bufferedImage;
	}
	
	public void drawCar(Graphics2D g2D) {
		carOffset+=10;
		// Draw Body of Car, RED
		g2D.setColor(Color.RED);
		int x = carOffset;
		int y = 500;
		int width=75;
		int height=35;		
		g2D.fillRect(x,y,width,height);
		g2D.fillRect(x,y+15,width+20,20);
		
		// Draw Wheels of Car, Black
		g2D.setColor(Color.BLACK);
		g2D.fillOval(x+15, y+20, 25, 25);
		g2D.fillOval(x+50, y+20, 25, 25);
		
		
		if (carOffset>1000) {
			carOffset=0;
		}		
	}
}

StreamImageView class

package application;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;

import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import multithreading.ThreadUtil;
import util.GraphicsUtil;

public class StreamImageView {
	private static AtomicInteger instanceIdGenerator = new AtomicInteger();
	
	private ConcurrentLinkedQueue<Image> imageQueue = new ConcurrentLinkedQueue<>();
	
	public ConcurrentLinkedQueue<Image> getImageQueue() {
		return imageQueue;
	}

	private ImageView imageView;
		
	public ImageView getImageView() {
		return imageView;
	}
	
	private String id;	

	public String getId() {
		return id;
	}
	
	public StreamImageView() {
		this(null);
	}

	public StreamImageView(Image initialFrame) {
		id="streamImageView-"+instanceIdGenerator.getAndIncrement();
		
		if (null == initialFrame) {
			BufferedImage bufferedImage = new BufferedImage(1000, 1000, BufferedImage.TYPE_INT_RGB);
			Graphics2D g2D = bufferedImage.createGraphics();
			
			g2D.setColor(Color.WHITE);
			g2D.fillRect(0, 0, 1000, 1000);
			
			initialFrame = GraphicsUtil.convertBufferedImageToImage(bufferedImage);
		}
		
	    imageView = new ImageView(initialFrame);
	
		Runnable updateImageView = () -> {
			while (true) {
				Image image = imageQueue.poll();
				if (null != image) {
					imageView.setImage(image);
				}
			}
		};
		
		Thread imageViewUpdateConsumer = new Thread(updateImageView);
		ThreadUtil.addTask(imageViewUpdateConsumer);		
	}	
}

Utility Class for turning BufferedImage into JavaFX Image

package util;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.logging.Logger;

import javax.imageio.ImageIO;

import javafx.scene.image.Image;

public class GraphicsUtil {
	private static Logger logger = Logger.getLogger(GraphicsUtil.class.getName());
	
	public static Image convertBufferedImageToImage(BufferedImage bufferedImage) {
		try {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();								
			ImageIO.write(bufferedImage, "BMP", baos);
			ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
			Image image = new Image(bais);
			return image;
		} catch (IOException e) {
			logger.severe("Error converting BufferedImage to Image");
			return null;
		}
	}
}

Wired together in main application and set to run on a different thread

package application;
	
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import multithreading.ThreadUtil;


public class Main extends Application {
	@Override
	public void start(Stage primaryStage) {
		try {
			VBox vbox = new VBox();
			Scene scene = new Scene(vbox,400,400);
			scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
			primaryStage.setScene(scene);
			primaryStage.show();			
			StreamImageView streamImageView = new StreamImageView();
			
			vbox.getChildren().add(streamImageView.getImageView());
			
			RenderEngine renderEngine = new RenderEngine(streamImageView.getImageQueue());
			ThreadUtil.addTask(renderEngine);
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		launch(args);
	}
}

Thread Pool Utility Class

package multithreading;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

public class ThreadUtil {
	private static Logger logger = Logger.getLogger(ThreadUtil.class.toString());
	private static BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(6);
	private static ThreadPoolExecutor threadPoolExecutor;
	
	
	public static BlockingQueue<Runnable> getWorkQueue() {
		if (null == workQueue) {
			workQueue = new ArrayBlockingQueue<>(6);
		}
		return workQueue;
	}
	
	public static ThreadPoolExecutor getThreadPool() {
		if (null == threadPoolExecutor) {
			threadPoolExecutor = new ThreadPoolExecutor(6, 12, 1000, TimeUnit.MILLISECONDS, getWorkQueue());
		}
		
		return threadPoolExecutor;
	}
	
	public static void addTask(Runnable task) {
		getThreadPool().submit(task);
	}
	
	/* public static void addVirtualTask(Runnable task) {
		getThreadPool().submit(Thread.ofVirtual().start(task));
	} */ // Potential update for Java 19	
}

There would be an Image here, provided the Video on Twitter

Rain Sounds Help as Encouragement

Added a draw Mountain function and shared on Twitter

	public void drawMountain(Graphics2D g2D) {
		g2D.setColor(Color.CYAN);
		int x[] = { 100, 250, 400 };
		int y[] = { 400, 250, 400 };
		g2D.fillPolygon(x, y, 3);
	}

The car in front of the Mountain needs a story

Free Starter Story Outline to go with

Random THEME – Love conquers all

Random PLOT – Tragedy

Onomatopoeia Metaphor Allegory Flashback Juxtaposition Metaphor Onomatopoeia Flashback Simile Imagery

Random Villain Dragon

Siren Swarm Giant Necromancer Bandit Dragon Mislead Revolutionary Stone Elemental Deranged Sniper Water Elemental Siren Poltergeist Siren Siren Mislead Revolutionary Swarm Psychopath Hostile Alien Spaceship Giant Dragon

Descriptive Writing Amps

  1. [brilliant, loud, proper] lizard whispered
  2. [smooth, diminished, resonant] gas giant relayed
  3. [happy, sweet, rough] demon halted
  4. [violet, harmonious, blue] ice cream evaded
  5. [gargantuan, kinetic, loud] moon dashed
  6. [soft, microscopic, green] earth pulverized
  7. [sad, delightful, black] castle evoked
  8. [green, cyan, gargantuan] ruby unfurled
  9. [colossal, blissful, calm] gold blocked
  10. [sweet, microscopic, happy] jet magnified

Random Hero – Knight

And But Therefore Event Sets

  1. [Hero] is attacked by [Monster] but they are delayed therefore they fight the [monster]
  2. [Hero] is given assistance from [side character] but [monster] challenges [Hero] with hurtful scary words therefore they decide to learn more
  3. Dramatic Dialogue with subtext but [monster] challenges [Hero] with hurtful scary words therefore they fight the [monster]
  4. [Hero] is given assistance from [side character] but they get there early therefore they fight the [monster]
  5. [Hero] gets in jet but they are delayed therefore they seek assistance with [side character]
  6. diffuse a bomb but it rains therefore they travel to a new area
  7. There is a solar eclipse but [monster] shows up therefore they seek assistance with [side character]
  8. [Hero] is given assistance from [side character] but they get there early therefore they travel to a new area
  9. fight a [monster] but they are delayed therefore they fight the [monster]
  10. fight a [monster] but it rains therefore they fight the [monster]

The World invests in Tech and Villain Contrast, Obfuscation through Acronyms, seems only wise to invest in some repair

Fault Tolerance is Power that might not always be taught ideally in High Schools

https://en.wikipedia.org/wiki/Fault_tolerance

https://en.wikipedia.org/wiki/Triple_modular_redundancy

Terms I really didn’t learn about until my Masters in Engineering

Ahead of the game is Power, easy to upsell it to less

Sun erosion feature

	public void drawSun(Graphics2D g2D) {
		g2D.setColor(new Color(0x2222FF));
		g2D.fillOval(25, 25, 300, 300);
		g2D.setColor(new Color(0x5555FF));
		g2D.fillOval(75, 75, 100, 100);
		g2D.setColor(Color.YELLOW);		
		g2D.fillOval(100, 100, 30, 30);
		g2D.setColor(new Color(0xFFFFFF));
		g2D.fillOval(105, 105, 20, 20);		
	}

Updated for Flying Cars

Video available on Twitter

package application;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.Logger;

import javafx.scene.image.Image;
import javafx.scene.input.KeyCode;
import performance.PerformanceReading;
import performance.PerformanceUtil;
import performance.TimeMeasurementUtil;
import util.GraphicsUtil;

public class RenderEngine implements Runnable {
	public static Logger logger = Logger.getLogger(RenderEngine.class.getName());
	
	PerformanceUtil performanceUtil = new PerformanceUtil();
	
	private ConcurrentLinkedQueue<Image> concurrentImageQueue;
	private ConcurrentLinkedQueue<KeyCode> keyBoardEvent = new ConcurrentLinkedQueue<>();
	
	public ConcurrentLinkedQueue<KeyCode> getKeyBoardEventQueue() {
		return keyBoardEvent;
	}

	public RenderEngine(ConcurrentLinkedQueue<Image> concurrentImageQueue) {
		this.concurrentImageQueue = concurrentImageQueue;
	}
	
	@Override
	public void run() {
		renderFrameLoop();
	}
	
	public void renderFrameLoop() {
		int timeSinceLastPerformanceReading = 0;
		int sleepTimeMilliseconds = 15;
		while (true) {
			performanceUtil.start();
			BufferedImage bufferedImage = renderFrame();
			
			Image image = GraphicsUtil.convertBufferedImageToImage(bufferedImage);			
			concurrentImageQueue.add(image);
			performanceUtil.stop();
			performanceUtil.addPerformanceReading("Frame Rendered");
			// logger.info("Frame rendered");
			
			try {
				Thread.sleep(sleepTimeMilliseconds);
							
				while (!keyBoardEvent.isEmpty()) {
					KeyCode keyCode = keyBoardEvent.poll();
					logger.info("Key pressed: "+keyCode.getName());
					
					if (keyCode.isArrowKey())
					{
						if (keyCode.getCode()==KeyCode.DOWN.getCode()) {
							carVerticalOffset+=3;
						}
						if (keyCode.getCode()==KeyCode.UP.getCode()) {
							carVerticalOffset-=3;
						}						
					}
				}
				
				if (timeSinceLastPerformanceReading>5000) {
					timeSinceLastPerformanceReading=0;
					PerformanceReading reading = performanceUtil.summarizePerformanceReadings(
							"Frame Render Time Average",
							performanceUtil.getPerformanceReadings());
					logger.info("Current render time average nanoseconds: "+reading.getNanoseconds());
					int milliseconds = TimeMeasurementUtil.convertNanosecondsToMilliseconds(
							reading.getNanoseconds());
					logger.info("Current render time average milliseconds: "+milliseconds);					
				} else {
					timeSinceLastPerformanceReading += sleepTimeMilliseconds;
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}		
	}
	
	private int carOffset=0;
	private int carVerticalOffset=0;
	
	public BufferedImage renderFrame() {
		BufferedImage bufferedImage = new BufferedImage(1000, 1000, BufferedImage.TYPE_INT_RGB);
		Graphics2D g2D = bufferedImage.createGraphics();
		
		g2D.setColor(Color.BLACK);
		g2D.fillRect(0, 0, 1000, 1000);
		
		g2D.setColor(Color.GREEN); // Draw Green Ground Height 400 to 1000
		g2D.fillRect(0, 400, 1000, 1000);
		
		g2D.setColor(Color.BLUE); // Draw Blue Sky Height 0 to 400
		g2D.fillRect(0, 0, 1000, 400);
		
		drawMountain(g2D);
		drawSun(g2D);
		
		drawCar(g2D);
		
		return bufferedImage;
	}
	
	public void drawSun(Graphics2D g2D) {
		g2D.setColor(new Color(0x2222FF));
		g2D.fillOval(25, 25, 300, 300);
		g2D.setColor(new Color(0x5555FF));
		g2D.fillOval(75, 75, 100, 100);
		g2D.setColor(Color.YELLOW);		
		g2D.fillOval(100, 100, 30, 30);
		g2D.setColor(new Color(0xFFFFFF));
		g2D.fillOval(105, 105, 20, 20);		
	}
	
	public void drawMountain(Graphics2D g2D) {
		g2D.setColor(Color.CYAN);
		int x[] = { 100, 250, 400 };
		int y[] = { 400, 250, 400 };
		g2D.fillPolygon(x, y, 3);
	}
	
	public void drawCar(Graphics2D g2D) {
		carOffset+=10;
		// Draw Body of Car, RED
		g2D.setColor(Color.RED);
		int x = carOffset;
		int y = 500+carVerticalOffset;
		int width=75;
		int height=35;		
		g2D.fillRect(x,y,width,height);
		g2D.fillRect(x,y+15,width+20,20);
		
		// Draw Wheels of Car, Black
		g2D.setColor(Color.BLACK);
		g2D.fillOval(x+15, y+20, 25, 25);
		g2D.fillOval(x+50, y+20, 25, 25);
		
		if (carOffset>1000) {
			carOffset=0;
		}		
	}
}
package application;
	
import java.util.logging.Logger;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import multithreading.ThreadUtil;


public class Main extends Application {
	private static Logger logger = Logger.getLogger(Main.class.getName());
	
	@Override
	public void start(Stage primaryStage) {
		try {
			VBox vbox = new VBox();
			Scene scene = new Scene(vbox,400,400);
			scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
			primaryStage.setScene(scene);
			primaryStage.show();			
			StreamImageView streamImageView = new StreamImageView();
			
			vbox.getChildren().add(streamImageView.getImageView());
			
			RenderEngine renderEngine = new RenderEngine(streamImageView.getImageQueue());
			ThreadUtil.addTask(renderEngine);
			
			scene.setOnKeyPressed((event) -> {
				// Process Keyboard Input
				KeyCode keyCode = event.getCode();
				renderEngine.getKeyBoardEventQueue().add(keyCode);
			});
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		launch(args);
	}
}

Free with Glacier Melting Tech

Add in the potential for Processing Buffered Images on Servers

Exascale with a little latency likely can be a lot of power

One server draws the flying car

One server draws the background

Client combines the images together

Comprehension of gains to Load Balancing and Ability to use Heterogeneous Multiprocessing Fully Comprehended?

Faster Home Interconnects?

Potential for Multimachine Frame Processing as Possibility

Phones and Laptops have processors, processors that sit idle while gaming, or are useful for processing frames? Potential could be Power

More Ability to utilizing Processing in Real Ways will become more and more possible as time goes on, getting Companies to enable Heterogenous Multiprocessing like OpenCL is Not a given

https://www.netgear.com/home/wifi/routers/raxe500/

10.8Gbps / 8 bytes/s = 1.35 Gigabytes/second theoretical Max Bandwidth

Some potential for Throughput of off client rendered frames

Thoughts of Pattern Matching used to analyze Runtime Systems like the JRE (Java Runtime Environment) for suggestions to increase Performance

Game Engines analyzed by systems like Cortana and Alexa turned up with the Power of the cloud?

Pipeline gains fully appreciated?

Theoretical Maxes do not always lead to actual Throughput, that said current gains in Technology have potential for much less than Max Throughput to lead to a lot of Power

Testing my PCIE Drive in an Enclosure Writing a 1 GB file got the following results

INFO: Time Required to add and verify one million numbers: 1452 ms
Mar 13, 2023 4:34:11 AM performance.DiskWriteReadPerformance testWritePerformance
INFO: Bytes in String: 1034 mb
Mar 13, 2023 4:34:27 AM file.FileUtil writeFile
INFO: Wrote to G:\testwrite.txt with 1034240000 bytes.
Mar 13, 2023 4:34:27 AM performance.DiskWriteReadPerformance testWritePerformance
INFO: Time Required to write 1034 mb data to G:\testwrite.txt: 15720 ms
Mar 13, 2023 4:34:29 AM performance.DiskWriteReadPerformance testReadPerformance
INFO: Time Required to read 1034 mb data from G:\testwrite.txt: 1760 ms
Mar 13, 2023 4:34:32 AM performance.DiskWriteReadPerformance testWritePerformance
INFO: Bytes in String: 1034 mb
Mar 13, 2023 4:34:35 AM file.FileUtil writeFile
INFO: Wrote to C:\Users\jason\eclipse-workspace\PerformanceTestRunner\testwrite.txt with 1034240000 bytes.
Mar 13, 2023 4:34:35 AM performance.DiskWriteReadPerformance testWritePerformance
INFO: Time Required to write 1034 mb data to C:\Users\jason\eclipse-workspace\PerformanceTestRunner\testwrite.txt: 3340 ms
Mar 13, 2023 4:34:37 AM performance.DiskWriteReadPerformance testReadPerformance
INFO: Time Required to read 1034 mb data from C:\Users\jason\eclipse-workspace\PerformanceTestRunner\testwrite.txt: 1907 ms

G drive is PCIE Samsung 970 in an ASUS external enclosure

C drive is SSD on my MSI GF65 Thin 10UE

I believe it is USB 3.0

16 seconds to write 1 GB, or 8 gigabits, write throughput of 0.5 gigabits/second.

2 seconds to read 1 GB from PCIE drive equals read throughput of 0.5 gigabytes/second, or 0.5*8 = 4 gigabits/second

Routers with Max Throughput of 10.8 Gigabits per second is a lot of Power

Network Speeds rivaling speeds of PCIE drives is pretty impressive, has potential to enable things potentially once thought impossible.

More Network Throughput equals bigger files, bigger files need stronger processors

Free Starter Performance Testing Classes (MIT License)

package performance;

import java.io.IOException;
import java.io.StringWriter;
import java.util.logging.Logger;

import file.FileUtil;

public class DiskWriteReadPerformance {
	private static Logger logger = Logger.getLogger(DiskWriteReadPerformance.class.getName());
	
	public static void testWritePerformance(String filename) {
		final StringWriter stringWriter = new StringWriter();
		for (int i=0; i<10240000; i++) {
			stringWriter.append("AAAAAaaaaaBBBBBccccc");
			stringWriter.append("CCCCCdddddEEEEEfffff");
			stringWriter.append("GGGGGhhhhhIIIIIjjjjj");
			stringWriter.append("KKKKKlllllMMMMMnnnnn");
			stringWriter.append("OOOOOpppppQQQQQrrrrr\n");
		}
		
		int numberOfBytes = stringWriter.toString().getBytes().length;
		int megabytes = numberOfBytes/1000000;
		logger.info("Bytes in String: "+megabytes+" mb");
		PerformanceUtil.getInstance().start();
		try {
			FileUtil.writeFile(filename, stringWriter.toString());
		} catch (IOException e) {
			logger.severe(e.getMessage());
		}
		PerformanceUtil.getInstance().stop();
		logger.info("Time Required to write "+megabytes+ " mb data to "+filename+": "
		  +PerformanceUtil.getInstance().getRecordedTimeMilliseconds()+" ms");
		
	}
	
	public static void testReadPerformance(String filename) {
		PerformanceUtil.getInstance().start();
		try {
			String fileAsString = FileUtil.readFileAsString(filename);
			PerformanceUtil.getInstance().stop();
			int megabytes = fileAsString.getBytes().length/1000000;
			logger.info("Time Required to read "+megabytes+" mb data from "+filename+": "
					+PerformanceUtil.getInstance().getRecordedTimeMilliseconds()+" ms");
		} catch (IOException e) {
			logger.severe(e.getMessage());
		}
	}
}
package performance;

import java.util.ArrayList;

public class PerformanceUtil {
	private ArrayList<PerformanceReading> performanceReadings = new ArrayList<>();
	private boolean stopWatchStarted = false;
	private long startTime;
	private long endTime;
	private long recordedTime=0;
	private static PerformanceUtil instance;
	
	public static PerformanceUtil getInstance() {
		if (null == instance) {
			instance = new PerformanceUtil();
		}
		
		return instance;
	}
	
	public boolean start() {
		if (stopWatchStarted) {
			return false;
		} else {
			startTime=System.nanoTime();
			stopWatchStarted=true;
			return true;
		}
	}
	
	public boolean stop() {
		if (!stopWatchStarted) {
			return false;
		} else {
			endTime=System.nanoTime();
			stopWatchStarted=false;
			return true;
		}
	}
	
	public long getRunningTime() {
		long runningTime = System.nanoTime()-startTime;
		return runningTime;
	}
	
	public long getRecordedTime() {
		recordedTime=endTime-startTime;
		return recordedTime;
	}
	
	public int getRecordedTimeMilliseconds() {
		recordedTime=endTime-startTime;
		double milliseconds = recordedTime/1000000;
		return (int) milliseconds;
	}	
	
	public void clearPerformanceReadingsList() {
		performanceReadings = new ArrayList<>();		
	}
	
	public void addPerformanceReading(String performanceReadingName) {
		long recordedTime = getRecordedTime();
		PerformanceReading performanceReading = new PerformanceReading(recordedTime, performanceReadingName);
		performanceReadings.add(performanceReading);		
	}
	
	public PerformanceReading summarizePerformanceReadings(String readingName, ArrayList<PerformanceReading> readings) {
		long sum=0;
		for (int i=0; i<readings.size(); i++) {
			sum = readings.get(i).getNanoseconds();			
		}
		long average = sum/readings.size();
		
		return new PerformanceReading(average, readingName);
	}
	
	public ArrayList<PerformanceReading> getPerformanceReadings() {
		return performanceReadings;
	}
}
package performance;

public class PerformanceReading {
	
	public PerformanceReading(final long nanoseconds, final String name) {
		this.nanoseconds = nanoseconds;
		this.name = name;
	}
	
	private long nanoseconds;
	private String name;
	
	public long getNanoseconds() {
		return nanoseconds;
	}
	public String getName() {
		return name;
	}	
}

Published by techinfodebug

Flex and Java Developer, Christian, Art, Music, Video, and Vlogging

Leave a comment