Multi-Mobject FadeIn and FadeOut Simultaneously in manim - manim

I want to draw multiple Circles that appear and disappear almost simultaneously.
How should I write the code?
If the scene I want to draw is the scene like all the circles appear and then all the circles disappear, then, I could write it like case A in the code below, but that is not what I want to do.
How can I draw the scene where some circles appear after some disappear?
I tried Trial1 but it didn't show anything.
from manim import *
class MultiMobjectFadeInAndOut(Scene):
def construct(self):
circles = [Circle(r / 10) for r in range(10)]
anims_in = [FadeIn(c, scale=10) for c in circles]
anims_out = [FadeOut(c, scale=10) for c in circles]
# Case A
self.play(LaggedStart(*anims_in, lag_ratio=0.1))
self.play(LaggedStart(*anims_out, lag_ratio=0.1))
# Trial 1
anims = []
anims.extend(anims_in)
anims.extend(anims_out)
self.play(LaggedStart(*anims, lag_ratio=0.1))
I'm using Manim Community v0.16.0.post0

Related

How can I get camera scrolling to work in Lua (using the PlayDate SDK)?

I have three issues with my PlayDate game, one big, two small:
#1 (small): I can't get camera scrolling to work;
#2 (small): I can't figure out how to not get circles to generate inside of eachother;
#3 (big): I have NO IDEA how to make a menu screen and have it change the songs (I haven't added the songs yet, I'm still writing them)
Here's my code:
import "CoreLibs/graphics"
import "CoreLibs/object"
import "CoreLibs/sprites"
import "CoreLibs/nineslice"
import "CoreLibs/timer"
import "CoreLibs/frameTimer"
import "config"
import "core/definitions"
import "core/cotton/all"
import "scripts/index"
import "core/lieb/all"
import "core/CoreGame"
bpm = 60
lastX = math.random(80, 320)
lastY = math.random(80, 160)
circles = {}
tf = playdate.geometry.affineTransform.new()
local circles = {}
local count = 0
function addCircle()
tf:rotate(math.random(360))
x, y = (tf * playdate.geometry.point.new(80, 0)):unpack()
x += lastX
y += lastY
local new_circle = playdate.graphics.drawCircleAtPoint(x, y, 40)
count = count + 1
table.insert(circles, new_circle)
lastX = x
lastY = y
playdate.graphics.setDrawOffset(x, y)
end
beatTimer = playdate.timer.performAfterDelay(60000 / bpm, addCircle)
beatTimer.repeats = true
function playdate.update()
playdate.timer.updateTimers()
end
For the menu, I know I should use grid view, but I don't know how to make things happen when something is selected, and different things when something else is selected.
For the scrolling, I want it so that you're always seeing the circles and they never go off screen, so I'm trying to change the camera's origin point to where the circles are, but it's not working.
And finally, #2 is pretty self explanatory.

How to have multiple dots move at constant speed around a circle in manim?

I want to reproduce the animation here in manim.
I found how to have multiple dots move along a circle, but they only do one turn and don't have constant speed.
How to have them move at constant speed and do multiple turns ?
Here is my attempt up to now :
def construct(self):
circle = Circle()
points = Group(*[Dot((1, 0, 0)) for _ in range(2)])
self.add(circle)
self.add(points)
self.play(
MoveAlongPath(points[0], circle, run_time=1),
MoveAlongPath(points[1], circle, run_time=2)
)
Just found an answer, easier than I thought :
self.play(Rotating(points[0],
radians=2 * TAU,
about_point=ORIGIN),
Rotating(points[1],
radians=TAU,
about_point=ORIGIN),
)

Why the angle moves lagging behind the dot

There is a grouped angle (two lines and a arc) moving and rotating at the same time, depending on the location of another Dot, from the video, the grouped angle is lagged behind the Dot, don't know why? below is the code:
class MovRot(Scene):
def construct(self):
ln = Line(LEFT*2, LEFT*1+UP*1.5)
self.add(ln)
ln_ab = Line(LEFT*2, interpolate(LEFT*2, LEFT*1+UP*1.5, 0.7), color=RED_D)
ln_bc = Line(LEFT*2, ORIGIN, color=RED_D)
arc_b = Arc(0, ln_ab.get_angle(), radius=0.6, color=RED_D).move_arc_center_to(LEFT*2)
grp_b = VGroup(ln_ab, ln_bc, arc_b)
self.add(grp_b)
dt = Dot(color=YELLOW_D).move_to(LEFT*2)
grp_1 = grp_b.copy()
def update_grp1(mob, alpha):
mob.become(grp_1)
mob.move_to(dt.get_center(), aligned_edge=arc_b.get_arc_center())
mob.rotate(alpha*PI, about_point=arc_b.get_arc_center())
self.add(grp_1, dt)
self.play(UpdateFromAlphaFunc(grp_b, update_grp1, rate_func=smooth), dt.move_to, LEFT*1+UP*1.5,
rate_func=smooth,
run_time=2)
Thanks for any help.
You always have to write the "master" animation at the beginning of the play method, in your case, the animation that "takes the baton" is move_to, so it must be the first to be written:
self.play(
dt.move_to, LEFT*1+UP*1.5,
UpdateFromAlphaFunc(grp_b, update_grp1, rate_func=smooth),
rate_func=smooth,
run_time=2
)

Box2D: How to use b2ChainShape for a tile based map with squares

Im fighting here with the so called ghost collisions on a simple tile based map with a circle as player character.
When applying an impulse to the circle it first starts bouncing correctly, then sooner or later it bounces wrong (wrong angle).
Looking up on the internet i read about an issue in Box2D (i use iOS Swift with Box2d port for Swift).
Using b2ChainShape does not help, but it looks i misunderstood it. I also need to use the "prevVertex" and "nextVertex" properties to set up the ghost vertices.
But im confused. I have a simple map made up of boxes (simple square), all placed next to each other forming a closed room. Inside of it my circle i apply an impulse seeing the issue.
Now WHERE to place those ghost vertices for each square/box i placed on the view in order to solve this issue? Do i need to place ANY vertex close to the last and first vertice of chainShape or does it need to be one of the vertices of the next box to the current one? I dont understand. Box2D's manual does not explain where these ghost vertices coordinates are coming from.
Below you can see an image describing the problem.
Some code showing the physics parts for the walls and the circle:
First the wall part:
let bodyDef = b2BodyDef()
bodyDef.position = self.ptm_vec(node.position+self.offset)
let w = self.ptm(Constants.Config.wallsize)
let square = b2ChainShape()
var chains = [b2Vec2]()
chains.append(b2Vec2(-w/2,-w/2))
chains.append(b2Vec2(-w/2,w/2))
chains.append(b2Vec2(w/2,w/2))
chains.append(b2Vec2(w/2,-w/2))
square.createLoop(vertices: chains)
let fixtureDef = b2FixtureDef()
fixtureDef.shape = square
fixtureDef.filter.categoryBits = Constants.Config.PhysicsCategory.Wall
fixtureDef.filter.maskBits = Constants.Config.PhysicsCategory.Player
let wallBody = self.world.createBody(bodyDef)
wallBody.createFixture(fixtureDef)
The circle part:
let bodyDef = b2BodyDef()
bodyDef.type = b2BodyType.dynamicBody
bodyDef.position = self.ptm_vec(node.position+self.offset)
let circle = b2CircleShape()
circle.radius = self.ptm(Constants.Config.playersize)
let fixtureDef = b2FixtureDef()
fixtureDef.shape = circle
fixtureDef.density = 0.3
fixtureDef.friction = 0
fixtureDef.restitution = 1.0
fixtureDef.filter.categoryBits = Constants.Config.PhysicsCategory.Player
fixtureDef.filter.maskBits = Constants.Config.PhysicsCategory.Wall
let ballBody = self.world.createBody(bodyDef)
ballBody.linearDamping = 0
ballBody.angularDamping = 0
ballBody.createFixture(fixtureDef)
Not sure that I know of a simple solution in the case that each tile can potentially have different physics.
If your walls are all horizontal and/or vertical, you could write a class to take a row of boxes, create a single edge or rectangle body, and then on collision calculate which box (a simple a < x < b test) should interact with the colliding object, and apply the physics appropriately, manually calling the OnCollision method that you would otherwise specify as the callback for each individual box.
Alternatively, to avoid the trouble of manually testing intersection with different boxes, you could still merge all common straight edge boxes into one edge body for accurate reflections. However, you would still retain the bodies for the individual boxes. Extend the boxes so that they overlap the edge.
Now here's the trick: all box collision handlers return false, but they toggle flags on the colliding object (turning flags on OnCollision, and off OnSeparation). The OnCollision method for the edge body then processes the collision based on which flags are set.
Just make sure that the colliding body always passes through a box before it can touch an edge. That should be straightforward.

Make a line thicker in 3D?

In reference to this question
Drawing a line between two points using SceneKit
I'm drawing a line in 3D and want to make it thicker by using this code
func renderer(aRenderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: NSTimeInterval) {
//Makes the lines thicker
glLineWidth(20)
}
but it doesn't work, iOS 8.2.
Is there another way?
Update
From the docs
https://developer.apple.com/library/prerelease/ios/documentation/SceneKit/Reference/SCNSceneRendererDelegate_Protocol/index.html#//apple_ref/occ/intfm/SCNSceneRendererDelegate/renderer:updateAtTime:
I did add SCNSceneRendererDelegate and a valid line width but still could not get the line width to increase.
You cannot assign any number to glLineWidth().
You can check the range of possible values of glLineWidth()by:
glGetFloatv(GL_LINE_WIDTH_RANGE,sizes);
One crazy idea is to use a cylinder for drawing lines ;). I use it when I want to have nice and controllable lines but I am not aware of a handy OpenGl function to do so.
#G Alexander: here you go my implementation of cylinder. It is a bit tedious but it is what I have at the moment.
If you give me points p0 and p1, Vector normal=(p1-p0).normalize() would be the axis of the cylinder.
pick point p2 that is not on the vector Normal.
q=(p2-p0).normalize();
normal.crossproduct(q)=v0;
normal.crossproduct(v0)=v1;
Having these two vectors you can have circles with any radius that are stacked along the axis of the cylinder using the following function (A cylinder is a stack of circles):
public Circle make_circle(Point center, Vector v0, Vector v1, double radius)
{
Circle c;
for (double i = 0; i < 2 * Math.PI; i += 0.05)
{
Point p = new Point(center + radius * Math.Cos(i) * v0 + radius * Math.Sin(i) * v1);
c.Add(p);
}
return c;
}
You only need to make circles using this function along the axis of the cylinder:
List<Circle> Cylinder = new List<Circle>();
for(double i=0;i<1;i+=0.1)
{
Cylinder.add( make_circle(P0+i*normal, v0, v1,radius);
}
Now you should take two consecutive circles and connect them with quads by sampling uniformly.
I have implemented it this way since I had circles implemented already.
A simpler way to implement is make the circle along the x axis and then rotate and translate it to p0 and make it align with normal or to use gluCylinder if you are the fan of Glu....
Hopefully it works for you.

Resources