ゲーム プログラミング

ショーモナイノ/ ソースコード(サーバーサイド)

投稿日:2021年9月1日 更新日:

ショーモナイノのコードを公開していないかとのお問い合わせを頂きました。GitHubでの公開を検討しましたが、書き散らかした粗末なコードをGitHubに置くべきではないと判断しました。代わりに自分のブログに載せるなら迷惑にならないと思い、ここで公開する事にしました。
ざっと見返してみるとテンプレートから改良を加えていったために苦しい構造になってしまった印象です。もしフォートナイトを忠実に再現したければ、このコードを参考に一から作成し直すことをお勧めします。
私はここで力尽きてしまいましたが、若くエネルギーの溢れている誰かが「編集機能」などを追加してより良いものを作ってくれたら嬉しく思います。

※コードに関する質問は一切受け付けません。バグも多いに含まれているでしょう。全て自己解決して下さい。

【コード概要】
1〜30行:初期化、変数設定など
36〜151行:Gameオブジェクトクラス定義、サンプル流用
153〜209行:壁作成関数
211〜649行:プレイヤークラス定義
651〜670行:弾丸クラス定義
672〜764行:ボットプレイヤークラス定義
766〜792行:壁クラス定義
794〜820行:階段クラス定義
824〜840行:岩クラス定義(壊れない)
842〜852行:包帯クラス定義(体力回復アイテム)
854〜864行:ポーションクラス定義(シールド回復アイテム)
866〜871行:ストームクラス定義
887〜894行:変数初期化
913〜957行:岩生成関数
961〜973行:包帯生成関数
975〜987行:ポーション生成関数
989〜997行:ボット生成関数
1002〜1008行:ストーム設定関数
1010〜1052行:弾丸と壁の接触判定関数
1055〜1112行:弾丸とプレイヤーの接触判定関数
1115〜1215行:弾丸と岩の接触判定関数
1218〜1333行:socket関連
1346〜1717行:毎フレームの処理
1720〜1733行:app,server設定

sever.js

'use strict';

const express = require('express');
const http = require('http');
const path = require('path');
const socketIO = require('socket.io');
const app = express();
const server = http.Server(app);
const io = socketIO(server);
const yargs = require('yargs').argv;
const PORT = process.env.PORT || 7000;

const FIELD_SC = 32;
const FIELD_WIDTH = 1000*FIELD_SC, FIELD_HEIGHT = 1000*FIELD_SC;
const START_TALL = 1000 * 4;
var mFieldGridSize = 250;
var mBulletSize = 6;
var mBulletSpeed = mFieldGridSize * 1.0;
var mBulletLength = mBulletSpeed*1.0;
var mPlayerSpeed = 10;
var mPlayerTurnSpeed = 0.05;
var mPlayerTall = 100;
var mWallSize = mFieldGridSize;
var mWallThick = 25 * 1.0;
var mShootCycle = [6,30,60]; //AR,SG,S
var mMagagineSize = [30,8,1];
var mJumpHight = mWallSize *1.2;
var mJumpFrame = 40;
var mBandageSize = 20;
var mFallSpeed = 15;

function mFloorGS(v_){ //floor to grid size
    return Math.floor(v_/mFieldGridSize) * mFieldGridSize;
}

class GameObject{
    constructor(obj={}){
        this.id = Math.floor(Math.random()*1000000000);
        this.x = obj.x;
        this.y = obj.y;
        this.z = obj.z; //
        this.width = obj.width;
        this.height = obj.height;
        this.tall = obj.tall;
        this.angle = obj.angle;
        this.angle2 = obj.angle2;
        this.isMoving = 0;
        this.isSquat = 0;
    }
    move3(distance){ //for bullet
        const oldX = this.x, oldY = this.y, oldZ = this.z;
        this.isMoving = 1;

        var d1_ = distance * Math.sin(-this.angle2);
        var d2_ = distance * Math.cos(this.angle2);
        this.z += d1_;
        this.x += d2_ * Math.cos(this.angle);
        this.y += d2_ * Math.sin(this.angle);
        
        let collision = false;
        if(this.x < 0 || this.x + this.width >= FIELD_WIDTH || this.y < 0 || this.y + this.height >= FIELD_HEIGHT || this.z < 0 || this.z > FIELD_WIDTH){
            collision = true;
        }
        // if(this.intersectWalls()){
        //     collision = true;
        // }
        if(collision){
            this.x = oldX; this.y = oldY; this.z = oldZ;
        }
        return !collision;
    }    
    move(distance){
        const oldX = this.x, oldY = this.y;
        this.isMoving = 1;

        this.x += distance * Math.cos(this.angle);
        this.y += distance * Math.sin(this.angle);
        
        let collision = false;
        if(this.x < 0 || this.x + this.width >= FIELD_WIDTH || this.y < 0 || this.y + this.height >= FIELD_HEIGHT){
            collision = true;
        }
        // if(this.intersectWalls()){
        //     collision = true;
        // }
        if(collision){
            this.x = oldX; this.y = oldY;
        }
        return !collision;
    }
    side(distance){
        const oldX = this.x, oldY = this.y;
        this.isMoving = 1;
        
        this.x += distance * Math.cos(this.angle+3.1415/2);
        this.y += distance * Math.sin(this.angle+3.1415/2);
        
        let collision = false;
        if(this.x < 0 || this.x + this.width >= FIELD_WIDTH || this.y < 0 || this.y + this.height >= FIELD_HEIGHT){
            collision = true;
        }
        // if(this.intersectWalls()){
        //     collision = true;
        // }
        if(collision){
            this.x = oldX; this.y = oldY;
        }
        return !collision;
    }
    intersect(obj){
        return (this.x <= obj.x + obj.width) &&
            (this.x + this.width >= obj.x) &&
            (this.y <= obj.y + obj.height) &&
            (this.y + this.height >= obj.y) &&
            (this.z <= obj.z + obj.tall - obj.tall/2*obj.isSquat) &&
            (this.z + this.tall - this.tall/2*this.isSquat >= obj.z) ;
    }
    intersectXY(obj){ //wall
        return (this.x <= obj.x + obj.width) &&
            (this.x  >= obj.x) &&
            (this.y <= obj.y + obj.height) &&
            (this.y >= obj.y) &&
            (this.z <=obj.z + obj.tall * 0.9 )  &&
            (this.z + this.tall - this.tall/2*this.isSquat>=obj.z) ;
    }
    intersectZu(obj){ //wall
        return (this.x <= obj.x + obj.width) &&
        (this.x + this.width >= obj.x) &&
        (this.y <= obj.y + obj.height) &&
        (this.y + this.height >= obj.y) &&
        (this.z <= obj.z + obj.tall) &&
        (this.z >= obj.z + obj.tall - mWallThick*0.99) ;
    }
    intersectSlopeZ(obj){ //wall
        return (this.x <= obj.x + mFieldGridSize) &&
            (this.x >= obj.x) &&
            (this.y <= obj.y + mFieldGridSize) &&
            (this.y >= obj.y) &&
            (this.z <=obj.z + mFieldGridSize/2 )  &&
            (this.z >=obj.z-mFieldGridSize/2 -mWallThick) ;
    }
    intersectWalls(){
        return Object.values(walls).some((wall) => this.intersect(wall));
    }
    intersectRocks(){
        return Object.values(rocks).some((rock) => this.intersect(rock));
    }
    toJSON(){
        return {id: this.id, x: this.x, y: this.y, z: this.z, width: this.width, height: this.height, tall:this.tall , angle: this.angle, angle2: this.angle2, isMoving: this.isMoving};
    }
}

function mCreateWall(px,py,pz,pw,pa)
{
    console.log('mCreateWall()');

    const wall = new Wall({
        x: px,
        y: py,
        z: pz,
        width: mWallSize,
        height: mWallThick,
        tall: mWallSize,
    });
    wall.angle = pa; //this.angle; // + 3.1415/2;
    wall.angle = Math.floor( (wall.angle+3.1415/4) / (3.1415/2)) * 3.1415/2;
    wall.angle2 = 0;
    
    // player geo center
    var x_ = px + pw/2 * Math.cos(pa);
    var y_ = py + pw/2 * Math.sin(pa);

    wall.x = mFloorGS(x_);   //Math.floor(x_/mFieldGridSize)*mFieldGridSize;
    wall.y = mFloorGS(y_);   //Math.floor(y_/mFieldGridSize)*mFieldGridSize;
    wall.z = mFloorGS(pz);

    wall.x += mFieldGridSize * Math.cos(wall.angle);
    wall.y += mFieldGridSize * Math.sin(wall.angle);
    if( (wall.angle==0) || (wall.angle==3.1415*2) ){
        //console.log('pos:'+x_+','+y_+' wall:'+wall.x+','+wall.y);
        if( x_+this.width/2>=wall.x ){
            wall.x += mFieldGridSize;
        }
        wall.width = mWallThick;
        wall.height = mWallSize;
        //console.log('pos:'+x_+','+y_+' wall:'+wall.x+','+wall.y);
    }
    else if(wall.angle==3.1415){
        if( x_-this.width/2>=wall.x+mFieldGridSize ){
            wall.x += mFieldGridSize;
        }
        wall.width = mWallThick;
        wall.height = mWallSize;
    }
    else if(wall.angle==3.1415/2){
        if( y_+this.width/2>=wall.y ){
            wall.y += mFieldGridSize;
        }
    }
    else if(wall.angle==3.1415/2*3){
        if( y_-this.width/2>=wall.y+mFieldGridSize ){
            wall.y += mFieldGridSize;
        }
    }

    console.log('mCreateWall:'+wall.id);

    return wall;
}

class Player extends GameObject{
    constructor(obj={}){
        super(obj);
        this.socketId = obj.socketId;
        this.nickname = obj.nickname;
        this.width = 80;
        this.height = 80;
        this.tall = mPlayerTall; //original
        this.health = this.maxHealth = 100;
        this.shield = this.maxShield = 100;
        this.bullets = {};
        this.weapon = 1;
        this.point = 0;
        this.movement = {};
        this.shootCount = [0,0,0];
        this.isShoot = 0;
        this.isSquat = 0;
        this.timeCount = 0;
        this.shootTime = 0;
        this.giveDamage = 0;
        this.giveDamageTime = 0;
        this.isBot = 0;
        this.isGrounded = 1;
        this.isJump = 0;
        this.jumpTime = 0;
        this.jumpStartZ = 0;
        this.bandages = 0;
        this.potions = 0;
        this.isEmote = 0;
        this.mode = 0; // 0:falling, 1:shoot, 2:build
        this.buildTemp = null;
        this.buildType = 0; //0:wall, 1:floor
        this.inStorm = 0;

        do{
            this.x = Math.random() * (FIELD_WIDTH - this.width);
            this.y = Math.random() * (FIELD_HEIGHT - this.height);
            this.z = 0;//START_TALL;
            this.angle = Math.random() * 2 * Math.PI;
            this.angle2 = 0;
        }while( (this.intersectWalls()) && (this.intersectRocks())    );

        this.z = START_TALL;
    }
    shoot(){

        if(this.mode != 1 ){
            return;
        }

        const bullet = new Bullet({
            x: this.x + this.width/2 * Math.cos(this.angle),
            y: this.y + this.width/2 * Math.sin(this.angle),
            z: this.z + (this.tall -this.tall/2*this.isSquat )*0.7,
            angle: this.angle,
            angle: this.angle2,
            player: this,
            damageV: 20,
            // dx: Math.cos(this.angle2) * Math.cos(this.angle),
            // dy: Math.cos(this.angle2) * Math.sin(this.angle),
            // dz: Math.sin(this.angle2),
        });
        //console.log('bullet angle:'+bullet.angle+', '+bullet.angle2);
        bullet.dx = Math.cos(-this.angle2) * Math.cos(this.angle);
        bullet.dy = Math.cos(-this.angle2) * Math.sin(this.angle);
        bullet.dz = Math.sin(-this.angle2);

        //console.log('bullet d:'+bullet.dx+', '+bullet.dy+', '+bullet.dz);
        
        if(this.weapon==2){
            bullet.damageV = 50;
            bullet.height = mBulletSize*5;
            bullet.tall = mBulletSize*5;
        }
        else if(this.weapon==3){
            bullet.damageV = 120;
        }

        //bullet.move(this.width/2);
        //bullet.side(this.width/2*Math.cos(this.angle));
        this.bullets[bullet.id] = bullet;
        bullets[bullet.id] = bullet;

        //io.to(this.socketId).emit('shoot', this.weapon);
        //console.log('shoot from;'+this.socketId);
        io.sockets.emit('shoot',[this.socketId, this.weapon]);
    }
    funcWall(){
        const wall = new Wall({
            x: this.x,
            y: this.y,
            z: this.z,
            width: mWallSize,
            height: mWallThick,
            tall: mWallSize,
        });
        wall.angle = this.angle; // + 3.1415/2;
        //console.log('wall.angle:'+wall.angle);
        wall.angle = Math.floor( (wall.angle+3.1415/4) / (3.1415/2)) * 3.1415/2;
        wall.angle2 = 0;
        //console.log('wall.angle:'+wall.angle);

        // player geo center
        var x_ = this.x + this.width/2 * Math.cos(this.angle);
        var y_ = this.y + this.width/2 * Math.sin(this.angle);

        wall.x = mFloorGS(x_);   //Math.floor(x_/mFieldGridSize)*mFieldGridSize;
        wall.y = mFloorGS(y_);   //Math.floor(y_/mFieldGridSize)*mFieldGridSize;
        wall.z = mFloorGS(this.z);

        var dz_ =  this.z - mFloorGS(this.z);
        //console.log('dz_:'+dz_+', angle2:'+this.angle2);
        if( (dz_>mFieldGridSize/2) && (this.angle2<-3.1415/6) ){
            wall.z += mFieldGridSize;
        }

        wall.x += mFieldGridSize * Math.cos(wall.angle);
        wall.y += mFieldGridSize * Math.sin(wall.angle);

        wall.p1x = 0.0;
        wall.p1y = 0.0;
        wall.p1z = mFieldGridSize;
        wall.p2x = 0.0;
        wall.p2y = mFieldGridSize;
        wall.p2z = 0.0;

        if( (wall.angle==0) || (wall.angle==3.1415*2) ){
            //console.log('pos:'+x_+','+y_+' wall:'+wall.x+','+wall.y);
            if( x_+this.width/2>=wall.x ){
                wall.x += mFieldGridSize;
            }
            wall.width = mWallThick;
            wall.height = mWallSize;
            //console.log('pos:'+x_+','+y_+' wall:'+wall.x+','+wall.y);
        }
        else if(wall.angle==3.1415){
            if( x_-this.width/2>=wall.x+mFieldGridSize ){
                wall.x += mFieldGridSize;
            }
            wall.width = mWallThick;
            wall.height = mWallSize;
        }
        else if(wall.angle==3.1415/2){
            if( y_+this.width/2>=wall.y ){
                wall.y += mFieldGridSize;
            }
            wall.p2x = mFieldGridSize;
            wall.p2y = 0.0;
            wall.p2z = 0.0;    
        }
        else if(wall.angle==3.1415/2*3){
            if( y_-this.width/2>=wall.y+mFieldGridSize ){
                wall.y += mFieldGridSize;
            }
            wall.p2x = mFieldGridSize;
            wall.p2y = 0.0;
            wall.p2z = 0.0;    
        }

        wall.p0x = wall.x;
        wall.p0y = wall.y;
        wall.p0z = wall.z;

        return wall;
    }
    buildWall(){

        this.mode = 2;
        this.buildType = 0;

        this.buildTemp = this.funcWall();
    }
    funcFloor(){
        const wall = new Wall({
            x: this.x,
            y: this.y,
            z: this.z,
            width: mWallSize,
            height: mWallSize,
            tall: mWallThick,
        });
        wall.angle = this.angle; // + 3.1415/2;
        //console.log('wall.angle:'+wall.angle);
        wall.angle = Math.floor( (wall.angle+3.1415/4) / (3.1415/2)) * 3.1415/2;
        wall.angle2 = 0;
        //console.log('wall.angle:'+wall.angle);

        // player geo center
        var x_ = this.x + this.width/2 * Math.cos(this.angle);
        var y_ = this.y + this.width/2 * Math.sin(this.angle);

        wall.x = mFloorGS(x_);   //Math.floor(x_/mFieldGridSize)*mFieldGridSize;
        wall.y = mFloorGS(y_);   //Math.floor(y_/mFieldGridSize)*mFieldGridSize;
        wall.z = mFloorGS(this.z) - mWallThick;

        wall.x += mFieldGridSize * Math.cos(wall.angle);
        wall.y += mFieldGridSize * Math.sin(wall.angle);

        wall.p1x = mFieldGridSize;
        wall.p1y = 0.0;
        wall.p1z = 0.0;
        wall.p2x = 0.0;
        wall.p2y = mFieldGridSize;
        wall.p2z = 0.0;

        if( this.angle2<-3.1415/4 ){
            wall.z += mFieldGridSize;
        }

        if( (wall.angle==0) || (wall.angle==3.1415*2) ){
            //console.log('pos:'+x_+','+y_+' wall:'+wall.x+','+wall.y);
            if( x_+this.width/2>=wall.x ){
                wall.x += mFieldGridSize;
            }
            // wall.width = mWallThick;
            // wall.height = mWallSize;
            //console.log('pos:'+x_+','+y_+' wall:'+wall.x+','+wall.y);
        }
        else if(wall.angle==3.1415){
            if( x_-this.width/2>=wall.x+mFieldGridSize ){
                wall.x += mFieldGridSize;
            }
            // wall.width = mWallThick;
            // wall.height = mWallSize;
        }
        else if(wall.angle==3.1415/2){
            if( y_+this.width/2>=wall.y ){
                wall.y += mFieldGridSize;
            }
        }
        else if(wall.angle==3.1415/2*3){
            if( y_-this.width/2>=wall.y+mFieldGridSize ){
                wall.y += mFieldGridSize;
            }
        }

        if( (this.angle2<-3.1415/4) || (this.angle2>3.1415/4) ){
            wall.x = mFloorGS(x_);
            wall.y = mFloorGS(y_);
        }

        wall.p0x = wall.x;
        wall.p0y = wall.y;
        wall.p0z = wall.z;

        return wall;
    }
    buildFloor(){
        this.mode = 2;
        this.buildType = 1;

        this.buildTemp = this.funcFloor();
    }
    funcSlope(){
        const slope = new Slope({
            x: this.x,
            y: this.y,
            z: this.z,
            width: mWallSize*1.414,
            height: mWallSize*1.0,
            tall: mWallThick,
        });
        slope.angle = this.angle; // + 3.1415/2;
        slope.angle = Math.floor( (slope.angle+3.1415/4) / (3.1415/2)) * 3.1415/2;
        slope.angle2 = Math.PI/4;
        //console.log('wall.angle:'+wall.angle);

        // player geo center
        var x_ = this.x;// + this.width/2 * Math.cos(this.angle);
        var y_ = this.y;// + this.width/2 * Math.sin(this.angle);

        slope.x = mFloorGS(x_);   //Math.floor(x_/mFieldGridSize)*mFieldGridSize;
        slope.y = mFloorGS(y_);   //Math.floor(y_/mFieldGridSize)*mFieldGridSize;
        slope.z = mFloorGS(this.z) + mFieldGridSize/2;
        var dz_ =  this.z - mFloorGS(this.z);
        console.log('dz_:'+dz_+', angle2:'+this.angle2);
        if( (dz_>mFieldGridSize/2) && (this.angle2<-3.1415/6) ){
            slope.z += mFieldGridSize;
        }

        slope.x += mFieldGridSize * Math.cos(slope.angle);
        slope.y += mFieldGridSize * Math.sin(slope.angle);

        if( (this.angle2>3.1415/4) ){
            slope.x = mFloorGS(x_);
            slope.y = mFloorGS(y_);
        }

        slope.p1x = mFieldGridSize;
        slope.p1y = 0.0;
        slope.p1z = mFieldGridSize;
        slope.p2x = 0.0;
        slope.p2y = mFieldGridSize;
        slope.p2z = 0.0;

        if( (slope.angle==0) || (slope.angle==3.1415*2) ){

        }
        else if(slope.angle==3.1415){
            slope.p1x = -mFieldGridSize;
            slope.p1y = 0.0;
            slope.p1z = mFieldGridSize;    
        }
        else if(slope.angle==3.1415/2){
            slope.p1x = 0.0;
            slope.p1y = mFieldGridSize;
            slope.p1z = mFieldGridSize;
            slope.p2x = mFieldGridSize;
            slope.p2y = 0.0;
            slope.p2z = 0.0;    
        }
        else if(slope.angle==3.1415/2*3){
            slope.p1x = 0.0;
            slope.p1y = -mFieldGridSize;
            slope.p1z = mFieldGridSize;
            slope.p2x = mFieldGridSize;
            slope.p2y = 0.0;
            slope.p2z = 0.0;    
        }

        slope.p0x = slope.x;
        slope.p0y = slope.y;
        slope.p0z = slope.z - mFieldGridSize/2;

        return slope;
    }
    buildSlope(){
        this.mode = 2;
        this.buildType = 2;

        this.buildTemp = this.funcSlope();
    }
    doBuild(){
        if(this.buildType==0){
            var wall = this.funcWall();
            walls[wall.id] = wall;    
        }
        else if(this.buildType==1){
            var wall = this.funcFloor();
            walls[wall.id] = wall;    
        }
        else if(this.buildType==2){
            var slope = this.funcSlope();
            slopes[slope.id] = slope;    
        }
    }
    useBandage(){
        if((this.bandages>0) && this.health<this.maxHealth ){
            this.health += 10;
            this.health = Math.min(this.health,this.maxHealth);
            this.bandages -= 1;
            io.to(this.socketId).emit('usedBandage',1.0);
        }
        else{
            io.to(this.socketId).emit('cannotUseBandage',1.0);
        }
    }
    usePotion(){
        if((this.potions>0) && this.shield<this.maxShield ){
            this.shield += 50;
            this.shield = Math.min(this.shield,this.maxShield);
            this.potions -= 1;
            io.to(this.socketId).emit('usedPotion',1.0);
        }
        else{
            io.to(this.socketId).emit('cannotUsePotion',1.0);
        }
    }
    squat(){
        if(this.isSquat == 1){
            this.isSquat = 0;
        } 
        else{
            this.isSquat = 1;
        }
    }
    jump(){
        //this.z = 100;
        if(this.isBot==0){
            console.log('isGrounded:'+this.isGrounded);
        }
        
        if((this.isJump==0) && (this.isGrounded==1)){
            this.isGrounded = 0;
            this.isJump=1;
            this.jumpTime = this.timeCount;
            this.jumpStartZ = this.z;
        }
    }
    weaponChange(v_){
        this.weapon = v_;
        this.mode = 1;
    }
    emote(){
        if(this.isEmote == 1){
            this.isEmote = 0;
        } 
        else{
            this.isEmote = 1;
        }       
    }
    damage(v_){
        //this.health --;

        if(this.shield>0){
            this.shield -= v_;
            if(this.shield<0){
                v_ = -this.shield;
                this.shield = 0;
            }
            else{
                v_ = 0;
            }
        }

        this.health -= v_;
        this.health = Math.max(0,this.health);
        io.to(this.socketId).emit('recievedamage',1.0);
        if(this.health === 0){
            this.remove();
        }
    }
    stormDamage(v_){
        this.health -= v_;
        this.health = Math.max(0,this.health);
        //io.to(this.socketId).emit('recievedamage',1.0);
        if(this.health === 0){
            this.remove();
        }
    }
    remove(){
        io.sockets.emit('deadothers');
        delete players[this.id];
        io.to(this.socketId).emit('dead', (Object.keys(players).length+1) );
    }
    toJSON(){
        return Object.assign(super.toJSON(), {health: this.health, maxHealth: this.maxHealth, shield: this.shield, maxShield: this.maxShield,  socketId: this.socketId, point: this.point, nickname: this.nickname, weapon: this.weapon, isShoot: this.isShoot,  isSquat: this.isSquat, giveDamage: this.giveDamage, timeCount: this.timeCount, isBot: this.isBot, bandages: this.bandages, potions: this.potions, isEmote: this.isEmote, mode: this.mode, buildTemp: this.buildTemp, buildType: this.buildType, inStorm: this.inStorm});
    }
}

class Bullet extends GameObject{
    constructor(obj){
        super(obj);
        this.width = mBulletLength;// mBulletSize*20;
        this.height = mBulletSize;
        this.tall = mBulletSize;
        this.angle = obj.player.angle;
        this.angle2 = obj.player.angle2;
        this.player = obj.player;
        this.damageV = 20;
        this.isSquat = 0;
        this.dx = 0.0;
        this.dy = 0.0;
        this.dz = 0.0;
    }
    remove(){
        delete this.player.bullets[this.id];
        delete bullets[this.id];
    }
}

class BotPlayer extends Player{
    constructor(obj){
        super(obj);
        this.timer = setInterval(() => {
            this.timeCount+=1;
            this.isMoving=1;
            this.mode = 1;

            this.movement.forward = false;
            if(Math.random()*10<5){
                this.movement.forward = true;
            }
            
            if(! this.move(mPlayerSpeed*0.01)){
                this.angle = Math.random() * Math.PI * 2;
            }
            

            Object.values(players).forEach((player) => {
                if(player.isBot == 0){
                    var dx_ = player.x - this.x;
                    var dy_ = player.y - this.y;
                    var dz_ = player.z - this.z;
                    this.angle = Math.atan2(dy_,dx_);
                    var dr_ = Math.sqrt(dx_*dx_+dy_*dy_);
                    this.angle2 = -Math.atan2(dz_,dr_);
                    //console.log('angle2:'+ this.angle2/Math.PI*180.0+', ('+dz_+','+dr_);
                    return;
                }
             });


            if(Math.random()<0.01){
                this.shoot();
                var a_ = [1, 0.2];
            }
            if(Math.random()<0.01){
                this.squat();
            }
            if(Math.random()<0.01){
                this.jump();
            }

            Object.values(players).forEach((player) => {
                if(this.intersect(player)){
                    if(this !== player){
                    this.angle = Math.random() * Math.PI * 2;
                    return;
                    }
                } 
             });

             Object.values(walls).forEach((wall) => {
                if(this.intersect(wall)){
                    this.angle = Math.random() * Math.PI * 2;
                    return;
                } 
             });
             Object.values(rocks).forEach((rock) => {
                if(this.intersectXY(rock)){
                    this.angle = Math.random() * Math.PI * 2;
                    return;
                } 
             });
    
        }, 1000/30);
    }
    remove(){
        const bandage = new Bandage({
            x: this.x,
            y: this.y,
            z: this.z,
        });
        bandages[bandage.id] = bandage;

        if(Math.random()*10<5){
            const potion = new Potion({
                x: this.x + this.width,
                y: this.y + this.width,
                z: this.z,
            });
            potions[potion.id] = potion;    
        }

        super.remove();
        clearInterval(this.timer);
        //reborn
        // setTimeout(() => {
        //     const bot = new BotPlayer({nickname: this.nickname});
        //     players[bot.id] = bot;
        // }, 3000);
    }
}

class Wall extends GameObject{
    constructor(obj={}){
        super(obj);
        this.health = this.maxHealth = 100;
        this.p0x = 0.0;
        this.p0y = 0.0;
        this.p0z = 0.0;
        this.p1x = 0.0;
        this.p1y = 0.0;
        this.p1z = 0.0;
        this.p2x = 0.0;
        this.p2y = 0.0;
        this.p2z = 0.0;
    }
    damage(v_){
        //this.health --;
        this.health -= v_;
        this.health = Math.max(0,this.health);
        //console.log('wall damage:'+this.id+', health:'+this.health);
        if(this.health === 0){
            this.remove();
        }
    }
    remove(){
        delete walls[this.id];
    }
}

class Slope extends GameObject{
    constructor(obj={}){
        super(obj);
        this.health = this.maxHealth = 100;
        this.p0x = 0.0;
        this.p0y = 0.0;
        this.p0z = 0.0;
        this.p1x = 0.0;
        this.p1y = 0.0;
        this.p1z = 0.0;
        this.p2x = 0.0;
        this.p2y = 0.0;
        this.p2z = 0.0;
    }
    damage(v_){
        //this.health --;
        this.health -= v_;
        this.health = Math.max(0,this.health);
        console.log('wall damage:'+this.id+', v:'+v_+', health:'+this.health);
        if(this.health === 0){
            this.remove();
        }
    }
    remove(){
        delete slopes[this.id];
    }
}



class Rock extends GameObject{
    constructor(obj={}){
        super(obj);
        // this.p0x = 0.0;
        // this.p0y = 0.0;
        // this.p0z = 0.0;
        // this.p1x = 0.0;
        // this.p1y = 0.0;
        // this.p1z = 0.0;
        // this.p2x = 0.0;
        // this.p2y = 0.0;
        // this.p2z = 0.0;
    }
    remove(){
        delete rocks[this.id];
    }
}

class Bandage extends GameObject{
    constructor(obj={}){
        super(obj);
        this.width = mBandageSize;
        this.height = mBandageSize;
        this.tall =  mBandageSize*2;
    }
    remove(){
        delete bandages[this.id];
    }
}

class Potion extends GameObject{
    constructor(obj={}){
        super(obj);
        this.width = mBandageSize;
        this.height = mBandageSize;
        this.tall =  mBandageSize*2;
    }
    remove(){
        delete potions[this.id];
    }
}

class Storm extends GameObject{
    constructor(obj={}){
        super(obj);
    }

}

var mStorm = 
    new Storm({
        x: 0,
        y: 0,
        z: 0,
        width: FIELD_WIDTH,
        height: FIELD_WIDTH,
        tall: FIELD_WIDTH,
        angle: 0,
        angle2: 0,
        isSquat: 0,
    });


let players = {};
let bullets = {};
let walls = {};
let slopes = {};
let rocks = {};
let bandages = {};
let potions = {};
var mGlobalTime = 0;

//function mCreateWall(n_){
//    for(let i=0; i<n_; i++){
//        const wall = new Wall({
//                x: mFloorGS( Math.random() * FIELD_WIDTH ),
//                y: mFloorGS( Math.random() * FIELD_HEIGHT ),
//                z: 0,
//                width: mWallSize,
//                height: mWallThick,
//                tall: mWallSize,
//                angle: 0,
//                angle2: 0,
//                isSquat: 0,
//        });
//        walls[wall.id] = wall;
//    }
//}

function mCreateRock(){
    var n_ = 5;
    var d_ = FIELD_WIDTH * 0.2 / (n_*2);
    for(let i=0; i<n_; i++){        
        const rock1 = new Rock({
                x: FIELD_WIDTH*0.4 + d_*i,
                y: FIELD_HEIGHT*0.4 + d_*i,
                z: mWallSize*i,
                width: FIELD_WIDTH*0.3 - d_*2*i,
                height: FIELD_WIDTH*0.3 - d_*2*i,
                tall: mWallSize,
                angle: 0,
                angle2: 0,
                isSquat: 0,
        });
        rocks[rock1.id] = rock1;
    }

    const rock_sp1 = new Rock({
        x: 0.0,
        y: FIELD_HEIGHT*0.5,
        z: 0.0,
        width: FIELD_WIDTH,
        height: mFieldGridSize,
        tall: mFieldGridSize,
        angle: 0,
        angle2: 0,
        isSquat: 0,
    });
    rocks[rock_sp1.id] = rock_sp1;

    const rock_sp2 = new Rock({
        x: FIELD_WIDTH*0.5,
        y: 0.0,
        z: 0.0,
        width: mFieldGridSize,
        height: FIELD_HEIGHT,
        tall: mFieldGridSize,
        angle: 0,
        angle2: 0,
        isSquat: 0,
    });
    rocks[rock_sp2.id] = rock_sp2;

}

mCreateRock(); //constant map

function mCreateBandage(n_){
    for(let i=0; i<n_; i++){
        const bandage = new Bandage({
                x: Math.random() * FIELD_WIDTH,
                y: Math.random() * FIELD_HEIGHT,
                z: 0,
                angle: 0,
                angle2: 0,
                isSquat: 0,
        });
        bandages[bandage.id] = bandage;
    }    
}

function mCreatePotion(n_){
    for(let i=0; i<n_; i++){
        const potion = new Potion({
                x: Math.random() * FIELD_WIDTH,
                y: Math.random() * FIELD_HEIGHT,
                z: 0,
                angle: 0,
                angle2: 0,
                isSquat: 0,
        });
        potions[potion.id] = potion;
    }    
}

function mCreateBot(n_){
    for(let i=0; i<n_; i++){
        const bot = new BotPlayer({nickname: 'bot'+i});
        bot.z = START_TALL*0.1;
        bot.isBot = 1;
        bot.socketId = 'bot';
        players[bot.id] = bot;
    }    
}


// var mStormCx = 0;
// var mStormCy = 0;
function mSetStorm(){
    // mStormCx = Math.random() * FIELD_WIDTH;
    // mStormCy = Math.random() * FIELD_HEIGHT;
    mStorm.x = Math.random() * FIELD_WIDTH/2 + FIELD_WIDTH/4;
    mStorm.y = Math.random() * FIELD_HEIGHT/2 + FIELD_HEIGHT/4;
    mStorm.width = FIELD_WIDTH*1.0;
}

function mBulletWallCollision(wall_, bullet_){
    //console.log('mBWC:');
    var a11 = wall_.p1x;
    var a21 = wall_.p1y;
    var a31 = wall_.p1z;
    var a12 = wall_.p2x;
    var a22 = wall_.p2y;
    var a32 = wall_.p2z;
    var a13 = -bullet_.dx;
    var a23 = -bullet_.dy;
    var a33 = -bullet_.dz;
    var b1 = bullet_.x - wall_.p0x;
    var b2 = bullet_.y - wall_.p0y;
    var b3 = bullet_.z - wall_.p0z;

    // console.log(' A:'+[a11,a12,a13]);
    // console.log('  :'+[a21,a22,a23]);
    // console.log('  :'+[a31,a32,a33]);
    // console.log(' b:'+[b1,b2,b3]);

    var j = false;
    var res = [j, 0.0];
    
    var detA = a11*a22*a33 + a12*a23*a31 + a13*a21*a32 - a13*a22*a31 - a12*a21*a33 - a11*a23*a32;
    //console.log(' detA:'+detA);
    if( Math.abs(detA) < 0.000001){
        return res;
    }

    var s =(  (a22*a33-a23*a32)*b1 -(a12*a33-a13*a32)*b2 + (a12*a23-a13*a22)*b3 ) / detA;
    var t =( -(a21*a33-a23*a31)*b1 +(a11*a33-a13*a31)*b2 - (a11*a23-a13*a21)*b3 ) / detA;
    var e =(  (a21*a32-a22*a31)*b1 -(a11*a32-a12*a31)*b2 + (a11*a22-a12*a21)*b3 ) / detA;
    
    //console.log('mBWC:'+s+','+t+','+e );

    if( (s>=0.0) && (s<=1.0) && (t>=0.0) && (t<=1.0) && (e>=0.0) && (e<=mBulletLength) ){
        j = true;
        res = [j, 0.0];
    }
    //console.log(' res:'+res);

    return res;
}
//console.log('mBWC:'+mBulletWallCollision() );

function mBulletPlayerCollision(player_, bullet_)
{
    //var plane1;
    const plane1 = new Wall({
        x: 0,
        y: 0,
        z: 0,
    });

    var t_ = player_.tall - player_.tall/2*player_.isSquat;

    // y-z plane
    plane1.p0x = player_.x;
    plane1.p0y = player_.y - player_.width/2;
    plane1.p0z = player_.z;
    plane1.p1x = 0.0;
    plane1.p1y = 0.0;
    plane1.p1z = t_;
    plane1.p2x = 0.0;
    plane1.p2y = player_.width;
    plane1.p2z = 0.0;

    var res1 =mBulletWallCollision(plane1, bullet_);
    if(res1[0]){
        return res1;
    }

    // x-z plane
    plane1.p0x = player_.x - player_.width/2;
    plane1.p0y = player_.y;
    plane1.p0z = player_.z;
    plane1.p1x = 0.0;
    plane1.p1y = 0.0;
    plane1.p1z = t_;
    plane1.p2x = player_.width;
    plane1.p2y = 0.0;
    plane1.p2z = 0.0;

    res1 =mBulletWallCollision(plane1, bullet_);
    if(res1[0]){
        return res1;
    }

    // x-z plane
    plane1.p0x = player_.x - player_.width/2;
    plane1.p0y = player_.y - player_.width/2;
    plane1.p0z = player_.z + t_;
    plane1.p1x = player_.width;
    plane1.p1y = 0.0;
    plane1.p1z = 0.0;
    plane1.p2x = 0.0;
    plane1.p2y = player_.width;
    plane1.p2z = 0.0;

    res1 =mBulletWallCollision(plane1, bullet_);

    return res1;
}


function mBulletRockCollision(rock_, bullet_)
{
    //var plane1;
    const plane1 = new Wall({
        x: 0,
        y: 0,
        z: 0,
    });

    // x- plane
    plane1.p0x = rock_.x;
    plane1.p0y = rock_.y;
    plane1.p0z = rock_.z;
    plane1.p1x = 0.0;
    plane1.p1y = 0.0;
    plane1.p1z = rock_.tall;
    plane1.p2x = 0.0;
    plane1.p2y = rock_.height;
    plane1.p2z = 0.0;
    var res1 =mBulletWallCollision(plane1, bullet_);
    if(res1[0]){
        return res1;
    }

    // x+ plane
    plane1.p0x = rock_.x + rock_.width;
    plane1.p0y = rock_.y;
    plane1.p0z = rock_.z;
    plane1.p1x = 0.0;
    plane1.p1y = 0.0;
    plane1.p1z = rock_.tall;
    plane1.p2x = 0.0;
    plane1.p2y = rock_.height;
    plane1.p2z = 0.0;
    res1 =mBulletWallCollision(plane1, bullet_);
    if(res1[0]){
        return res1;
    }

    // y- plane
    plane1.p0x = rock_.x;
    plane1.p0y = rock_.y;
    plane1.p0z = rock_.z;
    plane1.p1x = 0.0;
    plane1.p1y = 0.0;
    plane1.p1z = rock_.tall;
    plane1.p2x = rock_.width;
    plane1.p2y = 0.0;
    plane1.p2z = 0.0;
    res1 =mBulletWallCollision(plane1, bullet_);
    if(res1[0]){
        return res1;
    }

    // y+ plane
    plane1.p0x = rock_.x;
    plane1.p0y = rock_.y+rock_.height;
    plane1.p0z = rock_.z;
    plane1.p1x = 0.0;
    plane1.p1y = 0.0;
    plane1.p1z = rock_.tall;
    plane1.p2x = rock_.width;
    plane1.p2y = 0.0;
    plane1.p2z = 0.0;
    res1 =mBulletWallCollision(plane1, bullet_);
    if(res1[0]){
        return res1;
    }

    // z- plane
    plane1.p0x = rock_.x;
    plane1.p0y = rock_.y;
    plane1.p0z = rock_.z;
    plane1.p1x = rock_.width;
    plane1.p1y = 0.0;
    plane1.p1z = 0.0;
    plane1.p2x = 0.0;
    plane1.p2y = rock_.height;
    plane1.p2z = 0.0;
    res1 =mBulletWallCollision(plane1, bullet_);
    if(res1[0]){
        return res1;
    }

    // z+ plane
    plane1.p0x = rock_.x;
    plane1.p0y = rock_.y;
    plane1.p0z = rock_.z + rock_.tall;
    plane1.p1x = rock_.width;
    plane1.p1y = 0.0;
    plane1.p1z = 0.0;
    plane1.p2x = 0.0;
    plane1.p2y = rock_.height;
    plane1.p2z = 0.0;
    res1 =mBulletWallCollision(plane1, bullet_);
    if(res1[0]){
        return res1;
    }

    return res1;
}


io.on('connection', function(socket) {
    let player = null;
    socket.on('game-start', (config) => {
        player = new Player({
            socketId: socket.id,
            nickname: config.nickname,
        });
        player.mode = 0;
        player.timeCount = 0;
        players[player.id] = player;
        io.to(player.socketId).emit('id', player.socketId);

        if(Object.keys(players).length == 1){
            mCreateBot(9);
            mGlobalTime = 0;
            mVictoryTime = 0;
            mSetStorm();
        }
        // if(Object.keys(walls).length < 20){
        //     mCreateWall(20-Object.keys(walls).length);
        // }
        if(Object.keys(bandages).length < 20){
            mCreateBandage(20-Object.keys(bandages).length);
        }
        if(Object.keys(potions).length < 20){
            mCreatePotion(20-Object.keys(potions).length);
        }

    });
    socket.on('movement', function(movement) {
        if(!player || player.health===0){return;}
        player.movement = movement;
    });
    socket.on('mousemoveX', function(v) {
        if(!player || player.health===0){return;}
        player.angle += v;
    });
    socket.on('mousemoveY', function(v) {
        if(!player || player.health===0){return;}
        player.angle2 += v;
        player.angle2 = Math.max(player.angle2,-3.1415/2*0.99);
        player.angle2 = Math.min(player.angle2,3.1415/2*0.99);
        //console.log('angle2:'+player.angle2);
    });
    // socket.on('shoot', function(){
    //     if(!player || player.health===0){return;}
    //     player.shoot();
    //     socket.broadcast.emit('shootFromOthers',0.3);
    // });
    socket.on('squat', function(){
        if(!player || player.health===0){return;}
        player.squat();
    });
    socket.on('jump', function(){
        if(!player || player.health===0){return;}
        player.jump();
    });
    socket.on('buildWall', function(){
        if(!player || player.health===0){return;}
        if(player.mode!=0){
            player.buildWall();
        }
    });
    socket.on('buildFloor', function(){
        if(!player || player.health===0){return;}
        if(player.mode!=0){
            player.buildFloor();
        }
    });
    socket.on('buildSlope', function(){
        if(!player || player.health===0){return;}
        if(player.mode!=0){
            player.buildSlope();
        }
    });
    socket.on('doBuild', function(){
        if(!player || player.health===0){return;}
        if(player.mode!=0){
            player.doBuild();
        }
    });
    socket.on('jumper', function(){
        if(!player || player.health===0){return;}
        player.z = START_TALL;
        player.mode = 0;
    });
    socket.on('weaponChange', function(v_){
        if(!player || player.health===0){return;}
        player.weaponChange(v_);
    });
    socket.on('reload', function(){
        if(!player || player.health===0){return;}
        player.shootCount[player.weapon-1]=0;
    });
    socket.on('useBandage', function(){
        if(!player || player.health===0){return;}
        player.useBandage();
    });
    socket.on('usePotion', function(){
        if(!player || player.health===0){return;}
        player.usePotion();
    });
    socket.on('emote', function(){
        if(!player || player.health===0){return;}
        player.emote();
    });
    socket.on('modeChanged', function(v_){
        if(!player || player.health===0){return;}
        player.mode = v_;
    });
    socket.on('disconnect', () => {
        if(!player){return;}
        delete players[player.id];
        player = null;
    });
});


function mRemoveAllPlayer()
{
    Object.values(players).forEach((player) => {
        player.remove();
    });
}


var mVictoryTime = 0;

setInterval(() => {

    mGlobalTime += 1;

    //Update strom
    mStorm.width -= FIELD_WIDTH/(30.0*60.0*5.0);
    mStorm.width = Math.max(1,mStorm.width);
    //console.log('strom w:'+mStorm.width);


    if(Object.keys(players).length == 1){
        Object.values(players).forEach((player) => {
            if(player.isBot==0){
                if(mVictoryTime == 0){
                    io.to(player.socketId).emit('victory');
                }
                else if(mVictoryTime >= 300){
                    mVictoryTime = 0;
                    player.remove();
                }
                mVictoryTime += 1;    
            }//

            //player.remove();
            //setTimeout(mRemoveAllPlayer, 10000);
        });
    }
    //console.log('players:'+ Object.keys(players).length);

    Object.values(players).forEach((player) => {
        const movement = player.movement;
        const oldX = player.x, oldY = player.y, oldZ = player.z;
        player.timeCount += 1;
        //player.isMoving = 0;

        //Storm
        var dx_ = mStorm.x - player.x;
        var dy_ = mStorm.y - player.y;
        var dis_ = Math.sqrt( dx_*dx_ + dy_*dy_ );
        if(player.isBot==0){
            //console.log('storm:'+mStorm.x+','+mStorm.y+', p:'+player.x+','+player.y+' dis_:'+dis_+', width:'+mStorm.width);
        }
        player.inStorm = 0;
        if( dis_ > mStorm.width ){
            //console.log('in storm:');
            //player.health -= 1.0/30.0;
            player.stormDamage(1.0/30.0);
            player.inStorm = 1;
            //io.to(player.socketId).emit('recievedamage',1.0);
        }

        var s_ = mPlayerSpeed;
        if(player.isSquat==1){
            s_ = mPlayerSpeed / 2;
        }
        if(player.mode==0){
            s_ = mPlayerSpeed * 5;
        }


        if((player.isJump==1)  && (player.mode!=0)){
            player.z = player.jumpStartZ + mJumpHight * Math.sin(3.1415*(player.timeCount-player.jumpTime)/mJumpFrame);
            if(player.timeCount-player.jumpTime>mJumpFrame){
                player.z = player.jumpStartZ;
                player.isJump = 0;
                //player.z -= mFieldGridSize;
            }
        }


        if(!movement.forward){
            player.isMoving = 0;
        }

        if(movement.forward){
            player.move(s_);
        }
        if(movement.back){
            player.move(-s_);
        }
        if(movement.left){
            player.angle -= mPlayerTurnSpeed;
        }
        if(movement.right){
            player.angle += mPlayerTurnSpeed;
        }
        if(movement.angup){
            player.angle2 -= mPlayerTurnSpeed/2;
        }
        if(movement.angdown){
            player.angle2 += mPlayerTurnSpeed/2;
        }
        if(movement.sideleft){
            player.side(-s_);
        }
        if(movement.sideright){
            player.side(s_);
        }

        player.x = Math.floor(player.x);
        player.y = Math.floor(player.y);
        player.z = Math.floor(player.z);

        if( player.angle > 2*3.1415 ){
            player.angle = player.angle - 2*3.1415;
        }
        if( player.angle < 0 ){
            player.angle = player.angle + 2*3.1415;
        }


        // build 
        if(player.mode == 2){
            if(player.buildType==0){
                player.buildWall();
            }
            else if(player.buildType==1){
                player.buildFloor();
            }            
            else if(player.buildType==2){
                player.buildSlope();
            }            
        }

        player.isShoot = 0;
        if(player.mode == 1)
        {
            if(movement.shoot){
                var mwp = player.weapon -1;
                if(player.timeCount>=player.shootTime+mShootCycle[mwp]) 
                {
                    if(player.shootCount[mwp]<mMagagineSize[mwp]){
                        player.isShoot = 1;
                        player.shoot();
                        player.shootTime = player.timeCount;
                        player.shootCount[mwp] += 1;    
                    }
                    else{
                        player.shootTime = player.timeCount;
                        io.to(player.socketId).emit('empty');
                    }
                }
            }
        }//

        if((player.giveDamageTime+30>=player.timeCount) &&
           (player.giveDamage>0) ) 
        {
            io.to(player.socketId).emit('displayGiveDamage', player.timeCount-player.giveDamageTime);//1, player.giveDamage);
        }
        else{
            player.giveDamage = 0;
            io.to(player.socketId).emit('displayGiveDamage',0);
        }

        var contactZ =0;
        player.isGrounded = 0;
        Object.values(walls).forEach((wall) => {
            if(player.intersectZu(wall)){
                //console.log('playerz:'+ player.z);
                player.z = wall.z + wall.tall; //mWallSize;
                player.isJump = 0;
                player.isGrounded = 1;
                contactZ = 1;

                if(player.mode == 0){
                    player.mode = 1;
                }    
                //console.log('intersectZu wall:'+ (wall.z+mWallSize) + ', '+player.z);
                return;
            } 
         });
         Object.values(rocks).forEach((rock) => {
            if(player.intersectZu(rock)){
                player.z = rock.z + rock.tall; //mWallSize;
                player.isJump = 0;
                player.isGrounded = 1;
                contactZ = 1;

                if(player.mode == 0){
                    player.mode = 1;
                }    
                return;
            } 
         });

        //  if(player.isBot==0){
        //     console.log('player.x:'+ player.x);
        //     console.log('player.z:'+ player.z);
        //  }

         Object.values(slopes).forEach((slope) => {
                     
            // if(player.isBot==0){
            //     console.log('slope.x:'+ slope.x);
            //     console.log('slope.z:'+ slope.z);
            // }

            if(player.intersectSlopeZ(slope)){
                //console.log(':');
                //console.log('player.x-slope.x:'+ (player.x-slope.x) );
                var c_ = 0;
                var dz_ = 0;
                if((slope.angle==0) || (slope.angle==3.1415*2)){
                    dz_ = slope.z - mFieldGridSize/2 + (player.x-slope.x);// + mWallThick;
                }
                else if(slope.angle==3.1415){
                    dz_ = slope.z - mFieldGridSize/2 + mFieldGridSize - (player.x-slope.x);// + mWallThick;
                }
                else if(slope.angle==3.1415/2){
                    dz_ = slope.z - mFieldGridSize/2 + (player.y-slope.y);// + mWallThick;
                }
                else if(slope.angle==3.1415/2*3){
                    dz_ = slope.z - mFieldGridSize/2 + mFieldGridSize - (player.y-slope.y);// + mWallThick;
                }

                // console.log('player.z:'+ player.z);
                // console.log('dz:'+ dz_);
                if(( player.z <= dz_ ) && (player.z >= dz_ - mWallThick ) ){
                    player.z = dz_;
                    c_ = 1;
                }
                else if( (player.z + player.tall >= dz_-mWallThick) && (player.z <= dz_)  ){
                    player.x = oldX;
                    player.y = oldY;
                    return;
                }

                //console.log('c_:'+ c_);

                
                if(c_==1){
                    player.isJump = 0;
                    player.isGrounded = 1;
                    contactZ = 1;
    
                    if(player.mode == 0){
                        player.mode = 1;
                    }    
                    return;
                }
                //console.log('player:'+ player.x+','+player.y+','+player.z);
                //console.log('intersectZu wall:'+ (wall.z+mWallSize) + ', '+player.z);
            } 
         });

        //  if(player.isBot==0){
        //     console.log('player.x:'+ player.x);
        //     console.log('player.z:'+ player.z);
        //     console.log(':');
        //  }

        if( ((player.isJump==0) && (player.isGrounded==0)) || (player.mode==0)  ){
            //fall
            player.z -= mFallSpeed;
        }
        //Ground contact
        if(player.z<0){
            player.z = 0;
            player.isJump = 0;
            player.isGrounded = 1;

            if(player.mode == 0){
                player.mode = 1;
            }
        }

         Object.values(walls).forEach((wall) => {
            if(player.intersectXY(wall)){
                player.x = oldX;
                player.y = oldY;
                //console.log('intersectXY wall:'+ player.x + ', '+player.y+ ', '+player.z);
                return;
            } 
         });
         Object.values(rocks).forEach((rock) => {
            if(player.intersectXY(rock)){
                player.x = oldX;
                player.y = oldY;
                //console.log('intersectXY wall:'+ player.x + ', '+player.y+ ', '+player.z);
                return;
            } 
         });

         Object.values(bandages).forEach((bandage) => {
            if(player.intersect(bandage)){
                player.bandages += 1;
                io.to(player.socketId).emit('getItem',1.0);
                bandage.remove();
                return;
            } 
         });

         Object.values(potions).forEach((potion) => {
            if(player.intersect(potion)){
                player.potions += 1;
                io.to(player.socketId).emit('getItem',1.0);
                potion.remove();
                return;
            } 
         });

    }); //player

    //console.log("bullets:"+Object.values(bullets).length);
    Object.values(bullets).forEach((bullet) =>{
        
        // if(! bullet.move3(mBulletSpeed)){
        //     bullet.remove();
        //     return;
        // }

        Object.values(walls).forEach((wall) => {
            //console.log('bullet wall collision:'+bullet.id+','+wall.id);
            var res_ = mBulletWallCollision(wall, bullet);
            if(res_[0]){
                wall.damage(bullet.damageV);
                bullet.remove();
                io.sockets.emit('walldamage', 0.5);
                return;           
            }
         });
         Object.values(slopes).forEach((slope) => {
            //console.log('bullet wall collision:'+bullet.id+','+wall.id);
            var res_ = mBulletWallCollision(slope, bullet);
            if(res_[0]){
                slope.damage(bullet.damageV);
                bullet.remove();
                io.sockets.emit('walldamage', 0.5);
                return;           
            }
         });
         Object.values(rocks).forEach((rock) => {
            //console.log('bullet wall collision:'+bullet.id+','+wall.id);
            var res_ = mBulletRockCollision(rock, bullet);
            if(res_[0]){
                bullet.remove();
                io.sockets.emit('walldamage', 0.5);
                return;           
            }
         });
    });


    Object.values(bullets).forEach((bullet) =>{

        Object.values(players).forEach((player) => {

            var res_ = mBulletPlayerCollision(player, bullet);
            if(res_[0]){
                if(player !== bullet.player){
                    player.damage(bullet.damageV);
                    bullet.remove();
                    bullet.player.point += 1;
                    //console.log('bullet intersect player:'+bullet.id+','+player.id);
                    io.to(bullet.player.socketId).emit('givedamage',1.0);

                    bullet.player.giveDamage=bullet.damageV;
                    bullet.player.giveDamageTime=bullet.player.timeCount;
                }
                return;
            } //res
        });

        if(! bullet.move3(mBulletSpeed)){
            bullet.remove();
            return;
        }

    }); //bullet
    io.sockets.emit('state', players, bullets, walls, slopes, rocks, bandages, potions, mStorm);
}, 1000/30);


app.use('/static', express.static(__dirname + '/static'));

app.get('/', (request, response) => {
  response.sendFile(path.join(__dirname, '/static/index.html'));//'/static/3d.html'
});

// const port = parseInt(yargs.port) || 3000;
// server.listen(port, () => {
//   console.log(`Starting server on port ${port}`);
// });

server.listen(PORT, function(){
    console.log('server listening. Port:' + PORT);
});
  

-ゲーム, プログラミング

執筆者:

関連記事

2重振り子の数値シミュレーション、解析から結果描画まで[Octave / Matlab / Android iPhoneアプリもあるよ]

久々に数値解析をやってみたくなりました。題材としては多くの人がやっている二重振り子が面白そうです。では言語は何にしようかと迷うところですが、コードを書いて計算して結果を描画するまで可能な「Octave …

弾丸と壁/人の接触判定を少し真面目に実装してみる|ゲーム作成

フォートナイトみたいなオンラインバトロワゲームを作っています。優秀なサンプルコードから作成を開始したので早い段階で一応形にはなりました。しかし、サンプルをいじりすぎて接触判定に矛盾が生じてきてしまいま …

no image

ショーモナイノ/ ソースコード(クライアントサイド)

サーバサイドのソースコードを公開したところ、結構ビュー数が伸びているようです。なのでクライアントサイドも公開しておきます。何かの役に立てればと思います。 内容はとんでもないジャンクコードとなっています …

エピックのアップル提訴問題 じゃあフォートナイトフォン作っちゃいなよ

8月13日、フォートナイトの開発元の米エピックゲームズがスマホアプリ課金システムなどが独占に当たるとして米アップルと米グーグルを提訴したそうです。現在、多数のフォートナイトプレイヤーYouTuberの …

Android studio|FFmpegでやりたい放題するための準備

動画を利用したアプリを作成するにあたりFFmpegを使用できると大変便利です。Web上に多数の情報がありますが、数年前の記事は役に立たなかったり、実用的な情報が少なかったりします。本記事ではAndro …

スポンサーリンク