I've been working on building a tile-based display grid for canvas. This is what I have so far: http://jsfiddle.net/dDmTf/7/
Some problems I'm having, and can't quite grasp are:
The initial load time is ridiculous... I don't understand what I'm doing wrong - fixed, found out I was rendering ^32 more than I was supposed to
The hover effect, which "should" just highlight the border of the tile, erases it, and I have no way of recovering the previous tile without re-rendering the entire canvas.
How do I use tilesheets, providing me a single image instead of a bunch of small ones
Resizing the window (which resizes the canvas) also erases the canvas. Do I need to re-render? Or can I maintain state of various things when width/height is changed - added an onresize callback, which re-renders the map. Might not be the best way though?
Multiple layers? How would I go about allowing transparency .png files overlaying each-other
Those are the main problems I'm stuck on right now, and any guidance would be majorly appreciated.
Also, if you have any pointers for my javascript, feel free! I'm learning it more as I go, and I'm sure I'm doing a lot of things wrong.
Edit
As an FYI, I just copy-pasted the sprite map currently being shown on the jsfiddle. It's not the one I'm planning to use, but it was easier than uploading one. I plan to maintain a 32x32 grid instead of (what appears to be) a 16x16 grid from that tilesheet
Edit
I've got the a 32x32 tilesheet displaying on there now, but the hover effect is still breaking it, and I'm not sure how to "know" what the old value was.
The problem is that you are not redrawing your tiles after 'mouseout'.
You either need to redraw the single tile after you move out of it, but this can get tricky as things get more complicated or better yet on mouse move do the following.
Clear the canvas
draw the grid
draw your tiles
then do the highlighting/clearing that cell.
If you end up having any sort of animation this is the process that will be used anyhow otherwise as something moves from one tile to another it will leave ghost images behind.
Related
I am working on a drawing app as a personal project (currently living at http://draw.ist/) and I'd like to get the drawn strokes smooth around the edges but it seems the only way to accomplish this is using clearRect. However, clearRect also clears the canvas every time I start a new path and I'd like to prevent that so the canvas actually accumulates the strokes.
I've seen stuff about creating a secondary canvas to save strokes to or something so the clear doesn't wipe them (at least I think it works somewhat like that) however that method would require a lot of additional code that I'd like to avoid. Most recently I've tried saving the canvas as an imageURL on mouseup and then re-placing it with drawImage right after every clearRect, and this seems to do the trick nicely but it has some bizarre interactions with my eraser and straightline tools, as well as some flickering every time it loads in the saved canvas image.
There isn't necessarily any particular snippet of relevant code here, but for reference the entire site can be found at http://draw.ist/ (Controls: hold shift to draw straight lines, hold spacebar to erase, scroll mousewheel to change brush size)
I'd like all drawn lines to be smooth and have antialiasing but without using the "secondary canvas as memory" method IF POSSIBLE. I think what could help me here as well is understanding why exactly clearRect is necessary to apply antialiasing to strokes in canvas and how it works exactly in layman's terms. I greatly appreciate any assistance on this, whether it's actually helpful or not!
I'm in the process of creating an interactive whiteboard application using PHP and jQuery. Creating a deck is not the issue, nor is applying a canvas overlay to the page so that I can write on it. I'm an amateur coder and completely self-taught. This is part an exercise in learning more, and part a means to give me a great tool to use in my teaching practice.
The problem that I'm encountering is applying a CSS transition to the canvas element, so that as the slides change, the canvas element moves as well, in order to avoid having the previously made drawings still present on new slides.
I have gotten the canvas element to move with the slide transition, however, when this happens, the canvas is rendered useless (on the current slide). If I transition back to the previous slide, I can see everything I've drawn.
I'm hoping that this isn't too vague of a question or explanation of the situation to get help, but any pointers would be great.
Figured out the problem. I thought the original script was taking into account the distance the slides were transitioning, but it wasn't. I added in a line to take care of this, and it works like a charm.
I'm animating a sprite on a pixel grid. I have a few options, with pros and cons for each. I have a fair amount of javascript experience (six years), but none with this kind of thing. The problem is I don't know how expensive each option will be.
The sprite needs to render quite fast, and be inexpensive enough to have at least five running at the same time while running collision detection.
Ideally, I would like to use a grid of elements inside of a wrapper, rendering colour and alpha channels to each element from a multidimensional array.
The major pro here is that I can run pixel-by-pixel collision detection and click past the transparent parts of the sprite. With any image-based sprite, the onClick event will fire even if I click on a transparent pixel (I'll have to do a lot of work to pass clicks through transparent pixels, and it might be quite expensive).
The next option is to use css sprites. css-tricks.com/css-sprites/
This would be easy peasy, but as mentioned previously, onClicks won't pass through the transparent pixels. I can probably force it, but again, it may be expensive, and take a lot of time to impliment.
Another option is animated gifs, but they are huge, limited in the colour department, and hard to control animation-wise. I'd rather not go there.
And then there's the html5 canvas element, which I don't know very much about and would like to stay away from if at all possible. I don't know how any of my code would even work in relation to the canvas element and I doubt it would do what I want in the long-run.
So which is the best for performance? Would the first (and most preferable) be a viable option? Or have I missed something out?
With today's browsers you will be fine on desktop computers for building a sprite out of positioned pixel sub-elements (as long as they aren't too complicated or large), and just to be safe I'd limit yourself to about 10 active sprites. With Mobile things might get a bit slow and clunky, but considering you seem to be designing a game that requires precision "onclicks" I doubt that this will be a problem.
Your most flexible bet is to use HTML5 Canvas, as you have already worked out, but it will involve quite a bit more JavaScript coding. But this sytem will allow you to apply a number of effects to your sprites and will allow you to use pixel perfect detection by using getImageData (which allows you to read the exact pixel colour at any pixel offset).
getPixel from HTML Canvas?
If you wanted to avoid the techinical problems and challenges of having a full screen canvas system (which can be tricky), you can actually create as many smaller Canvas elements and move them around as your sprites (with the ease of HTML Elements).. Then all you have to do is design the code that draws your animation frames, and also tells if the mouse has hit or not hit the sprite using the aforementioned method (along with a click handler and some code to calculate where the user has clicked relative to your canvas elements position). Obviously, it would be best to do this in a generalised way so your code can be applied to all your sprites :)
To draw your images on the canvas you can use a spritesheet as you were mentioning in your question, and use the rather flexible drawImage() method which supports a slicing mode. This just needs to be tied up to a setInterval or requestAnimationFrame style game loop.
https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Using_images
http://www.playmycode.com/blog/2011/08/building-a-game-mainloop-in-javascript/
UPDATE - for those who wish to be very optimal
If you wish to take a more optimal route - which is a little bit more involved again - you can do the following. This method benefits if you have many sprites that are exactly the same with only a few (20 or 30) frames of animation:
Power your sprites by normal DIVs with a background image sprite sheet that you shift the background position of. This is the most optimal you can be, save having static images as sprites, because the browser does all the work.
for each sprite type draw your spritesheet on a hidden canvas element that is big enough to incorporate your whole spritesheet.
When a user clicks on one of your DIV sprites, take the background position as coordinates, invert them, and you should then know where on your canvas element (looked up by sprite's type) the pixel data resides.
Use the getPixelData method on your hidden canvas to work out if the user has clicked on the sprite or not.
The above means you only have one canvas element in use - per sprite type, the browser handles all the graphics for you and you get pixel perfect collisions with an onclick.
Hope the above makes sense?
How about splitting your image spirit into 30x30 cells and only have elements where the cell is opaque and leave a gap where the cell is transparent so that clicks fall through. You lose a bit of accuracy in where the cells can be clicked though.
my link: http://dl.dropbox.com/u/7727742/playlistsite6/index5.html
I have a 3d cube using a variation of zachstronaut's demo
(link: http://www.zachstronaut.com/lab/galaxy-box/ ). It uses javascript, translate3d, scale3d, etc...
I've tried assigning different z-index values in the css file, but with no luck. I can access the objects outside the cube(you can see this with the hover effect), but not the objects inside the cube. I have a hunch it is because it's not doing a z-sort type of function like pre3d.js. I was wondering if anyone could offer some insight into where I should look for a solution.
Object coordinates are generated randomly, so you may have to refresh once or twice to get some objects that are inside the cube.
Thanks!
EDIT:
Only tested in safari and chrome dev
Webkit ignores z-indexes on anything that has translate3d defined, as it logically should. z-index is meant for a 2D world, it's like taking a bunch of paper and saying "this one is on top" -- you still have a flat surface. Unfortunately, if you want to be able to select one of the "stars" inside of your box, you're all but out of luck since you're using HTML nodes.
The normal way of doing this is using a click-map -- basically every object gets rendered twice. Once normally and once in a single color with no shading, etc. The 2nd rendering is never shown and is simply used to tell what the user clicked on. You get the color where they clicked and that color maps to a specific object. If you were using canvas, you would do it that way and just change the rendering order on the 2nd render.
Since you're using HTML nodes, you can't do that. You have a couple of options:
You can calculate which star is under the mouse on mouse-move based on viewport rotation and x/y/z position of the star
you can attempt the above method by overlaying an identical rendering without the cube and where the stars have a 0% opacity. Each star in your new rendering would map to a star in your existing one, and you'd have easy mouse-over detection.
Post the results! :)
First of all, I'm glad you found my demo interesting!
You're not going to have much luck trying to do a hover or capture a click event on objects inside of a 3D CSS3 cube for the exact same reason you wouldn't have much luck capturing a hover or click events on a div underneath another div... in HTML all the DOM events go to the top most DOM node. If one div overlaps another div, you can't click the one that is underneath. Everything inside the 3D cube is "underneath" another DOM node.
Things are further complicated because you're taking objects in 3D space and asking a user to interact with them on a 2D plane (the browser window) using a 2D input device (the mouse).
You could hide the faces of the cube so that they wouldn't block the user's clicks. You could do something like cwolves suggested.
Sorry I couldn't be more help... HTML kind of fails us a bit here. Welcome to the bleeding edge!
The 2nd part of the question is, which javascript library is better/easier to manipulate images with? I won't be actually drawing any shapes or anything. Other info: I'll be using jQuery and don't need to support all browsers, just webkit.
Edit:
More information: the current design is to layout/draw several rows/columns of images in a grid-like layout, with the image in the center being in "focus" (a little larger, with a border or something and some text next to it). The tricky thing is that we want the whole canvas of images to appear to slide/glide over to bring another random image into focus. So obviously the number of images in this grid needs to exceed what is visible in the viewport so that when the transition occurs there are always images occupying the canvas. Other than moving the images around, I won't be blurring them or otherwise modifying them. Eventually we will add user interactions like clicking/touching on a visible image to bring it to focus manually.
Let me know if this is not clear or still confusing.
I ran across scripty2 which seems like an alternative to using canvas/SVG for my purposes. I also started farting around with EaselJS last night, and it seems like this might work, but I'm wondering if it'll end up being more work/complex than just using standard HTML/CSS and a tool like Scripty2 to aid with animations and click/touch events. Just looking for any suggestions. Thanks!
The answer depends on your manipulation and animation.
If it's just translations, CSS wins for speed compared to canvas. I haven't tested, but I feel confident it easily beats SVG for the same sort of thing.
If you're going to be doing non-affine transformations or otherwise messing with the images (e.g. blurring them) you clearly want Canvas.
If you need event handlers per object, you clearly want a retained-mode drawing system like SVG or HTML+CSS. I haven't done enough CSS3 transforms to say how they compare in terms of speed to SVG, but they clearly do not have the robust transformation DOM of SVG.
This is a rather subjective question (or suite of questions) and you haven't yet given sufficient information for a clear answer to be possible.