public void init() {
		if (el.winwidth==0) {
			// get width/height from applet dimensions
			el.winwidth=getWidth();
			el.winheight=getHeight();
		}
		initCanvas();
		if (!el.view_initialised) {
			exitEngine("Canvas settings not initialised, use setCanvasSettings().");
		}
		if (!i_am_applet) {
			jre.createWindow(this,jre.win_decoration);
		}
		//setAudioLatency(getAudioLatencyPlatformEstimate());

		canvas = new JGCanvas(el.winwidth,el.winheight);
		jre.canvas = canvas;
	
		el.initPF();

		jre.clearKeymap();
		canvas.addMouseListener(jre);
		canvas.addMouseMotionListener(jre);
		canvas.addFocusListener(jre);



		// set bg color so that the canvas's padding is in the proper color
		canvas.setBackground(getAWTColor(el.bg_color));
		if (jre.my_win!=null) jre.my_win.setBackground(getAWTColor(el.bg_color));
		// determine default font size (unscaled)
		el.msg_font = new JGFont("Helvetica",0,
			(int)(16.0/(640.0/(el.tilex * el.nrtilesx))));
		setLayout(new FlowLayout(FlowLayout.LEADING,0,0));
		add(canvas);
		if (!JGObject.setEngine(this)) {
			/** yes, you see that right.  I've used a random interface with a
			 * method that allows me to pass a Graphics.  We shall move this
			 * stuff to JGCanvas later, i suppose */
			canvas.setInitPainter(new ListCellRenderer () {
				public Component getListCellRendererComponent(JList d1,
				Object value, int d2, boolean initialise, boolean d4) {
					Graphics g = (Graphics) value;
					//if (initialise) {
					//	g.setColor(bg_color);
					//	g.fillRect(0,0,width,height);
					//}
					setFont(g,el.msg_font);
					setColor(g,el.fg_color);
					drawString(g,"JGame is already running in this VM",
						el.viewWidth()/2,el.viewHeight()/3,0,false);
					return null;
				} } );
			return;
		}
		el.is_inited=true;
		canvas.setInitPainter(new ListCellRenderer () {
			public Component getListCellRendererComponent(JList d1,
			Object value, int d2, boolean initialise, boolean d4) {
				Graphics g = (Graphics) value;
				//if (initialise) {
				//	g.setColor(bg_color);
				//	g.fillRect(0,0,width,height);
				//}
				setFont(g,el.msg_font);
				setColor(g,el.fg_color);
				JGImage splash = el.existsImage("splash_image") ?
						el.getImage("splash_image")  :  null;
				if (splash!=null) {
					JGPoint splash_size=getImageSize("splash_image");
					drawImage(g,viewWidth()/2-splash_size.x/2,
						viewHeight()/4-splash_size.y/2,"splash_image",
						false);
				}
				drawString(g,canvas.progress_message,
					viewWidth()/2,viewHeight()/2,0,false);
				//if (canvas.progress_message!=null) {
					//drawString(g,canvas.progress_message,
					//		viewWidth()/2,2*viewHeight()/3,0);
				//}
				// paint the right hand side black in case the bar decreases
				setColor(g,el.bg_color);
				drawRect(g,(int)(viewWidth()*(0.1+0.8*canvas.progress_bar)),
						(int)(viewHeight()*0.6),
						(int)(viewWidth()*0.8*(1.0-canvas.progress_bar)),
						(int)(viewHeight()*0.05), true,false, false);
				// left hand side of bar
				setColor(g,el.fg_color);
				drawRect(g,(int)(viewWidth()*0.1), (int)(viewHeight()*0.6),
						(int)(viewWidth()*0.8*canvas.progress_bar),
						(int)(viewHeight()*0.05), true,false, false);
				// length stripes
				drawRect(g,(int)(viewWidth()*0.1), (int)(viewHeight()*0.6),
						(int)(viewWidth()*0.8),
						(int)(viewHeight()*0.008), true,false, false);
				drawRect(g,(int)(viewWidth()*0.1),
						(int)(viewHeight()*(0.6+0.046)),
						(int)(viewWidth()*0.8),
						(int)(viewHeight()*0.008), true,false, false);
				drawString(g,canvas.author_message,
					viewWidth()-16,
					viewHeight()-getFontHeight(g,el.msg_font)-10,
					1,false);
				return null;
			} } );
		if (jre.my_win!=null) {
			jre.my_win.setVisible(true);
			jre.my_win.validate();
			// insets are known, resize window
			jre.setWindowSize(jre.win_decoration);
		}
		// initialise keyboard handling
		canvas.addKeyListener(jre);
		canvas.requestFocus();
		thread = new Thread(new JGEngineThread());
		thread.start();
	}