OPTIMIZE = true; 
Ticker.update = true;
var isMobile = false;


function fishTank(){
      var scaling, width, height; // this will resize to fit inside the screen dimensions
    
    if (isMobile) {
        scaling = 'fit';
        width =  screen.width;
        height = screen.height;
        
    } else {
        scaling = "fit";
        width = 1650;
        height = 768;
    }
    var color = '#003611';
    var outerColor = darker;
    var stone, sea_shell, star_fish, floater, floater_gold, leaves_L_T, leaves_L_B, 
    fish_json, fish_image, main_header, sub_header, action_button, init_state, bubbles; // objects used across both frames
    
    function createImagesFromAssets (frame) {
        stone = frame.asset('XxAOo0i.png'); // logo is a Bitmap
        sea_shell = frame.asset('UQRSOha.png'); // logo is a Bitmap
        star_fish = frame.asset('TKHT88d.png'); // logo is a Bitmap
        floater = frame.asset('l2WBmke.png'); // logo is a Bitmap
        floater_gold = frame.asset('NPvfZMw.png'); // logo is a Bitmap
        leaves_T = frame.asset('Ancmkyx.png'); // logo is a Bitmap
        leaves_B = frame.asset('CT3oeb6.png'); // logo is a Bitmap
        fish_json = frame.asset('fish.json');
        fish_image = frame.asset('RaOIGHj.png');
    }

    function makelandingPageText(container) {
        var line_width, size, x, y, align, font_w, line_height, sub_size, x2, y2;
        if (isMobile && frame.orientation === 'vertical') {
            line_width = 470;
            size = 50;
            x = 5;
            y = 120;
            x2 = 5
            y2 = 50;
            align = "left";
            font_w = "normal";
            line_height = 60;
            sub_size = 30;
        } else if (isMobile && frame.orientation === 'horizontal'){
            line_width = 700;
            size = 80;
            x = -50;
            y = 200;
            x2 = -50;
            y2 = 50;
            align = "left";
            font_w = "normal";
            line_height = 100;
            sub_size = 45;
        } else {
            line_width = 550;
            size = 80;
            x = 20;
            y = 95;
            x2 = 24;
            y2 = 50;
            align = "left";
            font_w = "normal";
            line_height = 70;
            sub_size = 20;
        }
        main_header = new Label({
            text: `Click anywhere to make the fish Swim!`,
            size:size,
            font:"Helvetica",
            color:"white",
            fontOptions:font_w,
            lineWidth: line_width,
            lineHeight: line_height,
            align: align
        }).loc(x, y, container);
        sub_header = new Label({
            text: `Jump into the Pond,`,
            size:sub_size,
            font:"Helvetica",
            color:"white",
            fontOptions:"normal",
        }).loc(x2, y2, container);
        
    }

    function layout(frame, stage, col1, col2, backing) {
       
        // make the Layout - more useful for FULL scale mode
        
        
        var layout = new Layout({
           holder: stage,
           regions: [
            {object:col1, marginTop:10, maxWidth:80, minHeight:20, align:"left", valign:"top"},
            {object:col2, marginTop:4, minHeight:45}, // note, middle gets no minHeight
            
           ],
    
           
           lastMargin: 3
        });

        /* var layout2 = new Layout({
            holder: stage,
            regions: [
             {object:backing, marginTop:10, maxHeight:80, minHeight:65, valign:"middle", align:"middle",},
            ],
            
            lastMargin: 5
         }); */
        
    
        // add to LayoutManager to resize or dispose all layouts together
      
        var manager = new LayoutManager();
        manager.add(layout);
       
    
        frame.on('resize', function() {
           manager.resize();
           stage.update();
        });
    
        stage.update();
    }

    function makeBlocks(container){
        var block = new Bitmap(stone).centerReg(); 
        var block2;

        if (isMobile && frame.orientation === 'vertical') {
            block.pos(-100, rand(400, 450)).rot(zik([0, 155, 47, 77])).sca(0.6);
            block.addPhysics({
                dynamic: false,
                contract: 45,
                shape: 'circle'
            });
   
    
        } else if (isMobile && frame.orientation === 'horizontal') {
            block.pos((screen.width/2)+65, 15).rot(zik([0, 155, 47, 77])).sca(0.6);
            block.addPhysics({
                dynamic: false,
                contract: 45,
                shape: 'circle'
            });
        } else {
            block.pos(900, rand(30, 50)).rot(zik([0, 155, 47, 77]));
            block2 = new Bitmap(stone).centerReg().pos(1300, rand(30, 100)).rot(zik([0, 155, 47, 77]));
            block2.addPhysics({
                dynamic: false,
                contract: 90,
                
            });
            block.addPhysics({
                dynamic: false,
                contract: 60,
                shape: 'circle'
            });
        }
        
        

    }

    function makeSeaShells(container) {
        var scale, shells;
        var shell = new Bitmap(sea_shell).center();            

        if (isMobile) {
            scale = 0.4;
            shells = new Tile(shell, 2, 1, 5, 2).center(container);
        } else {
           scale = 0.12; 
           shells = new Tile(shell, 4, 3, 5, 2).center(container);

        }
        shells.loop(function (shell) {
            
            shell.mov(rand(200, 500), rand(300, 400)).sca(scale).alp(0.75).rot(rand(60, 180)).addTo(container);
        }, true);
    }

    function makeStarfishes(container) {
        var starfish = new Bitmap(star_fish).centerReg();            
        var starfishes = new Tile(starfish, 3, 1, 1, 0.2).center();

        starfishes.loop(function (starfish) {
            
            starfish.mov(rand(200, 300), rand(300, 300)).sca(0.1).alp(0.7).rot(rand(90, 180)).addTo(container);

        }, true);
    }

    function makeFloaters(container) {
        var scale1, scale2, pulse_x2, pulse_y2, restitution2;
        if (isMobile) {
            scale1 = 0.6;
            scale2 = 0.3;
            pulse_x2 = 5;
            pulse_y2 = 5;
            restitution2 = 1.1;
        } else {
            scale1 = 0.7;
            scale2 = 0.4;
            pulse_x2 = 50;
            pulse_y2 = 10;
            restitution2 = 2;
        }
        var floater_obj = new Bitmap(floater).sca(scale1).centerReg().mov(200, 200).addPhysics({
            dynamic: true,
            density: 0.1,
            restitution: 1,
            contract: 20,
            shape: 'circle'
        }).addTo(container).drag();
        var floater_obj2 = new Bitmap(floater_gold).sca(scale2).centerReg().mov(250, 250).addPhysics({
            dynamic: true,
            density: 0.3,
            restitution: restitution2,
            shape: 'circle',
            contract: 10,
        }).addTo(container).drag();

        floater_obj.impulse(-30, -30).torque(3000);
        floater_obj2.impulse(pulse_x2, pulse_y2);
    }

    function makeFish(stage, physics) {
        var fish = new GIF("https://i.imgur.com/G5G2deR.gif", 300, 300).centerReg().sha("rgba(0,0,0,.2)", 10, 10, 5);
      
 
         
        fish.addPhysics({
             // angular: 1,
             density: 3,
             friction: 0.5,
             shape: 'triangle'
        }).control("both", 130);


        function controlWithMouse(fish) {
            var amount;

            if (isMobile) {
                amount = 0.27;
            } else {
                amount = 5;
            }

            stage.on("stagemousedown", function () {
                fish.body.SetLinearVelocity(new b2Vec2(0,0));
                fish.body.SetAngularVelocity(0);


                var dX = frame.mouseX-fish.x;
                var dY = frame.mouseY-fish.y;
                var desired_angle = Math.atan2(dY, dX)*DEG+90;
                var starting_rotation = fish.body.rotation;


                var totalRotation = desired_angle - fish.body.rotation;
                while ( totalRotation < -180  ) totalRotation += 360;
                while ( totalRotation >  180 ) totalRotation -= 360;
                
                
                var desired_angular_velocity = desired_angle * 60;
                var torque = fish.body.GetInertia()/100 * desired_angular_velocity / (1/60.0);
                
                fish.damp = new Damp(0, 0.3);

                function setAngularVelocity() {
                    if(Math.sign(desired_angle) === 1){
                        fish.body.SetAngularVelocity(2);
                       
                    } else if(Math.sign(desired_angle) === -1){
                        fish.body.SetAngularVelocity(-2);
                        
                    }

                }
                
                
                fish.body.rotation = desired_angle;

                setTimeout(() => {
                    fish.impulse(dX*amount, dY*amount);
                }, 500);

                
                function stopRotation() {

                    function stopTurning () {
                        fish.body.SetAngularVelocity(0);
                        physics.Ticker.remove(stopRotation);
                    }
                    
                    var angle =  fish.body.rotation;
                    fish.body.rotation = fish.damp.convert(desired_angle);
                    if (starting_rotation === 0 && angle >= desired_angle) {
                        
                        stopTurning();
                    } else if (Math.sign(desired_angle) === -1 && angle <= desired_angle) {
                        
                        stopTurning();
                    } else if (Math.sign(desired_angle) === 1 && angle >= desired_angle) {
                        
                        stopTurning();
                    } else if (Math.sign(desired_angle) === -1 && angle >= desired_angle) {
                        
                        stopTurning();
                    } 

                }
               
                
            });
        }

        controlWithMouse(fish, stage);
      stage.update();
      zog("is fish swiming: ", fish.running);
    }

    function makeButtons(container) {
        var buttonW, buttonH, x, y, size;
        if (isMobile && frame.orientation === 'vertical') {
            buttonW = container.width * 1.49;
            buttonH = 80;
            x = 5;
            y = 400;
            size = 35;
        } else if(isMobile && frame.orientation === 'horizontal') {
            buttonW = 650;
            buttonH = 100;
            x = -50;
            y = 700;
            size = 50;
        } else {
            buttonW = 320;
            buttonH = 60;
            x = 24;
            y = 350;
            size = 25;
        }
        var label = new Label({
            text: "More",
            size:size,
            color: white,
            // backgroundColor:"violet",
            fontOptions:"bold"
         });
        action_button = new Button({
            label: label,
            width:buttonW,
            height:buttonH,
            backgroundColor:"#FF8300",
            rollBackgroundColor:"#FFE900",
            // borderWidth:8,
            // borderColor:"violet",
            gradient:.3,
            // corner:0
        });
        
        action_button.addTo(container).mov(x, y);
        action_button.on("click", function(){
            
            zgo(site_address.siteUrl + '/about');
        });
    }

    function makeLeaves () {
         var leaves_top = new Bitmap(leaves_T).sca(0.5).pos(-200, -40).addTo();
            
    }

    function makeBubbles(backing) {
       
        var x, y, angle, length;
        if (isMobile && frame.orientation === "vertical") {
            x = 70;
            y = (screen.height/2) + 50;
            angle = 42;
            length = 400;

        } else if (isMobile && frame.orientation === "horizontal") {
            // zog(frame.orientation)
            x = (screen.width/2) -10;
            y = 100;
            angle = 30;
            length = 400;

        } else {
            x = screen.width/2 + 50;
            y = screen.height/2 - 150;
            length = 850;
            angle = 30;

        }
        var squiggle = new Squiggle({
            lockControls: true,
            showControls : false,
            length: length,
            points: 8
        }).pos(x, y).rot(angle).alp(0); 
        bubbles = new Emitter({
        obj:[
            new Circle(20,null,null,4),
            new Circle(10,null,null,4),
            new Circle(5,null,null,4),
            
        ],
        random:{
            color:['#4FA4FF', '#86C8E4', white, 'rgba(30,40,50,0)'],
            borderColor:['#4FA4FF', '#86C8E4', white],
        },
        interval:500, // default
        life:3000,
        num: 7,
        decayTime:1500, // default
        sink:backing,
        sinkForce:.3,
        gravity:0,
        force:0.8,
        cache:mobile(), // default
        })
        .centerReg()
        .sca(2).animate({
            props:{path:squiggle},
            loop:true,
            time:2000,
            ease:"linear",
            dynamic:true,
            set:{percentSpeed:20} // no speed to start
         });


    }
    


    // as of ZIM 5.5.0 you do not need to put zim before ZIM functions and classes
    var gpu_obj = {preserveBuffer:true, antialias:true};
    var frame = new Frame({
        scaling: scaling, width: width, height: height, 
        color: color, outerColor: outerColor,
        sensors: true, // gpu: true, gpuObj: gpu_obj
    });
    // frame.scale = 0.75;
    frame.on("ready", function() {
        

        var stage = frame.stage;
        var stageW = frame.width;
        var stageH = frame.height;
        var imagesUrl = "https://i.imgur.com/";
        var left_column, right_column;
        var backing = new Rectangle(stageW, stageH, new GradientColor([ '#1E9CD7', '#0041A1'], [0, 0.7], 0, 50, 250, 700)).alp(1).center();
        var physics = new Physics(0, new Boundary(backing.x, backing.y, backing.width, backing.height), true);
        var waiter = new Waiter(stage);
        waiter.show();

        
        if (isMobile) {
            left_column = new Container(stage.width+ 100, 400).addTo().outline();
            right_column = new Container(stage.width + 100, 500).addTo().outline();
        } else {
            left_column = new Container(500, 500).loc(50, 100); //.outline();
            right_column = new Container(1080, 650).loc(550, 80); //.outline();
        }
       
        
      
        frame.loadAssets(['fish.json'], 'https://raw.githubusercontent.com/EnventDigital/QuizApp/fish-tank/');
        var first = frame.loadAssets( ['RaOIGHj.png','XxAOo0i.png', 'UQRSOha.png', 'Ancmkyx.png', 'CT3oeb6.png',
        'TKHT88d.png', 'l2WBmke.png', 'NPvfZMw.png'], imagesUrl ); // loads the images
      

        first.on('complete', function() {
            waiter.hide();
            makelandingPageText(left_column);
            createImagesFromAssets(frame);
            init_state = frame.orientation;
            makeBubbles(stage);
            makeStarfishes(right_column);
            makeSeaShells(right_column);
            makeButtons(left_column);
            makeBlocks(right_column); 
            makeFloaters(stage);
            makeFish(stage, physics);
            if (!isMobile) {
                makeLeaves(); 
            }
            
            stage.update();
        });


        // * This function creates the layout manager and its settings
        if (isMobile) {
            layout(frame, stage, left_column, right_column); 
        }


        stage.update(); // this is needed to show any changes

    }); // end of ready
}

fishTank();

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://zimjs.org/cdn/gifler.js
  2. https://zimjs.org/cdn/1.3.4/createjs.js
  3. https://zimjs.org/cdn/nft/01/zim_min.js
  4. https://zimjs.org/cdn/Box2dWeb-2.1.a.3.min.js
  5. https://zimjs.org/cdn/physics_2.0.js