P5.Play - Collision problems - javascript

hoping someone can help me with this.
I'm trying to create a game where balloons get popped by bullet.
Sort of similar to balloons tower defence. My only problem is that the frames are drawn every 60 seconds and each loop happens once per 60 seconds meaning that the bullet getting removed happens before the balloons change.
So far I've got:
Bullet is fired.
Bullets checks whether it has hit a balloon.
If hit remove bullet and change blue balloon to red balloon.
This would be easier if there was some way of checking which bullet collides with which balloon but as far as I can tell through the P5.Play reference theres no way to do this.
Sorry if this is stupid question I feel like I've been stuck on this issue for ages :(
Thanks for the help!
Code:
Bullets:
function bulletTime() {
bullet = createSprite(player.position.x, player.position.y, 3, 10);
bullet.setSpeed(4, 270);
bullet.setCollider("rectangle", 0, -2, 3, 10);
bullet.debug = true;
bullet.addToGroup(bullets);
}
// deletes bullets when they leave the screen prevents memory overload
function bulletDelete(){
for (i = 0; i < bullets.length; i++) {
if (bullets[i].overlap(balloons)){
bullet2 = createSprite(bullets[i].position.x, bullets[i].position.y+3, 3, 10);
bullet2.addToGroup(bullets2);
bullets[i].remove();
setTimeout(bullet2.remove(),10);
}
}
}
Balloons:
// pops Balloons
function popBalloon(){
for (i = 0; i < balloons.length; i++) {
if (balloons[i].overlap(bullets2)) {
if (balloonsRed.contains(balloons[i])){
balloons[i].addImage("redPop",redPop);
balloons[i].changeAnimation("redPop");
balloons[i].remove();
score += 100;
}
if (balloonsBlue.contains(balloons[i]) ){
balloons[i].addImage("redBalloon",redBalloon);
balloons[i].changeAnimation("redBalloon");
balloons[i].addToGroup(recentlyHit);
}
}
}
}

In case anyone else has a similar issue. HardcoreGameDev had it right!
Here's the working code.
// pops Balloons
function popBalloon(){
for (j = 0; j < balloons.length; j++) {
for (i = 0; i < bullets.length; i++) {
if (bullets[i].overlap(balloons[j])){
if (balloonsRed.contains(balloons[j])){
bullets[i].remove();
balloons[j].remove();
return;
}
if (balloonsBlue.contains(balloons[j])){
print("blue")
bullets[i].remove();
balloon = createSprite(balloons[j].position.x, balloons[j].position.y, 30, 30);
balloon.addSpeed(0.5,90);
balloon.addToGroup(balloons);
balloon.debug = true;
balloon.addImage("red",redBalloon);
balloon.changeAnimation("red");
balloon.scale = 0.2;
balloon.setCollider("circle",0,0,120);
balloon.addToGroup(balloonsRed);
balloons[j].remove();
return;
}
}
}
}
}
I know the code is arbitrary at some points :)

Your issue seems to related to your step 3.
If hit remove bullet and change blue balloon to red balloon.
The bullet attempted to remove itself / delete when a collision happens.
This actually implemented as "when the bullet hit a balloon the bullet disappears", so the balloon may never detect any collisions.
Since the balloon states are triggered by bullet, the popBalloon function should be called inside bulletDelete to update the specific balloon that got hit.

Related

How do I get a winning picture in a slide puzzle?

I make a slide puzzle game. When the puzzle is solved "won" should be displayed and the timer should stop.
I hope you can help me. Thanks.
Here is a link to the web editor for my puzzle link
Here is the part of the code but it doesn´t work:
function draw() {
if (isSolved()) {
console.log('SOLVED');
timerValue = 0;
text('Won', width/2, height/2);
}
}
function isSolved() {
for (let i = 0; i < plate.length - 1; i++) {
if (plate[i] !== tiles[i].index) {
return false;
}
}
return true;
}
P5JS is saying that createImage() was expecting Integer for the second parameter, received number instead. This can be solved by changing let img = createImage(w, h); tp let img = createImage(int(w), int(h));.
I'm not entirely sure if this helps, because I don't know how your puzzle works (how it's solved) so please tell me if this doesn't work and I'll investigate further.

Extreme Novice needing assistance with mousePressed() event

I am VERY new to P5.js/processing (taking programming for artists). I am trying to make a crude game where an image (Jar Jar) bounces across the screen and another image (lightsaber) that moves with the mouse and when the mouse attached image goes over the bouncing image then the lightsaber will be mirrored and activate a sound. If this at all makes sense...
I have the bouncing image part down so far, but I am unable to make the mousePressed() function work. like I mentioned, I need the "lightsaber.png" to flip when the mouse is pressed. Also, when the mouse is pressed and is directly over the JarJar image, how would I add a score count and sound event?
Thank you!
here is my code so far:
let jarJar;
let jarJarX=5;
let jarJarY=5;
let xspeed;
let yspeed;
let lightSaber;
function preload() {
jarJar = loadImage('jarjar.png');
lightSaber= loadImage ('lightSaber.png');
}
function setup() {
createCanvas(700,700);
xspeed=random (15,22);
yspeed=random (15,22);
}
function draw() {
background(0);
image (lightSaber,mouseX,mouseY,100,100);
image(jarJar,jarJarX,jarJarY, 140, 200);
jarJarX= jarJarX+xspeed;
if (jarJarX<=-300|| jarJarX>=width+200){
xspeed=xspeed*-1;
}
jarJarY= jarJarY+yspeed;
if (jarJarY<-200|| jarJarY>=height+200 ){
yspeed=yspeed*-1;
}
//picture mirrors when mouse pressed
if mouseClicked(){
scale(-1,1);
image(lightSaber);
}
//score counter coordinate with lightsaber hitting image
//
}
Let it be known that I'm not proficient at javaScript. This said, your question is quite simple so I can help anyway.
Some framework will have simple ways to mirror images. Processing likes to scale with a negative number. I re-coded some of your stuff to accommodate my changes. The main changes goes as follows:
I added a method to draw the lightsaber so we can "animate" it (read: flip it for a couple frames when the user clicks around).
I added a 'score' global variable to track the score, and a way for the user to see that score with the text method.
I added a method called "intersect" which isn't very well coded as it's something I did back when I was a student (please don't hurt me, it works just right so I still use it from time to time). For more details on how simple collisions works, take some time to read this answer I wrote some time ago, there are nice pictures too!
I added a mouseClicked method. This method will act like an event, which means that it will be triggered by a specific call (a left mouse button click in this case). This method contains the code to check for a collision between the squares which are the images. If there's an overlap, the score will increase and jarjar will run in another direction (this part is a bonus to demonstrate that this is the place where you can get creative about the collision).
I commented the code so you can get what I'm doing more easily:
let jarJar;
let jarJarX=5;
let jarJarY=5;
let xspeed;
let yspeed;
let lightSaber;
let flipLength;
let score = 0;
function preload() {
jarJar = loadImage('jarjar.png');
lightSaber= loadImage ('lightSaber.png');
}
function setup() {
createCanvas(700, 700);
runJarJarRun();
}
function draw() {
background(0);
drawLightSaber(); // this way I can deal with the lightsaber's appearance in a dedicated method
image(jarJar, jarJarX, jarJarY, 140, 200);
jarJarX= jarJarX+xspeed;
if (jarJarX<=-300|| jarJarX>=width+200) {
xspeed=xspeed*-1;
}
jarJarY= jarJarY+yspeed;
if (jarJarY<-200|| jarJarY>=height+200 ) {
yspeed=yspeed*-1;
}
//score counter coordinate with lightsaber hitting image
textSize(30);
fill(200, 200, 0);
text('Score: ' + score, 10, 40);
}
function drawLightSaber() {
if (flipLength) { // if the number is > 0 this will be true
flipLength--; // measure how ling the saber is flipped in frames # ~60 frames per second
push(); // isolating the translate ans scale manpulations to avoid ruining the rest of the sketch
translate(mouseX + 100, 0); // makes the coordinates so once flipped the lightsaber will still appear at the same location
scale(-1.0, 1.0); // flip x-axis backwards
image (lightSaber, 0, mouseY, 100, 100);
pop(); // ends the sequence started with 'push();'
} else {
image (lightSaber, mouseX, mouseY, 100, 100);
}
}
function runJarJarRun() {
xspeed=random (5, 10);
yspeed=random (5, 10);
}
function mouseClicked() { // this method will trigger once when the left mouse button is clicked
flipLength = 10;
if (intersect(jarJarX, jarJarY, 140, 200, mouseX, mouseY, 100, 100)) {
score++;
runJarJarRun(); // as a bonus, jarjar will run in another direction on hit
// you could totally put some more special effects, like a flash, a sound, some 'mesa ouchie bad!' text, whatever speaks to you
}
}
function intersect(x1, y1, w1, h1, x2, y2, w2, h2) {
let checkX = false;
let checkY = false;
if ( (x1<x2 && (x1+w1)>x2) || (x1<(x2+w2) && (x1+w1)>x2+w2) || (x1>x2 && (x1+w1)<(x2+w2)) ) {
checkX = true;
}
if ( (y1<y2 && (y1+h1)>y2) || (y1<(y2+h2) && (y1+h1)>y2+h2) || (y1>y2 && (y1+h1)<(y2+h2)) ) {
checkY = true;
}
return (checkX && checkY);
}
If there's something you don't understand, let me know in a comment and I'll be happy to elaborate. Good luck and have fun!
Hi and welcome to stack overflow. One thing to keep in mind when submitting here (or any forum where you're looking for help with code) is to post a minimal reproducible example. You'll be much more likely to get useful responses.
You'll also want to separate out your questions, as they each have multi-step responses.
Your first question is about how to get your sketch to display something when you press the mouse down. Your syntax isn't quite correct there. Here's a minimal example of how to check for a mouse held down.
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
if (mouseIsPressed == true) {
ellipse(100, 100, 100, 100);
}
}
Just a quick note that I tried to make this as 'novice-friendly' as possible. The == true is optional and not usually included.

3d motion/hitboxing with threejs

I am attempting to do some simple motion with threejs. My goal is to have a box you can move around that cannot walk through walls. As of right now my motion code looks like this
function handleMotion(mesh) {
var xClone = mesh.clone();
xClone.position.x += mesh.velocity.x;
if (checkColl(xClone, collisionMeshList, [mesh.uuid])) {
mesh.velocity.x = 0;
}
var yClone = mesh.clone();
yClone.position.y += mesh.velocity.y;
if (checkColl(yClone, collisionMeshList, [mesh.uuid])) {
mesh.velocity.y = 0;
}
var zClone = mesh.clone();
zClone.position.z += mesh.velocity.z;
if (checkColl(zClone, collisionMeshList, [mesh.uuid])) {
mesh.velocity.z = 0;
}
mesh.position.add(mesh.velocity);
}
It checks each axis of motion to ensure that it is not going to move into a wall on the next frame. The problem is it does not prevent the cube from moving into the wall, however, once it moves into the wall it prevents the cube move moving out.
I also tried adding a "sim step" just to check if it could be increased by increasing the number of calculations it did however led to no change. The code is basically acting like the clones are at the same position as the mesh however I have confirmed they are indeed offset.

Articulated animation

I am trying to figure out how to sequence the train animation so I can offset and rotate each wagon in turn around curves, for example, in Route_51 (click Test>Run[twice]) in this display. Needs Chrome or other HTML5 compliant browser.
Here is my so far 'non-complying' code (using KineticJs):
function animate(nr,path,incr,train,dirX,dirY){
var steps,offsetX,offsetY,count,a;
steps = Math.round(path[nr][2] / incr);
offsetX = path[nr][2]/steps;
offsetY = path[nr][3]/steps;
count = 0;
stage.onFrame(function(frame){
layer = train[0].getLayer();
if(count < steps){
for(a=0; a<train.length; a+=1){
incrX = train[a].getX() + offsetX * -dirX;
incrY = train[a].getY() - offsetY * -dirY;
train[a].setX(incrX);
train[a].setY(incrY);
}
layer.draw();
count += 1;
}
else{
stage.stop();
nr += 1;
if(path[nr]){
animate(nr,path,incr,train,dirX,dirY);
}
}
});
stage.start();
}
I don't seem to be able to grasp the logic (getting old).
All help appreciated. Thanks.
It seems a certain amount of time has to pass before some kind of logic emerges.
In this case it was that each loco/wagon needed its own fully incremented path for the starts and optionally finishes to be staggered. Here is a screenshot of the train in motion with the "normal" scale view inset. Room for improvement of course especially with curve coordinates.
For the animation visit http://glasier.hk and follow the KJS link.

gameQuery collision detection

it is the first time for me to explore jQuery and gameQuery for building games using JavaScript, so am asking about sth that might look very naive, but really i cant get it.
i am developing a game like Space Invader, the detection for collision between player missile and enemies not working.
This is my code:
the definition for my Enemy class
function Enemy(node){
this.node = $(node);
this.pts_value = 0;
return true;
}
this is the code i use to add ten enemy sprite next to each other. the enemies move together to the left and the right
$.each(new Array(10), function(index, value) {
$("#enemy_group").addSprite("enemy2_"+index,{animation: enemies[2],
posx: index * 55, posy: 0, width: 48, height: 48})
$("#enemy2_"+index).addClass("enemy");
$("#enemy2_"+index)[0].enemy = new Enemy($("#enemy2_"+index));
$("#enemy2_"+index)[0].pts_value = 150;
});
so when i need to move the enemies, i move the enemies together, i move the group that includes all the sprites "#enemy_group"
if(ENEMY_TO_RIGHT){
var enemiesNewPos = (parseInt($("#enemy_group").css("left"))) + ENEMY_SPEED;
if(enemiesNewPos < PLAYGROUND_WIDTH - 550){
$("#enemy_group").css("left", ""+enemiesNewPos+"px");
} else {
ENEMY_TO_RIGHT = false;
}
} else {
var enemiesNewPos = (parseInt($("#enemy_group").css("left"))) - ENEMY_SPEED;
if(enemiesNewPos > 0){
$("#enemy_group").css("left", ""+enemiesNewPos+"px");
} else {
ENEMY_TO_RIGHT = true;
}
}
finally for collision detection, i want to remove the enemy sprite that the players missile has hit, each missile sprite has an added class names ".playerMissiles"
$(".playerMissiles").each(function(){
var posy = parseInt($(this).css("top"));
if(posy < 0){
$(this).remove();
return;
}
$(this).css("top", ""+(posy - MISSILE_SPEED)+"px");
//Test for collisions
var collided = $(this).collision(".enemy, .group");
if(collided.length > 0){
//An enemy has been hit!
collided.each(function(){
$(this).setAnimation(enemies[0], function(node){$(node).remove();});
})
}
});
i was following the documentation tutorial on the gameQuery website.
any help appreciated, thanks,
I can't see any problem with your code. I can only give you a few pointers:
Did you create "enemy_group" with the addGroup function?
Is "enemy_group" nested in something special like a custom div ? for the collision detection to work you need a chain of parent composed only of sprites and groups (and tiles map)
Is "enemy_group" nested in a sprite, if so it's a bad idea because you will need to add the selector for this sprite in your methode call and this sprite will be included in the colliding element list.
The same goes for the ".playerMissiles"
Just to be sure what version of gameQuery and jQuery do you use? The last version from gitHub is unstable and I wouldn't recomend using it, user 0.5.1 instead.
You could use jquery collision plugin, so you avoid doid the logic by yourself.
Hope this helps. Cheers

Categories

Resources