I've decided to take up C for the CE (thank you, Mateo Smile ). My first game will be This Is The Only Level. You know, like this one.

I've gotten done with the tilemapper. Here's a gif of the current progress:



Download is here.

There are a couple of questions I want answered, though, so the development process can go as quickly as possible.

1. What's "sprite clipping" and should I use it?
2. For some odd reason, the gfx_TransparentSprite() routine leaves the tile sprites normal when drawn slightly off-screen, but the player sprite entirely disappears when he is off-screen even one pixel. Why is that, and how do I fix it?
3. The "random" colors for the background and spikes look like different shades of blue for some reason. Am I doing it wrong, or is there bias in the random numbers?
4. Are there any more conventions and things that can make my programming life easier?

EDIT: Fixed random color generation so a proper color is output.
Nice work! Looking pretty spiffy; I'd be happy to give suggestions on how to speed things up.

JWinslow23 wrote:
1. What's "sprite clipping" and should I use it?
2. For some odd reason, the gfx_TransparentSprite() routine leaves the tile sprites normal when drawn slightly off-screen, but the player sprite entirely disappears when he is off-screen even one pixel. Why is that, and how do I fix it?
3. The "random" colors for the background and spikes look like different shades of blue for some reason. Am I doing it wrong, or is there bias in the random numbers?
4. Are there any more conventions and things that can make my programming life easier?

1. Sprite clipping makes sure the sprite is drawn properly if parts of it are drawn offscreen or partially offscreen. Sprite functions have a _NoClip version which are a lot faster if the sprites you intend to use won't be offscreen ever.
2. It's probably because you are sending incorrect types (signed vs unsigned) values to the function as arguments. Take another look; the function works as intended Smile
3. You basically have to design the palette yourself and the random colors that should be selected. You can set up the palette with random rgb values by looping and doing something like gfx_palette[i] = rgbTo1555( r, g, b );
4. I don't believe there are any platformer games yet; but anything you learn or discover along the way would be neat Smile
MateoConLechuga wrote:
Nice work! Looking pretty spiffy; I'd be happy to give suggestions on how to speed things up.

JWinslow23 wrote:
1. What's "sprite clipping" and should I use it?
2. For some odd reason, the gfx_TransparentSprite() routine leaves the tile sprites normal when drawn slightly off-screen, but the player sprite entirely disappears when he is off-screen even one pixel. Why is that, and how do I fix it?
3. The "random" colors for the background and spikes look like different shades of blue for some reason. Am I doing it wrong, or is there bias in the random numbers?
4. Are there any more conventions and things that can make my programming life easier?

1. Sprite clipping makes sure the sprite is drawn properly if parts of it are drawn offscreen or partially offscreen. Sprite functions have a _NoClip version which are a lot faster if the sprites you intend to use won't be offscreen ever.
2. It's probably because you are sending incorrect types (signed vs unsigned) values to the function as arguments. Take another look; the function works as intended Smile
3. You basically have to design the palette yourself and the random colors that should be selected. You can set up the palette with random rgb values by looping and doing something like gfx_palette[i] = rgbTo1555( r, g, b );
4. I don't believe there are any platformer games yet; but anything you learn or discover along the way would be neat Smile


1. Well, most of the sprites will always be on-screen (the only ones I have to worry about are the solid block and the player (maybe)), so that's good.
2. Both are unsigned, but the arguments to the tiles are functions done to unsigned 8 bit integers, and the player x and y values are unsigned 16 bit integers. Help some more?
3. Design the palette myself? How do I do that? (Oh, and if I go that route, the random colors will probably be of a set of predetermined colors.)
4. I just discovered that redrawing every tile every frame is slow. Razz
JWinslow23 wrote:
1. Well, most of the sprites will always be on-screen (the only ones I have to worry about are the solid block and the player (maybe)), so that's good.
2. Both are unsigned, but the arguments to the tiles are functions done to unsigned 8 bit integers, and the player x and y values are unsigned 16 bit integers. Help some more?
3. Design the palette myself? How do I do that? (Oh, and if I go that route, the random colors will probably be of a set of predetermined colors.)
4. I just discovered that redrawing every tile every frame is slow. Razz

3. Something like this:


Code:
srand( rtc_Time() );

for(i=200, i<255, i++) {
    gfx_palette[i] = gfx_RGBTo1555( randInt(0,255), randInt(0,255), randInt(0,255) );
}


Then palette indexes 200 - 255 will all be some random color. You can bias it to depending on what you place in randInt.

Or even simpler:


Code:
srand( rtc_Time() );

for(i=200, i<255, i++) {
    gfx_palette[i] = randInt(0, 0xFFFF);
}


Looking through your code for tilemap drawing, here's some suggestions:
Avoid global variables like the plague unless they are structures. They are slower and take up more room than local (function) variables.

Here's an optimized solution to your draw_tilemap:


Code:
const gfx_image_t *tile_ptrs[] = {
   block, block, up_spike, down_spike, left_spike, right_spike, start_pipe, end_pipe, door, door, button
}

void draw_tilemap(void) {
   uint8_t tilemap_y, tilemap_x;
   
   for( tilemap_x = 0; tilemap_x < TILEMAP_WIDTH; tilemap_x++ ) {
      for( tilemap_y = 0; tilemap_y < TILEMAP_HEIGHT; tilemap_y++ ) {
         gfx_TansparentSprite_NoClip( tile_ptrs[TITOL_map[TILEMAP_WIDTH * tilemap_y + tilemap_x]],
         TILE_WIDTH * tilemap_x + TILEMAP_X_OFFSET,
         TILE_HEIGHT * tilemap_y + TILEMAP_Y_OFFSET);
      }
   }
}



Original:


Code:
void draw_tilemap() {
   for( tilemap_x = 0; tilemap_x <= TILEMAP_WIDTH - 1; tilemap_x++ ) {
      for( tilemap_y = 0; tilemap_y <= TILEMAP_HEIGHT - 1; tilemap_y++ ) {
         switch( TITOL_map[TILEMAP_WIDTH * tilemap_y + tilemap_x] ) {
            case 0:
               break;
            case 1:
               gfx_Sprite( block, TILE_WIDTH * tilemap_x + TILEMAP_X_OFFSET, TILE_HEIGHT * tilemap_y + TILEMAP_Y_OFFSET );
               break;
            case 2:
               gfx_TransparentSprite( up_spike, TILE_WIDTH * tilemap_x + TILEMAP_X_OFFSET, TILE_HEIGHT * tilemap_y + TILEMAP_Y_OFFSET );
               break;
            case 3:
               gfx_TransparentSprite( down_spike, TILE_WIDTH * tilemap_x + TILEMAP_X_OFFSET, TILE_HEIGHT * tilemap_y + TILEMAP_Y_OFFSET );
               break;
            case 4:
               gfx_TransparentSprite( left_spike, TILE_WIDTH * tilemap_x + TILEMAP_X_OFFSET, TILE_HEIGHT * tilemap_y + TILEMAP_Y_OFFSET );
               break;
            case 5:
               gfx_TransparentSprite( right_spike, TILE_WIDTH * tilemap_x + TILEMAP_X_OFFSET, TILE_HEIGHT * tilemap_y + TILEMAP_Y_OFFSET );
               break;
            case 6:
               gfx_TransparentSprite( start_pipe, TILE_WIDTH * tilemap_x + TILEMAP_X_OFFSET, TILE_HEIGHT * tilemap_y + TILEMAP_Y_OFFSET );
               break;
            case 7:
               gfx_TransparentSprite( end_pipe, TILE_WIDTH * tilemap_x + TILEMAP_X_OFFSET, TILE_HEIGHT * tilemap_y + TILEMAP_Y_OFFSET );
               break;
            case 8:
               gfx_TransparentSprite( door, TILE_WIDTH * tilemap_x + TILEMAP_X_OFFSET, TILE_HEIGHT * tilemap_y + TILEMAP_Y_OFFSET );
               break;
            case 9:
               gfx_TransparentSprite( door, TILE_WIDTH * tilemap_x + TILEMAP_X_OFFSET, TILE_HEIGHT * tilemap_y + TILEMAP_Y_OFFSET );
               break;
            case 10:
               gfx_TransparentSprite( button, TILE_WIDTH * tilemap_x + TILEMAP_X_OFFSET, TILE_HEIGHT * tilemap_y + TILEMAP_Y_OFFSET );
               break;
         }
      }
   }
}


Pretty niffty Smile
I have a better tilemapper, thank you.

Another question that I haven't been able to solve myself: how would I erase my character every time without having to redraw the entire tilemap? My sprites are all transparent, and one sprite is actually 3 tiles wide, so even redrawing that part of the tilemap hasn't worked.
JWinslow23 wrote:
I have a better tilemapper, thank you.

Another question that I haven't been able to solve myself: how would I erase my character every time without having to redraw the entire tilemap? My sprites are all transparent, and one sprite is actually 3 tiles wide, so even redrawing that part of the tilemap hasn't worked.

Use the buffer. Put gfx_SetDraw(gfx_buffer); before everything you draw, and use gfx_SwapDraw(); every time you want to redraw the screen. Usually done in a loop. See the graphx demos.
seanlego23 wrote:
JWinslow23 wrote:
I have a better tilemapper, thank you.

Another question that I haven't been able to solve myself: how would I erase my character every time without having to redraw the entire tilemap? My sprites are all transparent, and one sprite is actually 3 tiles wide, so even redrawing that part of the tilemap hasn't worked.

Use the buffer. Put gfx_SetDraw(gfx_buffer); before everything you draw, and use gfx_SwapDraw(); every time you want to redraw the screen. Usually done in a loop. See the graphx demos.

I was using the buffer. Any other ideas? The only solutions I can come up with with the buffer all cause flickering.
JWinslow23 wrote:
I was using the buffer. Any other ideas? The only solutions I can come up with with the buffer all cause flickering.

I made a post elsewhere about it, but here's the screenshot I guess.

I've implemented collision functions that work well enough for me.



Interaction with objects will come next. I suppose I'll work on dying, then pushing the button. And at some point, the guy's got to turn around when he walks left.

Download here.
The screenshot is slow for some reason, I blame Cemu.



Also, new version!

It adds jumping, gravity, a little bounce mechanic, and death! It also adds a placeholder for where a timer will be, if I can figure out how to time to the 100th of a second.

Download here.
Looks great. I don't know if this works but you could use the timers defined in tice and set it to 0. Then take a variable and add 1 to it in the loop you use for this game, for every iteration until the timer says 1 seconds. Somehow try to figure out where the loop equals 100 iterations per second, then just output that variable to the screen and reset it to 0 every second.
This is probably the worst way to do this, but it's an idea.
seanlego23 wrote:
Looks great. I don't know if this works but you could use the timers defined in tice and set it to 0. Then take a variable and add 1 to it in the loop you use for this game, for every iteration until the timer says 1 seconds. Somehow try to figure out where the loop equals 100 iterations per second, then just output that variable to the screen and reset it to 0 every second.
This is probably the worst way to do this, but it's an idea.

Seeing as there is an accurate second timer on the CE, and that you could (as far as I know) make some timer more accurate than that, I'd probably be OK with taking that magic accuracy number and converting that to 100ths of a second (like I did with TITOL 84+, in a way).
In demo 3 there's an example using the 32KHz clock. In order to figure out how many steps it is; just take the number 32768 and determine when checking it you should continue. For example, 32768/2 would be every half second, 32768/4 is every quarter second, 32768/100 is every 100th of a second, etc. Smile


Download here.
This is looking really good! Is that the original speed, or is CEmu gif recording acting up?
Unicorn wrote:
This is looking really good! Is that the original speed, or is CEmu gif recording acting up?

It's CEmu acting up :/ The timer is counting exactly, but as you can see the gif is really slow.
How would I make the second timer available run in conjunction with the first one? There's a part of an animation that triggers after a certain time that I want to do.
Download here.

Download here.
nice work Smile
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement