aboutsummaryrefslogtreecommitdiffstats
path: root/docs/dist/doc/examples/spacewar/Display.java
blob: 757cdd6e7c27ade717ae43158240b024472b4fbd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*

Copyright (c) Xerox Corporation 1998-2002.  All rights reserved.

Use and copying of this software and preparation of derivative works based
upon this software are permitted.  Any distribution of this software or
derivative works must comply with all applicable United States export control
laws.

This software is made available AS IS, and Xerox Corporation makes no warranty
about the software, its performance or its conformity to any specification.

|<---            this code is formatted to fit into 80 columns             --->|
|<---            this code is formatted to fit into 80 columns             --->|
|<---            this code is formatted to fit into 80 columns             --->|


Display.java
Part of the Spacewar system.
*/

package spacewar;

import java.util.Vector;
import java.util.Enumeration;
import java.awt.Graphics;
import java.awt.Canvas;
import java.awt.Image;
import java.awt.event.KeyListener;

/**
 * The display aspects capture the look and feel of the Game in modular
 * pluggable units.
 *
 * The model is that constructing a concrete subclass of Display attaches that
 * kind of display to the game.  It will Display the game as it goes along.
 * A game can have any number of displays.  Any of the displays will accept
 * keyboard input.
 *
 */

class Display  extends Canvas {

    private static Vector DISPLAYS = new Vector(2);
    private static Vector PLAYERS  = new Vector(2);
    private static Pilot  pilot1, pilot2;

    Game     game;
    SWFrame  frame;
    Image    offImage;
    Graphics offGraphics;

    Game  getGame()   { return game; }
    static Pilot getPilot1() { return pilot1; }
    static Pilot getPilot2() { return pilot2; }

    Display(Game g) {
        super();
        game = g;

        frame = new SWFrame(game, this);
        DISPLAYS.addElement(this);
    }


    void noticeSizeChange() {
        initializeOffImage();
    }

    private void initializeOffImage () {
        int w = getSize().width;
        int h = getSize().height;
        if ( w > 0 & h > 0) {
            offImage = createImage(w, h);
            offGraphics = offImage.getGraphics();
        }
    }

    /*
     * In our double buffering scheme, painting just means copying the buffer
     * to the screen.  The Display aspect draws into the buffer.
     */
    public void paint(Graphics g) {
        if (offImage != null)
            g.drawImage(offImage, 0, 0, null);
    }

    public void update(Graphics g) {
        /*
         * There are 4 steps to this:
         *  - clear the double buffer
         *  - paint the objects into the double buffer
         *  - paint the status into the double buffer
         *  - paint the doublebuffer into the buffer
         */
        offGraphics.setColor(getBackground());
        offGraphics.fillRect(0, 0, getBounds().width, getBounds().height);
        paintObjects(offGraphics);
        paintStatus(offGraphics);
        g.drawImage(offImage, 0, 0, null);
    }

    void paintObjects(Graphics g) { }
    void paintStatus(Graphics g) {}

    static aspect DisplayAspect {

        after (String mode) returning (Game game): call(Game+.new(String)) && args(mode) {
            new Display1(game);
            new Display2(game);

            if ( mode.equals("1") ) {
                pilot1 = game.newPlayer(1);
            }
            else if ( mode.equals("2") ) {
                pilot1 = game.newPlayer(1);
                pilot2 = game.newPlayer(2);
            }
            else if (mode. equals("demo")) {
                pilot1 = game.newRobot(1);
                pilot2 = game.newRobot(2);
            } else {
                game.error("Invalid mode: " + mode);
                game.quit();
            }
        }


        /*
         * I'm not really sure this belongs here.
         *
         * Being here what it does is makes the Display aspect
         * responsible for having the Players couple up to it.  That's
         * kind of nice, but its a bit incomplete, since Player is
         * really part of the GUI, not part of the core Game.
         *
         * In a future re-factoring this will get worked out better.
         * What will happen is that GUI will be an aspect that has the
         * core GUI.  Each of the different kinds of displays will be
         * aspects that tie themselves in.
         */
        after () returning (Player player): call(Player+.new(..)) {
            Enumeration elements = DISPLAYS.elements();
            while ( elements.hasMoreElements() ) {
                Display display = (Display)elements.nextElement();
                display.addKeyListener(player);
            }
        }

        after() returning (Display display): call(Display+.new(..)) {
            display.noticeSizeChange();
        }

        after(Display display) returning (): call(void setSize(..)) && target(display) {
            display.noticeSizeChange();
        }

        after() returning : call(void Game.clockTick()) {
            Enumeration elements = DISPLAYS.elements();
            while ( elements.hasMoreElements() ) {
                Display display = (Display)elements.nextElement();
                display.repaint();
            }
        }
    }
}