Wiceng404

game

Oct 4th, 2013
342
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.45 KB | None | 0 0
  1. <style type='text/css'>
  2. body{background:#000;margin:0;padding:0}
  3. #score_bord{position:absolute;left:0;top:0;z-index:1;padding:5px;color:#666;font-size:14px;font-family:Verdana, Geneva, sans-serif;}
  4. #message{
  5. font-family:Verdana, Geneva, sans-serif;
  6. position:absolute;
  7. right:0;
  8. bottom:0;
  9. z-index:20;
  10. color:#C00;
  11. font-size:11px;
  12. }
  13.  
  14. .pause {
  15. background-color:#000;
  16. left:0;
  17. top:0;
  18. height:100%;
  19. width:100%;
  20. }
  21. canvas{z-index:0;}
  22.  
  23. </style>
  24. <div id="score_bord"></div>
  25. <div id="message"></div>
  26. <canvas id="hell"></canvas>
  27.  
  28. <script type='text/javascript'>//<![CDATA[
  29. /**
  30. * Typing Blood
  31. *
  32. * ランダムに落ちてくる文字をタイプするだけのタイピングゲーム
  33. * パーティクル・グラデーション・テキスト・ライン・ context.shadow・キーイベントの組み合わせ
  34. * スコア計算とレベルアップロジックは真面目にテストしてないので超適当です
  35. *
  36. * [enter] Start/Resume
  37. * [space] Pause
  38. */
  39.  
  40. //MooTools $random
  41. function _random(Min, Max){
  42. return Math.floor(Math.random() * (Max - Min + 1) + Min);
  43. }
  44.  
  45. var TypingBlood = function(){
  46. var game = {
  47.  
  48. canvas:null,
  49. context:null,
  50. playing : false,
  51. loop_timer:null, //タイマーの棺桶
  52.  
  53. bones:[],//テキストオブジェクト入れる
  54. powders:[],
  55.  
  56. karma:0, //カルマ
  57.  
  58. bloodPondLineHeight:10,//1ミスあたりの高さ
  59. bloodPondHeight:0,
  60. bloodPondAlpha:1,
  61. bloodParticles:[],
  62.  
  63. scoreBord:null,
  64. level:1,//難易度
  65. miss:0,
  66. pass:0,
  67. totalScore:0,
  68. combo:0,
  69.  
  70. ascii : [48,49,50,51,52,53,54,55,56,57,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],//ASCII CODE
  71.  
  72. //イベントリスナー
  73. addEvent:function(obj, type, fn){
  74. if(obj.addEventListener)
  75. obj.addEventListener( type, fn, false );
  76. },
  77.  
  78. //実行関数。引数はcanvasのID
  79. load:function(id){
  80.  
  81. this.addEvent(window, 'load', function(event){
  82.  
  83. game.canvas = document.getElementById(id);
  84. game.scoreBord = document.getElementById("score_bord");
  85. game.message = document.getElementById("message");
  86.  
  87. if (game.canvas.getContext){
  88. game.context = game.canvas.getContext('2d');
  89. game.setCanvas();
  90.  
  91. game.setPondSize();
  92. game.title();
  93.  
  94. }
  95.  
  96. });
  97.  
  98. //画面がリサイズされたら
  99. this.addEvent(window, 'resize', function(){
  100. game.setCanvas();
  101. if(!game.playing) game.title();
  102. });
  103.  
  104. //pause
  105. this.addEvent(window,'blur', function(e){
  106. game.pause();
  107. });
  108.  
  109. //キー押されたとき
  110. this.addEvent(document,'keydown', function(e){
  111.  
  112.  
  113. if(e.keyCode==32){
  114. game.pause();
  115. }
  116.  
  117. //再開
  118. if(e.keyCode==13){
  119.  
  120. if(!game.loop_timer && game.totalScore === 0){//start
  121. game.play();
  122.  
  123. }else if(!game.playing && game.loop_timer){//gameover
  124. game.level=1;
  125. game.miss=0;
  126. game.pass=0;
  127. game.karma=0;
  128. game.totalScore=0;
  129. game.combo=0;
  130. game.bloodPondAlpha =1;
  131. game.score();
  132. game.setPondSize();
  133.  
  134. clearInterval(game.loop_timer);
  135. game.play();
  136.  
  137. }else if(!game.playing){//pause
  138. game.play();
  139. }
  140.  
  141. }
  142.  
  143. var index = game.searchString(e.keyCode);
  144.  
  145. if(index!==false){
  146. game.bones[index].clear = true;
  147. game.pass++;
  148. game.combo++;
  149. game.karma++;
  150. game.totalScore += 100;
  151. }else{
  152. game.miss++;
  153. game.combo=0;
  154. game.karma-=2;
  155. game.totalScore -= 100;
  156. game.bloodPondHeight+= game.bloodPondLineHeight;//池拡張
  157. }
  158.  
  159. });
  160.  
  161. },
  162.  
  163. //池のサイズセット
  164. setPondSize:function(){
  165. game.bloodPondLineHeight = Math.floor(game.height/100);
  166. game.bloodPondHeight = Math.floor((game.height/100)-game.bloodPondLineHeight)*100;
  167. },
  168.  
  169. //亡者よ眠れー
  170. pause:function(){
  171.  
  172. if(game.playing){
  173. game.message.className = "pause";
  174. game.message.innerHTML = '<p style="color:#fff;position:absolute;top:50%;left:0;width:100%;margin-top:-40px;text-align:center;font-size:20px;">Typing Blood<br/>- Pause -<br />push enter key</p>';
  175. }
  176.  
  177. clearInterval(game.loop_timer);
  178. game.playing = false;
  179. game.loop_timer = null;
  180. },
  181.  
  182. //ふっかつのじゅもん
  183. play:function(){
  184. game.playing = true;
  185. game.message.className = "";
  186. game.message.innerHTML = 'Press [space] to pause, [enter] to resume...';
  187. game.loop_timer = setInterval(function(){game.loop();}, 1000/60);
  188.  
  189. },
  190.  
  191. //タイトル表示(もっさり感とともに)
  192. title:function(){
  193.  
  194. game.context.save();
  195. game.context.font = "42px 'Arial'";
  196. var str = "Typing Blood";
  197. tm = game.context.measureText(str);
  198.  
  199. game.context.save();
  200. game.context.fillStyle = "red";
  201. game.context.shadowColor = "#ff0000";
  202. game.context.shadowBlur = 10;
  203. game.context.fillText(str, game.width/2-tm.width/2, game.height/2-80);
  204. game.context.restore();
  205.  
  206. game.context.font = "30px 'Arial'";
  207.  
  208. game.context.fillStyle = "#fff";
  209.  
  210. str = "[enter] Game start";
  211. tm = game.context.measureText(str);
  212. game.context.fillText(str, game.width/2-tm.width/2, game.height/2+20);
  213.  
  214. game.context.font = "11px 'Arial'";
  215.  
  216. str = "落ちてくる文字と同じキーをタイプすると文字を粉砕して血の池に沈むのを防ぎます。";
  217. tm = game.context.measureText(str);
  218. game.context.fillText(str, game.width/2-tm.width/2, game.height/2+60);
  219.  
  220. str = "画面が全て血色に染まったらゲームオーバーです。";
  221. tm = game.context.measureText(str);
  222. game.context.fillText(str, game.width/2-tm.width/2, game.height/2+75);
  223.  
  224. game.context.restore();
  225. },
  226.  
  227. //Canvasのセッター
  228. setCanvas:function(){
  229. game.width = window.innerWidth;
  230. game.height = window.innerHeight;
  231. game.canvas.height = game.height;
  232. game.canvas.width = game.width;
  233. game.canvas.style.backgroundColor="#000";
  234. game.canvas.style.position = 'absolute';
  235. game.canvas.style.top ="0px";
  236. game.canvas.style.left="0px";
  237. game.bloodPondLineHeight = Math.round(game.height/100);
  238. },
  239.  
  240. //骨と言う名のテキスト作成
  241. createText:function(){
  242. var c = game.ascii[_random(0, game.ascii.length-1)];
  243. var x = Math.floor(_random(35, game.width-35));
  244. var y = (game.level>1)? Math.floor( 0 - 20 * (Math.random()*7) ):0;
  245. var t = {
  246. code : c,
  247. text : String.fromCharCode(c),
  248. x : x,
  249. y : y,
  250. powder:null,
  251. clear:false
  252. };
  253.  
  254. game.bones.push(t);
  255. },
  256.  
  257. /** 文字検索
  258. * @code event.keyCode
  259. */
  260. searchString:function(code){
  261. for (var key in game.bones){
  262. if (game.bones[key].code == code) return key;
  263. }
  264.  
  265. return false;
  266. },
  267.  
  268. /*血の池地獄という名のグラデを作成
  269. *@a alpha
  270. */
  271. createBloodPond:function(a){
  272. var h = game.height-game.bloodPondHeight;
  273. a = (a<=0)? 0:a;
  274. game.context.save();
  275. var g = game.context.createLinearGradient(0, h, 0, game.width);
  276. g.addColorStop(0,'rgba('+game.bloodPondHeight+', 0, 0, '+a+')');
  277. g.addColorStop(1,'rgba('+game.bloodPondLineHeight+', 0, 0, '+a+')');
  278. game.context.fillStyle = g;
  279.  
  280. game.context.beginPath();
  281. game.context.rect(0, h, game.width, game.height);
  282. game.context.fill();
  283.  
  284. //水面
  285. game.context.shadowColor = "#ff0000";
  286. game.context.shadowBlur = 5;
  287. game.context.strokeStyle = 'rgb('+(game.bloodPondHeight+60)+',0,0)';
  288. game.context.beginPath();
  289. game.context.lineTo(0, h);
  290. game.context.lineTo( game.width, h);
  291. game.context.stroke();
  292. game.context.restore();
  293.  
  294. },
  295.  
  296. //血しぶきパーティクル作成
  297. createBloods:function ( x, y ) {
  298. var end = 10 + ( Math.random() * 15 );
  299.  
  300. while( end >= 0 ) {
  301. var p = {
  302. x: x,
  303. y: y,
  304. vx:Math.random() * 0.5,
  305. vy:Math.random() * 1 - 6.7,
  306. r: -4 + Math.random() * 8,
  307. alpha : 1
  308. };
  309.  
  310. game.bloodParticles.push( p );
  311. end--;
  312. }
  313. },
  314.  
  315. //骨粉砕パーティクル作成
  316. createPowder:function(x, y){
  317. var q = 20 + ( Math.random() * 15 );
  318. var a = [];
  319.  
  320. while( q >= 0 ) {
  321. var p = {
  322. x: Math.floor(x +( Math.sin(q) * 0.03 )),
  323. y: Math.floor(y + Math.cos(q) * 10 ),
  324. vx:-4 + Math.random() * 8,
  325. vy:-4 + Math.random() * 8,
  326. alpha : 1
  327. };
  328.  
  329. game.powders.push(p);
  330. q--;
  331. }
  332.  
  333. },
  334.  
  335. //ループ
  336. loop:function(){
  337.  
  338. game.context.save();
  339.  
  340. //テキスト作成
  341. if((game.bones.length < 1 * game.level) && game.playing){
  342. game.createText();
  343. }
  344.  
  345. game.context.clearRect(0,0, game.width, game.height);
  346. var borderLine = game.height-game.bloodPondHeight;
  347.  
  348. //テキスト動かす
  349. for(i=0; i < game.bones.length; i++){
  350. var e = game.bones[i];
  351.  
  352. if(e.y < borderLine){
  353. e.y = e.y + 2;
  354. }else{
  355. e.y = e.y + 0.3;
  356. }
  357.  
  358. game.context.font = "30px 'Arial'";
  359. game.context.fillStyle = "#fff";
  360. game.context.fillText(e.text, e.x, e.y);
  361.  
  362. if(e.clear){//粉砕フラグ立ってたら
  363.  
  364. game.bones.splice( i, 1 );//削除
  365. game.createPowder(e.x, e.y);
  366.  
  367. if(game.bloodPondHeight!==0) game.bloodPondHeight -= game.bloodPondLineHeight;//池縮小
  368.  
  369. }else if(e.y >= (borderLine+20)) {//高さ超えたら
  370.  
  371. game.bloodPondHeight+= game.bloodPondLineHeight;//池拡張
  372.  
  373. game.bones.splice( i, 1 );//削除
  374. game.miss++;
  375. game.karma-=3;
  376. game.totalScore-=100;
  377. game.createBloods(e.x, borderLine);//血飛沫作成
  378. }
  379. }
  380.  
  381. if( game.bloodPondHeight >= game.height) {
  382. game.playing = false;
  383. }
  384.  
  385.  
  386. //骨粉ぶわー
  387. for( b = 0; b < game.powders.length; b++ ) {
  388. powder = game.powders[b];
  389.  
  390. powder.x += powder.vx;
  391. powder.y += powder.vy;
  392.  
  393. powder.alpha -= 0.02;
  394.  
  395. game.context.save();//fillStyle混じるからセーブしとく
  396. game.context.fillStyle = 'rgba(255,255,255,'+Math.max(powder.alpha,0)+')';
  397. game.context.fillRect( powder.x, powder.y, 2, 2);
  398. game.context.restore();
  399.  
  400. if( powder.alpha <= 0 ) {
  401. game.powders.splice( b, 1 );
  402. }
  403. }
  404.  
  405. //血飛沫ばしゃー
  406. for( k = 0; k < game.bloodParticles.length; k++ ) {
  407. p = game.bloodParticles[k];
  408.  
  409. p.vy += 0.5;//おっとそこまでだ
  410.  
  411. p.x += p.vx + p.r;
  412. p.y += p.vy ;
  413.  
  414. p.alpha -= 0.01;
  415.  
  416. game.context.save();//血の池のfillStyleと混じるからセーブしとく
  417. game.context.fillStyle = 'rgba(255,0,0,'+Math.max(p.alpha,0)+')';
  418. game.context.fillRect( p.x, p.y, 3, 3 );
  419. game.context.restore();
  420.  
  421. if( p.alpha <= 0 ) {
  422. game.bloodParticles.splice( k, 1 );
  423. }
  424. }
  425.  
  426. if(!game.playing){
  427. game.bloodPondAlpha -= 0.01;//血の池地獄の透明度
  428. game.endroll();
  429. }
  430.  
  431. game.createBloodPond(game.bloodPondAlpha);
  432.  
  433. game.context.restore();
  434.  
  435. game.score();
  436.  
  437. if(game.bloodPondAlpha <= 0) {//透けたら停止
  438. clearInterval(game.loop_timer);
  439. }
  440. },
  441.  
  442. //ゲームオーバー表示
  443. endroll:function(){
  444. game.context.save();
  445. game.context.font = "42px 'Arial'";
  446. game.context.fillStyle = "#fff";
  447.  
  448. str = "Game Over";
  449. tm = game.context.measureText(str);
  450.  
  451. game.context.fillText(str, game.width/2-tm.width/2, 200);
  452. game.context.font = "24px 'Arial'";
  453.  
  454. str = "[enter] Restart game";
  455. tm = game.context.measureText(str);
  456. game.context.fillText(str, window.innerWidth/2-tm.width/2, 250);
  457. game.context.restore();
  458.  
  459. },
  460.  
  461. //スコア計算と表示(超適当)
  462. score:function(){
  463.  
  464. var c = Math.floor((game.pass+game.combo-game.miss+game.karma)/13.5);
  465.  
  466. if(c>0) game.level = c;
  467.  
  468. var html = "Miss:"+game.miss+" Passed:"+game.pass+" Combo:"+game.combo+" Level:"+game.level+" Score:"+game.totalScore;
  469. game.scoreBord.innerHTML = html;
  470. }
  471.  
  472. };
  473.  
  474. return game;
  475.  
  476. };
  477.  
  478. var typing = new TypingBlood();
  479. typing.load('hell');
  480.  
  481. //]]>
  482. </script>
Advertisement
Add Comment
Please, Sign In to add comment