This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 7 years ago.
Enchant.js is not familiarly used, but since it using same OOP style like prototype.js i think i've got a chance to ask it here.
this is my main.js:
var DIR_LEFT = 0;
var DIR_RIGHT = 1;
var DIR_UP = 2;
var DIR_DOWN = 3;
enchant();
window.onload = function () {
game = new Core(320, 320);
game.preload(
'res/map0.png',
'res/chara0.png'
);
game.fps = 30;
game.onload = function() {
var sceneGame = new SceneGame();
game.pushScene(sceneGame);
}
game.start();
//main gameplay scene
var SceneGame = Class.create(Scene, {
initialize: function() {
Scene.apply(this);
var stage, map, player, label;
stage = new Group();
map = tileMap(game.assets['res/map0.png']);
player = new Player();
label = new Label("hi!");
player.addEventListener(Event.ENTER_FRAME, this.update);
this.player = player;
this.map = map;
stage.addChild(map);
stage.addChild(player);
this.Elx = 1;
this.label = label;
this.addChild(stage);
this.addChild(label);
var pad = new Pad();
pad.y = 220;
this.addChild(pad);
},
update: function() {
this.Elx = 2;
console.log("Elx :" + this.Elx );
console.log(this.player.x);
}
});
var Player = Class.create(Sprite, {
initialize: function() {
Sprite.apply(this, [32, 32]);
this.image = game.assets['res/chara0.png'];
this.x = 2 * 16;
this.y = 16;
this.dir = DIR_DOWN;
this.anim = [
9, 10, 11, 10,
18, 19, 20, 19,
27, 28, 29, 28,
0, 1, 2, 1];
// Frame setting
if (!game.input.up && !game.input.down && !game.input.right && !game.input.left) {
this.age = 1;
this.frame = this.anim[this.dir * 4 + (this.age % 4)];
}
},
update: function (evt) {
}
});
}
initialize is the Enchant.js object constructor method,
the code above successfully returning the stage group child ( map and player) images on screen, but when i want to use on update SceneGame's method,
the console returned 2 for the this.Elx
but returning undefined error for this.player.x .
Why this is happening ?
any help are appreciated . thank you
thank you guys for your answer, so basically is my fault for lack of understanding about the Grouping method. So in the line i declared :
map = tileMap(game.assets['res/map0.png']);
this.map = map;
player = new Player();
this.player = player;
stage = new Group();
stage.addChild(player);
stage.addChild(map);
map.addChild(stage);
and in the update i tried to call console.log(this.player)
of course it wont work because the player inserted in scene as a child. I tried to change above line to :
map = tileMap(game.assets['res/map0.png']);
player = new Player();
stage = new Group();
stage.addChild(player);
this.player = stage.childNodes[0];
stage.addChild(map);
this.map = stage.childNodes[1];
map.addChild(stage);
above code succesfully return any property of this.player.
So this is solved . thank you :)
Related
How can I pause/stop the vehicle moving entity (to stop the vehicle from the moving) by calling another function? Cannot seem to use viewModel.pauseViewModel.command();. Appreciate if anyone can demonstrate how to provide a pause & continue for moving entity.
function togglesimulation() {
Cesium.Math.setRandomNumberSeed(3);
var start = Cesium.JulianDate.fromDate(new Date(2021, 6, 29, 16));
var stop = Cesium.JulianDate.addSeconds(start, 300, new Cesium.JulianDate);
//Make sure viewer is at the desired time.
var clock = new Cesium.Clock();
viewer.clock.startTime = start.clone();
viewer.clock.stopTime = stop.clone();
viewer.clock.currentTime = start.clone();
viewer.clock.clockRange = Cesium.ClockRange.CLAMPED; // stop at the end
viewer.clock.multiplier = clockmultiplier;
viewer.clock.shouldAnimate = true;
var position = new Cesium.SampledPositionProperty();
var time = Cesium.JulianDate.addSeconds(start, 120, new Cesium.JulianDate());
var timeStepInSeconds = 5;
var newPositions = mergedgeom1;
for (var i = 0; i < newPositions.length; i++) {
var poss = Cesium.Cartesian3.fromDegrees(parseFloat(newPositions[i][0]), parseFloat(newPositions[i][1])); //height
var time = Cesium.JulianDate.addSeconds(start, i * timeStepInSeconds, new Cesium.JulianDate());
position.addSample(time, poss);
}
var entity = viewer.entities.add({
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: start,
stop: stop,
}),
]),
model: {
uri: "../asset/vehicle/CesiumMilkTruck/CesiumMilkTruck.glb",
minimumPixelSize: 64,
},
viewFrom: new Cesium.Cartesian3(-100.0, 0.0, 100.0),
position: position,
orientation: new Cesium.VelocityOrientationProperty(position),
});
viewer.trackedEntity = entity;
var scene = viewer.scene;
}
Pause the clock with:
viewer.clock.shouldAnimate = false;
You can un-pause later with:
viewer.clock.shouldAnimate = true;
I got a game with falling pics
I push() the next func into an array
and my pics var bulletinare flickering, so I think it's probably I draw them a lot when use update() func
function rect () {
this.size = [rectSize.x, rectSize.y];
this.imagesSrc = rand(0, 1) ? 'bulletinYes' : 'bulletinNo';
this.position = [rand(0, w-rectSize.x), -rectSize.y];
this.bulletinValue = (this.imagesSrc === 'bulletinYes') ? 'bulletinYesValue' : 'bulletinNoValue';
}
rect.prototype = {
draw: function (){
var bulletin = new Image();
bulletin.src = imagesSrc[this.imagesSrc];
ctx.drawImage(bulletin, this.position[0], this.position[2], this.size[0], this.size[2]);
}
}
I've tried to put var bulletin outside the fuction like so
var bulletin = new Image();
bulletin.src = imagesSrc[this.imagesSrc]; <= ???
function rect () {
this.size = [rectSize.x, rectSize.y];
this.imagesSrc = rand(0, 1) ? 'bulletinYes' : 'bulletinNo';
this.position = [rand(0, w-rectSize.x), -rectSize.y];
this.bulletinValue = (this.imagesSrc === 'bulletinYes') ? 'bulletinYesValue' : 'bulletinNoValue';
}
rect.prototype = {
draw: function (){
ctx.drawImage(bulletin, this.position[0], this.position[1], this.size[0], this.size[1]);
}
}
but I have no idea how to change [this..imagesSrc] so it could work.
And also it is executed only once and pic are not randomizing for each pushed one.
Does anyone have any suggestion how to get rid of the flickering or change bulletin.src = imagesSrc[this.imagesSrc];
here's my github link if u want to see whole script
I just started my coding path, so thanks anyone who could answer this one:)
You create new image each time and trying to draw it before image is loaded.
Better way is prepare all images at start and just draw it.
Little changes in your code and all will work:
Prepare images:
var imagesSrc = {
ballotBoxImgSrc: 'img/ballotBox.png',
bulletinYes: 'img/yes.jpg',
bulletinNo: 'img/no.jpg'
};
var images = {
ballotBoxImgSrc: new Image(),
bulletinYes: new Image(),
bulletinNo: new Image()
}
for(let [name,value] of Object.entries(imagesSrc)) {
images[name].src = value;
}
Draw:
rect.prototype = {
draw: function (){
var bulletin = images[this.imagesSrc];
ctx.drawImage(bulletin, this.position[0], this.position[1], this.size[0], this.size[1]);
}
}
Firstly a little elaboration of the project I'm working on. I have started building a 'map maker' for a 2d game I am working on. The project is just for fun and has proven so far to be a great way to learn new things.
I recently showed my working map maker code to a friend who suggested it would be much more re-usable if I restructured the project to be more OOR, which I am now attempting.
The problem I have is when I add a 'Guild' instance to my map, the first one works fine, but the second causes a type error that is giving me a headache!
I will post all of the relevant code from the different files below, but the overall structure is as follows:
Map.js = Map class file, container for setting the map overall size and iterating over (and placing) map objects.
MapObject.js = Class file for simple map objects such as walls, contains the position and icon properties.
Guild.js = Class file, extends MapObject.js, this is where my problem seems to be, adds an additional 'MapIcon' and will have other features such as levels and names etc.
map-maker.js = Main file for generating the map-maker page, utilises the above class files to create the map.
Below is the code used to create an instance of 'Guild' on my map:
map-maker.js (creating the map / map object / guild instances)
// Initialise a new instance of map class from Map.js using the user
provided values for #mapX and #mapY.
var currentMap = new Map(XY,40);
// Get the user box volume * map boxsize from Map.js
currentMap.calcDimensions();
// Create a Map Object and push it to the currentMap with its position.
function createMapObject(x,y,floor){
currentMap.objects.push(new MapObject(x,y,floor));
}
// Create a Guild Object (extension of Map Object) and push it to the currentMap with its position.
function createGuildObject(x,y,floor){
currentMap.objects.push(new Guild(x,y,floor));
}
....
case 13: // Enter Key (Submit)
unhighlightTools();
currentMap.drawMap();
if(currentFloor != null){
currentFloor.hasFloor = true;
if(currentFloor.tileName == "Guild"){
createGuildObject(currentFloor.position.x,currentFloor.position.y,currentFloor);
}else {
createMapObject(currentFloor.position.x,currentFloor.position.y,currentFloor);
}
console.log("Map object created at - X:"+currentFloor.position.x+" Y:"+currentFloor.position.y);
}
currentFloor = [];
highlightTools();
break;
}
Guild.js (constructor and assigning map icon)
class Guild extends MapObject {
constructor(x,y,floor) {
super(x,y,floor);
this.levels = [];
}
mapIcon() {
this.mapIcon = new Image();
this.mapIcon.src = "../images/mapSprites/obj-1.png"
return this.mapIcon;
}
}
MapObject.js (position setup and constructor)
class MapObject {
constructor(x,y,floor) {
this.position = {x, y};
this.icon = this.wallFloorIcons(floor);
}
wallFloorIcons(floor) {
this.img = new Image();
this.name = "";
this.name += (floor.wallNorth) ? 'n' : '';
this.name += (floor.wallEast) ? 'e' : '';
this.name += (floor.wallSouth) ? 's' : '';
this.name += (floor.wallWest) ? 'w' : '';
this.name = 'wall-'+this.name+'.png';
if(this.name == 'wall-.png'){
this.img.src = "../images/mapSprites/floor.png";
}else {
this.img.src = "../images/mapSprites/"+this.name;
}
return this.img;
}
getIcon() {
return this.img;
}
}
Map.js (processing the objects at a given location and drawing the canvas)
class Map {
// Map Width / Height and number of boxes. Used to generate map and zoom level.
constructor(wh, boxSize) {
this.size = wh;
this.width = wh[0];
this.height = wh[1];
this.boxSize = boxSize;
this.objects = [];
this.boxes = wh[0];
}
// Calculates the width and height * boxSize for rendering the canvas.
calcDimensions(){
this.realX = Math.floor(this.width * this.boxSize);
this.realY = Math.floor(this.height * this.boxSize);
this.realX = parseInt(this.realX,10);
this.realY = parseInt(this.realY,10);
this.realXY = [
this.realX,
this.realY
];
return this.realXY;
}
// Draws the canvas, grid and adds the objects that belong to the map.
drawMap(){
var self = this;
self.canvas = document.getElementById("canvas");
self.c = self.canvas.getContext("2d");
self.background = new Image();
self.background.src = "../images/mapSprites/oldPaperTexture.jpg";
// Make sure the image is loaded first otherwise nothing will draw.
self.background.onload = function(){
self.c.drawImage(self.background,0,0);
self.fillMap();
}
}
fillMap(){
var self = this;
self.c.lineWidth = 1;
self.c.strokeStyle = 'black';
self.c.fillStyle = "rgba(255, 255, 255, 0.2)";
for (var row = 0; row < self.boxes; row++) {
for (var column = 0; column < self.boxes; column++) {
var x = column * self.boxSize;
var y = row * self.boxSize;
self.c.beginPath();
self.c.rect(x, y, self.boxSize, self.boxSize);
self.c.stroke();
self.c.closePath();
for (var i=0; i<self.objects.length; i++) {
var floor = self.objects[i];
if (floor.position.x == column && floor.position.y == row) {
if (self.objectsAtPosition({x:floor.position.x, y:floor.position.y}) != null) {
var mapObjects = self.objectsAtPosition({x:floor.position.x, y:floor.position.y})
for (var mapObject of mapObjects) {
this.c.drawImage(mapObject.getIcon(), x, y, self.boxSize, self.boxSize);
console.log(mapObject);
if(mapObject instanceof Guild){
console.log(mapObject);
this.c.drawImage(mapObject.mapIcon(), x, y, self.boxSize, self.boxSize);
}
}
}
}
}
}
}
}
deleteObject(pos){
this.objectsAtPosition(pos);
for( var i = 0; i < this.objects.length; i++){
if(this.objects[i] == this.objs){
delete this.objects[i];
this.objects.splice(i,1);
}
}
}
objectsAtPosition(position) {
var objs = [];
for (var o of this.objects) {
if (o.position.x == position.x && o.position.y == position.y) {
objs.push(o);
}
}
return objs;
}
}
When I run the code, this is my error:
Uncaught TypeError: mapObject.mapIcon is not a function
at Map.fillMap (Map.js:70)
at Image.self.background.onload (Map.js:39)
The error comes after I add 1 guild then try to add any other map object. Guild or otherwise.
Sorry if this question is a little vague, I'm still learning (as you can see :p).
Thanks for your time!
Earl Lemongrab
Got a solution from a friend in the end.
The issue was that I was reassigning this.mapIcon = new Image() so it exploded when it was called a second time.
Feel pretty silly for not spotting it.
Thanks for the help everyone.
Everything is working, except in the update function, when I put back the var player, it doesn't recognize it:
"Uncaught ReferenceError: player is not defined"
(I'm also not sure for the animation) (Mario is the player, it's a mario level)
Here is my code:
var SandBox = {
preload:function(){
//this.game
console.log("preload Sand Box");
this.game.load.image('platform', 'assets/platform.png');
this.game.load.spritesheet('mario', 'assets/mario.png', 32, 32 , 12);
this.game.load.image('coinbox', 'assets/coinbox.png');
},
create:function(){
console.log("create Sand Box");
var imageHeight = this.game.cache.getImage("platform").height;
this.game.physics.startSystem(Phaser.Physics.ARCADE);
var worldHeight = this.game.world.height;
var ground = this.game.add.sprite(0, worldHeight - imageHeight, 'platform');
var platform = this.game.add.sprite(250, 285, 'platform');
var platform = this.game.add.sprite(-250, 145, 'platform');
var platform = this.game.add.sprite(280, 285, 'coinbox');
var player = this.game.add.sprite(32, 100, 'mario');
this.game.physics.enable(ground);
this.game.physics.enable(platform);
this.game.physics.arcade.enable(player);
player.frame = 5;
ground.body.immovable = true;
platform.body.immovable = true;
player.body.bounce.y = 0.2;
player.body.gravity.y = 300;
player.body.collideWorldBounds = true;
player.animations.add('left', [0, 1, 2, 3], 10, true);
player.animations.add('right', [5, 6, 7, 8], 10, true);
},
update:function(){
console.log("update Sand Box");
this.game.physics.arcade.enable(player);
var hitPlatform = this.game.physics.arcade.collide(player, ground); // << THESE FUNCTIONS
}
}
The scope of variable player in thr snippet is local to the function it is in. One can move the declaration (with var) for player outside of the sandbox object:
var player;
var sandbox = {
create: function() {
//... skipping lines ...
player = this.game.add.sprite(32, 100, 'mario');
},
Update: function() {
//use player here
var hitPlatform = this.game.physics.arcade.collide(player, ground); // << THESE FUNCTIONS
}
};
Or make it part of the object:
var sandbox = {
create: function() {
//... skipping lines ...
this.player = this.game.add.sprite(32, 100, 'mario');
},
Update: function() {
//... skipping lines ...
//use this.player here
var hitPlatform = this.game.physics.arcade.collide(this.player, ground);
}
};
I have built this code using javascript that makes a few objects called monster. I then put those monsters in an array and finally am trying to call one of thous monsters to the console randomly. Unfortunately it displays in my console log as undefined. Any advice on how to get a random monster in the console log every time I refresh the page?
function Monster(type, level, mAttack, mAgility, mHP) {
this.type = type;
this.level = level;
this.mAttack = mAttack;
this.mAgility = mAgility;
this.mHP = mHP;
}
Monster.prototype.logInfo = function() {
console.log("I am a : ", this.type);
console.log("I am level : ", this.level);
console.log("I have the attack of : ", this.mAttack);
console.log("I have the agility : ", this.mAgility);
console.log("I have the health : ", this.mHP);
}
var troll = new Monster("troll", 1, 10, 10, 10);
var skeleton = new Monster("skeleton", 1, 10, 10, 10);
var slime = new Monster("slime", 1, 10, 10);
var boar = new Monster("boat", 1, 10, 10);
var monsterList = new Array();
monsterList[0] = troll;
monsterList[1] = skeleton;
monsterList[3] = slime;
monsterList[4] = boar;
var summonRandomMonster = function (){
monsterSummoner = monsterList[Math.floor(Math.random() * monsterList.length)];
}
console.log(monsterSummoner);
You create a function but never call it. Therefor monsterSummoner is never set.
// THIS IS NEVER CALLED
var summonRandomMonster = function (){
monsterSummoner = monsterList[Math.floor(Math.random() * monsterList.length)];
}
console.log(monsterSummoner);
Try this instead. Notice that now that the function is called the value is set.
var monsterSummoner;
var summonRandomMonster = function (){
monsterSummoner = monsterList[Math.floor(Math.random() * monsterList.length)];
}
summonRandomMonster();
console.log(monsterSummoner);
You're close... Change your last four lines as follows -
var monsterList = [troll,skeleton,slime,boar];
var summonRandomMonster = function (){
monsterSummoner = monsterList[Math.floor(Math.random() * monsterList.length)];
console.log(monsterSummoner);
}
for (var i = 0; i < 100; i++) {
summonRandomMonster();
}
There are atleast two problems in this code. The variable "monsterSummoner" is not defined, and the function "summonRandomMonster" is not called.