目次

エクスカベータシミュレータ(Processing)

 Processingでは画面を扱うので、スクリーン仕様を見直します。



 レバーのスティック、上下左右の矢印、バケット、ブーム、アームの
 アイコンを作成しておきます。




 Arduinoから送信されてくるレバースイッチの情報から
 アイコンを組み合わせて、操作を画面に表示します。

 アイコンは、タイルを敷き詰める仕様とします。

 アイコンロードは、次のように書けばよいでしょう。

PImage imgExecute ;
PImage imgIdle ;
PImage imgExit ;
PImage imgLarrow ;
PImage imgRarrow ;
PImage imgUarrow ;
PImage imgDarrow ;
PImage imgArm ;
PImage imgBucket ;
PImage imgBoom ;
PImage imgStick ;
PImage imgNone ;

  imgExecute = loadImage("execute.png");
  imgIdle    = loadImage("idle.png");
  imgExit    = loadImage("exit.png");
  imgLarrow  = loadImage("larrow.png");
  imgRarrow  = loadImage("rarrow.png");
  imgUarrow  = loadImage("uarrow.png");
  imgDarrow  = loadImage("darrow.png");
  imgArm     = loadImage("arm.png");
  imgBucket  = loadImage("bucket.png");
  imgBoom    = loadImage("boom.png");
  imgStick   = loadImage("stick.png");
  imgNone    = loadImage("none.png");

 3種類のレバーを、ユーザーがどの位置において
 あるのかを扱うために使う関数を定義。

void show_stick()
{
  /* left */
  image(imgStick, 40, 40);
  /* center left */
  image(imgStick,140, 40);
  /* center right */
  image(imgStick,180, 40);
  /* right */
  image(imgStick,280, 40);
}

void show_left(int x)
{
  image(imgNone, 40,  0);
  image(imgNone,  0, 40);
  image(imgNone, 80, 40);
  image(imgNone, 40, 80);
  if ( (x & 8) == 8 ) { image(imgUarrow, 40,  0); }
  if ( (x & 4) == 4 ) { image(imgLarrow,  0, 40); }
  if ( (x & 2) == 2 ) { image(imgRarrow, 80, 40); }
  if ( (x & 1) == 1 ) { image(imgDarrow, 40, 80); }
}

void show_center_left(int x)
{
  image(imgNone,140,  0);
  image(imgNone,140, 80);
  if ( (x & 2) == 2 ) { image(imgUarrow,140,  0); }
  if ( (x & 1) == 1 ) { image(imgDarrow,140, 80); }
}

void show_center_right(int x)
{
  image(imgNone,180,  0);
  image(imgNone,180, 80);
  if ( (x & 2) == 2 ) { image(imgUarrow,180,  0); }
  if ( (x & 1) == 1 ) { image(imgDarrow,180, 80); }
}

void show_right(int x)
{
  image(imgNone,280,  0);
  image(imgNone,240, 40);
  image(imgNone,320, 40);
  image(imgNone,280, 80);
  if ( (x & 8) == 8 ) { image(imgUarrow,280,  0); }
  if ( (x & 4) == 4 ) { image(imgLarrow,240, 40); }
  if ( (x & 2) == 2 ) { image(imgRarrow,320, 40); }
  if ( (x & 1) == 1 ) { image(imgDarrow,280, 80); }
}

 これらの関数を利用するのは、drawの中にある
 シリアル受信のイベントフラグで判断して動作
 するシーケンスとします。

 今回は、次のように定義しています。

 シーケンスをスケッチで使えるコードにすれば、以下。

  if ( scflag == true ) {
    scflag = false ;
    /* check */
    stmp = trim(cport.readStringUntil('\n'));
    println(stmp);
    /* separate */
    char[] ss = stmp.toCharArray();
    /* perform */
    if ( stmp.length() > 2 ) {
      /* left */
      {
        /* clear */
        show_left(0);
        /* show */
        if ( ss[0] != '0' ) {
          switch ( ss[0] ) {
            /* up */
            case '8' : show_left(8); break ;
            /* left */
            case '4' : show_left(4); break ;
            /* right */
            case '2' : show_left(2); break ;
            /* down */
            case '1' : show_left(1); break ;
          }
        }
      }
      /* center left */
      {
        /* clear */
        show_center_left(0);
        /* up */
        if ( ss[1] == '2' ) { show_center_left(2); }
        /* down */
        if ( ss[1] == '1' ) { show_center_left(1); }
      }
      /* center right */
      {
        /* clear */
        show_center_right(0);
        /* up */
        if ( ss[2] == '2' ) { show_center_right(2); }
        /* down */
        if ( ss[2] == '1' ) { show_center_right(1); }
      }
      /* right */
      {
        /* clear */
        show_right(0);
        /* show */
        if ( ss[3] != '0' ) {
          switch ( ss[3] ) {
            /* up */
            case '8' : show_right(8); break ;
            /* left */
            case '4' : show_right(4); break ;
            /* right */
            case '2' : show_right(2); break ;
            /* down */
            case '1' : show_right(1); break ;
          }
        }
      }
    }
  }

 Arduinoからレバーに関係する情報を取得できたなら
 アーム、ブーム、バケットのレバー情報があれば
 レバーの矢印をつけると共に、アイコンに矢印を追加
 します。

 アイコンの横に、矢印のアイコンを置くと考えれば
 次のように位置決めすればよいでしょう。



 アーム、バケットでは、アイコンをタイルのように
 左右に並べていき、矢印をアーム、バケットの垂直
 位置より下げて表示。

 ブームでは、上下矢印アイコンをおく位置を指定し
 上下矢印アイコンのつなぎ目にブームのアイコンを
 置けばよいでしょう。

 アーム、ブーム、バケットの矢印状態を指定する
 専用の関数を定義して利用します。

 専用関数の雛形は、以下。

void show_arm_boom_bucket()
{
  /* arm */
  image(imgArm,?,?);
  /* boom */
  image(imgBoom,?,?);
  /* bucket */
  image(imgBucket,?,?);
}

void show_arm(int x)
{
  /* no left  arrow icon */
  /* no right arrow icon */
  if ( (x & 2) == 2 ) { /* draw left  arrow icon */ }
  if ( (x & 1) == 1 ) { /* draw right arrow icon */ }
}

void show_boom(int x)
{
  /* no upper arrow icon */
  /* no lower arrow icon */
  if ( (x & 2) == 2 ) { /* draw upper arrow icon */ }
  if ( (x & 1) == 1 ) { /* draw lower arrow icon */ }
}

void show_bucket(int x)
{
  /* no left  arrow icon */
  /* no right arrow icon */
  if ( (x & 2) == 2 ) { /* draw left  arrow icon */ }
  if ( (x & 1) == 1 ) { /* draw right arrow icon */ }
}

 雛形を作ったら、各アイコンの表示位置をimageを
 利用して定義していきます。

void show_arm_boom_bucket()
{
  /* arm */
  image(imgArm,40,120);
  /* boom */
  image(imgBoom,300,140);
  /* bucket */
  image(imgBucket,360,120);
}

void show_arm(int x)
{
  /* no left  arrow icon */
  image(imgNone, 20,160);
  image(imgNone, 60,160);
  /* no right arrow icon */
  if ( (x & 2) == 2 ) { image(imgLarrow, 20,160); }
  if ( (x & 1) == 1 ) { image(imgRarrow, 60,160); }
}

void show_boom(int x)
{
  /* no upper arrow icon */
  image(imgNone,260,160);
  image(imgNone,260,220);
  /* no lower arrow icon */
  if ( (x & 2) == 2 ) { image(imgUarrow,260,120); }
  if ( (x & 1) == 1 ) { image(imgDarrow,260,160); }
}

void show_bucket(int x)
{
  /* no left  arrow icon */
  image(imgNone,340,160);
  image(imgNone,380,160);
  /* no right arrow icon */
  if ( (x & 2) == 2 ) { image(imgLarrow,340,160); }
  if ( (x & 1) == 1 ) { image(imgRarrow,380,160); }
}

 レバーの方向表示に加えて、アーム、ブーム、バケットの
 方向指示を加えます。

  if ( scflag == true ) {
    scflag = false ;
    /* check */
    stmp = trim(cport.readStringUntil('\n'));
    println(stmp);
    /* separate */
    char[] ss = stmp.toCharArray();
    /* perform */
    if ( stmp.length() > 2 ) {
      /* left */
      {
        /* clear */
        show_left(0);
        /* show */
        if ( ss[0] != '0' ) {
          switch ( ss[0] ) {
            /* up */
            case '8' : show_left(8); break ;
            /* left */
            case '4' : show_left(4); break ;
            /* right */
            case '2' : show_left(2); break ;
            /* down */
            case '1' : show_left(1); break ;
          }
        }
        /* arm */
        {
          /* clear */
          show_arm(0);
          /* left */
          if ( ss[0] == '4' ) { show_arm(2) ; }
          /* right */
          if ( ss[0] == '2' ) { show_arm(1) ; }
        }
      }
      /* center left */
      {
        /* clear */
        show_center_left(0);
        /* up */
        if ( ss[1] == '2' ) { show_center_left(2); }
        /* down */
        if ( ss[1] == '1' ) { show_center_left(1); }
      }
      /* center right */
      {
        /* clear */
        show_center_right(0);
        /* up */
        if ( ss[2] == '2' ) { show_center_right(2); }
        /* down */
        if ( ss[2] == '1' ) { show_center_right(1); }
      }
      /* right */
      {
        /* clear */
        show_right(0);
        /* show */
        if ( ss[3] != '0' ) {
          switch ( ss[3] ) {
            /* up */
            case '8' : show_right(8); break ;
            /* left */
            case '4' : show_right(4); break ;
            /* right */
            case '2' : show_right(2); break ;
            /* down */
            case '1' : show_right(1); break ;
          }
        }
        /* boom */
        {
          /* clear */
          show_boom(0);
          /* left */
          if ( ss[3] == '8' ) { show_boom(1); }
          /* right */
          if ( ss[3] == '1' ) { show_boom(2); }
        }
        /* bucket */
        {
          /* clear */
          show_bucket(0);
          /* left */
          if ( ss[3] == '4' ) { show_bucket(1) ; }
          /* right */
          if ( ss[3] == '2' ) { show_bucket(2) ; }
        }
      }
    }
  }

 スクリーンに投影される外界の風景は、後で入れることに
 して、ここまでの内容をスケッチにまとめます。
 (実際に動かしてデバッグしたので、アイコン表示に関係
  する処理は、これまでの説明と異なる場合もあります。)

import processing.serial.*;

Serial cport;

PImage imgExecute ;
PImage imgIdle ;
PImage imgExit ;
PImage imgLarrow ;
PImage imgRarrow ;
PImage imgUarrow ;
PImage imgDarrow ;
PImage imgArm ;
PImage imgBucket ;
PImage imgBoom ;
PImage imgStick ;
PImage imgNone ;

int FRATE = 25 ;

String stmp ;

boolean scflag ;

boolean isRangeOk(int x,int bx,int ex)
{
  boolean result ;
  /* default */
  result = false ;
  /* judge */
  if ( bx <= x && x <= ex ) { result = true ; }

  return result ;
}

void show_btn()
{
  image(imgExecute, 80,300);
  image(imgIdle   ,140,300);
  image(imgExit   ,220,300);
}

void show_stick()
{
  /* left */
  image(imgStick, 40, 40);
  /* center left */
  image(imgStick,140, 40);
  /* center right */
  image(imgStick,180, 40);
  /* right */
  image(imgStick,280, 40);
}

void show_left(int x)
{
  /* clear */
  image(imgNone, 40,  0);
  image(imgNone,  0, 40);
  image(imgNone, 80, 40);
  image(imgNone, 40, 80);
  /* arm forward */
  if ( (x & 8) == 8 ) { image(imgUarrow, 40,  0); }
  /* left */
  if ( (x & 4) == 4 ) { image(imgLarrow,  0, 40); }
  /* right */
  if ( (x & 2) == 2 ) { image(imgRarrow, 80, 40); }
  /* arm backward */
  if ( (x & 1) == 1 ) { image(imgDarrow, 40, 80); }
}

void show_center_left(int x)
{
  /* clear */
  image(imgNone,140,  0);
  image(imgNone,140, 80);
  /* forward */
  if ( (x & 2) == 2 ) { image(imgUarrow,140,  0); }
  /* backward */
  if ( (x & 1) == 1 ) { image(imgDarrow,140, 80); }
}

void show_center_right(int x)
{
  /* clear */
  image(imgNone,180,  0);
  image(imgNone,180, 80);
  /* forward */
  if ( (x & 2) == 2 ) { image(imgUarrow,180,  0); }
  /* backward */
  if ( (x & 1) == 1 ) { image(imgDarrow,180, 80); }
}

void show_right(int x)
{
  /* clear */
  image(imgNone,280,  0);
  image(imgNone,240, 40);
  image(imgNone,320, 40);
  image(imgNone,280, 80);
  /* boom up */
  if ( (x & 8) == 8 ) { image(imgUarrow,280,  0); }
  /* bucket scratch */
  if ( (x & 4) == 4 ) { image(imgLarrow,240, 40); }
  /* bucket dump */
  if ( (x & 2) == 2 ) { image(imgRarrow,320, 40); }
  /* boom up */
  if ( (x & 1) == 1 ) { image(imgDarrow,280, 80); }
}

void show_arm_boom_bucket()
{
  /* arm */
  image(imgArm,40,120);
  /* boom */
  image(imgBoom,300,140);
  /* bucket */
  image(imgBucket,360,120);
}

void show_arm(int x)
{
  /* no left  arrow icon */
  image(imgNone, 20,160);
  image(imgNone, 60,160);
  /* no right arrow icon */
  if ( (x & 2) == 2 ) { image(imgLarrow, 20,160); }
  if ( (x & 1) == 1 ) { image(imgRarrow, 60,160); }
}

void show_boom(int x)
{
  /* no upper arrow icon */
  image(imgNone,260,160);
  image(imgNone,260,120);
  /* no lower arrow icon */
  if ( (x & 2) == 2 ) { image(imgUarrow,260,120); }
  if ( (x & 1) == 1 ) { image(imgDarrow,260,160); }
}

void show_bucket(int x)
{
  /* no left  arrow icon */
  image(imgNone,340,160);
  image(imgNone,380,160);
  /* no right arrow icon */
  if ( (x & 2) == 2 ) { image(imgLarrow,340,160); }
  if ( (x & 1) == 1 ) { image(imgRarrow,380,160); }
}

void clear_area()
{
  /* black */
  fill(0,0,0);
  /* clear status area */
  rect(390,200,100,140);
}

void show_caption()
{
  clear_area();
  /* white */
  fill(255,255,255);
  /* size */
  textSize(12);
}

void setup()
{
  size(440,340);
  /* title caption */
  surface.setTitle("Backhow simulator");
  /* select framerate */
  frameRate(FRATE);
  /* select back ground color with BLACK */
  background(0,0,0);
  //show serial port list (0:COM1 , 1:COM2 ... )
  //println(Serial.list());
  String arduinoPort = Serial.list()[4];
  /* initialize serial port */
  cport = new Serial(this,arduinoPort,9600);
  cport.clear();
  cport.bufferUntil('\n');
  scflag = false ;
  /* get image */
  imgExecute = loadImage("execute.png");
  imgIdle    = loadImage("idle.png");
  imgExit    = loadImage("exit.png");
  imgLarrow  = loadImage("larrow.png");
  imgRarrow  = loadImage("rarrow.png");
  imgUarrow  = loadImage("uarrow.png");
  imgDarrow  = loadImage("darrow.png");
  imgArm     = loadImage("arm.png");
  imgBucket  = loadImage("bucket.png");
  imgBoom    = loadImage("boom.png");
  imgStick   = loadImage("stick.png");
  imgNone    = loadImage("none.png");
  /* stick */
  show_stick();
  /* arrow */
  show_left(0);
  show_center_left(0);
  show_center_right(0);
  show_right(0);
  show_arm_boom_bucket();
  show_arm(0);
  show_boom(0);
  show_bucket(0);
}

void draw()
{
  /* button */
  show_btn();
  /* caption */
  show_caption();
  /* serial receive */
  if ( scflag == true ) {
    scflag = false ;
    /* check */
    stmp = trim(cport.readStringUntil('\n'));
    println(stmp);
    /* separate */
    char[] ss = stmp.toCharArray();
    /* perform */
    if ( stmp.length() > 2 ) {
      /* left */
      {
        /* clear */
        show_left(0);
        show_arm(0);
        /* show */
        if ( ss[0] != '0' ) {
          switch ( ss[0] ) {
            /* up */
            case '8' : 
              show_left(8);
              show_arm(2);
              break ;
            /* left */
            case '4' : 
              show_left(4);
              break ;
            /* right */
            case '2' : 
              show_left(2);
              break ;
            /* down */
            case '1' :
              show_left(1);
              show_arm(1);
              break ;
          }
        }
      }
      /* center left */
      {
        /* clear */
        show_center_left(0);
        /* up */
        if ( ss[1] == '2' ) { show_center_left(2); }
        /* down */
        if ( ss[1] == '1' ) { show_center_left(1); }
      }
      /* center right */
      {
        /* clear */
        show_center_right(0);
        /* up */
        if ( ss[2] == '2' ) { show_center_right(2); }
        /* down */
        if ( ss[2] == '1' ) { show_center_right(1); }
      }
      /* right */
      {
        /* clear */
        show_right(0);
        show_boom(0);
        show_bucket(0);
        /* show */
        if ( ss[3] != '0' ) {
          switch ( ss[3] ) {
            /* up */
            case '8' : 
              show_right(8);
              show_boom(1);  /* boom down */
              break ;
            /* left */
            case '4' : 
              show_right(4);
              show_bucket(1);
              break ;
            /* right */
            case '2' : 
              show_right(2);
              show_bucket(2);
              break ;
            /* down */
            case '1' : 
              show_right(1);
              show_boom(2);  /* boom up */
              break ;
          }
        }
      }
    }
  }
}

void mouseClicked()
{
  if ( mouseButton == LEFT ) {
    /* execute */
    if ( isRangeOk(mouseX, 80,130) &&
         isRangeOk(mouseY,300,320)    ) {
      /* debug */
      println("Execute");
      /* send command */
      cport.write('E'); 
      cport.write('\r');
    }
    /* idle */
    if ( isRangeOk(mouseX,140,190) &&
         isRangeOk(mouseY,300,320)    ) {
      /* debug */
      println("Idle");
      /* send command */
      cport.write('I'); 
      cport.write('\r');
    }
    /* exit */
    if ( isRangeOk(mouseX,220,390) &&
         isRangeOk(mouseY,300,320)    ) {
      /* send command */
      cport.write('I'); 
      cport.write('\r');
      exit();
    }
  } 
  /* Exit */
  if ( mouseButton == RIGHT ) {
    /* send command */
    cport.write('I'); 
    cport.write('\r');
    exit();
  } 
}

void serialEvent(Serial p)
{
  scflag = true ;
}

 このスケッチのテスト、デバッグに利用したArduinoスケッチは、以下。

#include <MsTimer2.h>

#define OFF 0
#define ON  OFF+1

#define LASTSTATE 10
#define LASTXCNT  10

#define LED_BIT 5

#define NPER 100

#define MASK0F 0x0f 

/* variables */
byte uflag ;
byte tflag ;
byte eflag ;
byte cmd ;
byte sindex ;
byte sbuf[4] ;
byte state ;
byte xcnt ;
char msg[5];
char ll[10];
char cl[10];
char cr[10];
char rr[10];

/* function prototype */
void show_help();
char get_asc(byte x);
void rs_putchar(char x);
void rs_puts(char *ptr);
void crlf();
void send_led(byte x);
void update_trigger(void);

void setup()
{
  /* initialize serial */
  Serial.begin(9600);
  sindex = 0 ;
  /* clear flags */
  uflag  = OFF ;
  tflag  = OFF ;
  eflag  = OFF ;
  /* initialize */
  state = 0 ;
  xcnt  = 0 ;
  *(msg+4) = '\0' ;
  /* initialize port values */
  PORTB = 0xf0 ;
  PORTC = 0xf8 ;
  PORTD = 0x01 ;
  /* initialize port direction */
  DDRB = 0xff ;
  DDRC = 0x07 ;
  DDRD = 0xfe ;
  /* initialize left and right */
  *(ll+0) = '0' ; *(rr+0) = '0' ;
  *(ll+1) = '0' ; *(rr+1) = '0' ;
  *(ll+2) = '1' ; *(rr+2) = '8' ;
  *(ll+3) = '1' ; *(rr+3) = '8' ;
  *(ll+4) = '2' ; *(rr+4) = '4' ;
  *(ll+5) = '2' ; *(rr+5) = '4' ;
  *(ll+6) = '4' ; *(rr+6) = '2' ;
  *(ll+7) = '4' ; *(rr+7) = '2' ;
  *(ll+8) = '8' ; *(rr+8) = '1' ;
  *(ll+9) = '8' ; *(rr+9) = '1' ;
  /* initialize center left and center right */
  *(cl+0) = '0' ; *(cr+0) = '0' ;
  *(cl+1) = '0' ; *(cr+1) = '1' ;
  *(cl+2) = '1' ; *(cr+2) = '0' ;
  *(cl+3) = '1' ; *(cr+3) = '2' ;
  *(cl+4) = '2' ; *(cr+4) = '0' ;
  *(cl+5) = '2' ; *(cr+5) = '1' ;
  *(cl+6) = '0' ; *(cr+6) = '0' ;
  *(cl+7) = '0' ; *(cr+7) = '2' ;
  *(cl+8) = '1' ; *(cr+8) = '0' ;
  *(cl+9) = '1' ; *(cr+9) = '0' ;
  /* trigger period */
  MsTimer2::set(NPER,update_trigger);
  /* enable */ 
  MsTimer2::start();
}

void loop()
{
  /* transfer switch state */
  if ( tflag == ON ) {
    /* clear event flag */
    tflag = OFF ;
    /* generate code */
    *(msg+0) = *(ll+state) ;
    *(msg+1) = *(cl+state) ;
    *(msg+2) = *(cr+state) ;
    *(msg+3) = *(rr+state) ;
    /* update */
    state++ ;
    if ( state == LASTSTATE ) { state = 0 ; }
    /* judge transfer */
    if ( eflag == ON ) {
      rs_puts( msg );
      crlf();
    }
  }
  /* command interpreter */
  if ( uflag == ON ) {
    /* clear event flag */
    uflag = OFF ;
    /* new line */
    crlf();
    /* get command */
    cmd = *(sbuf+0) ;
    /* help */
    if ( cmd == '?' ) { show_help() ; }
    /* execute */
    if ( cmd == 'E' ) {
      eflag = ON ; 
      state = 0 ;
    }
    /* idle */
    if ( cmd == 'I' ) { eflag = OFF ; }
    /* show status */
    if ( cmd == 'S' ) {
      /* message */
      if ( eflag == ON ) { rs_puts("run"); }
      else               { rs_puts("idle"); }
      /* new line */
      crlf();
    }
  }
}

/* receive interrupt */
void serialEvent()
{
  char ch;

  if ( Serial.available() > 0 ) {
    /* get 1 character */
    ch = Serial.read();
    /* store */
    *(sbuf+sindex) = ch ;
    /* increment */
    sindex++ ;
    /* judge */
    if ( ch == '\r' ) {
      sindex = 0 ; 
      uflag  = ON ;
    }
  }
}

char get_asc(byte x)
{
  byte result ;
  /* default */
  result = '0' ;
  /* judge */
  if ( x < 10 ) { result = x + '0' ; }
  if ( 9 < x ) { result = x - 10 + 'A' ; }
  
  return result ;
}

void show_help()
{
  rs_puts("? help");        crlf();
  rs_puts("E execute");     crlf();
  rs_puts("I idle");        crlf();
  rs_puts("S show status"); crlf();
}

void rs_putchar(char x)
{
  Serial.write(x);
}

void rs_puts(char *ptr)
{
  while ( *ptr ) {
    rs_putchar( *ptr );
    ptr++;
  }
}

void crlf()
{
  rs_putchar('\r');
  rs_putchar('\n');
}

void  send_led(byte x)
{
  if ( x ) { PORTB |=  (1 << LED_BIT) ; }
  else     { PORTB &= ~(1 << LED_BIT) ; }
}

void  update_trigger(void)
{
  /* led handling */
  send_led(xcnt & ON);
  /* update counter */
  xcnt++ ;
  /* judge */
  if ( xcnt == LASTXCNT ) {
    xcnt = 0 ;
    tflag = ON ;
  }
}

 中央スクリーンで、前後に移動した場合と運転台を
 左右に回転した場合の処理を定義します。

 十文字のアイコンを利用し、前後の移動ではアイコンが
 大きくなるか小さくなるかで表現します。
 回転の場合、アイコンサイズは変えないで左右に移動
 させます。

 車体を中央にあるレバーで前後に移動する他に、信地
 旋回する場合には、アイコンは左右に移動することに
 加えて、上下動を与えます。

 スクリーン上のアイコンは、次の3種の操作を
 組み合わせて表示すればよいでしょう。

 十文字アイコンは、縦と横の竿が交差する点を
 左右、上下に平行移動後、竿を描けばいけそう
 です。サイズ変更は、竿の長さを変える処理で
 対応できます。

 スクリーンのサイズは固定なので、アイコンがはみ
 出す場合には、竿を描画しなければよいはず。

(under construction)

目次

inserted by FC2 system