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

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