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

Revision 122, 14.6 KB checked in by atzm, 12 years ago (diff)

add stage bgm rotation

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