Excalibur project not showing anything - javascript

My code is supposedly made to show two sprites of buttons (nothing terribly complex (or is it?), but nothing is appearing, not even the blue screen that is supposed to show with only creating the game variable and initiating it. All my code has been made from following the official Excalibur documentation, so what is happening?
The code:
var game = new ex.Engine({
width: 1024,
height: 768
});
function loadAssets()
{
var loader = new ex.Loader();
var resources = {
txGameTitle: new.ex.Texture("icons/GUI/final/"),
txStartButton: new.ex.Texture("icons/GUI/final/MenuPlayButton.png"),
txLoadButton: new.ex.Texture("icons/GUI/final/MenuLoadButton.png"),
txOptionsButton: new.ex.Texture("icons/GUI/final/"),
txExitButton: new.ex.Texture("icons/GUI/final/"),
txMenuBackground: new.ex.Texture("icons/GUI/final/"),
txMenuMusic: new.ex.Sound("icons/GUI/final/")
};
for (var loadable in resources)
{
if (resources.hasOwnProperty(loadable))
{
loader.addResource(resources[loadable]);
}
}
}
function startUp()
{
var StartButton = new ex.Actor.extend({
onInitialize: function (engine)
{
this.addDrawing(txStartButton.asSprite());
}
});
var LoadButton = new ex.Actor.extend({
onInitialize: function (engine)
{
this.addDrawing(txLoadButton.asSprite());
}
});
}
function init()
{
loadAssets();
startUp();
}
init();
game.start(loader).then(function () {
console.log("Game started!");
});
sorry for the bad formatting.

I think that could be because of a code error. I noticed that right at the end of the file
game.start(loader)
the loader variable is referenced but seems like it is not defined. There is the same variable which created inside loadAssets function, but it is a local one. Probably in order to use it, you need to define it above.
var loader;
function loadAssets() {
loader = ...
}
...other code
game.start(loader).then(...
Another variant is to define loader outside the loadAssets function.
var loader = new ex.Loader();
function loadAssets() {
var resources = {...
}
...other code
game.start(loader).then(...

Related

How to run the animation only once per page?

How can I change the following code to run only once per session, and once per page. The div#edgtf-manon-loading-title appears on every page. So, on the second time the same user/session goes to the same page they went before, the animation would NOT load anymore. Thanks!
function edgtfLoadingTitle() {
var loadingTitle = $('#edgtf-manon-loading-title');
if (loadingTitle.length) {
var fallback = edgtf.body.hasClass('edgtf-ms-explorer') ? true : false;
var done = function() {
edgtfEnableScroll();
edgtf.body.addClass('edgtf-loading-title-done');
$(document).trigger('edgtfTitleDone');
};
var toTop = function() {
loadingTitle
.addClass('edgtf-to-top')
.one(edgtf.transitionEnd, done);
};
edgtfDisableScroll();
loadingTitle.addClass('edgtf-load');
if(fallback) {
toTop();
}
loadingTitle.one(edgtf.animationEnd, toTop);
}
}
Is there a way I can add something like this code below to the original? And where exactly?
var yetVisited = localStorage['visited'];
if (!yetVisited) {
//something here
};

Flickity & Swup - destroying flickity

I am trying to destroy and re-load my Flickity slideshow while using Swup for page transitions, and I am not having much luck. This is my js file:
import Swup from 'swup';
var Flickity = require('flickity');
function init() {
if (document.querySelector('.testimonials-slideshow')) {
var flkty = new Flickity('.testimonials-slideshow', {
wrapAround: true,
pageDots: false,
autoPlay: true,
arrowShape: 'M68.374,83.866L31.902,50L68.374,16.134L64.814,12.3L24.214,50L64.814,87.7L68.374,83.866Z'
});
}
}
function unload() {
flkty.destroy();
}
init();
const swup = new Swup();
swup.on('contentReplaced', init);
swup.on('willReplaceContent', unload);
But when I try this I get the error flkty is not defined. Can anyone give me any pointers on this?
Variable scoping
As mentioned by CBroe, your var is undefined because of where you define it. It is defined in a function, but should be defined at the "top level".
import Swup from 'swup';
var Flickity = require('flickity');
// Added a "global" definition here:
var flkty;
function init() {
if (document.querySelector('.testimonials-slideshow')) {
// Removed var:
flkty = new Flickity('.testimonials-slideshow', {
wrapAround: true,
pageDots: false,
autoPlay: true,
arrowShape: 'M68.374,83.866L31.902,50L68.374,16.134L64.814,12.3L24.214,50L64.814,87.7L68.374,83.866Z'
});
}
}
function unload() {
flkty.destroy();
}
init();
const swup = new Swup();
swup.on('contentReplaced', init);
swup.on('willReplaceContent', unload);
Furthermore, if you are using any kind of module bundler, sometimes it can still get lost, so you could consider doing something like:
window.flkty = new Flickity('.testimonials-slideshow', ...
And always reference it in that way, i.e.
window.flkty.destroy();
Only destroying instances that exist
That's it for your variable definition. The next potential error is that you only init flkty when the query selector matches:
if (document.querySelector('.testimonials-slideshow')) {
But you destroy it every willReplaceContent, so really you could do with a check on "is it inited, this page load?". In this instance, you can do a check like so:
// Init the var as false:
var flkty = false
function init() {
if (document.querySelector('.testimonials-slideshow')) {
flkty = new Flickity('.testimonials-slideshow', ...);
}
}
function unload() {
if(flkty){
flkty.destroy();
// Make sure the flkty var is set to false at the end:
flkty = false;
}
}
Neatening up your code
This can all get a bit out of hand, so what we started doing was creating modules. Here is a skeleton of a carousel module we use:
// modules/Carousel.js
import Swiper from "swiper";
export default {
carouselEl: null,
carouselSwiper: null,
setup() {
this.carouselEl = document.getElementById("header-carousel");
if (!this.carouselEl) {
// Just stop if there is no carousel on this page
return;
}
this.carouselSwiper = new Swiper(this.carouselEl, { ... });
this.carouselSwiper.on("slideChange", () => { ... });
},
destroy() {
// If we already have one:
if (this.carouselSwiper) {
this.carouselSwiper.destroy();
}
// Make sure we are reset, ready for next time:
this.carouselSwiper = null;
},
};
Then, in our main.js we do something like you have:
import Carousel from "./modules/Carousel.js";
function init(){
Carousel.setup();
// Add more here as the project grows...
}
function unload(){
Carousel.unload();
}
swup = new Swup();
swup.on("contentReplaced", init);
swup.on("willReplaceContent", unload);
init();
All of the modules have setup and unload functions that won't break if the elements don't exist, so we can call all of them on each page load and unload.
I love swup but also have personal experience in the nightmare of initing and destroying things so let me know if you need any further help.

How to have multiple instances of a jQuery plugin

I am trying to create a SoundCloud music player. It can play any track from SoundCloud, but this plugin is only working if there is only one instance of it in the page. So it wont work if two of the same plugin are in the page.
Here is an example of having two players in the page: JSFiddle
var trackURL = $(".player").text();
$(".player").empty();
$(".player").append("<div class='playBTN'>Play</div>");
$(".player").append("<div class='title'></div>");
var trackId;
SC.get('/resolve', { url: trackURL }, function (track) {
var trackId = track.id;
//var trackTitle = track.title;
$(".title").text(track.title);
$(".playBTN").on('click tap', function () {
//trackId = $(".DSPlayer").attr('id');
stream(trackId);
});
// first do async action
SC.stream("/tracks/" + trackId, {
useHTML5Audio: true,
preferFlash: false
}, function (goz) {
soundToPlay = goz;
sound = soundToPlay;
scTrack = sound;
//updater = setInterval( updatePosition, 100);
});
});
var is_playing = false,
sound;
function stream(trackId) {
scTrack = sound;
if (sound) {
if (is_playing) {
sound.pause();
is_playing = false;
$(".playBTN").text("Play");
} else {
sound.play();
is_playing = true;
$(".playBTN").text("Pause");
}
} else {
is_playing = true;
}
}
If you remove any of these div elements that hold the .player class, the other element will work. So it only doesn't work because there are two instances of the same plugin.
How can I fix it? to have multiple instances of the player in one page?
I have identified the problem. It has to do with the fact that you are trying to load multiple tracks at the same time, but have not separated the code to do so.
As #Greener mentioned you need to iterate over the .player instances separately and execute a SC.get() for each one of them.
Here is what I see happening that is causing the problem:
var trackURL = $(".player").text();
^The code above returns a string that contains both of the URLs you want to use back-to-back without spaces. This creates a problem down the road because of this code:
SC.get('/resolve', { url: trackURL }, function (track) {...
That is a function that is trying to load the relevant song from SoundCloud. You are passing it a variable "trackURL" for it to try and load a specific URL. The function gets a string that looks like "URLURL" what it needs is just "URL".
What you can do is iterate over all the different ".player" elements that exist and then call the sounds that way. I modified your script a little to make it work using a for loop. I had to move the "empty()" functions into the for loop to make it work correctly. You have to use .eq(index) when referring to JQuery array of elements.
Like this:
var trackURL
var trackId;
for(index = 0; index < $(".player").length; index++){
trackURL = $(".player").eq(index).text();
//alert(trackURL);
$(".player").eq(index).empty();
$(".player").eq(index).append("<div class='playBTN'>Play</div>");
$(".player").eq(index).append("<div class='title'></div>");
SC.get('/resolve', { url: trackURL }, function (track) {
var trackId = track.id;
alert(track.id);
//var trackTitle = track.title;
$(".title").eq(index).text(track.title);
$(".playBTN").eq(index).on('click tap', function () {
//trackId = $(".DSPlayer").attr('id');
stream(trackId);
});
// first do async action
SC.stream("/tracks/" + trackId, {
useHTML5Audio: true,
preferFlash: false
}, function (goz) {
soundToPlay = goz;
sound = soundToPlay;
scTrack = sound;
//updater = setInterval( updatePosition, 100);
});
});
}
This is not a completely finished code here, but it will initiate two separate songs "ready" for streaming. I checked using the commented out alert what IDs SoundCloud was giving us (which shows that its loaded now). You are doing some interesting stuff with your streaming function and with the play and pause. This should give you a good idea on what was happening and you can implement your custom code that way.

Passing functions between RequireJS files

I've got a file which needs to run on page load (randomise_colors.js), but also needs to be called by another file as part of a callback function (in infinite_scroll.js). The randomise_colors script just loops through a list of posts on the page and assigns each one a color from an array which is used on the front-end.
Infinite Scroll loads new posts in to the DOM on a button click, but because the randomise_colors.js file has already ran on page load, new content loaded is not affected by this so I need it to run again. I'm open to other suggestions if it sounds like I could be tackling the problem in a different way, I'm no JS expert.
Currently I'm getting Uncaught ReferenceError: randomise_colours is not defined referring this line of infinite_scroll.js:
randomise_colours.init();
I'm calling all files that need be loaded on document.ready in app.js
require(['base/randomise-colours', 'base/infinite-scroll'],
function(randomise_colours, infinite_scroll) {
var $ = jQuery;
$(document).ready(function() {
infinite_scroll.init();
randomise_colours.init();
});
}
);
This is infinite_scroll.js which initialises Infinite Scroll and features the callback. The callback function runs whenever new items are loaded in via AJAX using the Infinite Scroll jQuery plugin. I've put asterix around the area where I need to run the randomise_colors.init() function from randomise_colors.js.
define(['infinitescroll'], function() {
var $ = jQuery,
$loadMore = $('.load-more-posts a');
function addClasses() {
**randomise_colours.init();**
};
return {
init: function() {
if($loadMore.length >= 1) {
this.setUp();
} else {
return false;
}
},
setUp: function() {
this.initInfiniteScroll();
},
initInfiniteScroll: function() {
$('.article-listing').infinitescroll({
navSelector : '.load-more-posts',
nextSelector : '.load-more-posts a',
itemSelector : '.standard-post'
}, function(newItems) {
addClasses();
});
//Unbind the standard scroll-load function
$(window).unbind('.infscr');
//Click handler to retrieve new posts
$loadMore.on('click', function() {
$('.article-listing').infinitescroll('retrieve');
return false;
});
}
};
});
And this is my randomise_colors.js file which runs fine on load, but needs to be re-called again after new content has loaded in.
define([], function() {
var $ = jQuery,
$colouredSlide = $('.image-overlay'),
colours = ['#e4cba3', '#867d75', '#e1ecb9', '#f5f08a'],
used = [];
function pickRandomColour() {
if(colours.length == 0) {
colours.push.apply(colours, used);
used = [];
}
var selected = colours[Math.floor(Math.random() * colours.length)];
var getSelectedIndex = colours.indexOf(selected);
colours.splice(getSelectedIndex, 1);
used.push(selected);
return selected;
};
return {
init: function() {
if($colouredSlide.length >= 1) {
this.setUp();
} else {
return false;
}
},
setUp: function() {
this.randomiseColours();
},
randomiseColours: function() {
console.log('randomise');
$colouredSlide.each(function() {
var newColour = pickRandomColour();
$(this).css('background', newColour);
});
}
};
});
You would have to reference randomiseColours inside the infiniteScroll file. So you need to change your define function to the following:
define(['infinitescroll', 'randomise-colours'], function(infiniteScroll, randomise_colours)
Remember that when using require you need to reference all variables through the define function, otherwise they will not be recognised.

processing.js change script source

I need to find a way where I can dynamically change the source of a processing script inside an HTML document.
This is the embedded script which works fine:
<script type='application/processing' src='sketch.txt' id="applet">
</script>
Now I try to change the source:
$('#applet').attr('src', 'sketch2.txt');
alert($('#applet').attr('src'));
The alert shows that the source was changed to 'sketch2.txt' but the applet still remains the same. I think I need to refresh the script in some way.
Thank you in advance for any help!
I believe you have to manually attach each proc to the canvas, instead of just changing the the source file. This worked here:
function first_call(processing) {
processing.size(300,300);
processing.background(100);
var called = false;
processing.draw = function() {
if (!called) { processing.println("called #1"); called = true; }
}
}
function second_call(processing) {
processing.size(400,400);
processing.background(200);
var called = false;
processing.draw = function() {
if (!called) { processing.println("called #2"); called = true; }
}
}
var canvas = document.getElementById('canvas1');
var processingInstance = new Processing(canvas, first_call);
var processingInstance = new Processing(canvas, second_call);

Categories