1: import java.awt.*;
  2: import java.awt.event.*;
  3: import java.awt.geom.*;
  4: import scm.game.*;
  5: import scm.graph.*;
  6: 
  7: public class Aster extends Game {
  8:     class TrianglePic implements Paintable {
  9:         int color;
 10: 
 11:         TrianglePic(int color) {
 12:             this.color = color;
 13:         }
 14: 
 15:         public void paint(Graphics2D g) {
 16:             Color c = new Color(color % 2 * 255,
 17:                 color / 2 % 2 * 255, color / 4 % 2 * 255);
 18:             g.setColor(c);
 19:             g.fillPolygon(new int[] { 0, 1, -1 },
 20:                           new int[] { -2, 2, 2 }, 3);
 21:         }
 22:     }
 23: 
 24:     class CirclePic implements Paintable {
 25:         public void paint(Graphics2D g) {
 26:             g.setColor(Color.BLACK);
 27:             g.fill(new Ellipse2D.Double(-0.3, -0.3, 0.6, 0.6));
 28:         }
 29:     }
 30: 
 31:     ScmManager mgr;
 32:     Surface surf;
 33:     Clock clock;
 34: 
 35:     Ship[] ships;
 36: 
 37:     double wrap(double x, double total) {
 38:         x = x % total;
 39:         if (x < 0)
 40:             x += total;
 41:         return x;
 42:     }
 43: 
 44:     class Ship {
 45:         Trans pos;
 46:         Controller ctrl;
 47:         double x, y, vx, vy, dir;
 48:         boolean hit;
 49:         double nextFireTime;
 50: 
 51:         void reset() {
 52:             x = 100 * mgr.rand();
 53:             y = 75 * mgr.rand();
 54:             dir = 360 * mgr.rand();
 55:             vx = 0;
 56:             vy = 0;
 57:         }
 58: 
 59:         void doHit() {
 60:             if (hit)
 61:                 return;
 62:             hit = true;
 63:             for (int i = 0; i < 30; ++i) {
 64:                 pos.scale(1.05);
 65:                 clock.sleep(10);
 66:             }
 67:             for (int i = 0; i < 70; ++i) {
 68:                 pos.scale(0.9);
 69:                 clock.sleep(10);
 70:             }
 71:             hit = false;
 72:         }
 73: 
 74:         void service() {
 75:             reset();
 76:             for (;;) {
 77:                 if (hit) {
 78:                     clock.sleep(1000);
 79:                     reset();
 80:                 }
 81:                 pos.clear();
 82:                 pos.translate(x, y);
 83:                 pos.rotate(dir);
 84:                 handleKeys();
 85:                 x = wrap(x + 0.2 * vx, 100);
 86:                 y = wrap(y + 0.2 * vy, 75);
 87:                 double v = Math.sqrt(vx * vx + vy * vy);
 88:                 if (v > 1) {
 89:                     vx = vx / v;
 90:                     vy = vy / v;
 91:                 }
 92:                 clock.sleep(10);
 93:             }
 94:         }
 95: 
 96:         void handleKeys() {
 97:             final double S = 0.005;
 98:             if (ctrl.isKeyDown(0)) {
 99:                 vx += S * Math.sin(dir * Math.PI / 180);
100:                 vy -= S * Math.cos(dir * Math.PI / 180);
101:             }
102:             if (ctrl.isKeyDown(1)) {
103:                 vx -= S * Math.sin(dir * Math.PI / 180);
104:                 vy += S * Math.cos(dir * Math.PI / 180);
105:             }
106:             if (ctrl.isKeyDown(2))
107:                 dir -= 1;
108:             if (ctrl.isKeyDown(3))
109:                 dir += 1;
110:             if (ctrl.isKeyDown(4) &&
111:                     clock.getTime() >= nextFireTime) {
112:                 nextFireTime = clock.getTime() + 1000;
113:                 clock.startThread(new Runnable() {
114:                     public void run() {
115:                         fireMissle(x, y, dir);
116:                     }
117:                 });
118:             }
119:         }
120:     }
121: 
122:     void fireMissle(double x, double y, double dir) {
123:         Sprite sprite = new Sprite(new CirclePic());
124:         surf.addPic(sprite);
125:         Trans t = sprite.addTrans();
126:         double S = 1.1;
127:         for (int i = 0; i < 50; ++i) {
128:             x = wrap(x + S * Math.sin(dir*Math.PI/180), 100);
129:             y = wrap(y - S * Math.cos(dir*Math.PI/180), 75);
130:             if (i > 3) {
131:                 if (checkCollision(x, y))
132:                     break;
133:             }
134:             t.clear();
135:             t.translate(x, y);
136:             clock.sleep(10);
137:         }
138:         surf.removePic(sprite);
139:     }
140: 
141:     boolean checkCollision(double mx, double my) {
142:         for (int i = 0; i < ships.length; ++i) {
143:             final Ship ship = ships[i];
144:             double dx = mx - ship.x;
145:             double dy = my - ship.y;
146:             double d = Math.sqrt(dx * dx + dy * dy);
147:             if (d <= 1.5) {
148:                 clock.startThread(new Runnable() {
149:                     public void run() {
150:                         ship.doHit();
151:                     }
152:                 });
153:                 return true;
154:             }
155:         }
156:         return false;
157:     }
158: 
159:     public void start(ScmManager mgr, int playerCount) {
160:         this.mgr = mgr;
161:         this.surf = mgr.getSurface();
162:         this.clock = mgr.getClock();
163:         surf.setVirtualRect(0, 0, 100, 75);
164:         ships = new Ship[playerCount];
165:         for (int i = 1; i <= playerCount; ++i) {
166:             final Ship ship = new Ship();
167:             ships[i - 1] = ship;
168:             Sprite sprite = new Sprite(new TrianglePic(i));
169:             surf.addPic(sprite);
170:             ship.ctrl = mgr.getController(i);
171:             ship.pos = sprite.addTrans();
172:             clock.startThread(new Runnable() {
173:                 public void run() {
174:                     ship.service();
175:                 }
176:             });
177:         }
178:     }
179: 
180:     public void initNetworkGame(ScmManager mgr,
181:             int playerNumber, int playerCount) {
182:         mgr.createLocalController(playerNumber, new int[] {
183:                 KeyEvent.VK_UP, KeyEvent.VK_DOWN,
184:                 KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT,
185:                 KeyEvent.VK_CONTROL });
186:     }
187: 
188:     public void initLocalGame(ScmManager mgr) {
189:         mgr.createLocalController(1, new int[] {
190:                 KeyEvent.VK_UP, KeyEvent.VK_DOWN,
191:                 KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT,
192:                 KeyEvent.VK_CONTROL });
193:         mgr.createLocalController(2, new int[] {
194:                 KeyEvent.VK_W, KeyEvent.VK_S,
195:                 KeyEvent.VK_A, KeyEvent.VK_D,
196:                 KeyEvent.VK_SHIFT });
197:     }
198: 
199:     public static void main(String[] args) {
200:         Game.startLocalGame(Aster.class, "AsterWar", 2);
201:     }
202: }