javascript_terminal
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| javascript_terminal [2023/11/20 11:57] – appledog | javascript_terminal [2023/11/24 01:34] (current) – appledog | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| = JavaScript Terminal | = JavaScript Terminal | ||
| + | * Also see: [[JavaScript Terminal v2|Version 2]] which is a more advanced version of this codebase. | ||
| + | |||
| This section will outline the basic JavaScript terminal code. This code was not used much when I taught JavaScript to Roger and Neo, but it serves the same basic purpose as the [[PyGame Terminal]]. | This section will outline the basic JavaScript terminal code. This code was not used much when I taught JavaScript to Roger and Neo, but it serves the same basic purpose as the [[PyGame Terminal]]. | ||
| - | The level of this code will be towards the end of JavaScript Season 1, or at the beginning of JavaScript | + | The level of this code is the beginning of Season 2, for many reasons. If we took out the resize code, it might be late season |
| + | |||
| + | You can view a technical demo of this program at: [[https:// | ||
| + | |||
| + | == The Font | ||
| + | The font used in this technical demo is PxPlus_IBM_VGA_8x16.ttf which is available from the [[https:// | ||
| == index.html | == index.html | ||
| Line 8: | Line 15: | ||
| < | < | ||
| - | < | ||
| < | < | ||
| < | < | ||
| - | | + | |
| - | < | + | < |
| - | | + | |
| - | body, html { | + | body, html { |
| - | margin: 0; | + | margin: 0; |
| - | overflow: hidden; | + | overflow: hidden; |
| - | } | + | } |
| - | canvas { | + | |
| - | display: block; | + | |
| - | } | + | display: block; |
| - | + | | |
| - | </ | + | |
| + | |||
| + | </ | ||
| </ | </ | ||
| - | | + | |
| < | < | ||
| - | <!-- Add your site or application content here --> | + | < |
| - | | + | <script src=" |
| - | <script src=" | + | <script src=" |
| - | <script src=" | + | <script src=" |
| - | <script src=" | + | <script src=" |
| - | <script src=" | + | |
| </ | </ | ||
| Line 38: | Line 45: | ||
| </ | </ | ||
| - | There is not much to see here. In the original we used normalizer, modernizer and a few other things, but I have stripped those off to show the basic idea. | + | There is not much to see here. The most interesting line is probably |
| - | There are four main parts: Color.js, which is a color map, Character.js which discusses what needs to be known to represent a character, Terminal, which holds the information about characters on the screen and how to draw them, and main.js which sets up everything and starts the game loop. | + | Otherwise our main goal is to load and run the JavaScript files. |
| Actually, you could probably refactor some things in main into a class (such as a Game.js class) and then just instantiate and run the class, like we do in Python for PyGame. Perhaps this will be done in a part two sequel article to this one. For now, it's left as an exercise to the reader. | Actually, you could probably refactor some things in main into a class (such as a Game.js class) and then just instantiate and run the class, like we do in Python for PyGame. Perhaps this will be done in a part two sequel article to this one. For now, it's left as an exercise to the reader. | ||
| == Color.js | == Color.js | ||
| - | <code: | + | <Code: |
| class Color { | class Color { | ||
| static black = '# | static black = '# | ||
| Line 63: | Line 70: | ||
| static yellow = '# | static yellow = '# | ||
| static white = '# | static white = '# | ||
| - | | + | |
| - | static colorMap = [ this.black, this.blue, this.green, this.cyan, | + | static colorMap = [this.black, |
| this.red, this.magenta, | this.red, this.magenta, | ||
| this.darkgray, | this.darkgray, | ||
| - | this.lightred, | + | this.lightred, |
| static getColor(index) { | static getColor(index) { | ||
| Line 108: | Line 116: | ||
| < | < | ||
| class Character { | class Character { | ||
| - | | + | |
| - | this.ch = ch; | + | this.ch = ch; |
| - | this.color = color; | + | this.color = color; |
| - | this.background = background; | + | this.background = background; |
| - | } | + | } |
| } | } | ||
| + | </ | ||
| Simple! We will store the character (or it's ASCII code for printing), it's color, and it's background. This is all the data we need to represent a character on the screen. | Simple! We will store the character (or it's ASCII code for printing), it's color, and it's background. This is all the data we need to represent a character on the screen. | ||
| Line 232: | Line 241: | ||
| < | < | ||
| // Set up Canvas | // Set up Canvas | ||
| - | // let canvas = document.getElementById(' | + | let canvas = document.getElementById(' |
| let ctx = canvas.getContext(' | let ctx = canvas.getContext(' | ||
| Line 242: | Line 251: | ||
| // load font | // load font | ||
| const font = new FontFace(' | const font = new FontFace(' | ||
| - | ctx.font = '32px myvga'; | ||
| font.load().then(() => { | font.load().then(() => { | ||
| - | | + | |
| - | | + | |
| - | const measureTextResult | + | |
| - | + | ||
| - | // Calculate the baseline offset | + | |
| - | font_baseline = 32 - measureTextResult.actualBoundingBoxAscent; | + | |
| - | terminal.font_baseline = font_baseline | + | |
| }); | }); | ||
| Line 275: | Line 278: | ||
| terminal.copyContentTo(t); | terminal.copyContentTo(t); | ||
| terminal = t; | terminal = t; | ||
| + | |||
| + | ctx.font = '32px myvga'; | ||
| } | } | ||
| // Call the resizeCanvas function when the window is resized | // Call the resizeCanvas function when the window is resized | ||
| - | window.addEventListener(' | + | window.addEventListener(' |
| - | // Initial canvas setup | + | // Animation logic, timed events, etc. |
| - | resizeCanvas(); | + | // I don't plan for this to be used much in a roguelike. |
| - | + | // but it is useful for (ex.) a static demo of the display engine. | |
| - | function | + | function |
| - | | + | n = getRandomInt(1, 100); |
| + | if (n === 1) { | ||
| + | x = getRandomInt(0, | ||
| + | y = getRandomInt(0, | ||
| + | ch = getRandomLetter() | ||
| + | color = Color.getColor(getRandomInt(0, | ||
| + | background = Color.black | ||
| + | terminal.setch(x, | ||
| + | // | ||
| + | } | ||
| } | } | ||
| Line 296: | Line 310: | ||
| // draw characters on terminal | // draw characters on terminal | ||
| terminal.draw(ctx); | terminal.draw(ctx); | ||
| - | } | ||
| - | |||
| - | // Animation logic, timed events, etc. | ||
| - | // I don't plan for this to be used much in a roguelike. | ||
| - | // but it is useful for (ex.) a static demo of the display engine. | ||
| - | function update() { | ||
| - | n = getRandomInt(1, | ||
| - | if (n == 1) { | ||
| - | x = getRandomInt(0, | ||
| - | y = getRandomInt(0, | ||
| - | ch = getRandomLetter() | ||
| - | color = Color.getColor(getRandomInt(0, | ||
| - | background = Color.black | ||
| - | terminal.setch(x, | ||
| - | // | ||
| - | } | ||
| } | } | ||
| function gameLoop() { | function gameLoop() { | ||
| - | | + | |
| - | update() | + | update() |
| - | | + | |
| - | render(); | + | render(); |
| - | | + | |
| - | requestAnimationFrame(gameLoop); | + | requestAnimationFrame(gameLoop); |
| } | } | ||
| + | // Initial canvas setup | ||
| + | resizeCanvas(); | ||
| + | |||
| + | // Quick test -- see update() for the rest of the ' | ||
| terminal.setch(3, | terminal.setch(3, | ||
| terminal.setch(5, | terminal.setch(5, | ||
| Line 330: | Line 332: | ||
| terminal.setch(7, | terminal.setch(7, | ||
| terminal.setch(8, | terminal.setch(8, | ||
| - | |||
| // Start the game loop | // Start the game loop | ||
| gameLoop(); | gameLoop(); | ||
| - | |||
| </ | </ | ||
| == Analysis | == Analysis | ||
| Most of this should already be familiar since all of it would have been covered in JavaScript Season 1. | Most of this should already be familiar since all of it would have been covered in JavaScript Season 1. | ||
| + | |||
| + | However, one interesting quirk which arose is that the ctx.font has to be set upon terminal resize. I am not sure where the best place is to set it, but it seems to work great setting it on a resize. It would also work if you set it every time you drew a character, but if we assume that we are only using one font and are essentially the main application (a one-canvas app) then setting it on every character draw is probably unnecessary. | ||
| + | |||
| + | == Also See | ||
| + | * Also see: [[JavaScript Terminal v2|Version 2]] which is a more advanced version of this codebase. | ||
| + | |||
| + | |||
javascript_terminal.1700481443.txt.gz · Last modified: 2023/11/20 11:57 by appledog
