I am trying to create my first website using the p5.js library, with the end goal being an online digital portfolio. I am currently working on a splash screen, in which I have some large title text filling the center of the screen on a simple black background, which actively resizes to fill the window.
I would like to place a simple doodle in the background to add some interest. My challenge is that I would not like this doodle to draw on top of my text, but instead place it underneath my text. Initially I was thinking of infinitely redrawing the text so it stays at the top, however I have deduced there is no way to do this while still animating something beneath it.
My knowledge of HTML / CSS is minimal, however I was thinking of making the background of the title sketch transparent, a separate sketch with the doodle, and use the z index property in CSS to place the doodle beneath the title, is this even possible?
Thanks!
Further edits based on recommendations:
function preload() {
myFont = loadFont('assets/HighTide.otf');
}
function setup() {
canvas = createCanvas(window.innerWidth, window.innerHeight);
title = text("Welcome", width/2, height/2);
background(30);
fsize = window.innerHeight/4;
pg = createGraphics(window.innerWidth, window.innerHeight);
}
function draw() {
background(30);
pg.fill(random(0,255), random(0,255), random(0,255));
//pg.translate(width/2, height/2);
pg.ellipse(random(window.innerWidth), random(window.innerHeight), 60, 60)
image(pg, 0, 0);
textFont(myFont);
textSize(fsize);
textAlign(CENTER);
fill(255);
text("Welcome", width/2, height/2);
}
window.onresize = function() {
var w = window.innerWidth;
var h = window.innerHeight;
canvas.size(w,h);
fsize = window.innerHeight/4;
title.textSize(fsize);
width = w;
height = h;
}
It depends on exactly how you're drawing everything, but if you're doing this all in P5.js then you've already described exactly what you need to do.
Step 1: Each frame, clear out old frames by calling the background() function.
Step 2: Then draw your doodle.
Step 3: Finally, draw your text. Since you're drawing the text after the doodle, it shows up "on top" of the doodle.
This is how most P5.js sketches work: every frame, you clear out the old frames and then draw the next frame.
Edit: If you need a sketch that doesn't clear out old frames but still shows two different layers (your doodle and your text), then what you could do is draw your doodle to a buffer, then draw that buffer each frame, then draw the text on top of the buffer. Check out the createGraphics() function in the reference.
Related
https://editor.p5js.org/LttntLark/sketches/JBSg2zIfEf
All the code is above.
I've been trying to make a camera that follows the player(Mover), and it says I need WEBGL. Is there a way to do this without it in p5.js? I've searched up tutorials, and nothing says I can make a "camera" for p5 in 2d, and that I "NEED WEBGL" And I cant remodel my game in WEBGL, so I need a code that is a "viewport" that keeps my player centered on the screen while he moves.
To enable WebGL mode, add WEBGL to your createCanvas()
Example:
createCanvas(1500, 2560, WEBGL);
// Let WIDTH be the canvas width
// Let HEIGHT be the canvas height
// Let player be the center of perspective (with x and y positions)
function draw() {
// Do not push/pop
// This line of code should affect all drawing below
//
translate(WIDTH / 2 - player.x, HEIGHT / 2 - player.y);
//
// This line translate the camera making the player always centered
/////////////////
//
// Your other drawings here
//
/////////////////
}
Is there a way to clear the canvas (html5)of only 1 element only ? I have a moving image on a canvas and when I erase the image the background color goes as well. Is there a way to just remove the image and not the whole background. My background is just a simple color but in the future it will be more complicated.
This is also tricky because there is no way to get image x,y pos from a property.
ClassLoadImages.prototype.m_move = function(){
this.x=++img1_x;
this.y=++img1_y;
//img1_x++;
//img1_y++;
// alert(img.x);
ctx.drawImage(img.imgElement, this.x, this.y);
// ctx.fillText("finished loading " ,10,40);
};
function doGameLoop() {
ctx.clearRect(0,0,600,400);
img.m_move();
if (img.x>30)
{
clearInterval(gameLoop);
}
}
var img= new ClassLoadImages('images/image4.jpg');
gameLoop = setInterval(doGameLoop, 100);
</script>
Simple answer is no. A canvas is a flat bitmap, not a layered collection of objects. Once you draw to it you lose the background behind the thing you draw.
You could try to implement the functionality yourself by recording the steps you used to create the canvas in the first place, and re-creating it with or without the relevant image.
Say I drew a rectangle on the canvas. Surely there is some sort of built in method to get the XY coordinates, and dimensions of that rectangle? But after some googling I came up with nothing. And just to clarify, I am not talking about the coordinates of the canvas element itself, but rather a shape/image that is drawn unto the canvas.
Any help is appreciated.
If you're talking about a 2D canvas drawing, then the drawing maps 1:1 with screen coordinates, so it is just location of <canvas> + location of the drawing.
To clarify, drawing on a <canvas> basically just changes the pixels of the canvas - after you draw to it, you can't reference the drawn object the same way you can reference an html element.
Canvas is 2D table (Array) of numbers (= pixels = colors). When drawing into canvas, you are just editing this table. When you draw into canvas (= change numbers in table), what should be the coordinates of your adjustment?
If you are drawing rectangles only and you can define the coordinates for your rectangle, you must know your coordinates inside a program, because you have just drawn it.
If you want your image to be separated into some "objects" (shapes), you should use SVG.
Basically, you should be using canvas as a means to output graphics to the screen and the rest of your logic goes straight into the JavaScript that powers your game/application. The best way to go about making something like this is to create objects and assign properties to them; in its simplest form that can look like this:
function Player(x, y)
{
this.x = x;
this.y = y;
}
var examplePlayerObject = new Player(20, 20);
By extending this object via prototyping you can create multiple copies of an object that has the exact same functions; such as draw. Drawing the player in this instance could just be a red square that is 20px*20px.
Player.prototype.draw = function()
{
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillStyle = 'red';
context.fillRect(this.x, this.y, 20, 20);
}
Then, you should have an update step with some means of clearing what is on the screen and redrawing the parts which have changed.
function animationStep()
{
examplePlayerObject.x++;
examplePlayerObject.y++;
examplePlayerObject.draw();
}
This animation step should run each frame; look into requestAnimationFrame for smooth animation. Paul Irish has a good shim for older browsers. Add in requestAnimationFrame(animationStep) at the end of that function and you will have a red square moving slowly across the screen. Good luck!
I am creating a click and clear game. Once the user clicks some brick its adjacent bricks are checked for same color and all these bricks are bricks are cleared at once.
These are Cleared using clearRect() function.
Now this leaves a white patch right between the bricks above and bricks below leaving the above bricks hanging.
Now i want to bring these bricks above downward. How do i do this..?
Plz help
The question is quite vague, but based on the title, you'll need to clear your canvas before you can redraw. Otherwise, the drawn elements would simply stack on top of each other.
To do this, call the function clearRect on the canvas itself:
function clear() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, 500, 500);
}
Where canvas is the ID of your canvas, and 500, 500 the dimensions. Now you'll have an empty canvas where you can redraw everything again.
I once created a simple HTML5 canvas game as well, you might learn from the source code.
I think I understand what you're asking. If so then you're wanting to know how to move the blocks down when the blocks below have been removed.
This is just a matter of increasing the x position (remember the canvas starts at 0,0) with each iteration of your game loop.
How far to increase? Well that would be to where the highest "solid tower" is. I.E., say you have a column of 10 tokens and you remove the 7. The 3 below need all fall to the height of the remaining 6 - so that would be board height - (6*token height)
*
*
*
+ <- remove
* <- 6x token height (and less the board height)
*
*
*
*
*
I had success at redrawing the HTML Canvas by DOM.
var c = document.getElementsByName("myCanvas")[0];
if (c != null)
{
c.remove();
}
var c = document.createElement("canvas");
c.setAttribute("name", "myCanvas");
c.setAttribute("width", 900);
c.setAttribute("height", 600);
c.setAttribute("style", "border:1px solid #d3d3d3");
I'm writing a 2D game in html5 using Canvas which requires mouse click and hover events to be detected. There are 3 problems with this: detections must be pixel-perfect, objects are not rectangular (houses, weird-shaped UI buttons...), and it is required to be fast and responsive. (Obviously brute force is not an option)
So what I want to ask is how do I find out which object the mouse is on, and what are the possible optimizations.
P.S: I did some investigation and found a guy who used QuadTree here.
I have a (dated) tutorial that explains the concept of a ghost canvas which is decent for pixel-perfect hit detection. The tutorial is here. Ignore the warning about a newer tutorial, the newer one does not use the ghost canvas concept.
The idea is to draw the image in question to an in-memory canvas and then use getImageData to get the single pixel of the mouse click. Then you see if that single pixel is fully transparent or not.
If its not fully transparent, well, you've got your target.
If it is fully transparent, draw the next object to the in-memory canvas and repeat.
You only have to clear the in-memory canvas at the end.
getImageData is slow but it is your only option if you want pixel-perfect hit detection and aren't pre-computing anything.
Alternatively you could precompute a path or else an array of pixels with an offset. This would be a lot of work but might be faster. For instance if you have a 40x20 image with some transparency you'd compute an array[40][20] that would have true or false corresponding to transparent or not. Then you'd test that against the mouse position, with some offset, if the image is drawn at (25, 55) you'd want to subtract that from the mouse position and then test if the new position is true when you look at array[posx][posy].
That's my answer to your question. My Suggestion? Forget pixel-perfect detection if this is a game.
Seriously.
Instead make paths (not in canvas, in plain javascript code) that represent the objects but are not pixel perfect, for instance a house might be a square with a triangle on the top that is a very close approximation of the image but is used in its stead when it comes to hit testing. It is comparatively extremely fast to compute if a point is inside a path than it is to do pixel-perfect detection. Look up point in polygon winding number rule detection. That's your best bet, honestly.
The common solution in traditional game development is to build a click mask. You can re-render everything onto a separate off-screen canvas in a solid color (the rendering should be very quick). When you want to figure out what was clicked on, you simply sample the color at the x/y co-ordinate on the off-screen canvas. You end up building a color-->obj hash, akin to:
var map = {
'#000000' : obj1
, '#000001' : obj2
, ...
};
You can also optimize the rendering to the secondary canvas to only happen when the user clicks on something. And using various techniques, you can further optimize it to only draw the part of the canvas that the user has clicked on (for example, you can split you canvas into an NxN grid, e.g. a grid of 20x20 pixel squares, and flag all of the objects in that square -- you'd then only need to re-draw a small number of objects)
HTML5 Canvas is just a drawing plane, where you can set different transforms before calling each drawing API function. Objects cannot be created and there is no display list. So you have to build these features yourself or you can use different libraries available for this.
http://www.kineticjs.com/
http://easeljs.com/
A few months before I got interested in this and even wrote a library for this purpose. You can see it here : http://exsprite.com. Ended up facing a lot of performance issues, but because of lack of time I couldn't optimize it. It was really interesting, so waiting for some time to make it perfect.
I believe the comments should suffice. This is how I determine user intention in my 2d isometric scroller, currently located at http://untitled.servegame.com
var lastUp = 0;
function mouseUp(){
mousedown = false; //one of my program globals.
var timeNow = new Date().getTime();
if(mouseX == xmouse && mouseY == ymouse && timeNow > lastUp + 100){//if it was a centralized click. (mouseX = click down point, xmouse = mouse's most recent x) and is at least 1/10th of a second after the previous click.
lastUp = new Date().getTime();
var elem = document.elementFromPoint(mouseX, mouseY); //get the element under the mouse.
var url = extractUrl($(elem).css('background-image')); // function I found here: http://webdevel.blogspot.com/2009/07/jquery-quick-tip-extract-css-background.html
imgW = $("#hiddenCanvas").width(); //EVERY art file is 88px wide. thus my canvas element is set to 88px wide.
imgH = $(elem).css('height').split('p')[0]; //But they vary in height. (currently up to 200);
hiddenCanvas.clearRect(0, 0, imgW, imgH); //so only clear what is necessary.
var img = new Image();
img.src = url;
img.onload = function(){
//draw this elements image to the canvas at 0,0
hiddenCanvas.drawImage(img,0,0);
///This computes where the mouse is clicking the element.
var left = $(elem).css('left').split('p')[0]; //get this element's css absolute left.
var top = $(elem).css('top').split('p')[0];
offX = left - offsetLeft; //left minus the game rendering element's absolute left. gives us the element's position relative of document 0,0
offY = top - offsetTop;
offX = mouseX - offX; //apply the difference of the click point's x and y
offY = mouseY - offY;
var imgPixel = hiddenCanvas.getImageData(offX, offY, 1, 1); //Grab that pixel. Start at it's relative X and it's relative Y and only grab one pixel.
var opacity = imgPixel.data[3]; //get the opacity value of this pixel.
if(opacity == 0){//if that pixel is fully transparent
$(elem).hide();
var temp = document.elementFromPoint(mouseX, mouseY); //set the element right under this one
$(elem).show();
elem = temp;
}
//draw a circle on our hiddenCanvas so when it's not hidden we can see it working!
hiddenCanvas.beginPath();
hiddenCanvas.arc(offX, offY, 10, 0, Math.PI*2, true);
hiddenCanvas.closePath();
hiddenCanvas.fill();
$(elem).css("top", "+=1"); //apply something to the final element.
}
}
}
In conjunction with this:
<canvas id="hiddenCanvas" width="88" height="200"></canvas>
Set the CSS positioning absolute and x = -(width) to hide;