EaselJS Triangle Stroke - javascript

I'm working with EaselJS to recreate something I've seen in real life and I'm having a slight issue with triangle strokes.
In the above image you can see my triangle. I understand corner A and why it isn't filled like the others but I want it filled. How can I do this exactly?
Because it won't include my code snippet, my JavaScript is:
var stage = new createjs.Stage('c'),
poly = new createjs.Shape(),
s = 400,
h = s * (Math.sqrt(3)/2),
x = stage.canvas.width/2+s,
y = stage.canvas.height/2+s/2;
poly.graphics.beginStroke('#0da4d3').setStrokeStyle(75)
.moveTo(x,y).lineTo(x+s/2,y+h).lineTo(x-s/2,y+h).lineTo(x,y);
stage.addChild(poly);
stage.update();
createjs.Ticker.addEventListener('tick', handleTick);
function handleTick(e) {
stage.update();
}
window.onresize = function() {
stage.canvas.width = $(window).width();
stage.canvas.height = $(window).height();
}
stage.canvas.width = $(window).width();
stage.canvas.height = $(window).height();
and a link to CodePen: http://codepen.io/Spedwards/pen/hqvsc
Also as a small sub-question, why is my stage only updating in a Ticker?

As kihu answered, you only need to add closePath to the graphics. Take a look at the documentation: http://www.createjs.com/Docs/EaselJS/classes/Graphics.html#method_closePath
For your sub question: the stage draw things on the screen on the stage.update() call. In your example, this call is inside a function executed every tick event, i.e., ~ 24 times per second. You only need to call stage.update when you have new things to draw (e.g., when you add other object to the stage or when you move, rotate or perform other transformations to the objects already in stage). Thus, in your case, you only need to call the update method after adding the shape to the stage and after the window resize event.

You can fix the corner issue using closePath();
poly.graphics.beginStroke('#0da4d3').setStrokeStyle(75);
poly.graphics.moveTo(x,y).lineTo(x+s/2,y+h).lineTo(x-s/2,y+h).closePath();
http://codepen.io/anon/pen/fyxvI
As for the ticker - this is how CreateJS was designed. I think it's related to game development. When animating things, you are 100% sure that all the operations inside 'tick' handler have been executed before the next 'tick' is handled.

Related

Calculate time taken by PixiJs for initial render

How to calculate the time taken by PixiJs for initial render?
This is my function which renders thousand rectangles. I want to calculate the time taken by PixiJS to complete the initial render?
Is there any renderComplete event in PixiJS?
function createRectsUsingPixi (container, width, height, points) {
const app = new PIXI.Application({ antialias: true, width, height });
container.appendChild(app.view);
const rect = new PIXI.Graphics();
rect.beginFill(0x626262);
for (let i = 0; i < points.length; i++) {
const { x, y, width, height } = points[i];
rect.drawRect(x, y, width, height));
}
rect.endFill();
app.stage.addChild(rect);
}
Please check this example: https://codepen.io/domis86/pen/poJrKdq - and focus on following lines:
This creates Ticker and turns off "automatic rendering":
// See: https://pixijs.download/dev/docs/PIXI.Ticker_.html
let ticker = PIXI.Ticker.shared;
ticker.autoStart = false;
ticker.stop();
Then inside "game loop" we call render method manually:
renderer.render(app.stage);
This render method seems to be synchronous according to experts (including one of authors of pixi.js) here: https://github.com/pixijs/pixi.js/issues/5299 (comment about manual render: https://github.com/pixijs/pixi.js/issues/5299#issuecomment-449080238 ), and here: https://www.html5gamedevs.com/topic/27849-detect-when-view-has-been-rendered/?do=findComment&comment=160061
So, you can calculate execution time of render method.
See also description how to setup "custom game loop" without "Ticker": https://github.com/pixijs/pixi.js/wiki/v5-Custom-Application-GameLoop#custom-gameloop
Is there any renderComplete event in PixiJS?
You can try https://pixijs.download/dev/docs/PIXI.Renderer.html#postrender
Also additional performance tip: in your example i see that you create one PIXI.Graphics objects and draw many rectangles inside it. Please try creating one PIXI.Graphics per rectangle (draw one rectangle in one PIXI.Graphics object) and compare performance.
Also, usually you want to create PIXI.Application only once (at beginning of program). So line:
const app = new PIXI.Application({ antialias: true, width, height });
should be probably extracted from function createRectsUsingPixi and called separately elsewhere once.

How do I keep Transform Control from moving your object if there is a collision, using raycasting?

So I'm using Three.js and I have some cubes inside of a box. I'm using the Transform Control to move the cubes around inside of the box with my mouse. I'd like to use raycasting in order to check for collisions. The question is how to I prevent the transform controller from moving the object if there is a collision? I'd like to stop it if it hits the wall. By the way, I'm on version r81 for Three.js.
UPDATE: I've used the size of the room to constrain the cubes from
moving outside of the room. This seems to work well. Is there a way
to use the cannon.js just for collisions? I don't want the momentum
or gravity or any other feature. JUST the collision check and to stop
it dead in its tracks when there is a collision.
I know this post is from a long time ago, but hopefully a googler finds this helpful. I wasn't able to stop the user from moving my object, but I was able to move it back to its proper position immediately afterward by adding some logic to the render method.
For the original poster's problem with collisions, you could attach an event listener to the transform controls and request the object to be repositioned if it is in an illegal state.
transformControls.addEventListener('objectChange', (e) => {
if (illegalPosition(this.obj.position)) {
needsReset = true;
}
lastPosition = attachedObject.position.clone();
});
and then in your render function
if (needsReset) {
attachedObject.position.set(lastPosition.x, lastPosition.y, lastPosition.z);
}
If this feels a little hacky, that's because it is. But for those of us who don't have the time or skill to read and modify TransformControls.js, I think it may prove helpful.
You could create helper raycaster and place all colliders in separate container. After movement is applied to object move raycaster to its position and test if ray intersects any of other objects in container. If yes: reset previous position for that object. In case of cube colliders you could want to raycast from cube center in multiple directions with half of side length as ray length.
Ben S does have the best and most painless way to implement collision detection with transform controls. Within a event listener.
But I don't know if the time of writing his answer he knew about or if there even was a function called "requestAnimationFrame". All you would have to do for collision detection instead of simply resetting the models position is to set up your render call within a loop (60 fps) by adding "requestAnimationFrame" to your render (I call it animate since that is more descriptive) function.
Since it is in a loop and is called when the every frame the scene is drawn it will just not allow the object to move past the point of collision.
function animate() {
// Called to draw onto screen every frame (60fps).
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
And your event listener would just look like this.
control.addEventListener('objectChange', (e) => {
// Collision detection code here. Set colliding model position here.
// No need to set it in render
});
Old post, I know. But here is a method that is still fairly simple but does not flicker or use ray casting. The biggest catch here is that you have a little bit of a bounce if you move the Transform control really quickly. But otherwise it seems to work fairly well. You can control the precision of the collision by adjusting the step value.
let transStart = null;
//capture objects position on start
control.addEventListener('mouseDown', function(){
transStart = control.object.position.clone();
})
//you'll have to provide your own collision function
control.addEventListener('objectChange', function(e){
if(collision(sphere, cube)){ stopControls() };
});
function stopControls(){
if(control.dragging && stopAt){
//calculate direction object was moving at time of collision
const s = transStart;
const e = control.object.position.clone();
const n = e.clone().sub(s).negate().normalize();
//janky hack nonsense that stops the transform control from
//continuing without making the camera controller go nuts.
control.pointerUp({button:0});
control.dragging = true;
//translate back the direction it came by the step amount and do not
//stop until the objects are no longer colliding.
//Increase the step size if you do not need super precise collision
//detection. It will save calculations.
let step = 0.00005;
while(colliding(sphere, cube)){
sphere.translateOnAxis( n, step ) ;
sphere.updateMatrix();
}
}
}

Performance issue : canvas seems to be redrawing on addition of every Path

I see performance issue when lot of path points are added. When there are far too little points, the curves are very smooth. However when canvas has added moderate number of points the curves seems to become sharp because of performance impact. I noticed the paper js clears the entire canvas and draws the view again on every paper.view.update call. This update call is called on every mouse event.
Here is the summary of my application --
canvas assigns mouse event listenenrs
onMouseDown - paper.Path is initialized
onMouseMove - a point is plotted using paper.Point
onMouseUp - the path is simplfied and smoothen.
Here is the snippet of the code I debugged in full version of paperjs. line - 11578 onwards
CanvasView :
update: function(force) {
var project = this._project;
if (!project || !force && !project._needsUpdate)
return false;
var ctx = this._context,
size = this._viewSize;
ctx.clearRect(0, 0, size.width + 1, size.height + 1);
project.draw(ctx, this._matrix, this._pixelRatio);
project._needsUpdate = false;
return true;
}
This update method is called by paper js.
As number of points grow, the performance is extremely degraded. How can I improve this to make it acceptable performance?
I have asked the similar question on paperjs forum PaperJS forum question

Canvas Rendering Optical Illusion in JS Game (Briefly duplicated graphics) - Fix?

I'm creating a side-scrolling space-shooter in javascript. So far everything seems to be working well. However, there is an odd bug in the canvas rendering that I can't quite figure out (and is difficult to describe, so bear with me!)
I have a player that can shoot projectiles by clicking the left mouse button. When the projectile first leaves the player, there appears to be two of them for a brief second, until they eventually merge in to the one projectile. I'm not creating two, so this seems like an optical illusion (this is most evident if you fire a few projectiles in quick succession).
The really odd thing is, when I try and capture a screenshot of this happening, all looks fine. Can anyone figure out what's going on?
Player code including projectiles (full code in fiddle);
var Player = (function () {
// ------------------------------------------------------------------------------------------------
// PLAYER VARIABLES
// ------------------------------------------------------------------------------------------------
var w = 50;
var h = 50;
var x = 0;
var y = 0;
var projectiles = [];
// ------------------------------------------------------------------------------------------------
// BIND EVENTS TO THE GLOBAL CANVAS
// ------------------------------------------------------------------------------------------------
Canvas.bindEvent('mousemove', function (e) {
y = (e.pageY - Canvas.element.getBoundingClientRect().top) - (h / 2);
});
Canvas.bindEvent('click', function () {
createProjectile(50, (y + (h / 2)) - 10);
});
// ------------------------------------------------------------------------------------------------
// FUNCTIONS
// ------------------------------------------------------------------------------------------------
var createProjectile = function (x, y) {
projectiles.push({
x: x,
y: y
})
};
var update = function () {
for (var p = projectiles.length - 1; p >= 0; p--) {
projectiles[p].x += 10;
if (projectiles[p].x > Canvas.element.width)projectiles.splice(p, 1);
}
};
var render = function () {
Canvas.context.fillStyle = 'white';
Canvas.context.fillRect(x, y, w, h);
for (var p = 0; p < projectiles.length; p++) {
Canvas.context.fillStyle = 'red';
Canvas.context.fillRect(projectiles[p].x, projectiles[p].y, 5, 5);
}
};
// ------------------------------------------------------------------------------------------------
// Exposed Variables and Functions
// ------------------------------------------------------------------------------------------------
return {
update: update,
render: render
}
})();
Js Fiddle Demo HERE: https://jsfiddle.net/oqz204bj/
EDIT
Based on #Pimskie's answer, It does indeed seem like an optical illusion - so my question now becomes, how could I reduce this effect? I plan on implementing a feature in the future that allows the player to switch weapons (where some of them would **actually* fire multiple projectiles) but I don't want this effect to remain for fear of confusion.
yes it is an optical illusion. The reason it looks like there multiple squares when first fired is because your eyes are focused on the big static ship square. Once your eye starts to follow the movement path, then it looks more like a fluid square moving instead of a square being redrawn 60 or 30 times per second. hold a piece of paper or your hand up to your screen covering the left half of it. Focus on the piece of paper and fire a few shots. You'll notice that the shots seem to appear multiple, the same as when just fired. It's a matter of your mind seeing 3 different frames as the same one.
requestAnimationFrame depends on the frame rate of your browser and computer. In most cases that's 60fps. 60 to 70fps is the limit of most monitors, and so it doesn't make sense to try and go above that. HOWEVER you can create the illusion of a more fluid movement by having a trailing tracer effect on your projectiles. That would involve having 2 or 3 extra squares created behind each projectile that have less and less opacity.
My best guess it's an optical illusion indeed.
Check this updated fiddle: https://jsfiddle.net/oqz204bj/1/
I removed one requestAnimationFrame and replaced a other with a very slow setInterval, just for demonstration. You can see only one bullet is created.

Image Flickering In Canvas Game

For a university project I have been tasked with creating a Flappy Bird clone. It's being done using the HTML5 canvas.
The issue doesn't happen very often, but it seems that every 6 or so seconds, the grass will flicker. I'm not sure what's causing this, it could be a performance issue.
Here is a link so you may see the issue: http://canvas.pixcelstudios.uk
Here is the function I'm using to the draw the grass:
var drawGrass = function(cWidth, ctx, minusX)
{
var x = bg_grass.x;
var y = bg_grass.y;
var w = bg_grass.w;
var h = bg_grass.h;
var img = bg_grass.img;
if (minusX[0] >= cWidth)
{
bg_grass.x = 0;
minusX[0] = 0;
}
ctx.drawImage(img, x, y, w, h);
if (minusX[0] > 0)
{
ctx.drawImage(img, w-minusX[0], y, w, h);
}
};
Basically, I'm drawing two grass sprites, each taking up a canvas width. One starts with an X of 0 and the other starts at the end of the canvas. Both are decremented each frame, then one is completely off the screen, it's completely reset to keep it looping.
I don't think it's anything to do with my update loop which is as follows:
this.update = function()
{
clearScreen();
updateBackground();
updatePositions();
checkCollisions();
render();
requestAnimFrame(gameSpace.update);
};
I've done a little bit of reading and I've read about having a second canvas to act as a buffer. Apparently this can stop flickering and improve performance? But all of the examples I've seen show the parts being drawn into the canvas out of a loop and I can't really see how doing it within a game loop (moving parts and all) would increase performance rather than decrease it. Surely the same operations are being performed, except now you also have to draw the second canvas onto the first?
Please let me know if you need any more information (although you should be able to see the whole source from the web link).
Thanks!
Okay I found the issue! Was just a simple mistake in my drawGrass function.
Due to the ordering, there'd be just a single frame where I'd set my shorthand X variable to bg_grass.x and THEN set bg_grass.x to something else, therefore drawing the wrong value.
I've now set my shorthand variables after the first if-statement.
However, if anyone could provide any insight into the second part of the question regarding a buffer canvas, I'd still much appreciate that.

Categories

Resources