life decrease on collision - javascript

I am making a little game using HTML5 Canvas and javascript. I am so far that I have a kite moving some sort of power up on collision and an obstacle on collision.
Now I'm at the point I want to add lives and when you hit an obstacle your life will decrease 1.
I tried some stuff and when you hit an obstacle the life decreases but it decreases constantly and the player image gets removed instead of the obstacle image.
here is the life thing you can check all the code there.
http://nickzijlstra.com/kite
Here the code I think is the most important for the problem.
function hitObject(player, obj){
var a = (obj.x - player.x),
b = (obj.y - player.y),
c = Math.sqrt(a*a + b*b),
r0 = player.image.width/2,
r1 = obj.image.width/2;
if (c < r0+r1) {
player.drawable = false;
lifes -=1;
window.location.reload(true);
}
}
If someone sees the problem or knows the solution I would really appreciate it!

The reason the player disappears is because of this line in the hitObject function:
player.drawable = false;
This will cause the player to not be drawn because of this condition in your drawing function:
if (player.drawable == true) {
context.drawImage(player.image, player.x, player.y, player.image.width, player.image.height);
}
I presume you actually want to move the obj back to a random spot on the top of the screen if the player gets hit. It doesn't do this at the moment, which is why the lives go down rapidly: the object hits the player, it removes a life, and then the next frame it hits the player again (even though the player isn't visible).
What you might want is something like:
...
if (c < r0+r1) {
lifes -=1;
// Respawn the object.
obj.y = -50;
obj.x = Math.random() * canvas.width;
...

At a guess, I'd say that you should replace the
player.drawable = false;
with
obj.drawable = false;
and wrap the whole collision detection inside of an if obj.drawable=true so that removed obstacles won't collide with the kite.

Related

Logic: Prevent infinite loop when using portals

In a game that I am currently working on, there are portals, which are linked in pairs of two. Whenever the player enters a portal, it should be teleported to the other portal that is linked to the portal that they just entered. The problem is, that once it is teleported over, the other portal see's that the player is collding with it, and will teleport it back to the first, which will send it back and so on. The code for this porject is large and over many files, but here is the most important:
(Javascript, ignore the frame and pause vaibles, those are for animation)
export class Portal extends gameObject{
constructor(x, y, size, id){
super(x, y, size);
this.currentFrame = 0;//updated when (below) > (2 below)
this.countingFrame =0;//update every time;
this.pause = 3;//frames between frames
this.id = id;
this.justVisited = false;
}
update(player, portals){
if(this.countingFrame >= this.pause){
this.currentFrame = (this.currentFrame + 1) % 4;
this.countingFrame = 0;
}else{
this.countingFrame ++;
}
if(super.checkPlayerCollision(player)){
this.justVisited = true;
for(let i in portals){
if(this.id === portals[i].id && portals[i] !== this && !portals[i].justVisited){
player.x = portals[i].x;
player.y = portals[i].y;
}
}
}else{
for(let i in portals){
if(this.id === portals[i].id && portals[i] !== this && portals[i].justVisited){
this.justVisited = false;
}
}
}
}
render(canvas, spritesheet){
super.render(canvas, spritesheet, this.currentFrame , 26);
}
}
This is one attempt at patching it up, but it still failed. How can I make it so that the player goes throught the first one as soon as it collides, comes out the second, and won't retrun to the first untill the player moves off and then back on?
EDIT:After a little bit of seaching, the answer that was most often given to this question was "Move the player outside the reach of the second portal when it teleports over there". This will not work in my case, because when the player updates, his position changes with respect to the amount of time seince the last frame. In a perfet world, that would be ok, but because it is not perfect, the player cannot reliably be on a single point. Also, it would look weird if I moved it out of the hitbox entirely, so that doesn't work either.

Animate a flying bird in p5.js

I want to create an animation of a bird with p5 js. I have 6 pictures of the bird - when the wings are up, in the middle, and so on... When I press 'space bar' on the keyboard, the bird should fly - so all the pics should be shown as an animation (as if the bird is really flying). I want to build this code snippet without spritemap.
This is my code, but somehow it doesn't work..
let time = 0;
let frame = 0;
let img = [];
function preload() {
img.push(loadImage("assets/Bird/bird-1.png"));
img.push(loadImage("assets/Bird/bird-2.png"));
img.push(loadImage("assets/Bird/bird-3.png"));
img.push(loadImage("assets/Bird/bird-4.png"));
img.push(loadImage("assets/Bird/bird-5.png"));
}
function draw() {
function keyPressed() {
if (key == ' ') {
const speed = 1;
const numImage = img.length;
let current = frame % numImage;
let display = img[current];
image(display, width / 2, height / 2, display.width, display.length);
time += speed;
if (time > 5) {
time = 0;
frame++;
}
}
}
}
Looking forward to reading some ideas! Thank you in advance.
First things first you should not need to handle frames and such things. It is better to use keyPressed function outside of scope draw since it is a special event function and automatically called when a key is pressed.
It is better to use setup functionality instead of preload since preload is a little bit more early function then we needed. Setup is more relevant in such things like loading an array and so on.
I see that you forgot to create a canvas to draw an image on it. I added that on setup and also set the framerate of canvas regarding the img array's size.
function setup() {
createCanvas(400, 400);
background(51);
img.push(loadImage("1.png"));
img.push(loadImage("2.png"));
img.push(loadImage("3.png"));
img.push(loadImage("4.png"));
frameRate(img.length * 2); // double speed on animate sprites
}
From this point it is only a matter of checking the keyCode and looping through array.
function draw() {
if (keyIsDown(32)) {
background(51);
const numImage = img.length;
let current = frameCount % numImage;
let display = img[current];
image(display, width / 2 - display.width , height / 2 - display.height , display.width, display.length);
}
}
Here in the keyIsDown(32) check, 32 represents spacebar. You can check others from here easily : http://keycode.info/
You want to re-set the background of canvas on each sprite display. If not, they will still be showing on each render.
You can see the working version of your code in here :
https://editor.p5js.org/darcane/sketches/rVl22hkv7

Have particles appear OnClick function in p5.js

New to p5.js and trying to learn more every day. Basically, I am currently learning about particle systems and objects, and getting confused by the amount of code. Anyways, I'd like that on function mousePressed(), an array of particles (particle system) that I've created appears. It'd also be awesome if the particle system could trail the position of the mouse. So, basically, if you click your mouse on the screen particles appear in that position, and also trail your mouse.
I can't figure out what I'm missing in the code. I feel kind of lost about what half of it is even doing (my professor wrote a lot of it). When I add in the mousePressed function, everything goes to pot. I feel like I'm too overwhelmed to even know what's missing. Any help, plus detailed insight into what I need to do and why that solution works would be super appreciated. Thank you!
var particles = [];
var now = null;
function setup() {
createCanvas(windowWidth, windowHeight);
}
function draw() {
background(255, 25, 25);
function mousePressed() {
particles.push(new Particle(new p5.Vector(mouseX, mouseY)));
//particles.push(new Particle(new p5.Vector(width / 2, height / 1.5)));
for (var i = 0; i < particles.length; i++) {
// if our particle is dead, remove it
if (particles[i].lifespan <= 0) {
//splice is a way of removing a specific
//element from an array
particles.splice(i, 2);
} else {
particles[i].update();
particles[i].display();
}
//this.particle = new ParticleSystem(createVector(mouseX, mouseY));
// patricles.push(p);
}
}
}
function Particle(loc) {
this.loc = loc;
this.acc = new p5.Vector();
this.vel = new p5.Vector(random(-100, 100), random(-2, 0));
this.lifespan = 555;
}
Particle.prototype = {
constructor: Particle,
update: function() {
this.vel.add(this.acc);
this.loc.add(this.vel);
this.lifespan -= 4.0;
},
display: function() {
stroke(random(0), this.lifespan);
fill(random(255), random(255), random(255))
ellipse(this.loc.x, this.loc.y, 20, 20);
}
}
First of all, your mousePressed() function is inside your draw() function. That doesn't make a ton of sense. You want your mousePressed() function to be at the same level as your draw() function.
function draw(){
//draw code here
}
function mousePressed(){
//mousePressed code here
}
If I were you, I would start smaller. Can you create a program that draws a single ellipse? Can you then make it so that single ellipse appears when you click the mouse? Then can you have that ellipse follow the mouse? Only if you can get that working perfectly by itself, then you should start thinking about adding multiple ellipses.
You're trying to go from your end goal and work backwards, which is just going to confuse you. Instead, start from the simplest sketch possible and take one small step at a time. Then if you get stuck you can post an MCVE along with a specific question, and it'll be easier to help you.

How to speed up this moving algorithm? In Javascript

I have an Array of 16 billiard balls in JS and want to move each ball smoothly with its direction and speed.
For that I set up a timer, calling UpdateThis() every 42ms (for 24 fps).
The problem is that UpdateThis() takes 53ms as firebug states.
Now UpdateThis iterates over every ball and calls UpdateBall(ball).
I assume that the problem lies there.UpdateBall looks like this:
function UpdateBall(ball)
{
if(ball.direction.x != 0 && ball.direction.y != 0) {
//ball moving!
for(var i = 0; i < balls.length; i++) {
//CheckCollision(ball, balls[i]); //even without this it takes 53 ms!
}
var ps = VAdd(ball.position, VMul(ball.direction, ball.speed)); //Multiply Direction with speed and add to position!
if(ps.x < Bx || ps.y < By || ps.x > Bw || ps.y > Bh) { //Bounce off the wall!
ball.direction = VMul(ball.direction, -1); //Invert direction
ball.speed *= 1;
ps = VAdd(ball.position, VMul(ball.direction, ball.speed)); //Calc new position!
}
ball.position = ps;
ball.MoveTo(); //See explanation at the bottom.
ball.speed *= GRK; //Gravity
if(ball.speed < 0.05) {
ball.speed = 0;
}
}
}
it seems that the most time is spent in ball.MoveTo() which looks like this:
function()
{
this.image.style.left = this.position.x + "px";
this.image.style.top = this.position.y + "px";
}
-- UPDATE --
function UpdateThis() {
for(var i = 0; i < balls.length; i++) {
var cur = balls[i];
UpdateBall(cur);
balls[i] = cur;
}
}
and onload looks like
nx = setInterval(function() { UpdateThis(); }, 42);
Does somebody have any ideas on how to speed this up?
-- UPDATE 2 --
You can download the folder with the HTML file here (the password is password)
What about separating the position updates from the drawing? So have something like this (untested code):
function DrawBall(ball)
{
ball.MoveTo(); //Take this line out of UpdateBall
}
-
function UpdateThis() {
for(var i = 0; i < balls.length; i++) {
var cur = balls[i];
UpdateBall(cur);
balls[i] = cur;
}
}
-
function DrawThis() {
for(var i = 0; i < balls.length; i++) {
DrawBall(balls[i]);
}
setTimeout(function() { DrawThis(); }, 42);
}
-
nx = setInterval(function() { UpdateThis(); }, 42);
setTimeout(function() { DrawThis(); }, 42);
If indeed it's the moving of the position that's slow, this way the logic update still happens at 42ms, and the framerate is no faster than 42ms but it can skip frames. (I haven't actually tried this, so this is all theoretical and you may need to tweak some stuff)
Why moving may be (and most probably is) slow?
Move functionality could be slow, because it has more things to do than simple variable assignment. It has to actually render some element to some other place. You could test this if you run this on IE9. I anticipate it should run faster since it uses hardware video acceleration.
As for the other routine I hope others will dissect it. :)
Questions for you
Can you please describe how do balls move? Sporadically? How do you call UpdateBall() for each ball? Do you queue those calls?
Provide VMul and VAdd functionality
Have you played with styling? Maybe relative positioning of balls' immediate parent may speed up rendering. And setting overflow:hidden on it as well. I don't know. Depends on how you've done it. Hence a JSFiddle would be very helpful.
A suggestion
Instead of using setInterval to call your function you should maybe just queue them and let them execute as fast as it gets. And just for the sake of it, provide a central setInterval with some watcher that they don't run too fast.
But I guess that it still utilizes your processor to 100% which isn't good anyway.
Very important note: Don't run you app while Firebug's enabled because it's a well known fact that Javascript executes much slower when Firebug is running.
That's tough, if MoveTo() is in fact your bottleneck, since there is not a whole lot going on there. About the only things I can think of, right off hand, are
1) Cache the style property of the image and position for faster lookups. Everytime you see a dot in the object chain it's requires stepping through the scope chain. Ideally you can cache this property at the time the parent of MoveTo() is constructed.
2) Are the 'px' strings required? It may result in an invalid CSS specification, but it may still work. I have a hard time believing 2 string concats would really change all that much though.
The main problem here is likely the fact that anytime you change the DOM, the browsers re-flows the entire page. Your only other option may be to refactor such that instead of changing the styles, you actually remove the previous contents, and replace it with the a document fragment describing the new state. This would result in only 2 re-flows for the entire step (1 for removal, 1 for addition), instead of 2 for each ball.
EDIT: Regarding #1 above, when I say cache, I don't mean just locally in the function call. But perhaps as a closure in the parent object. For example:
var Ball = function(img){
var style = img.style;
var posX;
var posY;
function MoveTo(){
style.left = posX + "px";
style.right = posY + "px";
}
};

collision detection in javascript game?

My Map array ;;
map[0] = [0,0,0,0,0,0]
map[1] = [0,1,0,1,0,1]
map[2] = [0,0,0,0,0,0]
map[3] = [1,0,1,0,1,0]
map[4] = [0,0,0,0,0,0]
map[5] = [0,1,0,1,0,1]
1= Hurdle
0 = Nothing
i've to detect collision detection b/w player and hurdles in map.
player.x & player.y is the reference from left top .
Each hurdle is 40px of width and length .
i need a roughly concept not codes
You have to normalize player position to the collision map unit as player position is in px units and your collision map is in array index units and then test if the field the player tries to enter is not a hurdle.
function normalizePosition(entity){
return {
x: Math.ceil(entity.pos.x / TILE_WIDTH),
y: Math.ceil(entity.pos.y / TILE_HEIGHT)
}
}
Normalize position will give you entity coordinates on the collision map and next you have to test the actual collision to see what kind of tile is the entity entering
function mapCollision(entity, map){
var mapCoords = normalizePosition(entity),
tileType = map[mapCoords.y][mapCoords.x];
return tileType;
}
It will return the code of tile type on the map for player normalized position in case you wanted to have there different things then just blocks like some kind of slowing down traps or whatever other bear pits. You could then handle different cases where zero would default to accepts player entering the tile.
Hope I didn't tell to much :)
Good luck with your game and if you'll remember I'd be happy if you'd share the effects with me when its done :)
Tom
Update
I made a simple example for better interpretation purpose:
http://fiddle.jshell.net/qFCyn/1/
Use this:
var BLOCK_SIZE = 40; // 40px * 40px blocks
var hurdle = map[player.y/BLOCK_SIZE][player.x/BLOCK_SIZE]
if(hurdle) {
// stuff
} else {
// other stuff
}

Categories