Having a slight issue getting some coins to generate multiplayer using eureca.io websockets. I've got the players working multiplayer and from remote connections but I can't seem to get the coins to generate across the connection so they appear in the same place on all the players connections. I'm using phaser to generate the game and eureca and engine for my web connection. I've got the coins to spawn on the page with no problems, but whenever a new player joins, the coin always displays in a different place, I wondering how I can make them generate across the connection. My game code is below:
Game Code
var myId = 0;
var background;
var blueSquare;
var player;
var coins;
var goldCoin;
var squareList;
var coinList;
var cursors;
var score;
var highScore;
var ready = false;
var eurecaServer;
var eurecaClientSetup = function () {
var eurecaClient = new Eureca.Client();
eurecaClient.ready(function (proxy) {
eurecaServer = proxy;
});
eurecaClient.exports.setId = function (id)
{
myId = id;
create();
eurecaServer.handshake();
ready = true;
}
eurecaClient.exports.kill = function (id)
{
if (squareList[id]) {
squareList[id].kill();
console.log('Player has left the game ', id, squareList[id]);
}
}
eurecaClient.exports.spawnBlueSquare = function (i, x, y)
{
if (i == myId) return;
console.log('A new player has joined the game');
var blsq = new BlueSquare(i, game, blueSquare);
squareList[i] = blsq;
}
eurecaClient.exports.spawnCoins = function (c, x, y)
{
console.log('A coin has been generated');
var cn = new GenerateCoin(c, game, coin);
coinList[c] = cn;
}
eurecaClient.exports.updateState = function (id, state)
{
if (squareList[id]) {
squareList[id].cursor = state;
squareList[id].blueSquare.x = state.x;
squareList[id].blueSquare.y = state.y;
squareList[id].blueSquare.angle = state.angle;
squareList[id].update();
coinList.cursor = state;
coinList.blueSquare.x = state.x;
coinList.blueSquare.y = state.y;
coinList.update();
}
}
}
BlueSquare = function (index, game, player) {
this.cursor = {
left:false,
right:false,
up:false,
down:false,
}
this.input = {
left:false,
right:false,
up:false,
down:false,
}
var x = 0;
var y = 0;
this.game = game;
this.player = player;
this.currentSpeed = 0;
this.isBlue = true;
this.blueSquare = game.add.sprite(x, y, 'blueSquare');
this.blueSquare.anchor.set(0.5);
this.blueSquare.id = index;
game.physics.enable(this.blueSquare, Phaser.Physics.ARCADE);
this.blueSquare.body.immovable = false;
this.blueSquare.body.collideWorldBounds = true;
this.blueSquare.body.setSize(34, 34, 0, 0);
this.blueSquare.angle = 0;
game.physics.arcade.velocityFromRotation(this.blueSquare.rotation, 0, this.blueSquare.body.velocity);
}
BlueSquare.prototype.update = function () {
var inputChanged = (
this.cursor.left != this.input.left ||
this.cursor.right != this.input.right ||
this.cursor.up != this.input.up ||
this.cursor.down != this.input.down
);
if (inputChanged)
{
if (this.blueSquare.id == myId)
{
this.input.x = this.blueSquare.x;
this.input.y = this.blueSquare.y;
this.input.angle = this.blueSquare.angle;
eurecaServer.handleKeys(this.input);
}
}
if (this.cursor.left)
{
this.blueSquare.body.velocity.x = -250;
this.blueSquare.body.velocity.y = 0;
}
else if (this.cursor.right)
{
this.blueSquare.body.velocity.x = 250;
this.blueSquare.body.velocity.y = 0;
}
else if (this.cursor.down)
{
this.blueSquare.body.velocity.x = 0;
this.blueSquare.body.velocity.y = 250;
}
else if (this.cursor.up)
{
this.blueSquare.body.velocity.x = 0;
this.blueSquare.body.velocity.y = -250;
}
else
{
this.blueSquare.body.velocity.x = 0;
this.blueSquare.body.velocity.y = 0;
}
}
BlueSquare.prototype.kill = function () {
this.alive = false;
this.blueSquare.kill();
}
GenerateCoin = function (game, goldCoin) {
this.game = game;
this.goldCoin = goldCoin;
x = 0;
y = 0;
this.coins = game.add.sprite(x, y, 'coin');
game.physics.enable(this.coins, Phaser.Physics.ARCADE);
this.coins.body.immovable = true;
this.coins.body.collideWorldBounds = true;
this.coins.body.setSize(16, 16, 0, 0);
}
window.onload = function() {
function countdown( elementName, minutes, seconds )
{
var element, endTime, hours, mins, msLeft, time;
function twoDigits( n )
{
return (n <= 9 ? "0" + n : n);
}
function updateTimer()
{
msLeft = endTime - (+new Date);
if ( msLeft < 1000 ) {
element.innerHTML = "Game Over!";
} else {
time = new Date( msLeft );
hours = time.getUTCHours();
mins = time.getUTCMinutes();
element.innerHTML = (hours ? hours + ':' + twoDigits( mins ) : mins) + ':' + twoDigits( time.getUTCSeconds() );
setTimeout( updateTimer, time.getUTCMilliseconds() + 500 );
}
}
element = document.getElementById( elementName );
endTime = (+new Date) + 1000 * (60*minutes + seconds) + 500;
updateTimer();
}countdown( "countdown", 5, 0 );
}
var game = new Phaser.Game(700, 600, Phaser.AUTO, 'Square Hunt', { preload: preload, create: eurecaClientSetup, update: update, render: render });
function preload () {
game.load.spritesheet('coin', 'assets/coin.png', 18, 18);
game.load.image('blueSquare', 'assets/blue-square.png');
game.load.image('redSquare', 'assets/red-square.png');
game.load.image('earth', 'assets/sand.png');
}
function create () {
game.world.setBounds(0, 0, 1500, 1500);
game.stage.disableVisibilityChange = true;
background = game.add.tileSprite(0, 0, 800, 600, 'earth');
background.fixedToCamera = true;
squareList = {};
player = new BlueSquare(myId, game, blueSquare);
squareList[myId] = player;
blueSquare = player.blueSquare;
blueSquare.x = Math.floor(Math.random() * 650);
blueSquare.y = Math.floor(Math.random() * 650);
blueSquare.bringToTop();
game.camera.follow(blueSquare);
game.camera.deadzone = new Phaser.Rectangle(150, 150, 500, 300);
game.camera.focusOnXY(0, 0);
cursors = game.input.keyboard.createCursorKeys();
coinList = {};
goldCoin = new GenerateCoin(game, coins);
coinList = goldCoin;
coins = goldCoin.coins;
coins.x = Math.floor(Math.random() * 650);
coins.y = Math.floor(Math.random() * 650);
coins.bringToTop();
}
function update () {
if (!ready) return;
game.physics.arcade.collide(blueSquare, coins);
player.input.left = cursors.left.isDown;
player.input.right = cursors.right.isDown;
player.input.up = cursors.up.isDown;
player.input.down = cursors.down.isDown;
player.input.fire = game.input.activePointer.isDown;
player.input.tx = game.input.x+ game.camera.x;
player.input.ty = game.input.y+ game.camera.y;
background.tilePosition.x = -game.camera.x;
background.tilePosition.y = -game.camera.y;
for (var i in squareList)
{
if (!squareList[i]) continue;
var curBlue = squareList[i].blueSquare;
for (var j in squareList)
{
if (!squareList[j]) continue;
if (j!=i)
{
var targetBlue = squareList[j].blueSquare;
}
if (squareList[j].isBlue)
{
squareList[j].update();
}
}
}
}
function test(){
console.log('collsion');
}
function render () {}
Server.js Files
var express = require('express')
, app = express(app)
, server = require('http').createServer(app);
app.use(express.static(__dirname));
var clients = {};
var EurecaServer = require('eureca.io').EurecaServer;
var eurecaServer = new EurecaServer({allow:['setId', 'spawnBlueSquare', 'spawnCoins', 'kill', 'updateState']});
eurecaServer.attach(server);
eurecaServer.onConnect(function (conn) {
console.log('New Client id=%s ', conn.id, conn.remoteAddress);
var remote = eurecaServer.getClient(conn.id);
clients[conn.id] = {id:conn.id, remote:remote}
remote.setId(conn.id);
});
eurecaServer.onConnectionLost(function (conn) {
console.log('connection lost ... will try to reconnect');
});
eurecaServer.onDisconnect(function (conn) {
console.log('Client disconnected ', conn.id);
var removeId = clients[conn.id].id;
delete clients[conn.id];
for (var c in clients)
{
var remote = clients[c].remote;
remote.kill(conn.id);
}
});
eurecaServer.exports.handshake = function()
{
for (var c in clients)
{
var remote = clients[c].remote;
for (var cc in clients)
{
var x = clients[cc].laststate ? clients[cc].laststate.x: 0;
var y = clients[cc].laststate ? clients[cc].laststate.y: 0;
remote.spawnBlueSquare(clients[cc].id, x, y);
}
}
}
eurecaServer.exports.handleKeys = function (keys) {
var conn = this.connection;
var updatedClient = clients[conn.id];
for (var c in clients)
{
var remote = clients[c].remote;
remote.updateState(updatedClient.id, keys);
clients[c].laststate = keys;
}
}
server.listen(8000);
Instead of generating coins randomly positioned on each client, you could generate this random position(x and y) in server side(on conexion event) and then send this position to all clients so they can generate the coin in the same position.
Related
Long story short, I made this Simon Game in a bootcamp a month ago in jQuery, but the days pass and I started to feel the necesity of translate it to pure vanilla javaScript.
the thing is that I feel stuck in the last part, when I have to check the answers of the game and add that to the gamePatern array and userChosenPattern.
here is the main part in jQuery
var buttonColors = ["red", "blue", "green", "yellow"];
var gamePattern = [];
var userClickedPattern = [];
var started = false;
var level = 0;
$(document).keypress(function () {
if (!started) {
$("#level-title").text("level " + level);
nextSequence();
started = true;
}
});
function nextSequence() {
userClickedPattern = [];
level++;
$("#level-title").text("level " + level);
var randomNumber = Math.floor(Math.random() * 4);
var randomChosenColour = buttonColors[randomNumber];
gamePattern.push(randomChosenColour);
$("#" + randomChosenColour)
.fadeIn(100)
.fadeOut(100)
.fadeIn(100);
playSound(randomChosenColour);
}
$(".btn").click(function () {
var userChosenColor = $(this).attr("id");
userClickedPattern.push(userChosenColor);
playSound(userChosenColor);
animatePress(userChosenColor);
checkTheAnswer(userClickedPattern.length - 1);
});
function checkTheAnswer(currentLevel) {
if (gamePattern[currentLevel] === userClickedPattern[currentLevel]) {
console.log("success");
if (userClickedPattern.length === gamePattern.length) {
setTimeout(function () {
nextSequence();
}, 1000);
}
} else {
$("body").addClass("game-over");
setTimeout(function () {
$("body").removeClass("game-over");
}, 200);
gameOverAudio();
$("#level-title").text("Game Over, Press Any Key to Restart");
$("#level-title").css("font-size", "2rem");
startOver();
}
}
function startOver() {
level = 0;
gamePattern = [];
started = false;
}
function playSound(name) {
var audio = new Audio("sounds/" + name + ".mp3");
audio.play();
}
function gameOverAudio() {
var gameOver = new Audio("sounds/wrong.mp3");
gameOver.play();
}
function animatePress(currentColor) {
$("#" + currentColor).addClass("pressed");
setTimeout(function () {
$("#" + currentColor).removeClass("pressed");
}, 100);
}
and here is the same part and the whole code but in vanilla JS
const buttonColors = ["red", "blue", "green", "yellow"];
const gamePattern = [];
const userClickedPattern = [];
const started = false;
const level = 0;
const body = document.querySelector("body");
const levelTitle = document.getElementById("level-title");
// to start the game
document.addEventListener("keypress", () => {
if (!started) {
levelTitle.innerHTML = `level ${level}`;
nextSequence();
sarted = true;
}
});
// generete the next sequence
function nextSequence() {
var randomNumber = Math.floor(Math.random() * 4);
var randomChosenColour = buttonColors[randomNumber];
gamePattern.push(randomChosenColour);
let animationBtn = document.querySelector("#" + randomChosenColour);
animationBtn.classList.add("FadeInFadeOut");
setTimeout(() => {
animationBtn.classList.remove("FadeInFadeOut");
}, 50);
playSound(randomChosenColour);
}
// here we detect which button is pressed by the user
var bTn = document.getElementsByClassName("btn");
document.querySelectorAll(".btn").forEach((bt) => {
bt.onclick = () => {
let userChosenColor = bt.id;
userClickedPattern.push(userChosenColor);
playSound(userChosenColor);
animatePress(userChosenColor);
checkTheAnswer(userClickedPattern.length - 1);
};
});
// check the answer and dynamic of the game
const checkTheAnswer = (currentLevel) => {
if (gamePattern[currentLevel] === userClickedPattern[currentLevel]) {
console.log("succes");
if (userClickedPattern.length === gamePattern.length) {
setTimeout(() => {
nextSequence();
}, 1000);
}
} else {
body.classList.add("game-over");
setTimeout(() => {
body.classList.remove("game-over");
}, 200);
gameOverAudio();
levelTitle.innerHTML = `Game Over, Press Any Key to Restart`;
levelTitle.style.fontSize = "2rem";
startOver();
}
};
const startOver = () => {
level = 0;
gamePattern = [];
started = false;
};
// adudio stuff
const playSound = (name) => {
let audio = new Audio("sounds/" + name + ".mp3");
audio.play();
};
function gameOverAudio() {
var gameOver = new Audio("sounds/wrong.mp3");
gameOver.play();
}
//animation in button
const animatePress = (currentColor) => {
const buttons = document.querySelector(`#${currentColor}`);
buttons.classList.add("pressed");
setTimeout(() => {
buttons.classList.remove("pressed");
}, 100);
};
console.log(gamePattern);
console.log(userClickedPattern);
Also here is the game in my codepen, it’s without the sounds for obvious reasons.
Simon Game
I'm have 2 websites hosted on localhost with different ports and I'm trying to make first one only to send data and second one only to receive that data. Earlier, I made that happens with only one website. User could login, and logged users could change data and that data would be emitted to all other users. Users which aren't logged could just view page. But there were so many problems. Taking that a part would fix some problems. I'm trying to do all this without back-end experience and knowledge just watching some videos and pasting code, and I'm sorry about that, I know this is wrong. I figured out some things but I can't make it work. So here is my terrible code:
This is node.js code for website which will send data
var express = require("express");
var app = express();
var server = app.listen(3000);
app.use(express.static('public'));
var socket = require("socket.io");
var io = socket(server);
io.sockets.on('connection', newConnection);
function newConnection(socket)
{
console.log('Connection: ' + socket.id);
socket.on('data', dataMsg);
function dataMsg(data)
{
socket.broadcast.emit('data', data);
}
}
This is javascript code for website which will send data which works fine
Btw functions press1(), press2() etc. are called from html by clicking certain buttons
let ps = 2.5;
let bl = 3.5;
const socket = io('http://localhost:3000');
function update(data)
{
buttons[0].time = data.btn11;
buttons[0].price = data.btn12;
buttons[1].time = data.btn21;
buttons[1].price = data.btn22;
buttons[2].time = data.btn31;
buttons[2].price = data.btn32;
buttons[3].time = data.btn41;
buttons[3].price = data.btn42;
}
let buttons = [];
buttons[0] = new Button(ps);
buttons[1] = new Button(ps);
buttons[2] = new Button(ps);
buttons[3] = new Button(bl);
let arr = [];
arr[0] = [document.getElementById("prviprvi"), document.getElementById('prvidrugi')];
arr[1] = [document.getElementById('drugiprvi'), document.getElementById('drugidrugi')];
arr[2] = [document.getElementById('treciprvi'), document.getElementById('trecidrugi')];
arr[3] = [document.getElementById('cetvrtiprvi'), document.getElementById('cetvrtidrugi')];
var tempD = setInterval( () => {
var data = {
btn11 : buttons[0].time,
btn12 : buttons[0].price,
btn21 : buttons[1].time,
btn22 : buttons[1].price,
btn31 : buttons[2].time,
btn32 : buttons[2].price,
btn41 : buttons[3].time,
btn42 : buttons[3].price
}
socket.emit("data", data);
for(var i = 0; i < 4; i++)
{
buttons[i].update();
buttons[i].show(arr[i][0], arr[i][1]);
}
},100);
function press1()
{
buttons[0].press();
}
function press2()
{
buttons[1].press();
}
function press3()
{
buttons[2].press();
}
function press4()
{
buttons[3].press();
}
function Button(tempD1)
{
this.val = tempD1;
this.pressed = false;
this.startingTime = Date.now();
this.endingTime = Date.now();
this.hours = 0;
this.min = 0;
this.sec = 0;
this.price = 0;
this.time = "0:0:0";
this.show = function(span1, span2)
{
span1.innerHTML = this.time;
span2.innerHTML = this.price + " Din";
}
this.update = function()
{
if(this.pressed)
{
this.endingTime = Date.now();
this.tempD = this.endingTime - this.startingTime;
this.sec = parseInt((this.tempD / 1000) % 60);
this.min = parseInt(((this.tempD / 1000) / 60) % 60);
this.hours = parseInt((((this.tempD / 1000) / 60) / 60) % 24);
this.time = this.hours + ":" + this.min + ":" + this.sec;
this.price = this.hours * 60 * this.val + this.min * this.val;
}
}
this.press = function()
{
if(this.pressed == false)
{
this.startingTime = Date.now();
this.pressed = true;
}
else
{
this.pressed = false;
}
}
}
This is node.js for website which receiving data
var express = require("express");
var app = express();
var server = app.listen(3001);
app.use(express.static('public'));
var socket = require("socket.io");
var io = socket('localhost:3000');
io.sockets.on('connection', newConnection);
function newConnection(socket)
{
console.log('Connection: ' + socket.id);
socket.on('data', dataMsg);
function dataMsg(data)
{
socket.broadcast.emit('data', data);
}
}
This is javascript code for website which receiving data
let ps = 2.5;
let bl = 3.5;
const socket = io('http://localhost:3000');
socket.on('data', update);
function update(data)
{
buttons[0].time = data.btn11;
buttons[0].price = data.btn12;
buttons[1].time = data.btn21;
buttons[1].price = data.btn22;
buttons[2].time = data.btn31;
buttons[2].price = data.btn32;
buttons[3].time = data.btn41;
buttons[3].price = data.btn42;
}
var tempD = setInterval( () => {
for(var i = 0; i < 4; i++)
buttons[i].show(arr[i][0], arr[i][1]);
}
let buttons = [];
buttons[0] = new Button(ps);
buttons[1] = new Button(ps);
buttons[2] = new Button(ps);
buttons[3] = new Button(bl);
let arr = [];
arr[0] = [document.getElementById("prviprvi"), document.getElementById('prvidrugi')];
arr[1] = [document.getElementById('drugiprvi'), document.getElementById('drugidrugi')];
arr[2] = [document.getElementById('treciprvi'), document.getElementById('trecidrugi')];
arr[3] = [document.getElementById('cetvrtiprvi'), document.getElementById('cetvrtidrugi')];
function Button(tempD1)
{
this.val = tempD1;
this.pressed = false;
this.startingTime = Date.now();
this.endingTime = Date.now();
this.hours = 0;
this.min = 0;
this.sec = 0;
this.price = 0;
this.time = "0:0:0";
this.show = function(span1, span2)
{
span1.innerHTML = this.time;
span2.innerHTML = this.price + " Din";
}
this.update = function()
{
if(this.pressed)
{
this.endingTime = Date.now();
this.tempD = this.endingTime - this.startingTime;
this.sec = parseInt((this.tempD / 1000) % 60);
this.min = parseInt(((this.tempD / 1000) / 60) % 60);
this.hours = parseInt((((this.tempD / 1000) / 60) / 60) % 24);
this.time = this.hours + ":" + this.min + ":" + this.sec;
this.price = this.hours * 60 * this.val + this.min * this.val;
}
}
this.press = function()
{
if(this.pressed == false)
{
this.startingTime = Date.now();
this.pressed = true;
}
else
{
this.pressed = false;
}
}
}
Asking this may be too much but I will do it anyway:
How to allow access to the one which sends data with just the right password.
When user go to website he will be asked for password and if he type right one, he will be forwarded further. I did it last time in javascript but anyone could just go to inspect elements and see password
Thank you!
I am using slick carousel slider which has 5 slides, each slide should trigger an animation after it gets displayed on the page.
An animator has created an animation using Adobe Animate CC and exported the animation in createjs format so it is compatible with html5.
If I try to call the animation on afterchange I get an error:
TypeError: lib.FlowerGrowTemplate is not a constructor
See the comment below for where the error is happening:
/*The error is pointing to here*/
Adobe Animate CC generated javascript code:
(function (cjs, an) {
var p; // shortcut to reference prototypes
var lib={};var ss={};var img={};
lib.ssMetadata = [];
// symbols:
// helper functions:
function mc_symbol_clone() {
var clone = this._cloneProps(new this.constructor(this.mode, this.startPosition, this.loop));
clone.gotoAndStop(this.currentFrame);
clone.paused = this.paused;
clone.framerate = this.framerate;
return clone;
}
function getMCSymbolPrototype(symbol, nominalBounds, frameBounds) {
var prototype = cjs.extend(symbol, cjs.MovieClip);
prototype.clone = mc_symbol_clone;
prototype.nominalBounds = nominalBounds;
prototype.frameBounds = frameBounds;
return prototype;
}
.....
})(createjs = createjs||{}, AdobeAn = AdobeAn||{});
var createjs, AdobeAn;
var graphic_canvas_1, graphic_stage_1, graphic_exportRoot_1, graphic_container_1, graphic_dom_overlay_container_1, graphic_fnStartAnimation_1;
function graphic_init_1() {
graphic_canvas_1 = document.getElementById("graphic_canvas");
graphic_container_1 = document.getElementById("graphic_container");
graphic_dom_overlay_container_1 = document.getElementById("graphic_dom_overlay_container");
var comp=AdobeAn.getComposition("AD6FD640782B2A4DAD43D647860AC61B");
var lib=comp.getLibrary();
graphic_handleComplete_1({},comp);
}
function graphic_handleComplete_1(evt,comp) {
//This function is always called, irrespective of the content. You can use the variable "stage" after it is created in token create_stage.
var lib=comp.getLibrary();
var ss=comp.getSpriteSheet();
graphic_exportRoot_1 = new lib.FlowerGrowTemplate(); /*The error is pointing to here*/
graphic_stage_1 = new lib.Stage(graphic_canvas_1);
//Registers the "tick" event listener.
graphic_fnStartAnimation_1 = function() {
graphic_stage_1.addChild(graphic_exportRoot_1);
createjs.Ticker.setFPS(lib.properties.fps);
createjs.Ticker.addEventListener("tick", graphic_stage_1)
graphic_stage_1.addEventListener("tick", graphic_handleTick_1)
function graphic_getProjectionMatrix_1(container, totalDepth) {
var focalLength = 528.25;
var projectionCenter = { x : lib.properties.width/2, y : lib.properties.height/2 };
var scale = (totalDepth + focalLength)/focalLength;
var scaleMat = new createjs.Matrix2D;
scaleMat.a = 1/scale;
scaleMat.d = 1/scale;
var projMat = new createjs.Matrix2D;
projMat.tx = -projectionCenter.x;
projMat.ty = -projectionCenter.y;
projMat = projMat.prependMatrix(scaleMat);
projMat.tx += projectionCenter.x;
projMat.ty += projectionCenter.y;
return projMat;
}
function graphic_handleTick_1(event) {
var cameraInstance = graphic_exportRoot_1.___camera___instance;
if(cameraInstance !== undefined && cameraInstance.pinToObject !== undefined)
{
cameraInstance.x = cameraInstance.pinToObject.x + cameraInstance.pinToObject.pinOffsetX;
cameraInstance.y = cameraInstance.pinToObject.y + cameraInstance.pinToObject.pinOffsetY;
if(cameraInstance.pinToObject.parent !== undefined && cameraInstance.pinToObject.parent.depth !== undefined)
cameraInstance.depth = cameraInstance.pinToObject.parent.depth + cameraInstance.pinToObject.pinOffsetZ;
}
graphic_applyLayerZDepth_1(graphic_exportRoot_1);
}
function graphic_applyLayerZDepth_1(parent)
{
var cameraInstance = parent.___camera___instance;
var focalLength = 528.25;
var projectionCenter = { 'x' : 0, 'y' : 0};
if(parent === graphic_exportRoot_1)
{
var stageCenter = { 'x' : lib.properties.width/2, 'y' : lib.properties.height/2 };
projectionCenter.x = stageCenter.x;
projectionCenter.y = stageCenter.y;
}
for(child in parent.children)
{
var layerObj = parent.children[child];
if(layerObj == cameraInstance)
continue;
graphic_applyLayerZDepth_1(layerObj, cameraInstance);
if(layerObj.layerDepth === undefined)
continue;
if(layerObj.currentFrame != layerObj.parent.currentFrame)
{
layerObj.gotoAndPlay(layerObj.parent.currentFrame);
}
var matToApply = new createjs.Matrix2D;
var cameraMat = new createjs.Matrix2D;
var totalDepth = layerObj.layerDepth ? layerObj.layerDepth : 0;
var cameraDepth = 0;
if(cameraInstance && !layerObj.isAttachedToCamera)
{
var mat = cameraInstance.getMatrix();
mat.tx -= projectionCenter.x;
mat.ty -= projectionCenter.y;
cameraMat = mat.invert();
cameraMat.prependTransform(projectionCenter.x, projectionCenter.y, 1, 1, 0, 0, 0, 0, 0);
cameraMat.appendTransform(-projectionCenter.x, -projectionCenter.y, 1, 1, 0, 0, 0, 0, 0);
if(cameraInstance.depth)
cameraDepth = cameraInstance.depth;
}
if(layerObj.depth)
{
totalDepth = layerObj.depth;
}
//Offset by camera depth
totalDepth -= cameraDepth;
if(totalDepth < -focalLength)
{
matToApply.a = 0;
matToApply.d = 0;
}
else
{
if(layerObj.layerDepth)
{
var sizeLockedMat = graphic_getProjectionMatrix_1(parent, layerObj.layerDepth);
if(sizeLockedMat)
{
sizeLockedMat.invert();
matToApply.prependMatrix(sizeLockedMat);
}
}
matToApply.prependMatrix(cameraMat);
var projMat = graphic_getProjectionMatrix_1(parent, totalDepth);
if(projMat)
{
matToApply.prependMatrix(projMat);
}
}
layerObj.transformMatrix = matToApply;
}
}
}
//Code to support hidpi screens and responsive scaling.
function graphic_makeResponsive_1(isResp, respDim, isScale, scaleType) {
var lastW, lastH, lastS=1;
window.addEventListener('resize', graphic_resizeCanvas_1);
graphic_resizeCanvas_1();
function graphic_resizeCanvas_1() {
var w = lib.properties.width, h = lib.properties.height;
var iw = window.innerWidth, ih=window.innerHeight;
var pRatio = window.devicePixelRatio || 1, xRatio=iw/w, yRatio=ih/h, sRatio=1;
if(isResp) {
if((respDim=='width'&&lastW==iw) || (respDim=='height'&&lastH==ih)) {
sRatio = lastS;
}
else if(!isScale) {
if(iw<w || ih<h)
sRatio = Math.min(xRatio, yRatio);
}
else if(scaleType==1) {
sRatio = Math.min(xRatio, yRatio);
}
else if(scaleType==2) {
sRatio = Math.max(xRatio, yRatio);
}
}
graphic_canvas_1.width = w*pRatio*sRatio;
graphic_canvas_1.height = h*pRatio*sRatio;
graphic_canvas_1.style.width = graphic_dom_overlay_container_1.style.width = graphic_container_1.style.width = w*sRatio+'px';
graphic_canvas_1.style.height = graphic_container_1.style.height = graphic_dom_overlay_container_1.style.height = h*sRatio+'px';
graphic_stage_1.scaleX = pRatio*sRatio;
graphic_stage_1.scaleY = pRatio*sRatio;
lastW = iw; lastH = ih; lastS = sRatio;
graphic_stage_1.tickOnUpdate = false;
graphic_stage_1.update();
graphic_stage_1.tickOnUpdate = true;
}
}
graphic_makeResponsive_1(false,'both',false,1);
AdobeAn.compositionLoaded(lib.properties.id);
graphic_fnStartAnimation_1();
}
My javascript code:
(function($){
$('.custom-graphic-slider .slider').slick({
slidesToShow: 1,
slidesToScroll: 1,
arrows: false,
dots: true,
fade: true,
});
$('.custom-graphic-slider .slider').on('afterChange', function(event, slick, currentSlide){
graphic_init_1();
});
})(jQuery);
I hope everything makes sense
How can I use PIXI js to animate from spritesheets using TiledSprites? I need to animate a tiled sprite background from a sprite sheet.
Currently there is API calls to animate a tiled sprite in the PIXI.js API. I have created the following class to help me load and animate tiled backgrounds.
/////////////////////////////////////////////////////////////////////////////
/// Tiling Sprite Animation
/////////////////////////////////////////////////////////////////////////////
(function() {
PIXI.TilingSpriteAnimation = function(texture, frames, rows, frametime, loop) {
PIXI.TilingSprite.call(
this, texture,
VIEWPORTWIDTH,
this._texture.baseTexture.height);
this._stop = true;
this._texture = new PIXI.Texture(texture);
this.frameTime = frametime;
this.loop = loop || true;
this.curX = 0;
this.curY = 0;
this.fh = this._texture.height / rows;
this.fw = this._texture.width / frames;
this.ticks = 0;
this.maxFrames = frames;
this.maxRows = rows;
this.done = false;
this.calculateFrame();
};
PIXI.TilingSpriteAnimation.prototype = Object.create( PIXI.TilingSprite.prototype );
PIXI.TilingSpriteAnimation.prototype.constructor = PIXI.TilingSpriteAnimation;
Object.defineProperty(PIXI.TilingSpriteAnimation.prototype, 'texture', {
get: function() {
return this._texture;
}
});
PIXI.TilingSpriteAnimation.prototype.update = function() {
console.log(this.ticks);
if(!this._stop) {
this.ticks += 1;
}
if (this.done == false) {
if (this.ticks >= this.frameTime) {
this.curX++;
this.ticks = 0;
if (this.curX == this.maxFrames) {
this.curX = 0;
this.curY++;
if (this.curY == this.maxRows) {
this.curY = 0;
if (!this.loop)
this.done = true;
}
}
this.calculateFrame();
}
}
};
PIXI.TilingSpriteAnimation.prototype.goto = function(frame, row) {
this.curX = frame;
this.curY = row || 0;
};
PIXI.TilingSpriteAnimation.prototype.stop = function() {
this._stop = true;
};
PIXI.TilingSpriteAnimation.prototype.play = function() {
this._stop = false;
};
PIXI.TilingSpriteAnimation.prototype.calculateFrame = function() {
this.texture.frame.x = this.curX * this.fw;
this.texture.frame.y = this.curY * this.fh;
this.texture.frame.width = this.fw;
this.texture.frame.height = this.fh;
this.texture.setFrame(this.texture.frame);
this.generateTilingTexture(this.texture);
};
}).call(this);
This code is however highly inefficient because it calculates a new TiledTexture each time a new frame is entered. How can I optimize this?
I struggeled some time with this but came up with the following. I hope it helps
/////////////////////////////////////////////////////////////////////////////
/// Tiling Sprite Animation
/////////////////////////////////////////////////////////////////////////////
(function() {
PIXI.TilingSpriteAnimation = function(texture, frames, frametime, loop) {
PIXI.TilingSprite.call(
this, texture,
VIEWPORTWIDTH,
VIEWPORTHEIGHT);
this._stop = true;
this._texture = new PIXI.Texture(texture);
this.frameTime = frametime;
this.loop = loop || true;
this.curX = 0;
this.fh = this._texture.height;
this.fw = this._texture.width / frames;
this.ticks = 0;
this.maxFrames = frames;
for (var i=0;i<frames;i++){
this.preLoadFrame(i);
}
this.calculateFrame();
};
PIXI.TilingSpriteAnimation.prototype = Object.create( PIXI.TilingSprite.prototype );
PIXI.TilingSpriteAnimation.prototype.constructor = PIXI.TilingSpriteAnimation;
Object.defineProperty(PIXI.TilingSpriteAnimation.prototype, 'texture', {
get: function() {
return this._texture;
}
});
PIXI.TilingSpriteAnimation.prototype.update = function() {
if (this._stop == false) {
this.ticks += 1;
if (this.ticks >= this.frameTime) {
this.curX++;
this.ticks = 0;
if (this.curX == this.maxFrames) {
this.curX = 0;
if (!this.loop) {
this._stop = true;
}
}
this.calculateFrame();
}
}
};
PIXI.TilingSpriteAnimation.prototype.goto = function(frame) {
this.curX = frame;
};
PIXI.TilingSpriteAnimation.prototype.stop = function() {
this._stop = true;
};
PIXI.TilingSpriteAnimation.prototype.play = function() {
this._stop = false;
};
PIXI.TilingSpriteAnimation.prototype.calculateFrame = function() {
this.tilingTexture = PIXI.Texture.fromFrame("texture" + this.curX);
};
PIXI.TilingSpriteAnimation.prototype.preLoadFrame = function(frame) {
var text = new PIXI.TilingSprite(this.texture);
text.texture.frame.x = frame * this.fw;
text.texture.frame.y = 0;
text.texture.frame.width = this.fw;
text.texture.frame.height = this.fh;
text.texture.setFrame(text.texture.frame);
text.generateTilingTexture(text);
PIXI.Texture.addTextureToCache(text.tilingTexture, "texture" + frame)
};
}).call(this);
Here is the module i am working on:
var FeatureRotator = (function($,global) {
var self = {},
currentFeature = 0,
images = [],
imagePrefix = "/public/images/features/",
timer = null,
totalImages = 0,
initialFeature,
interval,
blendSpeed,
element = null,
img1 = null,
img2 = null;
function setVisibleImage(iid) {
$("#img1").attr('src',images[iid].src).css('opacity',1);
$("#img2").css('opacity',0);
$(".active").removeClass("active");
$("#f"+iid).addClass("active");
}
function setCurrentImage(id) {
currentFeature = id;
setVisibleImage(id);
}
function doHoverIn(position) {
if (currentFeature === position) {
self.pause();
} else {
setCurrentImage(global.parseInt(position, 10));
self.pause();
}
}
function doHoverOut(position) {
self.unpause();
}
self.init = function(options,callback) {
var i = 0,
tempImg = null;
interval = options.interval || 5000;
blendSpeed = options.blendSpeed || 500;
element = options.element;
initialFeature = options.initialFeature || 0;
img1 = $("<img/>").attr('id','img1');
img2 = $("<img/>").attr('id','img2').css('opacity','0').css('margin-top',-options.height);
$(element).append(img1).append(img2);
totalImages = $(".feature").size();
for (i = 0;i < totalImages; i++) {
tempImg = new global.Image();
tempImg.src = imagePrefix +"feature_" + i + ".png";
images.push(tempImg);
$("#f"+i).css('background-image',
'url("'+imagePrefix+"feature_"+i+"_thumb.png"+'")')
.hover(doHoverIn($(this).attr('position'))
, doHoverOut($(this).attr('position'))
).attr('position',i);
}
setVisibleImage(initialFeature);
if (options.autoStart) {
self.start();
}
if (callback !== null) {
callback();
}
};
function updateImage() {
var active = $("#img1").css('opacity') === 1 ? "#img1" : "#img2";
var nextFeature = (currentFeature === totalImages-1 ? 0 : currentFeature+1);
if (active === "#img1") {
$("#img2").attr('src',images[nextFeature].src);
$("#img2").fadeTo(blendSpeed, 1);
$("#img1").fadeTo(blendSpeed, 0);
} else {
$("#img1").attr('src',images[nextFeature].src);
$("#img1").fadeTo(blendSpeed, 1);
$("#img2").fadeTo(blendSpeed, 0);
}
$("#f"+currentFeature).removeClass("active");
$("#f"+nextFeature).addClass("active");
currentFeature = nextFeature;
}
self.start = function() {
currentFeature = initialFeature;
setVisibleImage(currentFeature);
timer = global.setInterval(function(){
updateImage();
}, interval);
};
self.pause = function() {
global.clearTimeout(timer);
};
self.unpause = function() {
timer = global.setInterval(function(){
updateImage();
}, interval);
};
return self;
}(this.jQuery, this));
And here is how it is used on the page:
<script type="text/javascript">
// ...
$(function() {
FeatureRotator.init({
interval:5000,
element:'#intro',
autoStart:true,
height:177,
blendSpeed:1000,
initialFeature:0
});
});
</script>
The problem is, when setVisibleImage is called from the init method, the value of iid is NaN. I've stepped through the debugger and verified that 'initialFeature' is 0 when the setVisibleImage function is called, but alas, the value doesn't make it over there.
Can anyone help me determine what the problem is? I've run the code through JSLint, and it came back clean.
UPDATE
Ok here is my updated code, which works now except the fading doesnt work, the image just flips to the next one and doesn't fade smoothly anymore:
var FeatureRotator = (function($,global) {
var self = {},
currentFeature = 0,
images = [],
imagePrefix = "/public/images/features/",
timer = null,
totalImages = 0,
initialFeature = 0,
interval,
blendSpeed;
function setVisibleImage(iid) {
$("#img1").attr('src',images[iid].src).css('opacity',1);
$("#img2").css('opacity',0);
$(".active").removeClass("active");
$("#f"+iid).addClass("active");
}
function setCurrentImage(id) {
currentFeature = id;
setVisibleImage(id);
}
function doHoverIn(obj) {
var position = global.parseInt(obj.target.attributes["position"].value,10);
if (currentFeature === position) {
self.pause();
} else {
setCurrentImage(global.parseInt(position, 10));
self.pause();
}
}
function doHoverOut() {
self.unpause();
}
self.init = function(options,callback) {
var i = 0,
tempImg = null,
element = null,
img1 = null,
img2 = null;
interval = options.interval || 5000;
blendSpeed = options.blendSpeed || 500;
element = options.element;
initialFeature = options.initialFeature || 0;
img1 = $("<img/>").attr('id','img1');
img2 = $("<img/>").attr('id','img2').css('opacity','0').css('margin-top',-options.height);
$(element).append(img1).append(img2);
totalImages = $(".feature").size();
for (i = 0;i < totalImages; i++) {
tempImg = new global.Image();
tempImg.src = imagePrefix +"feature_" + i + ".png";
images.push(tempImg);
$("#f"+i).css('background-image','url("'+imagePrefix+"feature_"+i+"_thumb.png"+'")')
.hover(doHoverIn, doHoverOut)
.attr('position',i);
}
setVisibleImage(initialFeature);
if (options.autoStart) {
self.start();
}
if (typeof callback === "function") {
callback();
}
};
function updateImage() {
var active = $("#img1").css('opacity') === 1 ? "#img1" : "#img2";
var nextFeature = (currentFeature === totalImages-1 ? 0 : currentFeature+1);
if (active === "#img1") {
$("#img2").attr('src',images[nextFeature].src);
$("#img2").fadeTo(blendSpeed, 1);
$("#img1").fadeTo(blendSpeed, 0);
} else {
$("#img1").attr('src',images[nextFeature].src);
$("#img1").fadeTo(blendSpeed, 1);
$("#img2").fadeTo(blendSpeed, 0);
}
$("#f"+currentFeature).removeClass("active");
$("#f"+nextFeature).addClass("active");
currentFeature = nextFeature;
}
self.start = function() {
currentFeature = initialFeature;
setVisibleImage(currentFeature);
timer = global.setInterval(function(){
updateImage();
}, interval);
};
self.stop = function() {
global.clearTimeout(timer);
};
self.pause = function() {
global.clearTimeout(timer);
};
self.unpause = function() {
timer = global.setInterval(function(){
updateImage();
}, interval);
};
return self;
}(this.jQuery, this));
Since you're getting NaN, I'm guessing it is actually taking place from this line:
.hover(doHoverIn($(this).attr('position'))
...which calls this:
setCurrentImage(global.parseInt(position, 10)); // note the parseInt()
...which calls this:
setVisibleImage(id);
So the position being passed to parseInt is coming from $(this).attr('position'), which is likely an value that can't be parsed into a Number, so you get NaN.
Check out the value of that attribute in first line of the block for the for statement.
for (i = 0;i < totalImages; i++) {
console.log( $(this).attr('position') ); // verify the value of position
// ...