I am creating a Pac-Man game using JavaScript and I am encountering an issue. I have been working on this project for some time now and I have reached a point where I am stuck.
I am trying to create the movement for Pac-Man, but I am having trouble making it so that Pac-Man does not go through the walls. I have tried using if statements to check if Pac-Man is colliding with a wall, but it is not working. I have also tried using a CGRectIntersectsRect function, but that has not worked either.
// Initialize Pac-Man's position and size
var pacManX = ...
var pacManY = ...
var pacManWidth = ...
var pacManHeight = ...
// Initialize the walls
let walls = [CGRect(x: ..., y: ..., width: ..., height: ...),
CGRect(x: ..., y: ..., width: ..., height: ...),
...]
// Function to check for collision between Pac-Man and walls
func checkCollision() {
let pacManRect = CGRect(x: pacManX, y: pacManY, width: pacManWidth, height: pacManHeight)
for wall in walls {
if pacManRect.intersects(wall) {
// Handle the collision (e.g., stop Pac-Man's movement)
}
}
}
// Call the collision detection function in the update loop
while true {
// Update Pac-Man's position
pacManX += ...
pacManY += ...
checkCollision()
}
Related
In my scenario, i create a ship according to player's preferences. The ship consists of the flag and the hull.
An example view
PROBLEM-1
Ship is an Arcade.Group and i want to prevent this group from going outside the borders of the world.
create(){
// Create a group for ship
this.shipGroup = this.physics.add.group()
// Add hull to shipGroup
this.shipGroup.create(400, 500, "1021")
// Add flag to shipGroup
const mainFlag = this.shipGroup.create(400, 500, "FA1")
mainFlag.setOrigin(0.5, 0.8)
// Set collision property to true of every object in shipGroup
this.shipGroup.children.each((item: any) =>
item.setCollideWorldBounds(true)
)
}
update(t: number, dt: number){
if (this.cursor.up.isDown) {
this.shipGroup.setVelocity(...)
}
else {
this.shipGroup.setVelocity(0, 0)
}
}
With this approach every object in group calculated seperately. After hitting the world boundary, the position of the objects is distorted.
PROBLEM-2
To avoid this i tried another approach. I add bounding box to group. Instead of check collision for every object, i will only check collision for bounding box.
create(){
// Create a group for ship
this.shipGroup = this.physics.add.group()
// Add bounding box for shipGroup
this.shipBox = this.shipGroup.create(400, 500, "bbox")
this.shipBox.setCollideWorldBounds(true)
this.shipBox.body.onWorldBounds = true
// Add hull to shipGroup
this.shipGroup.create(400, 500, "1021")
// Add flag to shipGroup
const mainFlag = this.shipGroup.create(400, 500, "FA1")
mainFlag.setOrigin(0.5, 0.8)
/*this.shipGroup.children.each((item: any) =>
item.setCollideWorldBounds(true)
)*/
}
update(t: number, dt: number){
if (this.cursor.up.isDown && !this.shipBox.body.checkWorldBounds()) {
this.shipGroup.setVelocity(...)
}
else {
this.shipGroup.setVelocity(0, 0)
}
}
The problem is checkWorldBounds() returns false even if shipBox hits world boundaries. But collision for shipBox is work.
checkWorldBounds()
Description: Checks for collisions between this Body and the world
boundary and separates them.
Returns: True if this Body is colliding with the world boundary.
How can i implement collision for group and world boundary?
P.S. : phaser version is 3.55.2
There are a few ways to solve/work around this issue, I personally would just use only one image why one physics-body (hull and flag combined) and just move that single image/texture, and switch the image, when needed.
That said, if you need to use the separate images, the easy way is to use a phaser container. (link to the documentation)
create a container
add the images to the container
set the size for the container (default size is width=0 height=0)
create a physics body for the container
done
A short demo:
document.body.style = 'margin:0;';
var config = {
type: Phaser.AUTO,
width: 536,
height: 183,
physics: {
default: 'arcade',
arcade: {
gravity:{ y: 0 },
debug: true
}
},
scene: {
create
},
banner: false
};
function create () {
this.add.text(10,10, 'Ship with physics')
.setScale(1.5)
.setOrigin(0)
.setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
let graphics = this.make.graphics();
graphics.fillStyle(0xffffff);
graphics.fillRect(0, 0, 10, 40);
graphics.generateTexture('ship', 10, 40);
graphics.fillStyle(0xff0000);
graphics.fillRect(0, 0, 30, 10);
graphics.generateTexture('flag', 30, 10);
graphics.generateTexture('flag2', 20, 6);
let hull = this.add.image(0, 0, 'ship')
let flag = this.add.image(0, -5, 'flag')
let flag2 = this.add.image(0, 10, 'flag2')
this.ship = this.add.container(100, 80, [ hull, flag, flag2]);
this.ship.setAngle(-90)
this.ship.setSize(40, 30)
this.physics.world.enable(this.ship);
this.ship.body.setVelocity(100, 0).setBounce(1, 1).setCollideWorldBounds(true);
}
new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>
Info: this demo is based partly from this official example
Is it possible to create a single gravity / force point in matter.js that is at the center of x/y coordinates?
I have managed to do it with d3.js but wanted to enquire about matter.js as it has the ability to use multiple polyshapes.
http://bl.ocks.org/mbostock/1021841
The illustrious answer has arisen:
not sure if there is any interest in this. I'm a fan of what you have created. In my latest project, I used matter-js but I needed elements to gravitate to a specific point, rather than into a general direction. That was very easily accomplished. I was wondering if you are interested in that feature as well, it would not break anything.
All one has to do is setting engine.world.gravity.isPoint = true and then the gravity vector is used as point, rather than a direction. One might set:
engine.world.gravity.x = 355;
engine.world.gravity.y = 125;
engine.world.gravity.isPoint = true;
and all objects will gravitate to that point.
If this is not within the scope of this engine, I understand. Either way, thanks for the great work.
You can do this with the matter-attractors plugin. Here's their basic example:
Matter.use(
'matter-attractors' // PLUGIN_NAME
);
var Engine = Matter.Engine,
Events = Matter.Events,
Runner = Matter.Runner,
Render = Matter.Render,
World = Matter.World,
Body = Matter.Body,
Mouse = Matter.Mouse,
Common = Matter.Common,
Bodies = Matter.Bodies;
// create engine
var engine = Engine.create();
// create renderer
var render = Render.create({
element: document.body,
engine: engine,
options: {
width: Math.min(document.documentElement.clientWidth, 1024),
height: Math.min(document.documentElement.clientHeight, 1024),
wireframes: false
}
});
// create runner
var runner = Runner.create();
Runner.run(runner, engine);
Render.run(render);
// create demo scene
var world = engine.world;
world.gravity.scale = 0;
// create a body with an attractor
var attractiveBody = Bodies.circle(
render.options.width / 2,
render.options.height / 2,
50,
{
isStatic: true,
// example of an attractor function that
// returns a force vector that applies to bodyB
plugin: {
attractors: [
function(bodyA, bodyB) {
return {
x: (bodyA.position.x - bodyB.position.x) * 1e-6,
y: (bodyA.position.y - bodyB.position.y) * 1e-6,
};
}
]
}
});
World.add(world, attractiveBody);
// add some bodies that to be attracted
for (var i = 0; i < 150; i += 1) {
var body = Bodies.polygon(
Common.random(0, render.options.width),
Common.random(0, render.options.height),
Common.random(1, 5),
Common.random() > 0.9 ? Common.random(15, 25) : Common.random(5, 10)
);
World.add(world, body);
}
// add mouse control
var mouse = Mouse.create(render.canvas);
Events.on(engine, 'afterUpdate', function() {
if (!mouse.position.x) {
return;
}
// smoothly move the attractor body towards the mouse
Body.translate(attractiveBody, {
x: (mouse.position.x - attractiveBody.position.x) * 0.25,
y: (mouse.position.y - attractiveBody.position.y) * 0.25
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.12.0/matter.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/matter-attractors#0.1.6/build/matter-attractors.min.js"></script>
Historical note: the "gravity point" functionality was proposed as a feature in MJS as PR #132 but it was closed, with the author of MJS (liabru) offering the matter-attractors plugin as an alternate. At the time of writing, this answer misleadingly seems to indicate that functionality from the PR was in fact merged.
Unfortunately, the attractors library is 6 years outdated at the time of writing and raises a warning when using a newer version of MJS than 0.12.0. From discussion in issue #11, it sounds like it's OK to ignore the warning and use this plugin with, for example, 0.18.0. Here's the warning:
matter-js: Plugin.use: matter-attractors#0.1.4 is for matter-js#^0.12.0 but installed on matter-js#0.18.0.
Behavior seemed fine on cursory glance, but I'll keep 0.12.0 in the above example to silence it anyway. If you do update to a recent version, note that Matter.World is deprecated and should be replaced with Matter.Composite and engine.gravity.
The goal of my project is to make a tree planting game. When the game starts it should already have say, 10 trees in random positions as a starting point. Then, the duck can plant trees via moving with the cursor and planting with the spacebar. Every 1 second that passes, i want a random number of trees between 5-15 inclusive to destruct on their own. There will be a counter for the number of trees currently on screen and it updates every second. Game over when it hits 0.
Here is what I have so far/planning on implementing:
Counter for the trees
Duck moving and planting on canvas
Here is what I'm having trouble with:
Getting the game to already start off with 10 trees.
I am getting an error message that says that onEvent() method is not defined when it seems like it is in the code for destroying trees.
Here is my code so far, trying to implement the destruction of trees and I do not know how to instantiate the initial 10 trees :( :
As you can see, I've already tried fix the onEvent not defined error by putting it before i call the method but im still recieving the same error.
class Scene2 extends Phaser.Scene{
constructor(){
super("playGame");
}
//var timedEvent;
onEvent(){
for(var i = 0; i<2; i++){
var tree = this.projectiles.getChildren()[i];
tree.update();
}
}
create(){
this.grass = this.add.tileSprite(0,0,config.width,config.height,'grass').setOrigin(0,0);
//maybe add loops (and some updated sprites) for animals to move in place. i can learn that from one of gamedev acad's tutorials.
this.ella = this.add.sprite(200, 400, "ella"); // later do random spots
this.ella.play("ella_anim");
this.ella.setScale(.45);
this.tiger = this.add.sprite(500, 200, "tiger"); // later do random spots
this.tiger.play("tiger_anim");
this.tiger.setScale(.4);
this.monkey = this.add.sprite(100, 100, "monkey"); // later do random spots
this.monkey.play("monkey_anim");
this.monkey.setScale(.4);
this.duck =this.physics.add.sprite(200,300, "duck");
var follower = this.duck.setDepth(100);
follower.play("duck_anim");
follower.setScale(.6);
this.input.on('pointermove', function(pointer)
{
this.physics.moveToObject(follower, pointer, 240);
},this);
follower.setCollideWorldBounds(true);
//follower.setScale(.5);
this.add.text(20,20, "Playing game", {font: "25px Arial", fill: "yellow"});
this.spacebar = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE);
var timedEvent = this.time.addEvent({ delay: 1000, callback: onEvent, callbackScope: this, loop: true });
this.projectiles = this.add.group(); //holds all the trees
}
update(){
text.setText('Event.progress: ' + timedEvent.getProgress().toString().substr(0, 4));
if(Phaser.Input.Keyboard.JustDown(this.spacebar)){
this.plantTree();
}
}
plantTree(){
var tree = new Tree(this).setScale(.2);
}
}
This is the tree class:
class Tree extends Phaser.GameObjects.Sprite{
constructor(scene,place){
var x = scene.duck.x;
var y = scene.duck.y;
super(scene,x,y, "tree");
scene.add.existing(this);
}
update(){
this.destroy();
}
}
I'm fairly new to Phaser. Pls let me know if you know the answer to how to instantiate trees in the game initially and how to fix the error with onEvent. Thanks.
Error is:
Uncaught ReferenceError: onEvent is not defined
at Scene2.create (Scene2.js:44)
at initialize.create (phaser.min.js:1)
at initialize.bootScene (phaser.min.js:1)
at initialize.start (phaser.min.js:1)
at initialize.processQueue (phaser.min.js:1)
at initialize.update (phaser.min.js:1)
at initialize.step (phaser.min.js:1)
at initialize.step (phaser.min.js:1)
at e (phaser.min.js:1)
I'm working on a project and I need to add 3d sounds effects, like the sound is continually moving around the listener effects. Is it possible to achieve that with howlerjs i see that with howler i'm able to play a sound from specific coordinates/orientation but how to achieve surrounding/ambisonics sounds ?
Or another library in JavaScript to achieve that?
Thanks for your help.
Half a year late, but yeah that's entirely possible in howler.js, haven't used it myself but judging from the docs you can just update the position. there's some more libraries that do it that I've found, check here how 3dage does exactly what you want:
https://codepen.io/naugtur/pen/QgmvOB?editors=1010
var world = IIIdage.World({
tickInterval: 200
})
var annoyingFly = IIIdage.Thing({
is: ['fly'],
sounds: {
'buzzing constantly': {
sound: 'buzz',
times: Infinity
}
},
reacts: [
{
// to: world.random.veryOften(),
to: world.time.once(),
with: 'buzzing constantly'
}
]
})
// scene should create and expose a default world or accept one
var scene = IIIdage.Scene({
title: 'Annoying fly',
library: {
sounds: {
'buzz': {
src: ['https://webaudiogaming.github.io/3dage/fly.mp3']
}
}
},
world: world,
things: [ // scene iterates all things and spawns them into the world. same can be done manually later on.
annoyingFly({
pos: [-1, -15, 0],
dir: [1, 0, 0],
v: 1
})
]
}).load().run()
setTimeout(function () {
scene.dev.trace(IIIdage.dev.preview.dom())
}, 500)
setInterval(function rotateVector() {
var angleRad = 0.15
var d=scene.things[0].attributes.dir
var x=d[0], y=d[1]
var cosAngle = Math.cos(angleRad), sinAngle = Math.sin(angleRad)
scene.things[0].attributes.dir = [x * cosAngle - y * sinAngle, y * cosAngle + x * sinAngle, 0]
}, 500)
window.scene = scene
There's still some others that do similar stuff:
https://www.npmjs.com/package/songbird-audio
https://www.npmjs.com/package/ambisonics
Hope this pushes you in the right direction if you still want help with it.
I wanted to know how to have a Aframe Component for any entity that define if the entity is seen by the camera, like a bool attribute.
"isSeen"= true || false
I tried with trigonometry (knowing the rotation of the camera, and the Entities' positions), but I failed.
How about frustums: checking out if a point(x, y ,z) is within the camera's field of view .
The code is quite simple. To use it within a-frame, You could create a component, which will check if the point is seen on each render loop:
AFRAME.registerComponent('foo', {
tick: function() {
if (this.el.sceneEl.camera) {
var cam = this.el.sceneEl.camera
var frustum = new THREE.Frustum();
frustum.setFromMatrix(new THREE.Matrix4().multiplyMatrices(cam.projectionMatrix,
cam.matrixWorldInverse));
// Your 3d point to check
var pos = new THREE.Vector3(x, y, z);
if (frustum.containsPoint(pos)) {
// Do something with the position...
}
}
}
}
Check it out in my fiddle