SquirrelJME/SquirrelJME

View on GitHub
modules/squirrel-quarrel/src/main/java/net/multiphasicapps/squirrelquarrel/lcdui/Renderer.java

Summary

Maintainability
A
0 mins
Test Coverage
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the Mozilla Public License Version 2.0.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package net.multiphasicapps.squirrelquarrel.lcdui;

import cc.squirreljme.runtime.cldc.debug.Debugging;
import javax.microedition.lcdui.Graphics;
import net.multiphasicapps.squirrelquarrel.game.GameLooper;
import net.multiphasicapps.squirrelquarrel.player.Player;
import net.multiphasicapps.squirrelquarrel.player.PlayerColor;
import net.multiphasicapps.squirrelquarrel.ui.GameScreen;
import net.multiphasicapps.squirrelquarrel.ui.SplitScreen;
import net.multiphasicapps.squirrelquarrel.world.MegaTile;

/**
 * This contains the renderer for the level and performs the actual drawing
 * of the game to the canvas.
 *
 * @since 2018/03/18
 */
public final class Renderer
{
    /** The game looper to draw. */
    protected final GameLooper looper;
    
    /** The splitscreens to have viewports for. */
    protected final SplitScreen splitscreen;
    
    /**
     * Initializes the renderer.
     *
     * @param __g The game looper to use.
     * @param __ss The splitscreen to use.
     * @throws NullPointerException On null arguments.
     * @since 2018/03/19
     */
    public Renderer(GameLooper __g, SplitScreen __ss)
        throws NullPointerException
    {
        if (__g == null || __ss == null)
            throw new NullPointerException("NARG");
        
        this.looper = __g;
        this.splitscreen = __ss;
    }
    
    /**
     * Paints the game to the given graphics.
     *
     * @param __scr The screen to draw for.
     * @param __g The graphics to draw on.
     * @throws NullPointerException On null arguments.
     * @since 2017/02/08
     */
    public void paint(GameScreen __scr, Graphics __g)
        throws NullPointerException
    {
        if (__scr == null || __g == null)
            throw new NullPointerException("NARG");
        
        // Get basic information
        Player player = __scr.player();
        PlayerColor playercolor = player.color();
        int sx = __scr.x(),
            sy = __scr.y(),
            sw = __scr.width(),
            sh = __scr.height();
        
        /*
        // If already painting, do not duplicate a paint
        if (this._inpaint)
            return;
        this._inpaint = true;
        
        // Get the current frame the game is on
        Game game = this.game;
        this._renderframe = game.frameCount();
        Level level = game.level();
        int framenum = game.frameCount();
        Player viewplayer = this._viewplayer;
        
        // Get the viewport
        int viewx = this._viewx,
            viewy = this._viewy,
            vieww = this._vieww,
            viewh = this._viewh;
        
        // MegaTiles do not often change
        MegaTileCacher mtcacher = this.mtcacher;
        
        // Megatile draw loop
        int msx = this._msx,
            msy = this._msy,
            mex = this._mex,
            mey = this._mey;
        for (int my = msy,
            sy = mapToScreenY(my * MegaTile.MEGA_TILE_PIXEL_SIZE),
            bsx = mapToScreenX(msx * MegaTile.MEGA_TILE_PIXEL_SIZE);
            my < mey; my++, sy += MegaTile.MEGA_TILE_PIXEL_SIZE)
            for (int mx = msx, sx = bsx; mx < mex; mx++,
                sx += MegaTile.MEGA_TILE_PIXEL_SIZE)
            {
                // Get the megatile here
                MegaTile mt = level.megaTile(mx, my);
                
                // Draw it
                __g.drawImage(mtcacher.cacheMegaTile(mt), sx, sy, 0);
                    
                // Draw units in this mega tile
                __drawUnits(__g, mt);
                
                // Setup flags for fog drawing
                __g.setColor(0x000000);
                __g.setStrokeStyle(Graphics.DOTTED);
                
                // Draw fog scanlines
                for (int sty = 0, psy = sy, bpsx = sx;
                    sty < MegaTile.TILES_PER_MEGA_TILE;
                    sty++, psy += MegaTile.TILE_PIXEL_SIZE)
                    for (int stx = 0, psx = bpsx;
                        stx < MegaTile.TILES_PER_MEGA_TILE;
                        stx++, psx += MegaTile.TILE_PIXEL_SIZE)
                    {
                        // Ignore revealed tiles
                        if (mt.subTileRevealed(viewplayer, stx, sty))
                            continue;
                        
                        // Otherwise find the next revealed tile (or the end)
                        int end;
                        for (end = stx + 1; end < MegaTile.TILES_PER_MEGA_TILE;
                            end++)
                            if (mt.subTileRevealed(viewplayer, end, sty))
                                break;
                        
                        // Draw dotted lines for fog
                        int endpx = sx + (stx * MegaTile.TILE_PIXEL_SIZE) +
                            (end * MegaTile.TILE_PIXEL_SIZE),
                            endpy = psy + MegaTile.TILE_PIXEL_SIZE;
                        for (int py = psy; py < endpy; py++)
                        {
                            // Lines off to the side can get clipped where the
                            // dot patterns stop being correct
                            int bx = (psx < 0 ? 0 : psx);
                            __g.drawLine(bx + (py & 1), py, endpx, py);
                        }
                        
                        // Set current spot to the end
                        stx = end;
                        psx = bpsx + (end * MegaTile.TILE_PIXEL_SIZE);
                    }
            }
        
        // Reset translation for the HUD
        __g.translate(-__g.getTranslateX(), -__g.getTranslateY());
        
        // Draw the automap in the bottom left corner
        Image map = this.automap.update();
        __g.setAlpha(160);
        __g.drawImage(map, 0, viewh, Graphics.LEFT | Graphics.BOTTOM);
        
        // Draw debug image
        __g.setAlpha(255);
        Image debugimage = this.debugimage;
        int ww = debugimage.getWidth(), hh = debugimage.getHeight();
        int sx = 50 - 5, sy = 50 - 5,
            ex = sx + ((ww * 3) + 10), ey = sy + ((hh * 3) + 10);
        __g.drawRegion(debugimage, 0, 0, ww, hh, Sprite.TRANS_NONE,
            sx + 5, sy + 5, 0, ww * 3, hh * 3);
        __g.setColor(0xFF0000);
        __g.drawLine(sx, sy, ex, sy);
        __g.setColor(0x00FF00);
        __g.drawLine(ex, sy, ex, ey);
        __g.setColor(0x0000FF);
        __g.drawLine(ex, ey, sx, ey);
        __g.setColor(0xFFFF00);
        __g.drawLine(sx, ey, sx, sy);
        
        // No longer painting
        this._inpaint = false;
        */
        
        // Draw the player's color around the screen
        __g.setColor(playercolor.rgb());
        __g.drawRect(sx, sy, sw - 2, sh - 2);
    }
    
    /**
     * Draws units in this megatile.
     *
     * @param __g The target graphics.
     * @param __mt The megatile to source from.
     * @since 2017/02/17
     */
    private void __drawUnits(Graphics __g, MegaTile __mt)
    {
        throw Debugging.todo();
        /*
        // Store the old clip
        int oldcx = __g.getClipX(),
            oldcy = __g.getClipY(),
            oldcw = __g.getClipWidth(),
            oldch = __g.getClipHeight();
        
        // Used for selection boxes
        __g.setColor(0xFFFF00);
        __g.setStrokeStyle(Graphics.SOLID);
        
        // Set new clipping so units are not drawn outside of the tile and
        // potentially into other tiles
        int mdx = mapToScreenX(__mt.x() * MegaTile.MEGA_TILE_PIXEL_SIZE),
            mdy = mapToScreenY(__mt.y() * MegaTile.MEGA_TILE_PIXEL_SIZE);
        __g.setClip(mdx, mdy, mdx + MegaTile.MEGA_TILE_PIXEL_SIZE,
            mdy + MegaTile.MEGA_TILE_PIXEL_SIZE);
        
        // Load units
        List<Unit.Pointer> drawunits = this._drawunits;
        drawunits.clear();
        __mt.loadLinkedUnits(drawunits);
        
        // Draw them
        for (int i = 0, n = drawunits.size(); i < n; i++)
            try
            {
                // Get unit, and its information
                Unit unit = drawunits.get(i).get();
                UnitType type = unit.type();
                if (type == null)
                    continue;
                UnitInfo info = type.info();
                
                // Get draw position on the screen
                int dx = mapToScreenX(unit.centerX()),
                    dy = mapToScreenY(unit.centerY());
                
                // Draw sprite
                __g.drawRect(dx - 10, dy - 10, 20, 20);
            }
            
            // Ignore due to threading potential
            catch (UnitDeletedException e)
            {
            }
        
        // Restore the old clip
        __g.setClip(oldcx, oldcy, oldcw, oldch);
        */
    }
}