Canvas entity constructor - javascript

i'm trying to make a sort of constructor so it will be easier in the future to create entities. now i got the first couple things done to make a player but it's not seeing the functions inside of the entity function.
My error : Cannot read property 'update' of undefined
My code :
(function () {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var entity = function(type,x,y,vx,vy,life) {
var self = {
x : canvas.width / 2,
y : canvas.height / 2,
vx : 5,
vy : 5,
life : 100,
pressingDown : false,
pressingUp : false,
pressingLeft : false,
pressingRight : false
};
if(self.type == 'player') {
alert('we got a player');
};
self.update = function(){
self.updatePosition();
self.draw();
};
self.updatePosition = function(){
console.log('position');
};
self.draw = function(){
console.log('drawing');
};
};
var actor = function(type,x,y,vx,vy,life) {
var self = entity(type, 25, 25, 5, 5, 100);
return self;
};
var Player = function() {
var p = actor('player', 25, 25, 5, 5, 100);
p.pressingDown = false;
p.pressingUp = false;
p.pressingLeft = false;
p.pressingRight = false;
};
var update = function(){
player.update();
};
var player = new Player();
setInterval(function(){
update();
},30)
})();
Can anyone spot what i'm doing wrong here? THANKS ALOT!

Player has no update method please notice you are using new in thix context
var Player = function() {
var p = actor('player', 25, 25, 5, 5, 100);
p.pressingDown = false;
p.pressingUp = false;
p.pressingLeft = false;
p.pressingRight = false;
this.update = p.update; //<<<<< here
};
var update = function(){
player.update();
};
var player = new Player();
also I want to add you should stick to one method of creating objects
var Entity = function(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
var e = new Entity(1,2,3);
or
var entity = function(x, y, z) {
var obj {
x: x,
y: y,
z: z
}
return obj;
}
var e = entity(1,2,3);
otherwise your code will be more and more unreadable and you'll end with problems like that more often

Related

Game components won't draw after adding if/else statement

My game components won't draw onto the canvas after adding if/else statement.
The statement only checks if the game piece hit the game obstacle.
I tried changing attributes and rewrite some functions but it seems the problem hasn't been fixed.
Whenever I remove the if/else function, the components draw.
Here is part of the code that holds that if/else function:
if(gamePieceBorder.crashGame(gameObstacle) || gamePieceRed.crashGame(gameObstacle))
{
gameArea.stop();
}
else
{
obstacle.update();
gamePieceBorder.pos();
gamePieceBorder.move();
gamePieceBorder.update();
gamePieceRed.pos();
gamePieceRed.move();
gamePieceRed.update();
gameArea.clear();
}
For me not pasting an entire code, here is the pastebin link to the code: https://pastebin.com/HuiR7r7D
How can I get the components to draw? If someone fixes the code, what was the issue? I am not an expert at javascript but only a beginner.
There are several problems:
window.EventListener should be window.addEventListener
keyup and keydown should have no upper case letters
gameObstacle in that if is undefined (should be obstacle probably)
clear method should be called before drawing, not after it
Here is the corrected script: https://pastebin.com/bXpQ2qvB
//-----------------------------------------Variables
var gamePieceRed;
var gamePieceBorder;
var gameObstacle;
//-----------------------------------------
//-----------------------------------------Main game function
function startGame()
{
gamePieceRed = new component(22, 22, "rgb(255, 132, 156)", 10, 120);
gamePieceBorder = new component(24, 24, "black", 9, 119);
obstacle = new component(10, 200, "rgb(64, 0 ,12)", 300, 120)
gameArea.start();
}
//-----------------------------------------
//-----------------------------------------Creating game area and applying controls
var gameArea =
{
canvas : document.createElement("canvas"), start : function()
{
this.canvas.width = 510;
this.canvas.height = 280;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.interval = setInterval(gameUpdate, 20);
window.addEventListener("keydown", function (e)
{
gameArea.keys = (gameArea.keys || []);
gameArea.keys[e.keyCode] = true;
}, true)
window.addEventListener("keyup", function (e)
{
gameArea.keys[e.keyCode] = false;
}, true)
},
clear : function()
{
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
stop : function()
{
clearInterval(this.interval);
},
keyboard: function() {
if (this.keys) {
if (this.keys[37]) {gamePieceBorder.speedX = gamePieceRed.speedX = -2;}
else if (this.keys[39]) {gamePieceBorder.speedX = gamePieceRed.speedX = 2;}
else {gamePieceBorder.speedX = gamePieceRed.speedX = 0;}
if (this.keys[38]) {gamePieceBorder.speedY = gamePieceRed.speedY = -2;}
else if (this.keys[40]) {gamePieceBorder.speedY = gamePieceRed.speedY = 2;}
else {gamePieceBorder.speedY = gamePieceRed.speedY = 0;}
}
}
}
//-----------------------------------------
//-----------------------------------------Game component
function component(width, height, color, x, y)
{
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.speedX = 0;
this.speedY = 0;
this.update = function()
{
ctx = gameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height)
}
this.move = function()
{
this.x += this.speedX;
this.y += this.speedY;
}
this.crashGame = function(obj)
{
var left = this.x;
var right = this.x + (this.width);
var top = this.y;
var bottom = this.y + (this.height);
var otherLeft = obj.x;
var otherRight = obj.x + (obj.width);
var otherTop = obj.y;
var otherBottom = obj.y + (obj.height);
var crash = true;
if (bottom < otherTop || top > otherBottom || right < otherLeft || left > otherRight)
{
crash = false;
}
return crash;
}
}
//-----------------------------------------
//-----------------------------------------Game area updater
function gameUpdate()
{
if(gamePieceBorder.crashGame(obstacle) || gamePieceRed.crashGame(obstacle))
{
gameArea.stop();
}
else
{
gameArea.clear();
obstacle.update();
gameArea.keyboard();
gamePieceBorder.move();
gamePieceBorder.update();
gamePieceRed.move();
gamePieceRed.update();
}
}
//-----------------------------------------
<html>
<style>
canvas
{
border: 1px solid #d3d3d3;
background-image: url("https://ak0.picdn.net/shutterstock/videos/22492090/thumb/1.jpg");
}
</style>
<body onload = "startGame()">
</body>
</html>

Text not showing on canvas in HTML5

I am trying to display text on the screen and it's not working for me.
Here is some of my code you give you an idea on what I made:
duck.js
class duck {
constructor (canvas, logs = false, start = () => {}, update = () => {}) {
document.documentElement.style.overflowX = 'hidden';
self.canvas = canvas;
self.ctx = self.canvas.getContext('2d');
self.logs = logs;
self.keys = {};
window.onkeyup = (e) => self.keys[e.keyCode] = false;
var dpi = window.devicePixelRatio;
var style_height = +getComputedStyle(self.canvas).getPropertyValue("height").slice(0, -2);
var style_width = +getComputedStyle(self.canvas).getPropertyValue("width").slice(0, -2);
self.canvas.setAttribute('height', style_height * dpi);
self.canvas.setAttribute('width', style_width * dpi);
self.init = () => {
var a;
self.logs ? console.info('Duck initialized!') : a = 0;
};
self.init.call();
start();
setInterval(update, 1);
};
rect (x = 0, y = 0, w = 1, h = 1, color = "#FFFFFF", fill = true) {
self.ctx.fillStyle = color;
fill ? self.ctx.fillRect(x, y, w, h): self.ctx.strokeRect(x, y, w, h);
}
fill (color = "#000000") {
self.ctx.fillStyle = color;
self.ctx.fillRect(0, 0, canvas.width, canvas.height);
}
text (x = 0, y = 0, text = 'Hello world!', align='left', font = '16px Verdana', color = '#000000') {
self.ctx.font = font;
console.log(self.ctx.font)
self.ctx.fillStyle = color;
console.log(self.ctx.fillStyle);
self.ctx.textAlign = align;
console.log(self.ctx.textAlign)
self.ctx.fillText(text, x, y);
}
get getWidth() {
return canvas.width;
}
get getHeight() {
return canvas.height;
}
screenshot() {
var image = self.canvas.toDataURL('image/png').replace("image/png", "image/octet-stream");
window.location.href = image;
}
keyDown(key = 'q') {
if (self.keys[key]) {return true} else {return false};
}
}
index.js
let duck_core = new duck(document.getElementById('main'), true, start, update);
function start() {
console.log('test');
}
function update() {
duck_core.fill('#FFFFFF');
duck_core.rect(0, 0, duck_core.getWidth, 10, '#222222');
duck_core.text(0, 0);
if (duck_core.keyDown('q')) {
duck_core.screenshot();
}
}
The reason why it wasn't showing is that the text has the center point on the bottom left corner and not the top right corner. To fix this, I added t the y position the size of my text, in this case, 16px.
Change self to this inside your duck class. In JavaScript, the global self variable is a reference to the window object, meaning it doesn't point to the instance of your class:
MDN
EDIT
You also have to update these parts:
get getWidth() {
return this.canvas.width; // added "this"
}
get getHeight() {
return this.canvas.height; // added "this"
}

Access object inside object without using function to get it?

I want to access an object but I don't know how.
I want to access 'ctx', but using base.ctx always returns null (is this a closure?).
window.base = function () {
var c = null,
ctx = null;
window.addEventListener("load", function(){
c = document.getElementById("canvas");
ctx = c.getContext("2d");
}
}
I found the solution was to call a function in base that returned ctx.
window.base = function () {
var c = null,
ctx = null;
window.addEventListener("load", function(){
c = document.getElementById("canvas");
ctx = c.getContext("2d");
}
return {
ctx: function(){return ctx;}
};
}
Then I can access ctx, but now all my accesses need to be:
base.ctx().setStyle = "white";
Rather than what I'd like which is:
base.ctx.setStyle = "white";
Is it possible? I'm thinking there's a possible solution with 'this'/scope or something, but I don't know enough JavaScript yet.
base is a function.
use it like this:
base().ctx()
I would write your code in this way:
window.addEventListener('load', function () {
var base = function () {
return document.getElementById("canvas").getContext("2d");
}
// Do something with base()
});
You can also drop the function and just use the context:
window.addEventListener('load', function () {
var base = document.getElementById("canvas").getContext("2d");
// Do something
});
The answer for me was to store the values in an object called "inter", and then update the contents of that object - the changes were then visible to other code.
So then I could use:
base.ctx.fillStyle = "white";
I have no idea why the other way didn't work!
var base = function () {
var fps = 60,
canvasWidth = 300,
canvasHeight = 200,
scaling = 1;
function updateCanvas(){
ctx.putImageData(imageData, 0, 0);
}
var c = null,
cStyle = null,
updateGraphicsCallBack = null;
function initialiseCanvas(canvasName, theCallBack){
updateGraphicsCallBack = theCallBack;
c = document.getElementById(canvasName);
cStyle = c.style;
inter.ctx = c.getContext("2d");
inter.imageData = inter.ctx.getImageData(0, 0, canvasWidth, canvasHeight);
inter.imageArray = inter.imageData.data;
inter.buff8 = new Uint8ClampedArray(inter.imageArray.buffer);
inter.buff32 = new Uint32Array(inter.imageArray.buffer);
cStyle.width = canvasWidth * scaling + "px";
cStyle.height = canvasHeight * scaling + "px";
c.width = canvasWidth;
c.height = canvasHeight;
inter.ctx.imageSmoothingEnabled = true;
inter.ctx.fillStyle="#909090";
//mouse = (typeof window.mouseInit !== "undefined") ? window.mouseInit(c) : null;
//if(typeof window.db !== "undefined") window.db.setOutput("debugOutput");
requestAnimationFrame(drawLoop);
}
var oldTimeStamp = 0, timeTweak = 0;
function drawLoop(currentTimeStamp) {
currentTime = currentTimeStamp;
if(typeof timeChart !== "undefined") timeChart.start();
setTimeout(
function() {
requestAnimationFrame(drawLoop);
}, (1000 - ((currentTimeStamp - oldTimeStamp) - timeTweak)) / fps);
updateGraphicsCallBack(currentTimeStamp);
if(typeof timeChart !== "undefined") {
timeChart.end();
if(timeChart.currentFrameCount() > -1){
var difference = timeChart.currentFrameCount() - fps;
timeTweak += difference;
if(timeTweak<-10000) timeTweak = -10000;
if(timeTweak>10000) timeTweak = 10000;
}
inter.timeTweak = timeTweak;
}
oldTimeStamp = currentTimeStamp;
}
var inter = {
updateCanvas: updateCanvas,
ctx: null,//function(){return ctx;},
canvasWidth: canvasWidth,
canvasHeight: canvasHeight,
fps: fps,
scaling: scaling,
imageData: null,
imageArray: null,
buff8: null,
buff32: null,
timeTweak: timeTweak,
initialiseCanvas: initialiseCanvas
};
return inter;
}();

JavaScript add too var in object every frame not working

So i have a object named Paddle and it has a var in it called posX and for some reason i cant just add one to it every frame but i can set its value, here is my coed
https://jsfiddle.net/noig/s9yxx13q/
var Paddle = function(sizeX, sizeY){
var posX, posY;
var sizeX, sizeY;
this.sizeX = sizeX;
this.sizeY = sizeY;
this.shape = new createjs.Shape();
}
Paddle.prototype.update = function(){
this.shape.x = this.posX;
};
var paddle1 = new Paddle(25, 75);
function init(){
var stage = new createjs.Stage("canvas");
//shape = new createjs.Shape();
paddle1.shape.graphics.beginFill("blue").drawRect( 15, 0, paddle1.sizeX, paddle1.sizeY);
stage.addChild(paddle1.shape);
stage.update();
createjs.Ticker.setFPS(60);
createjs.Ticker.addEventListener('tick', stage);
createjs.Ticker.addEventListener('tick', update);
}
function update(){
//paddle1.update(); This runs the code to make shape.x = posX
//paddle1.shape.x++; This moves paddle 1 every frame when not useing paddle.update();
//paddle1.posX = 50; This moves to the paddel50 units with paddle1.update();
//paddle1.posX++; This dose not move the paddle 1 unit every frame
//paddle1.posX += 1; This dose not move the paddle 1 unit ever frame
//paddle1.posX = paddle1.posX + 1; This dose not move the paddle 1 unit every frame
}
init();
It sounds like you want to update this.shape.x when you set this.posX. One way to do that is to define a property with getter/setter. Try adding this:
Object.defineProperty(Paddle.prototype, "posX", {
get: function() {return this.shape.x},
set: function(x) { this.shape.x = x; }
});
Object.defineProperty(Paddle.prototype, "posY", {
get: function() {return this.shape.y},
set: function(y) { this.shape.y = y; }
});
var Paddle = function(sizeX, sizeY){
this.sizeX = sizeX;
this.sizeY = sizeY;
this.shape = new createjs.Shape();
}
Object.defineProperty(Paddle.prototype, "posX", {
get: function() {return this.shape.x},
set: function(x) { this.shape.x = x; }
});
Object.defineProperty(Paddle.prototype, "posY", {
get: function() {return this.shape.y},
set: function(y) { this.shape.y = y; }
});
var paddle1 = new Paddle(25, 75);
function init(){
var stage = new createjs.Stage("canvas");
//shape = new createjs.Shape();
paddle1.shape.graphics.beginFill("blue").drawRect( 15, 0, paddle1.sizeX, paddle1.sizeY);
stage.addChild(paddle1.shape);
stage.update();
createjs.Ticker.setFPS(60);
createjs.Ticker.addEventListener('tick', stage);
createjs.Ticker.addEventListener('tick', update);
}
function update(){
paddle1.posX++;
}
init();
<script src="https://code.createjs.com/createjs-2015.05.21.min.js"></script>
<canvas id="canvas"></canvas>

Loading Images from a Canvas

I'm trying to make a game in HTML5 and I'm having trouble loading image assets. My issue is that the onload event of the code isn't firing and so the boolean isn't changing.
var c = document.getElementById("gamearea");
var gs = c.getContext("2d");
var one_x = 0;
//Sprite Loading//
function sprite(src,x, y, width, height, frames, levels) {
this.sprite = Image();
this.sprite.src = src;
this.x = x;
this.y = y;
this.w = width;
this.h = height;
this.f = frames;
this.l = levels;
this.cf = 0;
this.cl = 0;
this.loaded = false;
this.src = src;
}
sprite.prototype.draw = function () {
if (this.loaded) {
document.getElementById("ass").innerHTML = "Ass";
gs.drawImage(this.src, this.x, this.y);
}
}
dog = new sprite("/images/sDog.png", 10, 10, 10, 10, 1, 1);
dog.sprite.onload = function () {
alex.loaded = true;
}
setInterval(alex.draw, 30);
I would suggest putting the onload event before the set event for your dog sprite image object. I see that you set everything in the constructor, but I would suggest against that.
In you current code you object is being loaded before the line that initializes the onload event.
I have seen this a lot with loading images, I would do something like this.
function sprite(src,x, y, width, height, frames, levels) {
var self = this;
self.sprite = new Image();
self.init = function(){
self.sprite.src = src;
self.x = x;
self.y = y;
self.w = width;
self.h = height;
self.f = frames;
self.l = levels;
self.cf = 0;
self.cl = 0;
self.loaded = false;
self.src = src;
}
}
dog = new sprite();
dog.sprite.onload = function () {
alex.loaded = true;
}
dog.init("/images/sDog.png", 10, 10, 10, 10, 1, 1);
setInterval(alex.draw, 30);
or, to get a little fancier
function sprite(src,x, y, width, height, frames, levels, onLoad) {
var self = this;
self.sprite = new Image();
self.sprite.onload = function(){
onLoad();
}
self.sprite.src = src;
self.x = x;
self.y = y;
self.w = width;
self.h = height;
self.f = frames;
self.l = levels;
self.cf = 0;
self.cl = 0;
self.loaded = false;
self.src = src;
}
dog = new Sprite("/images/sDog.png", 10, 10, 10, 10, 1, 1, function(){
alex.loaded = true;
});
setInterval(alex.draw, 30);
after looking at your fiddle
var c = document.getElementById("gamearea");
var gs = c.getContext("2d");
var one_x = 0;
//Sprite Loading//
function sprite(src, x, y, width, height, frames, levels, loaded) {
var self = this;
self.sprite = new Image();
self.sprite.onload = function(){
self.loaded = true;
}
self.sprite.src = src;
self.x = x;
self.y = y;
self.w = width;
self.h = height;
self.f = frames;
self.l = levels;
self.cf = 0;
self.cl = 0;
self.loaded = false;
self.src = src;
self.update = function () {
one_x += 1;
gs.fillStyle = "white";
gs.fillRect(0, 0, 1000, 10000);
gs.fillStyle = "black";
gs.fillRect(one_x, 20, 10, 10);
}
self.draw = function (){
if (self.loaded) {
document.getElementById("ass").innerHTML = "Ass";
gs.drawImage(self.sprite, self.x, self.y);
}
}
}
dog = new sprite("http://www.bit-101.com/blog/wp-content/uploads/2009/05/ball.png", 10, 10, 10, 10, 1, 1);
setInterval(dog.draw, 30);
You're missing new here:
this.sprite = Image();
Try:
this.sprite = new Image();
Also make sure that the image file actually exists in the given location.

Categories

Resources