org.geekygoblin.nedetlesmaki.game.systems.DrawSystem.java Source code

Java tutorial

Introduction

Here is the source code for org.geekygoblin.nedetlesmaki.game.systems.DrawSystem.java

Source

/*
 The MIT License (MIT)
    
 Copyright (c) 2013 devnewton <devnewton@bci.im>
    
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
    
 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.
    
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */
package org.geekygoblin.nedetlesmaki.game.systems;

import org.geekygoblin.nedetlesmaki.core.systems.IDrawSystem;
import org.geekygoblin.nedetlesmaki.core.systems.MouseArrowSystem;
import im.bci.jnuit.artemis.sprite.SpriteProjector;
import com.artemis.Aspect;
import com.artemis.ComponentMapper;
import com.artemis.Entity;
import com.artemis.EntitySystem;

import com.artemis.utils.Bag;
import com.artemis.utils.ImmutableBag;
import com.artemis.utils.Sort;
import im.bci.jnuit.lwjgl.LwjglHelper;
import im.bci.jnuit.lwjgl.LwjglNuitFont;
import im.bci.jnuit.animation.IAnimationFrame;
import im.bci.jnuit.animation.IPlay;
import java.util.Comparator;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import im.bci.jnuit.NuitFont;
import im.bci.jnuit.NuitRenderer;
import org.geekygoblin.nedetlesmaki.core.NedGame;
import org.geekygoblin.nedetlesmaki.core.NamedEntities;
import im.bci.jnuit.artemis.sprite.Sprite;
import org.geekygoblin.nedetlesmaki.core.components.LevelBackground;
import org.geekygoblin.nedetlesmaki.core.components.ui.MainMenu;
import org.geekygoblin.nedetlesmaki.core.components.ui.DialogComponent;
import org.geekygoblin.nedetlesmaki.core.constants.VirtualResolution;
import im.bci.jnuit.lwjgl.sprite.SpriteBatcher;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.geekygoblin.nedetlesmaki.core.components.ui.InGameUI;
import org.geekygoblin.nedetlesmaki.core.utils.Viewport;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Cursor;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;
import pythagoras.f.Vector;
import pythagoras.f.Vector3;

/**
 *
 * @author devnewton
 */
@Singleton
public class DrawSystem extends EntitySystem implements IDrawSystem {

    private ComponentMapper<LevelBackground> levelBackgroundMapper;
    private ComponentMapper<Sprite> spriteMapper;
    private ComponentMapper<MainMenu> mainMenuMapper;
    private ComponentMapper<DialogComponent> dialogMapper;
    private ComponentMapper<InGameUI> inGameUIMapper;

    private final Comparator<Entity> zComparator = new Comparator<Entity>() {
        @Override
        public int compare(Entity o1, Entity o2) {
            Sprite s1 = spriteMapper.get(o1);
            Sprite s2 = spriteMapper.get(o2);
            int result = Integer.compare(s1.getZOrder(), s2.getZOrder());
            if (result == 0) {
                result = spriteProjector.compare(s1.getPosition(), s2.getPosition());
            }
            return result;
        }
    };
    private SpriteProjector spriteProjector;
    private final Viewport viewPort = new Viewport();
    private static final float spriteGlobalScale = 1.5f;
    private final Bag<Entity> backgrounds = new Bag<Entity>();
    private final Bag<Entity> sprites = new Bag<Entity>();
    private final Bag<Entity> uis = new Bag<Entity>();

    private final SpriteBatcher spriteBatcher = new SpriteBatcher();
    private final LwjglNuitFont font;
    private final NuitRenderer nuitRenderer;

    @Override
    protected void initialize() {
        levelBackgroundMapper = world.getMapper(LevelBackground.class);
        spriteMapper = world.getMapper(Sprite.class);
        mainMenuMapper = world.getMapper(MainMenu.class);
        dialogMapper = world.getMapper(DialogComponent.class);
        inGameUIMapper = world.getMapper(InGameUI.class);
    }

    @Override
    protected void inserted(Entity e) {
        if (levelBackgroundMapper.has(e)) {
            backgrounds.add(e);
        } else if (spriteMapper.has(e)) {
            sprites.add(e);
        } else {
            uis.add(e);
        }
    }

    @Override
    protected void removed(Entity e) {
        backgrounds.remove(e);
        sprites.remove(e);
        uis.remove(e);
    }

    @Inject
    public DrawSystem(@NamedEntities.DefaultFont NuitFont font, NuitRenderer nuitRenderer) {
        super(Aspect.getAspectForOne(LevelBackground.class, MainMenu.class, InGameUI.class, DialogComponent.class,
                Sprite.class));
        this.font = (LwjglNuitFont) font;
        this.nuitRenderer = nuitRenderer;
    }

    @Override
    protected void processEntities(ImmutableBag<Entity> entities) {
        GL11.glClearColor(99f / 255f, 201f / 255f, 183f / 255f, 1f);
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
        Sort.instance().sort(sprites, zComparator);

        GL11.glPushAttrib(GL11.GL_ENABLE_BIT | GL11.GL_TRANSFORM_BIT | GL11.GL_HINT_BIT | GL11.GL_COLOR_BUFFER_BIT
                | GL11.GL_SCISSOR_BIT | GL11.GL_LINE_BIT | GL11.GL_TEXTURE_BIT);
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glPushMatrix();
        GL11.glLoadIdentity();

        updateViewPort();
        GL11.glViewport(viewPort.x, viewPort.y, viewPort.width, viewPort.height);
        GLU.gluOrtho2D(-VirtualResolution.WIDTH / 2.0f, VirtualResolution.WIDTH / 2.0f,
                VirtualResolution.HEIGHT / 2.0f, -VirtualResolution.HEIGHT / 2.0f);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glPushMatrix();
        GL11.glLoadIdentity();
        GL11.glEnable(GL11.GL_TEXTURE_2D);
        GL11.glEnable(GL11.GL_BLEND);
        GL11.glEnable(GL11.GL_LINE_SMOOTH);
        GL11.glDisable(GL11.GL_DEPTH_TEST);
        GL11.glDisable(GL11.GL_LIGHTING);
        GL11.glDisable(GL11.GL_SCISSOR_TEST);
        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
        GL11.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_NICEST);

        NedGame game = (NedGame) world;
        Entity ned = game.getNed();
        if (null != ned) {
            Sprite nedSprite = spriteMapper.get(ned);
            Vector nedPos = spriteProjector.project(nedSprite.getPosition());
            GL11.glTranslatef(-nedPos.x, -nedPos.y, 0.0f);
        }

        for (Entity e : backgrounds) {
            LevelBackground level = levelBackgroundMapper.getSafe(e);
            if (null != level) {
                drawLevel(level);
            }
        }

        GL11.glPushMatrix();
        GL11.glScalef(spriteGlobalScale, spriteGlobalScale, 1.0f);
        spriteBatcher.begin();
        for (Entity e : sprites) {
            spriteBatcher.draw(spriteMapper.getSafe(e));
        }
        spriteBatcher.end();
        for (Entity e : sprites) {
            drawSpriteLabel(spriteMapper.getSafe(e));
        }
        GL11.glPopMatrix();

        for (Entity e : uis) {
            MainMenu mainMenu = mainMenuMapper.getSafe(e);
            if (null != mainMenu) {
                nuitRenderer.render(mainMenu.getRoot());
            }
            DialogComponent dialog = dialogMapper.getSafe(e);
            if (null != dialog) {
                nuitRenderer.render(dialog.getRoot());
            }
            InGameUI inGameUI = inGameUIMapper.getSafe(e);
            if (null != inGameUI) {
                nuitRenderer.render(inGameUI.getRoot());
            }
        }
        GL11.glPopMatrix();
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glPopMatrix();
        GL11.glPopAttrib();

    }

    @Override
    protected boolean checkProcessing() {
        return true;
    }

    private void drawLevel(LevelBackground level) {

        GL11.glPushMatrix();
        GL11.glLoadIdentity();
        IPlay backgroundAnimationPlay = level.getBackground();
        backgroundAnimationPlay.update((long) (world.getDelta() * 1000L));
        final IAnimationFrame currentFrame = backgroundAnimationPlay.getCurrentFrame();
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, (Integer) currentFrame.getImage().getId());
        float x1 = -VirtualResolution.WIDTH / 2.0f;
        float x2 = VirtualResolution.WIDTH / 2.0f;
        float y1 = VirtualResolution.HEIGHT / 2.0f;
        float y2 = -VirtualResolution.HEIGHT / 2.0f;
        float u1 = currentFrame.getU1();
        float u2 = currentFrame.getU2();

        float v1 = currentFrame.getV2();
        float v2 = currentFrame.getV1();
        GL11.glBegin(GL11.GL_QUADS);
        GL11.glTexCoord2f(u1, v1);
        GL11.glVertex2f(x1, y2);
        GL11.glTexCoord2f(u2, v1);
        GL11.glVertex2f(x2, y2);
        GL11.glTexCoord2f(u2, v2);
        GL11.glVertex2f(x2, y1);
        GL11.glTexCoord2f(u1, v2);
        GL11.glVertex2f(x1, y1);
        GL11.glEnd();
        GL11.glPopMatrix();
    }

    private void drawSpriteLabel(Sprite sprite) {
        Vector pos = spriteProjector.project(sprite.getPosition());
        if (null != sprite.getLabel()) {
            GL11.glPushMatrix();
            GL11.glScalef(spriteGlobalScale, spriteGlobalScale, 1.0f);
            GL11.glTranslatef(pos.x, pos.y, 0.0f);
            GL11.glScalef(0.5f, -0.5f, 1f);
            GL11.glEnable(GL11.GL_BLEND);
            font.drawString(sprite.getLabel(), LwjglNuitFont.Align.CENTER);
            GL11.glDisable(GL11.GL_BLEND);
            GL11.glPopMatrix();
        }
    }

    public void setSpriteProjector(SpriteProjector spriteProjector) {
        this.spriteProjector = spriteProjector;
        this.spriteBatcher.setSpriteProjector(spriteProjector);
    }

    public SpriteProjector getSpriteProjector() {
        return spriteProjector;
    }

    @Override
    public Vector3 getMouseSpritePos(int yAdjust) {
        if (null != spriteProjector) {
            float mouseX = (Mouse.getX() - viewPort.x) * VirtualResolution.WIDTH / viewPort.width
                    - VirtualResolution.WIDTH / 2.0f;
            float mouseY = VirtualResolution.HEIGHT
                    - ((Mouse.getY() + yAdjust - viewPort.y) * VirtualResolution.HEIGHT / viewPort.height)
                    - VirtualResolution.HEIGHT / 2.0f;
            Entity ned = ((NedGame) world).getNed();
            if (null != ned) {
                Sprite nedSprite = spriteMapper.get(ned);
                Vector nedPos = spriteProjector.project(nedSprite.getPosition());
                mouseX += nedPos.x;
                mouseY += nedPos.y;
            }
            return spriteProjector.unProject(new Vector(mouseX / spriteGlobalScale, mouseY / spriteGlobalScale));
        } else {
            return null;
        }
    }

    private void updateViewPort() {
        final float aspect = (float) VirtualResolution.WIDTH / (float) VirtualResolution.HEIGHT;
        int screenWidth = LwjglHelper.getWidth();
        int screenHeight = LwjglHelper.getHeight();
        viewPort.width = screenWidth;
        viewPort.height = (int) (screenWidth / aspect);
        if (viewPort.height > screenHeight) {
            viewPort.height = screenHeight;
            viewPort.width = (int) (screenHeight * aspect);
        }
        viewPort.x = (screenWidth - viewPort.width) / 2;
        viewPort.y = (screenHeight - viewPort.height) / 2;
    }

    @Override
    public void hideCursor() {
        try {
            Cursor emptyCursor = new Cursor(1, 1, 0, 0, 1, BufferUtils.createIntBuffer(1), null);
            Mouse.setNativeCursor(emptyCursor);
        } catch (LWJGLException ex) {
            Logger.getLogger(MouseArrowSystem.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void setDefaultCursor() {
        try {
            Mouse.setNativeCursor(null);
        } catch (LWJGLException ex) {
            Logger.getLogger(MouseArrowSystem.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

}