I'm using ThreeJS to create an interaction where people can click cubes. However these cubes behave differently when clicked (different color animations, to keep the idea simple).
My idea was to create extension classes of the THREE.Mesh object and add my custom functions and attributes. This would help isolate the different behaviors of the cubes and provide a cleaner code.
I tried using John Resigs' function to extend classes, but it seems to work just for classes that ultimately extend his "Class" class.
Is there a way to do this?
There are several ways to make class-based systems in Javascript. John Resig's "Class" is a great one, but it is not the type of inheritance that Three.js uses.
Notice in the Cube class file the line:
THREE.Geometry.call( this );
Javascript does not provide a built-in model for class inheritance, so unless you are using a library (like John Resig's) that bakes inheritance into class construction, you have to call the super method explicitly.
Your class would inherit from CubeGeometry if, inside your class, you call:
THREE.CubeGeometry.call( this );
You will also likely want to set CubeGeometry to be the prototype:
THREE.MyCubeGeometry.prototype = new THREE.CubeGeometry();
THREE.MyCubeGeometry.prototype.constructor = THREE.MyCubeGeometry;
Related
This is a question about javascript and three.js coding style conventions. I prefer to use the latest ES-whatever conventions.
I'm wondering if instead of doing the usual:
var scene = new THREE.Scene();
var cube = new THREE.Mesh(new THREE.BoxGeometry(1,1,1), new THREE.MeshBasicMaterial(0xffffff))
scene.add(cube)
it would be ok to store the mesh object (and other objects, maybe lights and even camera) as properties of the scene object:
const scene = new THREE.Scene(); // or var, but that's not my question
scene.cube = THREE.Mesh(new THREE.BoxGeometry(1,1,1), new THREE.MeshBasicMaterial(0xffffff))
scene.add(scene.cube)
I like the idea of having references to all the three.js objects underneath the scene namespace -- makes it easier for me to access them later. I know I could use this with .name and .getObjectByName but that takes more code and seems messier to me.
There is a field on Object3D derived objects called .userData that you can store stuff that should get saved/serialized. But as far as storing props directly on objects.. It works.. but kinda has potential for problems if you end up overwriting something or later revs of three make use of your property name...
Edit: after reading the other posts here, they raise some good point, and I also wanted to throw out there that you can subclass the built-in three objects and make your own custom type that has your stuff. That might be tidier.
As far as separation of concern goes, you don't want to use Three's objects as data holders. It might seem like an easy way out, but will greatly reduce maintainability of your code. There is nothing preventing you from doing it today, though. Just consider, that you will have
scene.cube
scene.children[0] //same cube
scene.getObjectById(... cube id ...) //same cube
//... byName, ...byProperty etc. all pointing to the same cube
Remember, Scene extends Object3D with all its methods and properties, so, in the example scene below all objects are Object3D with each having children[] property.
[scene]
+----^-----------------------------+
[chairGroup] [light]
+--^--+-----+-----+-----+------+
[leg] [leg] [leg] [leg] [back] [seat]
Doesn't each node above look similar to DOM's Element?
I would encourage you to think about your scene as a tree. In fact, any UI is an n-tree of elements: web, mobile, X11 etc., and every UI framework is a tool to manipulate such tree. All approaches you use to manipulate DOM tree effectively work here.
Hence, below are various ways you can organize your code, from simple to more complex:
hello world rotating cube example is fine, 15-20 lines of code are ok as-is
rendering context: move scene, camera and renderer into some context object you can pass around your layers. Think of it as an equivalent of document in the browser.
high-level "Shadow DOM": organize a tree of your own components that each handle a group of 3d objects, make them react to events - external from UI clicks etc., or from Three, like visitor pattern during rendering. You can either keep references to 3d objects on these components, or recursively pass your structure to a function to adjust scene's hierarchy. Examples of such components in your tree could be Chair, Building, Planet, Starship etc.
data model: it might be tempting to store some data inside your components, but you should have a distinction between external data, usually a bit global, like numeberOfPlanets, timeOfDay etc., and internal data, like current rotation speed of a planet. Latter can be kept as part of your scene domain components.
full MVC: as with any UI, model-view-controller is applicable here. E.g. you can follow this intro into three.js MVC.
mediators, observers and usual workflows. See, e.g. my answer here.
... all the way to Redux-like immutable state management system
I hope, this answer will help people do some tactical architecture around Three.js that suits their project best.
I'm messing around with Phaser 3 in an es6 syntax. In Phaser 3 everything is now composed of Scenes, where you load/update/etc everything. So, for the primary Game scene, I extend Phaser.Scene.
export default class Game extends Phaser.Scene {
preload()
create()
...
But let's say I have a player, which will involve 100's of lines of code that I would like to keep in a separate file for code cleanliness. How do I organize that?
Every tutorial/info I find about it just includes all of the code for the scene in the same file, but this is obviously not realistic for fully fleshed-out games. I want to separate many elements of the game into their respective classes/files.
So, I just create a player class, that doesn't extend anything? Or should I extend it by something like Phaser.Sprite?
I think the reason most tutorials throw everything in one file is because:
they're geared towards beginners, who may be experiencing programming for the first time and therefore might get confused by working with multiple source files
fun games in Phaser can definitely be created in one source file
some game hosting platforms want/prefer a single JS file
To answer your specific question "So, I just create a player class, that doesn't extend anything? Or should I extend it by something like Phaser.Sprite?", it depends.
I'm working in TypeScript, so my structure and code is a bit different, but I have a src directory structure like the following:
assets
ts
Prefabs
Scenes
Game.ts
In the ts/Scenes directory I throw all of my scenes, that extend Phaser.Scene. In the ts/Prefabs directory (prefabs is something I picked up years ago from a Phaser 2 tutorial) I put any custom classes.
Looking at the game I'm working on now, I have one that extends Phaser.GameObjects.Group, three that extend off of that custom object, and then a couple that don't extend off of anything. In the past I've extended off of Phaser.Sprite as well.
The real question of whether to extend off of Phaser.Sprite or not is based upon what you want the object to do for you.
In my case I wanted to create a basic Character class that my Hero and Monster instances could extend, and that would create sprites within the game when I created them. I opted for a Group because the sprites I'm using consist of two parts, so with a Group I could add both Sprites to it when I created the object, but could have gone with a Sprite had I just needed one asset.
One of my other custom objects just stores information about the game state, so since there's nothing that actually needs to display in game when it exists, it doesn't extend anything in Phaser.GameObjects.
So the question for you is, when you create a new Player, do you want it to display as a Sprite with additional functionality/properties, or not? If the former, extend Sprite (or whatever Phaser.GamesObjects you need to. Otherwise don't.
Maybe you can try nkholski/phaser3-es6-webpack.
I'm currently developing a game this way.
What is the THREE in three.js . For example, when we create a scene or any object we qualify the name like new THREE.Scene() or new THREE.WebGLRenderer() What does THREE refer to??
THREE refers to the THREE base object which contains all of the THREE stuff like geometry, materials, methods, and well every THREE thing really.
This is like calling your homie THREE who knows how to do all the THREE things, but only THREE things. You couldn't be like, "THREE.createWebpage()" because THREE doesn't know how to do that.
THREE is named in three.js which was first released by Mr. Doob.
If this still seems confusing I would recommend you look into what an object is in programming. here is an explanation.
you can just type "THREE" in Chrome console, and you will got what you want to know
The base object of three.js - you can see the source here.
THREE stores all the properties and methods that make the library useful.
First off, I use the term "classes" to mean functions with prototypes that might be in a separate file from the main initializing file for what I'm working on.
Now for my question/issue:
I'm working on building something in JavaScript/HTML5, and trying to program it "properly" (ie. using prototypes with formats that are, I hope, standard). In my main JavaScript file, I have methods that have create use an instance (basically the root instance of my OOP/prototype based script) that sets up the canvas.
I also have another file that is loaded which contains a 'class' for creating clickable buttons. As of right now, I'm just trying to get the buttons to draw on the canvas, however, I can't access the instance of the canvas because I believe the instance is out of scope (which is fine, I don't want everything I do to contain a long dot-notation for referencing instances). However, this is giving me trouble when trying to draw a rectangle on the canvas, considering the 'class' the button is in, isn't able to reference the context outside of it.
I found a way around this by using something along the lines of:
function CreateButton(btn_x, btn_y, btn_width, btn_height, btn_txt) {
// ... (check and define parameters)
CreateButton.prototype.custom_canvas = document.getElementById('root_canvas');
CreateButton.prototype.ctxt = this.custom_canvas.getContext('2d');
CreateButton.prototype.ctxt.fillStyle = '#666666';
CreateButton.prototype.ctxt.fillRect(this.x, this.y, this.width, this.height);
}
Basically, it's writing on top of the canvas with a canvas of the same name? I'd assume that I can still manipulate the regular canvas afterwards and it would just act as if it was a single canvas element. I worried that redrawing on the canvas might use up a lot of memory when many things are added, however, no matter the method, writing on top of the canvas can't be avoided (even when in the same scope).
Any suggestions, or help? Or is my method of using the same canvas within a different class acceptable?
Thanks for any feedback.
[UPDATE]
Hmm, maybe I should try passing the context as a parameter and just using that.
...Or should I just make the canvas a global object? Any suggestions?
I guess you could try to implement some sort of "WidgetManager" that retains reference to canvas and your widgets. It will use a callback mechanism to render widgets. Each widget (ie. in this case Button) will have certain kind of rendering states (pressed, released) and some kind of internal state. Other widgets might have more complicated states.
Note that "WidgetManager" should probably keep track of widget "z" and user presses (which widget was hit). Based on this it should be able to trigger handlers bound to widgets. In a way you have to reinvent what basic UI libs do already. :)
I think you are better off by working out your design this way before moving into the implementation phase. A lot depends on what you really want to with it. :)
Note that you can simplify rendering and checks a lot by using multiple canvasii instead of just one. In this case you'll have to deal with z-index and absolute positioning but at least you get to piggyback on some of the existing stuff without having to implement it yourself.
I already make extensive use of prototype and don't want to add an extra framework like YUI.
I need a javascript calendar which enables me to customize rendering of calendar-cells on a cell by cell basis. (For rendering events, prices, etc. on a certain date) .
YUI Calendar makes this possible, but I already make extensive use of prototype and don't want to add an extra framework like YUI.
Does anyone know a good alternative?
Thanks,
Brits
Here's one: CalendarView and another CalendarDateSelect.
Have you thought of upgrading from Prototype to YUI or jQuery? Both would give you a lot more functionality than prototype and both have excellent calendar options.
If you've got the time, you can build your own. I've personally used this blog entry to create my own and it works beautifully. The code doesn't use Prototype, but as I was walking through it I converted the whole thing into a Prototype class and used all the nice features of Prototype to make the code look better. And best of all, you know exactly what the tag classes are so you can customize it completely (personally it is easier for me to code the CSS as I go rather than trying to reverse engineer a pre-built one, besides, the equivalent jQuery one may be too much or too little for what you want).
I've used jscalendar before, which works well.
As far as I know, Prototype is a collection of helper functions, but it has no widgets.
YUI is a total different beast (there's a minor overlapping in DOM methods).
We use Prototype for Ajax calls and YUI for widgets (calendar, dialogs, grid).