I am trying to write a simple animation in XPCE/Prolog for a project, but it is not smooth enough; it appears flashing or flickering.
I run this on an ASUS N550jv laptop with Intel i7 (quad core, 2.4 Ghz+), so this shouldn't be a problem.
The moving object is always the same (just drawing it at different positions), double-buffering is explicitly enabled, I'm using 40 FPS.
What could be done to improve the smoothness?
Here is the code I'm using:
sm:- %run this
sm(600,4,40). %runs animation over 600 pixels, 4 seconds long, with 40 FPS
sm(Length,Duration,FPS):-
(object( #window),!,free(#window);true), %check is window exists; if it does, delete it
(object( #floor), !, free( #floor); true), %check is floor exists; if it does, delete it
(object( #box), !, free( #box); true), %%check if box exists; if it does, delete it
new( #window,picture('Window',size(900,300))), %create window
send( #window,open), %display window
send(#window,buffered_update,true), %make sure to use double-buffering
new( #floor,box(800,10)), %create floor
send( #floor,fill_pattern,colour(green)), %colour floor
send( #window,display,#floor,point(50,70)), %show floor
new( #box,box(50,50)), %creates box
send( #box,fill_pattern,colour(yellow)), %colours box yellow
Frames is Duration*FPS, %how many frames are to be drawn
Step is Length/Frames, %what's the distance between steps
Delay is 1/FPS, %what is the delay between steps
send( #window,display,#box,point(50,20)), %shows Object
send( #window,flush), %flushes window
ani(Step,Delay,Frames,point(50,20)), %actual animation
sleep(1), %wait 1 second, and then
free( #box), %delete box
free( #floor), %delete floor
free( #window). %delete window (and exit)
ani(_,_,0,_).
ani(Step,Delay,Frames,point(X,Y)):-
send( #box,x(X+Step)), %moves box to the right
send( #window,flush), %flushes
repeat,
sleep(Delay),
FramesLeft is Frames - 1,
NewX is X + Step,
ani(Step,Delay,FramesLeft,point(NewX,Y)).
You should use a timer, it avoids sleep :
sm:- %run this
sm(600,4,40). %runs animation over 600 pixels, 4 seconds long, with 40 FPS
sm(Length,Duration,FPS):-
(object( #window),!,free(#window);true), %check is window exists; if it does, delete it
(object( #floor), !, free( #floor); true), %check is floor exists; if it does, delete it
(object( #box), !, free( #box); true), %%check if box exists; if it does, delete it
(object( #my_timer), !, free( #my_timer); true), %%check if box exists; if it does, del
new( #window,picture('Window',size(900,300))), %create window
send( #window,open), %display window
send(#window,buffered_update,true), %make sure to use double-buffering
new( #floor,box(800,10)), %create floor
send( #floor,fill_pattern,colour(green)), %colour floor
send( #window,display,#floor,point(50,70)), %show floor
new( #box,box(50,50)), %creates box
send( #box,fill_pattern,colour(yellow)), %colours box yellow
Frames is Duration*FPS, %how many frames are to be drawn
Step is Length/Frames, %what's the distance between steps
Delay is 1/FPS, %what is the delay between steps
send( #window,display,#box,point(50,20)), %shows Object
send( #window,flush), %flushes window
ani(Step,Delay,Frames,point(50,20)).
ani(Step,Delay,Frames,point(X,Y)) :-
send( #box,x(X+Step)), %moves box to the right
send( #window,flush), %flushes
new(#my_timer, my_timer(Step, Delay, Frames, X)).
:- pce_begin_class(my_timer, object).
variable(mytimer, timer, both, "timer lançant l'animation fréquence 20 fois par seconde").
variable(step, number, both, "delta x").
variable(frames, number, both, "number of moves").
variable(posX, number, both, "xpos of the box").
% initialisation of the tmer
initialise(P, Step, Delay, Frames, PosX) :->
send(P, slot, step, Step),
send(P, slot, frames, Frames),
send(P, slot, posX, PosX),
send(P, mytimer, new(_, timer(Delay,message(P, my_message)))),
send(P?mytimer, start).
% must be called before destruction
% avoid any problem of non-freed resources
unlink(F) :->
send(F?mytimer, stop),
send(F, send_super, unlink).
my_message(P) :->
get(P, slot, frames, Frame),
( get(Frame, value, 0)
-> send(P?mytimer, stop),
free( #box), %delete box
free( #floor), %delete floor
free( #window), %delete window (and exit)
free(#my_timer)
; get(P, slot, step, Step),
get(P, slot, posX, PosX),
send( #box,x(PosX+Step)), %moves box to the right
send( #window,flush), %flushes
send(PosX, plus, Step),
send(Frame, minus, 1)).
:- pce_end_class.
Related
Given an input image and the homography matrix, I want to get an output image after the transformation.
This is the built-in function in ndimage:
im = np.array(Image.open('lena.jpg').convert('L'))
H = np.array([[1.4,0.05,-100],[0.05,1.5,-100],[0,0,1]])
im2 = ndimage.affine_transform(im, H[:2,:2], (H[0,2], H[1, 2]))
imshow(im)
imshow(im2)
For the original image I see this:
For im2 after ndimage transformation I see this:
Now I want to write a code only using python and numpy library to do this homography myself. This is the code I wrote:
left, up = 0, 0
right, down = im.shape[1], im.shape[0]
# define the homography operation
def get_point_coor(x, y, H):
input = np.array(([x], [y], [1]))
output = np.dot(H, input)
return int(output[0]), int(output[1])
# after transformation the image size might be different from the original one,
# we need to find the new size
height_max = max(get_point_coor(left, up, H)[0], get_point_coor(left, down, H)[0], get_point_coor(right, up, H)[0], get_point_coor(right, up, H)[0])
width_max = max(get_point_coor(left, up, H)[1], get_point_coor(left, down, H)[1], get_point_coor(right, up, H)[1], get_point_coor(right, up, H)[1])
height_min = min(get_point_coor(left, up, H)[0], get_point_coor(left, down, H)[0], get_point_coor(right, up, H)[0], get_point_coor(right, up, H)[0])
width_min = min(get_point_coor(left, up, H)[1], get_point_coor(left, down, H)[1], get_point_coor(right, up, H)[1], get_point_coor(right, up, H)[1])
# can ignore this 50 now. The new_height without 50 should be able to be the new boundary
# , but somehow it is not, so I add a random big number (50) for ploting.
new_height = abs(height_max) + abs(height_min)+50
new_width = abs(width_max) + abs(width_min)+50
new_image = np.zeros((new_height, new_width))
# start the main
for row in range(im.shape[0]):
for col in range(im.shape[1]):
new_row, new_col = get_point_coor(row, col, H)
new_col += abs(width_min)
new_row += abs(height_min)
new_image[new_row, new_col] = im[row][col]
imshow(new_image)
The result I get is this:
The direction, color, and size all look very different from the ndimage one. What is the correct way to implement this homography?
Sorry to say, but you are making a beginner's mistake: if you scan the source image and copy the pixels to the destination at transformed coordinates, you will get poor results: either the points will be too dense and colliding with each other, or too sparse and leave holes.
The right thing to do is to scan the destination and get the source coordinate using the inverse transformation.
As the source coordinates will not be integer in general, you can round them, or for better quality use bilinear or bicubic interpolation between the source pixels.
A second difficulty appears: as the destination domain is a general quadrilateral, you should only paint the inside pixels, and that takes a raster scan conversion of the outline. Alternatively, you can fill the bounding box of this quadrilateral and assign the background color when the source pixel is out of the bounds.
I am trying to label my bars in a 3D bar graph:
clf
yMax = 2;
xMax = 3;
z=floor(10*rand(yMax,xMax));
bar3(z)
xlabel('x-axis')
ylabel('y-axis')
x = reshape( repmat(1:xMax,yMax,1), [], 1 );
y = repmat( (1:yMax)', xMax,1 );
%htext = text( x, y, z(:), repmat( {'TEST'}, xMax*yMax, 1 ) )
htext = text( x, y, z(:), 'TEST' )
No matter how big I make the figure, the text gets chopped at the bottom:
Can anyone suggest a way to track down the cause, and/or suggest a solution?
I was fortunate to catch a few minutes with a guru. The explanation: The VerticalAlignment defaults to middle, which works fine for 2D plots. For each of the 3D bars above, however, middle means that the middle of the text sits right at the top surface of the box. Therefore, the bottom half of the text is inside the box. The problem is solved by modifying the text command:
htext = text( x, y, z(:), 'TEST' , 'VerticalAlignment','Bottom' )
Weird how I couldn't find it in a web search, but hopefully, this answer will fix that.
I've made an Object called Player and an Object called Zombie, I would like to add a shooting function for Player, and the bullet to go from point Player to the point where I am holding my mouse, how can this be achived?
Let's eliminate the other directions first and just imagine that the direction is from left to right.
You first need to get the mouse's position which is possible by using
SDL_GetMouseState(int* placeX, int* placeY)
this pushes the mouses's x location to placeX and the mouses's y location to placeY.
Now you also need to get the position of the player, this could be done by getting the player's texture's rect while in the loop.
So if the character is at
(x,y) (0, 10)
with a
(w, h) (20, 40)
and you have the bullet source right at the middle-right of the character, then that makes it at
(20, 20)
then the actual current bullet source is at
(x, y) -> (20, 30) (basically rect.x + bulletsource.x and rect.y +
bulletsource.y).
Now all you have to do is something like
if(bullet.x < placeX)//this makes it look like the bullet is moving to the right
{
bullet.x++ //this moves the bullet closer to the right
Redraw bullet //you have to redraw to see the changes
}
do the same thing for y, it doesn't really have to be an if statement.
The same logic applies when you have multiple bullet directions.
You just have to think of the bullet's source as the center of the x and y axis and check if the mouseclick is within a certain quadrant (diagonal) or near the line of an axis(straight bullet).
Once you know what quadrant or line the mouse is at, then you just change the texture to be used(diagonal bullet facing north-east or just a plain ol' simple bullet facing the north).
Thanks, for the help, but I solved it by using atan2, and calculated the angle. When I had the angle I just added the value of speed * cos(angle) to the x variable and speed * sin(angle) to the y variable.
Supose I have a grid like this one(I don't know the size of the grid)
(-1,1) (0,1) (1,1)
(-1,0) (0,0) (1,0)
(-1,-1) (0,-1) (1,-1)
In this grid are N boxes. I want to write some predicates in order to move the robot in every cell of the grid and check if there is a box or not. It is important not to miss a cell because I don't know where the boxes are.
First of all I have this predicate
init([N,0,0])
N - number of boxex to discover
0,0 - my initial position
The predicates that handle the moves of the robot have got this structure
perform(+ProgramData, +ContainsBox, -Action, -ProgramDataUpdated)
perform([N,X,Y], false, move(west), [N,NX,Y]):- NX is X - 1, !
perform([N,X,Y],false, move(east), [N,NX,Y]):- NX is X + 1, !
perform([N,X,Y], false, move(north), [N,X,NY]):- NY is Y + 1, !
perform([N,X,Y], false, move(south), [N,X,NY]):- NY is Y - 1, !
If a box is in a cell I have this predicate:
discovered([N,X,Y],true,discovered,[NN,X,Y]):-NN is N-1,!.
If I have discovered N boxes my program ends and I have this predicate:
done([0,_,_],_,done,[0,_,_]).
I don't know how to make sure that I don't miss any cell of the grid
i found a example from %AHMADREZA ESHGHINEJAD () of a bouncing ball on a sinusoidal surface and tried to modify it to fit my model.
but matlab shows an error while calling the "graphicfunction" without any further information. i've been trying to figure out for hours trying to fix it, but it still does not work.
i would really appreciate your help.
main
%This set of files including (Rmain.m, RCalc.m, RGraficfunction.m and Rod.mdl) are written by:
%AHMADREZA ESHGHINEJAD (ahmadreza.eshghinejad#gmail.com), April 2011
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% to simulate and animation of a rod falling on a flat surface.
%
%clear
%clc
%global dblcart1 pa dt amp freq I m floormin floorwidth s R
spacing_width=0.001; %[m]
spacing_amplitude=0.008; %[m]
%disc diameter
d=0.01; %[m]
r=d/2; %Radius
x0=0; %% initial x
y0=spacing_amplitude; %% initial y
Bth0=0; %% initial angular position
pa=.001; %% pause in simulation step
T=30; %% simulation time
m=1; %% ball mass
dt=.01; % time steps
s=0; % Movement of frame counter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
animinit('disc on surface');
dblcart1 = findobj('Type','figure','Name','dblcart1 Animation');
hold on;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Initializing
% Initial Ball points
th=0:.1:2*pi;
xx=r*cos(th)+x0;
yy=r*sin(th)+y0;
% Initial Ball line points
x1l1=1*r*cos(Bth0)+x0;
x1l2=1*r*cos(Bth0+pi)+x0;
y1l1=1*r*sin(Bth0)+y0;
y1l2=1*r*sin(Bth0+pi)+y0;
x2l1=1*r*cos(Bth0+pi/2)+x0;
x2l2=1*r*cos(Bth0+pi+pi/2)+x0;
y2l1=1*r*sin(Bth0+pi/2)+y0;
y2l2=1*r*sin(Bth0+pi+pi/2)+y0;
% Drawing the floor
floormin=0;
floorwidth=3*2*pi*spacing_width;
floorheight=floorwidth;
axis([floormin floormin+floorwidth 0 floorheight]);
plot(floormin:.1:floormin+floorwidth,spacing_amplitude*sin((1/spacing_width)* (floormin:.1:floormin+floorwidth))+spacing_amplitude,'yellow','LineWidth',2);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Initial drawing of ball
Ballhndl1=plot([x1l1 x1l2],[y1l1 y1l2],'red');
Ballhndl2=plot([x2l1 x2l2],[y2l1 y2l2],'red');
Ballhndl=plot(xx,yy,'blue','EraseMode','background');
set(gca,'UserData',[Ballhndl;Ballhndl1;Ballhndl2]);
%set(gca,'UserData',Ballhndl);
sim('simmod.mdl')
matlab function inside the simulink model
function [x,y,Bth] = fcn(ures,yres)
r=0.01; %% Ball radius
spacing_width=0.001; %[m]
spacing_amplitude=0.008; %[m]
for th=2*pi:-.01:0
x=ures+r*cos(th); %% bal points
y=yres+r*sin(th);
end;
Bth=atan(2*pi*(1/spacing_width)*spacing_amplitude*cos(2*pi*(1/spacing_width)*x));
graphic function
function GraficFunction(x,y,Bth)
global Ball
spacing_width=0.001; %[m]
pa=.01; %% pause in simulation step
s=0; % Movement of frame counter
floormin=0;
floorwidth=3*2*pi*spacing_width;
pause(pa)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% passing the window margins and moving the object based on the "s"
%%%%% parameter
if x<(floormin+s*floorwidth),s=s-1;
elseif x>((s+1)*floorwidth),s=s+1;end
x=x-s*floorwidth;
set(0,'currentfigure',Ball)
Ballhndl=get(gca,'UserData');
%Ball Circle points
th=0:.1:2*pi;
x1=ures+r*cos(th);
y1=yres+r*sin(th);
%%%%%%%%%%%%%% Ball line points
x1l1=1*r*cos(Bth)+x;
x1l2=1*r*cos(Bth+pi)+x;
y1l1=1*r*sin(Bth)+y;
y1l2=1*r*sin(Bth+pi)+y;
x2l1=1*r*cos(Bth+pi/2)+x;
x2l2=1*r*cos(Bth+pi+pi/2)+x;
y211=1*r*sin(Bth+pi/2)+y;
y2l2=1*r*sin(Bth+pi+pi/2)+y;
% Draw Lines
set(Ballhndl(1),'XData',x1);
set(Ballhndl(1),'YData',y1);
set(Ballhndl,'XData',x1);
set(Ballhndl,'YData',y1);
set(Ballhndl(2),'XData',[x1l1 x1l2]);
set(Ballhndl(2),'YData',[y1l1 y1l2]);
set(Ballhndl(3),'XData',[x2l1 x2l2]);
set(Ballhndl(3),'YData',[y2l1 y2l2]);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
drawnow;
end