I've created a Javascript object for a Player class for a game I've been working on which "inherits" from a Collidable class using the follow line:
Player.prototype = new Collidable(50, 50, 70);
This Collidable class has an instance of a Vector class, which is instantiated in my code like:
this.pos = new Vector(x, y) || new Vector(50, 50);
My problem is that I can create a new Collidable object just fine, and the vector inside will have the values for x and y given in the first two arguments of the new Collidable(x, y, diameter) part. However, when a new Player is created (current = new Player();) the vector's values for x and y become NaN.
Below I have included the code for the Collidable constructor and Player constructor.
Collidable:
Collidable = function Collidable(x, y, d){
this.pos = new Vector(x, y) || new Vector(50, 50); // Position of centre
this.diam = d || 50; // Diameter
this.col = new Color().randomRGB(); // For debug
}
// More functions below
Player:
Player = function Player(){
this.health = 100;
this.facing = 0;
this.sprites = new Image();
this.sprites.src = "./npc-oldman1.png";
this.spriteNo = 0;
this.moveSpeed = 2;
}
Player.prototype = new Collidable(50, 50, 70);
// More functions below
I suspect this is related to this question, but haven't been able to work out what is going wrong.
My full code is availabe here. What it should do is display an image of an old man that moves to where the mouse clicks (it does flash at (50, 50) (where the Player is created) right at the beginning, or when you manually change the pos value). I have had the code working before I added the Collisions class.
Thanks in advance.
The problem seems to be a mix between Inheritance issues with nested objects and reason [not] to use the new keyword/shared properties from constructor inheritance. The solution will be
function Player(){
Collidable.call(this, 50, 50, 70); // give *this* instance an *own* Vector
this.health = 100;
this.facing = 0;
this.sprites = new Image();
this.sprites.src = "./npc-oldman1.png";
this.spriteNo = 0;
this.moveSpeed = 2;
}
Player.prototype = Object.create(Collidable.prototype); // without creating instance
Your vector.js code does this check:
if (typeof x === 'NaN' || typeof y === 'NaN')
However, typeof NaN == 'number'. You want isNaN(x), or more cryptically, x != x
Fixing that, it becomes obvious that your problem is elsewhere. This line:
var diff = new Vector(this.getCentre.x - x, this.getCentre.y - y);
Should be one of:
var diff = new Vector(this.getCentre().x - x, this.getCentre().y - y);
var diff = this.getCentre().diff(new Vector(x, y))
There are quite a few sets of missing parentheses.
Perhaps there is a different issue with your code than what you have shown. Perhaps it is out of order? I was unable to reproduce NaN, here is what I used:
html
<div>Vector</div>
<div><span>X: </span><span id="x"></span><div>
<div><span>Y: </span><span id="y"></span></div>
js
var Vector = function(x,y){
this.x = x;
this.y = y;
}
var Collidable = function Collidable(x, y, d){
this.pos = new Vector(x, y) || new Vector(50, 50);
}
var Player = function Player(){
this.health = 100;
}
Player.prototype = new Collidable(50, 50, 70);
var current = new Player();
console.log(current);
console.log(current.pos);
document.getElementById("x").innerHTML = current.pos.x;
document.getElementById("y").innerHTML = current.pos.y;
demo: http://jsfiddle.net/MuRNx/
Related
I'm trying to make a function for a skydiving game that'll make a sprite rotate left/right and then move that way depending on how angled it is, at least i would be if the object's get world centre parameter was recognised, code is as follows:
Dynamic circle creation:
function defineNewDynamicCircle(density, friction, restitution, x, y, r, objid) {
var fixDef = new b2FixtureDef;
fixDef.density = density;
fixDef.friction = friction;
fixDef.restitution = restitution;
var bodyDef = new b2BodyDef;
bodyDef.type = b2Body.b2_dynamicBody;
bodyDef.position.x = x / SCALE;
bodyDef.position.y = y / SCALE;
// This creates a new circle shape
fixDef.shape = new b2CircleShape(r/SCALE);
var thisobj = world.CreateBody(bodyDef).CreateFixture(fixDef);
thisobj.GetBody().SetUserData({id:objid})
return thisobj;
}
object initialisation:
var capsule = defineNewDynamicCircle(1.0,0.2,0.8,400,400,20,"capsule");
problematic function:
function bankleft() {
capsule.GetBody.ApplyImpulse(new b2Vec2(-0.5,0), capsule.GetBody.GetWorldCenter());
if(capsule.GetBody.GetLinearVelocity().x < -5) {
capsule.GetBody.SetLinearVelocity(new b2Vec2(-5,capsule.GetBody.GetLinearVelocity().y));
}
}
Thanks for any insights you can provide!
I created an instance of Shape using Object.create() method and tried accessing the property of Shape as follows, but the inherited property becomes undefined:
function Shape(){
this.x = 10;
this.y = 20;
}
var rectangle = Object.create(Shape);
console.log(rectangle.x) // undefined
To create an instance of a constructor, use new
var rectangle = new Shape()
May declare the shape as an object instead of function though functions are first class object in js. Create a function inside this object and return the required value from this function
var shape = {
userProperty: function(x, y) {
this.x = x || 10; // if no value of x is passed it will be 10
this.y = y || 10; // if no value of y is passed it will be 10
return {
x: this.x,
y: this.y
}
}
}
var rectangle = Object.create(shape);
console.log(rectangle.userProperty(40).x) // 40
I just started a tutorial in game development using JavaScript and HTML5. javascript.prototype has come into play many times. I can not really understand how it works. Here is a link I found with a good explanation, but I am still a little bit confused
How does JavaScript .prototype work?.
Can anyone explain this please?
Here is an example of my code:
function Enemy(){
this.srcX = 140; //gets the location of enemy in x and Y here
this.srcY = 600;
this.width = 45;//gets the enemies width and height here
this.height = 54;
this.drawX = randomRange(0, canvasWidth - this.width);
this.drawY = randomRange(0, canvasHeight - this.height);
this.centerX = this.drawX + (this.width / 2);
this.centerY = this.drawY +(this.height / 2);
//this.targetX = this.centerX;
//this.targetY = this.centerY;
//this.randomMoveTime = randomRange(4000,10000);
this.speed = 1;
//var that = this;
//this.moveInterval = setInterval(function() {that.setTargetLocation();},that.randomMOveTime);
this.isDead = false;
}
Enemy.prototype.update = function() {
//this.checkDirection();
this.centerX = this.drawX + (this.width / 2);
this.centerY = this.drawY + (this.height / 2);
}
I think the biggest confusion over prototype inheritance is that that objects inherit from their contructor's prototype via their internal [[Prototype]] property. Both are referred to as "the prototype". All functions have a default prototype property that is an empty object.
In your case:
function Enemy(){
this.srcX = 140; //gets the location of enemy in x and Y here
this.srcY = 600;
...
}
is a function that, when called with new, acts as a constructor that assigns properties to a new instance of itself. That instance has an internal [[Prototype]] property that points to Enemy.prototype.
Then:
Enemy.prototype.update = function() {
//this.checkDirection();
this.centerX = this.drawX + (this.width / 2);
this.centerY = this.drawY + (this.height / 2);
}
This assigns a new property to Enemy.prototype that is a function. So that puts an update property on the inheritance chain of all instances of Enemy, so they all inherit an update method.
So:
var enemy0 = new Enemy();
var enemy1 = new Enemy();
typeof enemy0.update // function
typeof enemy1.update // function
enemy0.update === enemy1.update // true
The test can only be true if both expressions reference the same object (i.e. the function assigned to Enemy.prototype.update).
You can continue to add properties and methods to Enemy.prototype and they will be inherited by all instances, even those already constructed. But if you change it to a different object:
Enemy.prototype = {update:function(){/*new update function*/}};
then old instances will still have the old [[Prototype]] and new instances will have the new one.
There are a million articles on the web about javascript's prototype inheritance, read a few and play with it, ask more questions if you have them. :-)
So it has been a good long while since I programmed in a functional language. I have this code functioning normally; however I dislike it due to my OOD preferences.
var canvasWidth = 900;
var canvasHeight = 200;
var canvas0;
var context0;
var x0 = 20;
var y0 = 20;
var dx0 = 4;
var dy0 = 4;
function draw() {
context0.clearRect(0, 0, context0.canvas.width, context0.canvas.height);
context0.beginPath();
context0.fillStyle = "red";
context0.arc(x0, y0, 20, 0, 2 * Math.PI, true);
context0.closePath();
context0.fill();
// Boundary Logic
if (x0 < 13 || x0 > context0.canvas.width - 13) {
dx0 = (-dx0);
}
if (y0 < 13 || y0 > context0.canvas.height - 13) {
dy0 = (-dy0);
}
x0 += dx0;
y0 += dy0;
}
function init() {
'use strict';
canvas0 = document.getElementById("gfxCanvas");
context0 = canvas0.getContext('2d');
context0.canvas.width = canvasWidth;
context0.canvas.height = canvasHeight;
setInterval(draw, 10);
}
I have tried to refactor it into more object oriented design but I am having problems with the graphics processing. I can get the ball to appear once but I can not get it to move. Here is my refactored code; be aware that it is in a mid point of refactoring so there are some clear errors due to random tinkering.
function Ball(x, y, r, color) {
this.radius = r;
this.x = x;
this.y = y;
this.color = color;
console.log("x in creation" + this.x);
console.log("y in creation" + this.y);
draw();
}
Ball.prototype.draw = function(){
context1.beginPath();
console.log("x in DRAW()" + this.x);
console.log("y in DRAW()" + this.y);
context1.fillStyle = this.color;
context1.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, true);
context1.closePath();
context1.fill();
};
Ball.prototype.move = function(dx, dy){
// Boundary Logic
if (this.x < 13 || this.x > context1.canvas.width - 13) {
dx = (-dx);
}
if (this.y < 13 || this.y > context1.canvas.height - 13) {
dy = (-dy);
}
this.x += dx;
this.y += dy;
};
function initialize() {
canvas1 = document.getElementById("gfxCanvas2");
context1 = canvas1.getContext('2d');
context1.canvas.width = 900;
context1.canvas.height = 200;
ball1 = new Ball(20,20,20, "red");
setInterval(ball1.move(4,4), 10);
}
I would preferably like this method to be the movement method. The actual method would take the direction/speed vectors.
setInterval(ball1.move(4,4), 10);
setInterval(ball1.move(4,4), 10);
This doesn't work the way you intended it: It calls ball1.move(4,4) once, then calls the result of that every 10ms. You want the move method to be called every 10ms instead, right? There are two ways to do that:
setInterval(function() {
ball1.move(4,4);
}, 10);
or like this (more elegant in my opinion):
setInterval(ball1.move.bind(ball1,4,4), 10);
You can use bind:
setInterval(ball1.move.bind(ball1, 4, 4), 10);
That is equivalent of wrapping your call to move in an anonymous function:
setInterval(function() { ball1.move(4, 4); }, 10);
Then you will also need to update move so that it calls draw appropriately too.
In addition, I would not use a global variable to access the drawing context - even if I wasn't going to go completely OOP I would make sure that the draw method and the move method take a context (which, for the sake of simplicity could be "owned" by the ball).
Thanks for all the help, everyone. You clarified everything very well and pointed me in the correct direction. I suspected it was working in the manner you articulated however I wasn't entirely sure. I knew a couple of things where wrong with my implementation but couldn't put it so succinctly with my current knowledge.
However, I discovered my problem which your solutions were remedying in a more direct manner. I can't treat javascript with OOD paradigms. I will be refactoring the code using a more functional design pattern. Not attempting to coerce the code into a OO design will make things considerably easier. Your solutions helped but the bounds checking code was the next problem I ran into.
I'l be working this into a module design pattern for the ball objects which should be much more suited for js scope/closures and procedural workflow.
Hello and thank you for your help in advance.
I am trying to push/create a new "ring" every couple seconds. I have a ring with a couple variables for the X and Y. The problem I am encountering is, how do I get a new ring and also increment the variables? I need a new variable name for every ring?
Here is how far I have gotten so far:
http://codepen.io/hossman/pen/AfwkF
You can see in the demo how 1 ring goes out, but I want more than 1 ring to go out of my eyes. So for instance 1 ring goes and then it waits a second and then shoots out another ring, so now there are 2 rings on the canvas, then 3, then 4, etc.... I have thought of multiple ways like using arrays and setTimeouts, but I cant put my finger on it. The only other idea I have is to create multiple variables with different names and have each ring be incremented, but thats not very D.R.Y.
Anyhelp?
Please ask questions if I didn't explain it good enough. Thanks again!
Add this to your global vars at the top (and set to whatever you want the distance to be between circles):
var distanceApart = 40;
Then update your main loop like this:
requestAnimationFrame(function print() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
var leftRing = new Ring(x, y);
var rightRing = new Ring(x2, y2);
var temp = startRadius;
var temp2 = 0;
while(temp > 0){
leftRing.draw(ctx, startRadius - temp2 , 'red');
rightRing.draw(ctx, startRadius - temp2 , 'red');
temp2 = temp2 + distanceApart;
temp = temp - distanceApart;
}
startRadius += increase;
requestAnimationFrame(print);
});
Forked here: http://codepen.io/anon/pen/plBmj
(Looks very memorizing!)
I would rewrite parts of your code to enable this. For example I would rewrite your Ring class as follows:
var Ring = defclass({
constructor: function (x, y, r) {
this.x = x;
this.y = y;
this.r = r;
},
draw: function (context) {
context.beginPath();
context.arc(this.x, this.y, this.r, 0, Math.PI * 2);
context.stroke();
return this;
},
addRadius: function (r) {
return new Ring(this.x, this.y, this.r + r);
}
});
Your Ring class constructor now takes x, y and a radius r. The addRadius function returns a new Ring instead of mutating the original one. This is good because immutability makes your code easier to work with. Oh, and defclass is declared as:
function defclass(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
Then we create the two rings for your eyes:
var radius = 10;
var delta = 0.1;
var left = new Ring(cx - (cx / 3.6), cy - 5, radius);
var right = new Ring(cx + (cx / 3.6), cy - 10, radius);
After that we call the animation loop:
var interval = 50 / 3;
var start = Date.now();
loop(start, [left, right]);
Since we want to playback at 60 FPS the interval is 1000 / 60 which can be simplified to 50 / 3. The animation loop is defined as follows:
function loop(last, rings) {
var next = last + interval;
context.clearRect(0, 0, width, height);
var newRings = rings.map(function (ring) {
return ring.draw(context).addRadius(delta);
});
var now = Date.now();
setTimeout(loop, next - now, next,
Math.floor((now - start) / 1000) === rings.length / 2 ?
[left, right].concat(newRings) : newRings);
}
Here's what's happening:
First we clear the screen.
Then we draw all the rings and increase their size.
If one second has elapsed we add two new rings to the array.
Finally we calculate when to call loop again so that it fires after the correct interval.
See the demo: http://jsfiddle.net/LAr76/