Ultimate screen mode?


#1

I’ve been thinking, for a scrolling platformer, a tiled screen mode would usually be best, and there are 2 of those already (I think).
From a general ‘handheld’ style point of view, would it be worth creating a new screen mode, or do we have enough already?

An idea I have been thinking about, would be an 256 colour tiled mode, using 8x8 low-res tiles, but also somehow allowing 16x16 hi-res 4 colour tiles at the same time. The hi-res tiles would not take up any extra storage space compared to the lo-res tiles. But then there might have to be a sprite mode add also to make the whole idea work.

Does anyone else have any ideas about this?


#2

Sounds like a good idea to me! What kind of graphics is in your mind for this mode? Problem with tiled modes are that game objects are flickering because of multiple same LCD-pixel writes per frame, but we can use my sprite system to combine scanlines before writing. That is fast enough if there are not many game objects.

We should also implement scrolling support by giving 16 pixel screen offset, x and y. And maybe double tile buffers, so we do not have to move the whole buffer iduring one frame when scrollling, in every 16th pixel. Copying only a small part of tiles to off-screen tile buffer in every frame gives smoother scrolling.


#3

About tiled mode: I start working on a external tool that allow graphicaly “build” map and export like c headers for Pokitto.
I made some test using multiple layers of tiles rendered in the 110x88 16 color mode. This allow me to add some particle effects over the tiles and results seems good.

Maps are stored in Flash memory: 2d tiles id with additional table for rendering modifiers (flip and rotation). Another table (Ram) will store “modifiable” properties (solid, movable, activation, tile life, etc…).
I’m planing to create Animation table for tiles and Action table to trigger the operations in level. This is quite tailored to my needs and allowing me to experiment with level design.

But back to topic: I don’t know if the actual tiles engine fits my need, mostly about the ability to draw over a background using graphics routines (line,pixels, rect, etc) and “mark” the tiles with some logic.
Also going to high number of colors never gave me great benefits. I’m not an artist and less the color, less mistakes.
Fast scroll with multiple layers is something tickles my interest.


#4

I must agree that I also usually like 8-bit pixel graphics aesthetics more than more advanced graphics in Pokitto games. That is why I asked @spinal about the graphics he had in mind.


#5

I have a feeling that what I was thinking and how it would end up might not be the same. Essentially it would be a bit like the C64, a low-res hi-colour screen with the ability to put hi-res low-colour tiles in also.
But I have a feeling that it would (A) not look as good as I imaging and (B) be a lot slower than anyone would want.


#6

i have tried custom tile mode platformer with pixelcroft
sending individual tiles is a little slow so i dont think scrolling will be very fast, in that game prototype im not even refreshing the hole screen just the tiles of the player
i would use like a tiny 8x8 or 16x16 (but could be any size) buffer to use as the compositor for sprites to remedy any flickering

actualy now i think about it, using 16bit (instead of 8bit) 565 color might speed this up a bit since your not unpacking every pixel and referencing a pallet, compositing a sprite on a tilebuffer would also be faster


#7

Indeed, 16-bit mode could speed up the basic pixel copy and the composing also. The memory limit can be an issue if all objects are 16-bit.

I would like to make a “best case” test for 220x176x16 bit mode to find out what would be the max FPS we can get in that mode. Just to copy simple vertical stripes to LCD as fast as possible and change the source x offset for scrolling effect.


#8

i made a little test with the existing tile mode, 565 sprites might be a little large in flash but it seems to work
also note that the sprites are drawn sideways so you have to account for that

// tile test


#include "Pokitto.h"
Pokitto::Core game;

const uint16_t tile[]={22, 22, /*width, height*/
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xc800,0xc800,0xc800,0xc800,0x9800,
0xf800,0xff0c,0xff0c,0xff0c,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xff0c,0xff0c,0xff0c,0xff0c,0xfff3,0xfff3,0xff0c,0xff0c,0xfff3,0xff0c,0xf629,0xf629,0x9800,
0xf800,0xff0c,0xff0c,0xff0c,0xff0c,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xff0c,0xff0c,0xfff3,0xff0c,0xff0c,0xf629,0xf629,0x9800,
0xf800,0xfff3,0xff0c,0xf629,0xf629,0xf629,0xc508,0xf629,0xc508,0xf629,0xf629,0xc508,0xf629,0xc508,0xc508,0xf629,0xc508,0xc508,0xf629,0x6aa3,0x6aa3,0x9800,
0xf800,0xfff3,0xfff3,0xc508,0xc508,0xf629,0xf629,0xc508,0xf629,0xf629,0xc508,0xc508,0xf629,0xf629,0xf629,0xc508,0xc508,0xf629,0xc508,0x6240,0x6aa3,0x9800,
0xf800,0xfff3,0xfff3,0xc508,0xf629,0xc508,0xc508,0xf629,0xff0c,0xc508,0xf629,0xc508,0xf629,0xc508,0xc508,0xc508,0xc508,0xc508,0xc508,0x6240,0x6aa3,0x9800,
0xf800,0xfff3,0xfff3,0xf629,0xc508,0xf629,0xff0c,0xc508,0xf629,0xc508,0xf629,0xc508,0xc508,0xc508,0xc508,0xc508,0xc508,0xac46,0xc508,0x6aa3,0x6aa3,0x9800,
0xf800,0xfff3,0xfff3,0xc508,0xf629,0xff0c,0xf629,0xc508,0xc508,0xf629,0xc508,0xc508,0xc508,0xf629,0xf629,0xac46,0x8384,0xc508,0xac46,0x6aa3,0x6240,0x9800,
0xf800,0xfff3,0xfff3,0xc508,0xc508,0xf629,0xc508,0xff0c,0xc508,0xac46,0xc508,0xac46,0xc508,0xc508,0xac46,0xac46,0xc508,0xac46,0xac46,0x6240,0x6aa3,0x9800,
0xf800,0xff0c,0xfff3,0xc508,0xf629,0xc508,0xc508,0xf629,0xc508,0xc508,0xc508,0xac46,0xac46,0xc508,0xc508,0xc508,0xc508,0x8384,0xc508,0x6240,0x6240,0x9800,
0xf800,0xff0c,0xfff3,0xf629,0xf629,0xf629,0xc508,0xc508,0xc508,0xc508,0xac46,0xc508,0xc508,0xc508,0xc508,0xc508,0xc508,0xac46,0xc508,0x6aa3,0x6240,0x9800,
0xf800,0xfff3,0xff0c,0xc508,0xc508,0xf629,0xf629,0xc508,0xc508,0xc508,0xc508,0xc508,0xc508,0xc508,0xc508,0xc508,0xac46,0x8384,0xc508,0x6240,0x6240,0x9800,
0xf800,0xff0c,0xff0c,0xac46,0xc508,0xc508,0xf629,0xc508,0xac46,0xac46,0xc508,0xc508,0xac46,0xac46,0xc508,0xc508,0x8384,0xac46,0xac46,0x6240,0x6aa3,0x9800,
0xf800,0xfff3,0xfff3,0xc508,0xc508,0xf629,0xc508,0xc508,0xc508,0xac46,0xc508,0xac46,0xac46,0xc508,0xac46,0xac46,0x8384,0xac46,0xc508,0x6aa3,0x6aa3,0x9800,
0xf800,0xff0c,0xff0c,0xac46,0xf629,0xf629,0xc508,0xc508,0xac46,0xac46,0xac46,0xac46,0x8384,0xac46,0x8384,0xac46,0x8384,0xc508,0xac46,0x6aa3,0x6240,0x9800,
0xf800,0xfff3,0xff0c,0xc508,0xc508,0xc508,0xac46,0xc508,0xc508,0xc508,0xc508,0xac46,0xc508,0xac46,0xac46,0xc508,0xc508,0xc508,0xc508,0x6aa3,0x6240,0x9800,
0xf800,0xff0c,0xff0c,0xc508,0xf629,0xf629,0xf629,0xc508,0xac46,0xc508,0xac46,0x8384,0xc508,0xc508,0x8384,0xc508,0xac46,0xc508,0xac46,0x6240,0x6aa3,0x9800,
0xc800,0xff0c,0xff0c,0xf629,0xf629,0xc508,0xc508,0xc508,0xc508,0xc508,0x8384,0xc508,0xac46,0xac46,0xac46,0x8384,0xac46,0xc508,0xac46,0x6aa3,0x6aa3,0x9800,
0xc800,0xff0c,0xff0c,0xf629,0xc508,0xf629,0xc508,0xac46,0xc508,0xac46,0xc508,0xc508,0xc508,0x8384,0xc508,0xac46,0xac46,0xac46,0xac46,0x6aa3,0x6240,0x9800,
0xc800,0xf629,0xf629,0x6aa3,0x6aa3,0x6aa3,0x6240,0x6aa3,0x6240,0x6240,0x6240,0x6240,0x6240,0x6240,0x6aa3,0x6240,0x6240,0x6aa3,0x6240,0x6aa3,0x6240,0x9800,
0xc800,0xf629,0xf629,0x6240,0x6aa3,0x6240,0x6aa3,0x6240,0x6240,0x6aa3,0x6aa3,0x6240,0x6aa3,0x6aa3,0x6240,0x6240,0x6aa3,0x6aa3,0x6aa3,0x6240,0x6240,0x9800,
0x9800,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,
};
void drawTile(int x, int y, const uint16_t* spr ){
    if(x >220-spr[1])  game.display.directTile(x,y,220,y+spr[0],(uint16_t*)(spr+2));
    else if(x <0)               game.display.directTile(0,y,spr[1]+x,y+spr[0],(uint16_t*)(spr+2+(spr[0]*-x)));
    else                        game.display.directTile(x,y,x+spr[1],y+spr[0],(uint16_t*)(spr+2));
}

void drawMap(int8_t x,int8_t y/*, uint8_t* mapdata*/){
    for(int i=0; i<11; i++){
        for(int j=0; j<8; j++){
             drawTile(x+(i*22),y+(j*22),tile);
        }
    }
}
    
int main(){
    game.begin();
    game.setFrameRate(100);
    int count;
   
    while(game.isRunning()){
       if(game.update(true)){
           
           drawMap(count-22,0);
          
           count++;
           count = count%22;
         
       }
    }
}

#9

What is the FPS?


#10

how do i check?


#11

#define PROJ_SHOW_FPS_COUNTER


#12

it gives me 16 fps with 80 tiles on screen :confused:
uhm its actualy giving me 16fps wen i draw nothing :S
i dont think this thing works

did a get game.getTime()and it seems to be 100ms per frame, also checked an empty hello world is 60ms per frame


#13

Remove the FPS throttle also (after Begin()):
Pokitto::Core::setFrameRate(100);


#14

ok it seems to be 10 fps (empty project is 18fps)
did a fix for the scrolling, can only scroll horizontal wen going to the edge of the screen

// tile test


#include "Pokitto.h"
Pokitto::Core game;

const uint16_t tile[]={22, 22, /*width, height*/
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xc800,0xc800,0xc800,0xc800,0x9800,
0xf800,0xff0c,0xff0c,0xff0c,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xff0c,0xff0c,0xff0c,0xff0c,0xfff3,0xfff3,0xff0c,0xff0c,0xfff3,0xff0c,0xf629,0xf629,0x9800,
0xf800,0xff0c,0xff0c,0xff0c,0xff0c,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xff0c,0xff0c,0xfff3,0xff0c,0xff0c,0xf629,0xf629,0x9800,
0xf800,0xfff3,0xff0c,0xf629,0xf629,0xf629,0xc508,0xf629,0xc508,0xf629,0xf629,0xc508,0xf629,0xc508,0xc508,0xf629,0xc508,0xc508,0xf629,0x6aa3,0x6aa3,0x9800,
0xf800,0xfff3,0xfff3,0xc508,0xc508,0xf629,0xf629,0xc508,0xf629,0xf629,0xc508,0xc508,0xf629,0xf629,0xf629,0xc508,0xc508,0xf629,0xc508,0x6240,0x6aa3,0x9800,
0xf800,0xfff3,0xfff3,0xc508,0xf629,0xc508,0xc508,0xf629,0xff0c,0xc508,0xf629,0xc508,0xf629,0xc508,0xc508,0xc508,0xc508,0xc508,0xc508,0x6240,0x6aa3,0x9800,
0xf800,0xfff3,0xfff3,0xf629,0xc508,0xf629,0xff0c,0xc508,0xf629,0xc508,0xf629,0xc508,0xc508,0xc508,0xc508,0xc508,0xc508,0xac46,0xc508,0x6aa3,0x6aa3,0x9800,
0xf800,0xfff3,0xfff3,0xc508,0xf629,0xff0c,0xf629,0xc508,0xc508,0xf629,0xc508,0xc508,0xc508,0xf629,0xf629,0xac46,0x8384,0xc508,0xac46,0x6aa3,0x6240,0x9800,
0xf800,0xfff3,0xfff3,0xc508,0xc508,0xf629,0xc508,0xff0c,0xc508,0xac46,0xc508,0xac46,0xc508,0xc508,0xac46,0xac46,0xc508,0xac46,0xac46,0x6240,0x6aa3,0x9800,
0xf800,0xff0c,0xfff3,0xc508,0xf629,0xc508,0xc508,0xf629,0xc508,0xc508,0xc508,0xac46,0xac46,0xc508,0xc508,0xc508,0xc508,0x8384,0xc508,0x6240,0x6240,0x9800,
0xf800,0xff0c,0xfff3,0xf629,0xf629,0xf629,0xc508,0xc508,0xc508,0xc508,0xac46,0xc508,0xc508,0xc508,0xc508,0xc508,0xc508,0xac46,0xc508,0x6aa3,0x6240,0x9800,
0xf800,0xfff3,0xff0c,0xc508,0xc508,0xf629,0xf629,0xc508,0xc508,0xc508,0xc508,0xc508,0xc508,0xc508,0xc508,0xc508,0xac46,0x8384,0xc508,0x6240,0x6240,0x9800,
0xf800,0xff0c,0xff0c,0xac46,0xc508,0xc508,0xf629,0xc508,0xac46,0xac46,0xc508,0xc508,0xac46,0xac46,0xc508,0xc508,0x8384,0xac46,0xac46,0x6240,0x6aa3,0x9800,
0xf800,0xfff3,0xfff3,0xc508,0xc508,0xf629,0xc508,0xc508,0xc508,0xac46,0xc508,0xac46,0xac46,0xc508,0xac46,0xac46,0x8384,0xac46,0xc508,0x6aa3,0x6aa3,0x9800,
0xf800,0xff0c,0xff0c,0xac46,0xf629,0xf629,0xc508,0xc508,0xac46,0xac46,0xac46,0xac46,0x8384,0xac46,0x8384,0xac46,0x8384,0xc508,0xac46,0x6aa3,0x6240,0x9800,
0xf800,0xfff3,0xff0c,0xc508,0xc508,0xc508,0xac46,0xc508,0xc508,0xc508,0xc508,0xac46,0xc508,0xac46,0xac46,0xc508,0xc508,0xc508,0xc508,0x6aa3,0x6240,0x9800,
0xf800,0xff0c,0xff0c,0xc508,0xf629,0xf629,0xf629,0xc508,0xac46,0xc508,0xac46,0x8384,0xc508,0xc508,0x8384,0xc508,0xac46,0xc508,0xac46,0x6240,0x6aa3,0x9800,
0xc800,0xff0c,0xff0c,0xf629,0xf629,0xc508,0xc508,0xc508,0xc508,0xc508,0x8384,0xc508,0xac46,0xac46,0xac46,0x8384,0xac46,0xc508,0xac46,0x6aa3,0x6aa3,0x9800,
0xc800,0xff0c,0xff0c,0xf629,0xc508,0xf629,0xc508,0xac46,0xc508,0xac46,0xc508,0xc508,0xc508,0x8384,0xc508,0xac46,0xac46,0xac46,0xac46,0x6aa3,0x6240,0x9800,
0xc800,0xf629,0xf629,0x6aa3,0x6aa3,0x6aa3,0x6240,0x6aa3,0x6240,0x6240,0x6240,0x6240,0x6240,0x6240,0x6aa3,0x6240,0x6240,0x6aa3,0x6240,0x6aa3,0x6240,0x9800,
0xc800,0xf629,0xf629,0x6240,0x6aa3,0x6240,0x6aa3,0x6240,0x6240,0x6aa3,0x6aa3,0x6240,0x6aa3,0x6aa3,0x6240,0x6240,0x6aa3,0x6aa3,0x6aa3,0x6240,0x6240,0x9800,
0x9800,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,
};
void drawTile(int x, int y, const uint16_t* spr ){
    if(x >220-spr[1])  game.display.directTile(x,y,220,y+spr[0],(uint16_t*)(spr+2));
    else if(x <0)               game.display.directTile(0,y,spr[1]+x,y+spr[0],(uint16_t*)(spr+2+(spr[0]*-x)));
    else                        game.display.directTile(x,y,x+spr[1],y+spr[0],(uint16_t*)(spr+2));
}

void drawMap(int8_t x,int8_t y/*, uint8_t* mapdata*/){
    for(int i=0; i<11; i++){
        for(int j=0; j<8; j++){
             drawTile(x+(i*22),y+(j*22),tile);
        }
    }
}
    
int main(){
    game.begin();
    game.setFrameRate(100);
    int count;
   
    while(game.isRunning()){
       if(game.update(true)){
           
           drawMap(count-22,0);
          
           count++;
           count = count%22;
         
       }
    }
}

Weird idea about compression
#15

you can set display.persistence=false if you redraw the whole screen. That saves full screen clearing.
Also directTile() is not the fastest way to draw tiles as there is some setting and calculation overhead in the beginning of each tile.


#16

sure but thats an easy fix to remove for dedicated mode, its not effecting the performance allot


#17

I’ve been using low-res mode (16 colours) for my current project which uses 32x32 meta-tiles made up of 16 8x8 tiles and I’m getting 22-23fps.
Looking at how slow mode15 is, it might be very ambitious to attmpt this mixed-mode idea.


#18

what you mean with mixed-mode?


#19

using both low-res and hi-res graphics at the same time. So a Hi-res tile would be 16x16 instead of 8x8, and probably take 4 times a long to draw.


#20

i see, well depends how you want to mix the 2 resolutions
if theres a clear divide you can do it with separate buffers or tiles
or if its on mode15 you could draw to the buffer 2x sprites (needs to be implemented but seems easy to do)