// Cloned by Adam Gray on 11 Nov 2022 from World "New World" by Niall Kelly
// Please leave this clone trail here.
var start_r = 100 //camera start pos
var max_r = 500 // Max render distance
var p1score = 0;
var p2score = 0;
var max_targets = 3;
var alltargets = new Array(0); // array of all targets currently in play
const mixers = [];
const animClock = new THREE.Clock();
const gameClock = new THREE.Clock();
var bird;
var hitbox;
const SKYBOX_ARRAY = [
"/uploads/kellyn88/sbleft.jpg", // left
"/uploads/kellyn88/sbr.png", // right
"/uploads/kellyn88/test.png",
"/uploads/kellyn88/skybox_base.png", //base
"/uploads/kellyn88/test.png",
"/uploads/kellyn88/test.png"
];
var gridSetup = [
[-160, -100, 70], [-80, -100, 70], [0, -100, 70], [80, -100, 70], [160, -100, 70],
[-160, -100, -10], [-80, -100, -10], [0, -100, -10], [80, -100, -10], [160, -100, -10], // Layout of poosible target spawn positions
[-160, -100, -90], [-80, -100, -90], [0, -100, -90], [80, -100, -90], [160, -100, -90]
]
// !!!BACKGROUND SOUND UNCOMMENT WHEN DONE!!!
// const MUSICFILE = '/uploads/kellyn88/ambience.mp3';
// AB.backgroundMusic ( MUSICFILE );
const shoot_short = "uploads/kellyn88/shoot_short.wav";
const shoot_long = "uploads/kellyn88/shoot_long.wav";
AB.newSplash ( splashScreen() );
AB.world.newRun = function()
{
// Code for Three.js initial drawing of objects.
// Should include one of:
// ABWorld.init2d ( arguments );
if (AB.onMobile()){
start_r = 500;
max_r = 1000;
loadBird();
}
AB.socketStart();
initScene();
AB.runReady = false;
cameraControls();
};
function initScene(){
var color = new THREE.Color();
ABWorld.init2d ( start_r, max_r, color );
ABWorld.scene.background = new THREE.CubeTextureLoader().load ( SKYBOX_ARRAY );
var light = new THREE.AmbientLight("white", 0.8);
ABWorld.scene.add(light);
};
AB.world.nextStep = function()
{
if (alltargets.length < max_targets){
spawnTarget();
wait(100);
}
if(AB.socket){
if(AB.socket.connected){
AB.socketOut(p1score)
AB.msg("P1 Score = " + p1score + " P2 score = " + p2score);
}
}
if(bird){
if(bird.pos.x(-(start_r / 5))){
ABWorld.scene.remove(bird) && ABWorld.scene.remove(hitbox);
bird = null;
}
else{
anim_bird() && bird.translateY(-0.5) && hitbox.translateX(-0.5);
}
}
else{
var t = gameClock.getElapsedTime();
console.log(t);
if (t >= 1){
var randomIndex = Math.floor(Math.random() * 50);
if(randomIndex == 25){
loadBird();
gameClock.start();
}
}
}
};
function spawnTarget(){
var texture = new THREE.TextureLoader().load("/uploads/kellyn88/target.png");
var shape = new THREE.CylinderGeometry(30, 30, 5, 32);
var cover = new THREE.MeshBasicMaterial({map: texture});
var target = new THREE.Mesh(shape, cover);
var randomIndex = Math.floor(Math.random() * gridSetup.length);
var item = gridSetup[randomIndex];
target.position.set(item[0], item[1], item[2]); // Select Random spaen location
ABWorld.scene.add(target);
gridSetup.splice(randomIndex, 1);
alltargets.push(target);
}
function loadHitbox(pos){
var shape = new THREE.BoxGeometry(2, 2, 0.5);
var cover = new THREE.MeshBasicMaterial(0xfff);
var target = new THREE.Mesh(shape, cover);
max_targets = 4;
target.visible = true;
target.name = "bird";
target.position.set(pos.x, pos.y, pos.z - 0.1);
ABWorld.scene.add(target);
hitbox = target;
alltargets.push(target);
console.log (alltargets);
}
function cameraControls()
{
ABHandler.initTouchDrag = mouseClick; // Mobile controls, will change if I have time.
ABHandler.touchDrag = mouseDrag;
ABHandler.touchZoom = mouseZoom;
ABHandler.initMouseDrag = mouseClick;
ABHandler.mouseDrag = mouseDrag;
ABHandler.mouseZoom = mouseZoom;
}
function mouseClick(x, y)
{
audioHandler("shoot");
targetHit(x, y);
return;
}
function mouseDrag(x, y){
return;
}
function mouseZoom(x){
return;
}
function targetHit(x, y)
{
if(alltargets.length > 0){
for (var i = 0; i < alltargets.length; i++){
var target = alltargets[i];
if ( ABWorld.hitsObject ( x, y, target )){
if (target.name != "bird"){
var pos = [target.position.x, target.position.y, target.position.z];
gridSetup.push(pos);
ABWorld.scene.remove(target);
alltargets.splice(i, 1);
p1score++;
}
else{
console.log("bird hit");
ABWorld.scene.remove(bird) && ABWorld.scene.remove(target);
bird = null;
alltargets.splice(i, 1);
max_targets = 3;
p1score = p1score + 20;
}
break;
}
}
}
return;
}
function wait(ms) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > ms){
break;
}
}
}
function audioHandler(instance){
if (instance == "shoot"){
var a = new Audio( shoot_long );
a.play();
}
}
function loadBird()
{
const loader = new THREE.GLTFLoader();
const onLoad = ( gltf, position ) =>
{
const model = gltf.scene.children[ 0 ];
model.position.copy( position );
const animation = gltf.animations[ 0 ];
const mixer = new THREE.AnimationMixer( model );
mixers.push( mixer );
const action = mixer.clipAction( animation );
action.play()
model.rotation.set( 0, Math.PI, Math.PI / 2);
loadHitbox(position);
ABWorld.scene.add( model );
bird = model;
};
const birdpos = new THREE.Vector3 ((start_r / 5), (start_r - (start_r * 0.1)), 0);
// can load 3D models of other user:
loader.load ( '/uploads/kellyn88/simple_bird.glb', gltf => onLoad ( gltf, birdpos ) );
}
function anim_bird(){
const delta = animClock.getDelta();
mixers.forEach( ( mixer ) => { mixer.update( delta ); } );
}
AB.world.endRun = function()
{
};
function splashScreen() // HTML format string of instructions for splash screen
{
var s = "Shoot targets as they appear to earn points.\n\n";
if ( AB.onDesktop() ) s = s + " Desktop instructions: Use your mouse to aim and click to shoot.\n\n" ;
else s = s + " Mobile instructions: Tap to shoot.\n\n" ;
s = s + "1 point is awarded for each target destroyed. Keep an eye out for ducks. They are more difficult to hit but are worth 10 points. Earn more points than your opponent to win!";
return ( s );
}
AB.splashClick ( function ()
{
AB.runReady = true;
AB.removeSplash(); // remove splash screen
});
AB.socketIn = function (s){
p2score = s
}
AB.socketUserlist = function ( array ) {
console.log(array.length);
};