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
//1. Module Name
module asteroids;

//2. Arc Imports and Game Imports 
import
    arc.input,
    arc.window,
    arc.time,
    arc.font,
    arc.gui.gui,
    arc.physics.colliders.boxcircle,
    arc.scenegraph.all;

import 
    ship,
    asteroid,
    laserbolt,
    spacearea,
    starfield,
    scoreboard, 
    gamegui;
        
import std.stdio;

//3. The starfield will draw the background stars, level will keep track of level user is on
Starfield stars;
int level = 1; 

//4. Main
void main()
{
    //5. Open window with title, width, height, and fullscreen-flag
    arc.window.open("Asteroids", 800, 600, false);
    
    //6. Open audio
    try
        arc.sound.open();
    catch(Exception e)
        writefln("There was an error initializing the sound, continuing anyway...");

    //7. initialize input handling, output logging and font handling
    arc.input.open();
    arc.log.open();
    arc.font.open();
    
    //8. load image and layout data
    Asteroid.loadResources();
    LaserBolt.loadResources();
    gamegui.load();    
    
    //9. reset game to start it up
    setupLevel(level); 
        
    //10. initialize time system
    arc.time.open();

    //11. loop until the user wants to quit
    while (!(arc.input.keyDown(arc.input.ARC_QUIT)))
    {
        //12. this works in conjunction with arc.time.limitFPS below
        // basically, it grabs the time at the beginning of this frame
        // and updates the fps-count
        arc.time.process();
        
        //13. updates data about keyboard, mouse and joysticks
        // you can either pull the data via arc.input.keyPressed and similar
        // or subscribe to changes using the signals in arc.input.signals
        arc.input.process();

        //14. clear the current screen
        arc.window.clear();
        
        //15. run game processing if the game is not paused 
        if (!gamegui.gamePaused)
        {
            //16. process players ship
            playerShip.process();
            
            //17. process sound effects 
            arc.sound.process();
            
            //18. Goes through the scenegraph, calling the advance method on every
            // node that's derived from IAdvancable.
            // The physics engine will process the collisions and movements of the ship and the asteriods
            // and animations will update their frames if the delay is over.
            arc.scenegraph.advancable.advanceScenegraph(arc.time.elapsedMilliseconds());
        }

        //19. Goes through the scenegraph and calls the draw method on every node
        // that is derived from IDrawable. Actually, it does a bit more - it respects
        // the draw order layed out by DrawOrder nodes, but basically it just calls draw
        // everywhere.
        arc.scenegraph.drawable.drawScenegraph();
 
        //20. If no asteroids are left, advance to the next level 
        if (spacearea.area.nChildrenOfType!(Asteroid) == 0)
        {
            setupLevel(++level); 
        }            
        
        //21. takes a screenshot if the s key is hit
        if (arc.input.keyPressed('s'))
            arc.window.screenshot("screen"); 
        
        //22. process and draw GUI
        gamegui.process();
        gui.process();
        gui.draw(); 
        
        //23. Swaps window buffers, showing what we just drew to the user
        arc.window.swap();
        
        //24. Limits the frames per second to a given value; can be used to simulate slow computers
        // and to make sure the program doesn't run too fast on fast machines
        arc.time.limitFPS(40);
    }    
    
    //25. this will be called even on exe crash or assert, so
    // it is a good place to clean up
    scope(exit)
    {
        // close what we opened above
        arc.log.close();
        arc.input.close();
        arc.font.close();
        arc.sound.close();
        arc.window.close();
    }
}

//26. reset game 
void setupLevel(uint levelNum, bool resetScore=false)
{
    //7. Create our ship, asteroids, stars, and score
    int oldScore=0;
    
    if (scoreBoard !is null)
    {
        oldScore = scoreBoard.getScore;
    }
    
    // remove everything from the root node
    rootNode.deleteAllChildTrees();

    // create new classes, set things up
    area = new SpaceArea;
    playerShip = new Ship;
    stars = new Starfield; 
    
    scoreBoard = new Scoreboard; 

    if (!resetScore)
    {
        scoreBoard.addScore(oldScore); 
    }
    
    // Build them into a scenegraph
    rootNode.addChild(stars);
    stars.addChild(area);
    area.addChild(playerShip);
    rootNode.addChild(scoreBoard);
    
    area.setupAsteroids(levelNum);
}