I have a simple javascript constructor-function which constructs an object that is supposed to draw conways game of life:
function startGame() {
var myGameOfLife = new GameOfLife();
myGameOfLife.initialize(500, 500);
}
function GameOfLife() {
this.canvas = document.createElement("canvas");
this.initialize = function(width, height) {
this.canvas.width = width;
this.canvas.height = height;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.interval = setInterval(this.update, 20);
}
this.update = function(){
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
canvas {
border:1px solid #d3d3d3;
background-color: #f1f1f1;
}
</style>
</head>
<body onload="startGame()">
<script>
</script>
</body>
</html>
When i debug this script, i can see that in the initialize-function this.context gets assigned. But when the update-function is called by the interval, this.context is undefined.
Why is it undefined when i can clearly see it being defined before?
you're referring to the wrong this in the update function.
Just bind the right context (that is the context of GameOfLife constructor)
this.interval = setInterval(this.update.bind(this), 20);
or alternatively use an arrow function in order to let it inherit the outer scope.
this.update = () => {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
Related
I am developing a game using JavaScript and I want to have the scenes of a classic 1990's game where the text appears in split-second intervals then disappears once the user clicks next. Is there a way to do this just using JavaScript?
I'm using PhpStorm for the moment. I have yet to start as I'm designing the blueprints with my friend. I am also a bit confused about where to start because I have searched for methods but no luck.
Since You Are Making A Game You Will Be Having A Canvas Too
So Use This Code If have Any Questions Ask Me
HTML
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
canvas {
border:1px solid #d3d3d3;
background-color: #f1f1f1;
}
</style>
</head>
<body onload="startGame()">
</body>
</html>
Javascript
<script>
var myGamePiece;
var myTitle;
//Function To Start the Game
function startGame() {
myTitle = new component("20px", "Consolas", "black", 150, 135, "text");
myGameArea.start();
}
// myGameArea Is The Canvas in Which The Whole Drawing Process Will be Drawn & The Title Is Drawn In This Too
var myGameArea = {
canvas : document.createElement("canvas"),
start : function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.frameNo = 0;
// setInterval Function Draws the Canvas 50 times in a Second You Can Change The Value Of 50 IF You Want
this.interval = setInterval(updateGameArea, 50);
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
}
// Component Function Makes a New Component Like We Have A Title By Component Function
function component(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
// This Checks if Component Type is Text And Every Frame is Divided By 70 Then Nothing Will Happen Else Your Title Will Appear You Glitch is Because Of This Function You Can The Value As You Want
if (this.type == "text" && everyinterval(70) ) {
} else {
ctx.font = this.width + " " + this.height;
ctx.fillStyle = color;
ctx.fillText(this.text, this.x, this.y);
}
}
}
// This Function Updates GameArea (The Canvas) I Added The Frame No So You Can See The Glitch At Every Frame Number
function updateGameArea() {
myGameArea.frameNo += 1;
myGameArea.clear();
myTitle.text = "Title Glitching at " + myGameArea.frameNo;
myTitle.update();
}
// The Function To Make The Glitch Which Divide's The FrameNo By "n" Number
function everyinterval(n) {
if ((myGameArea.frameNo / n) % 1 == 0) {return true;}
return false;
}
</script>
Hope This Helps!
I want a red square to appear where I click on the canvas with my mouse, but I'm having trouble getting the square to appear on the canvas when I click on it. The function start contains window.addEventListener() which is supposed to be creating a component on the mouseclick, but I'm not sure if I am missing something or if I'm just completely wrong.
<!DOCTYPE html>
<html>
<head>
<meta = name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
canvas {
border:1px solid #d3d3d3;
background-color: #f1f1f1;
}
</style>
</head>
<body onload="start() {
gameArea.start();
}
var gameArea = {
canvas : document.createElement("canvas"),
start : function() {
this.canvas.width = 840;
this.canvas.height = 540;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
//I don't know what Im doing wrong here
window.addEventListener('mousedown', function (e) {
new component(30, 30, "red", 10, 120);
})
}
}
//and here
function component(width, height, color, x, y) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;
}
</script>
</html>
window.addEventListener('mousedown', (e) => {
const {layerX, layerY} = e;
const rectSize = 30;
this.context.fillStyle = 'red';
this.context.fillRect(layerX - rectSize / 2, layerY - rectSize / 2, rectSize, rectSize);
});
you passed a function () {} which had no context of your gameArea. The other part is a canvas api.
I am learning how to make a minigame with javascript, but my player is not rendered.
I donĀ“t know why. I am not getting any errors.
The startGame() starts with
How should I edit my code to get it to run and get the sprites to render?
Here's my code :
<html>
<head>
<meta name="viewport" content="width = device-width, initial-scale = 1.0"/>
</head>
<body onload='startGame()'>
<script>
function startGame() {
createCanvas.start();
}
let ninja = new Image();
let ninjaImage = "images/player/stand01.png"
const createCanvas = {
canvas : document.createElement('canvas'),
start() {
this.canvas.width = 600;
this.canvas.height = 400;
this.context = this.canvas.getContext('2d');
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
}
}
function sprite(options){
let that = {};
that.context = options.context;
that.width = options.width;
that.height = options.height;
that.image = options.image;
return that;
that.render = function () {
that.context.drawImage(
that.image, 0, 0, that.width, that.height, 0, 0, that.width, that.height);
}
player.render();
}
player = sprite ({
width: 100,
height: 100,
image: ninjaImage
});
</script>
</body>
<style>
canvas {
border: 1px solid black;
background: grey;
}
</style>
Assuming you have taken care of the early return, your code isn't working because you are likely because your render() function is being called when your player object is created. Before you can draw anything it's better to setup your canvas and context object first.
My recommendation for creating objects in a class like way is to use the function/prototype approach.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: black;
}
canvas {
display: block;
margin: auto;
border: solid 1px white;
border-radius: 10px;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="application/javascript">
void function() {
"use strict";
/*
In JS a 'class' is made up of two things
A constructor function that attaches individual properties to every new instance
(When a contructor is called with 'new' I.E. 'new Sprite()', the 'this' variable in the constructor
is assigned to the newly created object.
The other part is a prototype that holds shared properties between instances of
the 'class'. (in an instance prototype values are accessible via the this keyword).
*/
// Constructor function
function Sprite(x,y,width,height,image) {
this.x = x || 0.0;
this.y = y || 0.0;
this.width = width || 1.0;
this.height = height || 1.0;
this.image = image || null;
}
// Prototype object (Shared between instances)
Sprite.prototype = {
render: function(ctx) {
if (this.image) {
ctx.drawImage(this.image,this.x,this.y,this.width,this.height);
} else {
ctx.fillStyle = "darkred";
ctx.fillRect(this.x,this.y,this.width,this.height);
}
}
};
var canvasWidth = 180;
var canvasHeight = 160;
var canvas = null;
var ctx = null;
var sprite = null;
var image = new Image();
image.src = "https://i.stack.imgur.com/WnNgY.png";
// window.onload, called when page has loaded
onload = function() {
canvas = document.getElementById("canvas");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
ctx = canvas.getContext("2d");
ctx.fillStyle = "gray";
ctx.fillRect(0,0,canvasWidth,canvasHeight);
sprite = new Sprite(65,55,50,50,image);
sprite.render(ctx);
}
}();
</script>
</body>
</html>
So we pretty much have this program working fine, we just need a little help, or a good pointer in the right direction on how we would start and stop the animation. I have tried several methods and none seem to have worked. I have spent a good amount of time online attempting to find help for the solution. I have come to believe that the problem lies somewhere in the lines that tell the shape to move. Thank you for any help in advance.
JS:
var myGamePiece;
function startGame() {
myGamePiece = new component(30, 30, "red", 10, 120);
myGameArea.start();
}
var myGameArea = {
canvas : document.createElement("canvas"),
start : function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.interval = setInterval(updateGameArea, 20);
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component(width, height, color, x, y) {
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
}
function updateGameArea() {
myGameArea.clear();
myGamePiece.newPos();
myGamePiece.update();
}
function moveup() {
myGamePiece.speedY -= 1;
}
function movedown() {
myGamePiece.speedY += 1;
}
function moveleft() {
myGamePiece.speedX -= 1;
}
function moveright() {
myGamePiece.speedX += 1;
}
HTML:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<script type="text/javascript" src="HallettBrocatoLab2.js"></script>
<style>
canvas {
border:1px solid #d3d3d3;
background-color: #f1f1f1;
}
</style>
</head>
<body onload="startGame()">
<div style="text-align:center;width:480px;">
<button onclick="moveup()">UP</button><br><br>
<button onclick="moveleft()">LEFT</button>
<button onclick="moveright()">RIGHT</button><br><br>
<button onclick="movedown()">DOWN</button><br><br>
<button onclick="start()">Start</button>
<button onclick="stop()">Stop</button>
</div>
<p>If you click a button the red square will start moving. Click the same button many times, and it will move faster and faster.</p>
</body>
</html>
The clearInterval() method clears a timer set with the setInterval() method.
The ID value returned by setInterval() is used as the parameter for the clearInterval() method.
add a function end pauseGame()
function pauseGame(){
clearInterval(this.interval);
}
change the definition of updateGameArea function
function updateGameArea() {
if(condition_to_stop){
myGameArea.pauseGame();
}
myGameArea.clear();
myGamePiece.newPos();
myGamePiece.update();
}
I am trying to use class on drawImage function.
But it seems that drawImage function couldn't get the attribute img of variable monster.
I have no idea what would caused this error.
Not quite understand why browser give me the below error code ... please help me.
Uncaught TypeError: Cannot read property 'img' of undefined.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Tower Defense</title>
<style>
canvas {
padding: 0;
margin: auto;
display: block;
}
</style>
</head>
<body>
<script>
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 500;
document.body.appendChild(canvas);
function Monster(img, x = 0, y = 0, w,h) {
this.img = img;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
var monster;
var DrawMonster = function(mons) {
ctx.drawImage(mons.img, mons.x, mons.y, mons.w, mons.h);
}
var PreLoadImages = function() {
var img = new Image();
img.addEventListener("load", function() { // or img.onload = function() { ...
monster = new Monster(this, 0, 0, 100, 100);
});
img.src = "res/Mons_Pirate.jpg";
}
PreLoadImages();
DrawMonster(monster);
</script>
</body>
</html>
Please change the link (res/Mons_Pirate.jpg) of image while testing.
DrawImage should be inside the image load function.Instance of Monster is created only inside the Image load function.Image will be loaded in async.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Tower Defense</title>
<style>
canvas {
padding: 0;
margin: auto;
display: block;
}
</style>
</head>
<body>
<script>
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 500;
document.body.appendChild(canvas);
function Monster(img, x = 0, y = 0, w,h) {
this.img = img;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
var monster;
var DrawMonster = function(mons) {
ctx.drawImage(mons.img, mons.x, mons.y, mons.w, mons.h);
}
var PreLoadImages = function() {
var img = new Image();
img.addEventListener("load", function() { // or img.onload =
function() {
monster = new Monster(this, 0, 0, 100, 100);
DrawMonster(monster);
});
img.src = "res/Mons_Pirate.jpg";
}
PreLoadImages();
</script>
</body>
</html>