7
\$\begingroup\$

I've been playing around with porting a simple strategy game over to Javascript, the idea being to run it in a browser for testing. I've done some simple Javascript code in the past, but this is my first model/view setup. I'd love to get feedback on following Javascript best practices and avoiding pitfalls. I know that I am falling way short of the full features of the language because I don't use any prototypes. I am using THREE.js and jQuery.js, THREE.js being the main rendering engine.

The code here simply creates a Tower that contains a Javascript version of a dictionary of Floor objects with positions. They are then rendered in the THREE.scene based on their position. The idea will be to calculate clicking on them to issue commands to the floor based on the camera position and click position, but I haven't gotten that far yet. I want to find out if I am doing things properly before I get much further. This is partly just for fun but I still want to learn how to do things the right way.

Here is the codepen. Just move the mouse up and down to move, and click to see the coordinates of the view and camera.

Here is the HTML:

<!DOCTYPE html>
<html>
<head lang="en">
 <style>
 body {
 background-color: #C0C0C0;
 margin: 0px;
 overflow: hidden;
 font-family:Monospace;
 font-size:13px;
 text-align:center;
 font-weight: bold;
 text-align:center;
 }
 div{
 background: #C0C0C0;
 }
 </style>
 <meta charset="UTF-8">
 <title></title>
</head>
<body>
 <script src="js/jquery.min.js"></script>
 <script src="js/three.min.js"></script>
 <script src = "js/three2dtest.js"></script>
</body>
</html>

And here is the Javascript Game:

var container;
var camera;
var scene;
var renderer;
var mouseX = 0;
var mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
//this is the game model object
var worldSize = new WorldSize(windowHalfX, windowHalfY);
var tower = new Tower(worldSize);
init();
//not good to do animate here
//animate();
function init() {
 container = document.createElement('div');
 document.body.appendChild(container);
 //these settings have to be very specific for the scene to work
 camera = new THREE.OrthographicCamera(window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, - 500, 1000);
 camera.position.x = 0;
 camera.position.y = 0;
 camera.position.z = 0;
 scene = new THREE.Scene();
 //fog seems to make no difference
 //scene.fog = new THREE.FogExp2(0x000000, 0.0025);
 console.log(scene);
 for (obj in tower.towerFloors) {
 //starting positions of the floors
 console.log(tower.towerFloors[obj].yposition);
 // Using wireframe materials to illustrate shape details.
 var darkMaterial = new THREE.MeshBasicMaterial({color: 0xffffcc});
 var wireframeMaterial = new THREE.MeshBasicMaterial({color: 0x000000, wireframe: true, transparent: true}); 
 var multiMaterial = [darkMaterial, wireframeMaterial];
 // create a cube for each of the floors on the tower
 var floorShape = THREE.SceneUtils.createMultiMaterialObject( 
 new THREE.CubeGeometry(500, tower.towerFloors[obj].floorSize * 10, 2, 1, 1, 1), 
 multiMaterial);
 floorShape.position.set(0, tower.towerFloors[obj].yposition * 10, 0);
 scene.add(floorShape);
 }
 renderer = new THREE.WebGLRenderer({clearColor: 0xff0000, clearAlpha: 1});
 renderer.setClearColorHex(0xC0C0C0, 1); //this is light grey
 renderer.setSize(window.innerWidth, window.innerHeight);
 container.appendChild(renderer.domElement);
 document.addEventListener('mousemove', onDocumentMouseMove, false);
 window.addEventListener('resize', onWindowResize, false);
 //should be better to start animate inside here rather than outside
 animate();
}
//position registering function
$('div').click(function(e) {
 alert(e.pageX+ ' , ' + e.pageY);
 alert (camera.position.x + ' , ' + camera.position.y);
});
function onDocumentMouseMove(event) {
 mouseX = event.clientX - windowHalfX;
 mouseY = event.clientY - windowHalfY;
}
function onWindowResize() {
 windowHalfX = window.innerWidth / 2;
 windowHalfY = window.innerHeight / 2;
 camera.aspect = window.innerWidth / window.innerHeight;
 camera.updateProjectionMatrix();
 renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
 requestAnimationFrame(animate);
 render();
}
function render() {
 //move only up and down
 //multiply by 0.15 to slow the overall scroll speed
 //camera.position.x += (mouseX - camera.position.x) * 0.15; 
 camera.position.y += (-mouseY - camera.position.y / 10) * 0.15; 
 //the camera wont move above the top floor so no bounds check needed
 if (camera.position.y < 0) {
 camera.position.y = 0;
 }
 renderer.render(scene, camera);
}
///////////////////////////////////////////////
/* Tower Objects */
///////////////////////////////////////////////
function Tower (worldSize) {
 //create the dictionary of floors
 this.towerFloors = {};
 var floorNumber = 0;
 for (floorNumber = 0; floorNumber < 50; floorNumber++) { 
 var floor = new Floor(floorNumber, worldSize);
 this.towerFloors[floorNumber] = floor;
 }
 this.testLog = "tower created and logged";
 console.log(this.testLog);
 //test methods
 for (obj in this.towerFloors) {
 console.log(this.towerFloors[obj].floorNumber);
 }
 for (obj in this.towerFloors) {
 console.log(this.towerFloors[obj].yposition);
 }
}
function Floor (floorNumber, worldSize) {
 this.floorNumber = floorNumber;
 this.floorSize = worldSize.ysize / 50;
 this.yposition = this.floorSize * floorNumber;
}
function WorldSize (xsize, ysize) {
 this.xsize = xsize;
 this.ysize = ysize;
}
ggorlen
4,1572 gold badges19 silver badges28 bronze badges
asked Jul 15, 2014 at 4:55
\$\endgroup\$
2
  • \$\begingroup\$ Is this really MVC? \$\endgroup\$ Commented Jul 29, 2014 at 15:14
  • \$\begingroup\$ By MVC I just mean that I tried to have a separation between the model that contains the game data, and its representation and rendering on the screen. So the model is the Tower "object", the view is the THREE.WebGLRenderer, and the controller is the Javascript that links them together. \$\endgroup\$ Commented Jul 29, 2014 at 15:20

1 Answer 1

3
\$\begingroup\$

From a once over:

  • HTML looks clean, though your title should not be blank per the HTML spec
  • Your objects look fine, old skool JS OO, which is nice to read
  • When you write for (obj in this.towerFloors) { you are polluting the global namespace, either declare obj on top in your function (my favourite approach) or use for (var obj in this.towerFloors) { , but only the first time you use obj otherwise JsHint throw warnings for duplicate declarations
  • There is not much functionality to review really, I hope that you got further with this and post a new question with more meat.
answered Nov 14, 2014 at 16:08
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.