Javascript support

[java]

/*

  • Copyright © 2009-2010 jMonkeyEngine
  • All rights reserved.

    *
  • Redistribution and use in source and binary forms, with or without
  • modification, are permitted provided that the following conditions are
  • met:

    *
    • Redistributions of source code must retain the above copyright
  • notice, this list of conditions and the following disclaimer.

    *
    • Redistributions in binary form must reproduce the above copyright
  • notice, this list of conditions and the following disclaimer in the
  • documentation and/or other materials provided with the distribution.

    *
    • Neither the name of ‘jMonkeyEngine’ nor the names of its contributors
  • may be used to endorse or promote products derived from this software
  • without specific prior written permission.

    *
  • THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  • "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  • TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  • PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  • CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  • EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  • PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  • PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  • LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  • NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  • SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    */



    package com.jme3.app;



    import com.jme3.app.state.AppStateManager;

    import com.jme3.input.JoyInput;

    import com.jme3.input.KeyInput;

    import com.jme3.input.MouseInput;

    import com.jme3.input.TouchInput;

    import com.jme3.math.Vector3f;

    import com.jme3.renderer.Camera;

    import com.jme3.renderer.Renderer;

    import com.jme3.asset.AssetManager;

    import com.jme3.audio.AudioContext;

    import com.jme3.audio.AudioRenderer;

    import com.jme3.audio.Listener;

    import com.jme3.input.InputManager;

    import com.jme3.renderer.RenderManager;

    import com.jme3.renderer.ViewPort;

    import com.jme3.system.AppSettings;

    import com.jme3.system.JmeCanvasContext;

    import com.jme3.system.JmeContext;

    import java.net.MalformedURLException;

    import java.net.URL;

    import java.util.concurrent.Callable;

    import java.util.concurrent.ConcurrentLinkedQueue;

    import java.util.concurrent.Future;

    import java.util.logging.Level;

    import java.util.logging.Logger;

    import com.jme3.system.JmeContext.Type;

    import com.jme3.system.JmeSystem;

    import com.jme3.system.NanoTimer;

    import com.jme3.system.SystemListener;

    import com.jme3.system.Timer;



    /**
  • The <code>Application</code> class represents an instance of a
  • real-time 3D rendering jME application.

    *
  • An <code>Application</code> provides all the tools that are commonly used in jME3
  • applications.

    *
  • jME3 applications should extend this class and call start() to begin the
  • application.

    *

    */

    public class Application implements SystemListener {



    private static final Logger logger = Logger.getLogger(Application.class.getName());



    protected AssetManager assetManager;



    protected AudioRenderer audioRenderer;

    protected Renderer renderer;

    protected RenderManager renderManager;

    protected ViewPort viewPort;

    protected ViewPort guiViewPort;



    protected JmeContext context;

    protected AppSettings settings;

    protected Timer timer = new NanoTimer();

    protected Camera cam;

    protected Listener listener;



    protected boolean inputEnabled = true;

    protected boolean pauseOnFocus = true;

    protected float speed = 1f;

    protected boolean paused = false;

    protected MouseInput mouseInput;

    protected KeyInput keyInput;

    protected JoyInput joyInput;

    protected TouchInput touchInput;

    protected InputManager inputManager;

    protected AppStateManager stateManager;



    protected java.applet.Applet applet;



    private final ConcurrentLinkedQueue<AppTask<?>> taskQueue = new ConcurrentLinkedQueue<AppTask<?>>();



    /**
  • Create a new instance of <code>Application</code>.

    */

    public Application(){

    }



    /**
  • Returns true if pause on lost focus is enabled, false otherwise.

    *
  • @return true if pause on lost focus is enabled

    *
  • @see #setPauseOnLostFocus(boolean)

    */

    public boolean isPauseOnLostFocus() {

    return pauseOnFocus;

    }



    /**
  • Enable or disable pause on lost focus.
  • <p>
  • By default, pause on lost focus is enabled.
  • If enabled, the application will stop updating
  • when it loses focus or becomes inactive (e.g. alt-tab).
  • For online or real-time applications, this might not be preferable,
  • so this feature should be set to disabled. For other applications,
  • it is best to keep it on so that CPU usage is not used when
  • not necessary.

    *
  • @param pauseOnLostFocus True to enable pause on lost focus, false
  • otherwise.

    */

    public void setPauseOnLostFocus(boolean pauseOnLostFocus) {

    this.pauseOnFocus = pauseOnLostFocus;

    }



    @Deprecated

    public void setAssetManager(AssetManager assetManager){

    if (this.assetManager != null)

    throw new IllegalStateException("Can only set asset manager"
  • " before initialization.");



    this.assetManager = assetManager;

    }



    private void initAssetManager(){

    if (settings != null){

    String assetCfg = settings.getString("AssetConfigURL");

    if (assetCfg != null){

    URL url = null;

    try {

    url = new URL(assetCfg);

    } catch (MalformedURLException ex) {

    }

    if (url == null) {

    url = Application.class.getClassLoader().getResource(assetCfg);

    if (url == null) {

    logger.log(Level.SEVERE, "Unable to access AssetConfigURL in asset config:{0}", assetCfg);

    return;

    }

    }

    assetManager = JmeSystem.newAssetManager(url);

    }

    }

    if (assetManager == null){

    assetManager = JmeSystem.newAssetManager(

    Thread.currentThread().getContextClassLoader()

    .getResource("com/jme3/asset/Desktop.cfg"));

    }

    }



    /**
  • Set the display settings to define the display created.
  • <p>
  • Examples of display parameters include display pixel width and height,
  • color bit depth, z-buffer bits, anti-aliasing samples, and update frequency.
  • If this method is called while the application is already running, then
  • {@link #restart() } must be called to apply the settings to the display.

    *
  • @param settings The settings to set.

    */

    public void setSettings(AppSettings settings){

    this.settings = settings;

    if (context != null && settings.useInput() != inputEnabled){

    // may need to create or destroy input based

    // on settings change

    inputEnabled = !inputEnabled;

    if (inputEnabled){

    initInput();

    }else{

    destroyInput();

    }

    }else{

    inputEnabled = settings.useInput();

    }

    }



    /**
  • Sets the Timer implementation that will be used for calculating
  • frame times. By default, Application will use the Timer as returned
  • by the current JmeContext implementation.

    */

    public void setTimer(Timer timer){

    this.timer = timer;



    if (timer != null) {

    timer.reset();

    }



    if (renderManager != null) {

    renderManager.setTimer(timer);

    }

    }



    private void initDisplay(){

    // aquire important objects

    // from the context

    settings = context.getSettings();



    // Only reset the timer if a user has not already provided one

    if (timer == null) {

    timer = context.getTimer();

    }



    renderer = context.getRenderer();

    }



    private void initAudio(){

    if (settings.getAudioRenderer() != null && context.getType() != Type.Headless){

    audioRenderer = JmeSystem.newAudioRenderer(settings);

    audioRenderer.initialize();

    AudioContext.setAudioRenderer(audioRenderer);



    listener = new Listener();

    audioRenderer.setListener(listener);

    }

    }



    /**
  • Creates the camera to use for rendering. Default values are perspective
  • projection with 45° field of view, with near and far values 1 and 1000
  • units respectively.

    */

    private void initCamera(){

    cam = new Camera(settings.getWidth(), settings.getHeight());



    cam.setFrustumPerspective(45f, (float)cam.getWidth() / cam.getHeight(), 1f, 1000f);

    cam.setLocation(new Vector3f(0f, 0f, 10f));

    cam.lookAt(new Vector3f(0f, 0f, 0f), Vector3f.UNIT_Y);



    renderManager = new RenderManager(renderer);

    //Remy - 09/14/2010 setted the timer in the renderManager

    renderManager.setTimer(timer);

    viewPort = renderManager.createMainView("Default", cam);

    viewPort.setClearFlags(true, true, true);



    // Create a new cam for the gui

    Camera guiCam = new Camera(settings.getWidth(), settings.getHeight());

    guiViewPort = renderManager.createPostView("Gui Default", guiCam);

    guiViewPort.setClearFlags(false, false, false);

    }



    /**
  • Initializes mouse and keyboard input. Also
  • initializes joystick input if joysticks are enabled in the
  • AppSettings.

    */

    private void initInput(){

    mouseInput = context.getMouseInput();

    if (mouseInput != null)

    mouseInput.initialize();



    keyInput = context.getKeyInput();

    if (keyInput != null)

    keyInput.initialize();



    touchInput = context.getTouchInput();

    if (touchInput != null)

    touchInput.initialize();



    if (!settings.getBoolean("DisableJoysticks")){

    joyInput = context.getJoyInput();

    if (joyInput != null)

    joyInput.initialize();

    }



    inputManager = new InputManager(mouseInput, keyInput, joyInput, touchInput);

    }



    private void initStateManager(){

    stateManager = new AppStateManager(this);

    }



    /**
  • @return The {@link AssetManager asset manager} for this application.

    */

    public AssetManager getAssetManager(){

    return assetManager;

    }



    /**
  • @return the {@link InputManager input manager}.

    */

    public InputManager getInputManager(){

    return inputManager;

    }



    /**
  • @return the {@link AppStateManager app state manager}

    */

    public AppStateManager getStateManager() {

    return stateManager;

    }



    /**
  • @return the {@link RenderManager render manager}

    */

    public RenderManager getRenderManager() {

    return renderManager;

    }



    /**
  • @return The {@link Renderer renderer} for the application

    */

    public Renderer getRenderer(){

    return renderer;

    }



    /**
  • @return The {@link AudioRenderer audio renderer} for the application

    */

    public AudioRenderer getAudioRenderer() {

    return audioRenderer;

    }



    /**
  • @return The {@link Listener listener} object for audio

    */

    public Listener getListener() {

    return listener;

    }



    /**
  • @return The {@link JmeContext display context} for the application

    */

    public JmeContext getContext(){

    return context;

    }



    /**
  • @return The {@link Camera camera} for the application

    */

    public Camera getCamera(){

    return cam;

    }



    /**
  • Starts the application in {@link Type#Display display} mode.

    *
  • @see #start(com.jme3.system.JmeContext.Type)

    */

    public void start(){

    start(JmeContext.Type.Display);

    }



    /**
  • Starts the application.
  • Creating a rendering context and executing
  • the main loop in a separate thread.

    */

    public void start(JmeContext.Type contextType){

    if (context != null && context.isCreated()){

    logger.warning("start() called when application already created!");

    return;

    }



    if (settings == null){

    settings = new AppSettings(true);

    }



    logger.log(Level.FINE, "Starting application: {0}", getClass().getName());

    context = JmeSystem.newContext(settings, contextType);

    context.setSystemListener(this);

    context.create(false);

    }



    /**
  • Initializes the application’s canvas for use.
  • <p>
  • After calling this method, cast the {@link #getContext() context} to
  • {@link JmeCanvasContext},
  • then acquire the canvas with {@link JmeCanvasContext#getCanvas() }
  • and attach it to an AWT/Swing Frame.
  • The rendering thread will start when the canvas becomes visible on
  • screen, however if you wish to start the context immediately you
  • may call {@link #startCanvas() } to force the rendering thread
  • to start.

    *
  • @see JmeCanvasContext
  • @see Type#Canvas

    */

    public void createCanvas(){

    if (context != null && context.isCreated()){

    logger.warning("createCanvas() called when application already created!");

    return;

    }



    if (settings == null){

    settings = new AppSettings(true);

    }



    logger.log(Level.FINE, "Starting application: {0}", getClass().getName());

    context = JmeSystem.newContext(settings, JmeContext.Type.Canvas);

    context.setSystemListener(this);

    }



    /**
  • Starts the rendering thread after createCanvas() has been called.
  • <p>
  • Same as calling startCanvas(false)

    *
  • @see #startCanvas(boolean)

    */

    public void startCanvas(){

    startCanvas(false);

    }



    /**
  • Starts the rendering thread after createCanvas() has been called.
  • <p>
  • Calling this method is optional, the canvas will start automatically
  • when it becomes visible.

    *
  • @param waitFor If true, the current thread will block until the
  • rendering thread is running

    */

    public void startCanvas(boolean waitFor){

    context.create(waitFor);

    }



    /**
  • Internal use only.

    */

    public void reshape(int w, int h){

    renderManager.notifyReshape(w, h);

    }



    /**
  • Restarts the context, applying any changed settings.
  • <p>
  • Changes to the {@link AppSettings} of this Application are not
  • applied immediately; calling this method forces the context
  • to restart, applying the new settings.

    */

    public void restart(){

    context.setSettings(settings);

    context.restart();

    }



    /**
  • Requests the context to close, shutting down the main loop
  • and making necessary cleanup operations.

    *
  • Same as calling stop(false)

    *
  • @see #stop(boolean)

    */

    public void stop(){

    stop(false);

    }



    /**
  • Requests the context to close, shutting down the main loop
  • and making necessary cleanup operations.
  • After the application has stopped, it cannot be used anymore.

    */

    public void stop(boolean waitFor){

    logger.log(Level.FINE, "Closing application: {0}", getClass().getName());

    context.destroy(waitFor);

    }



    /**
  • Do not call manually.
  • Callback from ContextListener.
  • <p>
  • Initializes the <code>Application</code>, by creating a display and
  • default camera. If display settings are not specified, a default
  • 640x480 display is created. Default values are used for the camera;
  • perspective projection with 45° field of view, with near
  • and far values 1 and 1000 units respectively.

    */

    public void initialize(){

    if (assetManager == null){

    initAssetManager();

    }



    initDisplay();

    initCamera();



    if (inputEnabled){

    initInput();

    }

    initAudio();

    initStateManager();



    // update timer so that the next delta is not too large

    // timer.update();

    timer.reset();



    // user code here…

    }



    /**
  • Internal use only.

    */

    public void handleError(String errMsg, Throwable t){

    logger.log(Level.SEVERE, errMsg, t);

    // user should add additional code to handle the error.

    stop(); // stop the application

    }



    /**
  • Internal use only.

    */

    public void gainFocus(){

    if (pauseOnFocus) {

    paused = false;

    context.setAutoFlushFrames(true);

    if (inputManager != null) {

    inputManager.reset();

    }

    }

    }



    /**
  • Internal use only.

    */

    public void loseFocus(){

    if (pauseOnFocus){

    paused = true;

    context.setAutoFlushFrames(false);

    }

    }



    /**
  • Internal use only.

    */

    public void requestClose(boolean esc){

    context.destroy(false);

    }



    /**
  • Enqueues a task/callable object to execute in the jME3
  • rendering thread.
  • <p>
  • Callables are executed right at the beginning of the main loop.
  • They are executed even if the application is currently paused
  • or out of focus.

    */

    public <V> Future<V> enqueue(Callable<V> callable) {

    AppTask<V> task = new AppTask<V>(callable);

    taskQueue.add(task);

    return task;

    }



    /**
  • Do not call manually.
  • Callback from ContextListener.

    */

    public void update(){

    // Make sure the audio renderer is available to callables

    AudioContext.setAudioRenderer(audioRenderer);



    AppTask<?> task = taskQueue.poll();

    toploop: do {

    if (task == null) break;

    while (task.isCancelled()) {

    task = taskQueue.poll();

    if (task == null) break toploop;

    }

    task.invoke();

    } while (((task = taskQueue.poll()) != null));



    if (speed == 0 || paused)

    return;



    timer.update();



    if (inputEnabled){

    inputManager.update(timer.getTimePerFrame());

    }



    if (audioRenderer != null){

    audioRenderer.update(timer.getTimePerFrame());

    }



    // user code here…

    }



    protected void destroyInput(){

    if (mouseInput != null)

    mouseInput.destroy();



    if (keyInput != null)

    keyInput.destroy();



    if (joyInput != null)

    joyInput.destroy();



    if (touchInput != null)

    touchInput.destroy();



    inputManager = null;

    }



    /**
  • Do not call manually.
  • Callback from ContextListener.

    */

    public void destroy(){

    stateManager.cleanup();



    destroyInput();

    if (audioRenderer != null)

    audioRenderer.cleanup();



    timer.reset();

    }



    /**
  • @return The GUI viewport. Which is used for the on screen
  • statistics and FPS.

    /

    public ViewPort getGuiViewPort() {

    return guiViewPort;

    }



    public ViewPort getViewPort() {

    return viewPort;

    }



    void setApplet(java.applet.Applet applet) {

    this.applet = applet;

    }

    public java.applet.Applet getApplet(){

    return applet;

    }

    public void javascript(String method, Object arguments){

    if(applet != null){

    try {

    getApplet().getAppletContext().showDocument

    (new URL("javascript:"+ method+ "("" + arguments +"")"));

    }

    catch (MalformedURLException me) {}

    }

    }

    }

    [/java]



    [java]

    /

  • Copyright © 2009-2010 jMonkeyEngine
  • All rights reserved.

    *
  • Redistribution and use in source and binary forms, with or without
  • modification, are permitted provided that the following conditions are
  • met:

    *
    • Redistributions of source code must retain the above copyright
  • notice, this list of conditions and the following disclaimer.

    *
    • Redistributions in binary form must reproduce the above copyright
  • notice, this list of conditions and the following disclaimer in the
  • documentation and/or other materials provided with the distribution.

    *
    • Neither the name of ‘jMonkeyEngine’ nor the names of its contributors
  • may be used to endorse or promote products derived from this software
  • without specific prior written permission.

    *
  • THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  • "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  • TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  • PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  • CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  • EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  • PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  • PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  • LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  • NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  • SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    */



    package com.jme3.app;



    import com.jme3.system.AppSettings;

    import com.jme3.system.JmeCanvasContext;

    import com.jme3.system.JmeSystem;

    import java.applet.Applet;

    import java.awt.Canvas;

    import java.awt.Graphics;

    import java.io.IOException;

    import java.io.InputStream;

    import java.net.MalformedURLException;

    import java.net.URL;

    import java.util.HashMap;

    import java.util.logging.Level;

    import java.util.logging.Logger;

    import javax.swing.JOptionPane;

    import javax.swing.SwingUtilities;



    /**
  • @author Kirill Vainer

    */

    public class AppletHarness extends Applet {



    public static final HashMap<Application, Applet> appToApplet

    = new HashMap<Application, Applet>();



    private JmeCanvasContext context;

    private Canvas canvas;

    private Application app;



    private String appClass;

    private URL appCfg = null;

    private URL assetCfg = null;



    public static Applet getApplet(Application app){

    return appToApplet.get(app);

    }



    private void createCanvas(){

    AppSettings settings = new AppSettings(true);



    // load app cfg

    if (appCfg != null){

    InputStream in = null;

    try {

    in = appCfg.openStream();

    settings.load(in);

    in.close();

    } catch (IOException ex){

    // Called before application has been created …

    // Display error message through AWT

    JOptionPane.showMessageDialog(this, "An error has occured while "
  • "loading applet configuration"
  • ex.getMessage(),

    “jME3 Applet”,

    JOptionPane.ERROR_MESSAGE);

    ex.printStackTrace();

    } finally {

    if (in != null)

    try {

    in.close();

    } catch (IOException ex) {

    }

    }

    }



    if (assetCfg != null){

    settings.putString(“AssetConfigURL”, assetCfg.toString());

    }



    settings.setWidth(getWidth());

    settings.setHeight(getHeight());



    JmeSystem.setLowPermissions(true);



    try{

    Class<? extends Application> clazz = (Class<? extends Application>) Class.forName(appClass);

    app = clazz.newInstance();

    }catch (ClassNotFoundException ex){

    ex.printStackTrace();

    }catch (InstantiationException ex){

    ex.printStackTrace();

    }catch (IllegalAccessException ex){

    ex.printStackTrace();

    }



    appToApplet.put(app, this);

    app.setSettings(settings);

    app.createCanvas();

    app.setApplet(this);



    context = (JmeCanvasContext) app.getContext();

    canvas = context.getCanvas();

    canvas.setSize(getWidth(), getHeight());



    add(canvas);

    app.startCanvas();

    app.javascript(“canvasReady”,"");

    }



    @Override

    public final void update(Graphics g) {

    canvas.setSize(getWidth(), getHeight());

    }



    @Override

    public void init(){

    appClass = getParameter(“AppClass”);

    if (appClass == null)

    throw new RuntimeException(“The required parameter AppClass isn’t specified!”);



    try {

    appCfg = new URL(getParameter(“AppSettingsURL”));

    } catch (MalformedURLException ex) {

    System.out.println(ex.getMessage());

    appCfg = null;

    }



    try {

    assetCfg = new URL(getParameter(“AssetConfigURL”));

    } catch (MalformedURLException ex){

    System.out.println(ex.getMessage());

    assetCfg = getClass().getResource("/com/jme3/asset/Desktop.cfg");

    }



    createCanvas();

    System.out.println(“applet:init”);

    }



    @Override

    public void start(){

    context.setAutoFlushFrames(true);

    System.out.println(“applet:start”);

    }



    @Override

    public void stop(){

    context.setAutoFlushFrames(false);

    System.out.println(“applet:stop”);

    }



    @Override

    public void destroy(){

    System.out.println(“applet:destroyStart”);

    SwingUtilities.invokeLater(new Runnable(){

    public void run(){

    removeAll();

    System.out.println(“applet:destroyRemoved”);

    }

    });

    app.stop(true);

    System.out.println(“applet:destroyDone”);



    appToApplet.remove(app);

    }

    public Application getApp(){

    return app;

    }



    }

    [/java]



    The above code adds a way to easily add javascript to applet games, both the applet talking to javascript and javascript talking to the applet :slight_smile:



    Heres a little example of it in action:



    inside of my game class that is extending SimpleApplication

    [java]

    private void gameOver() {

    stateManager.detach(bulletAppState);

    hudText.setText(“GAMEOVER!!! Score:” + scoreCounter);

    finalScore = scoreCounter;

    javascript(“showScore”, finalScore + “”);

    specialText.setText(“Spacebar to continue…”);

    gameOver = true;

    character_phys.setLinearVelocity(new Vector3f(0f, 0f, 0f));

    }

    public String getDirections(){

    return “Press spacebar to go up and down. b and v are specials”;

    }



    [/java]



    and in the applet webpage:

    [java]

    <script type=“text/javascript”>

    function canvasReady(){

    var dirs = document.applets[0].getApplet().getApp().getDirections();

    document.getElementById(“directions”).innerHTML = dirs;

    }

    function showScore(s) {

    document.getElementById(“score”).innerHTML = "your previous score: " + s ;

    }



    </script>

    [/java]







    kind of a weak example of calling a game method, but i thought i should demonstrate it.

    Let me know what ya’all think :slight_smile:
1 Like

20/20 i probly coulda just post the changes i made to the two classes, whoopsies :slight_smile:

99.9% sure you could have done all of the changes to core classes with an AppState instead.



…well, except the AppletHarness.getApp() part.

Yeah ill probably do that if these changes don’t take (don’t want to be codding against custom API), i just like it for the simplicity in the game to just do javascript(function, args) whenever i want to do javascript. I also like the app.javascript(“canvasReady”,"") in the AppletHarness to let the page know that the canvas is loaded, tho i suppose i could just do a js method call in my games init :slight_smile:



i would be most appreciative if AppletHarness.getApp() was added tho so i can access the game with document.applets[0].getApplet().getApp() otherwise ill have to use brain power to figure out how to get access to it (god knows i don’t have that :p)

Cheers

-Allman

There is also nothing preventing your from adding a javascript() method to your own SimpleApplication subclass. It’s a pretty rare thing to need and can be easily added by users, so I don’t think it will get added to core.



I could set the getApp() getting added but that’s not really my area.

Thanks pspeed!

Ill write a tut for the site after i get my project working, i’m working on getting a high score tracking system for rails :slight_smile: i need to practice up on my ruby so i can gemafy it when i’m done:D

I’ll say nothing about Ruby on Rails but it’s great that you plan to write a tutorial on this! I’m looking forward to it :slight_smile:

Well, through the JSR-223 you can use any scripting language.