source: pycodeshooter/trunk/shooter/system.js @ 114

Revision 114, 12.5 KB checked in by atzm, 12 years ago (diff)
  • add bullet patterns, xreflect series
  • Property svn:keywords set to Id
Line 
1/* -*- coding: utf-8 -*-
2 *
3 * Copyright (C) 2010 by Atzm WATANABE <atzm@atzm.org>
4 *
5 *  This program is free software; you can redistribute it and/or modify it
6 *  under the terms of the GNU General Public License (version 2) as
7 *  published by the Free Software Foundation.  It is distributed in the
8 *  hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
9 *  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 *  PURPOSE.  See the GNU General Public License for more details.
11 *
12 * $Id$
13 *
14 */
15
16System = {
17    "screen": {
18        "canvas": null,
19        "ctx":    null,
20        "width":  0,
21        "height": 0
22    },
23    "message":          null,
24    "enemyImages":      new Array(),
25    "enemies":          new Array(),
26    "players":          new Array(),
27    "score":            {},
28    "backgroundObject": new Array(),
29    "deathPieces":      new Array(),
30    "mainIntervalId":   0
31};
32
33
34/*
35 *  Tiun Tiun Utilities
36 */
37var DeathPiece = function(sizes, colors, x, y, dir, speed) {
38    var that = new LinerBullet(sizes[0], colors[0], null,
39                               System.screen.width, System.screen.height,
40                               x, y, dir, speed);
41
42    var sizeIdx  = -1;
43    var colorIdx = -1;
44
45    that.getSize = function() {
46        if (++sizeIdx >= sizes.length)
47            sizeIdx = 0;
48        return sizes[sizeIdx];
49    };
50
51    that.getColor = function() {
52        if (++colorIdx >= colors.length)
53            colorIdx = 0;
54        return colors[colorIdx];
55    };
56
57    return that;
58};
59
60function addDeathPieces(x, y, sizes, colors, speed, way) {
61    if (way % 2)
62        way++;
63
64    var pieces = new Array();
65    var angle  = 0;
66    var delta  = 2 / way;
67
68    for(var i = 0; i < way; i++) {
69        pieces.push(new DeathPiece(sizes, colors, x, y, angle * Math.PI, speed));
70        angle += delta;
71    }
72
73    System.deathPieces.push(pieces);
74}
75
76function updateDeathPieces(ctx, width, height) {
77    var newObjs = new Array();
78
79    for (var i = 0; i < System.deathPieces.length; i++) {
80        var pieces    = System.deathPieces[i];
81        var newPieces = new Array();
82
83        for (var k = 0; k < pieces.length; k++) {
84            pieces[k].next();
85            pieces[k].draw(ctx);
86            if (!pieces[k].vanished(width, height))
87                newPieces.push(pieces[k]);
88        }
89
90        if (newPieces.length)
91            newObjs.push(newPieces);
92    }
93
94    System.deathPieces = newObjs;
95}
96
97
98/*
99 *  Utility Functions
100 */
101function setMessage(elem, msg) {
102    if (elem)
103        elem.innerHTML = msg;
104}
105
106function addMessage(elem, msg) {
107    if (elem)
108        elem.innerHTML += msg;
109}
110
111function updateBackground(ctx, width, height, size, color, max) {
112    if (System.backgroundObject.length < max) {
113        var x = Math.ceil(Math.random() * width);
114        var s = Math.ceil(Math.random() * 5);
115        System.backgroundObject.push(
116            new LinerBullet(size, color, null,
117                            System.screen.width, System.screen.height,
118                            x, 0, 0.5 * Math.PI, s));
119    }
120
121    var newObjs = new Array();
122
123    for (var i = 0; i < System.backgroundObject.length; i++) {
124        System.backgroundObject[i].next();
125        System.backgroundObject[i].draw(ctx);
126        if (!System.backgroundObject[i].vanished(width, height))
127            newObjs.push(System.backgroundObject[i]);
128    }
129
130    System.backgroundObject = newObjs;
131}
132
133function drawScreen(ctx, op, style, width, height) {
134    var c = ctx.globalCompositeOperation;
135    ctx.globalCompositeOperation = op;
136    ctx.beginPath();
137    ctx.fillStyle = style;
138    ctx.fillRect(0, 0, width, height);
139    ctx.fill();
140    ctx.closePath();
141    ctx.globalCompositeOperation = c;
142}
143
144function drawLifeGauge(ctx, op, trooper, x, y, width) {
145    var length = trooper.life;
146
147    if (length > width - 20)
148        length = width - 20;
149
150    var c = ctx.globalCompositeOperation;
151    ctx.globalCompositeOperation = op;
152    ctx.beginPath();
153    ctx.fillStyle = trooper.color;
154    ctx.fillRect(x, y, length, 10);
155    ctx.fill();
156    ctx.closePath();
157    ctx.globalCompositeOperation = c;
158
159    drawString(ctx, op, trooper.life, x + 2, y + 8, trooper.color,
160               "6pt monospace", "left");
161}
162
163function drawString(ctx, op, string, x, y, color, font, align) {
164    var a = ctx.textAlign;
165    var f = ctx.font;
166    var c = ctx.globalCompositeOperation;
167    ctx.globalCompositeOperation = op;
168    ctx.beginPath();
169    ctx.textAlign = align;
170    ctx.fillStyle = color;
171    ctx.font      = font;
172    ctx.fillText(string, x, y);
173    ctx.fill();
174    ctx.textAlign = a;
175    ctx.font      = f;
176    ctx.closePath();
177    ctx.globalCompositeOperation = c;
178}
179
180function updateTrooper(trooper, enemyKey) {
181    trooper.update(System[enemyKey]);
182
183    var aliveEnemies = new Array();
184    for (var i = 0; i < System[enemyKey].length; i++) {
185        var enemy = System[enemyKey][i];
186
187        if (enemy.isDead()) {
188            addDeathPieces(
189                enemy.x, enemy.y,
190                [6, 8, 10], ["#55F", "#AAF"], 3, 8
191            );
192
193            if (System.score[trooper.name] !== undefined) {
194                System.score[trooper.name] += enemy.maxLife * 100;
195            }
196        }
197        else {
198            aliveEnemies.push(enemy);
199        }
200    }
201    System[enemyKey] = aliveEnemies;
202
203    trooper.draw(System.screen.ctx);
204}
205
206function numEnemies() {
207    return System.enemies.length;
208}
209
210function addEnemyImage(image) {
211    System.enemyImages.push(image);
212}
213
214function addEnemy(enemyData) {
215    var actList = EnemyActionLists[enemyData.mtime % EnemyActionLists.length];
216    var shot    = EnemyShots[enemyData.hitpoint % EnemyShots.length];
217    var numAct  = enemyData.agility       % (EnemyActions.length  - 1) + 1;
218    var numBlt  = enemyData.skills.length % (EnemyBullets.length  - 1) + 1;
219    var numBrrg = enemyData.skills.length % (EnemyBarrages.length - 1) + 1;
220    var acts    = new Array();
221    var brrgs   = new Array();
222
223    var bulletWay         = Math.ceil(enemyData.concentration / 10);
224    var bulletInterval    = Math.round(50 * 1 / Math.log(enemyData.skillpoint + 0.1));
225    var bulletSize        = Math.round(Math.log(enemyData.luck + 1));
226    var bulletFrameWidth  = (bulletSize + 5) * 2;
227    var bulletFrameHeight = (bulletSize + 5) * 4;
228    var bulletSpeed       = enemyData.strength / 15;
229
230    bulletSpeed = Math.log(bulletSpeed < 1.5 ? 1.5 : bulletSpeed);
231
232    for (var i = 0; i < numAct; i++) {
233        var idx = (enemyData.agility + i) % EnemyActions.length;
234        acts.push(new EnemyActions[idx](new shot()));
235    }
236
237    for (var i = 0; i < numBrrg; i++) {
238        var idx     = (enemyData.skillpoint + i * (enemyData.skills.length + 1)) % EnemyBarrages.length;
239        var brrgCls = EnemyBarrages[idx];
240
241        for (var k = 0; k < numBlt; k++) {
242            var iidx = (enemyData.skills.length + i + k) % EnemyBullets.length;
243            brrgs.push(
244                new brrgCls(
245                    EnemyBullets[iidx],
246                    bulletSize,
247                    "#FF3",
248                    {"style": "rect", "color": "rgba(128,32,32,0.5)",
249                     "width": bulletFrameWidth, "height": bulletFrameHeight},
250                    bulletInterval,
251                    bulletSpeed,
252                    bulletWay
253                )
254            );
255        }
256    }
257
258    var size  = Math.ceil((System.screen.width / 2) * (1 / enemyData.defense));
259    var enemy = new Trooper(
260        enemyData.name,
261        new actList(acts),
262        System.enemyImages[enemyData.hitpoint % System.enemyImages.length],
263        size,
264        size,
265        "#F33",
266        "#F33",
267        System.screen.width / 2,
268        System.screen.height / 7,
269        System.screen.width,
270        System.screen.height,
271        Math.floor(enemyData.hitpoint / 25) + 1,
272        Math.log(enemyData.agility + 0.1) * 3,
273        0,
274        ["rgba(255,0,0,0.3)", "rgba(0,0,255,0.3)"],
275        brrgs
276    );
277
278    System.enemies.push(enemy);
279}
280
281
282/*
283 *  Main loop
284 */
285function mainLoop() {
286    // clear screen
287    drawScreen(
288        System.screen.ctx,
289        "source-over",
290        "rgba(8,8,8,0.8)",
291        System.screen.width,
292        System.screen.height
293    );
294
295    // update background objects
296    updateBackground(
297        System.screen.ctx,
298        System.screen.width,
299        System.screen.height,
300        1, "#CAF", 10
301    );
302
303    // draw score
304    var scoreNames = Object.keys(System.score).sort();
305    for (var i = 0; i < scoreNames.length; i++) {
306        var name = scoreNames[i];
307        drawString(
308            System.screen.ctx,
309            "source-over",
310            name + " score " + System.score[name],
311            (System.screen.width - 10),
312            i * 16 + 15,
313            "#ACF", "9pt monospace", "right"
314        );
315    }
316
317    // update/draw troopers
318    for (var i = 0; i < System.players.length; i++) {
319        var player = System.players[i];
320
321        updateTrooper(player, "enemies");
322
323        drawLifeGauge(
324            System.screen.ctx,
325            "lighter",
326            player,
327            10,
328            (System.screen.height - 20) - (i * 33),
329            System.screen.width
330        );
331
332        drawString(
333            System.screen.ctx,
334            "source-over",
335            player.name,
336            10,
337            (System.screen.height - 23) - (i * 33),
338            "#ACF", "9pt monospace", "left"
339        );
340    }
341
342    // update/draw enemies
343    for (var i = 0; i < System.enemies.length; i++) {
344        var enemy = System.enemies[i];
345
346        updateTrooper(enemy, "players");
347
348        drawLifeGauge(
349            System.screen.ctx,
350            "lighter",
351            enemy, 10, i * 33 + 10,
352            System.screen.width
353        );
354
355        drawString(
356            System.screen.ctx,
357            "source-over",
358            enemy.name, 10, i * 33 + 33,
359            "#FCA", "9pt monospace", "left"
360        );
361    }
362
363    updateDeathPieces(System.screen.ctx,
364                      System.screen.width,
365                      System.screen.height);
366
367    if (!System.players.length) {
368        drawString(
369            System.screen.ctx, "source-over",
370            "GAME OVER",
371            System.screen.width / 2,
372            System.screen.height / 2,
373            "#ACF", "24pt monospace", "center"
374        );
375    }
376}
377
378
379/*
380 *  Initializer
381 */
382function initGame(canvas, msg, playerData) {
383    System.screen.canvas = canvas;
384    System.message       = msg;
385    System.screen.ctx    = System.screen.canvas.getContext("2d");
386    System.screen.width  = System.screen.canvas.width;
387    System.screen.height = System.screen.canvas.height;
388    System.gameOver      = false;
389
390    System.screen.ctx.globalCompositeOperation = "lighter";
391
392    if (System.mainIntervalId) {
393        clearInterval(System.mainIntervalId);
394        System.mainIntervalId = 0;
395    }
396
397    drawScreen(
398        System.screen.ctx,
399        "source-over",
400        "rgba(0,0,0,1)",
401        System.screen.width,
402        System.screen.height
403    );
404
405    System.players.push(new Trooper(
406        playerData.name,
407        new ActionList([new ManualAction(new ManualShot())]),
408        playerData.image,
409        playerData.size,
410        playerData.hitsize,
411        "#33F",
412        "#F33",
413        System.screen.width / 2,
414        System.screen.height - System.screen.height / 7,
415        System.screen.width,
416        System.screen.height,
417        playerData.hitpoint,
418        playerData.speed,
419        playerData.numbombs,
420        ["rgba(255,0,0,0.3)", "rgba(0,0,255,0.3)"],
421        [new LinerBarrage(YExtendBullet,
422                          playerData.shotsize,
423                          "rgba(64,64,128,0.7)",
424                          null,
425                          playerData.shotinterval,
426                          playerData.shotspeed,
427                          playerData.shotlevel,
428                          -0.5),
429         new LinerBarrage(YExtendBullet,
430                          playerData.shotsize,
431                          "rgba(64,64,128,0.7)",
432                          null,
433                          playerData.shotinterval,
434                          playerData.shotspeed,
435                          playerData.shotlevel,
436                          0.5),
437         new CircularBarrage(LinerBullet,
438                          playerData.shotsize,
439                          "rgba(64,64,128,0.7)",
440                          null,
441                          playerData.shotinterval,
442                          playerData.shotspeed,
443                          playerData.shotlevel + 2,
444                          -0.5)]
445    ));
446
447    for (var i = 0; i < System.players.length; i++) {
448        System.score[System.players[i].name] = 0;
449    }
450
451    System.backgroundObject = new Array();
452    System.mainIntervalId   = setInterval(mainLoop, 20);
453}
Note: See TracBrowser for help on using the repository browser.