BIFROST* Advanced Programming - part 1
In BIFROST*, it's much easier to just make changes in the tile map and let the engine automatically draw & animate everything in multicolor for you. Even so, sometimes experienced developers may decide to access BIFROST* internal routines directly, for the reasons explained in section "Advanced Programming" from the BIFROST* documentation. In order to help this process, I decided to demonstrate how to better use these routines by providing a few examples. Notice however that I will assume you already read the BIFROST* documentation first, so I won't waste time repeating everything again here.
The first demo (posted below) demonstrates how to move a set of multicolor tiles in hi-res coordinates. To avoid visual glitches, it's important for this kind of program to perform these tasks within a single frame:
The compiled version of this demo is available here.
Notice that in a C program there's barely enough time within a frame (with roughly 20K T-states available) to move 3 tiles. If the demo was implemented in Assembly, there would be enough time for 4 tiles, perhaps 5.
Another alternative would be increasing the total number of tiles, but only moving 3 of them per frame. However this would not work so well since a moving frame would erase other frames behind, that would not be redrawn immediately.
I believe it's now clear enough how this program above works. I'm available to answer any questions about it, except for questions already answered in the documentation.
Next week I will demonstrate how to use the "built-in sprite support" provided by BIFROST*, so you will be able to do something similar but with animated tiles in the background... Stay tuned!
The first demo (posted below) demonstrates how to move a set of multicolor tiles in hi-res coordinates. To avoid visual glitches, it's important for this kind of program to perform these tasks within a single frame:
- Erase all moving tiles;
- Adjust their coordinates;
- Draw them all again.
/* ---------------------------------------------------------------- * BIFROST* ENGINE HI-DEMO #1 * * Requires "BIFROSTENGINEV1.2H_z88dkInterface.zip" and z88dk * This program can be compiled as follows: * * zcc.exe +zx -lm -lndos -lbifrost -create-app -O2 bifrost_h1.c -obifrost_h1.bin * * After compiling it, use the following loader to execute: * * 10 CLEAR VAL "32767" * 20 LOAD "TILES"CODE * 30 LOAD "BIFROST*"CODE * 40 LOAD "bifrost_h1"CODE * 50 RANDOMIZE USR VAL "32768" * * Original version and further information is available at * http://www.worldofspectrum.org/infoseekid.cgi?id=0027405 * ---------------------------------------------------------------- */ #include <stdio.h> #include <stdlib.h> #include <input.h> #include "bifrost.h" #define printMode(mode) printf("\x01%c", mode) #define printCls() printf("\x0c") #define printInk(k) printf("\x10%c", '0'+k) #define printPaper(k) printf("\x11%c", '0'+k) #define printAt(row, col) printf("\x16%c%c", ' '+row, ' '+2*col) #define printAt64c(row, col) printf("\x16%c%c", ' '+row, ' '+col) #define INSIDE_COLOR 0 #define OUTSIDE_COLOR 7 #define NUM_TILES 3 extern unsigned char lastK(23560); // last pressed key unsigned char tile[NUM_TILES]; // tile number int lin[NUM_TILES]; // hi-res vertical tile position int col[NUM_TILES]; // hi-res horizontal tile position int dlin[NUM_TILES]; // hi-res vertical tile movement int dcol[NUM_TILES]; // hi-res horizontal tile movement int px, py; // "abstract" coordinates int f; // generic counter int frames; main() { // initialize variables randomize(); for (f = 0; f < NUM_TILES; ++f) { tile[f] = 8 + rand()%18; lin[f] = rand()%161; col[f] = rand()%19; dlin[f] = (rand()%2)*2 - 1; dcol[f] = (rand()%3) - 1; } frames = 1; // clear bitmap screen printMode(32); zx_border(OUTSIDE_COLOR); printPaper(OUTSIDE_COLOR); printInk(OUTSIDE_COLOR); printCls(); // show messages printInk(7-OUTSIDE_COLOR); printAt(20, 1); printf("Delay: %d frame(s)", frames); printAt(21, 1); printf("Use O/P to change"); // disable entire tile map for (f = 0; f < 81; ++f) { BIFROST_tilemap[f] = BIFROST_DISABLED; } // clear multicolor attributes (no glitches since BIFROST* is still disabled) for (px = 0; px < 9; ++px) { for (py = 0; py < 9; ++py) { BIFROST_fillTileAttrH((px+1)<<4, (py<<1)+1, INSIDE_COLOR*9); } } // start BIFROST_start(); while(1) { // process input keys if (lastK != 0) { if (lastK == 'o' && frames > 1) { --frames; } if (lastK == 'p' && frames < 9) { ++frames; } lastK = 0; printAt(20, 8); printf("%d", frames); } // bounce tiles for (f = 0; f < NUM_TILES; ++f) { // bounce above/below if (lin[f]+dlin[f] < 0 || lin[f]+dlin[f] > 160) { dlin[f] = -dlin[f]; } // bounce on the sides if (col[f]+dcol[f] < 0 || col[f]+dcol[f] > 18) { dcol[f] = -dcol[f]; } } // delay for (f = 0; f < frames; ++f) { // frame sync asm("halt"); } // erase tiles for (f = 0; f < NUM_TILES; ++f) { BIFROST_fillTileAttrH(lin[f], col[f], INSIDE_COLOR*9); } // move and draw tiles for (f = 0; f < NUM_TILES; ++f) { lin[f] += dlin[f]; col[f] += dcol[f]; BIFROST_drawTileH(lin[f], col[f], tile[f]); } } }
The compiled version of this demo is available here.
Notice that in a C program there's barely enough time within a frame (with roughly 20K T-states available) to move 3 tiles. If the demo was implemented in Assembly, there would be enough time for 4 tiles, perhaps 5.
Another alternative would be increasing the total number of tiles, but only moving 3 of them per frame. However this would not work so well since a moving frame would erase other frames behind, that would not be redrawn immediately.
I believe it's now clear enough how this program above works. I'm available to answer any questions about it, except for questions already answered in the documentation.
Next week I will demonstrate how to use the "built-in sprite support" provided by BIFROST*, so you will be able to do something similar but with animated tiles in the background... Stay tuned!
Post edited by Einar Saukas on
Creator of ZXDB, BIFROST/NIRVANA, ZX7/RCS, etc. I don't frequent this forum anymore, please look for me elsewhere.
Comments
Thanks!
I'll be looking forward to this :)
Looking forward to it. Fantastic stuff. This is just what I need for Hippy Space Invaders. 8-)
:)
This is actually a very good idea!
Are you planning to implement it yourself or just suggesting this idea for others to implement?
Either way, I'm willing to prepare an initial version to show the best way to use BIFROST* for this, if someone can commit to do all the hard work afterwards (tile images, graphics and remaining logic).
I must say that I didn't read this in the documentation but perhaps it was an somewhat older version.
Also, making 4 colour graphics is harder than monochrome. :)
EDIT: I will look at the other thread later. I'm very busy this week.
Games List 2016 - Games List 2015 - Games List 2014
I think it's worthwhile to provide a practical example for this sentence. In the first demo, the program had to perform all these tasks within a single frame:
- Erase 3 tiles
- Update coordinates for 3 tiles
- Redraw 3 tiles
However, if "sprite tiles" are used for drawing 2 of these sprites, the program will only need to perform the following tasks:- Erase 1 tile + 2 sprite tiles
- Update coordinates for 1 tile + 2 sprite tiles
- Redraw 1 tile
Since redrawing both sprite tiles is performed automatically by the engine, the program will save enough time to "manually" process (erase, update and redraw) one more sprite!So here's the optimized version (now moving 4 tiles instead of 3): The compiled version of this demo is available here.
Notice the only differences (in comparison to the original demo at the beginning of this current thread) are that it now enable sprites at the beginning, and it only updates sprite coordinates for the first 2 tiles instead of drawing them at the end. That's all!