Show Posts
|
|
Pages: [1]
|
|
1
|
Discussions / Jobs and Resumes / Software engineer (graphics) at UNC-CH
|
on: 2004-12-15 15:03:02
|
|
Looking for a software engineer with good background in graphics, OpenGL or DirectX, C++ and large software systems at University of North Carolina at Chapel Hill (UNC-CH) GAMMA Research Group. The person will be working on a DoD (department of defense) funded project on developing novel GPU (graphics processor)-based algorithms for simulation and geometric computations (including visibility, collision detection and path navigation). The person will work closely with graduate students and faculty at UNC-CH and also interact with industrial partners. Lots of potential for advanced learning, research, and publications. Flexible work schedule and open lab environment.
More information on the GAMMA Research Group at UNC-CH is available at:
<http://gamma.cs.unc.edu>
The GAMMA Research Group has developed a number of systems that are widely used in gaming and simulation industry. The person will be employed by the Department of Computer Science at UNC-CH, which has the number #1 ranked graduate program in computer graphics and user interaction in the U.S. (according to US News and World Report).
Length of position: 1-3 years.
Availability: January'05
Salary: Based on experience
Please contact Professor Dinesh Manocha <mailto://dm@cs.unc.edu> for more information.
|
|
|
|
|
3
|
Game Development / Performance Tuning / Re: NIO performance
|
on: 2004-02-14 06:41:37
|
Here's another example: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
|
import java.io.*; import java.nio.*; import java.nio.channels.*; import java.text.NumberFormat;
public class FastCopyFile { public static void main( String args[] ) { if (args.length != 2) { System.out.println("Usage: java FastCopyFile src_file dest_file"); System.exit(1); }
System.out.println("Copying file " + args[0] + " to file " + args[1] + "...");
long before = System.currentTimeMillis(); copyFile(args[0], outfile); long after = System.currentTimeMillis(); double cputime = .001 * (after - before);
NumberFormat digits = NumberFormat.getInstance(); digits.setMaximumFractionDigits(3);
System.out.println("Execution required " + digits.format(cputime) + " seconds."); }
private static void copyFile(String infile, String outfile) { final boolean DIRECT = true; final boolean TRANSFER = true; final int BUFFSIZE = 1024; ByteBuffer buffer;
FileChannel in = null; FileChannel out = null;
try { in = (new FileInputStream (infile )).getChannel(); out = (new FileOutputStream(outfile)).getChannel();
if (DIRECT) buffer = ByteBuffer.allocateDirect( BUFFSIZE ); else buffer = ByteBuffer.allocate( BUFFSIZE );
if (TRANSFER) {
in.transferTo(0, in.size(), out); } else { int ret; while ((ret = in.read(buffer)) > -1) { buffer.flip(); out.write(buffer); buffer.clear(); } } } catch (FileNotFoundException fnfx) { System.err.println("File not found: " + fnfx); } catch (IOException iox) { System.err.println("I/O problems: " + iox); } finally { if (in != null) { try { in.close(); } catch (IOException ignored) {} } if (out != null) { try { out.close(); } catch (IOException ignored) {} } } } }
|
|
|
|
|
|
4
|
Game Development / Newbie & Debugging Questions / Re: Creating custom Button Class
|
on: 2004-02-14 06:31:34
|
Here's a custom animated JButton class: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*;
public class HotButton extends JButton { private final String imageNames[]; private javax.swing.Timer t = null; private int n = 0; public HotButton(final String imageNames[], int speed) { super(); setContentAreaFilled(false); setBorderPainted(false); setFocusPainted(false); this.imageNames = imageNames;
ActionListener timedAction = new ActionListener() { public void actionPerformed(ActionEvent e) { setIcon( new ImageIcon(imageNames[n]) ); n = (n + 1) % imageNames.length; } };
t = new javax.swing.Timer(speed, timedAction); t.setInitialDelay(0); } public synchronized void start() { if ( !t.isRunning() ) { t.start(); } }
public synchronized void stop() { if ( t.isRunning() ) { t.stop(); } }
}
|
and here's a demo which uses it: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*;
public class AnimatedButtonDemo extends JFrame { int speed = 100; String[] imageNames = {"images/duck0.jpg", "images/duck1.jpg", "images/duck2.jpg", "images/duck3.jpg"}; HotButton button; boolean startstop = false; public AnimatedButtonDemo() { super("Animated Button Demo");
button = new HotButton(imageNames, speed); button.addActionListener ( new ActionListener() { public void actionPerformed(ActionEvent e) { if (startstop) { startstop = false; button.start(); System.out.println("<< button started >>"); } else { button.stop(); startstop = true; System.out.println("|| button stopped ||"); } } } ); button.start(); Container c = getContentPane(); c.setLayout(null); button.setBounds(150,100, 93,90); c.add(button);
} public static void main(String[] args) { JFrame f = new AnimatedButtonDemo(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setSize(400,300); f.setVisible(true); } } |
Have fun! Craig
|
|
|
|
|
5
|
Java Game APIs & Engines / JOGL Development / Re: Can't Get Jogl to work on Mac OS X
|
on: 2003-12-12 00:42:15
|
|
You may need to install Panther (10.3). Lots of important Carbon --> Cocoa graphics/threading changes were implemented post-Jaguar.
Both lessons 2 and 3 run fine for me in windowed mode but fullscreen mode gives me a black empty screen. When I press the escape key, I see the images display correctly but just for a moment.
Of course, I am running on a very old, slow iMac without enough VRAM for hardware acceleration. Mac OS X 10.3.1 (7C107)
Craig
|
|
|
|
|
8
|
Java Game APIs & Engines / Java 2D / Re: JTextField in fullscreen game
|
on: 2003-06-05 05:35:23
|
Perhaps this link is relevant: http://www.milk.com/java-rants/bug01-awt-event.htmlExcerpt: "The case is that a user thread calls JFrame.setVisible(true) on a frame which contains a text field. The act of visible-izing causes an attempt to acquire a read lock on the document of the text field. At the same time, the user is typing in the field, and a text insertion event is being processed, which has already caused a write lock to be acquired on the same document. Given that the write lock has already been acquired, the read lock acquisition is stalled. However, the thread doing the setVisible() has already managed to acquire the anonymous universal lock (which I suspect is java.awt.Component.LOCK). Soon, the AWT event thread tries to acquire that same lock (i.e. synchronize on it). Oops! Deadlock: the event queue has the document lock and wants the anonymous lock; the user thread has the anonymous lock and wants the document lock."
|
|
|
|
|
9
|
Java Game APIs & Engines / Java 2D / Re: JTextField in fullscreen game
|
on: 2003-06-04 13:59:33
|
|
Hmmm...
Since JTextField is a subclass of JTextComponent, it *should* be thread safe. However, the JavaDocs say:
"The swing text components provide some support of thread safe operations. Because of the high level of configurability of the text components, it is possible to circumvent the protection provided. The protection primarily comes from the model, so the documentation of AbstractDocument describes the assumptions of the protection provided."
Have you tried using a shortcut for invoking non-thread-safe methods to modify your GUI:
EventQueue.invokeLater (or better) SwingUtilities.invokeLater ( new Runnable() { public void run() { field.setText("Hola, Gringo!"); } } );
or:
SwingUtilities.invokeLater ( new Runnable() { public void run() { try { // Some GUI modifying method which throws InterruptedException } catch (InterruptedException x) { x.printStackTrace(); } } } );
See the discussion of the AbstractDocument class for further clues. There are read/write locks firing...
|
|
|
|
|
10
|
Java Game APIs & Engines / Java 2D / Re: Disappointing performance with OS X
|
on: 2003-06-04 05:53:49
|
|
What type of graphics images are being displayed? This is often system/video dependent. Try running this performance test on both platforms:
// Program : TestGraphics.java // Description: Test performance of graphics types. // Notes : Use 'java -Xcomp' to run this app. This option will // force JIT-compilation at startup, instead of letting // HotSpot decide when and what to compile. Without it, // HotSpot may trigger compilation at an unknown or // unexpected point, invalidating the elapsed times due // to a flurry of JITC-ing. It may also be useful to run // with -Xint and -Xmixed to show how much is interpreter // cost and how much is graphics rendering cost.
import java.awt.*; import java.awt.image.*;
public class TestGraphics { static final int WIDTH = 700, HEIGHT = 700;
static final int COUNT = Math.min(WIDTH,HEIGHT)/2;
static final String[] sImageNames = { "TYPE_INT_RGB (HotSpot warm-up, throw away)", "TYPE_INT_RGB", "TYPE_INT_ARGB", "TYPE_INT_ARGB_PRE", "TYPE_INT_BGR", "TYPE_3BYTE_BGR", "TYPE_4BYTE_ABGR", "TYPE_4BYTE_ABGR_PRE", "TYPE_USHORT_565_RGB", "TYPE_USHORT_555_RGB", "TYPE_BYTE_GRAY", "TYPE_USHORT_GRAY", "TYPE_BYTE_BINARY", "TYPE_BYTE_INDEXED", "native CompatibleImage" };
static final int[] sImageConstants = { BufferedImage.TYPE_INT_RGB, BufferedImage.TYPE_INT_RGB, BufferedImage.TYPE_INT_ARGB, BufferedImage.TYPE_INT_ARGB_PRE, BufferedImage.TYPE_INT_BGR, BufferedImage.TYPE_3BYTE_BGR, BufferedImage.TYPE_4BYTE_ABGR, BufferedImage.TYPE_4BYTE_ABGR_PRE, BufferedImage.TYPE_USHORT_565_RGB, BufferedImage.TYPE_USHORT_555_RGB, BufferedImage.TYPE_BYTE_GRAY, BufferedImage.TYPE_USHORT_GRAY, BufferedImage.TYPE_BYTE_BINARY, BufferedImage.TYPE_BYTE_INDEXED };
// This is a simple test that does setColors and fillRects static void recTest(BufferedImage bi) { Graphics g2D = (Graphics2D) bi.getGraphics(); for (int i=0; i<COUNT; i++) { if (i%2 == 0 ) { g2D.setColor(Color.black); } else { g2D.setColor(Color.red); } g2D.fillRect(i,i, WIDTH-i,HEIGHT-i); } }
public static void main(String[] args) { long startTime; long[] elapsedTime = new long[sImageConstants.length + 1];
// Allocate 14 different buffered images to cross-compare BufferedImage[] bis = new BufferedImage[sImageConstants.length + 1]; for (int i=0; i<sImageConstants.length; i++) bis = new BufferedImage(WIDTH, HEIGHT, sImageConstants);
// Include native type: bis[sImageConstants.length] = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(WIDTH, HEIGHT);
// Compute and print performance System.out.println("Simple Graphics Performance Example"); System.out.println("Time\tImage Type\n----\t----------"); for (int i=0; i<=sImageConstants.length; i++) { startTime = System.currentTimeMillis(); recTest(bis); elapsedTime = System.currentTimeMillis() - startTime; System.out.println(elapsedTime + "\t" + sImageNames); }
// Doing graphics may start the AWT event-thread, thereby preventing // a return from main() from causing an exit. So, always force an exit. System.exit(0); } }
|
|
|
|
|
12
|
Java Game APIs & Engines / Java 3D / Re: Army wants 3D game engine
|
on: 2003-05-14 06:10:28
|
|
> mattocks, are you concerned with that yourself? > Related somehow?
Nope, not at all. I've written SBIR proposals in other topic areas but this one is beyond my current capability.
I thought perhaps some of the 3D experts on this list might want to spin up a company or work together and get paid for developing a 3D API. A nice opportunity!
Just trying to be helpful, Craig
|
|
|
|
|
13
|
Java Game APIs & Engines / Java 3D / Army wants 3D game engine
|
on: 2003-05-13 06:01:13
|
Anyone want to get paid for developing a 3D game engine for the US Army? See the new SBIR (Small Business Innovative Research) solicitations (requests for proposals): https://www.dodsbir.net/solicitation/default.htmProposals are due August 14, 2003. Phase I : $70,000 for 6 months Phase I option: $50,000 for 4 months Phase II : $730,000 for 2 years Phase III : transition to private sector Matching funds: $250,000 if available - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A03-083 TITLE: Military 3-D Visualization Utilizing Gaming Technology TECHNOLOGY AREAS: Information Systems, Human Systems ACQUISITION PROGRAM: PM, Future Combat Systems OBJECTIVE: Develop a standardized application programming interface (API) for a military 3-D gaming simulation tool that will facilitate the integration of a gaming environment with planned military C2 applications (such as the Commanders Support Environment, Combined Arms Planning and Execution System, DaVinci Toolkit). DESCRIPTION: This 3-D visualization interface will be required to work with a standard C2 Data Model and associated XML Schema and DTD to render 3-D visualizations of military units, as well as have the desired capability to render 3-D terrains and environments from standard NIMA maps and imagery. The simulation tool should be capable of taking live feeds from the associated military planning tools in a networked environment (multiple feeds desired) and rendering a 3-D virtual environment in near real-time for war-gaming scenarios. The API developed as part of this effort should be robust and extensible to allow for integration of live sensor feeds at a later date. Currently, no standard gaming API exists in the industry, which hampers the rapid development and application of gaming technology to large-scale simulation systems and trainers. (Each system becomes a custom environment.) The system should leverage commercial standards to the maximum extent and leverage existing gaming engine technology. It is desired that the system be capable of running on a current Windows 2000 environment, but Unix/Linux based systems will be considered. Development of such a system will directly support all Future Combat System experiments, which currently employ the Commanders Support Environment. Commercial applications include the use of such a system for Homeland Security, both in stand-alone exercises of non-military emergency personnel, as well as joint operations between civilian authorities and NORTHCOM. Commercial applications also allow gaming manufacturers to develop an industry-standard interface to allow for gaming applications to be used as simulation trainers for various commercial environments. PHASE I: Research current 3-D visualization techniques that are generated in real-time on desktop computing platforms utilizing commercial gaming engines and develop a systems architecture to incorporate these systems into Future Combat Systems C2 operational software. The systems should have the capability of interoperating with a command and control object model based on the DaVinci architecture, along with the ability to read XML data streams as input drivers to the system to effect movement of the objects during an operation. PHASE II: Develop a prototype 3-D visualization system and API that can be integrated into the Future Combat System C2 application based on the DaVinci architecture and its associated object model, XML Schema and DTD. As part of this effort, verify the validity of the API by demonstrating a working prototype where the existing the C2 application input/output effects are displayed in 3-D form using the visualization engine in a laboratory environment over a wired network. PHASE III: Future Combat System applications. This 3-D visualization system can also be used in commercial simulation scenarios for Homeland Security and Disaster Relief and Recovery systems for both civil defense and corporate applications. REFERENCES: 1) Future Combat System - See http://www.darpa.mil/fcs/index.html2) DaVinci Architecture - See http://call-ditt.leavenworth.army.mil/docs/CECOMBAA001.htm;3) DaVinci Architecture - Also see diicoe.disa.mil/coe/aog_twg/twg/mstwg/agile_brief.ppt KEYWORDS: 3-D visualization, game engines, gaming technology, XML, DaVinci, C2, command and control, Future Combat Systems TPOC: M. Zieniewicz, P. E. Phone: (732) 427-3143 Fax: (732) 427-3645 Email: matthew.zieniewicz@us.army.mil 2nd TPOC: R. Szymanski Phone: (732) 427-3698 Fax: (732) 427-3645 Email: ron.szymanski@us.army.mil
|
|
|
|
|
15
|
Game Development / Game Mechanics / Re: Drag calculations
|
on: 2003-05-09 17:47:41
|
|
I have experience running fluid dynamics simulations based on the Navier-Stokes equations.
The key question is: how much resolution do you need? Do you want to simulate the turbulent motion in the logarithmic sublayer under different Richardson number (stability) regimes or do you just want to make a lumpy, rough object like a lounge chair fly differently than a streamlined airfoil?
You can use a very simple parameterization (equation) to increase your drag coefficient as the surface roughness of an object increases. In flow over mountains, for example, something simple like this is used:
Cd = .001 + .006*z/(1+z)
where z is the surface elevation in km. This accounts for the increased form drag/surface roughness as you ascend the mountain. (This is a cloud's point of view. In your case, the object will be moving instead of the air, unless you want winds.)
I would advise using some simple equation - it will also run faster!
Best of luck, Craig
|
|
|
|
|
17
|
Java Game APIs & Engines / Java 2D / Re: GAGE Engine Early Access
|
on: 2003-04-03 04:05:17
|
> Honestly, for the purpose of games, is the extra 300-400 nanoseconds > that important? No, that was the difference between C resolution and Java resolution using my native timer. > 1000 ticks per second should be more than enough to time a > hundred or so frames per second. Good point, especially since the thread resolution is not very accurate. Perhaps a more experienced game programmer than I could coment? 1500 nanoseconds => 1/(1500 * 10^-9) = 666,666 ticks per second > I'm not quite sure what you mean here. If the HotSpot compiler > doesn't think it should be compiled, then there's a good bet that it > doesn't need to be. From what I've read, HotSpot compiles methods that are called more than 1,000 times or so. Calling a timer once (interpreted mode) will give you a much slower response (larger time resolution measurement) than calling it thousands of times (compiled mode) and averaging the results. I find a speedup in performance of 20x (interpreted/compiled ratio), which is significant. > Well, I don't have a Mac (yet), so I can't create one. But if someone out > there has the time and the need, I'd happily accept a donation.  I'll try this when I get some spare time. Nice work! Craig
|
|
|
|
|
18
|
Java Game APIs & Engines / Java 2D / Re: GAGE Engine Early Access
|
on: 2003-04-03 01:42:03
|
> Excellent! And Macs even manage to give a full 1000 ticks per second! > I knew I liked those machines for a reason...  My Mac OS X native C timer gives a resolution of about 1100 nanoseconds (1.1 microseconds = .0011 milliseconds). When I use it in Java via JNI, the resolution is about 1500 nanoseconds, so I lose 300-400 nanoseconds going across the interface. Note that your resolution algorithm does not adequately "warm up" HotSpot, so the code will not be forced to compile (it will be interpreted). When using System.currentTimeMillis() on the Mac this is not an issue since the apparent JVM timer resolution is 1 millisecond, but if you used a native timer you would obtain inconsistent results. Are you planning to build in native timer support in future releases? Craig
|
|
|
|
|
19
|
Java Game APIs & Engines / Java 2D / Re: GAGE Engine Early Access
|
on: 2003-04-01 23:30:36
|
|
How are you calculating resolution?
Are you exercising HotSpot enough to force it to compile the code? I've read that this requires at least 1000 calls to a method. How about something like:
// Error expected in measured elapsed time in nanoseconds public long getResolution() { final byte NTIMES = 10; long t1, t2; long dt = 0L;
// Warm up JIT/HotSpot compiler for (short s=0; s<3000; ++s) t1 = getCounter();
for (byte b=0; b<NTIMES; ++b) { t1 = getCounter(); t2 = getCounter(); while (t1 == t2) t2 = getCounter(); dt += (t2 - t1); } return dt/NTIMES; }
- Craig
|
|
|
|
|
20
|
Game Development / Performance Tuning / Native hi-rez timer for Mac
|
on: 2003-03-28 19:12:23
|
|
1. Grab these 3 classes (slightly modified) from the book "Java 1.4 Game Programming": - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // File: BaseClock.java // Description: Define a clock's capabilities // From: Chapter 12, "Java 1.4 Game Programming" // by Mulholland & Murphy, ISBN 1-55622-963-1
public abstract class BaseClock { public abstract long getTime(); public abstract int getDefaultUnit(); public abstract void stampTime(); public abstract long getElapsedTime(); public abstract long getElapsedTime(int unit);
public long stampTime;
public static final int UNIT_SECONDS = 1; // 10^0 public static final int UNIT_MILLIS = 1000; // 10^3 public static final int UNIT_MICROS = 1000000; // 10^6 public static final int UNIT_NANOS = 1000000000; // 10^9 } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // File: StandardClock.java // Description: A standard pure Java clock // From: Chapter 12, "Java 1.4 Game Programming" // by Mulholland & Murphy, ISBN 1-55622-963-1
public class StandardClock extends BaseClock { public long getTime() { return System.currentTimeMillis(); }
public int getDefaultUnit() { return UNIT_MILLIS; }
public void stampTime() { stampTime = System.currentTimeMillis(); }
public long getElapsedTime() { return System.currentTimeMillis() - stampTime; }
public long getElapsedTime(int unit) { return ((System.currentTimeMillis() - stampTime) * unit) / UNIT_MILLIS; } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // File: HiresTimeExample.java // Description: Test hi-rez native clocks // From: Chapter 12, "Java 1.4 Game Programming" // by Mulholland & Murphy, ISBN 1-55622-963-1
public class HiresTimeExample { public static void main(String[] args) { BaseClock clock = null;
// if ( NativeWinClock.isAvailable() ) if ( NativeMacClock.isAvailable() ) { System.out.println("Using native clock"); // clock = new NativeWinClock(); clock = new NativeMacClock(); } else { System.out.println("Using standard clock"); clock = new StandardClock(); }
// Constant velocity vector (u,v) = (dx/dt, dy/dt) // is defined in pixels per microsecond. // Magnitudes 160 and 240 represent pixels per second. double u = (double)160 / BaseClock.UNIT_MICROS; double v = (double)240 / BaseClock.UNIT_MICROS;
// current position to update with movement double x = 0; double y = 0;
long dt; // elapsed time
long counter = 0L; int secondsCounter = 0;
clock.stampTime();
while (secondsCounter<10) // if not passed 10 seconds { // get elasped time dt = clock.getElapsedTime(BaseClock.UNIT_MICROS);
// stamp clock clock.stampTime();
// increase elasped time counter counter += dt;
// update world (move sprite) x += (u * dt); y += (v * dt);
if (counter >= BaseClock.UNIT_MICROS) // if 1 second has elapsed { System.out.println("Time (seconds): " + clock.getTime()); System.out.println("Elapsed time counter = " + counter); counter -= BaseClock.UNIT_MICROS; System.out.println("Pos = " + x + ", " + y); secondsCounter++; }
// Note: sleep() is not high-resolution, // it is a source of timing error. try { Thread.sleep(5); } catch (Exception e) {} } } }
2. Write a Java program 'NativeMacClock.java' (similar to 'NativeWinClock.java') which calls the native timer:
// File: NativeMacClock.java // Author: Craig A. Mattocks // Date: March 2003 // Description: Native hi-rez Apple Macintosh clock // Reference: Chapter 12, "Java 1.4 Game Programming" // by Mulholland & Murphy, ISBN 1-55622-963-1
public class NativeMacClock extends BaseClock { // JNI timer method. Keyword 'native' --> C function. // Method declaration only, implementation is in file 'MacClock.c' private native long getCounter();
// Global class instance vars private long frequency; private static boolean available;
// Constructor public NativeMacClock() { frequency = UNIT_NANOS; // Macintosh clock has nanosecond precision }
// Class methods public long getTime() { return getCounter() / frequency; // Time returned in seconds }
public int getDefaultUnit() { return UNIT_SECONDS; }
public void stampTime() { stampTime = getCounter();
// System.out.println("Time stamp: " + stampTime); // Verify precision }
public long getElapsedTime() { return ((getCounter() - stampTime) * UNIT_MILLIS) / frequency; }
public long getElapsedTime(int unit) { return ((getCounter() - stampTime) * unit) / frequency; }
public static boolean isAvailable() { return available; }
// Static initializer executes once, when // class is loaded by runtime system. // Loads compiled C shared library: libMacClock.jnilib (Mac OS X) static { try { System.loadLibrary("MacClock"); available = true; } catch (UnsatisfiedLinkError ulp) {} catch (SecurityException sex) {} } }
3. Compile the Java class that calls the native method:
javac -O NativeMacClock.java
4. Generate a header file for the native method using javah with the native interface flag -jni:
javah -jni NativeMacClock
5. Examine the header file and grab the JNIEXPORT signature for the native method:
more NativeMacClock.h
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class NativeMacClock */
#ifndef _Included_NativeMacClock #define _Included_NativeMacClock #ifdef __cplusplus extern "C" { #endif #undef NativeMacClock_UNIT_SECONDS #define NativeMacClock_UNIT_SECONDS 1L #undef NativeMacClock_UNIT_MILLIS #define NativeMacClock_UNIT_MILLIS 1000L #undef NativeMacClock_UNIT_MICROS #define NativeMacClock_UNIT_MICROS 1000000L #undef NativeMacClock_UNIT_NANOS #define NativeMacClock_UNIT_NANOS 1000000000L /* Inaccessible static: available */ /* * Class: NativeMacClock * Method: getCounter * Signature: ()J */ JNIEXPORT jlong JNICALL Java_NativeMacClock_getCounter (JNIEnv *, jobject);
#ifdef __cplusplus } #endif #endif
6. Create the C source file 'MacClock.c' which contains the native timer method. Include the header and insert the above JNIEXPORT method signature (with appropriate parameters!):
// File: MacClock.c // Author: Craig A. Mattocks // Date: March 2003 // Description: Native hi-rez Apple Macintosh timer // Returns elapsed time in nanoseconds // since the machine was last booted.
#include <Carbon/Carbon.h> #include "NativeMacClock.h"
JNIEXPORT jlong JNICALL Java_NativeMacClock_getCounter(JNIEnv *env, jobject this) { union { Nanoseconds ns; UInt64 i; } time;
time.ns = AbsoluteToNanoseconds( UpTime() ); return time.i; }
7. Compile the header and implementation files, building the JNI library as a bundle:
cc -bundle -I/System/Library/Frameworks/JavaVM.framework/Headers -o libMacClock.jnilib -framework JavaVM -framework CoreServices MacClock.c
8. Move the JNI library to an appropriate place (optional):
mv libMacClock.jnilib /Library/Java/Extensions/
then let Java know where it can be found, either by using the:
-Djava.library.path="/Library/Java/Extensions"
option on the command line or in your information property list, or by setting the environment variables:
setenv DYLD_LIBRARY_PATH .:/Library/Java/Extensions:/usr/local/lib setenv LD_LIBRARY_PATH .:/Library/Java/Extensions
9. Compile and run the timer example:
javac -O HiresTimeExample.java java HiresTimeExample
Hooray, it works! Craig
|
|
|
|
|
21
|
Game Development / Shared Code / Re: Beginners drawing
|
on: 2003-02-28 06:58:25
|
|
Hi juddman,
Nice code examples - thank you!!!
I hacked on your DrawingBasics source to include a start/stop animation capability, as per Sun's timer examples:
/* * @(#)DrawingLessons.java 1.0 03/01/11 * * You can modify the template of this file in the * directory ..\JCreator\Templates\Template_1\Project_Name.java * * You can also create your own project template by making a new * folder in the directory ..\JCreator\Template\. Use the other * templates as examples. * */ import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*;
class DrawingBasics extends JFrame { BubbleSprite[] sprites = new BubbleSprite[1000]; JmGraphicsPanel gpane = new JmGraphicsPanel(); int curFill = 0; JPanel cp; JButton addSpr = new JButton("Add sprite"); JButton startButton = new JButton("Start"); JButton stopButton = new JButton("Stop");
Timer timer; boolean frozen = true; // Animation frozen?
ActionListener timedAction = new ActionListener() { public void actionPerformed(ActionEvent e) { go(); } };
//--------------------------------------------------------------------//
// Constructor public DrawingBasics(int fps, String windowTitle) { super(windowTitle);
// Compute frame delay int delay = (fps > 0) ? (1000 / fps) : 100; // Milliseconds
// Set up a timer that calls this object's action handler. timer = new Timer(delay, timedAction); timer.setInitialDelay(0); // Start up immediately timer.setCoalesce(true); // Prevent event flooding
for (int i = 0; i < sprites.length; i++) sprites = null;
// Sprite #1 BubbleSprite tmp = new BubbleSprite( 80, 100, 30, 70); addSprite(tmp); // Sprite #2 tmp = new BubbleSprite( 40, 40, 80, 50); tmp.setFillColor (Color.green); tmp.setLineColor(Color.yellow); addSprite(tmp);
// Sprite #3 tmp = new BubbleSprite( 45, 45, Math.random()*100, Math.random()*100); tmp.setFillColor (Color.orange); tmp.setLineColor(Color.magenta); addSprite(tmp); // Create user interface cp = (JPanel)getContentPane(); cp.setLayout(new BorderLayout()); cp.add(gpane, BorderLayout.CENTER);
JPanel controlPanel = new JPanel(); controlPanel.setLayout( new GridLayout(1,3) ); // GridLayout (rows, cols, dx, dy) controlPanel.add(addSpr); controlPanel.add(startButton); controlPanel.add(stopButton);
cp.add(controlPanel, BorderLayout.SOUTH); gpane.setGraphicArray(sprites); addSpr.addActionListener ( new ActionListener() { public void actionPerformed(ActionEvent e) { addRandomSprite(); } } );
startButton.addActionListener ( new ActionListener() { public void actionPerformed(ActionEvent e) { if (frozen) { frozen = false; startButton.setEnabled(false); stopButton.setEnabled(true); startAnimation(); } } } );
stopButton.addActionListener ( new ActionListener() { public void actionPerformed(ActionEvent e) { if (! frozen) { stopAnimation(); frozen = true; startButton.setEnabled(true); stopButton.setEnabled(false); } } } );
// timer.start(); // Autostart (disabled) // Window closing listener addWindowListener ( new WindowAdapter() { public void windowDeiconified(WindowEvent e) { if (frozen) { frozen = false; startButton.setEnabled(false); stopButton.setEnabled(true); startAnimation(); } } public void windowIconified(WindowEvent e) { if (! frozen) { stopAnimation(); frozen = true; startButton.setEnabled(true); stopButton.setEnabled(false); } } public void windowClosing(WindowEvent e) { stopAnimation(); dispose(); System.exit(0); } } );
}
//--------------------------------------------------------------------//
public void go() { for (int i=0; i<sprites.length; i++) { if (sprites != null) sprites.randomMotion(); else break; } //System.out.print("."); gpane.repaint(); }
//--------------------------------------------------------------------//
// Can be invoked by any thread (since timer is thread-safe). public synchronized void startAnimation() { if (frozen) { // Do nothing. The user has requested // that we stop changing the image. } else { // Start animating! if ( !timer.isRunning() ) { timer.start(); } } }
//--------------------------------------------------------------------//
// Can be invoked by any thread (since timer is thread-safe). public synchronized void stopAnimation() { // Stop the animating thread. if ( timer.isRunning() ) { timer.stop(); } }
//--------------------------------------------------------------------//
public void addSprite(BubbleSprite in) { sprites[curFill] = in; curFill ++; }
//--------------------------------------------------------------------//
public void addRandomSprite() { BubbleSprite tmp = new BubbleSprite( 45, 45, Math.random()*100, Math.random()*100); int col1 = (int)(Math.random()*255); int col2 = (int)(Math.random()*255); int col3 = (int)(Math.random()*255); System.out.print ("" + col1 + col2 + col3); tmp.setFillColor (new Color(col1, col2, col3)); tmp.setLineColor(Color.magenta); addSprite(tmp); }
//--------------------------------------------------------------------//
public static void main(String args[]) { System.out.println("Starting DrawingBasics...");
int fps = 10; // 1000 ms = 1 sec so we expect 10 fps.
// Get frames per second from the command line argument. if (args.length > 0) { try { fps = Integer.parseInt(args[0]); } catch (Exception e) {} }
DrawingBasics mainFrame = new DrawingBasics(fps, "Sprite Animator"); mainFrame.setSize(400, 400); mainFrame.setTitle("DrawingBasics"); mainFrame.setVisible(true); }
}
- Craig
|
|
|
|
|
|
Add your game by posting it in the WIP section,
or publish it in Showcase.
The first screenshot will be displayed as a thumbnail.
|
|