I have written a function loja() in an external js. In another html file, at the end of the file I have linked it to the external js and then at the body of the html file I have created a div and onclick it will call the function loja(). It all works well but the thing is that the javascript function is not loaded inside the div but at the end of the page.Can you help me out?
This is from html file.
<div class="section-title" onclick="loja()">Luaj
</div>
This one is the javascript file.
// Create our 'main' state that will contain the game
function loja(){
var mainState = {
preload: function() {
game.load.image('bird', 'assets/car.png');
game.load.image('pipe', 'assets/pipe.png');
game.load.audio('jump', 'assets/jump.wav');
game.load.image('background', 'assets/background.png');
},
create: function() {
game.add.tileSprite(0, 0, 1000, 600, 'background');
// Set the physics system
game.physics.startSystem(Phaser.Physics.ARCADE);
// Display the bird at the position x=100 and y=245
this.bird = game.add.sprite(100, 245, 'bird');
// Add physics to the bird
// Needed for: movements, gravity, collisions, etc.
game.physics.arcade.enable(this.bird);
// Add gravity to the bird to make it fall
this.bird.body.gravity.y = 1000;
// Call the 'jump' function when the spacekey is hit
var spaceKey = game.input.keyboard.addKey(
Phaser.Keyboard.SPACEBAR);
spaceKey.onDown.add(this.jump, this);
// Create an empty group
this.pipes = game.add.group();
this.timer = game.time.events.loop(1500, this.addRowOfPipes, this);
this.score = 0;
this.labelScore = game.add.text(20, 20, "0",
{ font: "30px Arial", fill: "#ffffff" });
// Move the anchor to the left and downward
this.bird.anchor.setTo(-0.2, 0.5);
this.jumpSound = game.add.audio('jump');
},
update: function() {
// If the bird is out of the screen (too high or too low)
// Call the 'restartGame' function
if (this.bird.y < 0 || this.bird.y > 490)
this.restartGame();
game.physics.arcade.overlap(
this.bird, this.pipes, this.hitPipe, null, this);
if (this.bird.angle < 20)
this.bird.angle += 1;
},
// Make the bird jump
jump: function() {
// Add a vertical velocity to the bird
this.bird.body.velocity.y = -300;
// Create an animation on the bird
var animation = game.add.tween(this.bird);
// Change the angle of the bird to -20° in 100 milliseconds
animation.to({angle: -20}, 100);
// And start the animation
animation.start();
if (this.bird.alive == false)
return;
this.jumpSound.play();
},
// Restart the game
restartGame: function() {
// Start the 'main' state, which restarts the game
game.state.start('main');
},
addOnePipe: function(x, y) {
// Create a pipe at the position x and y
var pipe = game.add.sprite(x, y, 'pipe');
// Add the pipe to our previously created group
this.pipes.add(pipe);
// Enable physics on the pipe
game.physics.arcade.enable(pipe);
// Add velocity to the pipe to make it move left
pipe.body.velocity.x = -200;
// Automatically kill the pipe when it's no longer visible
pipe.checkWorldBounds = true;
pipe.outOfBoundsKill = true;
},
addRowOfPipes: function() {
// Randomly pick a number between 1 and 5
// This will be the hole position
var hole = Math.floor(Math.random() * 5) + 1;
// Add the 6 pipes
// With one big hole at position 'hole' and 'hole + 1'
for (var i = 0; i < 8; i++)
if (i != hole && i != hole + 1)
this.addOnePipe(400, i * 60 + 10);
this.score += 1;
this.labelScore.text = this.score;
},
hitPipe: function() {
// If the bird has already hit a pipe, do nothing
// It means the bird is already falling off the screen
if (this.bird.alive == false)
return;
// Set the alive property of the bird to false
this.bird.alive = false;
// Prevent new pipes from appearing
game.time.events.remove(this.timer);
// Go through all the pipes, and stop their movement
this.pipes.forEach(function(p){
p.body.velocity.x = 0;
}, this);
},
};
// Initialize Phaser, and create a 400px by 490px game
var game = new Phaser.Game(600, 800);
// Add the 'mainState' and call it 'main'
game.state.add('main', mainState);
// Start the state to actually start the game
game.state.start('main');
}
Where javascript code appears in your page in this case seems out of point.
You linked it at the end of file? Than it will appear at the end of file.
What I understand you want is your code to interact with some part of a html file structure, called DOM, some DIV tag in particular.
You need to use Javascript to interact with that DIV node. Probably to render your game inside of it.
In your JS file I only see definition and some method calls. I cant see part that would render some content into DOM.
Summarizing: place where your javascript methods definitions are it not the same place where effects of execution of those methods will appear.
It looks like you're trying to implement an open-source Phaser game (https://github.com/photonstorm/phaser/blob/v2.4.4/src/core/Game.js)
Since your issue is with functionality regarding that framework, that should be your starting place for information. Also you shouldn't leave out important information like any framework you're using when asking for help (especially since in this case the issue is only that you're not using the it properly).
If you look at the fourth parameter it actually allows you to specify a DOM parent, it accepts either the ID or the element itself. So you could just do something like this after inserting another element in your HTML with the ID pgame:
var game = new Phaser.Game(600, 800, void(0), 'pgame');
Related
I'm running into a bit of an odd issue with Paper.js - I'm using the library to scale the "petals" of a randomly generated flower while audio plays.
The issue crops up if the flower is "growing" and the user navigates to a different tab in the browser. Even though it appears that the onFrame event is not firing when the window is out of view, whichever petal is currently scaling at the time will continue to scale indefinitely.
I even tried using a special js library to determine if the window is in view and still wasn't able to get the petals to stop scaling.
You can view a demo here, as I was not even able to replicate this in a Paper sketch: https://demos2.paperbeatsscissors.com/
Also including my onFrame code here in case the problem is obvious to someone:
view.onFrame = function(event) {
// See if something is playing
if (playing > -1) {
// Get the active flower
var activeFlower = garden[playing],
activeData = activeFlower.data;
// Active layer and petal
var activeLayer = getEl(activeFlower, activeData.lIndex),
activePetal = getEl(activeLayer, activeData.pIndex);
// Variables
var time = activeData.audio.seek(),
scaleAmount = (1 / (activeData.timing / event.delta.toFixed(3))) * 2;
// Petal progression
if (!activeData.completed) {
if (activePetal.scaling.x < 1 && activePetal.scaling.y < 1) {
activePetal.pivot = {x: 0, y: activePetal.height / 2};
activePetal.scaling.x = activePetal.scaling.x + scaleAmount;
activePetal.scaling.y = activePetal.scaling.y + scaleAmount;
} else {
if (activeData.pIndex < (activeLayer.children.length - 1)) {
// If the petal is scaled, jump to a new petal
activeData.pIndex += 1;
} else {
if (activeData.lIndex > 0) {
// When all petals are bloomed, jump to a new layer
activeData.pIndex = 0;
activeData.lIndex -= 1;
} else {
// Set the flower as completed
activeData.completed = true;
}
}
}
}
activeFlower.rotate(.125, activeData.center);
// Reset the playing variable if the audio clip is complete and the flower has completed
if (!activeData.audio.playing() && time === 0 && activeData.completed) {
playing = -1;
}
}
}
Really stumped on this one so any help is greatly appreciated!
I think that your problem is coming from the fact that you base your scaling calculation on event.delta which represents the time elapsed since the last event fired.
The thing is that, if I'm not mistaken, under the hood, Paper.js onFrame event relies on requestAnimationFrame which does not fire when the tab if inactive.
So when you switch tab, wait for a while and get back to your tab event.delta value is big and your scaling value too, hence the size of your petals. This basic sketch showcase this behavior.
So in my opinion, you should simply check event.delta value and limit it if it's too high.
I found this codepen.io for the game 2048: http://codepen.io/anon/pen/dMzmae
The game is written in JavaScript with a GameManager, HTMLActuator to create the HTML elements, a ScoreManager to keep track of the score and a KeyboardInputManager to track what is pressed and what to do.
The application uses window.requestAnimationFrame to redraw the window. I was wondering how it does that. When the code actuates, it uses the window.requestAnimationFrame() and inside for each cell in the grid it uses the addTile() method to add each tile to the DOM.
HTMLActuator.prototype.actuate = function (grid, metadata) {
var self = this;
window.requestAnimationFrame(function () {
self.clearContainer(self.tileContainer);
grid.cells.forEach(function (column) {
column.forEach(function (cell) {
if (cell) {
self.addTile(cell);
}
});
});
self.updateScore(metadata.score);
if (metadata.over) self.message(false); // You lose
if (metadata.won) self.message(true); // You win!
});
};
If you look at the addTime() method, it too has a window.requestAnimationFrame method that updates the class with the currentPosition if the tile it's adding had a previousPosition property:
HTMLActuator.prototype.addTile = function (tile) {
var self = this;
var element = document.createElement("div");
var position = tile.previousPosition || { x: tile.x, y: tile.y };
positionClass = this.positionClass(position);
// We can't use classlist because it somehow glitches when replacing classes
var classes = ["tile", "tile-" + tile.value, positionClass];
this.applyClasses(element, classes);
element.textContent = tile.value;
if (tile.previousPosition) {
// Make sure that the tile gets rendered in the previous position first
window.requestAnimationFrame(function () {
classes[2] = self.positionClass({ x: tile.x, y: tile.y });
self.applyClasses(element, classes); // Update the position
});
} else if (tile.mergedFrom) {
classes.push("tile-merged");
this.applyClasses(element, classes);
// Render the tiles that merged
tile.mergedFrom.forEach(function (merged) {
self.addTile(merged);
});
} else {
classes.push("tile-new");
this.applyClasses(element, classes);
}
// Put the tile on the board
this.tileContainer.appendChild(element);
};
I guess I'm wondering how does this requestAnimationFrame work to correctly display the tiles when moved? It's building up each tile with the tile information in the grid. Then in addTile() it first uses the tile's previousPosition to build a tile that used to be on the board and creates a class for that position but then it checks if the tile has a previous position and updates the class back to the tile's new position on the grid.
But that only happens in a requestAnimationFrame method for tiles with a previous position and before the method finishes and appends the tile to the tile container in the DOM.
I hope the question makes sense. Are those nested window.RequestAnimationFrame's in the addTile method() called right after the original window.RequestAnimationFrame call in the HTMLActuator.prototype.actuate method so it moves to the new position after an instant and the CSS transition shows it moving?
I'm developing a Fez-based HTML5 Canvas game using EaselJS and I've found a problem, that I can't solve myself, while trying to implement SpriteSheets to the hero.
The problem is that I've defined three animations to my hero ("stand", "jump" and "run") and when I try to change from one animation to another using hero.gotoAndPlay("run") or hero.gotoAndStop("stand") the animations don't change, change but show the first frame only or change to the wrong animation.
Can someone help me? What I'm doing wrong and how can I fix it? Thanks.
Here's the relevant JavaScript code I'm using to create the hero Sprite:
var data = {
images: ["http://i.imgur.com/M0GmFnz.png"],
frames: {width:34, height:46},
animations: {
stand:0,
run:[0,12,true,0.25],
jump:13
}
};
var spriteSheet = new createjs.SpriteSheet(data);
var hero = new createjs.Sprite(spriteSheet, "stand");
hero.offset = 4 + 1; // "+1" is important, change the first number only.
hero.regX = hero.offset + 2;
hero.regY = hero.offset;
hero.width = 34 - (hero.offset*2) - 12;
hero.height = 46 - (hero.offset*2);
hero.x = 0;
hero.y = 0;
hero.jumping = true;
stage.addChild(hero);
And the code I'm using to change the animation:
if(!left && !right){ // User isn't pressing left arrow or right arrow
hero.gotoAndStop("stand");
}else{
hero.gotoAndPlay("run");
}
JSFiddle
Official Site
If you are calling gotoAndStop or gotoAndPlay in a tick (or similar) then it will constantly reset to the first frame. You have to ensure you only call these functions one time when the animation changes.
A good way to set this up is to store the current animation, store it, and only change it up if the animation changes. Something like:
var animation;
if(!left && !right){ // User isn't pressing left arrow or right arrow
animation = "stand";
}else{
animation = "run";
}
if (currentAnimation != animation) {
hero.gotoAndStop(animation);
}
This is just an example, but should give you an idea. You should only call these methods one time to kick off an animation.
I am in the prototyping stage of making a 2d map builder for a hybrid web/text adventure game and so far KineticJS seems like an ideal fit. Only issue currently is that given enough velocity on mouse movement, it will skip over cells and never fire their mouseover event handler.
2 core functionality goals: When the user highlights a cell, it would be marked as "active". Additionally if they're holding the mouse down and move across the grid, cells would be flipped on or off ( this maybe refactored to set all on if not if the first cell is not active, or vice versa ).
My question: Is there a way to ensure all cells are triggered, regardless of mouse cursor velocity? If not, is there a better way to draw a line over the cells so that it consistently triggers all relevant cells?
The entire prototype has been put into jsFiddle ( http://jsfiddle.net/7ggS4/ ) but for future sake, the rest will be copied below as well.
<head>
<title>KineticJS</title>
<script src="//cdnjs.cloudflare.com/ajax/libs/kineticjs/4.7.2/kinetic.min.js"></script>
</head>
<body>
<div id="canvas"></div>
</body>
<script defer="defer">
/**
Return's a KS layer
*/
function Grid(cells, stage) {
//Constants
// Illrelevant comment - It seriously pisses me off that canvas uses
// string color codes ( either name or string hexidecimal ) instead of taking an
// integer or actual hexidecimal 0xFFFF values. This just seems painfully inefficient.
this.activeCellColor = "green";
this.clearCellColor = "blue";
this.highlightCellColor = "red";
this.cells = cells,
this.layer = new Kinetic.Layer(),
this.grid = new Array(),
this.isMouseDown = false,
this.mouseLeft = false,
this.mouseRight = false,
this.adjRow = stage.getWidth() / cells,
this.adjCol = stage.getHeight() / cells;
this.generate();
stage.add(this.layer)
}
Grid.prototype.generate = function(){
var i, rx, ry, rect;
for (i = 0; i < this.cells * this.cells; i++) {
rx = Math.floor(i / this.cells) * this.adjRow;
ry = (i % this.cells) * this.adjCol;
rect = new Kinetic.Rect({
x: rx,
y: ry,
width: this.adjRow,
height: this.adjCol,
fill: this.clearCellColor,
stroke: 'black',
strokeWidth: .2,
cell: {x: Math.floor(i / this.cells), y: i % this.cells},
active: false,
grid: this //Just in case .bind(this) doesn't work right
});
rect.on('mouseenter', this.onMouseEnter.bind(this));
rect.on('mouseleave', this.onMouseLeave.bind(this));
rect.on('mousedown', this.onMouseDown.bind(this));
rect.on('mouseup', this.onMouseUp.bind(this));
this.grid.push(rect);
this.layer.add(rect);
}
}
Grid.prototype.onMouseEnter = function(evt) {
var src = evt.targetNode;
console.log(evt.type, this.isMouseDown, src.attrs.cell)
if (this.isMouseDown == true) {
src.attrs.active = ! src.attrs.active;
}
if (src.attrs.active == false) {
src.setFill(this.highlightCellColor);
} else {
src.setFill(this.activeCellColor);
}
this.layer.batchDraw();
}
Grid.prototype.onMouseLeave = function(evt) {
var src = evt.targetNode;
console.log(evt.type, this.isMouseDown, src.attrs.cell)
if (src.attrs.active == false) {
src.setFill(this.clearCellColor);
this.layer.batchDraw();
}
}
Grid.prototype.onMouseUp = function(evt){
var src = evt.targetNode;
console.log(evt.type, this.isMouseDown, src.attrs.cell)
this.isMouseDown = false;
}
Grid.prototype.onMouseDown = function(evt){
var src = evt.targetNode;
console.log(evt.type, this.isMouseDown, src.attrs.cell)
this.isMouseDown = true;
src.attrs.active = ! src.attrs.active;
if (src.attrs.active) {
src.setFill(this.activeCellColor);
} else {
src.setFill(this.clearCellColor);
}
this.layer.batchDraw();
}
var stage = new Kinetic.Stage({
container: 'canvas',
width: 600,
height: 600
}),
myGrid = new Grid(50, stage);
</script>
50x50=2500 active objects: that's too many for Kinetic to handle.
Remember that each "intelligent" Kinetic cell has a lot of overhead associated with it.
How about reducing your grid to 20x20?
Alternatively, you will have to separate the mouse handling from the cell handling to gain the required performance.
Mouse Handling
Your mouse handling would only involve capturing mouse points into an array of accumulated points. You can use this kind of code to capture mouse points on the stage:
$(stage.getContent()).on('click', function (event) {
myPointsArray.push(stage.getMousePosition());
});
Cell processing
The cell processing would involve applying those accumulated points to affect your grid cells. An effective place to do this code would be in a requestAnimationFrame (RAF) loop. You won't be doing animations, but RAF gives high performance because it is aware of the availability of system resources. An RAF loop would look like this:
function processPointsArray(array){
// request another loop even before we're done with this one
requestAnimationFrame(processPointsArray);
// process the points array and affect your cells here
}
A processing efficiency
RAF is called up to 60 times per second, so your user will probably navagate only a small portion of your grid during that time. You can increase performance by calculating the min/max x and y coordinates in the accumulated points array and only process those grid cells within that boundary.
I am developing a simple HTML5 game presently which you can play test at the following URL:
http://frankcaron.com/simplegame/game.html
The code is here:
https://github.com/frankcaron/Personal_HTML5_GamePrototype/blob/master/js/game.js
In order to animate elements, I'm using a few setIntervals. The main game loop has a setInterval which works fine. Some fading elements use them, as well, without issue. The one I'm having an issue with is one for an on-click animation.
The issue I'm having is that, in Safari and also to some extent in Chrome, the click event and animation is not responsive. It doesn't fire every time. I think there is some conflict with the concurrent intervals running. I'm not sure why.
I've done some research on the other method of HTML5 animation using requestAnimFrame but I don't think that'll solve my problem here.
Here is the code of interest:
//Track mousedown
addEventListener('mousedown', function (e) {
//Safari Fix
e.preventDefault();
//If you click while the game is going, do your special move
performSpecial();
}
//Perform a special move
var performSpecial = function () {
switch(classType)
{
case 1:
//Class 1
break;
default:
//No class
renderExplosion();
}
}
//Render explosion special move
var renderExplosion = function () {
//Temp vars
var alpha = 1.0; // full opacity
var circleMaxRadius = 32;
fadeCircle = setInterval(function () {
ctx.beginPath();
ctx.arc(hero.x + 16, hero.y + 16, circleMaxRadius, 0, 2 * Math.PI, false);
ctx.lineWidth = 5;
ctx.strokeStyle = "rgba(255, 0, 0, " + alpha + ")";
ctx.stroke();
circleMaxRadius = circleMaxRadius + 5;
alpha = alpha - 0.05 ; // decrease opacity (fade out)
if (alpha < 0) {
clearInterval(fadeCircle);
}
}, 1);
};
Welp, I rewrote the application using window.requestAnimationFrame and I no longer have this problem. The code is up on my Github if anyone wants to see the full solution.
In brief, I removed all of the intervals and replaced the entire game loop. When an animation effect is needed, I turn a flag on corresponding with the event. The renderer checks this conditional and renders the effect if the flag is on, turning the flag off again when it's done.