Compare commits

...

6 Commits

Author SHA1 Message Date
DaniTheSkunk 1f4d3f4d83 started implementing virtual terminal 2022-10-09 03:36:12 +00:00
DaniTheSkunk 94d657d7be added monospace functions to fonts 2022-10-09 02:25:15 +00:00
DaniTheSkunk f02b2a984e changed window clear colour to black 2022-10-09 01:03:46 +00:00
DaniTheSkunk 0cfbf54f7e added thin-6x12 and thin-12x12 fonts (incomplete) 2022-10-09 01:03:26 +00:00
DaniTheSkunk 61c660c0ce isCP437 for fonts 2022-10-09 01:02:58 +00:00
DaniTheSkunk bb54dea3b2 added some basic static colours 2022-10-09 01:02:25 +00:00
13 changed files with 289 additions and 13 deletions

View File

@ -1,5 +1,6 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="ENABLE_SECOND_REFORMAT" value="true" />
<codeStyleSettings language="JAVA">
<option name="SPACE_BEFORE_IF_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_WHILE_PARENTHESES" value="false" />

View File

@ -1,5 +1,8 @@
import com.danitheskunk.skunkworks.*;
import com.danitheskunk.skunkworks.gfx.Color;
import com.danitheskunk.skunkworks.gfx.vt.Terminal;
import java.nio.charset.StandardCharsets;
public class Test {
public static void main(String[] args) {
@ -26,38 +29,53 @@ public class Test {
var tex2 = window.loadTexture("C:\\art\\pixel stuff.png");
var tileset = window.loadTextureArray("C:\\stream\\coding\\rlc\\tilemap.png", new Vec2i(16, 16));
var font = window.loadFontTileset("EGA8x14.png");
var fontThin = window.loadFontTileset("fonts\\thin-6x12.png");
var fontThin2 = window.loadFontTileset("fonts\\thin-12x12.png");
var font2 = window.loadFontTTF("fonts\\LiberationSans-Regular.ttf", 16 * 8.f);
var font3 = window.loadFontTTF("fonts\\LiberationSans-Regular.ttf", 16);
var tex = window.loadTexture(img);
var slice = window.loadNineSlice("demoassets\\9slice-2.png");
var term = new Terminal(new Vec2i(80, 45), fontThin2, fontThin);
//window.setDebug(true);
term.setChar(new Vec2i(0, 0), 0xC9, Color.GREEN);
term.setChar(new Vec2i(9, 9), 0xC9, Color.GREEN);
term.setChar(new Vec2i(10, 10), 0xC9, Color.GREEN);
while(!window.shouldClose()) {
window.tick();
var renderContext = window.renderStart();
renderContext.drawTextureRectangle(
/*renderContext.drawTextureRectangle(
new Recti(0, 0, 1280, 720),
tex,
false
);
);*/
//renderContext.drawTextureRectangle(
// new Recti(new Vec2i(200, 100), tex2.getSize()),
// tex2,
// true
//);
renderContext.drawTextureRectangle(
/*renderContext.drawTextureRectangle(
new Recti(new Vec2i(400, 400), new Vec2i(160, 160)),
tileset.get(0x30),
true
);
);*/
renderContext.drawString(new Vec2i(710, 140), "hello world mew", font2);
//byte[] str = {(byte)0xC9, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xBB};
//renderContext.drawString(new Vec2i(36, 36), new String(str), fontThin2, new Color(0, 255, 0));
//renderContext.drawString(new Vec2i(36, 36), "\u00c9\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00BB", fontThin2, new Color(0, 255, 0));
//renderContext.drawString(new Vec2i(36, 48), "\u00ba \u00ba", fontThin2, new Color(0, 255, 0));
//renderContext.drawString(new Vec2i(36, 60), "\u00ba \u00ba", fontThin2, new Color(0, 255, 0));
//renderContext.drawString(new Vec2i(36, 72), "\u00c8\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00BC", fontThin2, new Color(0, 255, 0));
//renderContext.drawString(new Vec2i(48, 48), "The quick brown fox jumps over the lazy dog", fontThin, new Color(0, 255, 0));
//renderContext.drawString(new Vec2i(48, 60), "Soft Kitty, Warm Kitty, Little Ball of Fur. Happy Kitty, Sleepy Kitty, Purr Purr Purr.", fontThin, new Color(0, 255, 0));
renderContext.drawTerminal(term);
renderContext.drawNineSlice(slice, new Recti(100, 100, 75, 23));
//renderContext.drawNineSlice(slice, new Recti(100, 100, 75, 23));
//renderContext.drawString(new Vec2i(118, 117), "Meow", font3, new Color(0,0,0));
renderContext.drawString(new Vec2i(122, 105), "Meow", font, new Color(0,0,0));
//renderContext.drawString(new Vec2i(122, 105), "Meow", font, new Color(0,0,0));
window.renderFinish(renderContext);
}

View File

@ -12,7 +12,8 @@ class RenderContext extends BaseRenderContext implements IRenderContext {
private final int texSizeIndex;
private final int tintIndex;
public RenderContext(TextureAtlas atlas, int texCoordIndex, int texOffsetIndex, int texSizeIndex, int tintIndex) {
public RenderContext(Vec2i size, TextureAtlas atlas, int texCoordIndex, int texOffsetIndex, int texSizeIndex, int tintIndex) {
super(size);
this.atlas = atlas;
this.texCoordIndex = texCoordIndex;
this.texOffsetIndex = texOffsetIndex;

View File

@ -53,6 +53,7 @@ public class Window extends BaseWindow {
program = new Program(vertexSource, fragmentSource);
program.use();
renderContext = new RenderContext(
size,
textureAtlas,
program.getAttribLocation("texCoord"),
program.getUniformLocation("texOffset"),
@ -113,8 +114,7 @@ public class Window extends BaseWindow {
@Override
public IRenderContext renderStart() {
textureAtlas.update();
glClearColor(0.1f, 0.2f, 0.3f, 1.0f);
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClearColor(0.f, 0.f, 0.f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
program.use();
//glBegin(GL_TRIANGLES);

View File

@ -3,12 +3,19 @@ package com.danitheskunk.skunkworks.gfx;
import com.danitheskunk.skunkworks.gfx.font.IFont;
import com.danitheskunk.skunkworks.Recti;
import com.danitheskunk.skunkworks.Vec2i;
import com.danitheskunk.skunkworks.gfx.vt.Terminal;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
abstract public class BaseRenderContext implements IRenderContext {
protected Vec2i size;
protected BaseRenderContext(Vec2i size) {
this.size = size;
}
public void drawString(Vec2i pos, String string, IFont font) {
drawString(pos, string, font, Color.WHITE);
}
@ -30,4 +37,35 @@ abstract public class BaseRenderContext implements IRenderContext {
x += font.getXAdvance(ch);
}
}
public void drawTerminal(Terminal terminal) {
var off = Vec2i.div(Vec2i.sub(size, terminal.getPixelSize()), 2);
drawTerminal(terminal, off);
}
public void drawTerminal(Terminal terminal, Vec2i pos) {
var termSize = terminal.getSize();
var charSize = terminal.getFullCharSize();
var halfCharSize = terminal.getHalfCharSize();
var halfFont = terminal.getHalfFont();
var fullFont = terminal.getFullFont();
for(int y = 0; y < termSize.getY(); ++y) {
for(int x = 0; x < termSize.getX(); ++x) {
var charPos = new Vec2i(x, y);
var bgColor = terminal.getBackgroundColor(charPos);
var fgColor = terminal.getForegroundColor(charPos);
var pixelPos = Vec2i.add(pos, Vec2i.mul(charPos, charSize));
var isHalfWidth = terminal.isHalfWidth(charPos);
drawTexture(pixelPos, fullFont.getTexture(0xdb), bgColor);
if(isHalfWidth) {
drawTexture(pixelPos, fullFont.getTexture(terminal.getLeftHalfChar(charPos)), fgColor);
drawTexture(Vec2i.add(pixelPos, halfCharSize), fullFont.getTexture(terminal.getRightHalfChar(charPos)), fgColor);
} else {
drawTexture(pixelPos, fullFont.getTexture(terminal.getChar(charPos)), fgColor);
}
}
}
}
}

View File

@ -3,6 +3,17 @@ package com.danitheskunk.skunkworks.gfx;
public final class Color {
private final int r, g, b, a;
public final static Color WHITE = new Color(255, 255, 255);
public final static Color LIGHT_GRAY = new Color(192, 192, 192);
public final static Color GRAY = new Color(128, 128, 128);
public final static Color DARK_GRAY = new Color(64, 64, 64);
public final static Color BLACK = new Color(0, 0, 0);
public final static Color RED = new Color(255, 0, 0);
public final static Color GREEN = new Color(0, 255, 0);
public final static Color BLUE = new Color(0, 0, 255);
public final static Color YELLOW = new Color(255, 255, 0);
public final static Color MAGENTA = new Color(255, 0, 255);
public final static Color CYAN = new Color(0, 255, 255);
public Color(int r, int g, int b) {
this.r = r;

View File

@ -1,16 +1,29 @@
package com.danitheskunk.skunkworks.gfx;
import com.danitheskunk.skunkworks.*;
import com.danitheskunk.skunkworks.Recti;
import com.danitheskunk.skunkworks.Vec2i;
import com.danitheskunk.skunkworks.gfx.font.IFont;
import com.danitheskunk.skunkworks.gfx.vt.Terminal;
public interface IRenderContext {
void drawNineSlice(NineSlice slice, Recti rect); //todo: add rounding mode
void drawRectangle(Recti rect, Color color);
void drawString(Vec2i pos, String string, IFont font);
void drawString(Vec2i pos, String string, IFont font, Color color);
void drawTexture(Vec2i pos, ITexture texture);
void drawTexture(Vec2i pos, ITexture texture, Color color);
void drawTextureRectangle(Recti rect, ITexture texture, boolean repeat);
void drawTextureRectangle(Recti rect, ITexture texture, Color color, boolean repeat);
void drawTerminal(Terminal terminal);
void drawTerminal(Terminal terminal, Vec2i pos);
//todo: drawTextureRectangleRepeat
}

View File

@ -81,6 +81,21 @@ public class FontTTF implements IFont {
return chars.get(ch).advance;
}
@Override
public boolean isCP437() {
return false;
}
@Override
public boolean isMonospace() {
return false;
}
@Override
public Vec2i getMonospaceSize() {
throw new RuntimeException("Not a monospace font");
}
@Override
public int getLineHeight(int ch) {
cacheChar(ch);

View File

@ -19,6 +19,21 @@ public class FontTileset implements IFont {
return charSize.getX();
}
@Override
public boolean isCP437() {
return true;
}
@Override
public boolean isMonospace() {
return true;
}
@Override
public Vec2i getMonospaceSize() {
return charSize;
}
@Override
public int getLineHeight(int ch) {
return charSize.getY();

View File

@ -8,4 +8,7 @@ public interface IFont {
Vec2i getOffset(int ch);
ITexture getTexture(int ch);
int getXAdvance(int ch);
boolean isCP437();
boolean isMonospace();
Vec2i getMonospaceSize();
}

View File

@ -0,0 +1,161 @@
package com.danitheskunk.skunkworks.gfx.vt;
import com.danitheskunk.skunkworks.Vec2i;
import com.danitheskunk.skunkworks.gfx.Color;
import com.danitheskunk.skunkworks.gfx.font.IFont;
import java.util.ArrayList;
import java.util.List;
public class Terminal {
private List<Cell> cells;
private Vec2i size;
private Vec2i fullCharSize;
private Vec2i halfCharSize;
private IFont fullFont;
private IFont halfFont;
public Terminal(Vec2i size, IFont fullFont, IFont halfFont) {
this.cells = new ArrayList<>();
this.size = size;
this.fullFont = fullFont;
this.halfFont = halfFont;
if(!fullFont.isMonospace() || !halfFont.isMonospace()) {
throw new RuntimeException("Fonts need to be monospace");
}
this.fullCharSize = fullFont.getMonospaceSize();
this.halfCharSize = halfFont.getMonospaceSize();
if(fullCharSize.getY() != halfCharSize.getY() || fullCharSize.getX() != halfCharSize.getX() * 2) {
throw new RuntimeException("halfFont needs to be half width of fullFont");
}
for(int i = 0; i < size.getY() * size.getX(); ++i) {
var cell = new Cell();
cell.fullChar = 0;
cell.secondChar = 0;
cell.halfWidth = false;
cell.bgColor = Color.BLACK;
cell.fgColor = Color.WHITE;
cells.add(cell);
}
}
public Vec2i getFullCharSize() {
return fullCharSize;
}
public Vec2i getHalfCharSize() {
return halfCharSize;
}
public Vec2i getSize() {
return size;
}
public void setChar(Vec2i pos, int ch) {
var cell = cells.get(vecToPos(pos));
cell.fullChar = ch;
cell.halfWidth = false;
}
public void setChar(Vec2i pos, int ch, Color foregroundColor) {
var cell = cells.get(vecToPos(pos));
cell.fullChar = ch;
cell.halfWidth = false;
cell.fgColor = foregroundColor;
}
public void setChar(Vec2i pos, int ch, Color foregroundColor, Color backgroundColor) {
var cell = cells.get(vecToPos(pos));
cell.fullChar = ch;
cell.halfWidth = false;
cell.fgColor = foregroundColor;
cell.bgColor = backgroundColor;
}
public void setHalfChars(Vec2i pos, int chLeft, int chRight) {
var cell = cells.get(vecToPos(pos));
cell.fullChar = chLeft;
cell.secondChar = chRight;
cell.halfWidth = true;
}
public void setHalfChars(Vec2i pos, int chLeft, int chRight, Color foregroundColor) {
var cell = cells.get(vecToPos(pos));
cell.fullChar = chLeft;
cell.secondChar = chRight;
cell.halfWidth = true;
cell.fgColor = foregroundColor;
}
public void setHalfChars(Vec2i pos, int chLeft, int chRight, Color foregroundColor, Color backgroundColor) {
var cell = cells.get(vecToPos(pos));
cell.fullChar = chLeft;
cell.secondChar = chRight;
cell.halfWidth = true;
cell.fgColor = foregroundColor;
cell.bgColor = backgroundColor;
}
public void setForegroundColor(Vec2i pos, Color color) {
var cell = cells.get(vecToPos(pos));
cell.fgColor = color;
}
public void setBackgroundColor(Vec2i pos, Color color) {
var cell = cells.get(vecToPos(pos));
cell.fgColor = color;
}
public int getChar(Vec2i pos) {
return cells.get(vecToPos(pos)).fullChar;
}
public int getLeftHalfChar(Vec2i pos) {
return cells.get(vecToPos(pos)).fullChar;
}
public int getRightHalfChar(Vec2i pos) {
return cells.get(vecToPos(pos)).secondChar;
}
public Color getForegroundColor(Vec2i pos) {
return cells.get(vecToPos(pos)).fgColor;
}
public Color getBackgroundColor(Vec2i pos) {
return cells.get(vecToPos(pos)).bgColor;
}
public boolean isHalfWidth(Vec2i pos) {
return cells.get(vecToPos(pos)).halfWidth;
}
private int vecToPos(Vec2i pos) {
return pos.getX() + pos.getY() * size.getX();
}
public IFont getFullFont() {
return fullFont;
}
public IFont getHalfFont() {
return halfFont;
}
public Vec2i getPixelSize() {
return Vec2i.mul(size, fullCharSize);
}
private class Cell {
int fullChar;
int secondChar;
boolean halfWidth;
Color bgColor;
Color fgColor;
}
}

BIN
fonts/thin-12x12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 B

BIN
fonts/thin-6x12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 874 B