Im trying to finetune the controls of a javascript game (p5 library).
keyIsDown() is the type of control/feel im looking for but it's timing is too fast.
By timing is too fast, I mean when I hold down the key, the key repeats too fast. Im trying to control the timing speed of the key repeat when holding down the key.
I tried to make my own vertion with keytyped() and setInterval to time my move function. Then stopping it with keyReleased(). But it jams up.
I have also tried setTimeout but could not get it to work on keyboard input like this.
var controlInterval;
function keyReleased() {
if (key === 'a') {
clearInterval(controlInterval);
} else if (key === 'd') {
clearInterval(controlInterval);
}
//return false; // prevent any default behavior
}
function keyTyped() {
if (key === 'a') {
controlInterval = setInterval(left, 50);
} else if (key === 'd') {
controlInterval = setInterval(right, 50);
}
}
function left(){
var x = -1;
move(x);
}
function right(){
var x = 1;
move(x);
}
code I prefer to use:
if (keyIsDown(LEFT_ARROW)){
var west = -1;
move(west);
}
if (keyIsDown(RIGHT_ARROW)){
var east = 1;
move(east);
Take a look at debouncing and throttling principles which I think is what you are looking for here - limit the execution count of event.
The best explanation IMHO related to this subject is this article.
There are already libraries to help you like lodash. Go to their documentation page and search the functions - debounce or throttle and it there will be examples how to use them.
someDiv.addEventListener('keyup', _.debounce(handleKeyUp, 300));
function handleKeyUp(event) {
if (event.keyCode === 65 /* A */) left();
...
}
Arrow keys can be used to signal a direction, frame rate can be used to control speed and a delta variable used to control the amount of movement.
var xPos = 0;
var xDelta = 1;
function setup(){
createCanvas(200,200);
frameRate(10); // 10 frames per second, increase to move faster
}
function draw(){
background(100);
if (keyIsDown(LEFT_ARROW)){
var west = -1;
move(west);
}
if (keyIsDown(RIGHT_ARROW)){
var east = 1;
move(east);
}
rect(xPos, 100, 10,10);
}
function move(dir){
if (dir == -1){
xPos = xPos - xDelta;
}
else {
xPos = xPos + xDelta;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.min.js"></script>
Related
I have a script for a gambling site.
What I need is that after 2 calls to the function multiply, it bets the maximum stake possible and after that calls the function reset, I mean in each two sequential loss it bets the full balance in my account reset for the minimum stake and continue playing, Because I realized that in odds of 1.1 on 'manual bet' in each 2 loss the next will be a won.
It is like: after 2 multiplyCalls bet the full balance (it is the "MAX" button in the image below) and reset the game to continue playing. Am I being clear enough?
I tried to create a function for this but did not work
The "Maximum stake" button element code is:
MAX
this is the printscreen
The part of the script I want to modify is this, the multiplyCalls function is already created. I changed the var multiply = (current * 2).toFixed(8); to var multiply = (current * 1).toFixed(8); because my strategy does not have martingale.
function multiply(){
if(multiplyCalls < 2){ // test multiply
var current = $('#double_your_btc_stake').val();
var multiply = (current * 2).toFixed(8);
$('#double_your_btc_stake').val(multiply);
multiplyCalls++; // increment
}else{
reset();
console.log('=== RESETING ===');
}
}
This is the full script:
var startValue = '0.00000001', // Don't lower the decimal point more than 4x of current balance
stopPercentage = 0.001, // In %. I wouldn't recommend going past 0.08
maxWait = 500, // In milliseconds
stopped = false,
stopBefore = 3; // In minutes
multiplyCalls = 0; // <--- Added this global
var $loButton = $('#double_your_btc_bet_lo_button'),
$hiButton = $('#double_your_btc_bet_hi_button');
function multiply(){
if(multiplyCalls < 2){ // test multiply
var current = $('#double_your_btc_stake').val();
var multiply = (current * 1).toFixed(8);
$('#double_your_btc_stake').val(multiply);
multiplyCalls++; // increment
}else{
reset();
console.log('=== RESETING ===');
}
}
function getRandomWait(){
var wait = Math.floor(Math.random() * maxWait ) + 100;
console.log('Waiting for ' + wait + 'ms before next bet.');
return wait ;
}
function startGame(){
console.log('Game started!');
reset();
$loButton.trigger('click');
}
function stopGame(){
console.log('Game will stop soon! Let me finish.');
stopped = true;
}
function reset(){
$('#double_your_btc_stake').val(startValue);
}
// quick and dirty hack if you have very little bitcoins like 0.0000001
function deexponentize(number){
return number * 1000000;
}
function iHaveEnoughMoni(){
var balance = deexponentize(parseFloat($('#balance').text()));
var current = deexponentize($('#double_your_btc_stake').val());
return ((balance*2)/100) * (current*2) > stopPercentage/100;
}
function stopBeforeRedirect(){
var minutes = parseInt($('title').text());
if( minutes < stopBefore )
{
console.log('Approaching redirect! Stop the game so we don\'t get redirected while loosing.');
stopGame();
return true;
}
return false;
}
// Unbind old shit
$('#double_your_btc_bet_lose').unbind();
$('#double_your_btc_bet_win').unbind();
// Loser
$('#double_your_btc_bet_lose').bind("DOMSubtreeModified",function(event){
if( $(event.currentTarget).is(':contains("lose")') )
{
console.log('You LOST! Multiplying your bet and betting again.');
multiply();
setTimeout(function(){
$loButton.trigger('click');
}, getRandomWait());
//$loButton.trigger('click');
}
});
// Winner
$('#double_your_btc_bet_win').bind("DOMSubtreeModified",function(event){
if( $(event.currentTarget).is(':contains("win")') )
{
if( stopBeforeRedirect() )
{
return;
}
if( iHaveEnoughMoni() )
{
console.log('You WON! But don\'t be greedy. Restarting!');
reset();
if( stopped )
{
stopped = false;
return false;
}
}
else
{
console.log('You WON! Betting again');
}
setTimeout(function(){
$loButton.trigger('click');
}, getRandomWait());
multiplyCalls = 0; // reset value
}
});startGame
So basically, you want to max the bet after two losses. Because multiply calls only occur after a loss, we can assume that the if(multiplyCalls < 2) bit takes care of that. So in the following else, all you really need to do is hit max bet instead of call reset(). Based on what I understand the code to be doing, this should be sufficient, correct?
function multiply(){
if(multiplyCalls < 2){ // test multiply
var current = $('#double_your_btc_stake').val();
var multiply = (current * 1).toFixed(8);
$('#double_your_btc_stake').val(multiply);
multiplyCalls++; // increment
}else{
//reset(); /* instead of resetting here, let's max the bet. */
$('#double_your_btc_max').trigger('click');
console.log('=== RESETING ===');
}
}
My code is:
function slide(x)
{
if (x==undefined)
var x = 1;
if (x >= 4096)
return;
document.getElementById("slide").style.backgroundPosition = x + "px 0px";
x++;
setTimeout(function() {
slide(x);
}, 1);
}
JSFIDDLE
It makes a spin (?) by changing backgroundPosition, and it works. But it's too slow, I'd want to make it faster, and then gradually slow down. How can I do that?
You should pick a higher delay than 1ms. In most browsers 10 to 50 ms would be a lot more reliable. To speed up your animation though, increase x increments. For example:
function slide(x)
{
if(x==undefined) var x = 1;
if(x >= 4096) return;
document.getElementById("slide").style.backgroundPosition = x+"px 0px";
x += 10; // or some other value
setTimeout(function() {
slide(x);
}, 50); // or some other value
}
Also, you probably want to check x like this:
if (typeof x === 'undefined') { x = 1; }, no need for var.
2018 UPDATE:
Check out the https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame API. Using this over a fixed update interval is usually preferable.
I have rewrite all the function:
function slide() {
var x = 1;
var y = 30;
var clr = setInterval(function(){
if(x >= 4096) x = 1;
document.getElementById("slide").style.backgroundPosition = x+"px 0px";
x+=y;
y-=0.1;
if (y<=0) { clearInterval(clr); }
},10);
}
https://jsfiddle.net/tatrwkmh/4/
Currently the position is being changed by 1 pixel every time slide is called, via the line x++;. You can make it faster by changing this from x++ to x += 2 or x += 3 etc.
Your animation may look clunky without some sort of easing function, though. You should look into using some sort of animation library instead.
I got it nicely starting fast and then going slower by adding to your code the following:
if(x < 1000)
x+=2
else if(x < 1500)
x+=1.5
else
x++;
THis is my code gist.
Leap.loop({enableGestures: true}, function(frame) {
var gestures = frame.gestures;
for (var i = 0; i < gestures.length; i++) {
// I want to do something when draw circle with one pointable
if (gesture.type == "circle" && gesture.state == "stop" && gesture.pointableIds.length == 1) {
var isClockWise = ? ;// how to know the direction of circle ?
}
}
} );
How to know circle is clockwise or counter clock wise with gesture object ?
I was using leap motion only 2 days and really need your help.
Leap.loop({enableGestures: true},function(frame) {
var gestures = frame.gestures,
circle,
pointable,
direction,
normal;
// Check if is there any gesture going on
if(gestures.length > 0) {
// In this example we will focus only on the first gesture, for the sake of simplicity
if(gestures[0].type == 'circle') {
circle = gestures[0];
// Get Pointable object
circle.pointable = frame.pointable(circle.pointableIds[0]);
// Reset circle gesture variables as nedded, not really necessary in this case
if(circle.state == 'start') {
clockwise = true;
} else if (circle.state == 'update') {
direction = circle.pointable.direction;
// Check if pointable exists
if(direction) {
normal = circle.normal;
// Check if product of vectors is going forwards or backwards
// Since Leap uses a right hand rule system
// forward is into the screen, while backwards is out of it
clockwise = Leap.vec3.dot(direction, normal) > 0;
if(clockwise) {
//Do clockwose stuff
} else {
//Do counterclockwise stuff
}
}
}
}
}
});
Looking on the C++ sample given on the leap website, piece of code is given to detect is the circle is clockwise.
C++ code :
if (circle.pointable().direction().angleTo(circle.normal()) <= PI/4)
{
clockwiseness = "clockwise";
}
else
{
clockwiseness = "counterclockwise";
}
I haven't used the Javascript API, but I think this can be something equivalent
This code hasn't been tested, but in Javascript it may be something like :
// considere your gesture is a circle, and there is at least one pointable object.
if (gesture.type == "circle" && gesture.state == "stop" && gesture.pointableIds.length >= 1)
{
var dir = frame.pointables[gesture.pointableIds[0] ].direction; // get direction of the Pointable used for the circle gesture
var angle = dir.AngleTo (circle.normal);
var isClockWise = angle <= (3.14 / 4);
}
Got all infos from Leap JS API from GitHub and Leap Motion Developers site
-> Be careful frame.pointables return pointables objects given in arbitrary order.(Cf JS API doc). This piece of code is just for the explanation of the algorithm
This is the easiest way to find out
var isClockwise = (circleGesture.normal[2] <= 0);
It will return true or false
Tried other answers on this page and couldn't get it to work, simplified the code a bit and finally got it working. The pointableID logs normal as negative/positive based on direction of the circle gesture.
function pageScrollDown() {
window.scrollBy(0,10);
};
function pageScrollUp(){
window.scrollBy(0,-15);
};
$(window).bind('circle', function(e, gesture){
var circle = gesture;
circle.pointable = circle.pointableIds[0];
direction = gesture.normal[1];
if(direction < 0 ) {
pageScrollDown();
} else {
pageScrollUp();
}
});
I have been using the "Leap Cursor library" for my project and it is really cool. Identifying a circle gesture on a element is very simple with this library.
var circleTrackElements = document.querySelectorAll(".myDOMElements");
for (var i = 0; i < allTiles.length; i++) {
circleTrackElements[i].addEventListener("leap-circle-stop", function(e) {
console.log("CIRCLE DETECTED");
});
};
LeapManager.init({
maxCursors : 1,
interactiveSelector : ".myDOMElements"
});
GITHUB link for the library
I am trying to make a simple game in HTML5 Canvas. I want, at most, two keyboard input per second.
This is my code so far:
function move( x, y, r ) {
var canid=document.getElementById("draw");
canid.addEventListener('keydown',readkey,false);
function readkey(e) {
if(e.keyCode == 37) {
clearField();
x = x-draw.width / 10;
redrawpic(x,y,r);
}
else if(e.keyCode == 38){
clearField();
y = y-draw.height / 10;
redrawpic( x, y, r );
}
//..........etc
}
}
The function move is used to move picture from one cell to another. How to set delay a between two moves?
You can use a timestamp to check when the last event has occured:
function move(x,y,r){
/* your variable declarations*/
var d1 = Date.now();
var d2;
function readkey(e){
d2 = Date.now();
// difference between timestamps needs to be 500ms
if(d2-d1 > 500){
// set old Timestamp to new one
d1 = d2;
/*
Rest of your code
*/
}
This allows one key event every 500ms. Not exactly the same like 2 events in 1 second (which could occure in 50ms and then pause 950ms), but maybe close enough?
Timeout/Interval is possible too, but I personally dislike the overhead of consecutive (possibly unnecessary) timeout calls.
var throttle = false;
function readkey(e) {
if (throttle)
return;
throttle = true;
setTimeout(function () { throttle = false; }, 500);
/* the rest of your code */
500ms is two inputs per second, but they are throttled individually. You could also keep a count of how many inputs there have been in a full second. Something like
if (throttle > 1)
return;
throttle++;
setTimeout(function () { throttle = 0; }, 1000);
I have a game I am making: http://www.taffatech.com/DarkOrbit.html
What I want to be able to do is when I kill a certain amount of enemies it will level up. This part is working, however I also want the spawn amount to increase when you level up.
In my loop function:
function Loop()
{
if (isPlaying == true)
{
updateLevel(); //this updates the level but it calls it every frame which might be bad.
Player1.draw();
drawAllEnemies();
updateStats();
requestAnimFrame(Loop);
}
The update level function:
function updateLevel()
{
if(Player1.enemiesKilled <3)
{
level = 1;
}
else if(Player1.enemiesKilled > 3 && Player1.enemiesKilled <= 9)
{
level = 2;
}
else if(Player1.enemiesKilled > 9 && Player1.enemiesKilled <=18)
{
level = 3;
}
else if(Player1.enemiesKilled > 18 && Player1.enemiesKilled <= 38)
{
level = 4;
}
else if(Player1.enemiesKilled > 38 && Player1.enemiesKilled <= 70)
{
level = 5;
s
}
else if (Player1.enemiesKilled > 120)
{
level = 6;
}
if(level == 1)
{
spawnAmount = 1;
}
else if(level == 2)
{
spawnAmount = 2;
}
else if(level == 3)
{
spawnAmount = 3;
}
else if(level == 4)
{
spawnAmount = 4;
}
else if(level == 5)
{
spawnAmount = 5;
}
else if(level == 6)
{
spawnAmount = 6;
}
}
spawn enemy function:
function spawnEnemy(number) //total enemies starts at 0 and every-time you add to array
{
for (var x = 0; x < number; x++)
{
enemies[enemies.length] = new Enemy();
}
}
My init:
function init()
{
spawnEnemy(spawnAmount);
drawMenu();
sndIntro.play();
document.addEventListener('click', mouseClicked ,false);
}
I tried adding: spawnEnemy(spawnAmount); to after I change the spawn amount global var in the updateLevel function but as this gets called every frame it makes hundreds of enemies fly at me. How can I solve this problem?
If I try something like this hundreds of enemies are genrated, I assume because it gets called every frame:
if(level == 1)
{
spawnAmount = 1;
spawnEnemy(spawnAmount);
}
If your intent is to increase the spawn rate on each level, I'd suggest you start off with a spawnRate first. Let spawnRate represent the number of game updates in between enemy spawns. Every time an enemy spawns, decrement another variable (say spawnRateCountdown), until that variable reaches 0, Then spawn an enemy. Reset the variable back up to the spawnRate. Rinse and repeat.
spawnRate = 60; /* one enemy every 60 updates. */
spawnRateCountdown = spawnRate;
function updateLoop() {
spawnRateCountdown--;
if (spawnRateCountdown == 0) {
spawnRateCountdown = spawnRate;
spawnEnemy();
}
}
After that, you can just update your spawnRate variable as you see fit.
The problem is that you don't create new enemies from time to time, but just shift the same enemy further away on its explosion (i.e. call recycleEnemy method). This single enemy is spawned only once: spawnEnemy function is called in init method only with argument 1.
You should rework enemy spawning algorithm. Below is a pretty good sample, which increases enemy spawning rate:
Remove number argument from spawnEnemy function: spawn only one enemy
Change Enemy.prototype.recycleEnemy function to remove this from enemies. Be cautious: if you'll call this function inside a loop by enemies, you will need to decrease counter to make sure that you won't skip next enemy: --i
Add a function getSpawnCooldown() { return 100 / spawnAmount; } (100 is approximate constant, you can variate it to change initial spawning rate)
Add a variable time which means the number of effective Loop calls from the beginning, defaults to 0
Add a variable lastSpawnTime, set it to 0
Inside if block of Loop function, add lines:
++time
if (time >= lastSpawnTime + getSpawnCooldown()) spawnEnemy();
In spawnEnemy function, add a line: lastSpawnTime += getSpawnCooldown()
Generally, you should better structurize your code. At least, split it to several js files which are responsible for different parts of your application.