Sprite Hierarchies

Task

Create a rectangle which has a frog as its child and a rotating and pulsating box which has several balls as its children. All behaviour of the children is relative to the parent sprite.

Result

JavaScript

// Demo 12

const grayFrog = makeGrayFrogLibrary();

function start() {
    // Load images and start demo when loading has finished    
    let ip = new grayFrog.ImagePreloader();
    ip.preloadImages(
        [
            { name: 'grid', source: 'images/grid.png' },
            { name: 'quarterGrid', source: 'images/quarterGrid.png' },
            { name: 'spritesheet', source: 'images/sprites.png' }
        ],
        () => demo(ip.imageDictionary)
    );
}

function demo(imageDictionary) {
    // Spritesheet data
    let sprites = { 
        'blackBall' : { sx : 616, sy : 0, sw : 200, sh : 200 }, 
        'blueBall' : { sx : 616, sy : 200, sw : 200, sh : 200 }, 
        'blueStar' : { sx : 816, sy : 0, sw : 200, sh : 200 }, 
        'frog' : { sx : 360, sy : 0, sw : 256, sh : 256 }, 
        'grayBall' : { sx : 816, sy : 200, sw : 200, sh : 200 }, 
        'greenBall' : { sx : 1016, sy : 0, sw : 200, sh : 200 }, 
        'orangeBall' : { sx : 1016, sy : 200, sw : 200, sh : 200 }, 
        'purpleBall' : { sx : 1216, sy : 0, sw : 200, sh : 200 }, 
        'rays' : { sx : 0, sy : 0, sw : 360, sh : 360 }, 
        'redBall' : { sx : 1216, sy : 200, sw : 200, sh : 200 }, 
        'redStar' : { sx : 1416, sy : 0, sw : 200, sh : 200 }, 
        'yellowBall' : { sx : 1416, sy : 200, sw : 200, sh : 200 }
    };
    
    // Initialize canvas, controller, and scene
    let canvas = document.getElementById('demoCanvas');
    let controller = new grayFrog.Controller(canvas, true);
    let scene = controller.makeImageScene('main', imageDictionary.grid);
    controller.scene = scene;

    // Add a transparent overlay to the scene to get a gray background grid
    let overlay = new grayFrog.DrawnSprite(
        'overlay', scene.midX, scene.midY, scene.width, scene.height);
    overlay.customDraw = function() {
        this.drawRectangleOutline('#000000', '#000000', 0, 0.1, 0);
    };
    scene.addChild(overlay);
    
    // Add a rect with a grid background
    let rect = new grayFrog.ImageSprite(
        'rect', 250, scene.midY, imageDictionary.quarterGrid);
    rect.rotation = -30;
    overlay.addChild(rect);

    // Add a frog to the rect which moves from left to right
    let frog = new grayFrog.SheetSprite(
        'frog', 100, 100, imageDictionary.spritesheet, sprites.frog);
    frog.scale = 0.5;
    frog.addAction(new grayFrog.Action('x', 300, 2,
        grayFrog.EASING.inout,
        { atEndBehaviour: grayFrog.ACTION_AT_END_BEHAVIOUR.oscillate }));
    rect.addChild(frog);

    // Add a rotating and pulsating box to the scene
    let box = new grayFrog.DrawnSprite(
        'box', 650, 200, 100, 100);
    box.customDraw = function() {
        this.drawRectangleOutline('#ffffff', '#000000', 1, 1, 1);
    };
    box.addAction(new grayFrog.Action('rotation', 360, 4,
        grayFrog.EASING.linear,
        { atEndBehaviour: grayFrog.ACTION_AT_END_BEHAVIOUR.repeat }));
    box.addAction(new grayFrog.Action('scale', 2, 2,
        grayFrog.EASING.inout,
        { atEndBehaviour: grayFrog.ACTION_AT_END_BEHAVIOUR.oscillate }));
    scene.addChild(box);

    // Add moving balls to the box
    let ballNames = ['redBall', 'orangeBall', 'yellowBall',
        'greenBall', 'blueBall', 'purpleBall', 'grayBall'];
    let nb = ballNames.length;
    for (let i = 0; i < 30; i++) {
        let spriteName = ballNames[Math.floor(Math.random() * nb)];
        let ball = new grayFrog.SheetSprite('ball_' + i,
            box.midX, box.midY,
            imageDictionary.spritesheet,
            sprites[spriteName]);
        ball.scale = 0.1;
        ball.angle = Math.random() * 360;
        ball.speed = 20 + Math.random() * 60;
        ball.hasCircularShape = true;
        ball.positionAutoUpdate = true;
        ball.edgeBehaviour = grayFrog.EDGE_BEHAVIOUR.bounce;
        box.addChild(ball);
    }   

    // Start the game loop
    controller.start();
}