Fastest / most efficient way to draw moving speech bubbles on screen - CoreAnimation, Quartz2D? - iphone

I am adding some functionality to an iPhone app, and could use some help in picking the fastest / most efficient / best practice approach for solving this problem:
At the upper-half of my screen, I have speech bubbles (think comic book) that are UIImageViews translating across the screen (dynamic x & y position). It is a UIImageView because there is an image as the background of the speech bubble.
Each speech bubble has a matching image moving around the bottom of the screen (elsewhere in the layer tree)
I would like to draw a tail (that triangle bit from a speech bubble) so the point of the triangle is tracking the lower image, with the base of the triangle being attached to the bottom of the upper UIImageView. (technically the base doesn't have to be butted against, it can overlap as long as I can match the color of my background image to the triangle).
I have already done all the tracking & drawn a line with CGContextStrokePath methods, and now I am stuck on how to replace the line with a triangle.
I have looked at drawing a triangle in Quartz and filling it. My concern is the speech bubbles are repositioned every 1/10th of a second, and it looks like drawing just the line used for proof of concept had a pretty severe performance / visual smoothness impact.
One idea I have is to do the trigonometry myself, and stretch & rotate an image of a triangle to connect each of these speech bubbles with the lower spot. Something is telling me there is a more efficient / more elegant solution, but I am not able to see it looking through the documentation. Any help on how you have or would approach this issue is appreciated. Thanks.

If the speech bubbles are fixed in size, just use a static UIImage. Set the image view's layer.position property at the point of the triangle. Then you can use view animation to move the bubbles around.
If you need the speech bubbles to be different sizes, I'd create a resizeable image using resizableImageWithCapInsets. Then I'd do the same as above to position it.
If there was something special about the speech bubble that I could't achieve with either a static image or a resizable image, I'd probably create a custom CA Layer or layers to get the effect I wanted (Like a gradient layer with a shape layer as it's mask layer)

Related

2D sprite problem when setting up an instant messaging UI

I'm new to Unity and to game development in general.
I would like to make a text-based game.
I'm looking to reproduce the behavior of an instant messenger like messenger or whatapp.
I made the choice to use the Unity UI system for the pre-made components like the rect scroll.
But this choice led me to the following problem:
I have "bubbles" of dialogs, which must be able to grow in width as well as in height with the size of the text. Fig.1
I immediately tried to use VectorGraphics to import .svg with the idea to move runtime the points of my curves of Beziers.
But I did not find how to access these points and edit them runtime.
I then found the "Sprite shapes" but they are not part of the "UI",
so if I went with such a solution, I would have to reimplement
scroll, buttons etc...
I thought of cutting my speech bubble in 7 parts Fig.2 and scaling it according to the text size. But I have the feeling that this is very heavy for not much.
Finally I wonder if a hybrid solution would not be the best, use the
UI for scrolling, get transforms and inject them into Shape sprites
(outside the Canvas).
If it is possible to do 1. and then I would be very grateful for an example.
If not 2. 3. 4. seem feasible, I would like to have your opinion on the most relevant of the 3.
Thanks in advance.
There is a simpler and quite elegant solution to your problem that uses nothing but the sprite itself (or rather the design of the sprite).
Take a look at 9-slicing Sprites from the official unity documentation.
With the Sprite Editor you can create borders around the "core" of your speech bubble. Since these speech bubbles are usually colored in a single color and contain nothing else, the ImageType: Sliced would be the perfect solution for what you have in mind. I've created a small Example Sprite to explain in more detail how to approach this:
The sprite itself is 512 pixels wide and 512 pixels high. Each of the cubes missing from the edges is 8x8 pixels, so the top, bottom, and left borders are 3x8=24 pixels deep. The right side has an extra 16 pixels of space to represent a small "tail" on the bubble (bottom right corner). So, we have 4 borders: top=24, bottom=24, left=24 and right=40 pixels. After importing such a sprite, we just have to set its MeshType to FullRect, click Apply and set the 4 borders using the Sprite Editor (don't forget to Apply them too). The last thing to do is to use the sprite in an Image Component on the Canvas and set the ImageType of this Component to Sliced. Now you can scale/warp the Image as much as you like - the border will always keep its original size without deforming. And since your bubble has a solid "core", the Sliced option will stretch this core unnoticed.
Edit: When scaling the Image you must use its Width and Height instead of the (1,1,1)-based Scale, because the Scale might still distort your Image. Also, here is another screenshot showing the results in different sizes.

Unity3D - Make texture edges not stretch

I've been searching around for this one for a bit, and unfortunately I can't seem to find any good, consistent results. So, in the Unity UI system, buttons can stretch without becoming pixelated or distorted. This is because the texture is split up into 9 parts - the corners, middle, and sides.
This works because the button's middle and sides are stretched, but not the corners. Then, the button appears not pixelated, at any dimension.
So, the question is as follows: How can I do the same thing for a transparent, unlit texture in 3D space? I have a speech bubble texture on a flat plane that I know how to re-scale to fit the text in the speech bubble.
I've set the texture type to Multiple Sprite, and divided it up into 9 parts. However, I cannot seem to find where I can set the texture to act like the UI button does, and I'm not sure that this is even possible in this way in 3D space.
Is there a way, or should I just make the different parts of the texture different objects, and move them together? That would seem very inefficient and ugly compared to this.
To accomplish what you are asking, you would need to create tiles for this speech bubble and then write a script that procedurally builds a speech bubble based on the plane's scale value. You could also try just changing the texture's Filter Mode to Point.
However I really don't think you should be using textures for this anyway. Why not just use a Unity Canvas and set the Render Mode to World Space? Then you can just set your text box to be a sprite, not a texture, and set its filter mode to Point (See below). This would also make it a lot easier for when you want there to be text in the speech bubble later on.

How to draw a light effect over a texture on iPhone using UIKit/Quartz

I have a scene with a background image (a lit room), and a black image (shadow) over that. I need to be able to move my finger over the background and reveal some parts of the scene, simulating a dim light source in a dark room.
My current approach was to generate a mask depending on the position of the touch, and then applying that mask to the shadow image. The problem is I'm generating a new mask and applying it every time I receive a touch event. It's a large image (800x600) and this causes the performance to go down and it increases a lot the memory usage, eventually crashing the game (I think I don't have any memory leaks, but that's not warrantied... anyway the performance itself isn't acceptable).
Can anyone think of a better approach (which doesn't involve using OpenGL ES -- that's not an option in this project) to do this?
To go with my comments above.
Maybe to get around the different shadow levels you could also have a grid of views (squares) between the image and the shadow view. each grid square has a different alpha opacity and when the spot is over a grid square, the grid square's alpha opacity changes to 0. when the spot moves off the grid square it's alpha opacity changes back to it's default.
Without more information it is a little difficult to know whether this approach will work in your case but what you could do is generate a single mask image, say, a radial alpha gradient and then apply an affine transform to it to shape it according to the touches. This can be used to simulate a torch/flashlight beam.
I would try this: use one view with a custom drawRect implemetation: first draw the shadow image (in grayscale) then a bright spot image in white an alpha. And finally the background image in a 'multiply' blend mode.
Just a thought, does the shadow has to be an image? Perhaps you could simply fill the shadow layer with a color and mask it then? This way the memory usage should be less and the effect should be nearly identical (if not exactly the same).
There is no reason to generate a new mask on every touch move. Instead, let the mask be initialized once and manipulate it (reset it's frame) as needed upon touch events.

Creating a bounding box for a UIImageView

How can a bounding box be created for a UIImageView that is not a CGRect?
I would like to have objects in my view which should display images as well as detection collisions.
The issue is I would like these object to be whatever shape they are rather than fitting them into a CGRect and detecting collisions on areas which are inside the box but are nit the actual image.
How does one achieve this?
This is a non-trivial problem. But the basics are a CGRect is a rectangle and a hit test inside of a rectangle is fairly easy to understand. However, you sound like you want a more complex shape. UIImageView displays an image. It does not have any idea about what shape you want to use for your collision test. So you are going to have to tell it.
One easy thing to do is to look at the alpha/transparent values of the display image to create a shape. So to answer the question is a point hitting an image we figure out the location of point in the image and return true if the alpha is greater than 0. If you do this you can create any image with a transparent background and the code will just work.
If that will not work for you then can can also run a hit test on a point and a polygon this post covers that in detail.
How can I determine whether a 2D Point is within a Polygon?

Iphone/Ipad : What is the fastest way to draw an irregular polygon in a rectangle?

I have to draw the following shape in a rectangle. What is the best way to do it? The blue areas are the background color. The black is a border and the red is the interior color. I want to paint the black and red only.
Thanks
It totally depends on how you would use the shape; whether they will move, how many of them will be displayed, whether they will be scaled while being displayed, etc.
In general, OpenGL ES is considered to be the fastest way of drawing on iOS devices. However, if you have only a small number of those shape (say, <10~100?) and the other part of the application does not have a lot of fast animations Quart 2D is usually enough in terms of drawing, in order to, say, achieve a 30/60Hz drawing rate.
How you use Quartz2D still matters a lot. If you need to redraw the shapes frequently, you would need to draw the shape on CALayers, and rather than redrawing the shapes, you should move and transform the layers.
Comparing drawing as a bitmap and a vector shape, I believe both would work fine for this kind of shape (especially because you would not redraw the shape so often, but only work with the layer on which the image already is drawn). But if your shapes are scaled frequently, you would consider vector images for the quality of the image.
To summarize, learn (if you don't already know) how to draw into a graphics context first (see Drawing and Printing Guide for iOS). You should be able to draw a simple vector shape or a bitmap image by overriding drawRect or similar methods inside a UIView object. Then if you need to animate those shapes, learn how to create a CALayer and draw on the layer (see Core Animation Programming Guide). Finally, if you need to create many duplicates of the shape on the screen, learn how to use CGLayer to replicate an image (see Quartz 2D Programming Guide).