Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (578)
games submitted by our members
Games in WIP (499)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Native hi-rez timer for Mac  (Read 2139 times)
0 Members and 1 Guest are viewing this topic.
Offline mattocks

Senior Newbie




Java games rock!


« Posted 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
Offline GergisKhan

Junior Member




&quot;C8 H10 N4 O2&quot;


« Reply #1 - Posted 2003-04-02 15:28:16 »

Heres a BIG BIG BIG question:

Is there a way, using Java Web Start, to be able to deploy this hires timer to a mac client?

Moreover, can we deploy one for Windows and one for Mac without worrying about which platform is which?


gK

"Go.  Teach them not to mess with us."
          -- Cao Cao, Dynasty Warriors 3
Offline jbanes

JGO Coder


Projects: 1


"Java Games? Incredible! Mr. Incredible, that is!"


« Reply #2 - Posted 2003-04-02 15:39:41 »

Web Start actually has explicit support for native libraries. Here's  a description of how to do it:

http://java.sun.com/products/javawebstart/1.2/docs/developersguide.html#servlet

That being said, *you don't need a native high res timer on the Mac* unless you are doing something truely time-critical, requiring nano-second precision. System.currentTimeMillis() on the Mac, gives 1 beat per millisecond which allows you a 1/1000th of a second resolution. Windows is of course still a problem, but you can use a timer like (WARNING! Plug in for my stuff ahead!  Grin) the GAGETimer (http://java.dnsalias.com) to handle cross platform issues.

Java Game Console Project
Last Journal Entry: 12/17/04
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline GergisKhan

Junior Member




&quot;C8 H10 N4 O2&quot;


« Reply #3 - Posted 2003-04-02 15:46:15 »

jbanes, if I am right you should probably mention in the Shared Code thread that GAGETimer 1.0 is the same or supersedes the one previously posted.

gK

"Go.  Teach them not to mess with us."
          -- Cao Cao, Dynasty Warriors 3
Offline jbanes

JGO Coder


Projects: 1


"Java Games? Incredible! Mr. Incredible, that is!"


« Reply #4 - Posted 2003-04-02 15:58:11 »

Good point. I'll go do that. Smiley

Java Game Console Project
Last Journal Entry: 12/17/04
Offline swpalmer

JGO Coder




Where's the Kaboom?


« Reply #5 - Posted 2003-04-03 16:51:36 »

As has been pointed out naitve code with Web start is generally not a problem.  But I came a cross one HUGE issue with it that prevented me from using it for a project.

I needed to install some native code.. libraries that depended on other libraries that I was distributing..  Some were media codecs from 3rd parties...  I tried to use the mechanisms in webstart to install extensions and add paths to runtime so it could find libraries.. and that API did not work.  It seems if you have that kind of extension you MUST install stuff in a place that is already in the path because the webstart API is broken. (this was on Windows)

Also there seems to be no way to change the ccurrent directory in Java.. even from native code.. so I had no way of getting libraries into my path.

(I know of tricks to load libraries if you use A and A needs B, just loadLibrary B first and then load A.. but that hack wouldn't work in my situation. )

Btw, this has nothing to do with timers, sorry Smiley

Offline jbanes

JGO Coder


Projects: 1


"Java Games? Incredible! Mr. Incredible, that is!"


« Reply #6 - Posted 2003-04-03 16:54:20 »

You should statically link all the libs into one. That'll take care of the problem.

Java Game Console Project
Last Journal Entry: 12/17/04
Offline swpalmer

JGO Coder




Where's the Kaboom?


« Reply #7 - Posted 2003-04-04 05:23:45 »

That's not possible... the libraries are from 3rd party codecs, and they are dynamically loaded by design of those libraries. I can't change that.

Offline jbanes

JGO Coder


Projects: 1


"Java Games? Incredible! Mr. Incredible, that is!"


« Reply #8 - Posted 2003-04-04 14:44:43 »

Well, that leaves you one option. Your web start program should first run a bootloader that extracts the files into the user's path (i.e. c:\winnt\system32) before attempting to load the DLL.

Java Game Console Project
Last Journal Entry: 12/17/04
Offline swpalmer

JGO Coder




Where's the Kaboom?


« Reply #9 - Posted 2003-04-04 23:51:43 »

That isn't acceptable either...  I don't want to be one of those evil programmers that pollutes system32 :-)

Seriously.. there is a whole directory hierarchy for this stuff that has to be installed and trying to plunk that in system32 isn't going to work.

What I really need to do is to change the current directory.  So that file opens are relative to a directory structure that I install.  Something that seems to be impossible with java.

I tried using native code to change the current dir.. since bizarrely there is no Java API to do it!!  It did not work... it was like the JVM changed it back on me before my native code returned or something. Maybe something about preserving the current dir for the classpath???

I think this would all work if the WebStart API worked as advertised.,  I submitted a bug report months ago but have heard nothing.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Exocet

Senior Newbie





« Reply #10 - Posted 2003-04-28 15:10:46 »

Actually as of yet I see no need for a high res timer for mac... if you do some simple tests currentTimeMillis IS accurate to the millisecond.  If you want higher resolution, check out the UNIX command gettimeofday (also available in MACOSX).  It will give you accuracy up to the microsecond.  Just some simple JNI code required.

- Tristan

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (28 views)
2014-04-15 18:08:23

BurntPizza (25 views)
2014-04-15 03:46:01

UprightPath (40 views)
2014-04-14 17:39:50

UprightPath (22 views)
2014-04-14 17:35:47

Porlus (38 views)
2014-04-14 15:48:38

tom_mai78101 (62 views)
2014-04-10 04:04:31

BurntPizza (121 views)
2014-04-08 23:06:04

tom_mai78101 (221 views)
2014-04-05 13:34:39

trollwarrior1 (188 views)
2014-04-04 12:06:45

CJLetsGame (195 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!