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,
|
||||
0b10000000,
|
||||
0b10101000,
|
||||
|
@ -11,7 +23,7 @@ const unsigned char soweli_a[8] = {
|
|||
0b01010000,
|
||||
};
|
||||
|
||||
const unsigned char soweli_b[8] = {
|
||||
const u8 soweli_b[8] = {
|
||||
0b01111111,
|
||||
0b10000000,
|
||||
0b10101000,
|
||||
|
@ -22,7 +34,14 @@ const unsigned char soweli_b[8] = {
|
|||
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,
|
||||
|
@ -38,7 +57,6 @@ const unsigned char obstacle_sprites[OBSTACLE_TYPES][8] = {
|
|||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
|
||||
0b00111100,
|
||||
0b01100110,
|
||||
0b11000011,
|
||||
|
@ -74,7 +92,14 @@ const unsigned char obstacle_sprites[OBSTACLE_TYPES][8] = {
|
|||
0b00011000,
|
||||
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--;
|
||||
}
|
||||
|
||||
void spawn_obstacle(u8 pos)
|
||||
void spawn_ground_obstacle(u8 pos)
|
||||
{
|
||||
if (obstacle_count >= MAX_OBSTACLES)
|
||||
return;
|
||||
obstacle_positions[obstacle_count] = pos;
|
||||
obstacle_types[obstacle_count] = rand8() % OBSTACLE_TYPES;
|
||||
obstacle_types[obstacle_count] = rand8() % GROUND_OBSTACLE_TYPES;
|
||||
obstacle_count++;
|
||||
}
|
||||
void spawn_air_obstacle(u8 pos)
|
||||
{
|
||||
spawn_ground_obstacle(pos);
|
||||
obstacle_types[obstacle_count - 1] = 5;
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
|
@ -136,7 +141,9 @@ void update()
|
|||
obstacle_positions[i] -= SCROLL_SPEED;
|
||||
u8 type = obstacle_types[i];
|
||||
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;
|
||||
}
|
||||
|
@ -145,34 +152,25 @@ void update()
|
|||
{
|
||||
remove_obstacle();
|
||||
}
|
||||
if (time_to_obstacle < 5)
|
||||
if (time_to_obstacle == 0)
|
||||
{
|
||||
u8 count = 1 + (rand8() & rand8() & 1) + (rand8() & rand8() & rand8() & rand8() & 1);
|
||||
for (u8 i = 0; i < count; i++)
|
||||
if (rand8() & rand8() & 1)
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
ssd1306_drawPixel(x + 0, y + 0, (pixels >> 14) & 1);
|
||||
ssd1306_drawPixel(x + 1, y + 0, (pixels >> 13) & 1);
|
||||
ssd1306_drawPixel(x + 2, y + 0, (pixels >> 12) & 1);
|
||||
|
@ -218,13 +216,13 @@ void render()
|
|||
for (u8 i = 0; i < obstacle_count; 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)
|
||||
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
|
||||
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 */
|
||||
|
|
|
@ -232,6 +232,103 @@ void ssd1306_drawPixel(uint8_t x, uint8_t y, uint8_t color)
|
|||
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
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue