码迷,mamicode.com
首页 > 编程语言 > 详细

265行JavaScript代码的第一人称3D H5游戏Demo【个人总结1】

时间:2016-01-02 22:37:41      阅读:894      评论:0      收藏:0      [点我收藏+]

标签:

  本文目的是分解前面的代码。其实,它得逻辑很清楚,只是对于我这种只是用过 Canvas 画线的人来说,这个还是很复杂的。我研究这个背景天空也是搞了一天,下面就是只加载天空的代码。

在线效果点击:http://1.codemo2.sinaapp.com/3d_demo_265line/index.html   【可以用键盘“左右”键控制】【手机浏览器触控有些异常】

  原理大概就是:

1. 创建主循环  一个无限循环

2. 主循环内重复调用绘制方法

3. 绘制方法: 针对 Player 的位置和方向,绘制背景图

   其中用到了 H5 的 requestAnimationFrame(callback),bind(this, argu,...) 比较难以理解的函数。

  Player 是人物,含有平面x,y位置和方向三个特性;Controls 用来响应键盘和触屏操作;Map 是背景图还有后面的墙壁;Camera 是最重要的摄像机,用来绘制我们看到的炫酷图像;GameLoop 是整个程序的入口,一直循环调用 Camera 刷新绘制图形。

  

  1 <!--
  2 
  3 1. draw sky
  4 
  5 
  6 
  7 
  8 -->
  9 
 10 <!doctype html>
 11 <html>
 12   <head>
 13       <meta charset="utf-8">
 14     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
 15     <title>Raycaster Demo - PlayfulJS</title>
 16   </head>
 17   <body style=‘background: #000; margin: 0; padding: 0; width: 100%; height: 100%;‘>
 18     <canvas id=‘display‘ width=‘1‘ height=‘1‘ style=‘width: 100%; height: 100%;‘ />
 19 
 20     <script>
 21 
 22     var CIRCLE = Math.PI * 2;
 23     var MOBILE = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)
 24 
 25     function Controls(){
 26         this.codes  = { 37: left, 39: right, 38: forward, 40: backward };
 27         this.states = { left: false, right: false, forward: false, backward: false };
 28         document.addEventListener(keydown, this.onKey.bind(this, true), false);
 29         document.addEventListener(keyup, this.onKey.bind(this, false), false);
 30         document.addEventListener(touchstart, this.onTouch.bind(this), false);
 31         document.addEventListener(touchmove, this.onTouch.bind(this), false);
 32         document.addEventListener(toucheend, this.onTouchEnd.bind(this), false);
 33     }
 34 
 35     Controls.prototype.onTouch = function(e){
 36         var t = e.touches[0];
 37         this.onTouchEnd(e);
 38         if (t.pageY < window.innerHeight * 0.5) this.onKey(true, { keyCode: 38 });
 39         else if (t.pageX < window.innerWidth * 0.5) this.onKey(true, { keyCode: 37 });
 40         else if (t.pageY > window.innerWidth * 0.5) this.onKey(true, { keyCode: 39 });
 41     }
 42 
 43     Controls.prototype.onTouchEnd = function(e){
 44         this.states = { left: false, right: false, forward: false, backward: false };
 45         e.preventDefault();
 46         e.stopPropagation();
 47     }
 48 
 49     Controls.prototype.onKey = function(val,e){
 50         var state = this.codes[e.keyCode];
 51         if (typeof state === undefined) return;
 52         this.states[state] = val;
 53         e.preventDefault && e.preventDefault();
 54         e.stopPropagation && e.stopPropagation();
 55         // console.log(e.keyCode);
 56     }
 57 
 58     function Bitmap(url, width, height){
 59         this.image = new Image();
 60         this.image.src = url;
 61         this.width = width;
 62         this.height = height;
 63     }
 64     function Map(){
 65         this.skybox = new Bitmap(assets/deathvalley_panorama.jpg, 2000, 750);
 66     }
 67 
 68     function Player(x, y, direction){
 69         this.x = x;
 70         this.y = y;
 71         this.direction = direction;
 72     }
 73 
 74     //弧度制
 75     Player.prototype.rotate = function(angle){
 76         console.log(angle);
 77         this.direction = (this.direction + angle + CIRCLE) % (CIRCLE);
 78     }
 79 
 80     Player.prototype.update = function(controls, map, seconds){
 81         if (controls.left) {this.rotate(-Math.PI * seconds)};
 82         if (controls.right) this.rotate(Math.PI * seconds);
 83         // console.log("sdf");
 84     }
 85 
 86     
 87 
 88     //http://www.ituring.com.cn/article/50019
 89     //camera renderer scene
 90     //resolution : 分辨率
 91     function Camera(canvas, resolution , focalLength){
 92         this.ctx = canvas.getContext(2d);
 93         this.width = canvas.width = window.innerWidth * 0.5;
 94         this.height = canvas.height = window.innerHeight * 0.5;
 95         this.resolution = resolution;
 96         this.spacing = this.width / resolution;
 97         this.focalLength = focalLength || 0.8;
 98         this.range = MOBILE ? 8 : 14;
 99         this.lightRange = 5;
100         this.scale = (this.width + this.height) / 1200;
101     }
102 
103     Camera.prototype.render = function(player, map){
104         this.drawSky(player.direction, map.skybox, map.light);
105     }
106 
107     //ambient: environment light
108     Camera.prototype.drawSky = function(direction, sky, ambient){
109         var width = sky.width * (this.height / sky.height) * 2;
110         var left = (direction / CIRCLE) * -width;
111 
112         this.ctx.save();
113         this.ctx.drawImage(sky.image, left, 0, width, this.height);
114         if (left < width - this.width) {
115           this.ctx.drawImage(sky.image, left + width, 0, width, this.height);
116         }
117         this.ctx.restore();
118     }
119 
120     function GameLoop(){
121         // this.start = 
122         this.lastTime = 0;        //control FPS
123         this.frame = this.frame.bind(this);
124         this.callback = function(){};        //place holder
125     }
126 
127 
128     //requestAnimationFrame make borswer start animate,argu is callbadk
129     GameLoop.prototype.start = function(callback) {
130         this.callback = callback;
131         requestAnimationFrame(this.frame);
132         // body...
133     }
134 
135     GameLoop.prototype.frame = function(time){
136         var seconds = (time - this.lastTime) / 1000;
137         this.lastTime = time;
138         if (seconds < 0.2) this.callback(seconds);
139         requestAnimationFrame(this.frame);
140     }
141 
142 
143     var display = document.getElementById(display);
144     var player  = new Player(15.3, -1.2, Math.PI * 0.3);
145     var camera = new Camera(display, MOBILE ? 160 : 320, 0.8);
146     var map = new Map();
147     var controls = new Controls();
148     var loop = new GameLoop();
149 
150     loop.start(function frame(seconds){
151         //update map
152         // update player
153         player.update(controls.states, map, seconds);
154         // console.log("refresh..");
155         camera.render(player, map);
156     });
157 
158 
159 
160     </script>
161   </body>
162 </html>

 

265行JavaScript代码的第一人称3D H5游戏Demo【个人总结1】

标签:

原文地址:http://www.cnblogs.com/muyun/p/5095366.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!