add birds to runner game
This commit is contained in:
parent
42eda85fd0
commit
e2190c8dc8
3 changed files with 152 additions and 32 deletions
|
@ -1,6 +1,18 @@
|
||||||
#define OBSTACLE_TYPES 5
|
|
||||||
|
|
||||||
const unsigned char soweli_a[8] = {
|
const u16 digit_font[] = {
|
||||||
|
0b111101101101111, // 0
|
||||||
|
0b010110010010111, // 1
|
||||||
|
0b111001111100111, // 2
|
||||||
|
0b111001111001111, // 3
|
||||||
|
0b101101111001001, // 4
|
||||||
|
0b111100111001111, // 5
|
||||||
|
0b111100111101111, // 6
|
||||||
|
0b111001001001001, // 7
|
||||||
|
0b111101111101111, // 8
|
||||||
|
0b111101111001111, // 9
|
||||||
|
};
|
||||||
|
|
||||||
|
const u8 soweli_a[8] = {
|
||||||
0b01111111,
|
0b01111111,
|
||||||
0b10000000,
|
0b10000000,
|
||||||
0b10101000,
|
0b10101000,
|
||||||
|
@ -11,7 +23,7 @@ const unsigned char soweli_a[8] = {
|
||||||
0b01010000,
|
0b01010000,
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned char soweli_b[8] = {
|
const u8 soweli_b[8] = {
|
||||||
0b01111111,
|
0b01111111,
|
||||||
0b10000000,
|
0b10000000,
|
||||||
0b10101000,
|
0b10101000,
|
||||||
|
@ -22,7 +34,14 @@ const unsigned char soweli_b[8] = {
|
||||||
0b00000101,
|
0b00000101,
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned char obstacle_sprites[OBSTACLE_TYPES][8] = {
|
#define GROUND_OBSTACLE_TYPES 5
|
||||||
|
#define OBSTACLE_TYPES (GROUND_OBSTACLE_TYPES + 1)
|
||||||
|
|
||||||
|
const u8 obstacle_heights[OBSTACLE_TYPES] = {6, 4, 4, 8, 5, 8};
|
||||||
|
const u8 obstacle_widths[OBSTACLE_TYPES] = {8, 8, 8, 7, 5, 7}; // (width + 8 )/2
|
||||||
|
const u8 obstacle_y_offset[OBSTACLE_TYPES] = {0, 0, 0, 0, 0, 18};
|
||||||
|
|
||||||
|
const u8 obstacle_sprites[OBSTACLE_TYPES][8] = {
|
||||||
{
|
{
|
||||||
0b00000000,
|
0b00000000,
|
||||||
0b00000000,
|
0b00000000,
|
||||||
|
@ -38,7 +57,6 @@ const unsigned char obstacle_sprites[OBSTACLE_TYPES][8] = {
|
||||||
0b00000000,
|
0b00000000,
|
||||||
0b00000000,
|
0b00000000,
|
||||||
0b00000000,
|
0b00000000,
|
||||||
|
|
||||||
0b00111100,
|
0b00111100,
|
||||||
0b01100110,
|
0b01100110,
|
||||||
0b11000011,
|
0b11000011,
|
||||||
|
@ -74,7 +92,14 @@ const unsigned char obstacle_sprites[OBSTACLE_TYPES][8] = {
|
||||||
0b00011000,
|
0b00011000,
|
||||||
0b00111100,
|
0b00111100,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
0b00100000,
|
||||||
|
0b00010000,
|
||||||
|
0b00001000,
|
||||||
|
0b01010100,
|
||||||
|
0b00000010,
|
||||||
|
0b00011110,
|
||||||
|
0b00010000,
|
||||||
|
0b00010000,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned char obstacle_heights[OBSTACLE_TYPES] = {6, 4, 4, 8, 5};
|
|
||||||
const unsigned char obstacle_widths[OBSTACLE_TYPES] = {8, 8, 8, 7, 5};
|
|
|
@ -109,14 +109,19 @@ void remove_obstacle()
|
||||||
obstacle_count--;
|
obstacle_count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void spawn_obstacle(u8 pos)
|
void spawn_ground_obstacle(u8 pos)
|
||||||
{
|
{
|
||||||
if (obstacle_count >= MAX_OBSTACLES)
|
if (obstacle_count >= MAX_OBSTACLES)
|
||||||
return;
|
return;
|
||||||
obstacle_positions[obstacle_count] = pos;
|
obstacle_positions[obstacle_count] = pos;
|
||||||
obstacle_types[obstacle_count] = rand8() % OBSTACLE_TYPES;
|
obstacle_types[obstacle_count] = rand8() % GROUND_OBSTACLE_TYPES;
|
||||||
obstacle_count++;
|
obstacle_count++;
|
||||||
}
|
}
|
||||||
|
void spawn_air_obstacle(u8 pos)
|
||||||
|
{
|
||||||
|
spawn_ground_obstacle(pos);
|
||||||
|
obstacle_types[obstacle_count - 1] = 5;
|
||||||
|
}
|
||||||
|
|
||||||
void update()
|
void update()
|
||||||
{
|
{
|
||||||
|
@ -136,7 +141,9 @@ void update()
|
||||||
obstacle_positions[i] -= SCROLL_SPEED;
|
obstacle_positions[i] -= SCROLL_SPEED;
|
||||||
u8 type = obstacle_types[i];
|
u8 type = obstacle_types[i];
|
||||||
u8 dist_x = gfx_abs((s16)obstacle_positions[i] - (s16)PLAYER_X);
|
u8 dist_x = gfx_abs((s16)obstacle_positions[i] - (s16)PLAYER_X);
|
||||||
if (dist_x < obstacle_widths[type] && (player_y >> Y_PRECISION) < obstacle_heights[type])
|
u8 dist_y = gfx_abs((s16)obstacle_y_offset[type] - (s16)(player_y >> Y_PRECISION));
|
||||||
|
|
||||||
|
if (dist_x < obstacle_widths[type] && dist_y < obstacle_heights[type])
|
||||||
{
|
{
|
||||||
is_running = 0;
|
is_running = 0;
|
||||||
}
|
}
|
||||||
|
@ -145,34 +152,25 @@ void update()
|
||||||
{
|
{
|
||||||
remove_obstacle();
|
remove_obstacle();
|
||||||
}
|
}
|
||||||
if (time_to_obstacle < 5)
|
if (time_to_obstacle == 0)
|
||||||
{
|
{
|
||||||
u8 count = 1 + (rand8() & rand8() & 1) + (rand8() & rand8() & rand8() & rand8() & 1);
|
if (rand8() & rand8() & 1)
|
||||||
for (u8 i = 0; i < count; i++)
|
spawn_air_obstacle(128);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
spawn_obstacle(128 + i * 8);
|
spawn_ground_obstacle(128);
|
||||||
|
if (rand8() & rand8() & 1 && obstacle_types[obstacle_count - 1] != 5)
|
||||||
|
spawn_ground_obstacle(136);
|
||||||
}
|
}
|
||||||
time_to_obstacle = (rand8() & 31) + 50;
|
|
||||||
|
time_to_obstacle = (rand8() & 31) + 45;
|
||||||
}
|
}
|
||||||
time_to_obstacle -= 1;
|
time_to_obstacle -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void render_digit(u8 digit, u8 x, u8 y)
|
void render_digit(u8 digit, u8 x, u8 y)
|
||||||
{
|
{
|
||||||
const u16 digit_font[] = {
|
|
||||||
0b111101101101111, // 0
|
|
||||||
0b010110010010111, // 1
|
|
||||||
0b111001111100111, // 2
|
|
||||||
0b111001111001111, // 3
|
|
||||||
0b101101111001001, // 4
|
|
||||||
0b111100111001111, // 5
|
|
||||||
0b111100111101111, // 6
|
|
||||||
0b111001001001001, // 7
|
|
||||||
0b111101111101111, // 8
|
|
||||||
0b111101111001111, // 9
|
|
||||||
};
|
|
||||||
u16 pixels = digit_font[digit];
|
u16 pixels = digit_font[digit];
|
||||||
|
|
||||||
ssd1306_drawPixel(x + 0, y + 0, (pixels >> 14) & 1);
|
ssd1306_drawPixel(x + 0, y + 0, (pixels >> 14) & 1);
|
||||||
ssd1306_drawPixel(x + 1, y + 0, (pixels >> 13) & 1);
|
ssd1306_drawPixel(x + 1, y + 0, (pixels >> 13) & 1);
|
||||||
ssd1306_drawPixel(x + 2, y + 0, (pixels >> 12) & 1);
|
ssd1306_drawPixel(x + 2, y + 0, (pixels >> 12) & 1);
|
||||||
|
@ -218,13 +216,13 @@ void render()
|
||||||
for (u8 i = 0; i < obstacle_count; i++)
|
for (u8 i = 0; i < obstacle_count; i++)
|
||||||
{
|
{
|
||||||
u8 type = obstacle_types[i];
|
u8 type = obstacle_types[i];
|
||||||
ssd1306_drawImage(obstacle_positions[i], 31 - 8, obstacle_sprites[type], 8, 8, 0);
|
ssd1306_drawImage(obstacle_positions[i], 31 - 8 - obstacle_y_offset[type], obstacle_sprites[type], 8, 8, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (time & RUN_ANIM_SPEED && is_running)
|
if (time & RUN_ANIM_SPEED && is_running)
|
||||||
ssd1306_drawImage(PLAYER_X, 31 - (player_y >> Y_PRECISION) - 8, soweli_a, 8, 8, 0);
|
ssd1306_drawImage(PLAYER_X, 31 - 8 - (player_y >> Y_PRECISION), soweli_a, 8, 8, 0);
|
||||||
else
|
else
|
||||||
ssd1306_drawImage(PLAYER_X, 31 - (player_y >> Y_PRECISION) - 8, soweli_b, 8, 8, 0);
|
ssd1306_drawImage(PLAYER_X, 31 - 8 - (player_y >> Y_PRECISION), soweli_b, 8, 8, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* White Noise Generator State */
|
/* White Noise Generator State */
|
||||||
|
|
|
@ -232,6 +232,103 @@ void ssd1306_drawPixel(uint8_t x, uint8_t y, uint8_t color)
|
||||||
ssd1306_buffer[addr] &= ~(1 << (y & 7));
|
ssd1306_buffer[addr] &= ~(1 << (y & 7));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* plot a pixel in the buffer
|
||||||
|
*/
|
||||||
|
void ssd1306_xorPixel(uint8_t x, uint8_t y)
|
||||||
|
{
|
||||||
|
uint16_t addr;
|
||||||
|
|
||||||
|
/* clip */
|
||||||
|
if (x >= SSD1306_W)
|
||||||
|
return;
|
||||||
|
if (y >= SSD1306_H)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* compute buffer address */
|
||||||
|
addr = x + SSD1306_W * (y / 8);
|
||||||
|
|
||||||
|
ssd1306_buffer[addr] ^= (1 << (y & 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* draw a an image from an array, directly into to the display buffer
|
||||||
|
* the color modes allow for overwriting and even layering (sprites!)
|
||||||
|
*/
|
||||||
|
void ssd1306_drawImage(uint8_t x, uint8_t y, const unsigned char *input, uint8_t width, uint8_t height, uint8_t color_mode)
|
||||||
|
{
|
||||||
|
uint8_t x_absolute;
|
||||||
|
uint8_t y_absolute;
|
||||||
|
uint8_t pixel;
|
||||||
|
uint8_t bytes_to_draw = width / 8;
|
||||||
|
uint16_t buffer_addr;
|
||||||
|
|
||||||
|
for (uint8_t line = 0; line < height; line++)
|
||||||
|
{
|
||||||
|
y_absolute = y + line;
|
||||||
|
if (y_absolute >= SSD1306_H)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SSD1306 is in vertical mode, yet we want to draw horizontally, which necessitates assembling the output bytes from the input data
|
||||||
|
// bitmask for current pixel in vertical (output) byte
|
||||||
|
uint8_t v_mask = 1 << (y_absolute & 7);
|
||||||
|
|
||||||
|
for (uint8_t byte = 0; byte < bytes_to_draw; byte++)
|
||||||
|
{
|
||||||
|
uint8_t input_byte = input[byte + line * bytes_to_draw];
|
||||||
|
|
||||||
|
for (pixel = 0; pixel < 8; pixel++)
|
||||||
|
{
|
||||||
|
x_absolute = x + 8 * (bytes_to_draw - byte) + pixel;
|
||||||
|
if (x_absolute >= SSD1306_W)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// looking at the horizontal display, we're drawing bytes bottom to top, not left to right, hence y / 8
|
||||||
|
buffer_addr = x_absolute + SSD1306_W * (y_absolute / 8);
|
||||||
|
// state of current pixel
|
||||||
|
uint8_t input_pixel = input_byte & (1 << pixel);
|
||||||
|
|
||||||
|
switch (color_mode)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
// write pixels as they are
|
||||||
|
ssd1306_buffer[buffer_addr] = (ssd1306_buffer[buffer_addr] & ~v_mask) | (input_pixel ? v_mask : 0);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// write pixels after inversion
|
||||||
|
ssd1306_buffer[buffer_addr] = (ssd1306_buffer[buffer_addr] & ~v_mask) | (!input_pixel ? v_mask : 0);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
// 0 clears pixel
|
||||||
|
ssd1306_buffer[buffer_addr] &= input_pixel ? 0xFF : ~v_mask;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
// 1 sets pixel
|
||||||
|
ssd1306_buffer[buffer_addr] |= input_pixel ? v_mask : 0;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
// 0 sets pixel
|
||||||
|
ssd1306_buffer[buffer_addr] |= !input_pixel ? v_mask : 0;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
// 1 clears pixel
|
||||||
|
ssd1306_buffer[buffer_addr] &= input_pixel ? ~v_mask : 0xFF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if SSD1306_LOG_IMAGE == 1
|
||||||
|
printf("%02x ", input_byte);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if SSD1306_LOG_IMAGE == 1
|
||||||
|
printf("\n\r");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fast vert line
|
* fast vert line
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue