I'm trying to animate a man running:
Frames 1 to 5 = man leaning into run.
Frames 6 to 15 = man running a single step
frame = 1
frame +=1 //frames progress forwards at rate of 1 frame
function run(){
if(frame>15){ //at frame 15: man has completed leaning into run and completed one 'running' cycle
frame -=2 //frames now start to go backwards at rate of (1-2=)-1 frame
if(frame<6){ //until they reach frame 6 (beginning of running animation)
frame +=2 //frames start to progress forwards again at rate of (2-2+1=)+1 frame again
My method is really bad and seems to be only capable of going forwards then backwards ONCE between 15 and 6.
Does anyone know how I can bounce between these two numbers indefinitely?
After reaching frame = 15 and beginning your trip downward, you hit a condition (14) where neither of your IF statements is true. So your frame neither increments nor decrements. Stuck.
A possible better solution would be to maintain a variable called myDirection which toggles periodically between 1 and -1. That is, set myDirection = -1 when you hit 15, and set myDirection = 1 when you hit 6. Then, your iterative statement could always say frame = frame + myDirection and it would always be doing something -- you'd never be stuck doing nothing.
Ok, so using LesterDove's + schnaader's useful tips I've managed:
int step=1
function run(){
frame += step
if(frame>15){ step = -1}
if(frame<6){ step = 1}
}
and it works great guys. Thanks again!
Related
I'm trying to write a program that puts my ESP32 into a deep sleep state, and uses touch input to wake it up. I'm able to put it into the deep sleep state, but as soon as it enters, it wakes up and never calls into the callback function.
Reading the raw data from the touch pad, it idles around 25k, and touch inputs from my hand give it a value of around 180k. The 100k value in the code snippet below is the threshold to where I'm comfortable to determine that a touch has been detected.
I'd like to point out that this is different from ext0 and ext1 wake ups.
static void touchsensor_interrupt_cb(void *arg)
{
... // code here turns on an LED and prints to serial
}
void setup(){
...
touch_pad_init();
touch_pad_config(TOUCH_PAD_NUM2);
touch_pad_sleep_set_threshold(TOUCH_PAD_NUM2, 100000);
touch_pad_isr_register(touchsensor_interrupt_cb, NULL, TOUCH_PAD_INTR_MASK_ACTIVE);
touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE);
touch_pad_sleep_channel_enable(TOUCH_PAD_NUM2, true);
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
touch_pad_fsm_start();
esp_sleep_enable_touchpad_wakeup();
Serial.println("entering deep sleep");
esp_deep_sleep_start();
}
I've triple-checked that my circuit is correct. Running on an ESP32S3 Dev Kit v1.0. If there's a better place to post this please let me know.
The issue ended up being this line:
touch_pad_sleep_set_threshold(TOUCH_PAD_NUM2, 100000);
The threshold here was relative to the raw sensor data. Instead, it should be relative to raw_data - benchmark, where (I'm assuming) the benchmark is computed from what it considers the sensor's baseline value. You can get your benchmark using touch_pad_sleep_channel_read_benchmark.
Printing out the expression above on raw, unfiltered data gives values like:
01:25:10.619 -> 3
01:25:10.696 -> -4
01:25:10.774 -> 3
01:25:10.851 -> -10
01:25:10.930 -> -4
01:25:11.006 -> 20
01:25:11.100 -> -2
01:25:11.177 -> 2
01:25:11.255 -> 1
01:25:11.333 -> 0
Where those values oscillate around 0 (the noise in my touch sensor). I changed the line above it to:
touch_pad_sleep_set_threshold(TOUCH_PAD_NUM2, benchmark * threshold);
Where threshold is 0.2, meaning I'll consider a "touch" when the ESP32 reads sensor values of 120% of the benchmark value. I hope this helps someone.
I have this simple game i made in Godot Game Engine, and i have implemented some animations in my game's main character.
1. Run
This is a simple run animation i've added, which is played when the character is moving
2. Idle
This animation is more like a single image which is played when the character is not moving
3. Attack
This animation is played when user presses Left Mouse Button.
I am having my issue in attack animation, when i press Left Mouse Button my Animation doesn't play, instead i get first frame of the animation and then character goes back to idle Animation.
This is how it looks like:
This is my Character's Code:
extends KinematicBody2D
var _inputVec = Vector2.ZERO
var VELOCITY = Vector2.ZERO
var LAST_INPUT = Vector2.ZERO
const MAX_SPEED = 70
const ACCELERATION = 500
const FRICTION = 500
onready var animationPlayer = $AnimationPlayer
func _ready():
print("game started!")
func _physics_process(delta):
_inputVec.x = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
_inputVec.y = Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up")
_inputVec = _inputVec.normalized()
if _inputVec != Vector2.ZERO:
if _inputVec.x > 0:
animationPlayer.play("playerRunRight")
elif _inputVec.y < 0:
animationPlayer.play("playerRunUp")
elif _inputVec.y > 0:
animationPlayer.play("playerRunDown")
else:
animationPlayer.play("playerRunLeft")
VELOCITY = VELOCITY.move_toward(_inputVec * MAX_SPEED, ACCELERATION * delta)
LAST_INPUT = _inputVec
else:
VELOCITY = VELOCITY.move_toward(Vector2.ZERO, FRICTION * delta)
if Input.is_action_just_pressed("ui_lmb"):
if LAST_INPUT.x > 0:
animationPlayer.play("playerAttackRight")
elif LAST_INPUT.y < 0:
animationPlayer.play("playerAttackUp")
elif LAST_INPUT.y > 0:
animationPlayer.play("playerAttackDown")
else:
animationPlayer.play("playerAttackLeft")
else:
if LAST_INPUT.x > 0:
animationPlayer.play("playerIdleRight")
elif LAST_INPUT.y < 0:
animationPlayer.play("playerIdleUp")
elif LAST_INPUT.y > 0:
animationPlayer.play("playerIdleDown")
else:
animationPlayer.play("playerIdleLeft")
VELOCITY = move_and_slide(VELOCITY)
Full Project is Available at my Github Repo
Remember that _physics_process runs once per (physics) frame.
So, one frame you pressed the left mouse button, and this line got to execute:
animationPlayer.play("playerAttackRight")
But next (physics) frame, you had not just pressed the left mouse button, so this conditional is false:
if Input.is_action_just_pressed("ui_lmb"):
And then this line get to execute:
animationPlayer.play("playerIdleRight")
As a result, you only see about one frame of the "playerAttackRight" animation.
You are going to need to keep track of the current state (running, attacking, idle). The rule is that you can change from running to idle immediately, but you can only change from attacking to idle, when the attack animation ends.
You can keep track of the current state with a variable, of course. You can take input and the value of the state of the variable to decide the new state. Then separately read the state variable and decide which animation to play. You may also want to set the state variable when some animations end.
And to do something when an animation ends, you can either resource to yield:
yield(animationPlayer, "animation_finished")
Which will have your code resume after it receives the "animation_finished" signal.
Or, otherwise you can connect to the "animation_finished" signal.
By the way, you can also queue animations:
animationPlayer.queue("name_of_some_animation")
While using AnimationPlayer like you do is OK. When it gets complex, there is another tool you should consider: AnimationTree.
Create an AnimationTree node, give it your animation player, and set the root to a new AnimationNodeStateMachine. There you can create your state machine, and configure if the transition between them is immediate or at the end.
Then, from code, you can get the state machine playback object, like this:
var state_machine = $AnimationTree.get("parameters/playback")
You can ask it what the current state is with:
var state:String = state_machine.get_current_node()
Which you can use as part of the decision of which state you want to go to. And then tell it you want it to go to a different state, like this:
state_machine.travel("name_of_some_state")
And using that it will respect the transitions you set, so you do not have to worry about it in code.
You can find more information about using AnimationTree at:
Using AnimationTree
Controlling Animation States
I want to simulate mouse movement, but not just one way. I need my mouse to go to the bottom left, then go to the bottom right, then finally go back to the bottom left again.
bottom left, 2 seconds
bottom right, 2 seconds
bottom left again, 2 seconds
But I can't make it work. What do I need to do? Is this possible?
If we can not do all three; we can do first 2. i.e. only bottom left 2 sec then bottom right 2 sec.
I have this in ahk but its only one way, always going to the left bottom. I need it in C++.
#NoEnv
SendMode Input
~F6::Suspend
~End::ExitApp
~F5::Reload
LCtrl & ~LButton::
Loop
If GetKeyState("LButton", "LCtrl") {
Sleep, 3
moveAmount := (moveAmount = 0.2) ? 3 : -1
mouseXY(moveAmount,2)
}
else
break
~LButton::
Loop
If GetKeyState("LButton") {
Sleep, 3
moveAmount := (moveAmount = 0.2) ? 3 : -1
mouseXY(moveAmount,2)
}
else
break
Return
mouseXY(x,y)
{
DllCall("mouse_event",int,1,int,x,int,y,uint,0,uint,0)
}
You should be using GetAsyncKeyState, not GetKeyState. GetKeyState returns the value captured when the last message was dispatched.
Also, check out SendInput on MSDN. mouse_event has long been deprecated.
And please, add tag 'winapi' to your question.
It is very critical to learn the start time of each frame of a video.
I need to determine the starting point manually ( for example 848 here) by using below matlab code:
v = VideoReader('video1.avi','CurrentTime',848);
while hasFrame(v)
video_frame = readFrame(v);
counter=counter+1;
if counter==1
imshow(video_frame)
imhist(video_frame(:,:,1))
end
end
What I want is to distinguish some video frame from the others by using histogram. At the end my aim is to reach the exact showing time of the distinguished frames.
After editting:
This is frame histogram outputs:
Histogram size of the some frames are different from the previous one, do you know the reason?
difference=[difference sum(abs(histcounts(video_frame)-histcounts(lastframe)))];
Because of the taking the difference of the I had remove the different histogram sized frames but it causes missing some frames.
i havent found an video example that looks like what you discribe. please condsider always to have an example.
This example code calculates the differences in the histcounts. please notice that waitforbuttonpressis in the loop so you have to click for each frame while testing or remove it when the video is too long. Does this works on your file?
v = VideoReader('sample.avi','CurrentTime',1);
figure1=figure('unit','normalized','Position',[0.2 0.2 0.4 0.6]);
axes1=subplot(3,1,1);
axes2=subplot(3,1,2);
axes3 = subplot(3,1,3);
counter=0;
difference=[];
video_frame=readFrame(v);
while hasFrame(v)
lastframe=video_frame;
video_frame = readFrame(v);
counter=counter+1;
imshow(video_frame,'Parent',axes1);
[a,b]=histcounts(video_frame(:,:,1));
plot(b(1:end-1),a,'Parent',axes2);
difference=[difference sum(abs(histcounts(video_frame,0:255)-histcounts(lastframe,0:255)))];
bar(1:counter,difference,'Parent',axes3);
waitforbuttonpress
end
[~,onedistinguished]=max(difference);
%defining a threshold like every value that is bigger 4000
multidistinguished=find(difference>4000);
disp(['majorly changed at: ' num2str(distinguished)]);
I am creating a movie by addoing image frames to my QTMovie, every frame is suppose to show up for about 0.2 seconds. But the closest I have got was 1 second per frame.
I tried etering amounts less than 1 into my QTTime but that way my movie length would be 0 seconds, the documentation doesn't describe what the parameters in QTMakeTime are.
Any idea how to achieve this?
QTTime frameDuration = QTMakeTime(1, 1);
for (//here goes my loop to read each frame)
{
[movie addImage:img forDuration:frameDuration withAttributes:dict];
}
the second parameterf is the number of frames per second
QTTime frameDuration = QTMakeTime(1, 7);
this means 7 frames per second which worked fine