Im making a tower defense game in roblox and im wondering how to script towers having special effects when they hit a zombie, for example, freeze, slowness, poison etc. And how to make specific zombies immune to some of these effects.
What you could do is put a script in the zombie that can interpret what tower hit it and decide if it should deal damage or effects or something like that.
i would just have some numvalues inside the zombie and when u hit it change the value up 1 point and have another script in the value which will activate the effect and once the effect has been activated it removes 1 from the value.
u can change this around to fit the different effects so for a bleed effect you can name the value bleed and in the damage script when you hit a enemy it will findfirstchild for bleed and add 1 to the value and have another script within the value doing the bleed damage which would be something like
local bleedvalue = script.parent.value
local enemytype = script.parent.parent:waitforchild("humanoid")
while wait(tick speed) do
if script.parent.value < 0 then
bleedvalue = bleedvalue - (ammount you want removed per tick)
enemytype.health = enemytype.health - (damage ammount and health can be changed out for speed or can straight up just anchor the zombie for a freeze)
end
end
this was just off the top of my head so sorry if its wrong but i hope i helped anyone who may be seeking a alternative
Goal
I am trying to create a fast ticking sound in a Cordova app using Createjs.
The ticking sound speed changes based on user settings. At the moment the timing is erratic
Setup
I have an mp3 audio file of a single tick sound that is 50ms long.
A target speed of repetition could be as fast as 10 times per second.
Question
How can I get the sound to play evenly and consistently at that speed?
More Technical Detail
createjs.Ticker.timingMode = createjs.Ticker.RAF_SYNCHED;
createjs.Ticker.framerate = 30;
Cheers for any help
This should be pretty straightforward. I set up a quick fiddle to play a sound a specific amount of times per second. It seems pretty reliable, even when playing at 60fps.
https://jsfiddle.net/lannymcnie/ghjejvq9/
The approach is to just check every Ticker.tick if the amount of time has passed since the last tick sound. The duration is derived by 1000/ticksPerSecond.
// Every tick
var d = new Date().getTime();
if (d > lastTick + 1000/ticksPerSecond) {
createjs.Sound.play("tick");
lastTick = d;
}
I'm working on a 2D video game framework, and I've never written a game loop before. Most frameworks I've ever looked in to seem to implement both a draw and update methods.
For my project I implemented a loop that calls these 2 methods. I noticed with other frameworks, these methods don't always get called alternating. Some frameworks will have update run way more than draw does. Also, most of these types of frameworks will run at 60FPS. I figure I'll need some sort of sleep in here.
My question is, what is the best method for implementing this type of loop? Do I call draw then update, or vice versa? In my case, I'm writing a wrapper around SDL2, so maybe that library requires something to be setup in a certain way?
Here's some "pseudo" code I'm thinking of for the implementation.
loop do
clear_screen
draw
update
sleep(16.milliseconds)
break if window_is_closed
end
Though my project is being written in Crystal-Lang, I'm more looking for a general concept that could be applied to any language.
It depends what you want to achieve. Some games prefer the game logic to run more frequently than the frame rate (I believe Source games do this), for some games you may want the game logic to run less frequently (the only example of this I can think of is the servers of some multiplayer games, quite famously Overwatch).
It's important to consider as well that this is a question of resolution, not speed. A game with logic rate 120 and frame rate 60 is not necessarily running at x2 speed, any time critical operations within the game logic should be done relative to the clock*, not the tic rate, or your game will literally go into slow motion if the frames take too long to render.
I would recommend writing a loop like this:
loop do
time_until_update = (update_interval + time_of_last_update) - current_time
time_until_draw = (draw_interval + time_of_last_draw) - current_time
work_done = false
# Update the game if it's been enough time
if time_until_update <= 0
update
time_of_last_update = current_time
work_done = true
end
# Draw the screen if it's been enough time
if time_until_draw <= 0
clear_screen
draw
time_of_last_draw = current_time
work_done = true
end
# Nothing to do, sleep for the smallest period
if work_done == false
smaller = time_until_update
if time_until_draw < smaller
smaller = time_until_draw
end
sleep_for(smaller)
end
# Leave, maybe
break if window_is_closed
end
You don't want to wait for 16ms every frame otherwise you might end up over-waiting if the frame takes a non-trivial amount of time to complete. The work_done variable is so that we know whether or not the intervals we calculated at the start of the loop are still valid, we may have done 5ms of work, which would throw our sleeping completely off so in that scenario we go back around and calculate fresh values.
* You may want to abstractify the clock, using the clock directly can have some weird effects, for example if you save the game and you save the last time you used a magical power as a clock time, it will instantly come off cooldown when you load the save, as that is now minutes, hours or even days in the past. Similar issues exist with the process being suspended by the operating system.
I have a video that is about 12 seconds long. Seconds 5-10 are loopable.
I want to play the video from the start the first time, then continue to loop over seconds 5-10 afterwards indefinitely.
However when I try, the video just jumps back to the beginning again.
Am I doing something wrong here? The video is H.264 mp4 format.
Here's a snippet of code I use: (the update function gets called every frame)
-(void) update:(double)timeDelta
{
if ( !m_player ) {
return;
}
CMTime time = m_player.m_player.currentTime;
if ( CMTimeGetSeconds(time) > 10.0f ) {
[m_player seekToTime:CMTimeMakeWithSeconds(5.0f, time.timescale)];
}
}
Any help would be much appreciated.
Thanks,
Rich
Most players will only seek to I pictures (Intra pictures). It may be that your clip only has a I picture in the begining and another one after 5 seconds. Check that. If you can re-encode, then re-encode with I pictures inserted every 1 second to allow you to do this.
It's probably seeking to a keyframe, if the keyframe interval on that particular video is greater than 5 seconds.
Try either adjusting the way the video is encoded such that you are able to get a keyframe at the 5 second mark or use
[m_player seekToTime:CMTimeMakeWithSeconds(5.0f, time.timescale) toleranceBefore: kCMTimeZero toleranceAfter: kCMTimeZero];
Note that if you do this, the decoder will have to decode those 5 seconds of video before resuming playback at the point you want, so you may end up with a brief delay in your loop.
Do you have a simple debounce routine handy to deal with a single switch input?
This is a simple bare metal system without any OS.
I would like to avoid a looping construct with a specific count, as the processor speed might fluctuate.
I think you could learn a lot about this here: http://www.ganssle.com/debouncing.pdf
Your best bet is always to do this in hardware if possible, but there are some thoughts on software in there as well.
Simple example code from TFA:
#define CHECK_MSEC 5 // Read hardware every 5 msec
#define PRESS_MSEC 10 // Stable time before registering pressed
#define RELEASE_MSEC 100 // Stable time before registering released
// This function reads the key state from the hardware.
extern bool_t RawKeyPressed();
// This holds the debounced state of the key.
bool_t DebouncedKeyPress = false;
// Service routine called every CHECK_MSEC to
// debounce both edges
void DebounceSwitch1(bool_t *Key_changed, bool_t *Key_pressed)
{
static uint8_t Count = RELEASE_MSEC / CHECK_MSEC;
bool_t RawState;
*Key_changed = false;
*Key_pressed = DebouncedKeyPress;
RawState = RawKeyPressed();
if (RawState == DebouncedKeyPress) {
// Set the timer which allows a change from current state.
if (DebouncedKeyPress) Count = RELEASE_MSEC / CHECK_MSEC;
else Count = PRESS_MSEC / CHECK_MSEC;
} else {
// Key has changed - wait for new state to become stable.
if (--Count == 0) {
// Timer expired - accept the change.
DebouncedKeyPress = RawState;
*Key_changed=true;
*Key_pressed=DebouncedKeyPress;
// And reset the timer.
if (DebouncedKeyPress) Count = RELEASE_MSEC / CHECK_MSEC;
else Count = PRESS_MSEC / CHECK_MSEC;
}
}
}
Simplest solutions are often the best, and I've found that simply only reading the switch state every N millseconds (between 10 and 50, depending on switches) has always worked for me.
I've stripped out broken and complex debounce routines and replaced them with a simple slow poll, and the results have always been good enough that way.
To implement it, you'll need a simple periodic timer interrupt on your system (assuming no RTOS support), but if you're used to programming it at the bare metal, that shouldn't be difficult to arrange.
Note that this simple approach adds a delay to detection of the change in state. If a switch takes T ms to reach a new steady state, and it's polled every X ms, then the worst case delay for detecting the press is T+X ms. Your polling interval X must be larger than the worst-case bounce time T.
There's no single simple solution that works for all types of buttons. No matter what someone here tells you to use, you'll have to try it with your hardware, and see how well it works. And look at the signals on a scope, to make sure you really know what's going on. Rich B's link to the pdf looks like a good place to start.
I have used a majority vote method to debounce an input. I set up a simple three state shift register type of data structure, and shift each sample and take the best two out of three as the "correct" value. This is obviously a function of either your interrupt handler, or a poller, depending on what method is used to actually read the hardware.
But, the best advice is to ask your friendly hardware designer to "latch" the value and allow you to clear this value when you get to it.
To debounce, you want to ignore any switch up that lasts under a certain threshold. You can set a hardware timer on switch up, or use a flag set via periodic interrupt.
If you can get away with it, the best solution in hardware is to have the switch have two distinct states with no state between. That is, use a SPDT switch, with each pole feeding either the R or S lines of a flip/flop. Wired that way, the output of the flip/flop should be debounced.
The algorithm from ganssle.com could have a bug in it. I have the impression the following line
static uint8_t Count = RELEASE_MSEC / CHECK_MSEC;
should read
static uint8_t Count = PRESS_MSEC / CHECK_MSEC;
in order to debounce correctly the initial press.
At the hardware level the basic debouncing routine has to take into account the following segments of a physical key's (or switch's) behavior:
Key sitting quietly->finger touches key and begins pushing down->key reaches bottom of travel and finger holds it there->finger begins releasing key and spring pushes key back up->finger releases key and key vibrates a bit until it quiesces
All of these stages involve 2 pieces of metal scraping and rubbing and bumping against each other, jiggling the voltage up and down from 0 to maximum over periods of milliseconds, so there is electrical noise every step of the way:
(1) Noise while the key is not being touched, caused by environmental issues like humidity, vibration, temperature changes, etc. causing voltage changes in the key contacts
(2) Noise caused as the key is being pressed down
(3) Noise as the key is being held down
(4) Noise as the key is being released
(5) Noise as the key vibrates after being released
Here's the algorithm by which we basically guess that the key is being pressed by a person:
read the state of the key, which can be "might be pressed", "definitely is pressed", "definitely is not pressed", "might not be pressed" (we're never really sure)
loop while key "might be" pressed (if dealing with hardware, this is a voltage sample greater than some threshold value), until is is "definitely not" pressed (lower than the threshold voltage)
(this is initialization, waiting for noise to quiesce, definition of "might be" and "definitely not" is dependent on specific application)
loop while key is "definitely not" pressed, until key "might be" pressed
when key "might be" pressed, begin looping and sampling the state of the key, and keep track of how long the key "might be" pressed
- if the key goes back to "might not be" or "definitely is not" pressed state before a certain amount of time, restart the procedure
- at a certain time (number of milliseconds) that you have chosen (usually through experimenting with different values) you decide that the sample value is no longer caused by noise, but is very likely caused by the key actually being held down by a human finger and you return the value "pressed"
while(keyvalue = maybepressed){
//loop - wait for transition to notpressed
sample keyvalue here;
maybe require it to be "notpressed" a number of times before you assume
it's really notpressed;
}
while(keyvalue = notpressed){
//loop - wait for transition to maybepressed
sample keyvalue
again, maybe require a "maybepressed" value a number of times before you
transition
}
while(keyvalue=maybepressed){
presstime+=1;
if presstime>required_presstime return pressed_affirmative
}
}
return pressed_negative
What I usually do is have three or so variables the width of the input register. Every poll, usually from an interrupt, shift the values up one to make way for the new sample. Then I have a debounced variable formed by setting the logical-and of the samples, and clearing the inverse logical-or. i.e. (untested, from memory)
input3 = input2;
input2 = input1;
input1 = (*PORTA);
debounced |= input1 & input2 & input3;
debounced &= (input1 | input2 | input3);
Here's an example:
debounced has xxxx (where 'x' is "whatever")
input1 = 0110,
input2 = 1100,
input3 = 0100
With the information above,
We need to switch only bit 2 to 1, and bit 0 to 0. The rest are still "bouncing".
debounced |= (0100); //set only bit 2
debounced &= (1110); //clear only bit 0
The result is that now debounced = x1x0
use integration and you'll be a happy camper. Works well for all switches.
just increment a counter when read as high and decrement it when read as low and when the integrator reaches a limit (upper or lower) call the state (high or low).
The whole concept is described well by Jack Ganssle. His solution posted as an answer to the original question is very good, but I find part of it not so clear how does it work.
There are three main ways how to deal with switch bouncing:
- using polling
- using interrupts
- combination of interrupts and pooling.
As I deal mostly with embedded systems that are low-power or tend to be low-power so the answer from Keith to integrate is very reasonable to me.
If you work with SPST push button type switch with one mechanically stable position then I would prefer the solution which works using a combination of interrupt and pooling.
Like this: use GPIO input interrupt to detect first edge (falling or rising, the opposite direction of un-actuated switch state). Under GPIO input ISR set flag about detection.
Use another interrupt for measuring time (ie. general purpose timer or SysTick) to count milliseconds.
On every SysTick increment (1 ms):
IF buttonFlag is true then call function to poll the state of push button (polling).
Do this for N consecutive SysTick increments then clear the flag.
When you poll the button state use logic as you wish to decide button state like M consecutive readings same, average more than Z, count if the state, last X readings the same, etc.
I think this approach should benefit from responsiveness on interrupt and lower power usage as there will be no button polling after N SysTick increments. There are no complicated interrupt modifications between various interrupts so the program code should be fairly simple and readable.
Take into consideration things like: do you need to "release" button, do you need to detect long press and do you need action on button release. I don't like button action on button release, but some solutions work that way.