I'm learning javascript by using the easeljs library to make a simple game, for school lessons.
I want to make a crosshair give some feedback to the player by showing a small animation while you are pointing at your target, using a hittest I made.
However, when the crosshair touches the target, the animation (should be two little triangles pointing to the middle of the crosshair) seems to be stuck on it's first frame.
Here is a bit of my code, I put both of these functions inside a ticker function. The functions do what they're supposed to do (I checked by sending a message to the console.log), but I think the animation is reset as soon as the variable "hitTestControle" is set to true, at every tick.
If you want to check out all of the code, here is a link to the "game":
http://athena.fhict.nl/users/i279907/achtergrond/achtergrond.html
function hitTest() {
if(distance(crossHair, block) < 60) {
hitTestControle = true;
} else {
hitTestControle = false;
console.log(hitTestControle);
}
}
function hitTestControl() {
if(hitTestControle == true) {
crossHair.gotoAndPlay("move");
console.log("hit");
} else {
crossHair.gotoAndPlay("stop");
}
}
PS: There also seems to be something wrong with this hittest I used.
function distance() {
var difx = blok.x - crossHair.x;
var dify = blok.y - crossHair.y;
return Math.sqrt( (difx * difx) + (dify * dify) );
}
It looks like you're starting the animation... setting it to the first frame and starting it... every time hitTestControle is true. Since hitTestControle will be true as long as you're hovering over the target, the animation will never reach the second frame.
What you need to do is start the animation when you transition from hitTestControle = false to hitTestControle = true, but once that happens you just let it play automatically.
Try changing your hitTestControl() function to something like this:
function hitTestControl() {
if(hitTestControle == true && alreadyOverHit == false) {
crossHair.gotoAndPlay("move");
alreadyOverHit = true;
console.log("hit");
} else {
crossHair.gotoAndPlay("stop");
alreadyOverHit = false;
}
}
In other words, only start the animation once, during the first frame you're detecting a hit, and then don't touch it unless you move off the target and back on.
Related
In phaser 3 framework, what syntax do I use to check the current frame index?
I want to make a hit area appear only when the player's sprite sheet reaches a certain index(the index displaying the motion of 'attack'). I want to accomplish this through detecting its current frame index.
How can I do this?
You could use the sprite events like: Phaser.Animations.Events.ANIMATION_UPDATE, details in official phaser documenation
player.on(Phaser.Animations.Events.ANIMATION_UPDATE, function (anim, frame, gameObject, frameKey) {
// Here you can check for the specific-frame
if(frameKey == "show_hit_area_frame"){
// ... show hitarea
}
// alternatively: with the index of the frame
if(frame.index == 7){
// ... show hitarea
}
});
In this selected Event, you can also check the current frame, for other properties of the frame object (details in official documenation), if you don't know/have the specific framekey/index.
The solution is found.
//hitbox solution: https://newdocs.phaser.io/docs/3.52.0/Phaser.Animations.Events.ANIMATION_COMPLETE_KEY
//hitboxB listener
gameState.playerB.on('animationstart-kill', function () {
console.log("finish kill <3")
gameState.hitBoxB.x = gameState.playerB.flipX ? gameState.playerB.x + 120 : gameState.playerB.x - 120;
gameState.hitBoxB.y = gameState.playerB.y;
// gameState.hitBoxB.visible = true;
})
gameState.playerB.on('animationcomplete-kill', function () {
console.log("kill <3")
gameState.hitBoxB.x =0 ;
gameState.hitBoxB.y = 0;
// gameState.hitBoxB.visible = false;
})
I am developing a game in JavaScript, which consists in being able to move on the screen and create walls, by holding the left click button, while moving the cursor around on the canvas. On the other hand, by pressing right click, one bullet is created. The problem appears when one bullet is created, by right clicking, which, also, determines the window.onmousedown() function to take place. I do not want to create walls by right clicking on the screen, because the right click is only supposed to create a bullet, not a wall, as the wall should only be created by the left click.
I've tried to create a variable, called wallCannotBeCreated, which is set to false, by default. In my mind, the window.oncontextmenu() function should take place, when right click event takes place, thus wallCannotBeCreated becomes true, in order that window.onmousedown() function is becoming "unable" to create any new wall, until window.onmouseup() function takes place, where wallCannotBeCreated becomes, again, false. Unfortunatelly, it doesn't seem to work, as, always, window.onmousedown() function occurs before window.oncontextmenu() function.
var wallCannotBeCreated = false;
window.oncontextmenu = function (e)
{
//alert("right click was pressed");
// a new bullet must be created
bullets[++counterBullets] = new Bullet(player.x + player.r / 2, player.y, e.x, e.y);
wallCannotBeCreated = true;
console.log(wallCannotBeCreated);
}
window.onmousedown = function()
{
console.log(wallCannotBeCreated);
if(wallCannotBeCreated == false)
{
//console.log("mouse is being pressed");
Keys.click = true;
// one wall must be created
walls[++wallNumber] = new Wall();
walls[wallNumber].timerStart();
}
}
window.onmouseup = function()
{
//console.log("mouse was released");
Keys.click = false;
wallCannotBeCreated = false;
}
I am new to Phaser. The code snippet is as follows and collisionCnt here is globally initialised as 0:
update: function() {
this.collisionChecker = this.physics.arcade.collide(this.ground, this.rainGroup, this.over, this.overCheck, this); //checks for collision between rain drops and ground
this.physics.arcade.collide(this.rainGroup, this.rainGroup); //checks for collision between rain drops
},
overCheck: function() {
collisionCnt++;
if(collisionCnt == 4) {
console.log(collisionCnt);
return true;
}
else {
console.log(collisionCnt);
return false;
}
},
over: function() {
this.state.start('gameOver');
}
The problem is update method continuously monitors an instance of collision and returns true continuously resulting in the collisionCnt becoming equals to 4 for a single collision event. I need at least 4 objects of rainGroup group to touch the ground before it is game over. All help is welcome and thanks in advance :)
One way to resolve this would be to give your rain drops a property that would denote whether they had collided or touched the ground. Then in your check see if that property was set and if it was not increment your counter and set the property.
I've created a full JSFiddle as a working example but the relevant code changes in your code might be something like this:
this.collisionChecker = this.physics.arcade.collide(this.ground, this.rainGroup, this.over); //checks for collision between rain drops and ground
over: function(ground, rainDrop) {
if (!rainDrop.hasTouchedGround) {
collisionCnt++;
rainDrop.hasTouchedGround = true;
if (collisionCnt >= 4) {
this.state.start('gameOver');
}
}
}
The second option is to kill rain drops when they touch the ground. That makes things much easier, but will remove the sprite from the display.
over: function(ground, rainDrop) {
collisionCnt++;
rainDrop.kill();
if (collisionCnt >= 4) {
this.state.start('gameOver');
}
}
JSFiddle example showing this option.
I am currently working on a battle system.
The health gets calculated every 200ms, and I'm using a Interval. It works pretty good, until I start the game - the Interval again. It doesn't stop anymore.
It is a lot of code - I have also an online live demo here http://wernersbacher.de/pro/coinerdev/
Like I said - works the first, but not the second.
So, just the main code:
var frameStop;
// Draws Startscreen
function showStartRaid(name) {
playerBTC = btc;
playerBTCs = btcs;
playerName = nick;
// Sets stats for called level
enemyBTC = dun[name]["buyer"]["btc"];
enemyBTCs = dun[name]["buyer"]["btcs"];
enemyName = dun[name]["buyer"]["label"];
enemyNum = dun[name]["meta"]["base"];
/* Reset everything in html */
}
var battle = false;
$(".raid_building").click(function() {
//Draws level
showStartRaid(name);
//Sets start BTC as fighting stats (they will decrease during battle)
fplayerBTC = playerBTC;
fenemyBTC = enemyBTC;
//Click on "Start"
$("#startRaid").click(function() {
function raiden() {
//Calculates fighting
fenemyBTC -= playerBTCs/frameMinus;
fplayerBTC -= enemyBTCs/frameMinus;
/*Draws stats and health here in html */
if(fplayerBTC >= 0 && fenemyBTC >= 0)
console.log("battle goes on")
else {
//If battle is over, stop it
clearInterval(frameStop);
}
}
//Start battle
frameStop = setInterval(raiden, frameRaid);
});
});
Thanks for any help, I'm helpless.
With your code, every time .raid_building is clicked, you hook up a new handler for clicks on #startRaid. So that means, if .raid_building is clicked twice, you'll have two handlers for clicks on #startRaid, both of which start a new interval timer. Your frameStop variable will only contain the handle of one of them; the other will continue. And of course, a third click will compound the problem (you'll have three click handlers, each of which fires up a new interval timer). And so on...
Move the code hooking click on #startRaid outside the click handler on .raid_building.
I am using EaselJS and want to create a flashing color rectangle that will flash a certain number of times when a button is pressed, displaying random colors from an array. It should stop after 10 color flashes and then I want to extract the final color.
So far the relevant code I have is:
var colorArray = ["#FE7B62","#CB2DD3","#F1FD66","#004CE8","#FFD068", "#02A97E"];
square = new createjs.Shape();
square.graphics.beginFill("#000").drawRoundRect(850, 50, 100, 100, 20);
function pushButton(event) {
square.graphics.inject(animateColor);
}
function animateColor(event) {
this.fillStyle = colorArray[parseInt(Math.random()*6)];
}
This code successfully triggers the flashing of colors from my color array, but I am not sure what the best method of running the animation for a limited number of frames is. I tried pausing the ticker and restarting it on the onclick of the button but that failed. I also tried using a for loop in the pushButton function but that caused a "too much recursion error" in the browser. Here is my full file link https://github.com/RMehta95/sherman-land/blob/master/main.js.
I would suggest creating an event to trigger your action (xamountOfFrames). Here is a link to some information that might help
http://www.w3schools.com/tags/ref_eventattributes.asp
I ended up not using the inject function and instead redrawing the shape each time, creating a couple counter and timer variables to ensure that it looped through the proper amount of times.
function pushButton() {
if (timer === false) {
animate = setInterval(animateColor, 200);
timer = true;
}
}
function animateColor() {
square.graphics.clear();
displayColor = colorArray[Math.floor(Math.random()*colorArray.length)];
square.graphics.beginFill(displayColor).drawRoundRect(850, 50, 100, 100, 20);
counter++;
if (counter===15) {
clearInterval(animate);
counter=0;
movePlayer(displayColor);
timer = false;
return;
}
}