How can I program a room full of objects during runtime

Sorry for the confusing title, i’m trying to make an abstract project i’m not a native English speaker.
I’m trying to make a ‘zoo’ with creatures that were programmed by people during an event.
These people will program these creatures on other laptops with processing.

And now the tricky part.
During the runtime of the program I want to upload new code.
Let’s say I press a button with: add another create and upload the code that that person has programmed.
Now their little programmed creature also joins the ‘zoo’ and will be visible on the screen.

The problem i’m running into is:
How do I execute code that is uploaded during a runtime of a processing program.

Let’s say person uploads a programmed a creature that is shaped like a rectangle and person b uploads a creature that is shaped like two ellipses.

Is this possible to do in Processing? Alternatively I might want to make something that just uploads gifs if code doesn’t work.

I hope I made myself clear, thank you for reading!

2 Likes

Hi! Welcome to the forum :slight_smile:

Does it have to be Processing? p5.js is much easier for something like this, as you can eval() code. Some years ago I created https://github.com/hamoid/joukkue and we performed live, four people coding in their computers, the result combined and projected in one screen. The code is probably outdated, but I just wanted to show that it’s possible.

Ah I had forgotten, a friend created a Processing based environment with a similar goal. Find it here: https://github.com/transfluxus/CJam Maybe it can serve as inspiration.

3 Likes

Hi Hamoid,

Thanks for your input! I’ve looked up processing p5.js, interesting!
I’m looking into the reference right now and it seems very promising.
Do you have any idea how I could handle the upload system?

Edit:
As in, do you have any idea how to open a window to put a String into?
Or otherwise load files from the drive. I’m not very proficient with p5.js.

Thanks a lot!
Greetings.

Injecting Code into an already running program is generally very hard (i tried to get something similar to run a year ago… ) if you don‘t know how it works already.

A much simpler alternative could be to have those „creatures“ have variables for visuals, behaviour and events. This way you can add a creature with the visuals variables at runtime easily and have it behave in certain ways if certain events are true.

How that might look like :

class Creature {

   float[] visuals;

   float[] events; //Note that you could also have a String[] 
//and use the strings like invoke(events[i]), 
//which could call a method with the name events[i], 
//but i had quite some problems with this, 
//so i‘ll just go for a switch statement

   Creature () {

   }

   void setVisuals (float[] dataFromOthers) {
      visuals = dataFromOthers;
   }

   void setPosition (float x, float y) {
      visuals[0] = x; // index 0 of visuals could stand for x position
      visuals[1] = y;
   }

   void setColor (float r, float g, float b) {
      visuals[25] = r; //index 25 stands for the red value of the color of the creature
      visuals[26] = g;
      visuals[27] = b;
   }

//You can add as many things as you can imagine. (Instead of float you could also go for Object, or maybe a HashMap)

   void setEvents (float[] dataFromOthers) {
      events = dataFromOthers;
   }

   void setIsHungry (float whatToDo) {
      events[0] = whatToDo; //events index 0 stands for the creature being hungry.
// whatToDo is the number of the behaviour that should happen when it‘s hungry.
//whatToDo = 17 for example
   }

   void creatureIsHungry() {
      switch (events[0]) { //because 0 stands for being hungry
         case 0 : 
            getFood();
            break;
          case 17 : // this will be called, because events[0] = 17;
             runWild();
             break;
       }
   }
}

Edit : You should probably use invoke() and have the events as String[] if you have a lot of different behaviours and events, because that‘s gonna be a lot of Hard Coded stuff… and a ton of repetitions… or maybe even have a go with this :

Might be better than invoke() or method().

1 Like

What @Lexyth says is true: it’s much easier to configure a creature than to program its behavior, because anyone could configure one, even if it involves lots of sliders and buttons. But not everyone knows how to program. But ok, that will depend on who the participants are, maybe they do know how to program :slight_smile:

About how Joukkue or CJam does it, it’s not trivial. There needs to be a server software that is listening for data coming from client computers, which transmit the source code. If you are not quite experienced in either Java or JavaScript then maybe it’s too big of a challenge. Then you have to deal with incorrect code: you don’t want that one person’s mistake brings down the whole thing, so you need to catch those.
In Joukkue for example if anyone sends an infinite loop (like while(true) {}) then all the participants browsers freeze and need to be killed and restarted. Quite fun :slight_smile:

In more detail, how Joukkue does it is with something called websockets, which are permanent network connections that allow bidirectional data transmission in real time. I would listen to a key shortcut, and when people press CTRL+ENTER the code is sent to the server and integrated into the main program. Each participant would be responsible of writing one function, and that function draws something. Then, in the server, all user functions are drawn sequentially each time draw() gets called, so it’s like each person has a graphical layer in which to draw. If the last person calls background(0) then that is not a nice person :slight_smile: because it would erase all the layers that were drawn under it. So our rule was: no calling background or drawing something covering the whole screen.

2 Likes

I understand this feedback, it’s for a coding workshop kind of thing.

And i’m not sure im going to be setting up a server :thinking: because it seems like a lot of work.

I think im just going to output image files and upload those to the ‘Zoo’.
Or use the ‘slider and buttons’ example but in a more flexible way, i’ve got a lot to think about :wink:

Thanks everbody for your help, i’ll call this topic solved :slight_smile:

2 Likes

Yet another way to do this in PDE might be JavaScript-in-Java, with Nashorn. A basic Processing Java framework passes small JavaScript program-lets from clients as Strings – eg via OSC. The central host then evals them.

Be careful when you run code from other people too!

The creature I would write is a divide-by-zero bird! :wink:

3 Likes

Yes, definitely try / catch the eval.

Ideally, something like:

  • Client runs the JS locally to send.
  • If it runs, it sends
  • Server loops over list of code and runs each
  • If code fails it’s try, it is removed from the list

Of course, this doesn’t help you with while(true) et cetera – although you could manage that by killing a thread.

At a certain point this requires a small community of trusted users – or a strong sandbox – or lots of static analysis – or a purpose-built secure language/api – or all of the above. Congratulations, you have invented a mobile app store that users publish to in real time!

1 Like

This is very possible as long as your users implement an interface that you have defined.

Users implement a known method (meaning a method defined by the interface) then your code calls the known method.

How? Load their code (classes that implement the interface) during runtime with the Java Classloader, and create objects from loaded classes. Your code should then call the relevant method on the object (such as draw()) where whatever the user wrote (such as a creature that is shaped like a rectangle or a creature that is shaped like two ellipses) will run.

I’ve done something that had similar requirements: a project where Processing sketches are loaded during runtime and run concurrently in smaller windows (like an operating system).

2 Likes

Interesting. Do you have a simple example of using ClassLoader with Processing? I haven’t done it myself, but seem to recall – and see in this veryold thread – that the way Processing converts things to inner classes might make it tricky…

https://forum.processing.org/beta/num_1128955821.html

Copied the 3 code blocks relevant to that:

private final ArrayList<OSApplet> programs; // loaded programs from file
private final ArrayList<Application> apps; // program instances
private static final String appPath = "c:\\users\\mike\\eclipse-workspace\\PPZ-OS\\apps\\";

public OS() {
	apps = new ArrayList<>();
	programs = new ArrayList<>();
	LoadClass(appPath, "com.micycle.ppz.Perlin"); // .class file
	LoadClass(appPath, "com.micycle.ppz.Stardust"); // .java file
}

/**
 * Loads classes only -- doesn't instantiate as processing objs
 * @param path path for
 * @param name package name of class (e.g. com.micycle.ppz.Perlin)
 */
private void LoadClass(String path, String name) {
	File classFile = new File(path);
	try {
		URL url = classFile.toURI().toURL();
		URLClassLoader externalClassLoader = new URLClassLoader(new URL[]{url}, OS.class.getClassLoader());
		Class<?> loadedClass = externalClassLoader.loadClass(name);
		OSApplet program = (OSApplet) loadedClass.getDeclaredConstructors()[0].newInstance(this);
		programs.add(program);
		externalClassLoader.close();
	} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException
			| InvocationTargetException | SecurityException | IOException e) {
		System.err.println(e + "Error occurred when loading OSApplet " + name);
	}
}

/**
 * Creates application windows from loaded classes.
 */
private void newApp() {
	for (OSApplet program : programs) {
		Application app = new Application(this, program, "Title", new PVector(0, random(600))); // window at random location
		app.open();
		apps.add(app);
	}
}
1 Like