I was trying to create a sample pixi application. Where I had an image, when user clicks on the image, it should move its position.
var canvasWidth = window.innerWidth;
var canvasHight = window.innerHeight
var renderer = PIXI.autoDetectRenderer(canvasWidth, canvasHight);
document.body.appendChild(renderer.view);
var stage = new PIXI.Container();
PIXI.loader
.add('images/sample.png')
.add('images/background.jpg')
.load(setup);
function setup() {
var backGround = new PIXI.Sprite(
PIXI.loader.resources["images/background.jpg"].texture);
var steve = new PIXI.Sprite(
PIXI.loader.resources["images/sample.png"].texture);
backGround.hieght = canvasHight;
backGround.width = canvasWidth;
setPropertiesToSteve(steve);
stage.addChild(backGround);
stage.addChild(steve);
renderer.render(stage);
}
// Function just to set properties for steve
function setPropertiesToSteve(steve) {
steve.interactive = true;
steve.position.x = canvasWidth/2;
steve.position.x = canvasWidth/4;
steve.on('pointerdown',function(){
steve.position.x = steve.position.x + 10;
});
}
But when I click on the object nothing happening. I am very much new to pixijs.SO don't know how to handle this.
You need to render the stage again :)
Take a look at the official Pixi examples https://pixijs.github.io/examples/
They use the PIXI.Application class which sets up common things like a ticker that automatically re renders your stage
Edit;
working codepen (need to provide video file to avoid cross-origin policy)
https://codepen.io/bw1984/pen/pezOXm
I am attempting to modify the excellent rutt etra example here https://airtightinteractive.com/demos/js/ruttetra/ to work for video (still using threejs) and am encountering strange issues with performance.
My code currently works as expected, and actually runs quite smoothly on chrome on my macbook pro, but seems to cause some sort of slow memory leak which i assume is to do with all the heavy lifting which is having to be done by getImageData. Strangely enough its only noticeable once i attempt to refresh the tab, so looks like it may be related to the garbage collection in chrome maybe? anyway to shunt the grunt work onto the GPU instead of killing the CPU?
I just wondered if i am missing anything obvious in terms of code optimisation or if the performance issues i am facing are to be expected given the nature of what i am trying to do.
I am only interested in WebGL / chrome functionality so dont really need to worry about browser compatibility of any kind.
<script>
var container, camera, scene, renderer, controls;
// PI
var PI = Math.PI;
var TWO_PI = PI*2;
// size
SCREEN_WIDTH = window.innerWidth;
SCREEN_HEIGHT = window.innerHeight;
SCREEN_PIXEL_RATIO = window.devicePixelRatio;
// camera
var VIEW_ANGLE = 45;
var ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT;
var NEAR = 0.1;
var FAR = 20000000;
// video raster
var video;
var videoImage;
var videoImageContext;
var _imageHeight;
var _imageWidth;
// lines
var _lineGroup;
// gui
var _guiOptions = {
stageSize: 1,
scale: 1.0,
scanStep: 5,
lineThickness: 10.0,
opacity: 1.0,
depth: 50,
autoRotate: false
};
// triggered from audio.php getMediaStream
function runme()
{
console.log('runme running');
init();
animate();
}
runme();
function init()
{
container = document.createElement('div');
document.body.appendChild(container);
//----------
// scene
//----------
scene = new THREE.Scene();
//----------
// camera
//----------
camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
//camera.position.set(0,0,450);
camera.position.set(0,150,300);
//----------
// objects
//----------
// create the video element
video = document.createElement('video');
// video.id = 'video';
// video.type = ' video/ogg; codecs="theora, vorbis" ';
video.src = 'data/sintel.ogv';
//video.src = 'data/az.mp4';
video.load(); // must call after setting/changing source
video.play();
videoImage = document.createElement('canvas');
//videoImage.width = 480;
//videoImage.height = 204;
videoImageContext = videoImage.getContext('2d');
_imageWidth = videoImage.width;
_imageHeight = videoImage.height;
//videoImageContext.fillStyle = '#ffffff';
//videoImageContext.fillRect(0, 0, videoImage.width, videoImage.height);
//----------
// controls
//----------
controls = new THREE.OrbitControls(camera);
//----------
// events
//----------
window.addEventListener('resize', onWindowResize, false);
//----------
// render
//----------
var args = {
//antialias: true // too slow
}
renderer = new THREE.WebGLRenderer(args);
renderer.setClearColor(0x000000, 1);
renderer.setPixelRatio(SCREEN_PIXEL_RATIO); //Set pixel aspect ratio
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
// attach to dom
container.appendChild(renderer.domElement);
//render();
}
function render()
{
if(video.readyState === video.HAVE_ENOUGH_DATA && !video.paused && !video.ended) // and video.currentTime > 0
{
//_imageWidth = videoImage.width;
//_imageHeight = videoImage.height;
videoImageContext.drawImage(video,0,0,_imageWidth,_imageHeight);
// Grab the pixel data from the backing canvas
var _data = videoImageContext.getImageData(0,0,videoImage.width,videoImage.height).data;
//log(data);
//_pixels = data;
var x = 0, y = 0;
if(_lineGroup)
{
scene.remove(_lineGroup);
//_lineGroup = null;
}
_lineGroup = new THREE.Object3D();
var _material = new THREE.LineBasicMaterial({
color: 0xffffff,
linewidth: _guiOptions.lineThickness
});
// loop through the image pixels
for(y = 0; y < _imageHeight; y+= _guiOptions.scanStep)
{
var _geometry = new THREE.Geometry();
for(x=0; x<_imageWidth; x+=_guiOptions.scanStep)
{
var color = new THREE.Color(getColor(x, y, _data));
var brightness = getBrightness(color);
var posn = new THREE.Vector3(x -_imageWidth/2,y - _imageHeight/2, -brightness * _guiOptions.depth + _guiOptions.depth/2);
//_geometry.vertices.push(new THREE.Vertex(posn));
_geometry.vertices.push(posn);
_geometry.colors.push(color);
_color = null;
_brightness = null;
_posn = null;
}
// add a line
var _line = new THREE.Line(_geometry, _material);
//log(line);
_lineGroup.add(_line);
// gc
_geometry = null;
}
scene.add(_lineGroup);
_data = null;
_line = null;
}
renderer.render(scene,camera);
}
function animate(){
requestAnimationFrame(animate);
stats.update();
render();
}
function onWindowResize(){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
render();
}
// Returns a hexadecimal color for a given pixel in the pixel array.
function getColor(x, y, _pixels)
{
var base = (Math.floor(y) * _imageWidth + Math.floor(x)) * 4;
var c = {
r: _pixels[base + 0],
g: _pixels[base + 1],
b: _pixels[base + 2],
a: _pixels[base + 3]
};
return (c.r << 16) + (c.g << 8) + c.b;
}
// return pixel brightness between 0 and 1 based on human perceptual bias
function getBrightness(c)
{
return ( 0.34 * c.r + 0.5 * c.g + 0.16 * c.b );
}
</script>
any help anyone could provide would be much appreciated, even if its just pointing me in the right direction as i am only just beginning to experiment with this stuff and have almost given myself an aneurysm trying to wrap my tiny mind around it.
The slow memory leak is most likely due to:
// add a line
var _line = new THREE.Line(_geometry, _material);
//log(line);
_lineGroup.add(_line);
THREE.Line is an object, containing other objects and lots of data. Every time you instantiate it, it creates .matrix, .matrixWorld, .modelViewMatrix, .normalMatrix which are all arrays with a bunch of numbers. .position,.quaternion, .scale, .rotation and probably .up are vectors,quats etc. and are slightly smaller but also arrays with special constructors.
Allocating all this every 16 miliseconds only to be released the next frame is probably the cause of your "leak".
You should create a pool of THREE.Line objects, and draw that every frame instead. The number of drawn objects you can control with .visible and mutate their transformation properties.
#pailhead I took your advice about pre-rendering the lines and lineGroup in advance and then updating the vertices on each animation frame instead and now its purring like a kitten. Also needed to insert the following line to make sure updated coords are picked up;
e.geometry.verticesNeedUpdate = true;
I cant figure out how to get a hosted video to work on codepen (cross-origin policy violation issues) but i have put a version up anyway to show the working code.
https://codepen.io/bw1984/pen/pezOXm
I will try to get a self-hosted (working) version up as soon as i can
I've been trying in vain to get colour working, but that will have to be an exercise for another day.
The Problem
I am finding it rather difficult to get my head around this, I am attempting to move an image using the mouse along the X axis only. I am finding it hard to even move the image at all and the many tutorials I have looked at arnt really helping me. Here is what I am trying to say:
As you can see by my beautiful image above I only want to image to move left and right at the bottom of the page.
The Code and the Question
Here is my first attempt, when I try this all the images loaded on the canvas no longer appear making it very hard for me to understand why it isnt working.
<script type="text/javascript">
//Referencing the canvas
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var width = canvas.getAttribute('width');
var height = canvas.getAttribute('height');
//Images
var bggameImage = new Image();
var playerImage = new Image();
var enemyImage = new Image();
var projectileImage = new Image();
var livesImage = new Image();
//Canvas dimensions
var width = 480;
var height = 320;
//Loading in the backgroundImage
bggameImage.src = "Images/bggameImage.png";
bggameImage.onload = function(){
context.drawImage(bggameImage, 0, 0);
}
//Loading in the playerImage
playerImage.src = "Images/playerImage.png";
playerImage.onload = function(){
context.drawImage(playerImage, 165, 240);
}
//Loading in the projectileImage
projectileImage.src = "Images/projectileImage.png";
projectileImage.onload = function(){
context.drawImage(projectileImage, 65, 240);
}
var playerImage = {
x:176,
y:74,
}
function init() {
playerImage.src = "Images/playerImage.png";
//Moving player
myCanvas.addEventListener("mousemove", function (e) {
var bounding_box = myCanvas.getBoundingClientRect();
playerImage = (e.clientX - bounding_box.left) * (myCanvas.width / bounding_box.width) - playerImage.width / 2;
playerImage = (e.clientY - bounding_box.top) * (myCanvas.height / bounding_box.height) - playerImage.height / 2;
}
)
</script>
The whole "function init()" part is what I have just tried but I thought I would include this anyway, I understand that I am loading in the playerImage twice.
You're using the same variable name twice (playerImage), so your image is being overwritten. You're using it for the image and also to store the position. Change the playerImage that's storing x and y to be playerPosition or something like that. Update that variable on your mouse event and then render the image according to that variable's values.
Ultimately, you're going to have to look at a game loop using setTimeout or requestAnimationFrame. So, this will become crucial at that stage. And yes, you shouldn't be loading the player image twice either. Do all of that at the start and only start your game when all your assets have successfully loaded.
For instance...
var playerImage;
var alienImage;
var bulletImage;
var assetCount = 0;
function loadAssets() {
playerImage = new Image();
playerImage.onload = checkAssetsLoaded;
playerImage.src = "assets/images/Brush01.png";
alienImage = new Image();
alienImage.onload = checkAssetsLoaded;
alienImage.src = "assets/images/Brush02.png";
bulletImage = new Image();
bulletImage.onload = checkAssetsLoaded;
bulletImage.src = "assets/images/Brush03.png";
}
function checkAssetsLoaded(event) {
assetCount++;
console.log("An asset has loaded!: " + assetCount);
if (assetCount == 3) {
startGame();
}
}
function startGame() {
// Start your game initialization logic here.
console.log("Game starting!");
}
I have a drawing canvas using EaselJS, the problem is that when I am drawing lines is working properly only the first one. Since second line is getting with some corners not with curved line as the first line, and it looks more like a polygon than a curved line. What is the best way to fix this?
I think here should to be something to correct
//containers
this.backgroundContainer = new createjs.Container();
this.stage.addChild(this.backgroundContainer);
var ss = new createjs.Shape();
ss.graphics.beginFill("#000000").drawRect(0, 0, 960, window.innerHeight);
this.stageArea = new createjs.Container();
this.stageArea.snapToPixel = true;
this.stageArea.hitArea = ss;
this.backgroundContainer.addChild(this.stageArea);
this.container = new createjs.Container();
this.stage.addChild(this.container);
this.stageArea.addEventListener("mousedown", this.handleMouseDown);
this.stage.addEventListener("stagemousemove" , this.handleMouseMove);
tick:function(){
if(app.mouseDOWN){
app.midPt = new createjs.Point(app.oldPt.x + app.stage.mouseX - app.stage.canvas.width/2>>1, app.oldPt.y+app.stage.mouseY - app.stage.canvas.height/2>>1);
app.lineArray[app.NUM_LINES].graphics
.beginStroke('#ffffff')
.moveTo(app.midPt.x, app.midPt.y)
.curveTo(app.oldPt.x, app.oldPt.y, app.oldMidPt.x, app.oldMidPt.y);
app.lineArray2[app.NUM_LINES].graphics
.beginStroke('#ffffff')
.moveTo(app.midPt.x, app.midPt.y)
.curveTo(app.oldPt.x, app.oldPt.y, app.oldMidPt.x, app.oldMidPt.y);
app.lineArray3[app.NUM_LINES].graphics
.beginStroke('#ffffff')
.moveTo(app.midPt.x, app.midPt.y)
.curveTo(app.oldPt.x, app.oldPt.y, app.oldMidPt.x, app.oldMidPt.y);
app.oldPt.x = app.stage.mouseX;
app.oldPt.y = app.stage.mouseY;
app.oldMidPt.x = app.midPt.x;
app.oldMidPt.y = app.midPt.y;
app.stage.update();
}
}
I am following up with a game development tutorial for windows 8 here http://www.sitepoint.com/creating-a-simple-windows-8-game-with-javascript-game-basics-createjseaseljs/.
The tutorial probably needs updating since at some point i had to add in createJS before using PreloadJS.
example:
stage = new createjs.Stage(canvas);
preload = new createjs.PreloadJS();
or else the debugging throws errors.
However the program breaks when bgImage is initialised. Any suggestive codes i can use?
bgImage = preload.getResult("screenImage").Result;
bgBitmap = new Bitmap(bgImage);
bgBitmap.scale_X = SCALE_X;
bgImage.scale_Y = SCALE_Y;
stage.addChild(bgBitmap);
stage.update();
Please make sure you are using correct syntax.
var bgImage = preload.getResult("screenImage").result;
var bgBitmap = new createjs.Bitmap(bgImage);
stage.addChild(bgBitmap);
Also what is the bug you are getting?
Here is a quick example that should help.
function init() {
canvas = document.getElementById("testCanvas");
//check to see if we are running in a browser with touch support
stage = new createjs.Stage(canvas);
createjs.Ticker.setFPS(24);
createjs.Ticker.addListener(stage);
images = images || {};
var manifest = [
{src:"image.jpg", id:"image"}
]
loader = new createjs.PreloadJS(false);
loader.onFileLoad = handleFileLoad;
loader.onComplete = handleComplete;
loader.loadManifest(manifest);
}
function handleFileLoad(o) {
//You could store all your images in object to call them easily.
if (o.type == "image") {
images[o.id] = o.result;
}
}
function handleComplete(event) {
var bg = new createjs.Bitmap(loader.getResult("image").result);
//OR samething
//var bg = new createjs.Bitmap(images['image']);
stage.addChild(bg);
}
function tick() {
stage.update();
}
Hope this helps.