Skip to content

Commit

Permalink
Pre-Release v8 Examples Update
Browse files Browse the repository at this point in the history
  • Loading branch information
bbazukun123 committed Dec 21, 2023
1 parent af6c7e0 commit 265ba3c
Show file tree
Hide file tree
Showing 14 changed files with 809 additions and 651 deletions.
313 changes: 164 additions & 149 deletions src/examples/v8.0.0-rc/advanced/collisionDetection.js
Original file line number Diff line number Diff line change
@@ -1,179 +1,194 @@
import * as PIXI from 'pixi.js';
import { Application, Assets, Point, Sprite, Texture, Ticker } from 'pixi.js';

// Based somewhat on this article by Spicy Yoghurt
// URL for further reading: https://spicyyoghurt.com/tutorials/html5-javascript-game-development/collision-detection-physics
const app = new PIXI.Application({ background: '#111', resizeTo: window });

document.body.appendChild(app.view);

// Options for how objects interact
// How fast the red square moves
const movementSpeed = 0.05;

// Strength of the impulse push between two objects
const impulsePower = 5;

// Test For Hit
// A basic AABB check between two different squares
function testForAABB(object1, object2)
(async () =>
{
const bounds1 = object1.getBounds();
const bounds2 = object2.getBounds();

return (
bounds1.x < bounds2.x + bounds2.width
&& bounds1.x + bounds1.width > bounds2.x
&& bounds1.y < bounds2.y + bounds2.height
&& bounds1.y + bounds1.height > bounds2.y
);
}

// Calculates the results of a collision, allowing us to give an impulse that
// shoves objects apart
function collisionResponse(object1, object2)
{
if (!object1 || !object2)
{
return new PIXI.Point(0);
}

const vCollision = new PIXI.Point(object2.x - object1.x, object2.y - object1.y);
// Create a new application
const app = new Application();

const distance = Math.sqrt(
(object2.x - object1.x) * (object2.x - object1.x) + (object2.y - object1.y) * (object2.y - object1.y),
);
// Initialize the application
await app.init({ background: '#111', resizeTo: window });

const vCollisionNorm = new PIXI.Point(vCollision.x / distance, vCollision.y / distance);
// Append the application canvas to the document body
document.body.appendChild(app.canvas);

const vRelativeVelocity = new PIXI.Point(
object1.acceleration.x - object2.acceleration.x,
object1.acceleration.y - object2.acceleration.y,
);
// Options for how objects interact
// How fast the red square moves
const movementSpeed = 0.05;

const speed = vRelativeVelocity.x * vCollisionNorm.x + vRelativeVelocity.y * vCollisionNorm.y;
// Strength of the impulse push between two objects
const impulsePower = 5;

const impulse = (impulsePower * speed) / (object1.mass + object2.mass);

return new PIXI.Point(impulse * vCollisionNorm.x, impulse * vCollisionNorm.y);
}

// Calculate the distance between two given points
function distanceBetweenTwoPoints(p1, p2)
{
const a = p1.x - p2.x;
const b = p1.y - p2.y;
// Test For Hit
// A basic AABB check between two different squares
function testForAABB(object1, object2)
{
const bounds1 = object1.getBounds();
const bounds2 = object2.getBounds();

return (
bounds1.x < bounds2.x + bounds2.width
&& bounds1.x + bounds1.width > bounds2.x
&& bounds1.y < bounds2.y + bounds2.height
&& bounds1.y + bounds1.height > bounds2.y
);
}

return Math.hypot(a, b);
}
// Calculates the results of a collision, allowing us to give an impulse that
// shoves objects apart
function collisionResponse(object1, object2)
{
if (!object1 || !object2)
{
return new Point(0);
}

// The green square we will knock about
const greenSquare = new PIXI.Sprite(PIXI.Texture.WHITE);
const vCollision = new Point(object2.x - object1.x, object2.y - object1.y);

greenSquare.position.set((app.screen.width - 100) / 2, (app.screen.height - 100) / 2);
greenSquare.width = 100;
greenSquare.height = 100;
greenSquare.tint = 0x00ff00;
greenSquare.acceleration = new PIXI.Point(0);
greenSquare.mass = 3;
const distance = Math.sqrt(
(object2.x - object1.x) * (object2.x - object1.x) + (object2.y - object1.y) * (object2.y - object1.y),
);

// The square you move around
const redSquare = new PIXI.Sprite(PIXI.Texture.WHITE);
const vCollisionNorm = new Point(vCollision.x / distance, vCollision.y / distance);

redSquare.position.set(0, 0);
redSquare.width = 100;
redSquare.height = 100;
redSquare.tint = 0xff0000;
redSquare.acceleration = new PIXI.Point(0);
redSquare.mass = 1;
const vRelativeVelocity = new Point(
object1.acceleration.x - object2.acceleration.x,
object1.acceleration.y - object2.acceleration.y,
);

const mouseCoords = { x: 0, y: 0 };
const speed = vRelativeVelocity.x * vCollisionNorm.x + vRelativeVelocity.y * vCollisionNorm.y;

app.stage.eventMode = 'static';
app.stage.hitArea = app.screen;
app.stage.on('mousemove', (event) =>
{
mouseCoords.x = event.global.x;
mouseCoords.y = event.global.y;
});
const impulse = (impulsePower * speed) / (object1.mass + object2.mass);

// Listen for animate update
app.ticker.add((delta) =>
{
// Applied deacceleration for both squares, done by reducing the
// acceleration by 0.01% of the acceleration every loop
redSquare.acceleration.set(redSquare.acceleration.x * 0.99, redSquare.acceleration.y * 0.99);
greenSquare.acceleration.set(greenSquare.acceleration.x * 0.99, greenSquare.acceleration.y * 0.99);

// Check whether the green square ever moves off the screen
// If so, reverse acceleration in that direction
if (greenSquare.x < 0 || greenSquare.x > app.screen.width - 100)
{
greenSquare.acceleration.x = -greenSquare.acceleration.x;
return new Point(impulse * vCollisionNorm.x, impulse * vCollisionNorm.y);
}

if (greenSquare.y < 0 || greenSquare.y > app.screen.height - 100)
// Calculate the distance between two given points
function distanceBetweenTwoPoints(p1, p2)
{
greenSquare.acceleration.y = -greenSquare.acceleration.y;
}
const a = p1.x - p2.x;
const b = p1.y - p2.y;

// If the green square pops out of the cordon, it pops back into the
// middle
if (
greenSquare.x < -30
|| greenSquare.x > app.screen.width + 30
|| greenSquare.y < -30
|| greenSquare.y > app.screen.height + 30
)
{
greenSquare.position.set((app.screen.width - 100) / 2, (app.screen.height - 100) / 2);
return Math.hypot(a, b);
}

// If the mouse is off screen, then don't update any further
if (app.screen.width > mouseCoords.x || mouseCoords.x > 0 || app.screen.height > mouseCoords.y || mouseCoords.y > 0)
{
// Get the red square's center point
const redSquareCenterPosition = new PIXI.Point(
redSquare.x + redSquare.width * 0.5,
redSquare.y + redSquare.height * 0.5,
);
// The green square we will knock about
const greenSquare = new Sprite(Texture.WHITE);

// Calculate the direction vector between the mouse pointer and
// the red square
const toMouseDirection = new PIXI.Point(
mouseCoords.x - redSquareCenterPosition.x,
mouseCoords.y - redSquareCenterPosition.y,
);
greenSquare.position.set((app.screen.width - 100) / 2, (app.screen.height - 100) / 2);
greenSquare.width = 100;
greenSquare.height = 100;
greenSquare.tint = 0x00ff00;
greenSquare.acceleration = new Point(0);
greenSquare.mass = 3;

// Use the above to figure out the angle that direction has
const angleToMouse = Math.atan2(toMouseDirection.y, toMouseDirection.x);
// The square you move around
const redSquare = new Sprite(Texture.WHITE);

// Figure out the speed the square should be travelling by, as a
// function of how far away from the mouse pointer the red square is
const distMouseRedSquare = distanceBetweenTwoPoints(mouseCoords, redSquareCenterPosition);
const redSpeed = distMouseRedSquare * movementSpeed;
redSquare.position.set(0, 0);
redSquare.width = 100;
redSquare.height = 100;
redSquare.tint = 0xff0000;
redSquare.acceleration = new Point(0);
redSquare.mass = 1;

// Calculate the acceleration of the red square
redSquare.acceleration.set(Math.cos(angleToMouse) * redSpeed, Math.sin(angleToMouse) * redSpeed);
}
const mouseCoords = { x: 0, y: 0 };

// If the two squares are colliding
if (testForAABB(greenSquare, redSquare))
app.stage.eventMode = 'static';
app.stage.hitArea = app.screen;
app.stage.on('mousemove', (event) =>
{
// Calculate the changes in acceleration that should be made between
// each square as a result of the collision
const collisionPush = collisionResponse(greenSquare, redSquare);
// Set the changes in acceleration for both squares

redSquare.acceleration.set(collisionPush.x * greenSquare.mass, collisionPush.y * greenSquare.mass);
greenSquare.acceleration.set(-(collisionPush.x * redSquare.mass), -(collisionPush.y * redSquare.mass));
}
mouseCoords.x = event.global.x;
mouseCoords.y = event.global.y;
});

greenSquare.x += greenSquare.acceleration.x * delta;
greenSquare.y += greenSquare.acceleration.y * delta;

redSquare.x += redSquare.acceleration.x * delta;
redSquare.y += redSquare.acceleration.y * delta;
});

// Add to stage
app.stage.addChild(redSquare, greenSquare);
// Listen for animate update
Ticker.shared.add((time) =>
{
const delta = time.deltaTime;

// Applied deacceleration for both squares, done by reducing the
// acceleration by 0.01% of the acceleration every loop
redSquare.acceleration.set(redSquare.acceleration.x * 0.99, redSquare.acceleration.y * 0.99);
greenSquare.acceleration.set(greenSquare.acceleration.x * 0.99, greenSquare.acceleration.y * 0.99);

// Check whether the green square ever moves off the screen
// If so, reverse acceleration in that direction
if (greenSquare.x < 0 || greenSquare.x > app.screen.width - 100)
{
greenSquare.acceleration.x = -greenSquare.acceleration.x;
}

if (greenSquare.y < 0 || greenSquare.y > app.screen.height - 100)
{
greenSquare.acceleration.y = -greenSquare.acceleration.y;
}

// If the green square pops out of the cordon, it pops back into the
// middle
if (
greenSquare.x < -30
|| greenSquare.x > app.screen.width + 30
|| greenSquare.y < -30
|| greenSquare.y > app.screen.height + 30
)
{
greenSquare.position.set((app.screen.width - 100) / 2, (app.screen.height - 100) / 2);
}

// If the mouse is off screen, then don't update any further
if (
app.screen.width > mouseCoords.x
|| mouseCoords.x > 0
|| app.screen.height > mouseCoords.y
|| mouseCoords.y > 0
)
{
// Get the red square's center point
const redSquareCenterPosition = new Point(
redSquare.x + redSquare.width * 0.5,
redSquare.y + redSquare.height * 0.5,
);

// Calculate the direction vector between the mouse pointer and
// the red square
const toMouseDirection = new Point(
mouseCoords.x - redSquareCenterPosition.x,
mouseCoords.y - redSquareCenterPosition.y,
);

// Use the above to figure out the angle that direction has
const angleToMouse = Math.atan2(toMouseDirection.y, toMouseDirection.x);

// Figure out the speed the square should be travelling by, as a
// function of how far away from the mouse pointer the red square is
const distMouseRedSquare = distanceBetweenTwoPoints(mouseCoords, redSquareCenterPosition);
const redSpeed = distMouseRedSquare * movementSpeed;

// Calculate the acceleration of the red square
redSquare.acceleration.set(Math.cos(angleToMouse) * redSpeed, Math.sin(angleToMouse) * redSpeed);
}

// If the two squares are colliding
if (testForAABB(greenSquare, redSquare))
{
// Calculate the changes in acceleration that should be made between
// each square as a result of the collision
const collisionPush = collisionResponse(greenSquare, redSquare);
// Set the changes in acceleration for both squares

redSquare.acceleration.set(collisionPush.x * greenSquare.mass, collisionPush.y * greenSquare.mass);
greenSquare.acceleration.set(-(collisionPush.x * redSquare.mass), -(collisionPush.y * redSquare.mass));
}

greenSquare.x += greenSquare.acceleration.x * delta;
greenSquare.y += greenSquare.acceleration.y * delta;

redSquare.x += redSquare.acceleration.x * delta;
redSquare.y += redSquare.acceleration.y * delta;
});

// Add to stage
app.stage.addChild(redSquare, greenSquare);
})();
Loading

0 comments on commit 265ba3c

Please sign in to comment.