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: }