ThsApplet.java
作成: JBuilder
package matsubara.thssimulator;

import java.applet.Applet;
import java.awt.Label;
import java.awt.Checkbox;
import java.awt.Choice;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.Image;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.Dimension;
import java.awt.SystemColor;
import java.awt.Toolkit;
import java.awt.MediaTracker;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.BorderLayout;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.AWTEvent;
import java.awt.event.AWTEventListener;

//import java.awt.image.*;
//import java.awt.image.BufferedImage;
import java.awt.image.ImageProducer;

//import java.text.*;
import java.text.NumberFormat;
import java.text.FieldPosition;
import matsubara.gear.*;
import matsubara.graphics.ProgressLine;
import matsubara.carcontroller.*;
import java.beans.*;
import matsubara.uiext.*;
import matsubara.uiext.event.*;


/**
 * 

タイトル: THSシミュレータの動作と描画のスレッド

*

著作権: Copyright (c) 2002 matsubara masakazu

* @author m.matsubara * @version 1.2.0 */ class ThsDrawThread extends Thread { private ThsApplet m_applet; private volatile boolean m_bStopRequest = false; /** * THSシミュレータの動作と描画のスレッドの初期化 * @param applet 制御するTHSシミュレータ本体 */ ThsDrawThread(ThsApplet applet) { m_applet = applet; } /** * スレッド本体 */ public void run() { long nSleep; long nTime, nTime2, nTime3; nTime = System.currentTimeMillis(); nTime3 = System.currentTimeMillis(); Graphics graphics = m_applet.getGraphics(); while (m_bStopRequest == false) { try { long nInterval = nTime3 - nTime; nTime = nTime3; // m_applet.lbDebug.setText(String.valueOf(nInterval != 0 ? 1000 / nInterval : 0) + " fps"); m_applet.moveThs(nInterval); m_applet.drawThsObjects(m_applet.getGraphics()); nTime2 = System.currentTimeMillis(); nSleep = 50 - (nTime2 - nTime); if (nSleep < 10) nSleep = 10; sleep(nSleep); } catch (Exception e) { } nTime3 = System.currentTimeMillis(); } } /** * スレッドの停止要求を発行 */ public void stopRequest() { m_bStopRequest = true; } } /** *

タイトル: THSシミュレータ

*

説明: プリウスのハイブリッドシステム(THS)の心臓部、遊星歯車機構のシミュレーション

*

著作権: Copyright (c) 2001

* @author m.matsubara * @version 1.0.0 */ public class ThsApplet extends Applet { /** アプリケーション名 */ public final String mc_sApplicationName = "Prius driving simulator"; /** バージョン表示 */ public final String mc_sVersion = "version 1.3.0"; /** 著作権表示 */ public final String mc_sCopyright = "copyright(c) 2002 matsubara masakazu"; ThsDrawThread m_threadDraw; ThsController m_thsController = null; // BufferedImage m_imgPGear = new BufferedImage(160, 160, BufferedImage.TYPE_INT_RGB); // プラネタリギア描画用バッファ Image m_imgPGear = null; Image[] m_imgPrius = new Image[2]; // 走行中のプリウスの画像2枚(2枚を交代に表示させて走っている感じを出す) Image[] m_imgKame = new Image[2]; // 走行中(?)のカメの画像2枚(2枚を交代に表示させて走っている感じを出す) int m_nImgPriusNo = 0; // 表示中のプリウスの番号(インデックス) Image m_imgMotor; // モーター動作を表すアイコン(オレンジの電球) Image m_imgKaisei; // 回生発電を表すアイコン(緑の電球) Image m_imgGasoline; // エンジンの動作を表すアイコン(ガソリンスタンド) Image m_imgMeter; // メーター Image m_imgMeterKame; // メーター表示用カメ(出力制限警告灯) Image m_imgEnergyMonitor; // エネルギーモニタの図 Image m_imgPriusBrake; // プリウスのブレーキランプ // メーターの位置 final int m_nMeterBaseX = 200; final int m_nMeterBaseY = 55; // エネルギーモニタの位置 final int m_nEmOffsetX = 447; final int m_nEmOffsetY = 0; // エネルギーモニタでエネルギーの流れを表す線、2文字ずつついている大文字の意味は以下のとおり // B : バッテリー, I : インバーター, M : モーター, F : ファイナルギア // G : 発電機, P : プラネタリギア, E : エンジン, T : タイヤ ProgressLine m_lineBI = new ProgressLine(m_nEmOffsetX + 121, m_nEmOffsetY + 38, m_nEmOffsetX + 112, m_nEmOffsetY + 64, Color.red, 6); ProgressLine m_lineIM = new ProgressLine(m_nEmOffsetX + 112, m_nEmOffsetY + 64, m_nEmOffsetX + 102, m_nEmOffsetY + 94, Color.red, 6); ProgressLine m_lineMF = new ProgressLine(m_nEmOffsetX + 102, m_nEmOffsetY + 94, m_nEmOffsetX + 83, m_nEmOffsetY + 88, Color.red, 6); ProgressLine m_lineIG = new ProgressLine(m_nEmOffsetX + 112, m_nEmOffsetY + 64, m_nEmOffsetX + 85, m_nEmOffsetY + 57, Color.red, 6); ProgressLine m_lineGP = new ProgressLine(m_nEmOffsetX + 85, m_nEmOffsetY + 57, m_nEmOffsetX + 72, m_nEmOffsetY + 84, Color.red, 6); ProgressLine m_lineEP = new ProgressLine(m_nEmOffsetX + 50, m_nEmOffsetY + 77, m_nEmOffsetX + 72, m_nEmOffsetY + 84, Color.red, 6); ProgressLine m_linePF = new ProgressLine(m_nEmOffsetX + 72, m_nEmOffsetY + 84, m_nEmOffsetX + 83, m_nEmOffsetY + 88, Color.red, 6); ProgressLine m_lineFT = new ProgressLine(m_nEmOffsetX + 83, m_nEmOffsetY + 88, m_nEmOffsetX + 70, m_nEmOffsetY + 116, Color.red, 6); // 道路描画用のバッファ、この上にプリウスやメーター、エネルギーモニタなどが表示される。 Image m_imgRoad = null; double m_rRoadPosition = 0; // 道路の白線を描画するためのインデックス、プリウスが進むと増える。 // アプレット最下段に表示されるメッセージ String m_sMessage1 = ""; String m_sMessage2 = ""; boolean isStandalone = false; Label label1 = new Label(); Label label2 = new Label(); Label lbRingGearSpeed = new Label(); Label label4 = new Label(); Label lbPlaCarrierSpeed = new Label(); Label label6 = new Label(); Label lbSunGearSpeed = new Label(); Choice cmbRange = new Choice(); Panel panel1 = new Panel(); Checkbox ckDriveMode = new Checkbox(); Label label8 = new Label(); Label label9 = new Label(); Slider sliRingGear = new Slider(); Slider sliPlaCarrier = new Slider(); Slider sliSunGear = new Slider(); Slider sliBrake = new Slider(); Slider sliAccel = new Slider(); Label lbDebug = new Label(); //引数値の取得 public String getParameter(String key, String def) { return isStandalone ? System.getProperty(key, def) : (getParameter(key) != null ? getParameter(key) : def); } //アプレットの構築 public ThsApplet() { try { m_thsController = new ThsController(80, 80, 60); } catch (Exception e) { e.printStackTrace(); } } //アプレットの初期化 public void init() { try { jbInit(); } catch(Exception e) { e.printStackTrace(); } } //コンポーネントの初期化 private void jbInit() throws Exception { label1.setAlignment(1); label1.setFont(new java.awt.Font("Dialog", 0, 12)); label1.setForeground(new Color(255, 128, 0)); label1.setText("動力分割機構(遊星歯車)"); label1.setBounds(new Rectangle(20, 7, 160, 17)); this.setBackground(Color.white); this.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() { public void mouseMoved(MouseEvent e) { this_mouseMoved(e); } }); this.setLayout(null); label2.setAlignment(1); label2.setFont(new java.awt.Font("Dialog", 0, 12)); label2.setForeground(new Color(0, 186, 0)); label2.setText("モーター"); label2.setBounds(new Rectangle(202, 6, 56, 17)); lbRingGearSpeed.setAlignment(2); lbRingGearSpeed.setForeground(new Color(0, 186, 0)); lbRingGearSpeed.setText("0 rpm"); lbRingGearSpeed.setBounds(new Rectangle(197, 21, 67, 17)); label4.setAlignment(1); label4.setFont(new java.awt.Font("Dialog", 0, 12)); label4.setForeground(Color.red); label4.setText("エンジン"); label4.setBounds(new Rectangle(270, 6, 59, 17)); lbPlaCarrierSpeed.setAlignment(2); lbPlaCarrierSpeed.setForeground(Color.red); lbPlaCarrierSpeed.setText("0 rpm"); lbPlaCarrierSpeed.setBounds(new Rectangle(266, 21, 67, 17)); label6.setAlignment(1); label6.setFont(new java.awt.Font("Dialog", 0, 12)); label6.setForeground(Color.blue); label6.setText("発電機"); label6.setBounds(new Rectangle(371, 6, 63, 17)); lbSunGearSpeed.setAlignment(2); lbSunGearSpeed.setForeground(Color.blue); lbSunGearSpeed.setText("0 rpm"); lbSunGearSpeed.setBounds(new Rectangle(369, 21, 67, 17)); cmbRange.setBackground(new Color(204, 204, 205)); cmbRange.setBounds(new Rectangle(10, 27, 104, 24)); cmbRange.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(ItemEvent e) { cmbRange_itemStateChanged(e); } }); panel1.setBackground(new Color(204, 204, 205)); panel1.setBounds(new Rectangle(464, 10, 124, 177)); panel1.setLayout(null); ckDriveMode.setBackground(new Color(204, 204, 205)); ckDriveMode.setFont(new java.awt.Font("Dialog", 0, 12)); ckDriveMode.setLabel("運転する"); ckDriveMode.setBounds(new Rectangle(19, 1, 88, 25)); ckDriveMode.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(ItemEvent e) { ckDriveMode_itemStateChanged(e); } }); label8.setFont(new java.awt.Font("Dialog", 0, 12)); label8.setText("ブレーキ"); label8.setBounds(new Rectangle(7, 156, 51, 17)); label9.setFont(new java.awt.Font("Dialog", 0, 12)); label9.setText("アクセル"); label9.setBounds(new Rectangle(68, 156, 52, 17)); sliRingGear.setBounds(new Rectangle(209, 43, 76, 136)); sliRingGear.setMaximum(6000); sliRingGear.setMinimum(-2000); sliRingGear.setMajorTickSpacing(2000); sliRingGear.setMinorTickSpacing(1000); sliRingGear.setPrintLabel(true); sliRingGear.addChangeListener(new matsubara.uiext.event.ChangeListener() { public void stateChanged(ChangeEvent e) { sliRingGear_stateChanged(e); } }); sliRingGear.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() { public void mouseMoved(MouseEvent e) { sliRingGear_mouseMoved(e); } }); sliPlaCarrier.setPrintLabel(true); sliPlaCarrier.addChangeListener(new matsubara.uiext.event.ChangeListener() { public void stateChanged(ChangeEvent e) { sliPlaCarrier_stateChanged(e); } }); sliPlaCarrier.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() { public void mouseMoved(MouseEvent e) { sliPlaCarrier_mouseMoved(e); } }); sliPlaCarrier.setMajorTickSpacing(2000); sliPlaCarrier.setMaximum(4000); sliPlaCarrier.setBounds(new Rectangle(279, 72, 76, 79)); sliPlaCarrier.setMinorTickSpacing(1000); sliSunGear.setPrintLabel(true); sliSunGear.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() { public void mouseMoved(MouseEvent e) { sliSunGear_mouseMoved(e); } }); sliSunGear.setMajorTickSpacing(2000); sliSunGear.setMinimum(-4000); sliSunGear.setMaximum(6000); sliSunGear.setEnabled(false); sliSunGear.setBounds(new Rectangle(384, 40, 76, 172)); sliSunGear.setMinorTickSpacing(1000); sliBrake.setBounds(new Rectangle(21, 55, 37, 96)); sliBrake.addChangeListener(new matsubara.uiext.event.ChangeListener() { public void stateChanged(ChangeEvent e) { sliBrake_stateChanged(e); } }); sliAccel.setBounds(new Rectangle(79, 55, 37, 96)); sliAccel.addChangeListener(new matsubara.uiext.event.ChangeListener() { public void stateChanged(ChangeEvent e) { sliAccel_stateChanged(e); } }); lbDebug.setBounds(new Rectangle(7, 186, 369, 21)); this.add(label2, null); this.add(lbRingGearSpeed, null); this.add(label6, null); this.add(lbSunGearSpeed, null); panel1.add(label8, null); panel1.add(label9, null); panel1.add(ckDriveMode, null); panel1.add(cmbRange, null); panel1.add(sliAccel, null); panel1.add(sliBrake, null); this.add(sliRingGear, null); this.add(lbPlaCarrierSpeed, null); this.add(label4, null); this.add(panel1, null); this.add(sliSunGear, null); this.add(sliPlaCarrier, null); this.add(lbDebug, null); this.add(label1, null); } //アプレットの開始 public void start() { System.out.println("Welcome to Prius"); System.out.println("Prius driving simulator - ignition !!"); m_imgPGear = createImage(160, 160); m_imgRoad = createImage(600, 180); m_imgPrius[0] = loadImage("/matsubara/thssimulator/image/prius1.gif"); m_imgPrius[1] = loadImage("/matsubara/thssimulator/image/prius2.gif"); m_imgKame[0] = loadImage("/matsubara/thssimulator/image/kame1.gif"); m_imgKame[1] = loadImage("/matsubara/thssimulator/image/kame2.gif"); m_imgMotor = loadImage("/matsubara/thssimulator/image/motor.gif"); m_imgKaisei = loadImage("/matsubara/thssimulator/image/kaisei.gif"); m_imgGasoline = loadImage("/matsubara/thssimulator/image/gasoline.gif"); m_imgMeter = loadImage("/matsubara/thssimulator/image/meter.gif"); m_imgMeterKame = loadImage("/matsubara/thssimulator/image/meterKame.gif"); m_imgEnergyMonitor = loadImage("/matsubara/thssimulator/image/energyMonitor.gif"); m_imgPriusBrake = loadImage("/matsubara/thssimulator/image/priusBrake.gif"); cmbRange.addItem("P Range"); cmbRange.addItem("R Range"); cmbRange.addItem("N Range"); cmbRange.addItem("D Range"); cmbRange.addItem("B Range"); cmbRange.select(0); m_thsController.setShiftPosition("P"); m_threadDraw = new ThsDrawThread(this); m_threadDraw.start(); } //アプレットの停止 public void stop() { m_threadDraw.stopRequest(); try { Thread.sleep(100); // 描画系スレッドの停止を待つ } catch (Exception e) { } System.out.println(mc_sApplicationName + " " + mc_sVersion + " " + mc_sCopyright); System.out.println("good bye :-)"); } //アプレットの破棄 public void destroy() { } //アプレットの情報取得 public String getAppletInfo() { return mc_sApplicationName + " " + mc_sVersion + " " + mc_sCopyright; } //引数情報の取得 /* public String[][] getParameterInfo() { return null; } */ //Main メソッド public static void main(String[] args) { ThsApplet applet = new ThsApplet(); applet.isStandalone = true; Frame frame; frame = new Frame() { protected void processWindowEvent(WindowEvent e) { super.processWindowEvent(e); if (e.getID() == WindowEvent.WINDOW_CLOSING) { System.exit(0); } } public synchronized void setTitle(String title) { super.setTitle(title); enableEvents(AWTEvent.WINDOW_EVENT_MASK); } }; frame.setTitle(applet.mc_sApplicationName); frame.add(applet, BorderLayout.CENTER); applet.init(); applet.start(); frame.setSize(610,400); Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); frame.setLocation((d.width - frame.getSize().width) / 2, (d.height - frame.getSize().height) / 2); frame.setVisible(true); } public Image createImage(int nWidth, int nHeight) { // if (isStandalone) // return new java.awt.image.BufferedImage(nX, nY, java.awt.image.BufferedImage.TYPE_INT_RGB); // else Image img = super.createImage(nWidth, nHeight); if (img == null) { try { Class clsBi = Class.forName("java.awt.image.BufferedImage"); java.lang.reflect.Constructor clsBiConstruct = clsBi.getConstructor(new Class[] {int.class, int.class, int.class}); img = (Image)clsBiConstruct.newInstance(new Object[] { new Integer(nWidth), new Integer(nHeight), new Integer(clsBi.getField("TYPE_INT_RGB").getInt(null)) }); } catch (Exception e2) { e2.printStackTrace(); } } return img; } /** * このクラスのリソースから画像をロードする * @param sImage リソースファイルのURL * @return ロードした Image オブジェクト */ Image loadImage(final String sImage) { Class myClass = this.getClass(); Image img; try { //throw new Exception("Image error"); img = createImage((ImageProducer)myClass.getResource(sImage).getContent()); } catch (Exception e) { System.out.println("image file load error : " + e.getMessage()); img = createImage(100, 20); // ファイルの読み込み失敗に備えて Graphics g = img.getGraphics(); g.setColor(Color.white); g.fillRect(0, 0, 100, 20); g.setColor(Color.red); g.drawString("image load error.", 5, 15); // return img; } /* try { MediaTracker mt = new MediaTracker(this); mt.addImage(img, 0); mt.checkAll(true); mt.waitForAll(1000); } catch (Exception e) { e.printStackTrace(); } */ return img; } /** * アプレットの描画 * @param g 描画する Graphics オブジェクト */ public void paint(Graphics g) { super.paint(g); try { drawThsObjects(g); } catch (Exception e) { } } /** * 現在のプリウスの速度 * @return プリウスの速度(km/h) */ public double getSpeed() { return m_thsController.getSpeed(); } /** * ギアやさまざまなオブジェクトの描画 * @param g 描画する Graphics オブジェクト */ /* synchronized */ public void drawThsObjects(Graphics g) { PlanetaryGear planetaryGear = m_thsController.getPlanetaryGear(); double rSpeed = getSpeed(); // プラネタリーギアの色設定 if (m_thsController.isGasoline()) { planetaryGear.getPlanetaryCarrier().setColor1(Color.white); planetaryGear.getPlanetaryCarrier().setColor2(Color.red); } else { planetaryGear.getPlanetaryCarrier().setColor1(new Color(224, 224, 224)); planetaryGear.getPlanetaryCarrier().setColor2(new Color(224, 0, 0)); } if (planetaryGear.getSunGearSpeed() > 0) { planetaryGear.getSunGear().setColor1(Color.white); planetaryGear.getSunGear().setColor2(Color.blue); } else { planetaryGear.getSunGear().setColor1(new Color(224, 224, 224)); planetaryGear.getSunGear().setColor2(new Color( 0, 0, 210)); } // プラネタリーギア描画 Graphics gi = m_imgPGear.getGraphics(); gi.setColor(Color.white); gi.fillRect(0, 0, m_imgPGear.getWidth(null), m_imgPGear.getHeight(null)); planetaryGear.draw(gi); // 道路 gi = m_imgRoad.getGraphics(); gi.setColor(new Color(160, 160, 160)); gi.fillRect(0, 0, 445, 100); gi.setColor(Color.white); gi.fillRect(445, 0, 600 - 445, 100); gi.setColor(Color.white); gi.fillRect(0, 100, 600, 120); for (int nIdx = 0 - 65 - (int)m_rRoadPosition; nIdx < 600 + 100 + (int)m_rRoadPosition; nIdx += 100) gi.fillRect(nIdx, 48, 65, 4); // プリウス if (m_thsController.isPowerSaveMode() == false || ckDriveMode.getState() == false) { gi.drawImage(m_imgPrius[m_nImgPriusNo], 60 + (int)(getSpeed() / 4), 1, null); // プリウス if (sliBrake.getValue() >= 3) gi.drawImage(m_imgPriusBrake, 60 + (int)(getSpeed() / 4), 1, null); // ブレーキランプ if (m_thsController.getShiftPosition().equals("R") || (ckDriveMode.getState() == false && rSpeed < 0)) { // バックランプ gi.setColor(Color.white); gi.fillRect(60 + (int)(getSpeed() / 4) + 2, 23, 1, 1); } } else gi.drawImage(m_imgKame[m_nImgPriusNo], 60 + (int)(getSpeed() / 4), 1, null); // カメ // メーター drawMeter(gi); // エネルギーモニタ drawEnergyMonitor(gi); if (ckDriveMode.getState()) { // 燃費表示(グラフ) java.text.DecimalFormat format = new java.text.DecimalFormat("0.0"); double rFuelEfficiency = m_thsController.getFuelEfficiency(); String sFuelEfficiency = "瞬間燃費 : " + format.format(rFuelEfficiency) + " km/L";; gi.setFont(new Font("dialog", Font.PLAIN, 12)); gi.setColor(new Color(114, 114, 153)); gi.fillRoundRect(310, 2, (int)(130 * Math.min(rFuelEfficiency, 40) / 40), 18, 3, 3); gi.setColor(Color.white); gi.drawRoundRect(310, 2, 130, 18, 2, 2); gi.drawString(sFuelEfficiency, 315, 16); if (m_thsController.getFuel() != 50) rFuelEfficiency = Math.abs(m_thsController.getTripMeter()) / (50 - m_thsController.getFuel()); else if (m_thsController.getTripMeter() == 0) rFuelEfficiency = 0; else rFuelEfficiency = Double.POSITIVE_INFINITY; sFuelEfficiency = "累計燃費 : " + format.format(rFuelEfficiency) + " km/L"; gi.setColor(new Color(114, 114, 153)); gi.fillRoundRect(310, 22, (int)(130 * Math.min(rFuelEfficiency, 40) / 40), 18, 3, 3); gi.setColor(Color.white); gi.drawRoundRect(310, 22, 130, 18, 2, 2); gi.drawString(sFuelEfficiency, 315, 36); } gi.setFont(new Font("Dialog", Font.PLAIN, 10)); gi.setColor(Color.black); gi.drawString(m_sMessage1, 5, 115); gi.drawString(m_sMessage2, 5, 135); // 実際の描画 g.drawImage(m_imgPGear, 20, 20, null); g.drawImage(m_imgRoad, 0, 215, null); } /** * メーターを描く * @param g 描画する Graphics オブジェクト */ public void drawMeter(Graphics g) { double rSpeed = getSpeed(); // メーター本体 g.drawImage(m_imgMeter, m_nMeterBaseX, m_nMeterBaseY, null); // レンジ表示 int nRange; if (ckDriveMode.getState()) nRange = cmbRange.getSelectedIndex(); else { if (rSpeed > 0) nRange = 3; // D Range else if (rSpeed < 0) nRange = 1; // R Range else nRange = 0; // P Range } if (nRange == 1) g.setColor(new Color(255, 100, 0)); // 赤 else g.setColor(new Color(64, 255, 255)); // 薄い緑 g.drawRoundRect(200 + 46 + 13 * nRange, 55 + 11, 10, 12, 2, 2); // スピード表示 java.text.DecimalFormat format = new java.text.DecimalFormat("0.0"); String sSpeed = String.valueOf((int)Math.abs(rSpeed)); //DialogInput、Monospaced、Serif、SansSerif g.setFont(new Font("Monospaced", Font.PLAIN, 26)); g.setColor(new Color(64, 255, 255)); g.drawString(sSpeed, m_nMeterBaseX + 153 - g.getFontMetrics().stringWidth(sSpeed), m_nMeterBaseY + 35); // トリップメーター StringBuffer sTrip = format.format(m_thsController.getTripMeter(), new StringBuffer(10), new FieldPosition(4)); //DialogInput、Monospaced、Serif、SansSerif g.setFont(new Font("Dialog", Font.PLAIN, 9)); g.setColor(new Color(64, 255, 255)); sTrip.append("km"); int nWidth = g.getFontMetrics().stringWidth(sTrip.toString()); g.drawString(sTrip.toString(), m_nMeterBaseX + 110 - nWidth, m_nMeterBaseY + 35); // 燃料残量(消費した分のメーターを黒で塗りつぶす)&燃料警告灯(燃料の残量が7Lを切ると点灯) int nNenryo = (int)((50 - m_thsController.getFuel()) / ((50 - 7) / 9.0)); if (nNenryo != 0) { if (nNenryo > 10) nNenryo = 10; g.setColor(Color.black); g.fillRect(m_nMeterBaseX + 28, m_nMeterBaseY + 6, 7, nNenryo * 3); if (nNenryo >= 9) { // 燃料警告灯 g.setColor(new Color(255, 100, 0)); g.fillRect(m_nMeterBaseX + 35, m_nMeterBaseY + 33, 4, 3); } } // 出力制限警告灯(いわゆるカメ) if (m_thsController.isPowerSaveMode() && ckDriveMode.getState() != false) g.drawImage(m_imgMeterKame, m_nMeterBaseX + 8, m_nMeterBaseY + 5, null); } /** * エネルギーモニタを描く * @param g 描画する Graphics オブジェクト */ public void drawEnergyMonitor(Graphics g) { g.drawImage(m_imgEnergyMonitor, m_nEmOffsetX, m_nEmOffsetY, null); // drawAxis(g, m_nEmOffsetX + 125, m_nEmOffsetY + 113, m_thsController.getRingGear().getAngle(), new Color(0, 0xbb, 0)); drawAxis(g, m_nEmOffsetX + 125, m_nEmOffsetY + 113, m_thsController.getRingGear().getAngle(), m_thsController.getRingGear().getColor2(), 7); drawAxis(g, m_nEmOffsetX + 40, m_nEmOffsetY + 80, m_thsController.getPlanetaryCarrier().getAngle(), m_thsController.getPlanetaryCarrier().getColor2(), 7); drawAxis(g, m_nEmOffsetX + 70, m_nEmOffsetY + 62, m_thsController.getSunGear().getAngle(), m_thsController.getSunGear().getColor2(), 7); // drawAxis(g, m_nEmOffsetX + 72, m_nEmOffsetY + 84, m_thsController.getRingGear().getAngle(), m_thsController.getRingGear().getColor2(), 7); // drawAxis(g, m_nEmOffsetX + 72, m_nEmOffsetY + 84, m_thsController.getPlanetaryCarrier().getAngle(), m_thsController.getPlanetaryCarrier().getColor2(), 5); // drawAxis(g, m_nEmOffsetX + 72, m_nEmOffsetY + 84, m_thsController.getSunGear().getAngle(), m_thsController.getSunGear().getColor2(), 3); if (ckDriveMode.getState()) { // インジケーター if (m_thsController.isMotor()) g.drawImage(m_imgMotor, 500 - 450, 55, null); if (m_thsController.isKaisei()) g.drawImage(m_imgKaisei, 500 - 450, 55, null); if (m_thsController.isGasoline()) g.drawImage(m_imgGasoline, 540 - 450, 55, null); // エンジンの start と stop double rEnginRpm = m_thsController.getEngineRpm(); if (rEnginRpm > 0 && rEnginRpm < 950 && m_thsController.getAcceleration() != 0) { g.setFont(new Font("Dialog", Font.BOLD, 11)); String sEngineMsg; if (m_thsController.getAcceleration() >= 0) sEngineMsg = "start"; else sEngineMsg = "stop"; FontMetrics fm = g.getFontMetrics(); g.setColor(new Color(0xAA, 0x44, 0)); g.fillRect(m_nEmOffsetX + 28, m_nEmOffsetY + 73, fm.stringWidth(sEngineMsg) + 4, fm.getHeight()); g.setColor(new Color(0xFF, 0x66, 0)); g.drawRect(m_nEmOffsetX + 28, m_nEmOffsetY + 73, fm.stringWidth(sEngineMsg) + 4, fm.getHeight()); g.drawString(sEngineMsg, m_nEmOffsetX + 30, m_nEmOffsetY + 73 + fm.getAscent()); } // エネルギーモニタ m_lineBI.setReverse(false); m_lineIM.setReverse(false); m_lineMF.setReverse(false); m_lineIG.setReverse(false); m_lineGP.setReverse(false); m_lineEP.setReverse(false); m_linePF.setReverse(false); m_lineFT.setReverse(false); m_lineBI.setColor(Color.red); m_lineIM.setColor(Color.red); m_lineMF.setColor(Color.red); m_lineFT.setColor(Color.red); switch (m_thsController.getThsMode()) { case ThsController.thsStop: break; case ThsController.thsStopAndEngine: m_lineGP.setReverse(true); m_lineIG.setReverse(true); m_lineBI.setReverse(true); m_lineBI.setColor(Color.green); m_lineEP.draw(g); m_lineGP.draw(g); m_lineIG.draw(g); m_lineBI.draw(g); break; case ThsController.thsStart: m_lineBI.draw(g); m_lineIM.draw(g); m_lineMF.draw(g); m_lineFT.draw(g); break; case ThsController.thsNormal: m_lineGP.setReverse(true); m_lineIG.setReverse(true); m_lineBI.setReverse(true); m_lineEP.draw(g); m_linePF.draw(g); m_lineFT.draw(g); m_lineGP.draw(g); m_lineIG.draw(g); m_lineBI.draw(g); break; case ThsController.thsNormalOD: m_lineIM.setReverse(true); m_lineMF.setReverse(true); m_lineBI.setReverse(true); m_lineBI.setColor(Color.green); m_lineEP.draw(g); m_linePF.draw(g); m_lineFT.draw(g); m_lineGP.draw(g); m_lineIG.draw(g); m_lineBI.draw(g); m_lineIM.draw(g); m_lineMF.draw(g); break; case ThsController.thsFullAccel: m_lineGP.setReverse(true); m_lineIG.setReverse(true); m_lineBI.draw(g); m_lineIM.draw(g); m_lineMF.draw(g); m_lineIG.draw(g); m_lineGP.draw(g); m_lineEP.draw(g); m_linePF.draw(g); m_lineFT.draw(g); break; case ThsController.thsFullAccelOD: m_lineBI.draw(g); m_lineIM.draw(g); m_lineMF.draw(g); m_lineIG.draw(g); m_lineGP.draw(g); m_lineEP.draw(g); m_linePF.draw(g); m_lineFT.draw(g); break; case ThsController.thsKaiseiAndEngine: m_lineIG.setReverse(true); m_lineGP.setReverse(true); m_lineEP.setReverse(true); m_linePF.setReverse(true); m_lineIG.draw(g); m_lineGP.draw(g); m_lineEP.draw(g); m_linePF.draw(g); case ThsController.thsKaisei: m_lineBI.setReverse(true); m_lineIM.setReverse(true); m_lineMF.setReverse(true); m_lineFT.setReverse(true); m_lineBI.setColor(Color.green); m_lineIM.setColor(Color.green); m_lineMF.setColor(Color.green); m_lineFT.setColor(Color.green); m_lineBI.draw(g); m_lineIM.draw(g); m_lineMF.draw(g); m_lineFT.draw(g); break; case ThsController.thsBackAndEngine: m_lineBI.setReverse(true); m_linePF.setReverse(true); m_lineIG.setReverse(true); m_lineGP.setReverse(true); m_lineBI.setColor(Color.green); m_lineBI.draw(g); m_lineIM.draw(g); m_lineMF.draw(g); m_lineIG.draw(g); m_lineGP.draw(g); m_lineEP.draw(g); m_linePF.draw(g); m_lineFT.draw(g); break; } // バッテリー表示 java.text.DecimalFormat format = new java.text.DecimalFormat("0.0"); double rBatterySOC = m_thsController.getBatterySOC(); String sBatterySOC = "batt " + format.format(rBatterySOC) + "%"; int nBarWidth = (int)(rBatterySOC / 100 * 40); if (m_thsController.isPowerSaveMode()) g.setColor(Color.red); else if (m_thsController.getBatterySOC() < 45) g.setColor(Color.yellow); else g.setColor(Color.green); g.fillRect(455, 10, nBarWidth, 10); g.setColor(Color.white); g.drawRect(455, 10, 40, 10); g.drawRect(495, 13, 2, 4); g.setFont(new Font("Dialog", Font.PLAIN, 9)); g.drawString(sBatterySOC, 455, 33); } } /** * 各オブジェクトをその状態に応じて動かす * @param nMilliSec 経過秒数 */ /* synchronized */ void moveThs(long nMilliSec) { // lbDebug.setText("" + m_thsController.getBatterySOC()); PlanetaryGear planetaryGear = m_thsController.getPlanetaryGear(); // 動かす double rSpeed = getSpeed(); if (ckDriveMode.getState()) { m_thsController.drive(nMilliSec, sliAccel.getValue(), sliBrake.getValue()); sliRingGear.setValue((int)planetaryGear.getRingGearSpeed()); sliPlaCarrier.setValue((int)planetaryGear.getPlaCarrierSpeed()); } else planetaryGear.move((double)nMilliSec / 100); m_rRoadPosition += rSpeed / 4; m_rRoadPosition %= 100; if ((int)rSpeed != 0) { // プリウスがわずかでも動いているときは画像を切り替える m_nImgPriusNo++; m_nImgPriusNo %= 2; } if (ckDriveMode.getState()) { // エネルギーモニタの線を動かす int nMove = (int)(nMilliSec / 10); m_lineBI.movePosition(nMove); m_lineIM.movePosition(nMove); m_lineMF.movePosition(nMove); m_lineIG.movePosition(nMove); m_lineGP.movePosition(nMove); m_lineEP.movePosition(nMove); m_linePF.movePosition(nMove); m_lineFT.movePosition(nMove); } // 説明表示 if (ckDriveMode.getState()) { if (m_thsController.getFuel() <= 0) { m_sMessage1 = "ガソリンが無くなりました。"; m_sMessage2 = "これ以上走ることが出来ません。"; } else { switch (m_thsController.getThsMode()) { case ThsController.thsStop: m_sMessage1 = "エネルギーの流れはありません。"; m_sMessage2 = ""; break; case ThsController.thsStopAndEngine: m_sMessage1 = "バッテリーの残量が少ないため、停止中も発電を行います。"; m_sMessage2 = ""; break; case ThsController.thsStart: m_sMessage1 = "モーターの力で走っています。エンジンは停止し、発電機は空転します。"; m_sMessage2 = "坂道発進でバックしないようにクリープ現象もこれで再現されます。"; break; case ThsController.thsNormal: m_sMessage1 = "エンジンの回転は動力分割機構で2つの出力に分割されます。"; m_sMessage2 = "片方の出力はタイヤを直接回しもう片方は発電機を回します。"; break; case ThsController.thsNormalOD: m_sMessage1 = "発電機をモーターとして使いエンジンの回転にプラスしてタイヤを回します。"; m_sMessage2 = "モーターは逆に発電を行い、余った電力をバッテリーに充電します。"; break; case ThsController.thsFullAccel: m_sMessage1 = "エンジン+モーターでフル加速を行います。"; m_sMessage2 = "エンジン回転の一部は発電機によって電力に変換されモーターを回します。"; break; case ThsController.thsFullAccelOD: m_sMessage1 = "エンジン+モーターでフル加速を行います。"; m_sMessage2 = "発電機はモーターとしてエンジン回転を補助します。"; break; case ThsController.thsKaiseiAndEngine: m_sMessage1 = "クルマの運動エネルギーをモーターを使って電力に変換して減速します。"; m_sMessage2 = "エンジンは運動エネルギーの一部で回り続けます。"; break; case ThsController.thsKaisei: m_sMessage1 = "クルマの運動エネルギーをモーターを使って電力に変換して減速します。"; m_sMessage2 = "エンジンは停止し、発電機は空転します。"; break; case ThsController.thsBackAndEngine: m_sMessage1 = "エンジンで発電するとともにモーターでバックします。"; m_sMessage2 = ""; break; } } } } /** * エンジン、モーター、発電機の軸を表すマークを書く。 * @param g グラフィック * @param nX X座標 * @param nY Y座標 * @param rAngle 角度 * @param color 色 * @param nSize 半径(ドット) */ void drawAxis(Graphics g, int nX, int nY, double rAngle, Color color, int nSize) { /* g.setColor(color); g.drawArc(nX - 7, nY - 7, 14, 14, 0, 360); g.fillArc(nX - 7, nY - 7, 14, 14, 360 - (int)(rAngle / (2 * Math.PI) * 360), 90); g.fillArc(nX - 7, nY - 7, 14, 14, 360 - (int)(rAngle / (2 * Math.PI) * 360 + 180), 90); */ g.setColor(Color.white); g.fillArc(nX - nSize, nY - nSize, nSize * 2, nSize * 2, 360 - (int)(rAngle / (2 * Math.PI) * 360) + 180, 360); g.setColor(color); g.fillArc(nX - nSize, nY - nSize, nSize * 2, nSize * 2, 360 - (int)(rAngle / (2 * Math.PI) * 360), 180); } /** フォームのラベルにギアの速度をセットする */ public void viewGearsSpeed() { PlanetaryGear planetaryGear = m_thsController.getPlanetaryGear(); int nRingGearSpeed = (int)planetaryGear.getRingGearSpeed(); int nPlanetaryCarrierSpeed = (int)planetaryGear.getPlaCarrierSpeed(); int nSunGearSpeed = (int)planetaryGear.getSunGearSpeed(); nRingGearSpeed -= nRingGearSpeed % 50; if (nPlanetaryCarrierSpeed >= 1000) nPlanetaryCarrierSpeed -= nPlanetaryCarrierSpeed % 50; else nPlanetaryCarrierSpeed -= nPlanetaryCarrierSpeed % 10; nSunGearSpeed -= nSunGearSpeed % 10; lbRingGearSpeed.setText(String.valueOf(nRingGearSpeed) + " rpm"); lbPlaCarrierSpeed.setText(String.valueOf(nPlanetaryCarrierSpeed) + " rpm"); lbSunGearSpeed.setText(String.valueOf(nSunGearSpeed) + " rpm"); } void sliRingGear_mouseMoved(MouseEvent e) { if (ckDriveMode.getState() == false) { m_sMessage1 = "モーターはリングギア(緑/白)とつながっています。"; m_sMessage2 = "リングギアの回転はタイヤの回転(クルマのスピード)と比例します。"; } } void sliPlaCarrier_mouseMoved(MouseEvent e) { if (ckDriveMode.getState() == false) { m_sMessage1 = "エンジンはプラネタリキャリア(赤/白)とつながっています。"; m_sMessage2 = "プラネタリキャリアには4つのピニオンギア(黄/黒)がつきます。"; } } void sliSunGear_mouseMoved(MouseEvent e) { if (ckDriveMode.getState() == false) { m_sMessage1 = "発電機はサンギア(青/白)とつながっています。"; m_sMessage2 = "発電機はエンジンのスターターとしても利用されます。"; } } void this_mouseMoved(MouseEvent e) { if (ckDriveMode.getState() == false) { m_sMessage1 = "スライダを動かすと、動力分割機構(遊星歯車)の回転をシミュレートできます。"; m_sMessage2 = ""; } } void ckDriveMode_itemStateChanged(ItemEvent e) { sliRingGear.setValue(0); sliPlaCarrier.setValue(0); sliSunGear.setValue(0); m_thsController.getPlanetaryGear().setRingGearSpeed(0.0); m_thsController.getPlanetaryGear().setPlaCarrierSpeed(0.0); lbRingGearSpeed.setText("0 rpm"); lbPlaCarrierSpeed.setText("0 rpm"); lbSunGearSpeed.setText("0 rpm"); } void cmbRange_itemStateChanged(ItemEvent e) { // シフトポジションの変更 switch (cmbRange.getSelectedIndex()) { case 0: m_thsController.setShiftPosition("P"); break; case 1: m_thsController.setShiftPosition("R"); break; case 2: m_thsController.setShiftPosition("N"); break; case 3: m_thsController.setShiftPosition("D"); break; case 4: m_thsController.setShiftPosition("B"); break; } // 実際に切り替わったかチェックする if (m_thsController.getShiftPosition().equals("P")) { if (cmbRange.getSelectedIndex() != 0) cmbRange.select(0); } else if (m_thsController.getShiftPosition().equals("R")) { if (cmbRange.getSelectedIndex() != 1) cmbRange.select(1); } else if (m_thsController.getShiftPosition().equals("N")) { if (cmbRange.getSelectedIndex() != 2) cmbRange.select(2); } else if (m_thsController.getShiftPosition().equals("D")) { if (cmbRange.getSelectedIndex() != 3) cmbRange.select(3); } else if (m_thsController.getShiftPosition().equals("B")) { if (cmbRange.getSelectedIndex() != 4) cmbRange.select(4); } } void sliBrake_stateChanged(ChangeEvent e) { sliAccel.setValue(0); } void sliAccel_stateChanged(ChangeEvent e) { sliBrake.setValue(0); } void sliRingGear_stateChanged(ChangeEvent e) { PlanetaryGear planetaryGear = m_thsController.getPlanetaryGear(); planetaryGear.setRingGearSpeed((double)sliRingGear.getValue()); sliSunGear.setValue((int)planetaryGear.getSunGearSpeed()); viewGearsSpeed(); } void sliPlaCarrier_stateChanged(ChangeEvent e) { PlanetaryGear planetaryGear = m_thsController.getPlanetaryGear(); // planetaryGear.setPlaCarrierSpeed((int)sliPlaCarrier.getValue() - sliPlaCarrier.getValue() % 50); planetaryGear.setPlaCarrierSpeed((int)sliPlaCarrier.getValue()); sliSunGear.setValue((int)planetaryGear.getSunGearSpeed()); viewGearsSpeed(); } }
ThsApplet.java
作成: JBuilder








aaa