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

Revision 112, 12.3 KB checked in by atzm, 12 years ago (diff)

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