Hello. I’m trying to implement the ray casting system in my FPS game for the shooting mechanic. I previously used rigidbody and realized that it’s not an ideal system for shooting bullets in a FPS game. So after some research and asking around, this is the current state of my script:
var Gun = pc.createScript('gun');
Gun.attributes.add('maxAmmo', { type: 'number' });
Gun.attributes.add('magazineSize', { type: 'number', default: 30 });
Gun.attributes.add('bullet', { type: 'entity' });
Gun.attributes.add('gunpower', { type: 'number', default: 1 });
Gun.attributes.add('bulletCount', { type: 'entity' });
Gun.attributes.add('currentAmmo', { type: 'number' });
Gun.attributes.add('reloadTime', { type: 'number', default: 2 });
Gun.attributes.add('reloadText', { type: 'entity' });
Gun.attributes.add('cameraEntity', { type: 'entity' });
// initialize code called once per entity
Gun.prototype.initialize = function () {
this.currentAmmo = this.maxAmmo;
this.isReloading = false;
//this.setMouse();
this.app.mouse.on(pc.EVENT_MOUSEDOWN, this.setMouse, this);
};
// update code called every frame
Gun.prototype.update = function (dt) {
this.setKeyboard();
this.bulletCount.element.text = this.currentAmmo + '/' + this.magazineSize;
};
Gun.prototype.ammoAmount = function (currentWeaponAmmo, currentWeaponMaxAmmo) {
this.currentAmmo = currentWeaponAmmo;
this.maxAmmo = currentWeaponMaxAmmo;
};
Gun.prototype.setMouse = function (event) {
var app = this.app;
app.mouse.on("mousedown", function () {
app.mouse.enablePointerLock();
if (this.app.mouse.isPressed(pc.MOUSEBUTTON_LEFT)) {
if (this.entity.enabled) {
this.shoot();
}
}
}, this);
};
Gun.prototype.setKeyboard = function (dt) {
var app = this.app;
if (app.keyboard.isPressed(pc.KEY_R)) {
this.Reload();
}
if (this.currentAmmo == 0) {
this.reloadText.element.text = 'Reload';
}
else {
this.reloadText.element.text = null;
}
};
Gun.prototype.shoot = function (screenPosition) {
this.isReloading = false;
if (this.currentAmmo == 0) {
console.log("out of ammo");
return false;
}
var from = this.cameraEntity.getPosition();
var to = this.cameraEntity.camera.screenToWorld(screenPosition.x, screenPosition.y, this.cameraEntity.camera.farClip);
var result = this.app.systems.rigidbody.raycastFirst(from, to);
// // Clone the bullet as specified by the attribute
// var bullet = this.bullet.clone();
// // Add it to the game
// this.app.root.addChild(bullet);
// var player = this.entity;
// var target = this.entity.findByName('target');
// // Its force is in the direction the player is facing
// this.force = new pc.Vec3();
// this.force.copy(target.forward);
// this.force.copy(target.forward);
// this.force.scale(this.gunpower);
// console.log(target);
// var pos = target.getPosition();
// var direction = target.forward;
// // Add it a little further if the player is already going fast
// // pos.add(direction.scale(5 + gun.rigidbody.linearVelocity.length() * 0.01));
// bullet.setPosition(pos);
// bullet.setPosition(pos);
// // var bulletRotation = player.getRotation();
// // bullet.setRotation( bulletRotation );
// // bullet.rotateLocal(90,0,0);
// bullet.enabled = true; //Must enable after setting position!
// bullet.rigidbody.applyImpulse(this.force);
this.currentAmmo--;
this.bulletCount.element.text = this.currentAmmo + '/' + this.magazineSize;
};
Gun.prototype.Reload = function () {
//
if (this.currentAmmo == this.maxAmmo) {
return false;
}
//
isReloading = true;
this.currentAmmo = this.maxAmmo;
this.bulletCount.element.text = this.currentAmmo + '/' + this.magazineSize;
/*if (this.magazineSize >= this.maxAmmo) {
this.currentAmmo = this.maxAmmo;
this.magazineSize -= this.maxAmmo;
} else {
this.currentAmmo = this.magazineSize;
this.magazineSize = 0;
}
this.isReloading = false;*/
};
When i launch the game, i get this error message: " Uncaught TypeError: Cannot read properties of undefined (reading ‘x’)"
I learned that this issue has something to do with the mouse event but i couldn’t pinpoint what it exactly is despite my research. I checked couple of examples of ray casting on PC but each of them uses a different method so i’m confused about what to do. I would appreciate any help for this. Thanks in advance
@Ronin This is the typical procedure I use in all my scripts for shooting.
// initialize code called once per entity
GunShoot.prototype.initialize = function() {
// Event for mouse button left fire
this.app.mouse.on(pc.EVENT_MOUSEDOWN, this.mouseDown, this);
};
// Handle mouse down event
GunShoot.prototype.mouseDown = function(e) {
// Check for Mouse left button
if(this.entity.enabled && e.button == pc.MOUSEBUTTON_LEFT) {
// Process action
this.shoot();
}
};
// handle shooting and raycast
GunShoot.prototype.shoot = function(e) {
// Get center of screen
var centerScreenX = this.app.graphicsDevice.width / 2;
var centerScreenY = this.app.graphicsDevice.height / 2;
//Get start and end point
var start = this.camera.camera.screenToWorld(centerScreenX, centerScreenY, this.camera.camera.nearClip);
var end = this.camera.camera.screenToWorld(centerScreenX, centerScreenY, this.camera.camera.farClip);
// raycast between the two points and return the closest hit result
var result = this.app.systems.rigidbody.raycastFirst(start, end);
// Play and reset muzzle flash
this.muzzleFx.particlesystem.play();
this.muzzleFx.particlesystem.reset();
if(this.entity.sound != null) {
// Play this weapons sound
this.entity.sound.play("fire");
}
// We hit something with collision
if(result) {
console.log("You Hit: " + result.entity.name);
this.handleImpact(result.entity,result.point,result.normal);
} else {
console.log("Nothing Hit");
}
};
I am not sure what is going on with the snippet above. You are calling setMouse to enablePointerLock and then after the entity.enable you fire shoot. Is there a reason for this method that I am missing? The reason for your error is probably not getting the screen center “.x” before using the screenToWorld(); The shoot function never passes this info. it’s empty. Please have a look to this.
“You are calling setMouse to enablePointerLock” setMouse is the function which handles everything about the mouse actions that’s why enablePointerLock is there. “then after the entity.enable you fire shoot.” this part is complicated to explain, you need to see the project to understand. It’s a solution to decrement the ammo amount of each weapon seperately when they shoot. After i posted this topic, i made this change in the initialize function:
and i stopped getting any errors but i don’t know if it’s working either. Also after that change i can only move the camera when i hold the left mouse button. Any idea why?
“Are you now getting your to/from from inside the shoot function?” it was there before, you must’ve overlooked that part:
var from = this.cameraEntity.getPosition();
var to = this.cameraEntity.camera.screenToWorld(screenPosition.x, screenPosition.y, this.cameraEntity.camera.farClip);
var result = this.app.systems.rigidbody.raycastFirst(from, to);
i did it the same way you do. only difference is i don’t have this in my shoot script
var centerScreenX = this.app.graphicsDevice.width / 2;
var centerScreenY = this.app.graphicsDevice.height / 2;
i looked at different examples, in non of them they defined the centerScreenX and centerScreenY. Maybe i need to do it. But i want to test it if it works first and fix the mouse movement
@Ronin You still have the app.mouse.enablePointerLock(); In this setMouse function. Nothing will happen until you do this. It’s on your left mouse click. Plus, the error is still present.
Gun.prototype.setMouse = function (event) {
var app = this.app;
if (this.app.mouse.isPressed(pc.MOUSEBUTTON_LEFT)) {
if (this.entity.enabled) {
this.shoot();
}
}
};
and call it in the init. Mouse movement is still broken