I'm trying to get my head around using QuartzCore to render semi-complex text/gradient/image UITableViewCell composites. Thankfully, Opacity will let me visually build the view and then spit out source code to drop in to cocoa touch. Trouble is, Opacity assumes the code is running on iOS 4, which is a problem if you want to draw Quartz views on an iPad.
For me, the offending method is CGPathGetPathBoundingBox ... would someone mind pointing me to a suitable alternative or workaround to this (presumably simple) method?
If you care to have some context (no pun intended), here you go:
transform = CGAffineTransformMakeRotation(1.571f);
tempPath = CGPathCreateMutable();
CGPathAddPath(tempPath, &transform, path);
pathBounds = CGPathGetPathBoundingBox(tempPath);
point = pathBounds.origin;
point2 = CGPointMake(CGRectGetMaxX(pathBounds), CGRectGetMinY(pathBounds));
transform = CGAffineTransformInvert(transform);
The alternative is to iterate on the points of the path and note down the leftmost, rightmost, upmost, and downmost co-ordinatesĀ of the anchor points yourself, then work out origin and size from those numbers.
You should wrap this in a function, and name it something like MyPathGetPathBoundingBox, and use that until you drop support for iOS 3.x. That will make it easy to switch to CGPathGetPathBoundingBox once you can.
Related
in this video, https://youtu.be/klBvssJE5Qg I shows you how to spawn enemies outside of a fixed camera. (this is in GDscript by the way) How could I make this work with a moving camera? I wanna make a zombie fighting game with a moving camera and zombies spawning outside that.
I would really appreciate help with this.
I've tried researching on the internet about how to do it, but I just didn't find it.
N/A..................................
After looking at the video, I see they are using this line to spawn:
Global.instance_node(enemy_1, enemy_position, self)
This suggest to me a couple thing:
The position is probably either relative to the self passed as argument or global.
There must be an Autoload called Global that I need to check to make sure.
And the answer is in another castle video.
In the video Godot Wave Shooter Tutorial #2 - Player Shooting we find this code:
extends Node
func instance_node(node, location, parent):
var node_isntance = node.instance()
parent.add_child(node_instance)
node_instance.global_position = location
return node_instance
And thus, we are working with global coordinates global_position. Thus enemy_position is used as global coordinates.
Ok, instead of using enemy_position as global coordinates we are going to use it as local coordinates of the Camera2D (or a child of it). Which means you need a reference to the Camera2D (which I don't know where do you have it).
You could make your code in a child of the Camera2D, or take the transform of the Camera2D using a RemoteTransform2D. Either way, you could then work in its local coordinates. Thus you would do this:
Global.instance_node(enemy_1, to_global(enemy_position), self)
Or you could have a reference by exporting a NodePath (or in the newest Godot you can export a Camera2D) from your script and set it via the inspector. So you can do this:
Global.instance_node(enemy_1, camera.to_global(enemy_position), self)
Where camera is your reference to the Camera2D.
In the following section of Arena.gd:
func _on_Enemy_spawn_timer_timeout():
var enemy_position = Vector2(rand_range(-160, 670), rand_range(-90, 390))
I believe you can add the X and Y coordinates of the camera to their corresponding random ranges in the enemy position Vector2. This will displace the enemy depending on where the camera is currently located.
You can get the position of the camera with this:
get_parent().get_node("Name of your camera").position
When this is all put together:
func _on_Enemy_spawn_timer_timeout():
var enemy_position = Vector2(rand_range(-160, 670) + get_parent().get_node("Name of your camera").position.x, rand_range(-90, 390) + get_parent().get_node("Name of your camera").position.y)
Keep in mind that you might need to displace the values in the following while loop as well. I hope this helps.
I try to add a B&W filter to the camera images of an ARSCNView, then render colored AR objects over it.
I'am almost there with the following code added to the beginning of - (void)renderer:(id<SCNSceneRenderer>)aRenderer updateAtTime:(NSTimeInterval)time
CVPixelBufferRef bg=self.sceneView.session.currentFrame.capturedImage;
if(bg){
char* k1 = CVPixelBufferGetBaseAddressOfPlane(bg, 1);
if(k1){
size_t x1 = CVPixelBufferGetWidthOfPlane(bg, 1);
size_t y1 = CVPixelBufferGetHeightOfPlane(bg, 1);
memset(k1, 128, x1*y1*2);
}
}
This works really fast on mobile, but here's the thing: sometimes a colored frame is displayed.
I've checked and my filtering code is executed but I assume it's too late, SceneKit's pipeline already processed camera input.
Calling the code earlier would help, but updateAtTime is the earliest point one can add custom frame by frame code.
Getting notifications on frame captures might help, but looks like the whole AVCapturesession is unaccessible.
The Metal ARKit example shows how to convert the camera image to RGB and that is the place where I would do filtering, but that shader is hidden when using SceneKit.
I've tried this possible answer but it's way too slow.
So how can I overcome the frame misses and convert the camera feed reliably to BW?
Here's the key for this problem:
session:didUpdateFrame:
Provides a newly captured camera image and accompanying AR information to the delegate.
So just moved CVPixelBufferRef manipulation, the image filtering code from
- (void)renderer:(id<SCNSceneRenderer>)aRenderer updateAtTime:(NSTimeInterval)time
to
- (void)session:(ARSession *)session didUpdateFrame:(ARFrame *)frame
Made sure to set self.sceneView.session.delegate = self to have this delegate called.
My CAMetalLayer background color is black, even if i'm assigning new color as the backgroundColor property.
Am i missing something? Thanks!
Link to the original project :
https://github.com/audiokit/MetalParticles
This project takes a rather unconventional approach to clearing the drawable's texture each frame: it replaces the textures contents with an array of zeros that is the same size as the texture (width * height * 4). Subsequently, it encodes some compute work that actually draws the particles. This is almost certainly not the most efficient way to achieve this effect, but if you want to make the smallest change that could possibly work (as opposed to experimenting with making the code as efficient as possible), Just fill the blankBitmapRawData array with your desired clear color (near line 82 of ParticleLab.swift).
I have gone through your code and can not see a place where you are setting background Color.
The metal layer is added as a sublayer to it, so you have to set it explicitly.
Add this line at the end of your init method in ParticialLab class and see if it works.
self.backgroundColor = UIColor.redColor().CGColor
I found that self.isOpaque = false was needed on the layer.
Note: for this I am using a program called spritebuilder, which allows me to create a game with less code than would normally be needed. If you know a solution that's just all code, then by all means feel free to share it :)
Also, for this question, I followed a tutorial at this link: Build Your Own Flappy Bird Clone. Just scroll down to the part that says: "Loop the Ground"
So here's my problem. Im currently working on a game, and I created a camera which scrolls vertically long with the character sprite i created, however i need a certain image to loop. When the image leaves the bottom part of the screen I would like it to loop around to the top of the screen, infinitely. For this i created two identical images (in this case its the bark of a tree). One will be on screen, while the other will be offscreen, so as the first image leaves the screen, the second will replace it (seamlessly). I created two objects for the images, and assigned them the name _ground1, and _ground2, and I also created an NSArray in which to store them in. (Please refer to the link above if it is somewhat confusing)
Here is the code that I have:
CCNode *_ground1;
CCNode *_ground2;
NSArray *_grounds;
for (CCNode *ground in _grounds) {
// get the world position of the ground
CGPoint groundWorldPosition = [_physicsNode convertToWorldSpace:ground.position];
// get the screen position of the ground
CGPoint groundScreenPosition = [self convertToNodeSpace:groundWorldPosition];
// if the left corner is one complete width off the screen, move it to the right
if (groundScreenPosition.y <(-1 * ground.contentSize.height)) {
ground.position = ccp(ground.position.x , ground.position.y + 2 * ground.contentSize.height);
}
For some reason when I try this, it doesnt seem to work. what happens is that, the camera will travel vertically as it is meant to do, but the images do not loop. Once the two images leave the bottom of the screen, no new images replace them.
i also done this project as above tutorials. it work fine but you have some mistake to set variable in spritebuilder. in your above code replce code as and try it. you only put less than may be it issue.
if (groundScreenPosition.y <=(-1 * ground.contentSize.height)) {
ground.position = ccp(ground.position.x , ground.position.y + 2 * ground.contentSize.height);
}
You are using CCNode objects as _ground1and _ground2.
CCNode objects usually do not have a contentSize, they will return 0 unless you explicitly set them inSpriteBuilder`.
Make sure that you are using CCSprite objects in SpriteBuilder and in your code.
Also, as a friendly hint you should also consider refactoring (renaming) your sprites with more meaningful names for your use case like _treeBark1 and treeBark2 for example.
I have a circle-shaped dynamic body and I need to resize it during the game (It appears like a point, then it grows to a circle and after that it starts moving). How should I do that?
I have an idea - it's to use some animation (Circle has the same radius, but due to animation it looks like the circle grows), but I'm not sure if it's right way or not. (Besides I don't know how to realize it)
For scaling circle, if you are using sprite just scale it sprite.setScale(float), if your sprite is attached to Box2d Circle-shape then get the Body's shape and set the radius
Shape shape = body.getFixture().getShape;
shape.setRadius(radiusValue);
and if you are using ShapeRenderer just multiply the points of ShapeRenderer.
I assume that you are talking about a Box2D body.
It is not possible to change a circle-shaped fixture with Box2D. Box2D is a rigid body simulator. What you would have to do is destroy the fixture and replace it with a smaller/bigger version of the circle. But this will cause a lot of problems, since you cannot destroy a fixture when there is still a contact for example.
It would be better to keep the circle the same size and just simulate a change in size with an animation of a texture on top.
If you cannot simulate that, then maybe try the following approach: Have several versions of that circle in different sizes and keep them on top of each other. Implement a ContactFilter which will only cause contacts for the one circle which is currently "active".
Inside any Object class with box2d, I use the following for dynamic resizing:
public void resize(float newradius) {
this.body.destroyFixture(this.fixture);
fixtureDef.density = (float) (this.mass/(Math.PI*newradius*newradius));
this.radius = newradius;
CircleShape circle = new CircleShape();
circle.setRadius(newradius);
this.fixtureDef.shape = circle;
circle.dispose();
this.fixture = body.createFixture(fixtureDef);
this.fixture.setUserData(this);
}
You can also see the following topic: How to change size after it has been created